diff --git a/pengine/allocate.c b/pengine/allocate.c index 48770e1d87..c681454b10 100644 --- a/pengine/allocate.c +++ b/pengine/allocate.c @@ -1,1668 +1,1674 @@ /* * 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 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_merge_weights, native_color, native_create_actions, native_create_probe, native_internal_constraints, native_rsc_colocation_lh, native_rsc_colocation_rh, native_rsc_order_lh, native_rsc_order_rh, native_rsc_location, native_expand, complex_migrate_reload, complex_stonith_ordering, }, { group_merge_weights, group_color, group_create_actions, native_create_probe, group_internal_constraints, group_rsc_colocation_lh, group_rsc_colocation_rh, group_rsc_order_lh, group_rsc_order_rh, group_rsc_location, group_expand, complex_migrate_reload, complex_stonith_ordering, }, { native_merge_weights, clone_color, clone_create_actions, clone_create_probe, clone_internal_constraints, clone_rsc_colocation_lh, clone_rsc_colocation_rh, clone_rsc_order_lh, clone_rsc_order_rh, clone_rsc_location, clone_expand, complex_migrate_reload, complex_stonith_ordering, }, { native_merge_weights, master_color, master_create_actions, clone_create_probe, master_internal_constraints, clone_rsc_colocation_lh, master_rsc_colocation_rh, clone_rsc_order_lh, clone_rsc_order_rh, clone_rsc_location, clone_expand, complex_migrate_reload, complex_stonith_ordering, } }; static gboolean check_rsc_parameters(resource_t *rsc, node_t *node, xmlNode *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); set_bit(rsc->flags, pe_rsc_start_pending); delete_resource = TRUE; } return delete_resource; } static void CancelXmlOp(resource_t *rsc, xmlNode *xml_op, node_t *active_node, const char *reason, pe_working_set_t *data_set) { int interval = 0; action_t *cancel = NULL; char *key = NULL; const char *task = NULL; const char *call_id = NULL; const char *op_version = NULL; const char *interval_s = NULL; CRM_CHECK(xml_op != NULL, return); CRM_CHECK(active_node != NULL, return); task = crm_element_value(xml_op, XML_LRM_ATTR_TASK); call_id = crm_element_value(xml_op, XML_LRM_ATTR_CALLID); op_version = crm_element_value(xml_op, XML_ATTR_CRM_VERSION); 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); crm_info("Action %s on %s will be stopped: %s", key, active_node->details->uname, reason?reason:"unknown"); cancel = custom_action(rsc, crm_strdup(key), RSC_CANCEL, active_node, FALSE, TRUE, data_set); crm_free(cancel->task); cancel->task = crm_strdup(RSC_CANCEL); add_hash_param(cancel->meta, XML_LRM_ATTR_TASK, task); add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID, call_id); add_hash_param(cancel->meta, XML_LRM_ATTR_INTERVAL, interval_s); custom_action_order(rsc, stop_key(rsc), NULL, rsc, NULL, cancel, pe_order_optional, data_set); crm_free(key); key = NULL; } static gboolean check_action_definition(resource_t *rsc, node_t *active_node, xmlNode *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; xmlNode *params_all = NULL; xmlNode *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) { xmlNode *op_match = NULL; crm_debug_2("Checking parameters for %s", key); op_match = find_rsc_op_entry(rsc, key); if(op_match == NULL && is_set(data_set->flags, pe_flag_stop_action_orphans)) { CancelXmlOp(rsc, xml_op, active_node, "orphan", data_set); return TRUE; } else 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); get_rsc_attributes(local_rsc_params, rsc, active_node, data_set); params_all = create_xml_node(NULL, XML_TAG_PARAMS); g_hash_table_foreach(local_rsc_params, hash2field, params_all); g_hash_table_foreach(action->extra, hash2field, params_all); g_hash_table_foreach(rsc->parameters, hash2field, params_all); g_hash_table_foreach(action->meta, hash2metafield, params_all); filter_action_parameters(params_all, op_version); digest_all_calc = calculate_xml_digest(params_all, TRUE, FALSE); 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, RSC_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, FALSE); 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. %s (restart:%s) %s", key, active_node->details->uname, crm_str(digest_restart), digest_restart_calc, op_version, crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC)); 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. %s (all:%s) %s", key, active_node->details->uname, crm_str(digest_all), digest_all_calc, op_version, crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC)); if(interval == 0 && safe_str_neq(task, RSC_STOP)) { /* Anything except stop actions should result in a restart, * never a re-probe */ task = RSC_START; } 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, gboolean optional, pe_working_set_t *data_set); static void check_actions_for(xmlNode *rsc_entry, resource_t *rsc, node_t *node, pe_working_set_t *data_set) { int interval = 0; int stop_index = 0; int start_index = 0; const char *id = NULL; const char *task = NULL; const char *interval_s = NULL; GListPtr op_list = NULL; GListPtr sorted_op_list = NULL; gboolean is_probe = FALSE; CRM_CHECK(node != NULL, return); if(is_set(rsc->flags, pe_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, FALSE, 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, xmlNode, 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, RSC_STATUS)) { is_probe = TRUE; } if(interval > 0 && is_set(data_set->flags, pe_flag_maintenance_mode)) { CancelXmlOp(rsc, rsc_op, node, "maintenance mode", data_set); } else if(is_probe || safe_str_eq(task, RSC_START) || interval > 0) { check_action_definition(rsc, node, rsc_op, data_set); } ); g_list_free(sorted_op_list); } static GListPtr find_rsc_list( GListPtr result, resource_t *rsc, const char *id, gboolean renamed_clones, gboolean partial, pe_working_set_t *data_set) { gboolean match = FALSE; if(id == NULL) { return NULL; } else if(rsc == NULL && data_set) { slist_iter(child, resource_t, data_set->resources, lpc, result = find_rsc_list(result, child, id, renamed_clones, partial, NULL)); return result; } if(partial) { if(strstr(rsc->id, id)) { match = TRUE; } else if(rsc->long_name && strstr(rsc->long_name, id)) { match = TRUE; } else if(renamed_clones && rsc->clone_name && strstr(rsc->clone_name, id)) { match = TRUE; } } else { if(strcmp(rsc->id, id) == 0){ match = TRUE; } else if(rsc->long_name && strcmp(rsc->long_name, id) == 0) { match = TRUE; } else if(renamed_clones && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) { match = TRUE; } } if(match) { result = g_list_append(result, rsc); } if(rsc->children) { slist_iter(child, resource_t, rsc->children, lpc, result = find_rsc_list(result, child, id, renamed_clones, partial, NULL); ); } return result; } static void check_actions(pe_working_set_t *data_set) { const char *id = NULL; node_t *node = NULL; xmlNode *lrm_rscs = NULL; xmlNode *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 || is_set(data_set->flags, pe_flag_stonith_enabled)) { xml_child_iter_filter( lrm_rscs, rsc_entry, XML_LRM_TAG_RESOURCE, if(xml_has_children(rsc_entry)) { GListPtr result = NULL; const char *rsc_id = ID(rsc_entry); CRM_CHECK(rsc_id != NULL, return); result = find_rsc_list(NULL, NULL, rsc_id, TRUE, FALSE, data_set); slist_iter(rsc, resource_t, result, lpc, check_actions_for(rsc_entry, rsc, node, data_set)); g_list_free(result); } ); } ); } 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; } static void common_apply_stickiness(resource_t *rsc, node_t *node, pe_working_set_t *data_set) { int fail_count = 0; resource_t *failed = rsc; if(rsc->children) { slist_iter( child_rsc, resource_t, rsc->children, lpc, common_apply_stickiness(child_rsc, node, data_set); ); return; } if(is_set(rsc->flags, pe_rsc_managed) && rsc->stickiness != 0 && g_list_length(rsc->running_on) == 1) { node_t *current = pe_find_node_id(rsc->running_on, node->details->id); node_t *match = pe_find_node_id(rsc->allowed_nodes, node->details->id); if(current == NULL) { } else if(match != NULL || is_set(data_set->flags, pe_flag_symmetric_cluster)) { resource_t *sticky_rsc = rsc; resource_location(sticky_rsc, node, rsc->stickiness, "stickiness", data_set); crm_debug("Resource %s: preferring current location" " (node=%s, weight=%d)", sticky_rsc->id, node->details->uname, rsc->stickiness); } else { crm_debug("Ignoring stickiness for %s: the cluster is asymmetric" " and node %s is not explicitly allowed", rsc->id, node->details->uname); slist_iter(node, node_t, rsc->allowed_nodes, lpc, crm_err("%s[%s] = %d", rsc->id, node->details->uname, node->weight)); } } if(is_not_set(rsc->flags, pe_rsc_unique)) { failed = uber_parent(rsc); } fail_count = get_failcount(node, rsc, NULL, data_set); if(fail_count > 0 && rsc->migration_threshold != 0) { if(rsc->migration_threshold <= fail_count) { resource_location(failed, node, -INFINITY, "__fail_limit__", data_set); crm_warn("Forcing %s away from %s after %d failures (max=%d)", failed->id, node->details->uname, fail_count, rsc->migration_threshold); } else { crm_notice("%s can fail %d more times on %s before being forced off", failed->id, rsc->migration_threshold - fail_count, node->details->uname); } } } static void complex_set_cmds(resource_t *rsc) { rsc->cmds = &resource_class_alloc_functions[rsc->variant]; slist_iter( child_rsc, resource_t, rsc->children, lpc, complex_set_cmds(child_rsc); ); } void set_alloc_actions(pe_working_set_t *data_set) { slist_iter( rsc, resource_t, data_set->resources, lpc, complex_set_cmds(rsc); ); } static void calculate_system_health (gpointer gKey, gpointer gValue, gpointer user_data) { const char *key = (const char *)gKey; const char *value = (const char *)gValue; int *system_health = (int *)user_data; if (!gKey || !gValue || !user_data) { return; } /* Does it start with #health? */ if (0 == strncmp (key, "#health", 7)) { int score; /* Convert the value into an integer */ score = char2score (value); /* Add it to the running total */ *system_health = merge_weights (score, *system_health); } } static gboolean apply_system_health(pe_working_set_t *data_set) { const char *health_strategy = pe_pref(data_set->config_hash, "node-health-strategy"); if (health_strategy == NULL || safe_str_eq (health_strategy, "none")) { /* Prevent any accidental health -> score translation */ node_score_red = 0; node_score_yellow = 0; node_score_green = 0; return TRUE; } else if (safe_str_eq (health_strategy, "migrate-on-red")) { /* Resources on nodes which have health values of red are * weighted away from that node. */ node_score_red = -INFINITY; node_score_yellow = 0; node_score_green = 0; } else if (safe_str_eq (health_strategy, "only-green")) { /* Resources on nodes which have health values of red or yellow * are forced away from that node. */ node_score_red = -INFINITY; node_score_yellow = -INFINITY; node_score_green = 0; } else if (safe_str_eq (health_strategy, "progressive")) { /* Same as the above, but use the r/y/g scores provided by the user * Defaults are provided by the pe_prefs table */ } else if (safe_str_eq (health_strategy, "custom")) { /* Requires the admin to configure the rsc_location constaints for * processing the stored health scores */ /* TODO: Check for the existance of appropriate node health constraints */ return TRUE; } else { crm_err ("Unknown node health strategy: %s", health_strategy); return FALSE; } crm_info ("Applying automated node health strategy: %s", health_strategy); slist_iter( node, node_t, data_set->nodes, lpc, int system_health = 0; /* Search through the node hash table for system health entries. */ g_hash_table_foreach ( node->details->attrs, calculate_system_health, &system_health); crm_info (" Node %s has an combined system health of %d", node->details->uname, system_health); /* If the health is non-zero, then create a new rsc2node so that the * weight will be added later on. */ if (system_health != 0) { slist_iter( rsc, resource_t, data_set->resources, lpc, rsc2node_new (health_strategy, rsc, system_health, node, data_set); ); } ); return TRUE; } gboolean stage0(pe_working_set_t *data_set) { xmlNode * 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); apply_system_health(data_set); unpack_constraints(cib_constraints, data_set); return TRUE; } /* * Check nodes for resources started outside of the LRM */ gboolean probe_resources(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); if(node->details->online == FALSE) { continue; } else if(node->details->unclean) { continue; } else if(probe_complete == NULL) { probe_complete = get_pseudo_op(CRM_OP_PROBED, data_set); } 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); + + if(node->details->pending) { + probe_node_complete->runnable = FALSE; + crm_info("Action %s on %s is unrunnable (pending)", + probe_node_complete->uuid, probe_node_complete->node->details->uname); + } - order_actions(probe_node_complete, probe_complete, pe_order_optional); + order_actions(probe_node_complete, probe_complete, pe_order_runnable_left); 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); custom_action_order( NULL, NULL, probe_complete, rsc, stop_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); slist_iter(node, node_t, data_set->nodes, lpc, slist_iter( rsc, resource_t, data_set->resources, lpc2, common_apply_stickiness(rsc, node, 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); ); probe_resources(data_set); slist_iter( rsc, resource_t, data_set->resources, lpc, rsc->cmds->create_actions(rsc, data_set); ); return TRUE; } static gboolean is_managed(const resource_t *rsc) { if(is_set(rsc->flags, pe_rsc_managed)) { return TRUE; } slist_iter( child_rsc, resource_t, rsc->children, lpc, if(is_managed(child_rsc)) { return TRUE; } ); return FALSE; } static gboolean any_managed_resouces(pe_working_set_t *data_set) { slist_iter( rsc, resource_t, data_set->resources, lpc, if(is_managed(rsc)) { return TRUE; } ); return FALSE; } /* * 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; action_t *ready = get_pseudo_op(STONITH_UP, data_set); action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set); action_t *done = get_pseudo_op(STONITH_DONE, data_set); gboolean need_stonith = FALSE; crm_debug_3("Processing fencing and shutdown cases"); if(is_set(data_set->flags, pe_flag_stonith_enabled) && (is_set(data_set->flags, pe_flag_have_quorum) || data_set->no_quorum_policy == no_quorum_ignore || data_set->no_quorum_policy == no_quorum_suicide)) { need_stonith = TRUE; } if(need_stonith && any_managed_resouces(data_set) == FALSE) { crm_info("Delaying fencing operations until there are resources to manage"); need_stonith = FALSE; } slist_iter( node, node_t, data_set->nodes, lpc, stonith_op = NULL; if(node->details->unclean && need_stonith) { 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); order_actions(ready, stonith_op, pe_order_implies_left); order_actions(stonith_op, all_stopped, pe_order_implies_right); 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); add_hash_param(down_op->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); 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(is_set(data_set->flags, pe_flag_stonith_enabled) == FALSE) { pe_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED"); pe_err("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE"); } else if(is_set(data_set->flags, pe_flag_have_quorum) == FALSE) { crm_notice("Cannot fence unclean nodes until quorum is" " attained (or no-quorum-policy is set to ignore)"); } } 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); } if(last_stonith) { order_actions(last_stonith, done, pe_order_implies_right); } order_actions(ready, done, pe_order_optional); 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_3("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); LogActions(rsc, data_set); ); return TRUE; } static gint sort_notify_entries(gconstpointer a, gconstpointer b) { int tmp; const notify_entry_t *entry_a = a; const notify_entry_t *entry_b = b; if(entry_a == NULL && entry_b == NULL) { return 0; } if(entry_a == NULL) { return 1; } if(entry_b == NULL) { return -1; } if(entry_a->rsc == NULL && entry_b->rsc == NULL) { return 0; } if(entry_a->rsc == NULL) { return 1; } if(entry_b->rsc == NULL) { return -1; } tmp = strcmp(entry_a->rsc->id, entry_b->rsc->id); if(tmp != 0) { return tmp; } if(entry_a->node == NULL && entry_b->node == NULL) { return 0; } if(entry_a->node == NULL) { return 1; } if(entry_b->node == NULL) { return -1; } return strcmp(entry_a->node->details->id, entry_b->node->details->id); } static void expand_list(GListPtr list, char **rsc_list, char **node_list) { const char *uname = NULL; const char *rsc_id = NULL; const char *last_rsc_id = NULL; if(list == NULL) { *rsc_list = crm_strdup(" "); if(node_list) { *node_list = crm_strdup(" "); } return; } *rsc_list = NULL; if(node_list) { *node_list = NULL; } slist_iter(entry, notify_entry_t, list, lpc, CRM_CHECK(entry != NULL, continue); CRM_CHECK(entry->rsc != NULL, continue); CRM_CHECK(node_list == NULL || entry->node != NULL, continue); uname = NULL; rsc_id = entry->rsc->id; CRM_ASSERT(rsc_id != NULL); /* filter dups */ if(safe_str_eq(rsc_id, last_rsc_id)) { continue; } last_rsc_id = rsc_id; if(rsc_list != NULL) { int existing_len = 0; int len = 2 + strlen(rsc_id); /* +1 space, +1 EOS */ if(rsc_list && *rsc_list) { existing_len = strlen(*rsc_list); } crm_debug_5("Adding %s (%dc) at offset %d", rsc_id, len-2, existing_len); crm_realloc(*rsc_list, len + existing_len); sprintf(*rsc_list + existing_len, "%s ", rsc_id); } if(entry->node != NULL) { uname = entry->node->details->uname; } if(node_list != NULL && uname) { int existing_len = 0; int len = 2 + strlen(uname); if(node_list && *node_list) { existing_len = strlen(*node_list); } crm_debug_5("Adding %s (%dc) at offset %d", uname, len-2, existing_len); crm_realloc(*node_list, len + existing_len); sprintf(*node_list + existing_len, "%s ", uname); } ); } static void dup_attr(gpointer key, gpointer value, gpointer user_data) { g_hash_table_replace(user_data, crm_strdup(key), crm_strdup(value)); } static action_t * pe_notify(resource_t *rsc, node_t *node, action_t *op, action_t *confirm, notify_data_t *n_data, pe_working_set_t *data_set) { char *key = NULL; action_t *trigger = NULL; const char *value = NULL; const char *task = NULL; if(op == NULL || confirm == NULL) { crm_debug_2("Op=%p confirm=%p", op, confirm); return NULL; } CRM_CHECK(node != NULL, return NULL); if(node->details->online == FALSE) { crm_debug_2("Skipping notification for %s: node offline", rsc->id); return NULL; } else if(op->runnable == FALSE) { crm_debug_2("Skipping notification for %s: not runnable", op->uuid); return NULL; } value = g_hash_table_lookup(op->meta, "notify_type"); task = g_hash_table_lookup(op->meta, "notify_operation"); crm_debug_2("Creating notify actions for %s: %s (%s-%s)", op->uuid, rsc->id, value, task); key = generate_notify_key(rsc->id, value, task); trigger = custom_action(rsc, key, op->task, node, op->optional, TRUE, data_set); g_hash_table_foreach(op->meta, dup_attr, trigger->meta); g_hash_table_foreach(n_data->keys, dup_attr, trigger->meta); /* pseudo_notify before notify */ crm_debug_3("Ordering %s before %s (%d->%d)", op->uuid, trigger->uuid, trigger->id, op->id); order_actions(op, trigger, pe_order_implies_left); order_actions(trigger, confirm, pe_order_implies_left); return trigger; } static void pe_post_notify(resource_t *rsc, node_t *node, notify_data_t *n_data, pe_working_set_t *data_set) { action_t *notify = NULL; CRM_CHECK(rsc != NULL, return); if(n_data->post == NULL) { return; /* Nothing to do */ } notify = pe_notify(rsc, node, n_data->post, n_data->post_done, n_data, data_set); if(notify != NULL) { notify->priority = INFINITY; } if(n_data->post_done) { slist_iter( mon, action_t, rsc->actions, lpc, const char *interval = g_hash_table_lookup(mon->meta, "interval"); if(interval == NULL || safe_str_eq(interval, "0")) { crm_debug_3("Skipping %s: interval", mon->uuid); continue; } else if(safe_str_eq(mon->task, "cancel")) { crm_debug_3("Skipping %s: cancel", mon->uuid); continue; } order_actions(n_data->post_done, mon, pe_order_optional); ); } } notify_data_t * create_notification_boundaries( resource_t *rsc, const char *action, action_t *start, action_t *end, pe_working_set_t *data_set) { /* Create the pseudo ops that preceed and follow the actual notifications */ /* * Creates two sequences (conditional on start and end being supplied): * pre_notify -> pre_notify_complete -> start, and * end -> post_notify -> post_notify_complete * * 'start' and 'end' may be the same event or ${X} and ${X}ed as per clones */ char *key = NULL; notify_data_t *n_data = NULL; if(is_not_set(rsc->flags, pe_rsc_notify)) { return NULL; } crm_malloc0(n_data, sizeof(notify_data_t)); n_data->action = action; n_data->keys = g_hash_table_new_full( g_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); if(start) { /* create pre-event notification wrappers */ key = generate_notify_key(rsc->id, "pre", start->task); n_data->pre = custom_action( rsc, key, RSC_NOTIFY, NULL, start->optional, TRUE, data_set); n_data->pre->pseudo = TRUE; n_data->pre->runnable = TRUE; add_hash_param(n_data->pre->meta, "notify_type", "pre"); add_hash_param(n_data->pre->meta, "notify_operation", n_data->action); /* create pre_notify_complete */ key = generate_notify_key(rsc->id, "confirmed-pre", start->task); n_data->pre_done = custom_action( rsc, key, RSC_NOTIFIED, NULL, start->optional, TRUE, data_set); n_data->pre_done->pseudo = TRUE; n_data->pre_done->runnable = TRUE; add_hash_param(n_data->pre_done->meta, "notify_type", "pre"); add_hash_param(n_data->pre_done->meta, "notify_operation", n_data->action); order_actions(n_data->pre_done, start, pe_order_optional); order_actions(n_data->pre, n_data->pre_done, pe_order_optional); } if(end) { /* create post-event notification wrappers */ key = generate_notify_key(rsc->id, "post", end->task); n_data->post = custom_action( rsc, key, RSC_NOTIFY, NULL, end->optional, TRUE, data_set); n_data->post->pseudo = TRUE; n_data->post->runnable = TRUE; n_data->post->priority = INFINITY; n_data->post->runnable = end->runnable; add_hash_param(n_data->post->meta, "notify_type", "post"); add_hash_param(n_data->post->meta, "notify_operation", n_data->action); /* create post_notify_complete */ key = generate_notify_key(rsc->id, "confirmed-post", end->task); n_data->post_done = custom_action( rsc, key, RSC_NOTIFIED, NULL, end->optional, TRUE, data_set); n_data->post_done->pseudo = TRUE; n_data->post_done->runnable = TRUE; n_data->post_done->priority = INFINITY; n_data->post_done->runnable = end->runnable; add_hash_param(n_data->post_done->meta, "notify_type", "pre"); add_hash_param(n_data->post_done->meta, "notify_operation", n_data->action); order_actions(end, n_data->post, pe_order_implies_right); order_actions(n_data->post, n_data->post_done, pe_order_implies_right); } if(start && end) { order_actions(n_data->pre_done, n_data->post, pe_order_optional); } if(safe_str_eq(action, RSC_STOP)) { action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set); order_actions(n_data->post_done, all_stopped, pe_order_optional); } return n_data; } void collect_notification_data(resource_t *rsc, gboolean state, gboolean activity, notify_data_t *n_data) { if(rsc->children) { slist_iter(child, resource_t, rsc->children, lpc, collect_notification_data(child, state, activity, n_data); ); return; } if(state) { notify_entry_t *entry = NULL; crm_malloc0(entry, sizeof(notify_entry_t)); entry->rsc = rsc; if(rsc->running_on) { /* we only take the first one */ entry->node = rsc->running_on->data; } crm_debug_2("%s state: %s", rsc->id, role2text(rsc->role)); switch(rsc->role) { case RSC_ROLE_STOPPED: n_data->inactive = g_list_append(n_data->inactive, entry); break; case RSC_ROLE_STARTED: n_data->active = g_list_append(n_data->active, entry); break; case RSC_ROLE_SLAVE: n_data->slave = g_list_append(n_data->slave, entry); break; case RSC_ROLE_MASTER: n_data->master = g_list_append(n_data->master, entry); break; default: crm_err("Unsupported notify role"); crm_free(entry); break; } } if(activity) { notify_entry_t *entry = NULL; enum action_tasks task; slist_iter( op, action_t, rsc->actions, lpc, if(op->optional == FALSE && op->node != NULL) { crm_malloc0(entry, sizeof(notify_entry_t)); entry->node = op->node; entry->rsc = rsc; task = text2task(op->task); switch(task) { case start_rsc: n_data->start = g_list_append(n_data->start, entry); break; case stop_rsc: n_data->stop = g_list_append(n_data->stop, entry); break; case action_promote: n_data->promote = g_list_append(n_data->promote, entry); break; case action_demote: n_data->demote = g_list_append(n_data->demote, entry); break; default: crm_free(entry); break; } } ); } } gboolean expand_notification_data(notify_data_t *n_data) { /* Expand the notification entries into a key=value hashtable * This hashtable is later used in action2xml() */ gboolean required = FALSE; char *rsc_list = NULL; char *node_list = NULL; if(n_data->stop) { n_data->stop = g_list_sort(n_data->stop, sort_notify_entries); } expand_list(n_data->stop, &rsc_list, &node_list); if(rsc_list != NULL && safe_str_neq(" ", rsc_list)) { if(safe_str_eq(n_data->action, RSC_STOP)) { required = TRUE; } } g_hash_table_insert(n_data->keys, crm_strdup("notify_stop_resource"), rsc_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_stop_uname"), node_list); if(n_data->start) { n_data->start = g_list_sort(n_data->start, sort_notify_entries); if(rsc_list && safe_str_eq(n_data->action, RSC_START)) { required = TRUE; } } expand_list(n_data->start, &rsc_list, &node_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_start_resource"), rsc_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_start_uname"), node_list); if(n_data->demote) { n_data->demote = g_list_sort(n_data->demote, sort_notify_entries); if(safe_str_eq(n_data->action, RSC_DEMOTE)) { required = TRUE; } } expand_list(n_data->demote, &rsc_list, &node_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_demote_resource"), rsc_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_demote_uname"), node_list); if(n_data->promote) { n_data->promote = g_list_sort(n_data->promote, sort_notify_entries); if(safe_str_eq(n_data->action, RSC_PROMOTE)) { required = TRUE; } } expand_list(n_data->promote, &rsc_list, &node_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_promote_resource"), rsc_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_promote_uname"), node_list); if(n_data->active) { n_data->active = g_list_sort(n_data->active, sort_notify_entries); } expand_list(n_data->active, &rsc_list, &node_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_active_resource"), rsc_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_active_uname"), node_list); if(n_data->slave) { n_data->slave = g_list_sort(n_data->slave, sort_notify_entries); } expand_list(n_data->slave, &rsc_list, &node_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_slave_resource"), rsc_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_slave_uname"), node_list); if(n_data->master) { n_data->master = g_list_sort(n_data->master, sort_notify_entries); } expand_list(n_data->master, &rsc_list, &node_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_master_resource"), rsc_list); g_hash_table_insert(n_data->keys, crm_strdup("notify_master_uname"), node_list); if(n_data->inactive) { n_data->inactive = g_list_sort(n_data->inactive, sort_notify_entries); } expand_list(n_data->inactive, &rsc_list, NULL); g_hash_table_insert(n_data->keys, crm_strdup("notify_inactive_resource"), rsc_list); if(required && n_data->pre) { n_data->pre->optional = FALSE; n_data->pre_done->optional = FALSE; } if(required && n_data->post) { n_data->post->optional = FALSE; n_data->post_done->optional = FALSE; } return required; } void create_notifications(resource_t *rsc, notify_data_t *n_data, pe_working_set_t *data_set) { action_t *stop = NULL; action_t *start = NULL; enum action_tasks task = text2task(n_data->action); if(rsc->children) { slist_iter( child, resource_t, rsc->children, lpc, create_notifications(child, n_data, data_set); ); return; } /* Copy notification details into standard ops */ slist_iter( op, action_t, rsc->actions, lpc, if(op->optional == FALSE && op->node != NULL) { enum action_tasks t = text2task(op->task); switch(t) { case start_rsc: case stop_rsc: case action_promote: case action_demote: g_hash_table_foreach(n_data->keys, dup_attr, op->meta); break; default: break; } } ); crm_debug_2("Creating notificaitons for: %s.%s (%s->%s)", n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role)); stop = find_first_action(rsc->actions, NULL, RSC_STOP, NULL); start = find_first_action(rsc->actions, NULL, RSC_START, NULL); /* stop / demote */ if(rsc->role != RSC_ROLE_STOPPED) { if(task == stop_rsc || task == action_demote) { slist_iter(current_node, node_t, rsc->running_on, lpc, pe_notify(rsc, current_node, n_data->pre, n_data->pre_done, n_data, data_set); if(task == action_demote || stop == NULL || stop->optional) { pe_post_notify(rsc, current_node, n_data, data_set); } ); } } /* start / promote */ if(rsc->next_role != RSC_ROLE_STOPPED) { if(rsc->allocated_to == NULL) { pe_proc_err("Next role '%s' but %s is not allocated", role2text(rsc->next_role), rsc->id); } else if(task == start_rsc || task == action_promote) { if(task != start_rsc || start == NULL || start->optional) { pe_notify(rsc, rsc->allocated_to, n_data->pre, n_data->pre_done, n_data, data_set); } pe_post_notify(rsc, rsc->allocated_to, n_data, data_set); } } } void free_notification_data(notify_data_t *n_data) { if(n_data == NULL) { return; } pe_free_shallow(n_data->stop); pe_free_shallow(n_data->start); pe_free_shallow(n_data->demote); pe_free_shallow(n_data->promote); pe_free_shallow(n_data->master); pe_free_shallow(n_data->slave); pe_free_shallow(n_data->active); pe_free_shallow(n_data->inactive); g_hash_table_destroy(n_data->keys); crm_free(n_data); } 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; transition_id++; crm_debug_2("Creating transition graph %d.", transition_id); data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH); value = pe_pref(data_set->config_hash, "cluster-delay"); crm_xml_add(data_set->graph, "cluster-delay", value); value = pe_pref(data_set->config_hash, "stonith-timeout"); crm_xml_add(data_set->graph, "stonith-timeout", value); crm_xml_add(data_set->graph, "failed-stop-offset", "INFINITY"); if(is_set(data_set->flags, pe_flag_start_failure_fatal)) { crm_xml_add(data_set->graph, "failed-start-offset", "INFINITY"); } else { crm_xml_add(data_set->graph, "failed-start-offset", "1"); } value = pe_pref(data_set->config_hash, "batch-limit"); crm_xml_add(data_set->graph, "batch-limit", value); crm_xml_add_int(data_set->graph, "transition_id", transition_id); /* 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; crm_debug_3("deleting inter-resource cons: %p", data_set->colocation_constraints); pe_free_shallow(data_set->colocation_constraints); data_set->colocation_constraints = NULL; cleanup_calculations(data_set); } diff --git a/pengine/graph.c b/pengine/graph.c index 6d9b6f9f48..d7f3a96841 100644 --- a/pengine/graph.c +++ b/pengine/graph.c @@ -1,784 +1,785 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include gboolean update_action(action_t *action); gboolean update_action_states(GListPtr actions) { crm_debug_2("Updating %d actions", g_list_length(actions)); slist_iter( action, action_t, actions, lpc, update_action(action); ); return TRUE; } static gboolean any_possible(resource_t *rsc, const char *task) { if(rsc && rsc->children) { slist_iter(child, resource_t, rsc->children, lpc, if(any_possible(child, task)) { return TRUE; } ); } else if(rsc) { slist_iter(op, action_t, rsc->actions, lpc, if(task && safe_str_neq(op->task, task)) { continue; } if(op->runnable) { return TRUE; } ); } return FALSE; } static action_t *first_required(resource_t *rsc, const char *task) { if(rsc && rsc->children) { slist_iter(child, resource_t, rsc->children, lpc, action_t *op = first_required(child, task); if(op) { return op; } ); } else if(rsc) { slist_iter(op, action_t, rsc->actions, lpc, if(task && safe_str_neq(op->task, task)) { continue; } if(op->optional == FALSE) { return op; } ); } return NULL; } gboolean update_action(action_t *action) { int local_type = 0; int default_log_level = LOG_DEBUG_3; int log_level = default_log_level; gboolean changed = FALSE; do_crm_log_unlikely(log_level, "Processing action %s: %s %s %s", action->uuid, action->optional?"optional":"required", action->runnable?"runnable":"unrunnable", action->pseudo?"pseudo":action->task); slist_iter( other, action_wrapper_t, action->actions_before, lpc, gboolean other_changed = FALSE; node_t *node = other->action->node; resource_t *other_rsc = other->action->rsc; enum rsc_role_e other_role = RSC_ROLE_UNKNOWN; unsigned long long other_flags = 0; const char *other_id = "None"; if(other_rsc) { other_id = other_rsc->id; other_flags = other_rsc->flags; other_role = other_rsc->fns->state(other_rsc, TRUE); } if(other->type & pe_order_test) { log_level = LOG_NOTICE; do_crm_log_unlikely(log_level, "Processing action %s: %s %s %s", action->uuid, action->optional?"optional":"required", action->runnable?"runnable":"unrunnable", action->pseudo?"pseudo":action->task); } else { log_level = default_log_level; } do_crm_log_unlikely(log_level, " Checking action %s: %s %s %s (flags=0x%.6x)", other->action->uuid, other->action->optional?"optional":"required", other->action->runnable?"runnable":"unrunnable", other->action->pseudo?"pseudo":other->action->task, other->type); local_type = other->type; if((local_type & pe_order_demote_stop) && other->action->pseudo == FALSE && other_role > RSC_ROLE_SLAVE && node != NULL && node->details->online) { local_type |= pe_order_implies_left; do_crm_log_unlikely(log_level,"Upgrading demote->stop constraint to implies_left"); } if((local_type & pe_order_demote) && other->action->pseudo == FALSE && other_role > RSC_ROLE_SLAVE && node != NULL && node->details->online) { local_type |= pe_order_runnable_left; do_crm_log_unlikely(log_level,"Upgrading restart constraint to runnable_left"); } if((local_type & pe_order_complex_right) && (local_type ^ pe_order_complex_right) != pe_order_optional) { if(action->optional && other->action->optional == FALSE) { local_type |= pe_order_implies_right; do_crm_log_unlikely(log_level,"Upgrading complex constraint to implies_right"); } else if(action->runnable && any_possible(other->action->rsc, RSC_START) == FALSE) { action_t *first = first_required(action->rsc, RSC_START); if(first && first->runnable) { do_crm_log_unlikely( log_level-1, " * Marking action %s manditory because of %s (complex right)", first->uuid, other->action->uuid); action->runnable = FALSE; first->runnable = FALSE; update_action(first); changed = TRUE; } } } if((local_type & pe_order_complex_left) && action->optional == FALSE && other->action->optional && (local_type ^ pe_order_complex_left) != pe_order_optional) { local_type |= pe_order_implies_left; do_crm_log_unlikely(log_level,"Upgrading complex constraint to implies_left"); } if((local_type & pe_order_shutdown) && action->optional && other->action->optional == FALSE && is_set(other_flags, pe_rsc_shutdown)) { action->optional = FALSE; changed = TRUE; do_crm_log_unlikely(log_level-1, " * Marking action %s manditory because of %s (complex)", action->uuid, other->action->uuid); } if((local_type & pe_order_restart) && other_role > RSC_ROLE_STOPPED) { if(other_rsc && other_rsc->variant == pe_native) { local_type |= pe_order_implies_left; do_crm_log_unlikely(log_level,"Upgrading restart constraint to implies_left"); } if(other->action->optional && other->action->runnable && action->runnable == FALSE) { do_crm_log_unlikely(log_level-1, " * Marking action %s manditory because %s is unrunnable", other->action->uuid, action->uuid); other->action->optional = FALSE; if(other_rsc) { set_bit(other_rsc->flags, pe_rsc_shutdown); } other_changed = TRUE; } } if((local_type & pe_order_runnable_left) && other->action->runnable == FALSE) { if(other->action->implied_by_stonith) { do_crm_log_unlikely(log_level, "Ignoring un-runnable - implied_by_stonith"); } else if(action->runnable == FALSE) { do_crm_log_unlikely(log_level+1, "Already un-runnable"); } else { action->runnable = FALSE; do_crm_log_unlikely(log_level-1, " * Marking action %s un-runnable because of %s", action->uuid, other->action->uuid); changed = TRUE; } } if((local_type & pe_order_runnable_right) && action->runnable == FALSE) { if(action->pseudo) { do_crm_log_unlikely(log_level, "Ignoring un-runnable - pseudo"); } else if(other->action->runnable == FALSE) { do_crm_log_unlikely(log_level+1, "Already un-runnable"); } else { other->action->runnable = FALSE; do_crm_log_unlikely(log_level-1, " * Marking action %s un-runnable because of %s", other->action->uuid, action->uuid); other_changed = TRUE; } } if(local_type & pe_order_implies_left) { if(other->action->optional == FALSE) { /* nothing to do */ do_crm_log_unlikely(log_level+1, " Ignoring implies left - redundant"); } else if(safe_str_eq(other->action->task, RSC_STOP) && other_role == RSC_ROLE_STOPPED) { do_crm_log_unlikely(log_level-1, " Ignoring implies left - %s already stopped", other_id); } else if((local_type & pe_order_demote) && other_role < RSC_ROLE_MASTER) { do_crm_log_unlikely(log_level-1, " Ignoring implies left - %s already demoted", other_id); } else if(action->optional == FALSE) { other->action->optional = FALSE; do_crm_log_unlikely(log_level-1, " * (implies left) Marking action %s mandatory because of %s", other->action->uuid, action->uuid); other_changed = TRUE; } else { do_crm_log_unlikely(log_level, " Ignoring implies left"); } } if(local_type & pe_order_implies_left_printed) { if(other->action->optional == TRUE && other->action->print_always == FALSE) { if(action->optional == FALSE || (other->action->pseudo && action->print_always)) { other_changed = TRUE; other->action->print_always = TRUE; do_crm_log_unlikely(log_level-1, " * (implies left) Ensuring action %s is included because of %s", other->action->uuid, action->uuid); } } } if(local_type & pe_order_implies_right) { if(action->optional == FALSE) { /* nothing to do */ do_crm_log_unlikely(log_level+1, " Ignoring implies right - redundant"); } else if(other->action->optional == FALSE) { action->optional = FALSE; do_crm_log_unlikely(log_level-1, " * (implies right) Marking action %s mandatory because of %s", action->uuid, other->action->uuid); changed = TRUE; } else { do_crm_log_unlikely(log_level, " Ignoring implies right"); } } if(local_type & pe_order_implies_right_printed) { if(action->optional == TRUE && action->print_always == FALSE) { if(other->action->optional == FALSE || (action->pseudo && other->action->print_always)) { changed = TRUE; action->print_always = TRUE; do_crm_log_unlikely(log_level-1, " * (implies right) Ensuring action %s is included because of %s", action->uuid, other->action->uuid); } } } if(other_changed) { do_crm_log_unlikely(log_level, "%s changed, processing after list", other->action->uuid); update_action(other->action); slist_iter( before_other, action_wrapper_t, other->action->actions_after, lpc2, do_crm_log_unlikely(log_level, "%s changed, processing %s", other->action->uuid, before_other->action->uuid); update_action(before_other->action); ); slist_iter( before_other, action_wrapper_t, other->action->actions_before, lpc2, do_crm_log_unlikely(log_level, "%s changed, processing %s", other->action->uuid, before_other->action->uuid); update_action(before_other->action); ); } ); if(changed) { update_action(action); do_crm_log_unlikely(log_level, "%s changed, processing after list", action->uuid); slist_iter( other, action_wrapper_t, action->actions_after, lpc, do_crm_log_unlikely(log_level, "%s changed, processing %s", action->uuid, other->action->uuid); update_action(other->action); ); do_crm_log_unlikely(log_level, "%s changed, processing before list", action->uuid); slist_iter( other, action_wrapper_t, action->actions_before, lpc, do_crm_log_unlikely(log_level, "%s changed, processing %s", action->uuid, other->action->uuid); update_action(other->action); ); } return FALSE; } gboolean shutdown_constraints( node_t *node, action_t *shutdown_op, pe_working_set_t *data_set) { /* add the stop to the before lists so it counts as a pre-req * for the shutdown */ slist_iter( rsc, resource_t, node->details->running_rsc, lpc, if(is_not_set(rsc->flags, pe_rsc_managed)) { continue; } custom_action_order( rsc, stop_key(rsc), NULL, NULL, crm_strdup(CRM_OP_SHUTDOWN), shutdown_op, pe_order_implies_left, data_set); ); return TRUE; } gboolean stonith_constraints( node_t *node, action_t *stonith_op, pe_working_set_t *data_set) { CRM_CHECK(stonith_op != NULL, return FALSE); /* * Make sure the stonith OP occurs before we start any shared resources */ if(stonith_op != NULL) { slist_iter( rsc, resource_t, data_set->resources, lpc, rsc->cmds->stonith_ordering(rsc, stonith_op, data_set); ); } /* add the stonith OP as a stop pre-req and the mark the stop * as a pseudo op - since its now redundant */ return TRUE; } xmlNode * action2xml(action_t *action, gboolean as_input) { gboolean needs_node_info = TRUE; xmlNode * action_xml = NULL; xmlNode * args_xml = NULL; char *action_id_s = NULL; if(action == NULL) { return NULL; } crm_debug_4("Dumping action %d as XML", action->id); if(safe_str_eq(action->task, CRM_OP_FENCE)) { action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT); /* needs_node_info = FALSE; */ } else if(safe_str_eq(action->task, CRM_OP_SHUTDOWN)) { action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT); } else if(safe_str_eq(action->task, CRM_OP_LRM_REFRESH)) { action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT); /* } else if(safe_str_eq(action->task, RSC_PROBED)) { */ /* action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT); */ } else if(action->pseudo) { action_xml = create_xml_node(NULL, XML_GRAPH_TAG_PSEUDO_EVENT); needs_node_info = FALSE; } else { action_xml = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP); } action_id_s = crm_itoa(action->id); crm_xml_add(action_xml, XML_ATTR_ID, action_id_s); crm_free(action_id_s); crm_xml_add(action_xml, XML_LRM_ATTR_TASK, action->task); if(action->rsc != NULL && action->rsc->clone_name != NULL) { char *clone_key = NULL; const char *interval_s = g_hash_table_lookup(action->meta, "interval"); int interval = crm_parse_int(interval_s, "0"); if(safe_str_eq(action->task, RSC_NOTIFY)) { const char *n_type = g_hash_table_lookup(action->meta, "notify_type"); const char *n_task = g_hash_table_lookup(action->meta, "notify_operation"); CRM_CHECK(n_type != NULL, crm_err("No notify type value found for %s", action->uuid)); CRM_CHECK(n_task != NULL, crm_err("No notify operation value found for %s", action->uuid)); clone_key = generate_notify_key(action->rsc->clone_name, n_type, n_task); } else { clone_key = generate_op_key(action->rsc->clone_name, action->task, interval); } CRM_CHECK(clone_key != NULL, crm_err("Could not generate a key for %s", action->uuid)); crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, clone_key); crm_xml_add(action_xml, "internal_"XML_LRM_ATTR_TASK_KEY, action->uuid); crm_free(clone_key); } else { crm_xml_add(action_xml, XML_LRM_ATTR_TASK_KEY, action->uuid); } if(needs_node_info && action->node != NULL) { crm_xml_add(action_xml, XML_LRM_ATTR_TARGET, action->node->details->uname); crm_xml_add(action_xml, XML_LRM_ATTR_TARGET_UUID, action->node->details->id); } if(action->failure_is_fatal == FALSE) { add_hash_param(action->meta, XML_ATTR_TE_ALLOWFAIL, XML_BOOLEAN_TRUE); } if(as_input) { return action_xml; } if(action->rsc) { if(action->pseudo == FALSE) { int lpc = 0; xmlNode *rsc_xml = create_xml_node( action_xml, crm_element_name(action->rsc->xml)); const char *attr_list[] = { XML_AGENT_ATTR_CLASS, XML_AGENT_ATTR_PROVIDER, XML_ATTR_TYPE }; if(action->rsc->clone_name != NULL) { crm_debug("Using clone name %s for %s", action->rsc->clone_name, action->rsc->id); crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->clone_name); crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->id); } else { crm_xml_add(rsc_xml, XML_ATTR_ID, action->rsc->id); crm_xml_add(rsc_xml, XML_ATTR_ID_LONG, action->rsc->long_name); } for(lpc = 0; lpc < DIMOF(attr_list); lpc++) { crm_xml_add(rsc_xml, attr_list[lpc], g_hash_table_lookup(action->rsc->meta, attr_list[lpc])); } } } args_xml = create_xml_node(NULL, XML_TAG_ATTRS); crm_xml_add(args_xml, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET); g_hash_table_foreach(action->extra, hash2field, args_xml); if(action->rsc != NULL && safe_str_neq(action->task, RSC_STOP)) { g_hash_table_foreach(action->rsc->parameters, hash2smartfield, args_xml); } g_hash_table_foreach(action->meta, hash2metafield, args_xml); if(action->rsc != NULL) { int lpc = 0; char *value = NULL; const char *key = NULL; const char *meta_list[] = { XML_RSC_ATTR_UNIQUE, XML_RSC_ATTR_INCARNATION, XML_RSC_ATTR_INCARNATION_MAX, XML_RSC_ATTR_INCARNATION_NODEMAX, XML_RSC_ATTR_MASTER_MAX, XML_RSC_ATTR_MASTER_NODEMAX, }; for(lpc = 0; lpc < DIMOF(meta_list); lpc++) { key = meta_list[lpc]; value = g_hash_table_lookup(action->rsc->meta, key); if(value != NULL) { char *key_copy = crm_strdup(key); /* fucking glib */ hash2metafield(key_copy, value, args_xml); crm_free(key_copy); } } } sorted_xml(args_xml, action_xml, FALSE); crm_log_xml_debug_4(action_xml, "dumped action"); free_xml(args_xml); return action_xml; } static gboolean should_dump_action(action_t *action) { int log_filter = LOG_DEBUG_5; CRM_CHECK(action != NULL, return FALSE); if(action->dumped) { do_crm_log_unlikely(log_filter, "action %d (%s) was already dumped", action->id, action->uuid); return FALSE; } else if(action->runnable == FALSE) { do_crm_log_unlikely(log_filter, "action %d (%s) was not runnable", action->id, action->uuid); return FALSE; } else if(action->optional && action->print_always == FALSE) { do_crm_log_unlikely(log_filter, "action %d (%s) was optional", action->id, action->uuid); return FALSE; } else if(action->rsc != NULL && is_not_set(action->rsc->flags, pe_rsc_managed)) { const char * interval = NULL; interval = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL); /* make sure probes and recurring monitors go through */ if(safe_str_neq(action->task, RSC_STATUS) && interval == NULL) { do_crm_log_unlikely(log_filter, "action %d (%s) was for an unmanaged resource (%s)", action->id, action->uuid, action->rsc->id); return FALSE; } } if(action->pseudo || safe_str_eq(action->task, CRM_OP_FENCE) || safe_str_eq(action->task, CRM_OP_SHUTDOWN)) { /* skip the next checks */ return TRUE; } if(action->node == NULL) { pe_err("action %d (%s) was not allocated", action->id, action->uuid); log_action(LOG_DEBUG, "Unallocated action", action, FALSE); return FALSE; } else if(action->node->details->online == FALSE) { pe_err("action %d was (%s) scheduled for offline node", action->id, action->uuid); log_action(LOG_DEBUG, "Action for offline node", action, FALSE); return FALSE; #if 0 /* but this would also affect resources that can be safely * migrated before a fencing op */ } else if(action->node->details->unclean == FALSE) { pe_err("action %d was (%s) scheduled for unclean node", action->id, action->uuid); log_action(LOG_DEBUG, "Action for unclean node", action, FALSE); return FALSE; #endif } return TRUE; } /* lowest to highest */ static gint sort_action_id(gconstpointer a, gconstpointer b) { const action_wrapper_t *action_wrapper2 = (const action_wrapper_t*)a; const action_wrapper_t *action_wrapper1 = (const action_wrapper_t*)b; if(a == NULL) { return 1; } if(b == NULL) { return -1; } if(action_wrapper1->action->id > action_wrapper2->action->id) { return -1; } if(action_wrapper1->action->id < action_wrapper2->action->id) { return 1; } return 0; } static gboolean should_dump_input(int last_action, action_t *action, action_wrapper_t *wrapper) { int type = wrapper->type; int log_dump = LOG_DEBUG_3; int log_filter = LOG_DEBUG_3; type &= ~pe_order_implies_left_printed; type &= ~pe_order_implies_right_printed; type &= ~pe_order_optional; wrapper->state = pe_link_not_dumped; if(last_action == wrapper->action->id) { do_crm_log_unlikely(log_filter, "Input (%d) %s duplicated for %s", wrapper->action->id, wrapper->action->uuid, action->uuid); wrapper->state = pe_link_dup; return FALSE; } else if(wrapper->type == pe_order_none) { do_crm_log_unlikely(log_filter, "Input (%d) %s suppressed for %s", wrapper->action->id, wrapper->action->uuid, action->uuid); return FALSE; } else if(wrapper->action->runnable == FALSE - && type == pe_order_none) { + && type == pe_order_none + && safe_str_neq(wrapper->action->uuid, CRM_OP_PROBED)) { do_crm_log_unlikely(log_filter, "Input (%d) %s optional (ordering) for %s", wrapper->action->id, wrapper->action->uuid, action->uuid); return FALSE; } else if(action->pseudo && (wrapper->type & pe_order_stonith_stop)) { do_crm_log_unlikely(log_filter, "Input (%d) %s suppressed for %s", wrapper->action->id, wrapper->action->uuid, action->uuid); return FALSE; } else if(wrapper->action->dumped || should_dump_action(wrapper->action)) { do_crm_log_unlikely(log_dump, "Input (%d) %s should be dumped for %s", wrapper->action->id, wrapper->action->uuid, action->uuid); goto dump; #if 0 } if(wrapper->action->runnable && wrapper->action->pseudo && wrapper->action->rsc->variant != pe_native) { do_crm_log(LOG_CRIT, "Input (%d) %s should be dumped for %s", wrapper->action->id, wrapper->action->uuid, action->uuid); goto dump; #endif } else if(wrapper->action->optional == TRUE && wrapper->action->print_always == FALSE) { do_crm_log_unlikely(log_filter, "Input (%d) %s optional for %s", wrapper->action->id, wrapper->action->uuid, action->uuid); do_crm_log_unlikely(log_filter, "Input (%d) %s n=%p p=%d r=%d o=%d a=%d f=0x%.6x", wrapper->action->id, wrapper->action->uuid, wrapper->action->node, wrapper->action->pseudo, wrapper->action->runnable, wrapper->action->optional, wrapper->action->print_always, wrapper->type); return FALSE; } dump: do_crm_log_unlikely(log_dump, "Input (%d) %s n=%p p=%d r=%d o=%d a=%d f=0x%.6x dumped for %s", wrapper->action->id, wrapper->action->uuid, wrapper->action->node, wrapper->action->pseudo, wrapper->action->runnable, wrapper->action->optional, wrapper->action->print_always, wrapper->type, action->uuid); return TRUE; } void graph_element_from_action(action_t *action, pe_working_set_t *data_set) { int last_action = -1; int synapse_priority = 0; xmlNode * syn = NULL; xmlNode * set = NULL; xmlNode * in = NULL; xmlNode * input = NULL; xmlNode * xml_action = NULL; if(should_dump_action(action) == FALSE) { return; } action->dumped = TRUE; syn = create_xml_node(data_set->graph, "synapse"); set = create_xml_node(syn, "action_set"); in = create_xml_node(syn, "inputs"); crm_xml_add_int(syn, XML_ATTR_ID, data_set->num_synapse); data_set->num_synapse++; if(action->rsc != NULL) { synapse_priority = action->rsc->priority; } if(action->priority > synapse_priority) { synapse_priority = action->priority; } if(synapse_priority > 0) { crm_xml_add_int(syn, XML_CIB_ATTR_PRIORITY, synapse_priority); } xml_action = action2xml(action, FALSE); add_node_nocopy(set, crm_element_name(xml_action), xml_action); action->actions_before = g_list_sort( action->actions_before, sort_action_id); slist_iter(wrapper,action_wrapper_t,action->actions_before,lpc, if(should_dump_input(last_action, action, wrapper) == FALSE) { continue; } wrapper->state = pe_link_dumped; CRM_CHECK(last_action < wrapper->action->id, ;); last_action = wrapper->action->id; input = create_xml_node(in, "trigger"); xml_action = action2xml(wrapper->action, TRUE); add_node_nocopy(input, crm_element_name(xml_action), xml_action); ); } diff --git a/pengine/regression.sh b/pengine/regression.sh index 8252f1f7db..8cbaf1f8d9 100755 --- a/pengine/regression.sh +++ b/pengine/regression.sh @@ -1,337 +1,339 @@ #!/bin/bash # 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 # if [ -x /usr/bin/valgrind ]; then export G_SLICE=always-malloc VALGRIND_CMD="valgrind -q --show-reachable=no --leak-check=full --trace-children=no --time-stamp=yes --num-callers=20 --suppressions=./ptest.supp" fi . regression.core.sh create_mode="true" echo Generating test outputs for these tests... # do_test file description echo Done. echo "" echo Performing the following tests... create_mode="false" echo "" do_test simple1 "Offline " do_test simple2 "Start " do_test simple3 "Start 2 " do_test simple4 "Start Failed" do_test simple6 "Stop Start " do_test simple7 "Shutdown " #do_test simple8 "Stonith " #do_test simple9 "Lower version" #do_test simple10 "Higher version" do_test simple11 "Priority (ne)" do_test simple12 "Priority (eq)" do_test simple8 "Stickiness" echo "" do_test params-0 "Params: No change" do_test params-1 "Params: Changed" do_test params-2 "Params: Resource definition" do_test params-4 "Params: Reload" do_test novell-251689 "Resource definition change + target_role=stopped" do_test bug-lf-2106 "Restart all anonymous clone instances after config change" echo "" do_test orphan-0 "Orphan ignore" do_test orphan-1 "Orphan stop" echo "" do_test target-0 "Target Role : baseline" do_test target-1 "Target Role : master" do_test target-2 "Target Role : invalid" echo "" do_test date-1 "Dates" -d "2005-020" do_test date-2 "Date Spec - Pass" -d "2005-020T12:30" do_test date-3 "Date Spec - Fail" -d "2005-020T11:30" do_test probe-0 "Probe (anon clone)" do_test probe-1 "Pending Probe" do_test probe-2 "Correctly re-probe cloned groups" +do_test probe-3 "Probe (pending node)" +do_test probe-4 "Probe (pending node + stopped resource)" --rc 5 do_test standby "Standby" do_test comments "Comments" echo "" do_test rsc_dep1 "Must not " do_test rsc_dep3 "Must " do_test rsc_dep5 "Must not 3 " do_test rsc_dep7 "Must 3 " do_test rsc_dep10 "Must (but cant)" do_test rsc_dep2 "Must (running) " do_test rsc_dep8 "Must (running : alt) " do_test rsc_dep4 "Must (running + move)" do_test asymmetric "Asymmetric - require explicit location constraints" echo "" do_test order1 "Order start 1 " do_test order2 "Order start 2 " do_test order3 "Order stop " do_test order4 "Order (multiple) " do_test order5 "Order (move) " do_test order6 "Order (move w/ restart) " do_test order7 "Order (manditory) " do_test order-optional "Order (score=0) " do_test order-required "Order (score=INFINITY) " do_test bug-lf-2171 "Prevent group start when clone is stopped" do_test order-clone "Clone ordering should be able to prevent startup of dependant clones" do_test order-sets "Ordering for resource sets" echo "" do_test coloc-loop "Colocation - loop" do_test coloc-many-one "Colocation - many-to-one" do_test coloc-list "Colocation - many-to-one with list" do_test coloc-group "Colocation - groups" do_test coloc-slave-anti "Anti-colocation with slave shouldn't prevent master colocation" do_test coloc-attr "Colocation based on node attributes" do_test coloc-negative-group "Negative colocation with a group" #echo "" #do_test agent1 "version: lt (empty)" #do_test agent2 "version: eq " #do_test agent3 "version: gt " echo "" do_test attrs1 "string: eq (and) " do_test attrs2 "string: lt / gt (and)" do_test attrs3 "string: ne (or) " do_test attrs4 "string: exists " do_test attrs5 "string: not_exists " do_test attrs6 "is_dc: true " do_test attrs7 "is_dc: false " do_test attrs8 "score_attribute " echo "" do_test mon-rsc-1 "Schedule Monitor - start" do_test mon-rsc-2 "Schedule Monitor - move " do_test mon-rsc-3 "Schedule Monitor - pending start " do_test mon-rsc-4 "Schedule Monitor - move/pending start" echo "" do_test rec-rsc-0 "Resource Recover - no start " do_test rec-rsc-1 "Resource Recover - start " do_test rec-rsc-2 "Resource Recover - monitor " do_test rec-rsc-3 "Resource Recover - stop - ignore" do_test rec-rsc-4 "Resource Recover - stop - block " do_test rec-rsc-5 "Resource Recover - stop - fence " do_test rec-rsc-6 "Resource Recover - multiple - restart" do_test rec-rsc-7 "Resource Recover - multiple - stop " do_test rec-rsc-8 "Resource Recover - multiple - block " do_test rec-rsc-9 "Resource Recover - group/group" echo "" do_test quorum-1 "No quorum - ignore" do_test quorum-2 "No quorum - freeze" do_test quorum-3 "No quorum - stop " do_test quorum-4 "No quorum - start anyway" do_test quorum-5 "No quorum - start anyway (group)" do_test quorum-6 "No quorum - start anyway (clone)" echo "" do_test rec-node-1 "Node Recover - Startup - no fence" do_test rec-node-2 "Node Recover - Startup - fence " do_test rec-node-3 "Node Recover - HA down - no fence" do_test rec-node-4 "Node Recover - HA down - fence " do_test rec-node-5 "Node Recover - CRM down - no fence" do_test rec-node-6 "Node Recover - CRM down - fence " do_test rec-node-7 "Node Recover - no quorum - ignore " do_test rec-node-8 "Node Recover - no quorum - freeze " do_test rec-node-9 "Node Recover - no quorum - stop " do_test rec-node-10 "Node Recover - no quorum - stop w/fence" do_test rec-node-11 "Node Recover - CRM down w/ group - fence " do_test rec-node-12 "Node Recover - nothing active - fence " do_test rec-node-13 "Node Recover - failed resource + shutdown - fence " do_test rec-node-15 "Node Recover - unknown lrm section" do_test rec-node-14 "Serialize all stonith's" echo "" do_test multi1 "Multiple Active (stop/start)" echo "" do_test migrate-stop "Migration in a stopping stack" do_test migrate-start "Migration in a starting stack" do_test migrate-stop_start "Migration in a restarting stack" do_test migrate-stop-complex "Migration in a complex stopping stack" do_test migrate-start-complex "Migration in a complex starting stack" do_test migrate-stop-start-complex "Migration in a complex moving stack" do_test migrate-1 "Migrate (migrate)" do_test migrate-2 "Migrate (stable)" do_test migrate-3 "Migrate (failed migrate_to)" do_test migrate-4 "Migrate (failed migrate_from)" do_test novell-252693 "Migration in a stopping stack" do_test novell-252693-2 "Migration in a starting stack" do_test novell-252693-3 "Non-Migration in a starting and stopping stack" do_test bug-1820 "Migration in a group" do_test bug-1820-1 "Non-migration in a group" do_test migrate-5 "Primitive migration with a clone" #echo "" #do_test complex1 "Complex " echo "" do_test group1 "Group " do_test group2 "Group + Native " do_test group3 "Group + Group " do_test group4 "Group + Native (nothing)" do_test group5 "Group + Native (move) " do_test group6 "Group + Group (move) " do_test group7 "Group colocation" do_test group13 "Group colocation (cant run)" do_test group8 "Group anti-colocation" do_test group9 "Group recovery" do_test group10 "Group partial recovery" do_test group11 "Group target_role" do_test group14 "Group stop (graph terminated)" do_test group15 "-ve group colocation" do_test bug-1573 "Partial stop of a group with two children" do_test bug-1718 "Mandatory group ordering - Stop group_FUN" echo "" do_test clone-anon-probe-1 "Probe the correct (anonymous) clone instance for each node" do_test clone-anon-probe-2 "Avoid needless re-probing of anonymous clones" do_test inc0 "Incarnation start" do_test inc1 "Incarnation start order" do_test inc2 "Incarnation silent restart, stop, move" do_test inc3 "Inter-incarnation ordering, silent restart, stop, move" do_test inc4 "Inter-incarnation ordering, silent restart, stop, move (ordered)" do_test inc5 "Inter-incarnation ordering, silent restart, stop, move (restart 1)" do_test inc6 "Inter-incarnation ordering, silent restart, stop, move (restart 2)" do_test inc7 "Clone colocation" do_test inc8 "Clone anti-colocation" do_test inc9 "Non-unique clone" do_test inc10 "Non-unique clone (stop)" do_test inc11 "Primitive colocation with clones" do_test inc12 "Clone shutdown" do_test cloned-group "Make sure only the correct number of cloned groups are started" do_test clone-no-shuffle "Dont prioritize allocation of instances that must be moved" do_test clone-max-zero "Orphan processing with clone-max=0" do_test clone-anon-dup "Bug LF#2087 - Correctly parse the state of anonymous clones that are active more than once per node" do_test bug-lf-2160 "Dont shuffle clones due to colocation" do_test bug-lf-2213 "clone-node-max enforcement for cloned groups" do_test bug-lf-2153 "Clone ordering constraints" echo "" do_test master-0 "Stopped -> Slave" do_test master-1 "Stopped -> Promote" do_test master-2 "Stopped -> Promote : notify" do_test master-3 "Stopped -> Promote : master location" do_test master-4 "Started -> Promote : master location" do_test master-5 "Promoted -> Promoted" do_test master-6 "Promoted -> Promoted (2)" do_test master-7 "Promoted -> Fenced" do_test master-8 "Promoted -> Fenced -> Moved" do_test master-9 "Stopped + Promotable + No quorum" do_test master-10 "Stopped -> Promotable : notify with monitor" do_test master-11 "Stopped -> Promote : colocation" do_test novell-239082 "Demote/Promote ordering" do_test novell-239087 "Stable master placement" do_test master-12 "Promotion based solely on rsc_location constraints" do_test master-13 "Include preferences of colocated resources when placing master" do_test master-demote "Ordering when actions depends on demoting a slave resource" do_test master-ordering "Prevent resources from starting that need a master" do_test bug-1765 "Master-Master Colocation (dont stop the slaves)" do_test master-group "Promotion of cloned groups" do_test bug-lf-1852 "Don't shuffle master/slave instances unnecessarily" do_test master-failed-demote "Dont retry failed demote actions" do_test master-failed-demote-2 "Dont retry failed demote actions (notify=false)" do_test master-depend "Ensure resources that depend on the master don't get allocated until the master does" do_test master-reattach "Re-attach to a running master" do_test master-allow-start "Don't include master score if it would prevent allocation" do_test master-colocation "Allow master instances placemaker to be influenced by colocation constraints" do_test master-pseudo "Make sure promote/demote pseudo actions are created correctly" do_test master-role "Prevent target-role from promoting more than master-max instances" echo "" do_test managed-0 "Managed (reference)" do_test managed-1 "Not managed - down " do_test managed-2 "Not managed - up " echo "" do_test interleave-0 "Interleave (reference)" do_test interleave-1 "coloc - not interleaved" do_test interleave-2 "coloc - interleaved " do_test interleave-3 "coloc - interleaved (2)" do_test interleave-pseudo-stop "Interleaved clone during stonith" do_test interleave-stop "Interleaved clone during stop" do_test interleave-restart "Interleaved clone during dependancy restart" echo "" do_test notify-0 "Notify reference" do_test notify-1 "Notify simple" do_test notify-2 "Notify simple, confirm" do_test notify-3 "Notify move, confirm" do_test novell-239079 "Notification priority" #do_test notify-2 "Notify - 764" echo "" do_test 594 "OSDL #594" do_test 662 "OSDL #662" do_test 696 "OSDL #696" do_test 726 "OSDL #726" do_test 735 "OSDL #735" do_test 764 "OSDL #764" do_test 797 "OSDL #797" do_test 829 "OSDL #829" do_test 994 "OSDL #994" do_test 994-2 "OSDL #994 - with a dependant resource" do_test 1360 "OSDL #1360 - Clone stickiness" do_test 1484 "OSDL #1484 - on_fail=stop" do_test 1494 "OSDL #1494 - Clone stability" do_test unrunnable-1 "Unrunnable" do_test stonith-0 "Stonith loop - 1" do_test stonith-1 "Stonith loop - 2" do_test stonith-2 "Stonith loop - 3" do_test stonith-3 "Stonith startup" do_test bug-1572-1 "Recovery of groups depending on master/slave" do_test bug-1572-2 "Recovery of groups depending on master/slave when the master is never re-promoted" do_test bug-1685 "Depends-on-master ordering" do_test bug-1822 "Dont promote partially active groups" do_test bug-pm-11 "New resource added to a m/s group" do_test bug-pm-12 "Recover only the failed portion of a cloned group" do_test bug-n-387749 "Don't shuffle clone instances" do_test bug-n-385265 "Don't ignore the failure stickiness of group children - resource_idvscommon should stay stopped" do_test bug-n-385265-2 "Ensure groups are migrated instead of remaining partially active on the current node" do_test bug-lf-1920 "Correctly handle probes that find active resources" do_test bnc-515172 "Location constraint with multiple expressions" echo "" do_test systemhealth1 "System Health () #1" do_test systemhealth2 "System Health () #2" do_test systemhealth3 "System Health () #3" do_test systemhealthn1 "System Health (None) #1" do_test systemhealthn2 "System Health (None) #2" do_test systemhealthn3 "System Health (None) #3" do_test systemhealthm1 "System Health (Migrate On Red) #1" do_test systemhealthm2 "System Health (Migrate On Red) #2" do_test systemhealthm3 "System Health (Migrate On Red) #3" do_test systemhealtho1 "System Health (Only Green) #1" do_test systemhealtho2 "System Health (Only Green) #2" do_test systemhealtho3 "System Health (Only Green) #3" do_test systemhealthp1 "System Health (Progessive) #1" do_test systemhealthp2 "System Health (Progessive) #2" do_test systemhealthp3 "System Health (Progessive) #3" echo "" test_results diff --git a/pengine/test10/probe-3.dot b/pengine/test10/probe-3.dot new file mode 100644 index 0000000000..39612290b5 --- /dev/null +++ b/pengine/test10/probe-3.dot @@ -0,0 +1,29 @@ +digraph "g" { +"FencingChild:0_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"FencingChild:0_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"lsb-dummy_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"lsb-dummy_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"migrator_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"migrator_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"ping-1:0_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"ping-1:0_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"probe_complete pcmk-4" -> "probe_complete" [ style = dashed] +"probe_complete pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"probe_complete" [ style=dashed color="red" fontcolor="orange" ] +"r192.168.101.181_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"r192.168.101.181_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"r192.168.101.182_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"r192.168.101.182_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"r192.168.101.183_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"r192.168.101.183_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"rsc_pcmk-1_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"rsc_pcmk-1_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"rsc_pcmk-2_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"rsc_pcmk-2_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"rsc_pcmk-3_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"rsc_pcmk-3_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"rsc_pcmk-4_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"rsc_pcmk-4_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"stateful-1:0_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"stateful-1:0_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +} diff --git a/pengine/test10/probe-3.exp b/pengine/test10/probe-3.exp new file mode 100644 index 0000000000..8700711440 --- /dev/null +++ b/pengine/test10/probe-3.exp @@ -0,0 +1,2 @@ + + diff --git a/pengine/test10/probe-3.scores b/pengine/test10/probe-3.scores new file mode 100644 index 0000000000..afb38cf00f --- /dev/null +++ b/pengine/test10/probe-3.scores @@ -0,0 +1,169 @@ +Allocation scores: +group_color: group-1 allocation score on pcmk-1: 0 +group_color: group-1 allocation score on pcmk-2: 0 +group_color: group-1 allocation score on pcmk-3: 0 +group_color: group-1 allocation score on pcmk-4: 0 +group_color: r192.168.101.181 allocation score on pcmk-1: 0 +group_color: r192.168.101.181 allocation score on pcmk-2: 0 +group_color: r192.168.101.181 allocation score on pcmk-3: 0 +group_color: r192.168.101.181 allocation score on pcmk-4: 0 +group_color: r192.168.101.182 allocation score on pcmk-1: 0 +group_color: r192.168.101.182 allocation score on pcmk-2: 0 +group_color: r192.168.101.182 allocation score on pcmk-3: 0 +group_color: r192.168.101.182 allocation score on pcmk-4: 0 +group_color: r192.168.101.183 allocation score on pcmk-1: 0 +group_color: r192.168.101.183 allocation score on pcmk-2: 0 +group_color: r192.168.101.183 allocation score on pcmk-3: 0 +group_color: r192.168.101.183 allocation score on pcmk-4: 0 +clone_color: master-1 allocation score on pcmk-1: 0 +clone_color: master-1 allocation score on pcmk-2: 0 +clone_color: master-1 allocation score on pcmk-3: 0 +clone_color: master-1 allocation score on pcmk-4: -1000000 +clone_color: stateful-1:0 allocation score on pcmk-1: 11 +clone_color: stateful-1:0 allocation score on pcmk-2: 5 +clone_color: stateful-1:0 allocation score on pcmk-3: 5 +clone_color: stateful-1:0 allocation score on pcmk-4: 0 +clone_color: stateful-1:1 allocation score on pcmk-1: 10 +clone_color: stateful-1:1 allocation score on pcmk-2: 6 +clone_color: stateful-1:1 allocation score on pcmk-3: 5 +clone_color: stateful-1:1 allocation score on pcmk-4: 0 +clone_color: stateful-1:2 allocation score on pcmk-1: 10 +clone_color: stateful-1:2 allocation score on pcmk-2: 5 +clone_color: stateful-1:2 allocation score on pcmk-3: 6 +clone_color: stateful-1:2 allocation score on pcmk-4: 0 +clone_color: stateful-1:3 allocation score on pcmk-1: 0 +clone_color: stateful-1:3 allocation score on pcmk-2: 0 +clone_color: stateful-1:3 allocation score on pcmk-3: 0 +clone_color: stateful-1:3 allocation score on pcmk-4: 0 +native_color: stateful-1:0 allocation score on pcmk-1: 11 +native_color: stateful-1:0 allocation score on pcmk-2: 5 +native_color: stateful-1:0 allocation score on pcmk-3: 5 +native_color: stateful-1:0 allocation score on pcmk-4: -1000000 +native_color: stateful-1:1 allocation score on pcmk-1: -1000000 +native_color: stateful-1:1 allocation score on pcmk-2: 6 +native_color: stateful-1:1 allocation score on pcmk-3: 5 +native_color: stateful-1:1 allocation score on pcmk-4: -1000000 +native_color: stateful-1:2 allocation score on pcmk-1: -1000000 +native_color: stateful-1:2 allocation score on pcmk-2: -1000000 +native_color: stateful-1:2 allocation score on pcmk-3: 6 +native_color: stateful-1:2 allocation score on pcmk-4: -1000000 +native_color: stateful-1:3 allocation score on pcmk-1: -1000000 +native_color: stateful-1:3 allocation score on pcmk-2: -1000000 +native_color: stateful-1:3 allocation score on pcmk-3: -1000000 +native_color: stateful-1:3 allocation score on pcmk-4: -1000000 +stateful-1:0 promotion score on pcmk-1: 10 +stateful-1:1 promotion score on pcmk-2: 5 +stateful-1:2 promotion score on pcmk-3: 5 +stateful-1:3 promotion score on none: 0 +native_color: r192.168.101.181 allocation score on pcmk-1: 11 +native_color: r192.168.101.181 allocation score on pcmk-2: -1000000 +native_color: r192.168.101.181 allocation score on pcmk-3: -1000000 +native_color: r192.168.101.181 allocation score on pcmk-4: -1000000 +native_color: r192.168.101.182 allocation score on pcmk-1: 0 +native_color: r192.168.101.182 allocation score on pcmk-2: -1000000 +native_color: r192.168.101.182 allocation score on pcmk-3: -1000000 +native_color: r192.168.101.182 allocation score on pcmk-4: -1000000 +native_color: r192.168.101.183 allocation score on pcmk-1: 0 +native_color: r192.168.101.183 allocation score on pcmk-2: -1000000 +native_color: r192.168.101.183 allocation score on pcmk-3: -1000000 +native_color: r192.168.101.183 allocation score on pcmk-4: -1000000 +native_color: rsc_pcmk-1 allocation score on pcmk-1: 100 +native_color: rsc_pcmk-1 allocation score on pcmk-2: 0 +native_color: rsc_pcmk-1 allocation score on pcmk-3: 0 +native_color: rsc_pcmk-1 allocation score on pcmk-4: 0 +native_color: rsc_pcmk-2 allocation score on pcmk-1: 0 +native_color: rsc_pcmk-2 allocation score on pcmk-2: 100 +native_color: rsc_pcmk-2 allocation score on pcmk-3: 0 +native_color: rsc_pcmk-2 allocation score on pcmk-4: 0 +native_color: rsc_pcmk-3 allocation score on pcmk-1: 0 +native_color: rsc_pcmk-3 allocation score on pcmk-2: 0 +native_color: rsc_pcmk-3 allocation score on pcmk-3: 100 +native_color: rsc_pcmk-3 allocation score on pcmk-4: 0 +native_color: rsc_pcmk-4 allocation score on pcmk-1: 0 +native_color: rsc_pcmk-4 allocation score on pcmk-2: 0 +native_color: rsc_pcmk-4 allocation score on pcmk-3: 0 +native_color: rsc_pcmk-4 allocation score on pcmk-4: 100 +native_color: lsb-dummy allocation score on pcmk-1: 0 +native_color: lsb-dummy allocation score on pcmk-2: -1000000 +native_color: lsb-dummy allocation score on pcmk-3: -1000000 +native_color: lsb-dummy allocation score on pcmk-4: -1000000 +native_color: migrator allocation score on pcmk-1: 0 +native_color: migrator allocation score on pcmk-2: 0 +native_color: migrator allocation score on pcmk-3: 0 +native_color: migrator allocation score on pcmk-4: 0 +clone_color: Connectivity allocation score on pcmk-1: 0 +clone_color: Connectivity allocation score on pcmk-2: 0 +clone_color: Connectivity allocation score on pcmk-3: 0 +clone_color: Connectivity allocation score on pcmk-4: 0 +clone_color: ping-1:0 allocation score on pcmk-1: 1 +clone_color: ping-1:0 allocation score on pcmk-2: 0 +clone_color: ping-1:0 allocation score on pcmk-3: 0 +clone_color: ping-1:0 allocation score on pcmk-4: 0 +clone_color: ping-1:1 allocation score on pcmk-1: 0 +clone_color: ping-1:1 allocation score on pcmk-2: 1 +clone_color: ping-1:1 allocation score on pcmk-3: 0 +clone_color: ping-1:1 allocation score on pcmk-4: 0 +clone_color: ping-1:2 allocation score on pcmk-1: 0 +clone_color: ping-1:2 allocation score on pcmk-2: 0 +clone_color: ping-1:2 allocation score on pcmk-3: 1 +clone_color: ping-1:2 allocation score on pcmk-4: 0 +clone_color: ping-1:3 allocation score on pcmk-1: 0 +clone_color: ping-1:3 allocation score on pcmk-2: 0 +clone_color: ping-1:3 allocation score on pcmk-3: 0 +clone_color: ping-1:3 allocation score on pcmk-4: 0 +native_color: ping-1:0 allocation score on pcmk-1: 1 +native_color: ping-1:0 allocation score on pcmk-2: 0 +native_color: ping-1:0 allocation score on pcmk-3: 0 +native_color: ping-1:0 allocation score on pcmk-4: -1000000 +native_color: ping-1:1 allocation score on pcmk-1: -1000000 +native_color: ping-1:1 allocation score on pcmk-2: 1 +native_color: ping-1:1 allocation score on pcmk-3: 0 +native_color: ping-1:1 allocation score on pcmk-4: -1000000 +native_color: ping-1:2 allocation score on pcmk-1: -1000000 +native_color: ping-1:2 allocation score on pcmk-2: -1000000 +native_color: ping-1:2 allocation score on pcmk-3: 1 +native_color: ping-1:2 allocation score on pcmk-4: -1000000 +native_color: ping-1:3 allocation score on pcmk-1: -1000000 +native_color: ping-1:3 allocation score on pcmk-2: -1000000 +native_color: ping-1:3 allocation score on pcmk-3: -1000000 +native_color: ping-1:3 allocation score on pcmk-4: -1000000 +stateful-1:0 promotion score on pcmk-1: 1000000 +stateful-1:1 promotion score on pcmk-2: -1000000 +stateful-1:2 promotion score on pcmk-3: -1000000 +stateful-1:3 promotion score on none: 0 +clone_color: Fencing allocation score on pcmk-1: 0 +clone_color: Fencing allocation score on pcmk-2: 0 +clone_color: Fencing allocation score on pcmk-3: 0 +clone_color: Fencing allocation score on pcmk-4: 0 +clone_color: FencingChild:0 allocation score on pcmk-1: 0 +clone_color: FencingChild:0 allocation score on pcmk-2: 0 +clone_color: FencingChild:0 allocation score on pcmk-3: 1 +clone_color: FencingChild:0 allocation score on pcmk-4: 0 +clone_color: FencingChild:1 allocation score on pcmk-1: 0 +clone_color: FencingChild:1 allocation score on pcmk-2: 0 +clone_color: FencingChild:1 allocation score on pcmk-3: 0 +clone_color: FencingChild:1 allocation score on pcmk-4: 0 +clone_color: FencingChild:2 allocation score on pcmk-1: 0 +clone_color: FencingChild:2 allocation score on pcmk-2: 1 +clone_color: FencingChild:2 allocation score on pcmk-3: 0 +clone_color: FencingChild:2 allocation score on pcmk-4: 0 +clone_color: FencingChild:3 allocation score on pcmk-1: 1 +clone_color: FencingChild:3 allocation score on pcmk-2: 0 +clone_color: FencingChild:3 allocation score on pcmk-3: 0 +clone_color: FencingChild:3 allocation score on pcmk-4: 0 +native_color: FencingChild:0 allocation score on pcmk-1: 0 +native_color: FencingChild:0 allocation score on pcmk-2: 0 +native_color: FencingChild:0 allocation score on pcmk-3: 1 +native_color: FencingChild:0 allocation score on pcmk-4: -1000000 +native_color: FencingChild:2 allocation score on pcmk-1: 0 +native_color: FencingChild:2 allocation score on pcmk-2: 1 +native_color: FencingChild:2 allocation score on pcmk-3: -1000000 +native_color: FencingChild:2 allocation score on pcmk-4: -1000000 +native_color: FencingChild:3 allocation score on pcmk-1: 1 +native_color: FencingChild:3 allocation score on pcmk-2: -1000000 +native_color: FencingChild:3 allocation score on pcmk-3: -1000000 +native_color: FencingChild:3 allocation score on pcmk-4: -1000000 +native_color: FencingChild:1 allocation score on pcmk-1: -1000000 +native_color: FencingChild:1 allocation score on pcmk-2: -1000000 +native_color: FencingChild:1 allocation score on pcmk-3: -1000000 +native_color: FencingChild:1 allocation score on pcmk-4: -1000000 diff --git a/pengine/test10/probe-3.xml b/pengine/test10/probe-3.xml new file mode 100644 index 0000000000..7c409d9893 --- /dev/null +++ b/pengine/test10/probe-3.xml @@ -0,0 +1,358 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pengine/test10/probe-4.dot b/pengine/test10/probe-4.dot new file mode 100644 index 0000000000..72b9b95350 --- /dev/null +++ b/pengine/test10/probe-4.dot @@ -0,0 +1,33 @@ +digraph "g" { +"FencingChild:0_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"FencingChild:0_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"lsb-dummy_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"lsb-dummy_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"migrator_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"migrator_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"migrator_monitor_10000 pcmk-3" [ style=bold color="green" fontcolor="black" ] +"migrator_start_0 pcmk-3" -> "migrator_monitor_10000 pcmk-3" [ style = bold] +"migrator_start_0 pcmk-3" [ style=bold color="green" fontcolor="black" ] +"ping-1:0_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"ping-1:0_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"probe_complete pcmk-4" -> "probe_complete" [ style = dashed] +"probe_complete pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"probe_complete" -> "migrator_start_0 pcmk-3" [ style = bold] +"probe_complete" [ style=dashed color="red" fontcolor="orange" ] +"r192.168.101.181_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"r192.168.101.181_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"r192.168.101.182_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"r192.168.101.182_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"r192.168.101.183_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"r192.168.101.183_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"rsc_pcmk-1_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"rsc_pcmk-1_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"rsc_pcmk-2_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"rsc_pcmk-2_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"rsc_pcmk-3_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"rsc_pcmk-3_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"rsc_pcmk-4_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"rsc_pcmk-4_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +"stateful-1:0_monitor_0 pcmk-4" -> "probe_complete pcmk-4" [ style = dashed] +"stateful-1:0_monitor_0 pcmk-4" [ style=dashed color="red" fontcolor="black" ] +} diff --git a/pengine/test10/probe-4.exp b/pengine/test10/probe-4.exp new file mode 100644 index 0000000000..562a754ad4 --- /dev/null +++ b/pengine/test10/probe-4.exp @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pengine/test10/probe-4.scores b/pengine/test10/probe-4.scores new file mode 100644 index 0000000000..afb38cf00f --- /dev/null +++ b/pengine/test10/probe-4.scores @@ -0,0 +1,169 @@ +Allocation scores: +group_color: group-1 allocation score on pcmk-1: 0 +group_color: group-1 allocation score on pcmk-2: 0 +group_color: group-1 allocation score on pcmk-3: 0 +group_color: group-1 allocation score on pcmk-4: 0 +group_color: r192.168.101.181 allocation score on pcmk-1: 0 +group_color: r192.168.101.181 allocation score on pcmk-2: 0 +group_color: r192.168.101.181 allocation score on pcmk-3: 0 +group_color: r192.168.101.181 allocation score on pcmk-4: 0 +group_color: r192.168.101.182 allocation score on pcmk-1: 0 +group_color: r192.168.101.182 allocation score on pcmk-2: 0 +group_color: r192.168.101.182 allocation score on pcmk-3: 0 +group_color: r192.168.101.182 allocation score on pcmk-4: 0 +group_color: r192.168.101.183 allocation score on pcmk-1: 0 +group_color: r192.168.101.183 allocation score on pcmk-2: 0 +group_color: r192.168.101.183 allocation score on pcmk-3: 0 +group_color: r192.168.101.183 allocation score on pcmk-4: 0 +clone_color: master-1 allocation score on pcmk-1: 0 +clone_color: master-1 allocation score on pcmk-2: 0 +clone_color: master-1 allocation score on pcmk-3: 0 +clone_color: master-1 allocation score on pcmk-4: -1000000 +clone_color: stateful-1:0 allocation score on pcmk-1: 11 +clone_color: stateful-1:0 allocation score on pcmk-2: 5 +clone_color: stateful-1:0 allocation score on pcmk-3: 5 +clone_color: stateful-1:0 allocation score on pcmk-4: 0 +clone_color: stateful-1:1 allocation score on pcmk-1: 10 +clone_color: stateful-1:1 allocation score on pcmk-2: 6 +clone_color: stateful-1:1 allocation score on pcmk-3: 5 +clone_color: stateful-1:1 allocation score on pcmk-4: 0 +clone_color: stateful-1:2 allocation score on pcmk-1: 10 +clone_color: stateful-1:2 allocation score on pcmk-2: 5 +clone_color: stateful-1:2 allocation score on pcmk-3: 6 +clone_color: stateful-1:2 allocation score on pcmk-4: 0 +clone_color: stateful-1:3 allocation score on pcmk-1: 0 +clone_color: stateful-1:3 allocation score on pcmk-2: 0 +clone_color: stateful-1:3 allocation score on pcmk-3: 0 +clone_color: stateful-1:3 allocation score on pcmk-4: 0 +native_color: stateful-1:0 allocation score on pcmk-1: 11 +native_color: stateful-1:0 allocation score on pcmk-2: 5 +native_color: stateful-1:0 allocation score on pcmk-3: 5 +native_color: stateful-1:0 allocation score on pcmk-4: -1000000 +native_color: stateful-1:1 allocation score on pcmk-1: -1000000 +native_color: stateful-1:1 allocation score on pcmk-2: 6 +native_color: stateful-1:1 allocation score on pcmk-3: 5 +native_color: stateful-1:1 allocation score on pcmk-4: -1000000 +native_color: stateful-1:2 allocation score on pcmk-1: -1000000 +native_color: stateful-1:2 allocation score on pcmk-2: -1000000 +native_color: stateful-1:2 allocation score on pcmk-3: 6 +native_color: stateful-1:2 allocation score on pcmk-4: -1000000 +native_color: stateful-1:3 allocation score on pcmk-1: -1000000 +native_color: stateful-1:3 allocation score on pcmk-2: -1000000 +native_color: stateful-1:3 allocation score on pcmk-3: -1000000 +native_color: stateful-1:3 allocation score on pcmk-4: -1000000 +stateful-1:0 promotion score on pcmk-1: 10 +stateful-1:1 promotion score on pcmk-2: 5 +stateful-1:2 promotion score on pcmk-3: 5 +stateful-1:3 promotion score on none: 0 +native_color: r192.168.101.181 allocation score on pcmk-1: 11 +native_color: r192.168.101.181 allocation score on pcmk-2: -1000000 +native_color: r192.168.101.181 allocation score on pcmk-3: -1000000 +native_color: r192.168.101.181 allocation score on pcmk-4: -1000000 +native_color: r192.168.101.182 allocation score on pcmk-1: 0 +native_color: r192.168.101.182 allocation score on pcmk-2: -1000000 +native_color: r192.168.101.182 allocation score on pcmk-3: -1000000 +native_color: r192.168.101.182 allocation score on pcmk-4: -1000000 +native_color: r192.168.101.183 allocation score on pcmk-1: 0 +native_color: r192.168.101.183 allocation score on pcmk-2: -1000000 +native_color: r192.168.101.183 allocation score on pcmk-3: -1000000 +native_color: r192.168.101.183 allocation score on pcmk-4: -1000000 +native_color: rsc_pcmk-1 allocation score on pcmk-1: 100 +native_color: rsc_pcmk-1 allocation score on pcmk-2: 0 +native_color: rsc_pcmk-1 allocation score on pcmk-3: 0 +native_color: rsc_pcmk-1 allocation score on pcmk-4: 0 +native_color: rsc_pcmk-2 allocation score on pcmk-1: 0 +native_color: rsc_pcmk-2 allocation score on pcmk-2: 100 +native_color: rsc_pcmk-2 allocation score on pcmk-3: 0 +native_color: rsc_pcmk-2 allocation score on pcmk-4: 0 +native_color: rsc_pcmk-3 allocation score on pcmk-1: 0 +native_color: rsc_pcmk-3 allocation score on pcmk-2: 0 +native_color: rsc_pcmk-3 allocation score on pcmk-3: 100 +native_color: rsc_pcmk-3 allocation score on pcmk-4: 0 +native_color: rsc_pcmk-4 allocation score on pcmk-1: 0 +native_color: rsc_pcmk-4 allocation score on pcmk-2: 0 +native_color: rsc_pcmk-4 allocation score on pcmk-3: 0 +native_color: rsc_pcmk-4 allocation score on pcmk-4: 100 +native_color: lsb-dummy allocation score on pcmk-1: 0 +native_color: lsb-dummy allocation score on pcmk-2: -1000000 +native_color: lsb-dummy allocation score on pcmk-3: -1000000 +native_color: lsb-dummy allocation score on pcmk-4: -1000000 +native_color: migrator allocation score on pcmk-1: 0 +native_color: migrator allocation score on pcmk-2: 0 +native_color: migrator allocation score on pcmk-3: 0 +native_color: migrator allocation score on pcmk-4: 0 +clone_color: Connectivity allocation score on pcmk-1: 0 +clone_color: Connectivity allocation score on pcmk-2: 0 +clone_color: Connectivity allocation score on pcmk-3: 0 +clone_color: Connectivity allocation score on pcmk-4: 0 +clone_color: ping-1:0 allocation score on pcmk-1: 1 +clone_color: ping-1:0 allocation score on pcmk-2: 0 +clone_color: ping-1:0 allocation score on pcmk-3: 0 +clone_color: ping-1:0 allocation score on pcmk-4: 0 +clone_color: ping-1:1 allocation score on pcmk-1: 0 +clone_color: ping-1:1 allocation score on pcmk-2: 1 +clone_color: ping-1:1 allocation score on pcmk-3: 0 +clone_color: ping-1:1 allocation score on pcmk-4: 0 +clone_color: ping-1:2 allocation score on pcmk-1: 0 +clone_color: ping-1:2 allocation score on pcmk-2: 0 +clone_color: ping-1:2 allocation score on pcmk-3: 1 +clone_color: ping-1:2 allocation score on pcmk-4: 0 +clone_color: ping-1:3 allocation score on pcmk-1: 0 +clone_color: ping-1:3 allocation score on pcmk-2: 0 +clone_color: ping-1:3 allocation score on pcmk-3: 0 +clone_color: ping-1:3 allocation score on pcmk-4: 0 +native_color: ping-1:0 allocation score on pcmk-1: 1 +native_color: ping-1:0 allocation score on pcmk-2: 0 +native_color: ping-1:0 allocation score on pcmk-3: 0 +native_color: ping-1:0 allocation score on pcmk-4: -1000000 +native_color: ping-1:1 allocation score on pcmk-1: -1000000 +native_color: ping-1:1 allocation score on pcmk-2: 1 +native_color: ping-1:1 allocation score on pcmk-3: 0 +native_color: ping-1:1 allocation score on pcmk-4: -1000000 +native_color: ping-1:2 allocation score on pcmk-1: -1000000 +native_color: ping-1:2 allocation score on pcmk-2: -1000000 +native_color: ping-1:2 allocation score on pcmk-3: 1 +native_color: ping-1:2 allocation score on pcmk-4: -1000000 +native_color: ping-1:3 allocation score on pcmk-1: -1000000 +native_color: ping-1:3 allocation score on pcmk-2: -1000000 +native_color: ping-1:3 allocation score on pcmk-3: -1000000 +native_color: ping-1:3 allocation score on pcmk-4: -1000000 +stateful-1:0 promotion score on pcmk-1: 1000000 +stateful-1:1 promotion score on pcmk-2: -1000000 +stateful-1:2 promotion score on pcmk-3: -1000000 +stateful-1:3 promotion score on none: 0 +clone_color: Fencing allocation score on pcmk-1: 0 +clone_color: Fencing allocation score on pcmk-2: 0 +clone_color: Fencing allocation score on pcmk-3: 0 +clone_color: Fencing allocation score on pcmk-4: 0 +clone_color: FencingChild:0 allocation score on pcmk-1: 0 +clone_color: FencingChild:0 allocation score on pcmk-2: 0 +clone_color: FencingChild:0 allocation score on pcmk-3: 1 +clone_color: FencingChild:0 allocation score on pcmk-4: 0 +clone_color: FencingChild:1 allocation score on pcmk-1: 0 +clone_color: FencingChild:1 allocation score on pcmk-2: 0 +clone_color: FencingChild:1 allocation score on pcmk-3: 0 +clone_color: FencingChild:1 allocation score on pcmk-4: 0 +clone_color: FencingChild:2 allocation score on pcmk-1: 0 +clone_color: FencingChild:2 allocation score on pcmk-2: 1 +clone_color: FencingChild:2 allocation score on pcmk-3: 0 +clone_color: FencingChild:2 allocation score on pcmk-4: 0 +clone_color: FencingChild:3 allocation score on pcmk-1: 1 +clone_color: FencingChild:3 allocation score on pcmk-2: 0 +clone_color: FencingChild:3 allocation score on pcmk-3: 0 +clone_color: FencingChild:3 allocation score on pcmk-4: 0 +native_color: FencingChild:0 allocation score on pcmk-1: 0 +native_color: FencingChild:0 allocation score on pcmk-2: 0 +native_color: FencingChild:0 allocation score on pcmk-3: 1 +native_color: FencingChild:0 allocation score on pcmk-4: -1000000 +native_color: FencingChild:2 allocation score on pcmk-1: 0 +native_color: FencingChild:2 allocation score on pcmk-2: 1 +native_color: FencingChild:2 allocation score on pcmk-3: -1000000 +native_color: FencingChild:2 allocation score on pcmk-4: -1000000 +native_color: FencingChild:3 allocation score on pcmk-1: 1 +native_color: FencingChild:3 allocation score on pcmk-2: -1000000 +native_color: FencingChild:3 allocation score on pcmk-3: -1000000 +native_color: FencingChild:3 allocation score on pcmk-4: -1000000 +native_color: FencingChild:1 allocation score on pcmk-1: -1000000 +native_color: FencingChild:1 allocation score on pcmk-2: -1000000 +native_color: FencingChild:1 allocation score on pcmk-3: -1000000 +native_color: FencingChild:1 allocation score on pcmk-4: -1000000 diff --git a/pengine/test10/probe-4.xml b/pengine/test10/probe-4.xml new file mode 100644 index 0000000000..5328aa81e6 --- /dev/null +++ b/pengine/test10/probe-4.xml @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +