diff --git a/pengine/allocate.c b/pengine/allocate.c index aa69be41bc..6183fa5866 100644 --- a/pengine/allocate.c +++ b/pengine/allocate.c @@ -1,2192 +1,2244 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include - #include #include #include #include #include #include CRM_TRACE_INIT_DATA(pe_allocate); -void set_alloc_actions(pe_working_set_t *data_set); -void migrate_reload_madness(pe_working_set_t *data_set); +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_location, - native_action_flags, - native_update_actions, - native_expand, - native_append_meta, - }, + native_merge_weights, + native_color, + native_create_actions, + native_create_probe, + native_internal_constraints, + native_rsc_colocation_lh, + native_rsc_colocation_rh, + native_rsc_location, + native_action_flags, + native_update_actions, + native_expand, + native_append_meta, + }, { - group_merge_weights, - group_color, - group_create_actions, - native_create_probe, - group_internal_constraints, - group_rsc_colocation_lh, - group_rsc_colocation_rh, - group_rsc_location, - group_action_flags, - group_update_actions, - group_expand, - group_append_meta, - }, + group_merge_weights, + group_color, + group_create_actions, + native_create_probe, + group_internal_constraints, + group_rsc_colocation_lh, + group_rsc_colocation_rh, + group_rsc_location, + group_action_flags, + group_update_actions, + group_expand, + group_append_meta, + }, { - native_merge_weights, - clone_color, - clone_create_actions, - clone_create_probe, - clone_internal_constraints, - clone_rsc_colocation_lh, - clone_rsc_colocation_rh, - clone_rsc_location, - clone_action_flags, - clone_update_actions, - clone_expand, - clone_append_meta, - }, + native_merge_weights, + clone_color, + clone_create_actions, + clone_create_probe, + clone_internal_constraints, + clone_rsc_colocation_lh, + clone_rsc_colocation_rh, + clone_rsc_location, + clone_action_flags, + clone_update_actions, + clone_expand, + clone_append_meta, + }, { - native_merge_weights, - master_color, - master_create_actions, - clone_create_probe, - master_internal_constraints, - clone_rsc_colocation_lh, - master_rsc_colocation_rh, - clone_rsc_location, - clone_action_flags, - clone_update_actions, - clone_expand, - master_append_meta, - } + native_merge_weights, + master_color, + master_create_actions, + clone_create_probe, + master_internal_constraints, + clone_rsc_colocation_lh, + master_rsc_colocation_rh, + clone_rsc_location, + clone_action_flags, + clone_update_actions, + clone_expand, + master_append_meta, + } }; static gboolean -check_rsc_parameters(resource_t *rsc, node_t *node, xmlNode *rsc_entry, - pe_working_set_t *data_set) +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 + 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; + 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) +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 *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); 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"); + key, active_node->details->uname, reason ? reason : "unknown"); - cancel = custom_action(rsc, crm_strdup(key), RSC_CANCEL, - active_node, FALSE, TRUE, data_set); + 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_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; + + 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) +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; 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); - if(safe_str_eq(task, RSC_STOP)) { - return FALSE; + if (safe_str_eq(task, RSC_STOP)) { + 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; + if (interval > 0) { + xmlNode *op_match = NULL; - crm_debug_2("Checking parameters for %s", key); - op_match = find_rsc_op_entry(rsc, key); + 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); - crm_free(key); key = NULL; - return TRUE; + if (op_match == NULL && is_set(data_set->flags, pe_flag_stop_action_orphans)) { + CancelXmlOp(rsc, xml_op, active_node, "orphan", data_set); + crm_free(key); + key = NULL; + 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; - } + } 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( - crm_str_hash, g_str_equal, - g_hash_destroy_str, g_hash_destroy_str); - + + local_rsc_params = g_hash_table_new_full(crm_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_operation_digest(params_all, op_version); 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(interval == 0 && safe_str_eq(task, RSC_STATUS)) { - /* Reload based on the start action not a probe */ - task = RSC_START; - } - - if(digest_restart) { - /* Changes that force a restart */ - params_restart = copy_xml(params_all); - if(restart_list) { - filter_reload_parameters(params_restart, restart_list); - } - - digest_restart_calc = calculate_operation_digest(params_restart, op_version); - if(safe_str_neq(digest_restart_calc, digest_restart)) { - did_change = TRUE; - crm_log_xml_info(params_restart, "params:restart"); - crm_info("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)) { - /* Changes that can potentially be handled by a reload */ - action_t *op = NULL; - did_change = TRUE; - crm_log_xml_info(params_all, "params:reload"); - crm_crit("Parameters to %s on %s changed: recorded %s vs. %s (reload:%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) { + if (interval == 0 && safe_str_eq(task, RSC_STATUS)) { + /* Reload based on the start action not a probe */ + task = RSC_START; + } + + if (digest_restart) { + /* Changes that force a restart */ + params_restart = copy_xml(params_all); + if (restart_list) { + filter_reload_parameters(params_restart, restart_list); + } + + digest_restart_calc = calculate_operation_digest(params_restart, op_version); + if (safe_str_neq(digest_restart_calc, digest_restart)) { + did_change = TRUE; + crm_log_xml_info(params_restart, "params:restart"); + crm_info("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)) { + /* Changes that can potentially be handled by a reload */ + action_t *op = NULL; + + did_change = TRUE; + crm_log_xml_info(params_all, "params:reload"); + crm_crit("Parameters to %s on %s changed: recorded %s vs. %s (reload:%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) { #if 0 - /* Always reload/restart the entire resource */ - op = custom_action(rsc, start_key(rsc), RSC_START, NULL, FALSE, TRUE, data_set); - update_action_flags(op, pe_action_allow_reload_conversion); + /* Always reload/restart the entire resource */ + op = custom_action(rsc, start_key(rsc), RSC_START, NULL, FALSE, TRUE, data_set); + update_action_flags(op, pe_action_allow_reload_conversion); #else - /* Re-sending the recurring op is sufficient - the old one will be cancelled automatically */ - key = generate_op_key(rsc->id, task, interval); - op = custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set); - custom_action_order(rsc, start_key(rsc), NULL, - NULL, NULL, op, pe_order_runnable_left, data_set); + /* Re-sending the recurring op is sufficient - the old one will be cancelled automatically */ + key = generate_op_key(rsc->id, task, interval); + op = custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set); + custom_action_order(rsc, start_key(rsc), NULL, + NULL, NULL, op, pe_order_runnable_left, data_set); #endif - - } else if(digest_restart) { - crm_trace("Reloading '%s' action for resource %s", task, rsc->id); - /* Allow this resource to reload */ + } else if (digest_restart) { + crm_trace("Reloading '%s' action for resource %s", task, rsc->id); - /* TODO: Set for the resource itself - * - thus avoiding causing depedant resources to restart - */ - key = generate_op_key(rsc->id, task, interval); - op = custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set); + /* Allow this resource to reload */ - update_action_flags(op, pe_action_allow_reload_conversion); + /* TODO: Set for the resource itself + * - thus avoiding causing depedant resources to restart + */ + key = generate_op_key(rsc->id, task, interval); + op = custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set); - } else { - crm_trace("Resource %s doesn't know how to reload", rsc->id); + update_action_flags(op, pe_action_allow_reload_conversion); - /* Re-send the start/demote/promote op - * Recurring ops will be detected independantly - */ - key = generate_op_key(rsc->id, task, interval); - custom_action(rsc, key, task, NULL, FALSE, TRUE, data_set); - } + } else { + crm_trace("Resource %s doesn't know how to reload", rsc->id); + + /* Re-send the start/demote/promote op + * Recurring ops will be detected independantly + */ + key = generate_op_key(rsc->id, task, interval); + custom_action(rsc, key, task, NULL, FALSE, TRUE, 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); +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) +check_actions_for(xmlNode * rsc_entry, resource_t * rsc, node_t * node, pe_working_set_t * data_set) { GListPtr gIter = NULL; int offset = -1; int interval = 0; int stop_index = 0; int start_index = 0; const char *task = NULL; const char *interval_s = NULL; xmlNode *rsc_op = 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; + 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); + + if (check_rsc_parameters(rsc, node, rsc_entry, data_set)) { + DeleteRsc(rsc, node, FALSE, data_set); } - - for(rsc_op = __xml_first_child(rsc_entry); rsc_op != NULL; rsc_op = __xml_next(rsc_op)) { - if(crm_str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, TRUE)) { - op_list = g_list_prepend(op_list, rsc_op); - } + + for (rsc_op = __xml_first_child(rsc_entry); rsc_op != NULL; rsc_op = __xml_next(rsc_op)) { + if (crm_str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, TRUE)) { + op_list = g_list_prepend(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); - for(gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) { - xmlNode *rsc_op = (xmlNode*)gIter->data; - offset++; + for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) { + xmlNode *rsc_op = (xmlNode *) gIter->data; + + offset++; - if(start_index < stop_index) { - /* stopped */ - continue; - } else if(offset < start_index) { - /* action occurred prior to a start */ - continue; - } - - is_probe = FALSE; - task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); + if (start_index < stop_index) { + /* stopped */ + continue; + } else if (offset < start_index) { + /* action occurred prior to a start */ + continue; + } - 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; - } + is_probe = FALSE; + task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK); - if(interval > 0 && is_set(data_set->flags, pe_flag_maintenance_mode)) { - CancelXmlOp(rsc, rsc_op, node, "maintenance mode", data_set); + interval_s = crm_element_value(rsc_op, XML_LRM_ATTR_INTERVAL); + interval = crm_parse_int(interval_s, "0"); - } else if(is_probe || safe_str_eq(task, RSC_START) || interval > 0) { - check_action_definition(rsc, node, rsc_op, data_set); - } + 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) +find_rsc_list(GListPtr result, resource_t * rsc, const char *id, gboolean renamed_clones, + gboolean partial, pe_working_set_t * data_set) { GListPtr gIter = NULL; gboolean match = FALSE; - - if(id == NULL) { - return NULL; - } else if(rsc == NULL && data_set) { + if (id == NULL) { + return NULL; + + } else if (rsc == NULL && data_set) { - for(gIter = data_set->resources; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; + for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; - result = find_rsc_list(result, child, id, renamed_clones, partial, NULL); - } - - return result; + result = find_rsc_list(result, child, id, renamed_clones, partial, NULL); + } - } else if(rsc == NULL) { - return NULL; + return result; + + } else if (rsc == NULL) { + return NULL; } - if(partial) { - if(strstr(rsc->id, id)) { - match = TRUE; + 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(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 (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_prepend(result, rsc); + if (match) { + result = g_list_prepend(result, rsc); } - if(rsc->children) { - gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - result = find_rsc_list(result, child, id, renamed_clones, partial, NULL); - } + if (rsc->children) { + gIter = rsc->children; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + result = find_rsc_list(result, child, id, renamed_clones, partial, NULL); + } } - + return result; } static void -check_actions(pe_working_set_t *data_set) +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); xmlNode *node_state = NULL; - for(node_state = __xml_first_child(status); node_state != NULL; node_state = __xml_next(node_state)) { - if(crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE)) { - 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)) { - xmlNode *rsc_entry = NULL; - for(rsc_entry = __xml_first_child(lrm_rscs); rsc_entry != NULL; rsc_entry = __xml_next(rsc_entry)) { - if(crm_str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, TRUE)) { - - if(xml_has_children(rsc_entry)) { - GListPtr gIter = NULL; - 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); - for(gIter = result; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; - - check_actions_for(rsc_entry, rsc, node, data_set); - } - g_list_free(result); - } - } - } - } - } + + for (node_state = __xml_first_child(status); node_state != NULL; + node_state = __xml_next(node_state)) { + if (crm_str_eq((const char *)node_state->name, XML_CIB_TAG_STATE, TRUE)) { + 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)) { + xmlNode *rsc_entry = NULL; + + for (rsc_entry = __xml_first_child(lrm_rscs); rsc_entry != NULL; + rsc_entry = __xml_next(rsc_entry)) { + if (crm_str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, TRUE)) { + + if (xml_has_children(rsc_entry)) { + GListPtr gIter = NULL; + 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); + for (gIter = result; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; + + check_actions_for(rsc_entry, rsc, node, data_set); + } + g_list_free(result); + } + } + } + } + } } } -static gboolean -apply_placement_constraints(pe_working_set_t *data_set) +static gboolean +apply_placement_constraints(pe_working_set_t * data_set) { GListPtr gIter = NULL; + crm_debug_3("Applying constraints..."); - for(gIter = data_set->placement_constraints; gIter != NULL; gIter = gIter->next) { - rsc_to_node_t *cons = (rsc_to_node_t*)gIter->data; - cons->rsc_lh->cmds->rsc_location(cons->rsc_lh, cons); + for (gIter = data_set->placement_constraints; gIter != NULL; gIter = gIter->next) { + rsc_to_node_t *cons = (rsc_to_node_t *) gIter->data; + + 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) +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) { - GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - 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_hash_table_lookup(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 { - GHashTableIter iter; - node_t *nIter = NULL; - crm_debug("Ignoring stickiness for %s: the cluster is asymmetric" - " and node %s is not explicitly allowed", - rsc->id, node->details->uname); - g_hash_table_iter_init (&iter, rsc->allowed_nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&nIter)) { - crm_err("%s[%s] = %d", rsc->id, nIter->details->uname, nIter->weight); - } - } - } - - if(is_not_set(rsc->flags, pe_rsc_unique)) { - failed = uber_parent(rsc); - } - + if (rsc->children) { + GListPtr gIter = rsc->children; + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + 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_hash_table_lookup(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 { + GHashTableIter iter; + node_t *nIter = NULL; + + crm_debug("Ignoring stickiness for %s: the cluster is asymmetric" + " and node %s is not explicitly allowed", rsc->id, node->details->uname); + g_hash_table_iter_init(&iter, rsc->allowed_nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&nIter)) { + crm_err("%s[%s] = %d", rsc->id, nIter->details->uname, nIter->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); - } + 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) +static void +complex_set_cmds(resource_t * rsc) { GListPtr gIter = rsc->children; + rsc->cmds = &resource_class_alloc_functions[rsc->variant]; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - complex_set_cmds(child_rsc); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + complex_set_cmds(child_rsc); } } void -set_alloc_actions(pe_working_set_t *data_set) +set_alloc_actions(pe_working_set_t * data_set) { - + GListPtr gIter = data_set->resources; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; - complex_set_cmds(rsc); + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; + + complex_set_cmds(rsc); } } static void -calculate_system_health (gpointer gKey, gpointer gValue, gpointer user_data) +calculate_system_health(gpointer gKey, gpointer gValue, gpointer user_data) { - const char *key = (const char *)gKey; - const char *value = (const char *)gValue; + const char *key = (const char *)gKey; + const char *value = (const char *)gValue; int *system_health = (int *)user_data; if (!gKey || !gValue || !user_data) { - return; + return; } /* Does it start with #health? */ - if (0 == strncmp (key, "#health", 7)) { - int score; + if (0 == strncmp(key, "#health", 7)) { + int score; - /* Convert the value into an integer */ - score = char2score (value); + /* Convert the value into an integer */ + score = char2score(value); - /* Add it to the running total */ - *system_health = merge_weights (score, *system_health); + /* Add it to the running total */ + *system_health = merge_weights(score, *system_health); } } static gboolean -apply_system_health(pe_working_set_t *data_set) +apply_system_health(pe_working_set_t * data_set) { GListPtr gIter = NULL; 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; + 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); - - for(gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { - int system_health = 0; - node_t *node = (node_t*)gIter->data; - - /* 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) { - - GListPtr gIter2 = data_set->resources; - for(; gIter2 != NULL; gIter2 = gIter2->next) { - resource_t *rsc = (resource_t*)gIter2->data; - - rsc2node_new (health_strategy, rsc, system_health, node, data_set); - } - } - + crm_err("Unknown node health strategy: %s", health_strategy); + return FALSE; + } + + crm_info("Applying automated node health strategy: %s", health_strategy); + + for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { + int system_health = 0; + node_t *node = (node_t *) gIter->data; + + /* 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) { + + GListPtr gIter2 = data_set->resources; + + for (; gIter2 != NULL; gIter2 = gIter2->next) { + resource_t *rsc = (resource_t *) gIter2->data; + + rsc2node_new(health_strategy, rsc, system_health, node, data_set); + } + } + } return TRUE; } gboolean -stage0(pe_working_set_t *data_set) +stage0(pe_working_set_t * data_set) { - xmlNode * cib_constraints = get_object_root( - XML_CIB_TAG_CONSTRAINTS, data_set->input); + xmlNode *cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, data_set->input); - if(data_set->input == NULL) { - return FALSE; + if (data_set->input == NULL) { + return FALSE; } - if(is_set(data_set->flags, pe_flag_have_status) == FALSE) { - crm_trace("Calculating status"); - cluster_status(data_set); + if (is_set(data_set->flags, pe_flag_have_status) == FALSE) { + crm_trace("Calculating status"); + cluster_status(data_set); } - + set_alloc_actions(data_set); apply_system_health(data_set); unpack_constraints(cib_constraints, data_set); - + return TRUE; } - -static void wait_for_probe( - resource_t *rsc, const char *action, action_t *probe_complete, pe_working_set_t *data_set) +static void +wait_for_probe(resource_t * rsc, const char *action, action_t * probe_complete, + pe_working_set_t * data_set) { - if(probe_complete == NULL) { - return; - } - - if(rsc->children) { - GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - wait_for_probe(child, action, probe_complete, data_set); - } - + if (probe_complete == NULL) { + return; + } + + if (rsc->children) { + GListPtr gIter = rsc->children; + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + wait_for_probe(child, action, probe_complete, data_set); + } + } else { - char *key = generate_op_key(rsc->id, action, 0); - custom_action_order( - NULL, NULL, probe_complete, rsc, key, NULL, - pe_order_optional, data_set); + char *key = generate_op_key(rsc->id, action, 0); + + custom_action_order(NULL, NULL, probe_complete, rsc, key, NULL, + pe_order_optional, data_set); } } - /* * Check nodes for resources started outside of the LRM */ gboolean -probe_resources(pe_working_set_t *data_set) +probe_resources(pe_working_set_t * data_set) { action_t *probe_complete = NULL; action_t *probe_node_complete = NULL; GListPtr gIter = NULL; GListPtr gIter2 = NULL; gIter = data_set->nodes; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - 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) { - action_t *probe_op = custom_action( - NULL, crm_strdup(CRM_OP_REPROBE), - CRM_OP_REPROBE, node, FALSE, TRUE, data_set); - add_hash_param(probe_op->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); - continue; - } - - probe_node_complete = custom_action( - NULL, crm_strdup(CRM_OP_PROBED), - CRM_OP_PROBED, node, FALSE, TRUE, data_set); - if(crm_is_true(probed)) { - crm_trace("unset"); - update_action_flags(probe_node_complete, pe_action_optional); - } else { - crm_trace("set"); - update_action_flags(probe_node_complete, pe_action_optional|pe_action_clear); - } - crm_trace("%s - %d", node->details->uname, probe_node_complete->flags & pe_action_optional); - probe_node_complete->priority = INFINITY; - add_hash_param(probe_node_complete->meta, - XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); - - if(node->details->pending) { - update_action_flags(probe_node_complete, pe_action_runnable|pe_action_clear); - 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_runnable_left/*|pe_order_implies_then*/); - - gIter2 = data_set->resources; - for(; gIter2 != NULL; gIter2 = gIter2->next) { - resource_t *rsc = (resource_t*)gIter2->data; - - if(rsc->cmds->create_probe( - rsc, node, probe_node_complete, - FALSE, data_set)) { - - update_action_flags(probe_complete, pe_action_optional|pe_action_clear); - update_action_flags(probe_node_complete, pe_action_optional|pe_action_clear); - - wait_for_probe(rsc, RSC_START, probe_complete, data_set); - } - } + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + 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) { + action_t *probe_op = custom_action(NULL, crm_strdup(CRM_OP_REPROBE), + CRM_OP_REPROBE, node, FALSE, TRUE, data_set); + + add_hash_param(probe_op->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); + continue; + } + + probe_node_complete = custom_action(NULL, crm_strdup(CRM_OP_PROBED), + CRM_OP_PROBED, node, FALSE, TRUE, data_set); + if (crm_is_true(probed)) { + crm_trace("unset"); + update_action_flags(probe_node_complete, pe_action_optional); + } else { + crm_trace("set"); + update_action_flags(probe_node_complete, pe_action_optional | pe_action_clear); + } + crm_trace("%s - %d", node->details->uname, probe_node_complete->flags & pe_action_optional); + probe_node_complete->priority = INFINITY; + add_hash_param(probe_node_complete->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); + + if (node->details->pending) { + update_action_flags(probe_node_complete, pe_action_runnable | pe_action_clear); + 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_runnable_left /*|pe_order_implies_then */ ); + + gIter2 = data_set->resources; + for (; gIter2 != NULL; gIter2 = gIter2->next) { + resource_t *rsc = (resource_t *) gIter2->data; + + if (rsc->cmds->create_probe(rsc, node, probe_node_complete, FALSE, data_set)) { + + update_action_flags(probe_complete, pe_action_optional | pe_action_clear); + update_action_flags(probe_node_complete, pe_action_optional | pe_action_clear); + + wait_for_probe(rsc, RSC_START, probe_complete, data_set); + } + } } gIter = data_set->resources; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; - wait_for_probe(rsc, RSC_STOP, probe_complete, data_set); + wait_for_probe(rsc, RSC_STOP, probe_complete, 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) +stage2(pe_working_set_t * data_set) { GListPtr gIter = NULL; - crm_debug_3("Applying placement constraints"); - + + crm_debug_3("Applying placement constraints"); + gIter = data_set->nodes; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; - if(node == NULL) { - /* error */ + 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++; - } + } 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); gIter = data_set->nodes; - for(; gIter != NULL; gIter = gIter->next) { - GListPtr gIter2 = NULL; - node_t *node = (node_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + GListPtr gIter2 = NULL; + node_t *node = (node_t *) gIter->data; + + gIter2 = data_set->resources; + for (; gIter2 != NULL; gIter2 = gIter2->next) { + resource_t *rsc = (resource_t *) gIter2->data; - gIter2 = data_set->resources; - for(; gIter2 != NULL; gIter2 = gIter2->next) { - resource_t *rsc = (resource_t*)gIter2->data; - common_apply_stickiness(rsc, node, data_set); - } + common_apply_stickiness(rsc, node, data_set); + } } return TRUE; } - /* * Create internal resource constraints before allocation */ gboolean -stage3(pe_working_set_t *data_set) +stage3(pe_working_set_t * data_set) { - + GListPtr gIter = data_set->resources; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; - rsc->cmds->internal_constraints(rsc, data_set); + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; + + rsc->cmds->internal_constraints(rsc, data_set); } - + return TRUE; } /* * Check for orphaned or redefined actions */ gboolean -stage4(pe_working_set_t *data_set) +stage4(pe_working_set_t * data_set) { check_actions(data_set); return TRUE; } - static gint sort_rsc_process_order(gconstpointer a, gconstpointer b, gpointer data) { int rc = 0; int level = LOG_TRACE; int r1_weight = -INFINITY; int r2_weight = -INFINITY; const char *reason = "existance"; - const GListPtr nodes = (GListPtr)data; - resource_t *resource1 = (resource_t*)convert_const_pointer(a); - resource_t *resource2 = (resource_t*)convert_const_pointer(b); + const GListPtr nodes = (GListPtr) data; + resource_t *resource1 = (resource_t *) convert_const_pointer(a); + resource_t *resource2 = (resource_t *) convert_const_pointer(b); node_t *node = NULL; GListPtr gIter = NULL; GHashTable *r1_nodes = NULL; GHashTable *r2_nodes = NULL; - if(a == NULL && b == NULL) { goto done; } - if(a == NULL) { return 1; } - if(b == NULL) { return -1; } - + if (a == NULL && b == NULL) { + goto done; + } + if (a == NULL) { + return 1; + } + if (b == NULL) { + return -1; + } reason = "priority"; r1_weight = resource1->priority; r2_weight = resource2->priority; - if(r1_weight > r2_weight) { - rc = -1; goto done; + if (r1_weight > r2_weight) { + rc = -1; + goto done; } - - if(r1_weight < r2_weight) { - rc = 1; goto done; + + if (r1_weight < r2_weight) { + rc = 1; + goto done; } - + reason = "no node list"; if (nodes == NULL) { - goto done; + goto done; } - r1_nodes = rsc_merge_weights(resource1, resource1->id, NULL, NULL, 1, pe_weights_forward|pe_weights_init); + r1_nodes = + rsc_merge_weights(resource1, resource1->id, NULL, NULL, 1, + pe_weights_forward | pe_weights_init); dump_node_scores(LOG_TRACE, NULL, resource1->id, r1_nodes); - r2_nodes = rsc_merge_weights(resource2, resource2->id, NULL, NULL, 1, pe_weights_forward|pe_weights_init); + r2_nodes = + rsc_merge_weights(resource2, resource2->id, NULL, NULL, 1, + pe_weights_forward | pe_weights_init); dump_node_scores(LOG_TRACE, NULL, resource2->id, r2_nodes); - /* Current location score */ reason = "current location"; r1_weight = -INFINITY; r2_weight = -INFINITY; - if(resource1->running_on) { - node = g_list_nth_data(resource1->running_on, 0); - node = g_hash_table_lookup(r1_nodes, node->details->id); - r1_weight = node->weight; - } - if(resource2->running_on) { - node = g_list_nth_data(resource2->running_on, 0); - node = g_hash_table_lookup(r2_nodes, node->details->id); - r2_weight = node->weight; - } - - if(r1_weight > r2_weight) { - rc = -1; goto done; + if (resource1->running_on) { + node = g_list_nth_data(resource1->running_on, 0); + node = g_hash_table_lookup(r1_nodes, node->details->id); + r1_weight = node->weight; } - - if(r1_weight < r2_weight) { - rc = 1; goto done; + if (resource2->running_on) { + node = g_list_nth_data(resource2->running_on, 0); + node = g_hash_table_lookup(r2_nodes, node->details->id); + r2_weight = node->weight; } - - reason = "score"; - for(gIter = nodes; gIter != NULL; gIter = gIter->next) { - node_t *r1_node = NULL; - node_t *r2_node = NULL; - - node = (node_t*)gIter->data; - - r1_weight = -INFINITY; - if(r1_nodes) { - r1_node = g_hash_table_lookup(r1_nodes, node->details->id); - } - if (r1_node) { - r1_weight = r1_node->weight; - } - r2_weight = -INFINITY; - if(r2_nodes) { - r2_node = g_hash_table_lookup(r2_nodes, node->details->id); - } - if (r2_node) { - r2_weight = r2_node->weight; - } + if (r1_weight > r2_weight) { + rc = -1; + goto done; + } - if(r1_weight > r2_weight) { - rc = -1; goto done; - } + if (r1_weight < r2_weight) { + rc = 1; + goto done; + } - if(r1_weight < r2_weight) { - rc = 1; goto done; - } + reason = "score"; + for (gIter = nodes; gIter != NULL; gIter = gIter->next) { + node_t *r1_node = NULL; + node_t *r2_node = NULL; + + node = (node_t *) gIter->data; + + r1_weight = -INFINITY; + if (r1_nodes) { + r1_node = g_hash_table_lookup(r1_nodes, node->details->id); + } + if (r1_node) { + r1_weight = r1_node->weight; + } + + r2_weight = -INFINITY; + if (r2_nodes) { + r2_node = g_hash_table_lookup(r2_nodes, node->details->id); + } + if (r2_node) { + r2_weight = r2_node->weight; + } + + if (r1_weight > r2_weight) { + rc = -1; + goto done; + } + + if (r1_weight < r2_weight) { + rc = 1; + goto done; + } } done: - if(r1_nodes) { - g_hash_table_destroy(r1_nodes); + if (r1_nodes) { + g_hash_table_destroy(r1_nodes); } - if(r2_nodes) { - g_hash_table_destroy(r2_nodes); + if (r2_nodes) { + g_hash_table_destroy(r2_nodes); } do_crm_log_unlikely(level, "%s (%d) %c %s (%d) on %s: %s", - resource1->id, r1_weight, rc<0?'>':rc>0?'<':'=', - resource2->id, r2_weight, node?node->details->id:"n/a", reason); + resource1->id, r1_weight, rc < 0 ? '>' : rc > 0 ? '<' : '=', + resource2->id, r2_weight, node ? node->details->id : "n/a", reason); return rc; } gboolean -stage5(pe_working_set_t *data_set) +stage5(pe_working_set_t * data_set) { GListPtr gIter = NULL; if (safe_str_neq(data_set->placement_strategy, "default")) { - GListPtr nodes = g_list_copy(data_set->nodes); + GListPtr nodes = g_list_copy(data_set->nodes); - nodes = g_list_sort_with_data(nodes, sort_node_weight, NULL); + nodes = g_list_sort_with_data(nodes, sort_node_weight, NULL); - data_set->resources = g_list_sort_with_data( - data_set->resources, sort_rsc_process_order, nodes); + data_set->resources = + g_list_sort_with_data(data_set->resources, sort_rsc_process_order, nodes); - g_list_free(nodes); + g_list_free(nodes); } gIter = data_set->nodes; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - dump_node_capacity(show_utilization?0:utilization_log_level, "Original", node); + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + dump_node_capacity(show_utilization ? 0 : utilization_log_level, "Original", node); } crm_trace("Allocating services"); /* Take (next) highest resource, assign it and create its actions */ gIter = data_set->resources; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; - crm_trace("Allocating: %s", rsc->id); - rsc->cmds->allocate(rsc, NULL, data_set); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; + + crm_trace("Allocating: %s", rsc->id); + rsc->cmds->allocate(rsc, NULL, data_set); } gIter = data_set->nodes; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - dump_node_capacity(show_utilization?0:utilization_log_level, "Remaining", node); - } - - if(is_set(data_set->flags, pe_flag_startup_probes)) { - crm_trace("Calculating needed probes"); - /* This code probably needs optimization - * ptest -x with 100 nodes, 100 clones and clone-max=100: - - With probes: - - ptest[14781]: 2010/09/27_17:56:46 notice: TRACE: do_calculations: pengine.c:258 Calculate cluster status - ptest[14781]: 2010/09/27_17:56:46 notice: TRACE: do_calculations: pengine.c:278 Applying placement constraints - ptest[14781]: 2010/09/27_17:56:47 notice: TRACE: do_calculations: pengine.c:285 Create internal constraints - ptest[14781]: 2010/09/27_17:56:47 notice: TRACE: do_calculations: pengine.c:292 Check actions - ptest[14781]: 2010/09/27_17:56:48 notice: TRACE: do_calculations: pengine.c:299 Allocate resources - ptest[14781]: 2010/09/27_17:56:48 notice: TRACE: stage5: allocate.c:881 Allocating services - ptest[14781]: 2010/09/27_17:56:49 notice: TRACE: stage5: allocate.c:894 Calculating needed probes - ptest[14781]: 2010/09/27_17:56:51 notice: TRACE: stage5: allocate.c:899 Creating actions - ptest[14781]: 2010/09/27_17:56:52 notice: TRACE: stage5: allocate.c:905 Creating done - ptest[14781]: 2010/09/27_17:56:52 notice: TRACE: do_calculations: pengine.c:306 Processing fencing and shutdown cases - ptest[14781]: 2010/09/27_17:56:52 notice: TRACE: do_calculations: pengine.c:313 Applying ordering constraints - 36s - ptest[14781]: 2010/09/27_17:57:28 notice: TRACE: do_calculations: pengine.c:320 Create transition graph - - Without probes: - - ptest[14637]: 2010/09/27_17:56:21 notice: TRACE: do_calculations: pengine.c:258 Calculate cluster status - ptest[14637]: 2010/09/27_17:56:22 notice: TRACE: do_calculations: pengine.c:278 Applying placement constraints - ptest[14637]: 2010/09/27_17:56:22 notice: TRACE: do_calculations: pengine.c:285 Create internal constraints - ptest[14637]: 2010/09/27_17:56:22 notice: TRACE: do_calculations: pengine.c:292 Check actions - ptest[14637]: 2010/09/27_17:56:23 notice: TRACE: do_calculations: pengine.c:299 Allocate resources - ptest[14637]: 2010/09/27_17:56:23 notice: TRACE: stage5: allocate.c:881 Allocating services - ptest[14637]: 2010/09/27_17:56:24 notice: TRACE: stage5: allocate.c:899 Creating actions - ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: stage5: allocate.c:905 Creating done - ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: do_calculations: pengine.c:306 Processing fencing and shutdown cases - ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: do_calculations: pengine.c:313 Applying ordering constraints - ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: do_calculations: pengine.c:320 Create transition graph - */ - - probe_resources(data_set); - } - + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + dump_node_capacity(show_utilization ? 0 : utilization_log_level, "Remaining", node); + } + + if (is_set(data_set->flags, pe_flag_startup_probes)) { + crm_trace("Calculating needed probes"); + /* This code probably needs optimization + * ptest -x with 100 nodes, 100 clones and clone-max=100: + + With probes: + + ptest[14781]: 2010/09/27_17:56:46 notice: TRACE: do_calculations: pengine.c:258 Calculate cluster status + ptest[14781]: 2010/09/27_17:56:46 notice: TRACE: do_calculations: pengine.c:278 Applying placement constraints + ptest[14781]: 2010/09/27_17:56:47 notice: TRACE: do_calculations: pengine.c:285 Create internal constraints + ptest[14781]: 2010/09/27_17:56:47 notice: TRACE: do_calculations: pengine.c:292 Check actions + ptest[14781]: 2010/09/27_17:56:48 notice: TRACE: do_calculations: pengine.c:299 Allocate resources + ptest[14781]: 2010/09/27_17:56:48 notice: TRACE: stage5: allocate.c:881 Allocating services + ptest[14781]: 2010/09/27_17:56:49 notice: TRACE: stage5: allocate.c:894 Calculating needed probes + ptest[14781]: 2010/09/27_17:56:51 notice: TRACE: stage5: allocate.c:899 Creating actions + ptest[14781]: 2010/09/27_17:56:52 notice: TRACE: stage5: allocate.c:905 Creating done + ptest[14781]: 2010/09/27_17:56:52 notice: TRACE: do_calculations: pengine.c:306 Processing fencing and shutdown cases + ptest[14781]: 2010/09/27_17:56:52 notice: TRACE: do_calculations: pengine.c:313 Applying ordering constraints + 36s + ptest[14781]: 2010/09/27_17:57:28 notice: TRACE: do_calculations: pengine.c:320 Create transition graph + + Without probes: + + ptest[14637]: 2010/09/27_17:56:21 notice: TRACE: do_calculations: pengine.c:258 Calculate cluster status + ptest[14637]: 2010/09/27_17:56:22 notice: TRACE: do_calculations: pengine.c:278 Applying placement constraints + ptest[14637]: 2010/09/27_17:56:22 notice: TRACE: do_calculations: pengine.c:285 Create internal constraints + ptest[14637]: 2010/09/27_17:56:22 notice: TRACE: do_calculations: pengine.c:292 Check actions + ptest[14637]: 2010/09/27_17:56:23 notice: TRACE: do_calculations: pengine.c:299 Allocate resources + ptest[14637]: 2010/09/27_17:56:23 notice: TRACE: stage5: allocate.c:881 Allocating services + ptest[14637]: 2010/09/27_17:56:24 notice: TRACE: stage5: allocate.c:899 Creating actions + ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: stage5: allocate.c:905 Creating done + ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: do_calculations: pengine.c:306 Processing fencing and shutdown cases + ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: do_calculations: pengine.c:313 Applying ordering constraints + ptest[14637]: 2010/09/27_17:56:25 notice: TRACE: do_calculations: pengine.c:320 Create transition graph + */ + + probe_resources(data_set); + } + crm_trace("Creating actions"); gIter = data_set->resources; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; - rsc->cmds->create_actions(rsc, data_set); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; + + rsc->cmds->create_actions(rsc, data_set); } crm_trace("Creating done"); return TRUE; } -static gboolean is_managed(const resource_t *rsc) +static gboolean +is_managed(const resource_t * rsc) { GListPtr gIter = rsc->children; - if(is_set(rsc->flags, pe_rsc_managed)) { - return TRUE; + + if (is_set(rsc->flags, pe_rsc_managed)) { + return TRUE; } - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - if(is_managed(child_rsc)) { - return TRUE; - } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + if (is_managed(child_rsc)) { + return TRUE; + } } - + return FALSE; } -static gboolean any_managed_resouces(pe_working_set_t *data_set) +static gboolean +any_managed_resouces(pe_working_set_t * data_set) { - + GListPtr gIter = data_set->resources; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; - if(is_managed(rsc)) { - return TRUE; - } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; + + if (is_managed(rsc)) { + return TRUE; + } } return FALSE; } /* * Create dependancies for stonith and shutdown operations */ gboolean -stage6(pe_working_set_t *data_set) +stage6(pe_working_set_t * data_set) { action_t *dc_down = NULL; action_t *dc_fence = 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; GListPtr gIter = data_set->nodes; - + 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_notice("Delaying fencing operations until there are resources to manage"); - need_stonith = FALSE; - } - - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - - 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_runnable_left); - order_actions(stonith_op, all_stopped, pe_order_implies_then); - - clear_bit_inplace(ready->flags, pe_action_optional); - - if(node->details->is_dc) { - dc_down = stonith_op; - dc_fence = stonith_op; - - } else { - if(last_stonith) { - order_actions(last_stonith, stonith_op, pe_order_optional); - } - last_stonith = stonith_op; - } - - } else if(node->details->online && node->details->shutdown) { - action_t *down_op = NULL; - crm_notice("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); - - gIter = shutdown_matches; - for(; gIter != NULL; gIter = gIter->next) { - action_t *node_stop = (action_t*)gIter->data; - - 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_optional); - } - - if(last_stonith && dc_down != last_stonith) { - order_actions(last_stonith, dc_down, pe_order_optional); - } - g_list_free(shutdown_matches); - } - - if(last_stonith) { - order_actions(last_stonith, done, pe_order_implies_then); - - } else if(dc_fence) { - order_actions(dc_down, done, pe_order_implies_then); + 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_notice("Delaying fencing operations until there are resources to manage"); + need_stonith = FALSE; + } + + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + 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_runnable_left); + order_actions(stonith_op, all_stopped, pe_order_implies_then); + + clear_bit_inplace(ready->flags, pe_action_optional); + + if (node->details->is_dc) { + dc_down = stonith_op; + dc_fence = stonith_op; + + } else { + if (last_stonith) { + order_actions(last_stonith, stonith_op, pe_order_optional); + } + last_stonith = stonith_op; + } + + } else if (node->details->online && node->details->shutdown) { + action_t *down_op = NULL; + + crm_notice("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); + + gIter = shutdown_matches; + for (; gIter != NULL; gIter = gIter->next) { + action_t *node_stop = (action_t *) gIter->data; + + 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_optional); + } + + if (last_stonith && dc_down != last_stonith) { + order_actions(last_stonith, dc_down, pe_order_optional); + } + g_list_free(shutdown_matches); + } + + if (last_stonith) { + order_actions(last_stonith, done, pe_order_implies_then); + + } else if (dc_fence) { + order_actions(dc_down, done, pe_order_implies_then); } 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 * */ -static GListPtr find_actions_by_task(GListPtr actions, resource_t *rsc, const char *original_key) +static GListPtr +find_actions_by_task(GListPtr actions, resource_t * rsc, const char *original_key) { GListPtr list = NULL; list = find_actions(actions, original_key, NULL); - if(list == NULL) { - /* we're potentially searching a child of the original resource */ - char *key = NULL; - char *tmp = NULL; - char *task = NULL; - int interval = 0; - if(parse_op_key(original_key, &tmp, &task, &interval)) { - key = generate_op_key(rsc->id, task, interval); - /* crm_err("looking up %s instead of %s", key, original_key); */ - /* slist_iter(action, action_t, actions, lpc, */ - /* crm_err(" - %s", action->uuid)); */ - list = find_actions(actions, key, NULL); - - } else { - crm_err("search key: %s", original_key); - } - - crm_free(key); - crm_free(tmp); - crm_free(task); - } - + if (list == NULL) { + /* we're potentially searching a child of the original resource */ + char *key = NULL; + char *tmp = NULL; + char *task = NULL; + int interval = 0; + + if (parse_op_key(original_key, &tmp, &task, &interval)) { + key = generate_op_key(rsc->id, task, interval); + /* crm_err("looking up %s instead of %s", key, original_key); */ + /* slist_iter(action, action_t, actions, lpc, */ + /* crm_err(" - %s", action->uuid)); */ + list = find_actions(actions, key, NULL); + + } else { + crm_err("search key: %s", original_key); + } + + crm_free(key); + crm_free(tmp); + crm_free(task); + } + return list; } -static void rsc_order_then( - action_t *lh_action, resource_t *rsc, order_constraint_t *order) +static void +rsc_order_then(action_t * lh_action, resource_t * rsc, order_constraint_t * order) { GListPtr gIter = NULL; GListPtr rh_actions = NULL; action_t *rh_action = NULL; enum pe_ordering type = order->type; CRM_CHECK(rsc != NULL, return); CRM_CHECK(order != NULL, return); rh_action = order->rh_action; crm_debug_3("Processing RH of ordering constraint %d", order->id); - if(rh_action != NULL) { - rh_actions = g_list_prepend(NULL, rh_action); + if (rh_action != NULL) { + rh_actions = g_list_prepend(NULL, rh_action); - } else if(rsc != NULL) { - rh_actions = find_actions_by_task( - rsc->actions, rsc, order->rh_action_task); + } else if (rsc != NULL) { + rh_actions = find_actions_by_task(rsc->actions, rsc, order->rh_action_task); } - if(rh_actions == NULL) { - crm_debug_4("No RH-Side (%s/%s) found for constraint..." - " ignoring", rsc->id,order->rh_action_task); - if(lh_action) { - crm_debug_4("LH-Side was: %s", lh_action->uuid); - } - return; + if (rh_actions == NULL) { + crm_debug_4("No RH-Side (%s/%s) found for constraint..." + " ignoring", rsc->id, order->rh_action_task); + if (lh_action) { + crm_debug_4("LH-Side was: %s", lh_action->uuid); + } + return; } - if(lh_action - && lh_action->rsc == rsc - && is_set(lh_action->flags, pe_action_dangle)) { - crm_trace("Detected dangling operation %s -> %s", - lh_action->uuid, order->rh_action_task); - clear_bit_inplace(type, pe_order_implies_then); + if (lh_action && lh_action->rsc == rsc && is_set(lh_action->flags, pe_action_dangle)) { + crm_trace("Detected dangling operation %s -> %s", lh_action->uuid, order->rh_action_task); + clear_bit_inplace(type, pe_order_implies_then); } - + gIter = rh_actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *rh_action_iter = (action_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + action_t *rh_action_iter = (action_t *) gIter->data; + + if (lh_action) { + order_actions(lh_action, rh_action_iter, type); - if(lh_action) { - order_actions(lh_action, rh_action_iter, type); - - } else if(type & pe_order_implies_then) { - update_action_flags(rh_action_iter, pe_action_runnable|pe_action_clear); - crm_warn("Unrunnable %s 0x%.6x", rh_action_iter->uuid, type); - } else { - crm_warn("neither %s 0x%.6x", rh_action_iter->uuid, type); - } + } else if (type & pe_order_implies_then) { + update_action_flags(rh_action_iter, pe_action_runnable | pe_action_clear); + crm_warn("Unrunnable %s 0x%.6x", rh_action_iter->uuid, type); + } else { + crm_warn("neither %s 0x%.6x", rh_action_iter->uuid, type); + } } g_list_free(rh_actions); } -static void rsc_order_first(resource_t *lh_rsc, order_constraint_t *order, pe_working_set_t *data_set) +static void +rsc_order_first(resource_t * lh_rsc, order_constraint_t * order, pe_working_set_t * data_set) { GListPtr gIter = NULL; GListPtr lh_actions = NULL; action_t *lh_action = order->lh_action; resource_t *rh_rsc = order->rh_rsc; crm_debug_3("Processing LH of ordering constraint %d", order->id); CRM_ASSERT(lh_rsc != NULL); - - if(lh_action != NULL) { - lh_actions = g_list_prepend(NULL, lh_action); - } else if(lh_action == NULL) { - lh_actions = find_actions_by_task( - lh_rsc->actions, lh_rsc, order->lh_action_task); - } + if (lh_action != NULL) { + lh_actions = g_list_prepend(NULL, lh_action); - if(lh_actions == NULL && lh_rsc != rh_rsc) { - char *key = NULL; - char *rsc_id = NULL; - char *op_type = NULL; - int interval = 0; + } else if (lh_action == NULL) { + lh_actions = find_actions_by_task(lh_rsc->actions, lh_rsc, order->lh_action_task); + } - parse_op_key(order->lh_action_task, &rsc_id, &op_type, &interval); - key = generate_op_key(lh_rsc->id, op_type, interval); + if (lh_actions == NULL && lh_rsc != rh_rsc) { + char *key = NULL; + char *rsc_id = NULL; + char *op_type = NULL; + int interval = 0; + parse_op_key(order->lh_action_task, &rsc_id, &op_type, &interval); + key = generate_op_key(lh_rsc->id, op_type, interval); - if(lh_rsc->fns->state(lh_rsc, TRUE) != RSC_ROLE_STOPPED - || safe_str_neq(op_type, RSC_STOP)) { - crm_debug_4("No LH-Side (%s/%s) found for constraint %d with %s - creating", - lh_rsc->id, order->lh_action_task, - order->id, order->rh_action_task); - lh_action = custom_action(lh_rsc, key, op_type, - NULL, TRUE, TRUE, data_set); - lh_actions = g_list_prepend(NULL, lh_action); - } else { - crm_free(key); - crm_debug_4("No LH-Side (%s/%s) found for constraint %d with %s - ignoring", - lh_rsc->id, order->lh_action_task, - order->id, order->rh_action_task); - } + if (lh_rsc->fns->state(lh_rsc, TRUE) != RSC_ROLE_STOPPED || safe_str_neq(op_type, RSC_STOP)) { + crm_debug_4("No LH-Side (%s/%s) found for constraint %d with %s - creating", + lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task); + lh_action = custom_action(lh_rsc, key, op_type, NULL, TRUE, TRUE, data_set); + lh_actions = g_list_prepend(NULL, lh_action); + } else { + crm_free(key); + crm_debug_4("No LH-Side (%s/%s) found for constraint %d with %s - ignoring", + lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task); + } - crm_free(op_type); - crm_free(rsc_id); + crm_free(op_type); + crm_free(rsc_id); } gIter = lh_actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *lh_action_iter = (action_t*)gIter->data; - + for (; gIter != NULL; gIter = gIter->next) { + action_t *lh_action_iter = (action_t *) gIter->data; - if(rh_rsc == NULL && order->rh_action) { - rh_rsc = order->rh_action->rsc; - } - if(rh_rsc) { - rsc_order_then(lh_action_iter, rh_rsc, order); + if (rh_rsc == NULL && order->rh_action) { + rh_rsc = order->rh_action->rsc; + } + if (rh_rsc) { + rsc_order_then(lh_action_iter, rh_rsc, order); - } else if(order->rh_action) { - order_actions(lh_action_iter, order->rh_action, order->type); - } + } else if (order->rh_action) { + order_actions(lh_action_iter, order->rh_action, order->type); + } } g_list_free(lh_actions); } -extern gboolean update_action(action_t *action); +extern gboolean update_action(action_t * action); gboolean -stage7(pe_working_set_t *data_set) +stage7(pe_working_set_t * data_set) { GListPtr gIter = NULL; + crm_debug_4("Applying ordering constraints"); /* Don't ask me why, but apparently they need to be processed in * the order they were created in... go figure * * Also g_list_prepend() has horrendous performance characteristics * So we need to use g_list_prepend() and then reverse the list here */ - data_set->ordering_constraints = g_list_reverse( - data_set->ordering_constraints); - + data_set->ordering_constraints = g_list_reverse(data_set->ordering_constraints); + gIter = data_set->ordering_constraints; - for(; gIter != NULL; gIter = gIter->next) { - order_constraint_t *order = (order_constraint_t*)gIter->data; - 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_order_first(rsc, order, data_set); - continue; - } - - rsc = order->rh_rsc; - if(rsc != NULL) { - crm_debug_4("action-to-rsc_action"); - rsc_order_then(order->lh_action, rsc, order); - - } else { - crm_debug_4("action-to-action"); - order_actions( - order->lh_action, order->rh_action, order->type); - } + for (; gIter != NULL; gIter = gIter->next) { + order_constraint_t *order = (order_constraint_t *) gIter->data; + 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_order_first(rsc, order, data_set); + continue; + } + + rsc = order->rh_rsc; + if (rsc != NULL) { + crm_debug_4("action-to-rsc_action"); + rsc_order_then(order->lh_action, rsc, order); + + } else { + crm_debug_4("action-to-action"); + order_actions(order->lh_action, order->rh_action, order->type); + } } crm_debug_2("Updating %d actions", g_list_length(data_set->actions)); gIter = data_set->actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - update_action(action); + for (; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + update_action(action); } crm_debug_2("Processing migrations"); gIter = data_set->resources; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; - rsc_migrate_reload(rsc, data_set); - LogActions(rsc, data_set); + rsc_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 == 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; } + 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 (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; } + 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) { GListPtr gIter = list; const char *uname = NULL; const char *rsc_id = NULL; const char *last_rsc_id = NULL; - if(rsc_list) { + if (rsc_list) { *rsc_list = NULL; } - - if(list == NULL) { - if(rsc_list) { - *rsc_list = crm_strdup(" "); - } - if(node_list) { - *node_list = crm_strdup(" "); - } - return; - } - - if(node_list) { - *node_list = NULL; - } - - for(; gIter != NULL; gIter = gIter->next) { - notify_entry_t *entry = (notify_entry_t*)gIter->data; - - 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); - } - } - + + if (list == NULL) { + if (rsc_list) { + *rsc_list = crm_strdup(" "); + } + if (node_list) { + *node_list = crm_strdup(" "); + } + return; + } + + if (node_list) { + *node_list = NULL; + } + + for (; gIter != NULL; gIter = gIter->next) { + notify_entry_t *entry = (notify_entry_t *) gIter->data; + + 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) +static void +dup_attr(gpointer key, gpointer value, gpointer user_data) { add_hash_param(user_data, key, 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) +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; + + 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(is_set(op->flags, pe_action_runnable) == FALSE) { - crm_debug_2("Skipping notification for %s: not runnable", op->uuid); - return NULL; + if (node->details->online == FALSE) { + crm_debug_2("Skipping notification for %s: node offline", rsc->id); + return NULL; + } else if (is_set(op->flags, pe_action_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); - + 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, - is_set(op->flags, pe_action_optional), TRUE, data_set); + is_set(op->flags, pe_action_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); + crm_debug_3("Ordering %s before %s (%d->%d)", op->uuid, trigger->uuid, trigger->id, op->id); order_actions(op, trigger, pe_order_optional); order_actions(trigger, confirm, pe_order_optional); return trigger; } static void -pe_post_notify(resource_t *rsc, node_t *node, notify_data_t *n_data, pe_working_set_t *data_set) +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 */ + 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 (notify != NULL) { + notify->priority = INFINITY; } - if(n_data->post_done) { - GListPtr gIter = rsc->actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *mon = (action_t*)gIter->data; - 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; - } + if (n_data->post_done) { + GListPtr gIter = rsc->actions; + + for (; gIter != NULL; gIter = gIter->next) { + action_t *mon = (action_t *) gIter->data; + const char *interval = g_hash_table_lookup(mon->meta, "interval"); - order_actions(n_data->post_done, mon, pe_order_optional); - } + 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_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; + + 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( - crm_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, is_set(start->flags, pe_action_optional), TRUE, data_set); - - update_action_flags(n_data->pre, pe_action_pseudo); - update_action_flags(n_data->pre, pe_action_runnable); - 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, is_set(start->flags, pe_action_optional), TRUE, data_set); - - update_action_flags(n_data->pre_done, pe_action_pseudo); - update_action_flags(n_data->pre_done, pe_action_runnable); - 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, is_set(end->flags, pe_action_optional), TRUE, data_set); - - n_data->post->priority = INFINITY; - update_action_flags(n_data->post, pe_action_pseudo); - if(is_set(end->flags, pe_action_runnable)) { - update_action_flags(n_data->post, pe_action_runnable); - } else { - update_action_flags(n_data->post, pe_action_runnable|pe_action_clear); - } - - 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, is_set(end->flags, pe_action_optional), TRUE, data_set); - - n_data->post_done->priority = INFINITY; - update_action_flags(n_data->post_done, pe_action_pseudo); - if(is_set(end->flags, pe_action_runnable)) { - update_action_flags(n_data->post_done, pe_action_runnable); - } else { - update_action_flags(n_data->post_done, pe_action_runnable|pe_action_clear); - } - - 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_then); - order_actions(n_data->post, n_data->post_done, pe_order_implies_then); - } - - 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); - } + n_data->keys = + g_hash_table_new_full(crm_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, is_set(start->flags, pe_action_optional), + TRUE, data_set); + + update_action_flags(n_data->pre, pe_action_pseudo); + update_action_flags(n_data->pre, pe_action_runnable); + 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, is_set(start->flags, pe_action_optional), + TRUE, data_set); + + update_action_flags(n_data->pre_done, pe_action_pseudo); + update_action_flags(n_data->pre_done, pe_action_runnable); + 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, is_set(end->flags, pe_action_optional), TRUE, + data_set); + + n_data->post->priority = INFINITY; + update_action_flags(n_data->post, pe_action_pseudo); + if (is_set(end->flags, pe_action_runnable)) { + update_action_flags(n_data->post, pe_action_runnable); + } else { + update_action_flags(n_data->post, pe_action_runnable | pe_action_clear); + } + + 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, is_set(end->flags, pe_action_optional), + TRUE, data_set); + + n_data->post_done->priority = INFINITY; + update_action_flags(n_data->post_done, pe_action_pseudo); + if (is_set(end->flags, pe_action_runnable)) { + update_action_flags(n_data->post_done, pe_action_runnable); + } else { + update_action_flags(n_data->post_done, pe_action_runnable | pe_action_clear); + } + + 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_then); + order_actions(n_data->post, n_data->post_done, pe_order_implies_then); + } + + 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) +collect_notification_data(resource_t * rsc, gboolean state, gboolean activity, + notify_data_t * n_data) { - if(rsc->children) { - GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - 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_prepend(n_data->inactive, entry); - break; - case RSC_ROLE_STARTED: - n_data->active = g_list_prepend(n_data->active, entry); - break; - case RSC_ROLE_SLAVE: - n_data->slave = g_list_prepend(n_data->slave, entry); - break; - case RSC_ROLE_MASTER: - n_data->master = g_list_prepend(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; - - GListPtr gIter = rsc->actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *op = (action_t*)gIter->data; - - if(is_set(op->flags, pe_action_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_prepend(n_data->start, entry); - break; - case stop_rsc: - n_data->stop = g_list_prepend(n_data->stop, entry); - break; - case action_promote: - n_data->promote = g_list_prepend(n_data->promote, entry); - break; - case action_demote: - n_data->demote = g_list_prepend(n_data->demote, entry); - break; - default: - crm_free(entry); - break; - } - } - } + if (rsc->children) { + GListPtr gIter = rsc->children; + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + 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_prepend(n_data->inactive, entry); + break; + case RSC_ROLE_STARTED: + n_data->active = g_list_prepend(n_data->active, entry); + break; + case RSC_ROLE_SLAVE: + n_data->slave = g_list_prepend(n_data->slave, entry); + break; + case RSC_ROLE_MASTER: + n_data->master = g_list_prepend(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; + + GListPtr gIter = rsc->actions; + + for (; gIter != NULL; gIter = gIter->next) { + action_t *op = (action_t *) gIter->data; + + if (is_set(op->flags, pe_action_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_prepend(n_data->start, entry); + break; + case stop_rsc: + n_data->stop = g_list_prepend(n_data->stop, entry); + break; + case action_promote: + n_data->promote = g_list_prepend(n_data->promote, entry); + break; + case action_demote: + n_data->demote = g_list_prepend(n_data->demote, entry); + break; + default: + crm_free(entry); + break; + } + } + } } } -gboolean -expand_notification_data(notify_data_t *n_data) +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); + + 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; - } + 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; - } + + 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; - } + + 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; - } + + 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); + + 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); + + 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); + + 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); + + 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) { - update_action_flags(n_data->pre, pe_action_optional|pe_action_clear); - update_action_flags(n_data->pre_done, pe_action_optional|pe_action_clear); + if (required && n_data->pre) { + update_action_flags(n_data->pre, pe_action_optional | pe_action_clear); + update_action_flags(n_data->pre_done, pe_action_optional | pe_action_clear); } - - if(required && n_data->post) { - update_action_flags(n_data->post, pe_action_optional|pe_action_clear); - update_action_flags(n_data->post_done, pe_action_optional|pe_action_clear); + + if (required && n_data->post) { + update_action_flags(n_data->post, pe_action_optional | pe_action_clear); + update_action_flags(n_data->post_done, pe_action_optional | pe_action_clear); } return required; } void -create_notifications(resource_t *rsc, notify_data_t *n_data, pe_working_set_t *data_set) +create_notifications(resource_t * rsc, notify_data_t * n_data, pe_working_set_t * data_set) { GListPtr gIter = NULL; action_t *stop = NULL; action_t *start = NULL; enum action_tasks task = text2task(n_data->action); - - if(rsc->children) { - gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - create_notifications(child, n_data, data_set); - } - return; + + if (rsc->children) { + gIter = rsc->children; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + create_notifications(child, n_data, data_set); + } + return; } /* Copy notification details into standard ops */ gIter = rsc->actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *op = (action_t*)gIter->data; - - if(is_set(op->flags, pe_action_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; - } - } - } - + for (; gIter != NULL; gIter = gIter->next) { + action_t *op = (action_t *) gIter->data; + + if (is_set(op->flags, pe_action_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)); - + 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) { - gIter = rsc->running_on; - for(; gIter != NULL; gIter = gIter->next) { - node_t *current_node = (node_t*)gIter->data; - - pe_notify(rsc, current_node, n_data->pre, n_data->pre_done, n_data, data_set); - if(task == action_demote || stop == NULL || is_set(stop->flags, pe_action_optional)) { - pe_post_notify(rsc, current_node, n_data, data_set); - } - } - } - } - + if (rsc->role != RSC_ROLE_STOPPED) { + if (task == stop_rsc || task == action_demote) { + gIter = rsc->running_on; + for (; gIter != NULL; gIter = gIter->next) { + node_t *current_node = (node_t *) gIter->data; + + pe_notify(rsc, current_node, n_data->pre, n_data->pre_done, n_data, data_set); + if (task == action_demote || stop == NULL + || is_set(stop->flags, pe_action_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 || is_set(start->flags, pe_action_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); - } - } + 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 || is_set(start->flags, pe_action_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) +void +free_notification_data(notify_data_t * n_data) { - if(n_data == NULL) { - return; + if (n_data == NULL) { + return; } - + slist_basic_destroy(n_data->stop); slist_basic_destroy(n_data->start); slist_basic_destroy(n_data->demote); slist_basic_destroy(n_data->promote); slist_basic_destroy(n_data->master); slist_basic_destroy(n_data->slave); slist_basic_destroy(n_data->active); slist_basic_destroy(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) +stage8(pe_working_set_t * data_set) { GListPtr gIter = NULL; 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"); + 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"); + 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); } ); */ - + gIter = data_set->resources; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; - crm_debug_4("processing actions for rsc=%s", rsc->id); - rsc->cmds->expand(rsc, data_set); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; + + 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"); + + 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"); gIter = data_set->actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - graph_element_from_action(action, data_set); + for (; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + 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) +cleanup_alloc_calculations(pe_working_set_t * data_set) { - if(data_set == NULL) { - return; + if (data_set == NULL) { + return; } crm_debug_3("deleting %d order cons: %p", - g_list_length(data_set->ordering_constraints), data_set->ordering_constraints); + g_list_length(data_set->ordering_constraints), data_set->ordering_constraints); pe_free_ordering(data_set->ordering_constraints); data_set->ordering_constraints = NULL; - + crm_debug_3("deleting %d node cons: %p", - g_list_length(data_set->placement_constraints), data_set->placement_constraints); + g_list_length(data_set->placement_constraints), data_set->placement_constraints); pe_free_rsc_to_node(data_set->placement_constraints); data_set->placement_constraints = NULL; crm_debug_3("deleting %d inter-resource cons: %p", - g_list_length(data_set->colocation_constraints), data_set->colocation_constraints); + g_list_length(data_set->colocation_constraints), data_set->colocation_constraints); slist_basic_destroy(data_set->colocation_constraints); data_set->colocation_constraints = NULL; crm_debug_3("deleting %d ticket deps: %p", - g_list_length(data_set->ticket_constraints), data_set->ticket_constraints); + g_list_length(data_set->ticket_constraints), data_set->ticket_constraints); slist_basic_destroy(data_set->ticket_constraints); data_set->ticket_constraints = NULL; - + cleanup_calculations(data_set); } diff --git a/pengine/clone.c b/pengine/clone.c index a459d2f819..85981e6d35 100644 --- a/pengine/clone.c +++ b/pengine/clone.c @@ -1,1502 +1,1570 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #define VARIANT_CLONE 1 #include gint sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set); -static void append_parent_colocation(resource_t *rsc, resource_t *child, gboolean all); +static void append_parent_colocation(resource_t * rsc, resource_t * child, gboolean all); static node_t * -parent_node_instance(const resource_t *rsc, node_t *node) +parent_node_instance(const resource_t * rsc, node_t * node) { node_t *ret = NULL; - if(node != NULL) { - ret = pe_hash_table_lookup(rsc->parent->allowed_nodes, node->details->id); + + if (node != NULL) { + ret = pe_hash_table_lookup(rsc->parent->allowed_nodes, node->details->id); } return ret; } -static gboolean did_fail(const resource_t *rsc) +static gboolean +did_fail(const resource_t * rsc) { GListPtr gIter = rsc->children; - if(is_set(rsc->flags, pe_rsc_failed)) { - return TRUE; + if (is_set(rsc->flags, pe_rsc_failed)) { + return TRUE; } - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - if(did_fail(child_rsc)) { - return TRUE; - } + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + if (did_fail(child_rsc)) { + return TRUE; + } } return FALSE; } - -gint sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set) +gint +sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set) { int rc = 0; int level = LOG_DEBUG_3; node_t *node1 = NULL; node_t *node2 = NULL; gboolean can1 = TRUE; gboolean can2 = TRUE; - - const resource_t *resource1 = (const resource_t*)a; - const resource_t *resource2 = (const resource_t*)b; + + const resource_t *resource1 = (const resource_t *)a; + const resource_t *resource2 = (const resource_t *)b; CRM_ASSERT(resource1 != NULL); CRM_ASSERT(resource2 != NULL); /* allocation order: * - active instances * - instances running on nodes with the least copies * - active instances on nodes that cant support them or are to be fenced * - failed instances * - inactive instances - */ - - if(resource1->running_on && resource2->running_on) { - if(g_list_length(resource1->running_on) < g_list_length(resource2->running_on)) { - do_crm_log_unlikely(level, "%s < %s: running_on", resource1->id, resource2->id); - return -1; - - } else if(g_list_length(resource1->running_on) > g_list_length(resource2->running_on)) { - do_crm_log_unlikely(level, "%s > %s: running_on", resource1->id, resource2->id); - return 1; - } - } - - if(resource1->running_on) { - node1 = resource1->running_on->data; - } - if(resource2->running_on) { - node2 = resource2->running_on->data; - } - - if(node1) { - node_t *match = pe_hash_table_lookup(resource1->allowed_nodes, node1->details->id); - if(match == NULL || match->weight < 0) { - do_crm_log_unlikely(level, "%s: current location is unavailable", resource1->id); - node1 = NULL; - can1 = FALSE; - } - } - - if(node2) { - node_t *match = pe_hash_table_lookup(resource2->allowed_nodes, node2->details->id); - if(match == NULL || match->weight < 0) { - do_crm_log_unlikely(level, "%s: current location is unavailable", resource2->id); - node2 = NULL; - can2 = FALSE; - } - } - - if(can1 != can2) { - if(can1) { - do_crm_log_unlikely(level, "%s < %s: availability of current location", resource1->id, resource2->id); - return -1; - } - do_crm_log_unlikely(level, "%s > %s: availability of current location", resource1->id, resource2->id); - return 1; - } - - if(resource1->priority < resource2->priority) { - do_crm_log_unlikely(level, "%s < %s: priority", resource1->id, resource2->id); - return 1; - - } else if(resource1->priority > resource2->priority) { - do_crm_log_unlikely(level, "%s > %s: priority", resource1->id, resource2->id); - return -1; - } - - if(node1 == NULL && node2 == NULL) { - do_crm_log_unlikely(level, "%s == %s: not active", - resource1->id, resource2->id); - return 0; - } - - if(node1 != node2) { - if(node1 == NULL) { - do_crm_log_unlikely(level, "%s > %s: active", resource1->id, resource2->id); - return 1; - } else if(node2 == NULL) { - do_crm_log_unlikely(level, "%s < %s: active", resource1->id, resource2->id); - return -1; - } - } - + */ + + if (resource1->running_on && resource2->running_on) { + if (g_list_length(resource1->running_on) < g_list_length(resource2->running_on)) { + do_crm_log_unlikely(level, "%s < %s: running_on", resource1->id, resource2->id); + return -1; + + } else if (g_list_length(resource1->running_on) > g_list_length(resource2->running_on)) { + do_crm_log_unlikely(level, "%s > %s: running_on", resource1->id, resource2->id); + return 1; + } + } + + if (resource1->running_on) { + node1 = resource1->running_on->data; + } + if (resource2->running_on) { + node2 = resource2->running_on->data; + } + + if (node1) { + node_t *match = pe_hash_table_lookup(resource1->allowed_nodes, node1->details->id); + + if (match == NULL || match->weight < 0) { + do_crm_log_unlikely(level, "%s: current location is unavailable", resource1->id); + node1 = NULL; + can1 = FALSE; + } + } + + if (node2) { + node_t *match = pe_hash_table_lookup(resource2->allowed_nodes, node2->details->id); + + if (match == NULL || match->weight < 0) { + do_crm_log_unlikely(level, "%s: current location is unavailable", resource2->id); + node2 = NULL; + can2 = FALSE; + } + } + + if (can1 != can2) { + if (can1) { + do_crm_log_unlikely(level, "%s < %s: availability of current location", resource1->id, + resource2->id); + return -1; + } + do_crm_log_unlikely(level, "%s > %s: availability of current location", resource1->id, + resource2->id); + return 1; + } + + if (resource1->priority < resource2->priority) { + do_crm_log_unlikely(level, "%s < %s: priority", resource1->id, resource2->id); + return 1; + + } else if (resource1->priority > resource2->priority) { + do_crm_log_unlikely(level, "%s > %s: priority", resource1->id, resource2->id); + return -1; + } + + if (node1 == NULL && node2 == NULL) { + do_crm_log_unlikely(level, "%s == %s: not active", resource1->id, resource2->id); + return 0; + } + + if (node1 != node2) { + if (node1 == NULL) { + do_crm_log_unlikely(level, "%s > %s: active", resource1->id, resource2->id); + return 1; + } else if (node2 == NULL) { + do_crm_log_unlikely(level, "%s < %s: active", resource1->id, resource2->id); + return -1; + } + } + can1 = can_run_resources(node1); can2 = can_run_resources(node2); - if(can1 != can2) { - if(can1) { - do_crm_log_unlikely(level, "%s < %s: can", resource1->id, resource2->id); - return -1; - } - do_crm_log_unlikely(level, "%s > %s: can", resource1->id, resource2->id); - return 1; + if (can1 != can2) { + if (can1) { + do_crm_log_unlikely(level, "%s < %s: can", resource1->id, resource2->id); + return -1; + } + do_crm_log_unlikely(level, "%s > %s: can", resource1->id, resource2->id); + return 1; } node1 = parent_node_instance(resource1, node1); node2 = parent_node_instance(resource2, node2); - if(node1 != NULL && node2 == NULL) { - do_crm_log_unlikely(level, "%s < %s: not allowed", resource1->id, resource2->id); - return -1; - } else if(node1 == NULL && node2 != NULL) { - do_crm_log_unlikely(level, "%s > %s: not allowed", resource1->id, resource2->id); - return 1; + if (node1 != NULL && node2 == NULL) { + do_crm_log_unlikely(level, "%s < %s: not allowed", resource1->id, resource2->id); + return -1; + } else if (node1 == NULL && node2 != NULL) { + do_crm_log_unlikely(level, "%s > %s: not allowed", resource1->id, resource2->id); + return 1; } - - if(node1 == NULL || node2 == NULL) { - do_crm_log_unlikely(level, "%s == %s: not allowed", resource1->id, resource2->id); - return 0; + + if (node1 == NULL || node2 == NULL) { + do_crm_log_unlikely(level, "%s == %s: not allowed", resource1->id, resource2->id); + return 0; } - if(node1->count < node2->count) { - do_crm_log_unlikely(level, "%s < %s: count", resource1->id, resource2->id); - return -1; + if (node1->count < node2->count) { + do_crm_log_unlikely(level, "%s < %s: count", resource1->id, resource2->id); + return -1; - } else if(node1->count > node2->count) { - do_crm_log_unlikely(level, "%s > %s: count", resource1->id, resource2->id); - return 1; + } else if (node1->count > node2->count) { + do_crm_log_unlikely(level, "%s > %s: count", resource1->id, resource2->id); + return 1; } can1 = did_fail(resource1); can2 = did_fail(resource2); - if(can1 != can2) { - if(can1) { - do_crm_log_unlikely(level, "%s > %s: failed", resource1->id, resource2->id); - return 1; - } - do_crm_log_unlikely(level, "%s < %s: failed", resource1->id, resource2->id); - return -1; - } - - if(node1 && node2) { - int lpc = 0; - int max = 0; - node_t *n = NULL; - GListPtr gIter = NULL; - GListPtr list1 = NULL; - GListPtr list2 = NULL; - GHashTable *hash1 = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str); - GHashTable *hash2 = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str); - - n = node_copy(resource1->running_on->data); - g_hash_table_insert(hash1, (gpointer)n->details->id, n); - - n = node_copy(resource2->running_on->data); - g_hash_table_insert(hash2, (gpointer)n->details->id, n); - - for(gIter = resource1->parent->rsc_cons; gIter; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - - do_crm_log_unlikely(level+1, "Applying %s to %s", constraint->id, resource1->id); - - hash1 = native_merge_weights( - constraint->rsc_rh, resource1->id, hash1, - constraint->node_attribute, - constraint->score/INFINITY, FALSE, FALSE); - } - - for(gIter = resource1->parent->rsc_cons_lhs; gIter; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - - do_crm_log_unlikely(level+1, "Applying %s to %s", constraint->id, resource1->id); - - hash1 = native_merge_weights( - constraint->rsc_lh, resource1->id, hash1, - constraint->node_attribute, - constraint->score/INFINITY, FALSE, TRUE); - } - - for(gIter = resource2->parent->rsc_cons; gIter; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - - do_crm_log_unlikely(level+1, "Applying %s to %s", constraint->id, resource2->id); - - hash2 = native_merge_weights( - constraint->rsc_rh, resource2->id, hash2, - constraint->node_attribute, - constraint->score/INFINITY, FALSE, FALSE); - } - - for(gIter = resource2->parent->rsc_cons_lhs; gIter; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - - do_crm_log_unlikely(level+1, "Applying %s to %s", constraint->id, resource2->id); - - hash2 = native_merge_weights( - constraint->rsc_lh, resource2->id, hash2, - constraint->node_attribute, - constraint->score/INFINITY, FALSE, TRUE); - } - - /* Current location score */ - node1 = g_list_nth_data(resource1->running_on, 0); - node1 = g_hash_table_lookup(hash1, node1->details->id); - - node2 = g_list_nth_data(resource2->running_on, 0); - node2 = g_hash_table_lookup(hash2, node2->details->id); - - if(node1->weight < node2->weight) { - if(node1->weight < 0) { - do_crm_log_unlikely(level, "%s > %s: current score", resource1->id, resource2->id); - rc=-1; goto out; - - } else { - do_crm_log_unlikely(level, "%s < %s: current score", resource1->id, resource2->id); - rc=1; goto out; - } - - } else if(node1->weight > node2->weight) { - do_crm_log_unlikely(level, "%s > %s: current score", resource1->id, resource2->id); - rc=-1; goto out; - } - - /* All location scores */ - list1 = g_hash_table_get_values(hash1); - list2 = g_hash_table_get_values(hash2); - - list1 = g_list_sort_with_data(list1, sort_node_weight, g_list_nth_data(resource1->running_on, 0)); - list2 = g_list_sort_with_data(list2, sort_node_weight, g_list_nth_data(resource2->running_on, 0)); - max = g_list_length(list1); - if(max < g_list_length(list2)) { - max = g_list_length(list2); - } - - for(;lpc < max; lpc++) { - node1 = g_list_nth_data(list1, lpc); - node2 = g_list_nth_data(list2, lpc); - if(node1 == NULL) { - do_crm_log_unlikely(level, "%s < %s: colocated score NULL", resource1->id, resource2->id); - rc = 1; - break; - - } else if(node2 == NULL) { - do_crm_log_unlikely(level, "%s > %s: colocated score NULL", resource1->id, resource2->id); - rc = -1; - break; - } - - if(node1->weight < node2->weight) { - do_crm_log_unlikely(level, "%s < %s: colocated score", resource1->id, resource2->id); - rc = 1; - break; - - } else if(node1->weight > node2->weight) { - do_crm_log_unlikely(level, "%s > %s: colocated score", resource1->id, resource2->id); - rc = -1; - break; - } - } - - /* Order by reverse uname - same as sort_node_weight() does? */ - out: - g_hash_table_destroy(hash1); /* Free mem */ - g_hash_table_destroy(hash2); /* Free mem */ - g_list_free(list1); - g_list_free(list2); - - if(rc != 0) { - return rc; - } - } - + if (can1 != can2) { + if (can1) { + do_crm_log_unlikely(level, "%s > %s: failed", resource1->id, resource2->id); + return 1; + } + do_crm_log_unlikely(level, "%s < %s: failed", resource1->id, resource2->id); + return -1; + } + + if (node1 && node2) { + int lpc = 0; + int max = 0; + node_t *n = NULL; + GListPtr gIter = NULL; + GListPtr list1 = NULL; + GListPtr list2 = NULL; + GHashTable *hash1 = + g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str); + GHashTable *hash2 = + g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, g_hash_destroy_str); + + n = node_copy(resource1->running_on->data); + g_hash_table_insert(hash1, (gpointer) n->details->id, n); + + n = node_copy(resource2->running_on->data); + g_hash_table_insert(hash2, (gpointer) n->details->id, n); + + for (gIter = resource1->parent->rsc_cons; gIter; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + do_crm_log_unlikely(level + 1, "Applying %s to %s", constraint->id, resource1->id); + + hash1 = native_merge_weights(constraint->rsc_rh, resource1->id, hash1, + constraint->node_attribute, + constraint->score / INFINITY, FALSE, FALSE); + } + + for (gIter = resource1->parent->rsc_cons_lhs; gIter; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + do_crm_log_unlikely(level + 1, "Applying %s to %s", constraint->id, resource1->id); + + hash1 = native_merge_weights(constraint->rsc_lh, resource1->id, hash1, + constraint->node_attribute, + constraint->score / INFINITY, FALSE, TRUE); + } + + for (gIter = resource2->parent->rsc_cons; gIter; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + do_crm_log_unlikely(level + 1, "Applying %s to %s", constraint->id, resource2->id); + + hash2 = native_merge_weights(constraint->rsc_rh, resource2->id, hash2, + constraint->node_attribute, + constraint->score / INFINITY, FALSE, FALSE); + } + + for (gIter = resource2->parent->rsc_cons_lhs; gIter; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + do_crm_log_unlikely(level + 1, "Applying %s to %s", constraint->id, resource2->id); + + hash2 = native_merge_weights(constraint->rsc_lh, resource2->id, hash2, + constraint->node_attribute, + constraint->score / INFINITY, FALSE, TRUE); + } + + /* Current location score */ + node1 = g_list_nth_data(resource1->running_on, 0); + node1 = g_hash_table_lookup(hash1, node1->details->id); + + node2 = g_list_nth_data(resource2->running_on, 0); + node2 = g_hash_table_lookup(hash2, node2->details->id); + + if (node1->weight < node2->weight) { + if (node1->weight < 0) { + do_crm_log_unlikely(level, "%s > %s: current score", resource1->id, resource2->id); + rc = -1; + goto out; + + } else { + do_crm_log_unlikely(level, "%s < %s: current score", resource1->id, resource2->id); + rc = 1; + goto out; + } + + } else if (node1->weight > node2->weight) { + do_crm_log_unlikely(level, "%s > %s: current score", resource1->id, resource2->id); + rc = -1; + goto out; + } + + /* All location scores */ + list1 = g_hash_table_get_values(hash1); + list2 = g_hash_table_get_values(hash2); + + list1 = + g_list_sort_with_data(list1, sort_node_weight, + g_list_nth_data(resource1->running_on, 0)); + list2 = + g_list_sort_with_data(list2, sort_node_weight, + g_list_nth_data(resource2->running_on, 0)); + max = g_list_length(list1); + if (max < g_list_length(list2)) { + max = g_list_length(list2); + } + + for (; lpc < max; lpc++) { + node1 = g_list_nth_data(list1, lpc); + node2 = g_list_nth_data(list2, lpc); + if (node1 == NULL) { + do_crm_log_unlikely(level, "%s < %s: colocated score NULL", resource1->id, + resource2->id); + rc = 1; + break; + + } else if (node2 == NULL) { + do_crm_log_unlikely(level, "%s > %s: colocated score NULL", resource1->id, + resource2->id); + rc = -1; + break; + } + + if (node1->weight < node2->weight) { + do_crm_log_unlikely(level, "%s < %s: colocated score", resource1->id, + resource2->id); + rc = 1; + break; + + } else if (node1->weight > node2->weight) { + do_crm_log_unlikely(level, "%s > %s: colocated score", resource1->id, + resource2->id); + rc = -1; + break; + } + } + + /* Order by reverse uname - same as sort_node_weight() does? */ + out: + g_hash_table_destroy(hash1); /* Free mem */ + g_hash_table_destroy(hash2); /* Free mem */ + g_list_free(list1); + g_list_free(list2); + + if (rc != 0) { + return rc; + } + } + rc = strcmp(resource1->id, resource2->id); - do_crm_log_unlikely(level, "%s %c %s: default", resource1->id, rc<0?'<':'>', resource2->id); + do_crm_log_unlikely(level, "%s %c %s: default", resource1->id, rc < 0 ? '<' : '>', + resource2->id); return rc; } static node_t * -can_run_instance(resource_t *rsc, node_t *node) +can_run_instance(resource_t * rsc, node_t * node) { node_t *local_node = NULL; clone_variant_data_t *clone_data = NULL; - if(can_run_resources(node) == FALSE) { - goto bail; - } else if(is_set(rsc->flags, pe_rsc_orphan)) { - goto bail; + if (can_run_resources(node) == FALSE) { + goto bail; + + } else if (is_set(rsc->flags, pe_rsc_orphan)) { + goto bail; } local_node = parent_node_instance(rsc, node); get_clone_variant_data(clone_data, rsc->parent); - if(local_node == NULL) { - crm_warn("%s cannot run on %s: node not allowed", - rsc->id, node->details->uname); - goto bail; + if (local_node == NULL) { + crm_warn("%s cannot run on %s: node not allowed", rsc->id, node->details->uname); + goto bail; - } else if(local_node->count < clone_data->clone_node_max) { - crm_trace("%s can run on %s: %d", - rsc->id, node->details->uname, local_node->count); - return local_node; + } else if (local_node->count < clone_data->clone_node_max) { + crm_trace("%s can run on %s: %d", rsc->id, node->details->uname, local_node->count); + return local_node; } else { - crm_debug_2("%s cannot run on %s: node full (%d >= %d)", - rsc->id, node->details->uname, local_node->count, clone_data->clone_node_max); + crm_debug_2("%s cannot run on %s: node full (%d >= %d)", + rsc->id, node->details->uname, local_node->count, clone_data->clone_node_max); } bail: - if(node) { - common_update_score(rsc, node->details->id, -INFINITY); + if (node) { + common_update_score(rsc, node->details->id, -INFINITY); } return NULL; } - static node_t * -color_instance(resource_t *rsc, node_t *prefer, gboolean all_coloc, pe_working_set_t *data_set) +color_instance(resource_t * rsc, node_t * prefer, gboolean all_coloc, pe_working_set_t * data_set) { node_t *chosen = NULL; node_t *local_node = NULL; crm_debug_2("Processing %s", rsc->id); - if(is_not_set(rsc->flags, pe_rsc_provisional)) { - return rsc->fns->location(rsc, NULL, FALSE); + if (is_not_set(rsc->flags, pe_rsc_provisional)) { + return rsc->fns->location(rsc, NULL, FALSE); - } else if(is_set(rsc->flags, pe_rsc_allocating)) { - crm_debug("Dependency loop detected involving %s", rsc->id); - return NULL; + } else if (is_set(rsc->flags, pe_rsc_allocating)) { + crm_debug("Dependency loop detected involving %s", rsc->id); + return NULL; } /* Only include positive colocation preferences of dependant resources * if not every node will get a copy of the clone */ append_parent_colocation(rsc->parent, rsc, all_coloc); - if(prefer) { - node_t *local_prefer = g_hash_table_lookup(rsc->allowed_nodes, prefer->details->id); - if(local_prefer == NULL || local_prefer->weight < 0) { - crm_trace("Not pre-allocating %s to %s - unavailable", rsc->id, prefer->details->uname); - return NULL; - } + if (prefer) { + node_t *local_prefer = g_hash_table_lookup(rsc->allowed_nodes, prefer->details->id); + + if (local_prefer == NULL || local_prefer->weight < 0) { + crm_trace("Not pre-allocating %s to %s - unavailable", rsc->id, prefer->details->uname); + return NULL; + } } - if(rsc->allowed_nodes) { - GHashTableIter iter; - node_t *try_node = NULL; - g_hash_table_iter_init (&iter, rsc->allowed_nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&try_node)) { - can_run_instance(rsc, try_node); - } + if (rsc->allowed_nodes) { + GHashTableIter iter; + node_t *try_node = NULL; + + g_hash_table_iter_init(&iter, rsc->allowed_nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&try_node)) { + can_run_instance(rsc, try_node); + } } chosen = rsc->cmds->allocate(rsc, prefer, data_set); - if(chosen) { - local_node = pe_hash_table_lookup( - rsc->parent->allowed_nodes, chosen->details->id); - - if(prefer && chosen && chosen->details != prefer->details) { - crm_err("Pre-allocation failed: got %s instead of %s", - chosen->details->uname, prefer->details->uname); - native_deallocate(rsc); - chosen = NULL; - - } else if(local_node) { - local_node->count++; - - } else if(is_set(rsc->flags, pe_rsc_managed)) { - /* what to do? we can't enforce per-node limits in this case */ - crm_config_err("%s not found in %s (list=%d)", - chosen->details->id, rsc->parent->id, - g_hash_table_size(rsc->parent->allowed_nodes)); - } + if (chosen) { + local_node = pe_hash_table_lookup(rsc->parent->allowed_nodes, chosen->details->id); + + if (prefer && chosen && chosen->details != prefer->details) { + crm_err("Pre-allocation failed: got %s instead of %s", + chosen->details->uname, prefer->details->uname); + native_deallocate(rsc); + chosen = NULL; + + } else if (local_node) { + local_node->count++; + + } else if (is_set(rsc->flags, pe_rsc_managed)) { + /* what to do? we can't enforce per-node limits in this case */ + crm_config_err("%s not found in %s (list=%d)", + chosen->details->id, rsc->parent->id, + g_hash_table_size(rsc->parent->allowed_nodes)); + } } return chosen; } -static void append_parent_colocation(resource_t *rsc, resource_t *child, gboolean all) +static void +append_parent_colocation(resource_t * rsc, resource_t * child, gboolean all) { - + GListPtr gIter = NULL; gIter = rsc->rsc_cons; - for(; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *cons = (rsc_colocation_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *cons = (rsc_colocation_t *) gIter->data; - if(all || cons->score < 0 || cons->score == INFINITY) { - child->rsc_cons = g_list_prepend(child->rsc_cons, cons); - } + if (all || cons->score < 0 || cons->score == INFINITY) { + child->rsc_cons = g_list_prepend(child->rsc_cons, cons); + } } - + gIter = rsc->rsc_cons_lhs; - for(; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *cons = (rsc_colocation_t*)gIter->data; - - if(all || cons->score < 0) { - child->rsc_cons_lhs = g_list_prepend(child->rsc_cons_lhs, cons); - } + for (; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *cons = (rsc_colocation_t *) gIter->data; + + if (all || cons->score < 0) { + child->rsc_cons_lhs = g_list_prepend(child->rsc_cons_lhs, cons); + } } } node_t * -clone_color(resource_t *rsc, node_t *prefer, pe_working_set_t *data_set) +clone_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set) { int allocated = 0; GHashTableIter iter; GListPtr gIter = NULL; node_t *node = NULL; int available_nodes = 0; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); - if(is_not_set(rsc->flags, pe_rsc_provisional)) { - return NULL; + if (is_not_set(rsc->flags, pe_rsc_provisional)) { + return NULL; - } else if(is_set(rsc->flags, pe_rsc_allocating)) { - crm_debug("Dependency loop detected involving %s", rsc->id); - return NULL; + } else if (is_set(rsc->flags, pe_rsc_allocating)) { + crm_debug("Dependency loop detected involving %s", rsc->id); + return NULL; } set_bit(rsc->flags, pe_rsc_allocating); crm_debug_2("Processing %s", rsc->id); /* this information is used by sort_clone_instance() when deciding in which * order to allocate clone instances */ gIter = rsc->rsc_cons; - for(; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; - crm_trace("%s: Coloring %s first", rsc->id, constraint->rsc_rh->id); - constraint->rsc_rh->cmds->allocate(constraint->rsc_rh, prefer, data_set); + crm_trace("%s: Coloring %s first", rsc->id, constraint->rsc_rh->id); + constraint->rsc_rh->cmds->allocate(constraint->rsc_rh, prefer, data_set); } - + gIter = rsc->rsc_cons_lhs; - for(; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - - rsc->allowed_nodes = constraint->rsc_lh->cmds->merge_weights( - constraint->rsc_lh, rsc->id, rsc->allowed_nodes, - constraint->node_attribute, constraint->score/INFINITY, TRUE, TRUE); - } - + for (; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + rsc->allowed_nodes = + constraint->rsc_lh->cmds->merge_weights(constraint->rsc_lh, rsc->id, rsc->allowed_nodes, + constraint->node_attribute, + constraint->score / INFINITY, TRUE, TRUE); + } + gIter = rsc->rsc_tickets; - for(; gIter != NULL; gIter = gIter->next) { - rsc_ticket_t *rsc_ticket = (rsc_ticket_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + rsc_ticket_t *rsc_ticket = (rsc_ticket_t *) gIter->data; - if(rsc_ticket->ticket->granted == FALSE) { - rsc_ticket_constraint(rsc, rsc_ticket, data_set); - } + if (rsc_ticket->ticket->granted == FALSE) { + rsc_ticket_constraint(rsc, rsc_ticket, data_set); + } } - - dump_node_scores(show_scores?0:scores_log_level, rsc, __FUNCTION__, rsc->allowed_nodes); - + + dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __FUNCTION__, rsc->allowed_nodes); + /* count now tracks the number of clones currently allocated */ - g_hash_table_iter_init (&iter, rsc->allowed_nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - node->count = 0; - if(can_run_resources(node)) { - available_nodes++; - } + g_hash_table_iter_init(&iter, rsc->allowed_nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + node->count = 0; + if (can_run_resources(node)) { + available_nodes++; + } } rsc->children = g_list_sort_with_data(rsc->children, sort_clone_instance, data_set); /* Pre-allocate as many instances as we can to their current location */ - g_hash_table_iter_init (&iter, rsc->allowed_nodes); + g_hash_table_iter_init(&iter, rsc->allowed_nodes); while (available_nodes - && available_nodes <= clone_data->clone_max - && g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - int lpc; - int loop_max = clone_data->clone_max / available_nodes; - if(loop_max < 1) { - loop_max = 1; - } - - if(can_run_resources(node) == FALSE || node->weight < 0) { - crm_trace("Not Pre-allocatiing %s", node->details->uname); - continue; - } - - crm_trace("Pre-allocatiing %s", node->details->uname); - for(lpc = 0; - allocated < clone_data->clone_max - && node->count < clone_data->clone_node_max - && lpc < clone_data->clone_node_max - && lpc < loop_max; - lpc++) { - for(gIter = rsc->children; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - if(child->running_on - && is_set(child->flags, pe_rsc_provisional) - && is_not_set(child->flags, pe_rsc_failed)) { - node_t *child_node = child->running_on->data; - if(child_node->details == node->details - && color_instance(child, node, clone_data->clone_max < available_nodes, data_set)) { - crm_trace("Pre-allocated %s to %s", child->id, node->details->uname); - allocated++; - break; - } - } - } - } + && available_nodes <= clone_data->clone_max + && g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + int lpc; + int loop_max = clone_data->clone_max / available_nodes; + + if (loop_max < 1) { + loop_max = 1; + } + + if (can_run_resources(node) == FALSE || node->weight < 0) { + crm_trace("Not Pre-allocatiing %s", node->details->uname); + continue; + } + + crm_trace("Pre-allocatiing %s", node->details->uname); + for (lpc = 0; + allocated < clone_data->clone_max + && node->count < clone_data->clone_node_max + && lpc < clone_data->clone_node_max && lpc < loop_max; lpc++) { + for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + if (child->running_on && is_set(child->flags, pe_rsc_provisional) + && is_not_set(child->flags, pe_rsc_failed)) { + node_t *child_node = child->running_on->data; + + if (child_node->details == node->details + && color_instance(child, node, clone_data->clone_max < available_nodes, + data_set)) { + crm_trace("Pre-allocated %s to %s", child->id, node->details->uname); + allocated++; + break; + } + } + } + } } crm_trace("Done pre-allocating"); - + gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - - if(g_list_length(child->running_on) > 0) { - node_t *child_node = child->running_on->data; - node_t *local_node = parent_node_instance(child, child->running_on->data); - if(local_node == NULL) { - crm_err("%s is running on %s which isn't allowed", - child->id, child_node->details->uname); - } - } - - if(is_not_set(child->flags, pe_rsc_provisional)) { - } else if(allocated >= clone_data->clone_max) { - crm_debug("Child %s not allocated - limit reached", child->id); - resource_location(child, NULL, -INFINITY, "clone_color:limit_reached", data_set); - - } else if(color_instance(child, NULL, clone_data->clone_max < available_nodes, data_set)) { - allocated++; - } - } - + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + if (g_list_length(child->running_on) > 0) { + node_t *child_node = child->running_on->data; + node_t *local_node = parent_node_instance(child, child->running_on->data); + + if (local_node == NULL) { + crm_err("%s is running on %s which isn't allowed", + child->id, child_node->details->uname); + } + } + + if (is_not_set(child->flags, pe_rsc_provisional)) { + } else if (allocated >= clone_data->clone_max) { + crm_debug("Child %s not allocated - limit reached", child->id); + resource_location(child, NULL, -INFINITY, "clone_color:limit_reached", data_set); + + } else if (color_instance(child, NULL, clone_data->clone_max < available_nodes, data_set)) { + allocated++; + } + } crm_debug("Allocated %d %s instances of a possible %d", - allocated, rsc->id, clone_data->clone_max); + allocated, rsc->id, clone_data->clone_max); clear_bit(rsc->flags, pe_rsc_provisional); clear_bit(rsc->flags, pe_rsc_allocating); - + return NULL; } static void -clone_update_pseudo_status( - resource_t *rsc, gboolean *stopping, gboolean *starting, gboolean *active) +clone_update_pseudo_status(resource_t * rsc, gboolean * stopping, gboolean * starting, + gboolean * active) { GListPtr gIter = NULL; - if(rsc->children) { - gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; + if (rsc->children) { - clone_update_pseudo_status(child, stopping, starting, active); - } + gIter = rsc->children; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; - return; + clone_update_pseudo_status(child, stopping, starting, active); + } + + return; } - + CRM_ASSERT(active != NULL); CRM_ASSERT(starting != NULL); CRM_ASSERT(stopping != NULL); - if(rsc->running_on) { - *active = TRUE; + if (rsc->running_on) { + *active = TRUE; } - + gIter = rsc->actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - - if(*starting && *stopping) { - return; - - } else if(is_set(action->flags, pe_action_optional)) { - crm_debug_3("Skipping optional: %s", action->uuid); - continue; - - } else if(is_set(action->flags, pe_action_pseudo) == FALSE && is_set(action->flags, pe_action_runnable) == FALSE){ - crm_debug_3("Skipping unrunnable: %s", action->uuid); - continue; - - } else if(safe_str_eq(RSC_STOP, action->task)) { - crm_debug_2("Stopping due to: %s", action->uuid); - *stopping = TRUE; - - } else if(safe_str_eq(RSC_START, action->task)) { - if(is_set(action->flags, pe_action_runnable) == FALSE) { - crm_debug_3("Skipping pseudo-op: %s run=%d, pseudo=%d", - action->uuid, is_set(action->flags, pe_action_runnable), - is_set(action->flags, pe_action_pseudo)); - } else { - crm_debug_2("Starting due to: %s", action->uuid); - crm_debug_3("%s run=%d, pseudo=%d", - action->uuid, is_set(action->flags, pe_action_runnable), - is_set(action->flags, pe_action_pseudo)); - *starting = TRUE; - } - } + for (; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + if (*starting && *stopping) { + return; + + } else if (is_set(action->flags, pe_action_optional)) { + crm_debug_3("Skipping optional: %s", action->uuid); + continue; + + } else if (is_set(action->flags, pe_action_pseudo) == FALSE + && is_set(action->flags, pe_action_runnable) == FALSE) { + crm_debug_3("Skipping unrunnable: %s", action->uuid); + continue; + + } else if (safe_str_eq(RSC_STOP, action->task)) { + crm_debug_2("Stopping due to: %s", action->uuid); + *stopping = TRUE; + + } else if (safe_str_eq(RSC_START, action->task)) { + if (is_set(action->flags, pe_action_runnable) == FALSE) { + crm_debug_3("Skipping pseudo-op: %s run=%d, pseudo=%d", + action->uuid, is_set(action->flags, pe_action_runnable), + is_set(action->flags, pe_action_pseudo)); + } else { + crm_debug_2("Starting due to: %s", action->uuid); + crm_debug_3("%s run=%d, pseudo=%d", + action->uuid, is_set(action->flags, pe_action_runnable), + is_set(action->flags, pe_action_pseudo)); + *starting = TRUE; + } + } } } static action_t * -find_rsc_action(resource_t *rsc, const char *key, gboolean active_only, GListPtr *list) +find_rsc_action(resource_t * rsc, const char *key, gboolean active_only, GListPtr * list) { action_t *match = NULL; GListPtr possible = NULL; GListPtr active = NULL; + possible = find_actions(rsc->actions, key, NULL); - if(active_only) { - GListPtr gIter = possible; - for(; gIter != NULL; gIter = gIter->next) { - action_t *op = (action_t*)gIter->data; - - if(is_set(op->flags, pe_action_optional) == FALSE) { - active = g_list_prepend(active, op); - } - } - - if(active && g_list_length(active) == 1) { - match = g_list_nth_data(active, 0); - } - - if(list) { - *list = active; active = NULL; - } - - } else if(possible && g_list_length(possible) == 1) { - match = g_list_nth_data(possible, 0); - - } if(list) { - *list = possible; possible = NULL; - } - - if(possible) { - g_list_free(possible); - } - if(active) { - g_list_free(active); - } - + if (active_only) { + GListPtr gIter = possible; + + for (; gIter != NULL; gIter = gIter->next) { + action_t *op = (action_t *) gIter->data; + + if (is_set(op->flags, pe_action_optional) == FALSE) { + active = g_list_prepend(active, op); + } + } + + if (active && g_list_length(active) == 1) { + match = g_list_nth_data(active, 0); + } + + if (list) { + *list = active; + active = NULL; + } + + } else if (possible && g_list_length(possible) == 1) { + match = g_list_nth_data(possible, 0); + + } + if (list) { + *list = possible; + possible = NULL; + } + + if (possible) { + g_list_free(possible); + } + if (active) { + g_list_free(active); + } + return match; } static void -child_ordering_constraints(resource_t *rsc, pe_working_set_t *data_set) +child_ordering_constraints(resource_t * rsc, pe_working_set_t * data_set) { char *key = NULL; action_t *stop = NULL; - action_t *start = NULL; + action_t *start = NULL; action_t *last_stop = NULL; action_t *last_start = NULL; GListPtr gIter = rsc->children; - gboolean active_only = TRUE; /* change to false to get the old behavior */ + gboolean active_only = TRUE; /* change to false to get the old behavior */ clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); - if(clone_data->ordered == FALSE) { - return; - } - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - - key = stop_key(child); - stop = find_rsc_action(child, key, active_only, NULL); - crm_free(key); - - key = start_key(child); - start = find_rsc_action(child, key, active_only, NULL); - crm_free(key); - - if(stop) { - if(last_stop) { - /* child/child relative stop */ - order_actions(stop, last_stop, pe_order_optional); - } - last_stop = stop; - } - - if(start) { - if(last_start) { - /* child/child relative start */ - order_actions(last_start, start, pe_order_optional); - } - last_start = start; - } + if (clone_data->ordered == FALSE) { + return; + } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + key = stop_key(child); + stop = find_rsc_action(child, key, active_only, NULL); + crm_free(key); + + key = start_key(child); + start = find_rsc_action(child, key, active_only, NULL); + crm_free(key); + + if (stop) { + if (last_stop) { + /* child/child relative stop */ + order_actions(stop, last_stop, pe_order_optional); + } + last_stop = stop; + } + + if (start) { + if (last_start) { + /* child/child relative start */ + order_actions(last_start, start, pe_order_optional); + } + last_start = start; + } } } -void clone_create_actions(resource_t *rsc, pe_working_set_t *data_set) +void +clone_create_actions(resource_t * rsc, pe_working_set_t * data_set) { gboolean child_active = FALSE; gboolean child_starting = FALSE; gboolean child_stopping = FALSE; action_t *stop = NULL; action_t *stopped = NULL; action_t *start = NULL; action_t *started = NULL; GListPtr gIter = rsc->children; resource_t *last_start_rsc = NULL; resource_t *last_stop_rsc = NULL; clone_variant_data_t *clone_data = NULL; get_clone_variant_data(clone_data, rsc); crm_debug_2("Creating actions for %s", rsc->id); - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - - child_rsc->cmds->create_actions(child_rsc, data_set); - clone_update_pseudo_status( - child_rsc, &child_stopping, &child_starting, &child_active); - - if(is_set(child_rsc->flags, pe_rsc_starting)) { - last_start_rsc = child_rsc; - } - if(is_set(child_rsc->flags, pe_rsc_stopping)) { - last_stop_rsc = child_rsc; - } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->create_actions(child_rsc, data_set); + clone_update_pseudo_status(child_rsc, &child_stopping, &child_starting, &child_active); + + if (is_set(child_rsc->flags, pe_rsc_starting)) { + last_start_rsc = child_rsc; + } + if (is_set(child_rsc->flags, pe_rsc_stopping)) { + last_stop_rsc = child_rsc; + } } /* start */ start = start_action(rsc, NULL, !child_starting); started = custom_action(rsc, started_key(rsc), - RSC_STARTED, NULL, !child_starting, TRUE, data_set); + RSC_STARTED, NULL, !child_starting, TRUE, data_set); - update_action_flags(start, pe_action_pseudo|pe_action_runnable); + update_action_flags(start, pe_action_pseudo | pe_action_runnable); update_action_flags(started, pe_action_pseudo); started->priority = INFINITY; - if(child_active || child_starting) { - update_action_flags(started, pe_action_runnable); + if (child_active || child_starting) { + update_action_flags(started, pe_action_runnable); } - + child_ordering_constraints(rsc, data_set); - if(clone_data->start_notify == NULL) { - clone_data->start_notify = create_notification_boundaries(rsc, RSC_START, start, started, data_set); + if (clone_data->start_notify == NULL) { + clone_data->start_notify = + create_notification_boundaries(rsc, RSC_START, start, started, data_set); } - + /* stop */ stop = stop_action(rsc, NULL, !child_stopping); stopped = custom_action(rsc, stopped_key(rsc), - RSC_STOPPED, NULL, !child_stopping, TRUE, data_set); + RSC_STOPPED, NULL, !child_stopping, TRUE, data_set); stopped->priority = INFINITY; - update_action_flags(stop, pe_action_pseudo|pe_action_runnable); - update_action_flags(stopped, pe_action_pseudo|pe_action_runnable); - if(clone_data->stop_notify == NULL) { - clone_data->stop_notify = create_notification_boundaries(rsc, RSC_STOP, stop, stopped, data_set); + update_action_flags(stop, pe_action_pseudo | pe_action_runnable); + update_action_flags(stopped, pe_action_pseudo | pe_action_runnable); + if (clone_data->stop_notify == NULL) { + clone_data->stop_notify = + create_notification_boundaries(rsc, RSC_STOP, stop, stopped, data_set); - if(clone_data->stop_notify && clone_data->start_notify) { - order_actions(clone_data->stop_notify->post_done, clone_data->start_notify->pre, pe_order_optional); - } + if (clone_data->stop_notify && clone_data->start_notify) { + order_actions(clone_data->stop_notify->post_done, clone_data->start_notify->pre, + pe_order_optional); + } } } void -clone_internal_constraints(resource_t *rsc, pe_working_set_t *data_set) +clone_internal_constraints(resource_t * rsc, pe_working_set_t * data_set) { - resource_t *last_rsc = NULL; + resource_t *last_rsc = NULL; GListPtr gIter = rsc->children; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); crm_trace("Internal constraints for %s", rsc->id); - new_rsc_order(rsc, RSC_STOPPED, rsc, RSC_START, pe_order_optional, data_set); - new_rsc_order(rsc, RSC_START, rsc, RSC_STARTED, pe_order_runnable_left, data_set); - new_rsc_order(rsc, RSC_STOP, rsc, RSC_STOPPED, pe_order_runnable_left, data_set); - - if(rsc->variant == pe_master) { - new_rsc_order(rsc, RSC_DEMOTED, rsc, RSC_STOP, pe_order_optional, data_set); - new_rsc_order(rsc, RSC_STARTED, rsc, RSC_PROMOTE, pe_order_runnable_left, data_set); - } - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - - child_rsc->cmds->internal_constraints(child_rsc, data_set); - - order_start_start(rsc, child_rsc, pe_order_runnable_left|pe_order_implies_first_printed); - new_rsc_order(child_rsc, RSC_START, rsc, RSC_STARTED, pe_order_implies_then_printed, data_set); - if(clone_data->ordered && last_rsc){ - order_start_start(last_rsc, child_rsc, pe_order_optional); - } - - order_stop_stop(rsc, child_rsc, pe_order_implies_first_printed); - new_rsc_order(child_rsc, RSC_STOP, rsc, RSC_STOPPED, pe_order_implies_then_printed, data_set); - if(clone_data->ordered && last_rsc){ - order_stop_stop(child_rsc, last_rsc, pe_order_optional); - } - - last_rsc = child_rsc; + new_rsc_order(rsc, RSC_STOPPED, rsc, RSC_START, pe_order_optional, data_set); + new_rsc_order(rsc, RSC_START, rsc, RSC_STARTED, pe_order_runnable_left, data_set); + new_rsc_order(rsc, RSC_STOP, rsc, RSC_STOPPED, pe_order_runnable_left, data_set); + + if (rsc->variant == pe_master) { + new_rsc_order(rsc, RSC_DEMOTED, rsc, RSC_STOP, pe_order_optional, data_set); + new_rsc_order(rsc, RSC_STARTED, rsc, RSC_PROMOTE, pe_order_runnable_left, data_set); + } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->internal_constraints(child_rsc, data_set); + + order_start_start(rsc, child_rsc, pe_order_runnable_left | pe_order_implies_first_printed); + new_rsc_order(child_rsc, RSC_START, rsc, RSC_STARTED, pe_order_implies_then_printed, + data_set); + if (clone_data->ordered && last_rsc) { + order_start_start(last_rsc, child_rsc, pe_order_optional); + } + + order_stop_stop(rsc, child_rsc, pe_order_implies_first_printed); + new_rsc_order(child_rsc, RSC_STOP, rsc, RSC_STOPPED, pe_order_implies_then_printed, + data_set); + if (clone_data->ordered && last_rsc) { + order_stop_stop(child_rsc, last_rsc, pe_order_optional); + } + + last_rsc = child_rsc; } } static void -assign_node(resource_t *rsc, node_t *node, gboolean force) +assign_node(resource_t * rsc, node_t * node, gboolean force) { - if(rsc->children) { + if (rsc->children) { + + GListPtr gIter = rsc->children; - GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - native_assign_node(child_rsc, NULL, node, force); - } + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; - return; + native_assign_node(child_rsc, NULL, node, force); + } + + return; } native_assign_node(rsc, NULL, node, force); } -static resource_t* -find_compatible_child_by_node( - resource_t *local_child, node_t *local_node, resource_t *rsc, enum rsc_role_e filter, gboolean current) +static resource_t * +find_compatible_child_by_node(resource_t * local_child, node_t * local_node, resource_t * rsc, + enum rsc_role_e filter, gboolean current) { node_t *node = NULL; GListPtr gIter = NULL; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); - - if(local_node == NULL) { - crm_err("Can't colocate unrunnable child %s with %s", - local_child->id, rsc->id); - return NULL; + + if (local_node == NULL) { + crm_err("Can't colocate unrunnable child %s with %s", local_child->id, rsc->id); + return NULL; } - + crm_trace("Looking for compatible child from %s for %s on %s", - local_child->id, rsc->id, local_node->details->uname); - + local_child->id, rsc->id, local_node->details->uname); + gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - enum rsc_role_e next_role = child_rsc->fns->state(child_rsc, current); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + enum rsc_role_e next_role = child_rsc->fns->state(child_rsc, current); + + node = child_rsc->fns->location(child_rsc, NULL, current); - node = child_rsc->fns->location(child_rsc, NULL, current); + if (filter != RSC_ROLE_UNKNOWN && next_role != filter) { + crm_trace("Filtered %s", child_rsc->id); + continue; + } - if(filter != RSC_ROLE_UNKNOWN && next_role != filter) { - crm_trace("Filtered %s", child_rsc->id); - continue; - } - - if(node && local_node && node->details == local_node->details) { - crm_debug_2("Pairing %s with %s on %s", - local_child->id, child_rsc->id, node->details->uname); - return child_rsc; + if (node && local_node && node->details == local_node->details) { + crm_debug_2("Pairing %s with %s on %s", + local_child->id, child_rsc->id, node->details->uname); + return child_rsc; - } else if(node) { - crm_trace("%s - %s vs %s", child_rsc->id, node->details->uname, local_node->details->uname); + } else if (node) { + crm_trace("%s - %s vs %s", child_rsc->id, node->details->uname, + local_node->details->uname); - } else { - crm_trace("%s - not allocated %d", child_rsc->id, current); - } + } else { + crm_trace("%s - not allocated %d", child_rsc->id, current); + } } crm_debug_3("Can't pair %s with %s", local_child->id, rsc->id); return NULL; } -resource_t* -find_compatible_child( - resource_t *local_child, resource_t *rsc, enum rsc_role_e filter, gboolean current) +resource_t * +find_compatible_child(resource_t * local_child, resource_t * rsc, enum rsc_role_e filter, + gboolean current) { resource_t *pair = NULL; GListPtr gIter = NULL; GListPtr scratch = NULL; node_t *local_node = NULL; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); - + local_node = local_child->fns->location(local_child, NULL, current); - if(local_node) { - return find_compatible_child_by_node(local_child, local_node, rsc, filter, current); + if (local_node) { + return find_compatible_child_by_node(local_child, local_node, rsc, filter, current); } scratch = g_hash_table_get_values(local_child->allowed_nodes); scratch = g_list_sort_with_data(scratch, sort_node_weight, NULL); gIter = scratch; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; - pair = find_compatible_child_by_node( - local_child, node, rsc, filter, current); - if(pair) { - goto done; - } + pair = find_compatible_child_by_node(local_child, node, rsc, filter, current); + if (pair) { + goto done; + } } - + crm_debug("Can't pair %s with %s", local_child->id, rsc->id); done: g_list_free(scratch); return pair; } -void clone_rsc_colocation_lh( - resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) +void +clone_rsc_colocation_lh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint) { /* -- Never called -- * * Instead we add the colocation constraints to the child and call from there */ - + GListPtr gIter = rsc_lh->children; + CRM_CHECK(FALSE, crm_err("This functionality is not thought to be used. Please report a bug.")); CRM_CHECK(rsc_lh, return); CRM_CHECK(rsc_rh, return); - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - - child_rsc->cmds->rsc_colocation_lh(child_rsc, rsc_rh, constraint); + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->rsc_colocation_lh(child_rsc, rsc_rh, constraint); } return; } -void clone_rsc_colocation_rh( - resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) +void +clone_rsc_colocation_rh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint) { GListPtr gIter = NULL; gboolean do_interleave = FALSE; clone_variant_data_t *clone_data = NULL; clone_variant_data_t *clone_data_lh = NULL; CRM_CHECK(rsc_lh != NULL, return); CRM_CHECK(rsc_lh->variant == pe_native, return); - + get_clone_variant_data(clone_data, constraint->rsc_rh); crm_debug_3("Processing constraint %s: %s -> %s %d", - constraint->id, rsc_lh->id, rsc_rh->id, constraint->score); - - if(constraint->rsc_lh->variant >= pe_clone) { - - get_clone_variant_data(clone_data_lh, constraint->rsc_lh); - if(clone_data->clone_node_max != clone_data_lh->clone_node_max) { - crm_config_err("Cannot interleave "XML_CIB_TAG_INCARNATION - " %s and %s because" - " they do not support the same number of" - " resources per node", - constraint->rsc_lh->id, constraint->rsc_rh->id); - - /* only the LHS side needs to be labeled as interleave */ - } else if(clone_data_lh->interleave) { - do_interleave = TRUE; - } - } - - if(rsc_rh == NULL) { - pe_err("rsc_rh was NULL for %s", constraint->id); - return; - - } else if(is_set(rsc_rh->flags, pe_rsc_provisional)) { - crm_debug_3("%s is still provisional", rsc_rh->id); - return; - - } else if(do_interleave) { - resource_t *rh_child = NULL; - - rh_child = find_compatible_child(rsc_lh, rsc_rh, RSC_ROLE_UNKNOWN, FALSE); - - if(rh_child) { - crm_debug("Pairing %s with %s", rsc_lh->id, rh_child->id); - rsc_lh->cmds->rsc_colocation_lh(rsc_lh, rh_child, constraint); - - } else if(constraint->score >= INFINITY) { - crm_notice("Cannot pair %s with instance of %s", rsc_lh->id, rsc_rh->id); - assign_node(rsc_lh, NULL, TRUE); - - } else { - crm_debug("Cannot pair %s with instance of %s", rsc_lh->id, rsc_rh->id); - } - - return; - - } else if(constraint->score >= INFINITY) { - GListPtr rhs = NULL; - - gIter = rsc_rh->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - node_t *chosen = child_rsc->fns->location(child_rsc, NULL, FALSE); - - if(chosen != NULL) { - rhs = g_list_prepend(rhs, chosen); - } - } - - node_list_exclude(rsc_lh->allowed_nodes, rhs, FALSE); - g_list_free(rhs); - return; + constraint->id, rsc_lh->id, rsc_rh->id, constraint->score); + + if (constraint->rsc_lh->variant >= pe_clone) { + + get_clone_variant_data(clone_data_lh, constraint->rsc_lh); + if (clone_data->clone_node_max != clone_data_lh->clone_node_max) { + crm_config_err("Cannot interleave " XML_CIB_TAG_INCARNATION + " %s and %s because" + " they do not support the same number of" + " resources per node", constraint->rsc_lh->id, constraint->rsc_rh->id); + + /* only the LHS side needs to be labeled as interleave */ + } else if (clone_data_lh->interleave) { + do_interleave = TRUE; + } + } + + if (rsc_rh == NULL) { + pe_err("rsc_rh was NULL for %s", constraint->id); + return; + + } else if (is_set(rsc_rh->flags, pe_rsc_provisional)) { + crm_debug_3("%s is still provisional", rsc_rh->id); + return; + + } else if (do_interleave) { + resource_t *rh_child = NULL; + + rh_child = find_compatible_child(rsc_lh, rsc_rh, RSC_ROLE_UNKNOWN, FALSE); + + if (rh_child) { + crm_debug("Pairing %s with %s", rsc_lh->id, rh_child->id); + rsc_lh->cmds->rsc_colocation_lh(rsc_lh, rh_child, constraint); + + } else if (constraint->score >= INFINITY) { + crm_notice("Cannot pair %s with instance of %s", rsc_lh->id, rsc_rh->id); + assign_node(rsc_lh, NULL, TRUE); + + } else { + crm_debug("Cannot pair %s with instance of %s", rsc_lh->id, rsc_rh->id); + } + + return; + + } else if (constraint->score >= INFINITY) { + GListPtr rhs = NULL; + + gIter = rsc_rh->children; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + node_t *chosen = child_rsc->fns->location(child_rsc, NULL, FALSE); + + if (chosen != NULL) { + rhs = g_list_prepend(rhs, chosen); + } + } + + node_list_exclude(rsc_lh->allowed_nodes, rhs, FALSE); + g_list_free(rhs); + return; } gIter = rsc_rh->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - - child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint); } } -static enum action_tasks clone_child_action(action_t *action) +static enum action_tasks +clone_child_action(action_t * action) { enum action_tasks result = no_action; - resource_t *child = (resource_t*)action->rsc->children->data; - - if(safe_str_eq(action->task, "notify") - || safe_str_eq(action->task, "notified")) { - - /* Find the action we're notifying about instead */ - - int stop = 0; - char *key = action->uuid; - int lpc = strlen(key); - - for(; lpc > 0; lpc--) { - if(key[lpc] == '_' && stop == 0) { - stop = lpc; - - } else if(key[lpc] == '_') { - char *task_mutable = NULL; - - lpc++; - task_mutable = crm_strdup(key+lpc); - task_mutable[stop-lpc] = 0; - - crm_trace("Extracted action '%s' from '%s'", task_mutable, key); - result = get_complex_task(child, task_mutable, TRUE); - crm_free(task_mutable); - break; - } - } + resource_t *child = (resource_t *) action->rsc->children->data; + + if (safe_str_eq(action->task, "notify") + || safe_str_eq(action->task, "notified")) { + + /* Find the action we're notifying about instead */ + + int stop = 0; + char *key = action->uuid; + int lpc = strlen(key); + + for (; lpc > 0; lpc--) { + if (key[lpc] == '_' && stop == 0) { + stop = lpc; + + } else if (key[lpc] == '_') { + char *task_mutable = NULL; + + lpc++; + task_mutable = crm_strdup(key + lpc); + task_mutable[stop - lpc] = 0; + + crm_trace("Extracted action '%s' from '%s'", task_mutable, key); + result = get_complex_task(child, task_mutable, TRUE); + crm_free(task_mutable); + break; + } + } } else { - result = get_complex_task(child, action->task, TRUE); + result = get_complex_task(child, action->task, TRUE); } - return result; + return result; } - -enum pe_action_flags clone_action_flags(action_t *action, node_t *node) +enum pe_action_flags +clone_action_flags(action_t * action, node_t * node) { GListPtr gIter = NULL; gboolean any_runnable = FALSE; gboolean check_runnable = TRUE; enum action_tasks task = clone_child_action(action); enum pe_action_flags flags = (pe_action_optional | pe_action_runnable | pe_action_pseudo); const char *task_s = task2text(task); gIter = action->rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - action_t *child_action = NULL; - resource_t *child = (resource_t*)gIter->data; - - child_action = find_first_action(child->actions, NULL, task_s, child->children?NULL:node); - crm_trace("Checking for %s in %s on %s", task_s, child->id, node?node->details->uname:"none"); - if(child_action) { - enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node); - if(is_set(flags, pe_action_optional) && is_set(child_flags, pe_action_optional) == FALSE) { - crm_trace("%s is manditory because of %s", action->uuid, child_action->uuid); - clear_bit_inplace(flags, pe_action_optional); - clear_bit_inplace(action->flags, pe_action_optional); - } - if(is_set(child_flags, pe_action_runnable)) { - any_runnable = TRUE; - } - - } else { - - GListPtr gIter2 = child->actions; - for(; gIter2 != NULL; gIter2 = gIter2->next) { - action_t *op = (action_t*)gIter2->data; - crm_trace("%s on %s (%s)", op->uuid, op->node?op->node->details->uname:"none", op->task); - } - } - } - - if(check_runnable && any_runnable == FALSE) { - crm_trace("%s is not runnable because no children are", action->uuid); - clear_bit_inplace(flags, pe_action_runnable); - if(node == NULL) { - clear_bit_inplace(action->flags, pe_action_runnable); - } + for (; gIter != NULL; gIter = gIter->next) { + action_t *child_action = NULL; + resource_t *child = (resource_t *) gIter->data; + + child_action = + find_first_action(child->actions, NULL, task_s, child->children ? NULL : node); + crm_trace("Checking for %s in %s on %s", task_s, child->id, + node ? node->details->uname : "none"); + if (child_action) { + enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node); + + if (is_set(flags, pe_action_optional) + && is_set(child_flags, pe_action_optional) == FALSE) { + crm_trace("%s is manditory because of %s", action->uuid, child_action->uuid); + clear_bit_inplace(flags, pe_action_optional); + clear_bit_inplace(action->flags, pe_action_optional); + } + if (is_set(child_flags, pe_action_runnable)) { + any_runnable = TRUE; + } + + } else { + + GListPtr gIter2 = child->actions; + + for (; gIter2 != NULL; gIter2 = gIter2->next) { + action_t *op = (action_t *) gIter2->data; + + crm_trace("%s on %s (%s)", op->uuid, op->node ? op->node->details->uname : "none", + op->task); + } + } + } + + if (check_runnable && any_runnable == FALSE) { + crm_trace("%s is not runnable because no children are", action->uuid); + clear_bit_inplace(flags, pe_action_runnable); + if (node == NULL) { + clear_bit_inplace(action->flags, pe_action_runnable); + } } return flags; } -static enum pe_graph_flags clone_update_actions_interleave( - action_t *first, action_t *then, node_t *node, enum pe_action_flags flags, enum pe_action_flags filter, enum pe_ordering type) +static enum pe_graph_flags +clone_update_actions_interleave(action_t * first, action_t * then, node_t * node, + enum pe_action_flags flags, enum pe_action_flags filter, + enum pe_ordering type) { gboolean current = FALSE; resource_t *first_child = NULL; GListPtr gIter = then->rsc->children; - enum pe_graph_flags changed = pe_graph_none; /*pe_graph_disable*/ + enum pe_graph_flags changed = pe_graph_none; /*pe_graph_disable */ enum action_tasks task = clone_child_action(first); const char *first_task = task2text(task); - + /* Fix this - lazy */ - if(strstr(first->uuid, "_stopped_0") || strstr(first->uuid, "_demoted_0")) { - current = TRUE; - } - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *then_child = (resource_t*)gIter->data; - - CRM_ASSERT(then_child != NULL); - first_child = find_compatible_child(then_child, first->rsc, RSC_ROLE_UNKNOWN, current); - if(first_child == NULL && current) { - crm_trace("Ignore"); - - } else if(first_child == NULL) { - crm_debug("No match found for %s (%d / %s / %s)", then_child->id, current, first->uuid, then->uuid); - - /* Me no like this hack - but what else can we do? - * - * If there is no-one active or about to be active - * on the same node as then_child, then they must - * not be allowed to start - */ - if(type & (pe_order_runnable_left|pe_order_implies_then) /* Mandatory */) { - crm_info("Inhibiting %s from being active", then_child->id); - assign_node(then_child, NULL, TRUE); - } - - } else { - action_t *first_action = NULL; - action_t *then_action = NULL; - - crm_debug("Pairing %s with %s", first_child->id, then_child->id); - - first_action = find_first_action(first_child->actions, NULL, first_task, node); - then_action = find_first_action(then_child->actions, NULL, then->task, node); - - CRM_CHECK(first_action != NULL || is_set(first_child->flags, pe_rsc_orphan), - crm_err("No action found for %s in %s (first)", first_task, first_child->id)); - - if(then_action == NULL - && is_not_set(then_child->flags, pe_rsc_orphan) - && crm_str_eq(then->task, RSC_STOP, TRUE) == FALSE - && crm_str_eq(then->task, RSC_DEMOTED, TRUE) == FALSE) { - crm_err("Internal error: No action found for %s in %s (then)", then->task, then_child->id); - } - - if(first_action == NULL || then_action == NULL) { - continue; - } - if(order_actions(first_action, then_action, type)) { - crm_debug("Created constraint for %s -> %s", first_action->uuid, then_action->uuid); - changed |= (pe_graph_updated_first|pe_graph_updated_then); - } - changed |= then_child->cmds->update_actions(first_action, then_action, node, then_child->cmds->action_flags(then_action, node), filter, type); - } + if (strstr(first->uuid, "_stopped_0") || strstr(first->uuid, "_demoted_0")) { + current = TRUE; + } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *then_child = (resource_t *) gIter->data; + + CRM_ASSERT(then_child != NULL); + first_child = find_compatible_child(then_child, first->rsc, RSC_ROLE_UNKNOWN, current); + if (first_child == NULL && current) { + crm_trace("Ignore"); + + } else if (first_child == NULL) { + crm_debug("No match found for %s (%d / %s / %s)", then_child->id, current, first->uuid, + then->uuid); + + /* Me no like this hack - but what else can we do? + * + * If there is no-one active or about to be active + * on the same node as then_child, then they must + * not be allowed to start + */ + if (type & (pe_order_runnable_left | pe_order_implies_then) /* Mandatory */ ) { + crm_info("Inhibiting %s from being active", then_child->id); + assign_node(then_child, NULL, TRUE); + } + + } else { + action_t *first_action = NULL; + action_t *then_action = NULL; + + crm_debug("Pairing %s with %s", first_child->id, then_child->id); + + first_action = find_first_action(first_child->actions, NULL, first_task, node); + then_action = find_first_action(then_child->actions, NULL, then->task, node); + + CRM_CHECK(first_action != NULL || is_set(first_child->flags, pe_rsc_orphan), + crm_err("No action found for %s in %s (first)", first_task, first_child->id)); + + if (then_action == NULL && is_not_set(then_child->flags, pe_rsc_orphan) + && crm_str_eq(then->task, RSC_STOP, TRUE) == FALSE + && crm_str_eq(then->task, RSC_DEMOTED, TRUE) == FALSE) { + crm_err("Internal error: No action found for %s in %s (then)", then->task, + then_child->id); + } + + if (first_action == NULL || then_action == NULL) { + continue; + } + if (order_actions(first_action, then_action, type)) { + crm_debug("Created constraint for %s -> %s", first_action->uuid, then_action->uuid); + changed |= (pe_graph_updated_first | pe_graph_updated_then); + } + changed |= + then_child->cmds->update_actions(first_action, then_action, node, + then_child->cmds->action_flags(then_action, node), + filter, type); + } } return changed; } -enum pe_graph_flags clone_update_actions( - action_t *first, action_t *then, node_t *node, enum pe_action_flags flags, enum pe_action_flags filter, enum pe_ordering type) +enum pe_graph_flags +clone_update_actions(action_t * first, action_t * then, node_t * node, enum pe_action_flags flags, + enum pe_action_flags filter, enum pe_ordering type) { const char *rsc = "none"; gboolean interleave = FALSE; enum pe_graph_flags changed = pe_graph_none; - if(first->rsc != then->rsc - && first->rsc && first->rsc->variant >= pe_clone - && then->rsc && then->rsc->variant >= pe_clone) { - clone_variant_data_t *clone_data = NULL; - if(strstr(then->uuid, "_stop_0") || strstr(then->uuid, "_demote_0")) { - get_clone_variant_data(clone_data, first->rsc); - rsc = first->rsc->id; - } else { - get_clone_variant_data(clone_data, then->rsc); - rsc = then->rsc->id; - } - interleave = clone_data->interleave; - } - + + if (first->rsc != then->rsc + && first->rsc && first->rsc->variant >= pe_clone + && then->rsc && then->rsc->variant >= pe_clone) { + clone_variant_data_t *clone_data = NULL; + + if (strstr(then->uuid, "_stop_0") || strstr(then->uuid, "_demote_0")) { + get_clone_variant_data(clone_data, first->rsc); + rsc = first->rsc->id; + } else { + get_clone_variant_data(clone_data, then->rsc); + rsc = then->rsc->id; + } + interleave = clone_data->interleave; + } + crm_trace("Interleave %s -> %s: %s (based on %s)", - first->uuid, then->uuid, interleave?"yes":"no", rsc); - - if(interleave) { - changed = clone_update_actions_interleave(first, then, node, flags, filter, type); - - } else if(then->rsc) { - GListPtr gIter = then->rsc->children; - changed |= native_update_actions(first, then, node, flags, filter, type); - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - action_t *child_action = find_first_action(child->actions, NULL, then->task, node); - - if(child_action) { - enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node); - if(is_set(child_flags, pe_action_runnable)) { - changed |= child->cmds->update_actions(first, child_action, node, flags, filter, type); - } - } - } - } - + first->uuid, then->uuid, interleave ? "yes" : "no", rsc); + + if (interleave) { + changed = clone_update_actions_interleave(first, then, node, flags, filter, type); + + } else if (then->rsc) { + GListPtr gIter = then->rsc->children; + + changed |= native_update_actions(first, then, node, flags, filter, type); + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + action_t *child_action = find_first_action(child->actions, NULL, then->task, node); + + if (child_action) { + enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node); + + if (is_set(child_flags, pe_action_runnable)) { + changed |= + child->cmds->update_actions(first, child_action, node, flags, filter, type); + } + } + } + } + return changed; } -void clone_rsc_location(resource_t *rsc, rsc_to_node_t *constraint) +void +clone_rsc_location(resource_t * rsc, rsc_to_node_t * constraint) { GListPtr gIter = rsc->children; - crm_debug_3("Processing location constraint %s for %s", - constraint->id, rsc->id); + + crm_debug_3("Processing location constraint %s for %s", constraint->id, rsc->id); native_rsc_location(rsc, constraint); - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - child_rsc->cmds->rsc_location(child_rsc, constraint); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->rsc_location(child_rsc, constraint); } } - -void clone_expand(resource_t *rsc, pe_working_set_t *data_set) +void +clone_expand(resource_t * rsc, pe_working_set_t * data_set) { GListPtr gIter = NULL; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); gIter = rsc->actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *op = (action_t*)gIter->data; - rsc->cmds->action_flags(op, NULL); + for (; gIter != NULL; gIter = gIter->next) { + action_t *op = (action_t *) gIter->data; + + rsc->cmds->action_flags(op, NULL); } - if(clone_data->start_notify) { - collect_notification_data(rsc, TRUE, TRUE, clone_data->start_notify); - expand_notification_data(clone_data->start_notify); - create_notifications(rsc, clone_data->start_notify, data_set); + if (clone_data->start_notify) { + collect_notification_data(rsc, TRUE, TRUE, clone_data->start_notify); + expand_notification_data(clone_data->start_notify); + create_notifications(rsc, clone_data->start_notify, data_set); } - if(clone_data->stop_notify) { - collect_notification_data(rsc, TRUE, TRUE, clone_data->stop_notify); - expand_notification_data(clone_data->stop_notify); - create_notifications(rsc, clone_data->stop_notify, data_set); + if (clone_data->stop_notify) { + collect_notification_data(rsc, TRUE, TRUE, clone_data->stop_notify); + expand_notification_data(clone_data->stop_notify); + create_notifications(rsc, clone_data->stop_notify, data_set); } - - if(clone_data->promote_notify) { - collect_notification_data(rsc, TRUE, TRUE, clone_data->promote_notify); - expand_notification_data(clone_data->promote_notify); - create_notifications(rsc, clone_data->promote_notify, data_set); + + if (clone_data->promote_notify) { + collect_notification_data(rsc, TRUE, TRUE, clone_data->promote_notify); + expand_notification_data(clone_data->promote_notify); + create_notifications(rsc, clone_data->promote_notify, data_set); } - - if(clone_data->demote_notify) { - collect_notification_data(rsc, TRUE, TRUE, clone_data->demote_notify); - expand_notification_data(clone_data->demote_notify); - create_notifications(rsc, clone_data->demote_notify, data_set); + + if (clone_data->demote_notify) { + collect_notification_data(rsc, TRUE, TRUE, clone_data->demote_notify); + expand_notification_data(clone_data->demote_notify); + create_notifications(rsc, clone_data->demote_notify, data_set); } - + /* Now that the notifcations have been created we can expand the children */ gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - child_rsc->cmds->expand(child_rsc, data_set); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->expand(child_rsc, data_set); } native_expand(rsc, data_set); /* The notifications are in the graph now, we can destroy the notify_data */ - free_notification_data(clone_data->demote_notify); clone_data->demote_notify = NULL; - free_notification_data(clone_data->stop_notify); clone_data->stop_notify = NULL; - free_notification_data(clone_data->start_notify); clone_data->start_notify = NULL; - free_notification_data(clone_data->promote_notify); clone_data->promote_notify = NULL; + free_notification_data(clone_data->demote_notify); + clone_data->demote_notify = NULL; + free_notification_data(clone_data->stop_notify); + clone_data->stop_notify = NULL; + free_notification_data(clone_data->start_notify); + clone_data->start_notify = NULL; + free_notification_data(clone_data->promote_notify); + clone_data->promote_notify = NULL; } - -static gint sort_rsc_id(gconstpointer a, gconstpointer b) +static gint +sort_rsc_id(gconstpointer a, gconstpointer b) { - const resource_t *resource1 = (const resource_t*)a; - const resource_t *resource2 = (const resource_t*)b; + const resource_t *resource1 = (const resource_t *)a; + const resource_t *resource2 = (const resource_t *)b; CRM_ASSERT(resource1 != NULL); CRM_ASSERT(resource2 != NULL); return strcmp(resource1->id, resource2->id); } -node_t *rsc_known_on(resource_t *rsc, GListPtr *list) +node_t * +rsc_known_on(resource_t * rsc, GListPtr * list) { GListPtr gIter = NULL; node_t *one = NULL; GListPtr result = NULL; - if(rsc->children) { + if (rsc->children) { - gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - rsc_known_on(child, &result); - } - - } else if(rsc->known_on) { - result = g_hash_table_get_values(rsc->known_on); + gIter = rsc->children; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + rsc_known_on(child, &result); + } + + } else if (rsc->known_on) { + result = g_hash_table_get_values(rsc->known_on); } - if(result && g_list_length(result) == 1) { - one = g_list_nth_data(result, 0); + if (result && g_list_length(result) == 1) { + one = g_list_nth_data(result, 0); } - - if(list) { - GListPtr gIter = NULL; - gIter = result; - for(; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - if(*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) { - *list = g_list_prepend(*list, node); - } - } + if (list) { + GListPtr gIter = NULL; + + gIter = result; + for (; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + if (*list == NULL || pe_find_node_id(*list, node->details->id) == NULL) { + *list = g_list_prepend(*list, node); + } + } } - g_list_free(result); + g_list_free(result); return one; } -static resource_t *find_instance_on(resource_t *rsc, node_t *node) +static resource_t * +find_instance_on(resource_t * rsc, node_t * node) { GListPtr gIter = NULL; gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - GListPtr gIter2 = NULL; - GListPtr known_list = NULL; - resource_t *child = (resource_t*)gIter->data; - - rsc_known_on(child, &known_list); - - gIter2 = known_list; - for(; gIter2 != NULL; gIter2 = gIter2->next) { - node_t *known = (node_t*)gIter2->data; - - if(node->details == known->details) { - g_list_free(known_list); - return child; - } - } - g_list_free(known_list); - } - + for (; gIter != NULL; gIter = gIter->next) { + GListPtr gIter2 = NULL; + GListPtr known_list = NULL; + resource_t *child = (resource_t *) gIter->data; + + rsc_known_on(child, &known_list); + + gIter2 = known_list; + for (; gIter2 != NULL; gIter2 = gIter2->next) { + node_t *known = (node_t *) gIter2->data; + + if (node->details == known->details) { + g_list_free(known_list); + return child; + } + } + g_list_free(known_list); + } + return NULL; } gboolean -clone_create_probe(resource_t *rsc, node_t *node, action_t *complete, - gboolean force, pe_working_set_t *data_set) +clone_create_probe(resource_t * rsc, node_t * node, action_t * complete, + gboolean force, pe_working_set_t * data_set) { GListPtr gIter = NULL; gboolean any_created = FALSE; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); rsc->children = g_list_sort(rsc->children, sort_rsc_id); - if(rsc->children == NULL) { - pe_warn("Clone %s has no children", rsc->id); - return FALSE; - } - - if(is_not_set(rsc->flags, pe_rsc_unique) - && clone_data->clone_node_max == 1) { - /* only look for one copy */ - resource_t *child = NULL; - - /* Try whoever we probed last time */ - child = find_instance_on(rsc, node); - if(child) { - return child->cmds->create_probe( - child, node, complete, force, data_set); - } - - /* Try whoever we plan on starting there */ - gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - node_t *local_node = child_rsc->fns->location(child_rsc, NULL, FALSE); - - if(local_node == NULL) { - continue; - } - - if(local_node->details == node->details) { - return child_rsc->cmds->create_probe( - child_rsc, node, complete, force, data_set); - } - } - - /* Fall back to the first clone instance */ - child = rsc->children->data; - return child->cmds->create_probe(child, node, complete, force, data_set); - } - + if (rsc->children == NULL) { + pe_warn("Clone %s has no children", rsc->id); + return FALSE; + } + + if (is_not_set(rsc->flags, pe_rsc_unique) + && clone_data->clone_node_max == 1) { + /* only look for one copy */ + resource_t *child = NULL; + + /* Try whoever we probed last time */ + child = find_instance_on(rsc, node); + if (child) { + return child->cmds->create_probe(child, node, complete, force, data_set); + } + + /* Try whoever we plan on starting there */ + gIter = rsc->children; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + node_t *local_node = child_rsc->fns->location(child_rsc, NULL, FALSE); + + if (local_node == NULL) { + continue; + } + + if (local_node->details == node->details) { + return child_rsc->cmds->create_probe(child_rsc, node, complete, force, data_set); + } + } + + /* Fall back to the first clone instance */ + child = rsc->children->data; + return child->cmds->create_probe(child, node, complete, force, data_set); + } + gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - - if(child_rsc->cmds->create_probe( - child_rsc, node, complete, force, data_set)) { - any_created = TRUE; - } - - if(any_created - && is_not_set(rsc->flags, pe_rsc_unique) - && clone_data->clone_node_max == 1) { - /* only look for one copy (clone :0) */ - break; - } + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + if (child_rsc->cmds->create_probe(child_rsc, node, complete, force, data_set)) { + any_created = TRUE; + } + + if (any_created && is_not_set(rsc->flags, pe_rsc_unique) + && clone_data->clone_node_max == 1) { + /* only look for one copy (clone :0) */ + break; + } } return any_created; } -void clone_append_meta(resource_t *rsc, xmlNode *xml) +void +clone_append_meta(resource_t * rsc, xmlNode * xml) { char *name = NULL; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); name = crm_meta_name(XML_RSC_ATTR_UNIQUE); - crm_xml_add(xml, name, is_set(rsc->flags, pe_rsc_unique)?"true":"false"); + crm_xml_add(xml, name, is_set(rsc->flags, pe_rsc_unique) ? "true" : "false"); crm_free(name); name = crm_meta_name(XML_RSC_ATTR_NOTIFY); - crm_xml_add(xml, name, is_set(rsc->flags, pe_rsc_notify)?"true":"false"); + crm_xml_add(xml, name, is_set(rsc->flags, pe_rsc_notify) ? "true" : "false"); crm_free(name); - + name = crm_meta_name(XML_RSC_ATTR_INCARNATION_MAX); crm_xml_add_int(xml, name, clone_data->clone_max); crm_free(name); name = crm_meta_name(XML_RSC_ATTR_INCARNATION_NODEMAX); crm_xml_add_int(xml, name, clone_data->clone_node_max); crm_free(name); } diff --git a/pengine/constraints.c b/pengine/constraints.c index 80647bb73e..a117920ed8 100644 --- a/pengine/constraints.c +++ b/pengine/constraints.c @@ -1,1653 +1,1686 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include - #include #include #include #include #include #include #include -enum pe_order_kind -{ +enum pe_order_kind { pe_order_kind_optional, pe_order_kind_mandatory, pe_order_kind_serialize, }; #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do { \ __rsc = pe_find_resource(data_set->resources, __name); \ if(__rsc == NULL) { \ crm_config_err("%s: No resource found for %s", __set, __name); \ return FALSE; \ } \ } while(0) -enum pe_ordering get_flags( - const char *id, enum pe_order_kind kind, - const char *action_first, const char *action_then, gboolean invert); +enum pe_ordering get_flags(const char *id, enum pe_order_kind kind, + const char *action_first, const char *action_then, gboolean invert); -gboolean -unpack_constraints(xmlNode * xml_constraints, pe_working_set_t *data_set) +gboolean +unpack_constraints(xmlNode * xml_constraints, pe_working_set_t * data_set) { xmlNode *xml_obj = NULL; xmlNode *lifetime = NULL; - for(xml_obj = __xml_first_child(xml_constraints); xml_obj != NULL; xml_obj = __xml_next(xml_obj)) { - const char *id = crm_element_value(xml_obj, XML_ATTR_ID); - if(id == NULL) { - crm_config_err("Constraint <%s...> must have an id", - crm_element_name(xml_obj)); - continue; - } - - crm_debug_3("Processing constraint %s %s", - crm_element_name(xml_obj),id); - - lifetime = first_named_child(xml_obj, "lifetime"); - if(lifetime) { - crm_config_warn("Support for the lifetime tag, used by %s, is deprecated." - " The rules it contains should instead be direct decendants of the constraint object", id); - } - - if(test_ruleset(lifetime, NULL, data_set->now) == FALSE) { - crm_info("Constraint %s %s is not active", - crm_element_name(xml_obj), id); - - } else if(safe_str_eq(XML_CONS_TAG_RSC_ORDER, - crm_element_name(xml_obj))) { - unpack_rsc_order(xml_obj, data_set); - - } else if(safe_str_eq(XML_CONS_TAG_RSC_DEPEND, - crm_element_name(xml_obj))) { - unpack_rsc_colocation(xml_obj, data_set); - - } else if(safe_str_eq(XML_CONS_TAG_RSC_LOCATION, - crm_element_name(xml_obj))) { - unpack_rsc_location(xml_obj, data_set); - - } else if(safe_str_eq(XML_CONS_TAG_RSC_TICKET, - crm_element_name(xml_obj))) { - unpack_rsc_ticket(xml_obj, data_set); - - } else { - pe_err("Unsupported constraint type: %s", - crm_element_name(xml_obj)); - } + + for (xml_obj = __xml_first_child(xml_constraints); xml_obj != NULL; + xml_obj = __xml_next(xml_obj)) { + const char *id = crm_element_value(xml_obj, XML_ATTR_ID); + + if (id == NULL) { + crm_config_err("Constraint <%s...> must have an id", crm_element_name(xml_obj)); + continue; + } + + crm_debug_3("Processing constraint %s %s", crm_element_name(xml_obj), id); + + lifetime = first_named_child(xml_obj, "lifetime"); + if (lifetime) { + crm_config_warn("Support for the lifetime tag, used by %s, is deprecated." + " The rules it contains should instead be direct decendants of the constraint object", + id); + } + + if (test_ruleset(lifetime, NULL, data_set->now) == FALSE) { + crm_info("Constraint %s %s is not active", crm_element_name(xml_obj), id); + + } else if (safe_str_eq(XML_CONS_TAG_RSC_ORDER, crm_element_name(xml_obj))) { + unpack_rsc_order(xml_obj, data_set); + + } else if (safe_str_eq(XML_CONS_TAG_RSC_DEPEND, crm_element_name(xml_obj))) { + unpack_rsc_colocation(xml_obj, data_set); + + } else if (safe_str_eq(XML_CONS_TAG_RSC_LOCATION, crm_element_name(xml_obj))) { + unpack_rsc_location(xml_obj, data_set); + + } else if (safe_str_eq(XML_CONS_TAG_RSC_TICKET, crm_element_name(xml_obj))) { + unpack_rsc_ticket(xml_obj, data_set); + + } else { + pe_err("Unsupported constraint type: %s", crm_element_name(xml_obj)); + } } return TRUE; } static const char * -invert_action(const char *action) +invert_action(const char *action) { - if(safe_str_eq(action, RSC_START)) { - return RSC_STOP; - - } else if(safe_str_eq(action, RSC_STOP)) { - return RSC_START; - - } else if(safe_str_eq(action, RSC_PROMOTE)) { - return RSC_DEMOTE; - - } else if(safe_str_eq(action, RSC_DEMOTE)) { - return RSC_PROMOTE; - - } else if(safe_str_eq(action, RSC_PROMOTED)) { - return RSC_DEMOTED; - - } else if(safe_str_eq(action, RSC_DEMOTED)) { - return RSC_PROMOTED; - - } else if(safe_str_eq(action, RSC_STARTED)) { - return RSC_STOPPED; - - } else if(safe_str_eq(action, RSC_STOPPED)) { - return RSC_STARTED; + if (safe_str_eq(action, RSC_START)) { + return RSC_STOP; + + } else if (safe_str_eq(action, RSC_STOP)) { + return RSC_START; + + } else if (safe_str_eq(action, RSC_PROMOTE)) { + return RSC_DEMOTE; + + } else if (safe_str_eq(action, RSC_DEMOTE)) { + return RSC_PROMOTE; + + } else if (safe_str_eq(action, RSC_PROMOTED)) { + return RSC_DEMOTED; + + } else if (safe_str_eq(action, RSC_DEMOTED)) { + return RSC_PROMOTED; + + } else if (safe_str_eq(action, RSC_STARTED)) { + return RSC_STOPPED; + + } else if (safe_str_eq(action, RSC_STOPPED)) { + return RSC_STARTED; } crm_config_warn("Unknown action: %s", action); return NULL; } -static enum pe_order_kind get_ordering_type(xmlNode *xml_obj) +static enum pe_order_kind +get_ordering_type(xmlNode * xml_obj) { enum pe_order_kind kind_e = pe_order_kind_mandatory; const char *kind = crm_element_value(xml_obj, XML_ORDER_ATTR_KIND); - if(kind == NULL) { - const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); - kind_e = pe_order_kind_mandatory; + if (kind == NULL) { + const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); + + kind_e = pe_order_kind_mandatory; - if(score) { - int score_i = char2score(score); - if(score_i == 0) { - kind_e = pe_order_kind_optional; - } + if (score) { + int score_i = char2score(score); - /* } else if(rsc_then->variant == pe_native && rsc_first->variant > pe_group) { */ - /* kind_e = pe_order_kind_optional; */ - } - - } else if(safe_str_eq(kind, "Mandatory")) { - kind_e = pe_order_kind_mandatory; + if (score_i == 0) { + kind_e = pe_order_kind_optional; + } - } else if(safe_str_eq(kind, "Optional")) { - kind_e = pe_order_kind_optional; + /* } else if(rsc_then->variant == pe_native && rsc_first->variant > pe_group) { */ + /* kind_e = pe_order_kind_optional; */ + } - } else if(safe_str_eq(kind, "Serialize")) { - kind_e = pe_order_kind_serialize; + } else if (safe_str_eq(kind, "Mandatory")) { + kind_e = pe_order_kind_mandatory; + + } else if (safe_str_eq(kind, "Optional")) { + kind_e = pe_order_kind_optional; + + } else if (safe_str_eq(kind, "Serialize")) { + kind_e = pe_order_kind_serialize; } else { - const char *id = crm_element_value(xml_obj, XML_ATTR_ID); - crm_config_err("Constraint %s: Unknown type '%s'", id, kind); + const char *id = crm_element_value(xml_obj, XML_ATTR_ID); + + crm_config_err("Constraint %s: Unknown type '%s'", id, kind); } return kind_e; } static gboolean -contains_stonith(resource_t *rsc) +contains_stonith(resource_t * rsc) { GListPtr gIter = rsc->children; - if(gIter == FALSE) { - const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); - if(safe_str_eq(class, "stonith")) { - return TRUE; - } + if (gIter == FALSE) { + const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); + + if (safe_str_eq(class, "stonith")) { + return TRUE; + } } - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - if(contains_stonith(child)) { - return TRUE; - } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + if (contains_stonith(child)) { + return TRUE; + } } return FALSE; } static gboolean -unpack_simple_rsc_order(xmlNode * xml_obj, pe_working_set_t *data_set) +unpack_simple_rsc_order(xmlNode * xml_obj, pe_working_set_t * data_set) { int order_id = 0; resource_t *rsc_then = NULL; resource_t *rsc_first = NULL; gboolean invert_bool = TRUE; enum pe_order_kind kind = pe_order_kind_mandatory; enum pe_ordering cons_weight = pe_order_optional; - const char *id_first = NULL; - const char *id_then = NULL; + const char *id_first = NULL; + const char *id_then = NULL; const char *action_then = NULL; const char *action_first = NULL; const char *instance_then = NULL; const char *instance_first = NULL; - - const char *id = crm_element_value(xml_obj, XML_ATTR_ID); + + const char *id = crm_element_value(xml_obj, XML_ATTR_ID); const char *invert = crm_element_value(xml_obj, XML_CONS_ATTR_SYMMETRICAL); crm_str_to_boolean(invert, &invert_bool); - - if(xml_obj == NULL) { - crm_config_err("No constraint object to process."); - return FALSE; - } else if(id == NULL) { - crm_config_err("%s constraint must have an id", - crm_element_name(xml_obj)); - return FALSE; + if (xml_obj == NULL) { + crm_config_err("No constraint object to process."); + return FALSE; + + } else if (id == NULL) { + crm_config_err("%s constraint must have an id", crm_element_name(xml_obj)); + return FALSE; } - id_then = crm_element_value(xml_obj, XML_ORDER_ATTR_THEN); + id_then = crm_element_value(xml_obj, XML_ORDER_ATTR_THEN); id_first = crm_element_value(xml_obj, XML_ORDER_ATTR_FIRST); - action_then = crm_element_value(xml_obj, XML_ORDER_ATTR_THEN_ACTION); + action_then = crm_element_value(xml_obj, XML_ORDER_ATTR_THEN_ACTION); action_first = crm_element_value(xml_obj, XML_ORDER_ATTR_FIRST_ACTION); instance_then = crm_element_value(xml_obj, XML_ORDER_ATTR_THEN_INSTANCE); instance_first = crm_element_value(xml_obj, XML_ORDER_ATTR_FIRST_INSTANCE); - - if(action_first == NULL) { - action_first = RSC_START; + + if (action_first == NULL) { + action_first = RSC_START; } - if(action_then == NULL) { - action_then = action_first; + if (action_then == NULL) { + action_then = action_first; } - if(id_then == NULL || id_first == NULL) { - crm_config_err("Constraint %s needs two sides lh: %s rh: %s", - id, crm_str(id_then), crm_str(id_first)); - return FALSE; - } + if (id_then == NULL || id_first == NULL) { + crm_config_err("Constraint %s needs two sides lh: %s rh: %s", + id, crm_str(id_then), crm_str(id_first)); + return FALSE; + } rsc_then = pe_find_resource(data_set->resources, id_then); rsc_first = pe_find_resource(data_set->resources, id_first); - if(rsc_then == NULL) { - crm_config_err("Constraint %s: no resource found for name '%s'", id, id_then); - return FALSE; - - } else if(rsc_first == NULL) { - crm_config_err("Constraint %s: no resource found for name '%s'", id, id_first); - return FALSE; - - } else if(instance_then && rsc_then->variant < pe_clone) { - crm_config_err("Invalid constraint '%s':" - " Resource '%s' is not a clone but instance %s was requested", - id, id_then, instance_then); - return FALSE; - - } else if(instance_first && rsc_first->variant < pe_clone) { - crm_config_err("Invalid constraint '%s':" - " Resource '%s' is not a clone but instance %s was requested", - id, id_first, instance_first); - return FALSE; - } - - if(instance_then) { - rsc_then = find_clone_instance(rsc_then, instance_then, data_set); - if(rsc_then == NULL) { - crm_config_warn("Invalid constraint '%s': No instance '%s' of '%s'", id, instance_then, id_then); - return FALSE; - } - } - - if(instance_first) { - rsc_first = find_clone_instance(rsc_first, instance_first, data_set); - if(rsc_first == NULL) { - crm_config_warn("Invalid constraint '%s': No instance '%s' of '%s'", id, instance_first, id_first); - return FALSE; - } - } - - if(safe_str_eq(action_first, RSC_STOP) && contains_stonith(rsc_then)) { - if(contains_stonith(rsc_first) == FALSE) { - crm_config_err("Constraint %s: Ordering STONITH resource (%s) to stop before %s is illegal", - id, rsc_first->id, rsc_then->id); - } - return FALSE; - } - + if (rsc_then == NULL) { + crm_config_err("Constraint %s: no resource found for name '%s'", id, id_then); + return FALSE; + + } else if (rsc_first == NULL) { + crm_config_err("Constraint %s: no resource found for name '%s'", id, id_first); + return FALSE; + + } else if (instance_then && rsc_then->variant < pe_clone) { + crm_config_err("Invalid constraint '%s':" + " Resource '%s' is not a clone but instance %s was requested", + id, id_then, instance_then); + return FALSE; + + } else if (instance_first && rsc_first->variant < pe_clone) { + crm_config_err("Invalid constraint '%s':" + " Resource '%s' is not a clone but instance %s was requested", + id, id_first, instance_first); + return FALSE; + } + + if (instance_then) { + rsc_then = find_clone_instance(rsc_then, instance_then, data_set); + if (rsc_then == NULL) { + crm_config_warn("Invalid constraint '%s': No instance '%s' of '%s'", id, instance_then, + id_then); + return FALSE; + } + } + + if (instance_first) { + rsc_first = find_clone_instance(rsc_first, instance_first, data_set); + if (rsc_first == NULL) { + crm_config_warn("Invalid constraint '%s': No instance '%s' of '%s'", id, instance_first, + id_first); + return FALSE; + } + } + + if (safe_str_eq(action_first, RSC_STOP) && contains_stonith(rsc_then)) { + if (contains_stonith(rsc_first) == FALSE) { + crm_config_err + ("Constraint %s: Ordering STONITH resource (%s) to stop before %s is illegal", id, + rsc_first->id, rsc_then->id); + } + return FALSE; + } + cons_weight = pe_order_optional; kind = get_ordering_type(xml_obj); - - if(kind == pe_order_kind_optional && rsc_then->restart_type == pe_restart_restart) { - crm_debug_2("Upgrade : recovery - implies right"); - cons_weight |= pe_order_implies_then; + + if (kind == pe_order_kind_optional && rsc_then->restart_type == pe_restart_restart) { + crm_debug_2("Upgrade : recovery - implies right"); + cons_weight |= pe_order_implies_then; } cons_weight |= get_flags(id, kind, action_first, action_then, FALSE); - order_id = new_rsc_order( - rsc_first, action_first, rsc_then, action_then, cons_weight, data_set); + order_id = new_rsc_order(rsc_first, action_first, rsc_then, action_then, cons_weight, data_set); crm_debug_2("order-%d (%s): %s_%s before %s_%s flags=0x%.6x", - order_id, id, rsc_first->id, action_first, rsc_then->id, action_then, - cons_weight); - - - if(invert_bool == FALSE) { - return TRUE; + order_id, id, rsc_first->id, action_first, rsc_then->id, action_then, cons_weight); + + if (invert_bool == FALSE) { + return TRUE; - } else if(invert && kind == pe_order_kind_serialize) { - crm_config_warn("Cannot invert serialized constraint set %s", id); - return TRUE; + } else if (invert && kind == pe_order_kind_serialize) { + crm_config_warn("Cannot invert serialized constraint set %s", id); + return TRUE; - } else if(kind == pe_order_kind_serialize) { - return TRUE; + } else if (kind == pe_order_kind_serialize) { + return TRUE; } - + action_then = invert_action(action_then); action_first = invert_action(action_first); - if(action_then == NULL || action_first == NULL) { - crm_config_err("Cannot invert rsc_order constraint %s." - " Please specify the inverse manually.", id); - return TRUE; - } - - if(safe_str_eq(action_first, RSC_STOP) && contains_stonith(rsc_then)) { - if(contains_stonith(rsc_first) == FALSE) { - crm_config_err("Constraint %s: Ordering STONITH resource (%s) to stop before %s is illegal", - id, rsc_first->id, rsc_then->id); - } - return FALSE; - } - + if (action_then == NULL || action_first == NULL) { + crm_config_err("Cannot invert rsc_order constraint %s." + " Please specify the inverse manually.", id); + return TRUE; + } + + if (safe_str_eq(action_first, RSC_STOP) && contains_stonith(rsc_then)) { + if (contains_stonith(rsc_first) == FALSE) { + crm_config_err + ("Constraint %s: Ordering STONITH resource (%s) to stop before %s is illegal", id, + rsc_first->id, rsc_then->id); + } + return FALSE; + } + cons_weight = pe_order_optional; - if(kind == pe_order_kind_optional && rsc_then->restart_type == pe_restart_restart) { - crm_debug_2("Upgrade : recovery - implies left"); - cons_weight |= pe_order_implies_first; + if (kind == pe_order_kind_optional && rsc_then->restart_type == pe_restart_restart) { + crm_debug_2("Upgrade : recovery - implies left"); + cons_weight |= pe_order_implies_first; } cons_weight |= get_flags(id, kind, action_first, action_then, TRUE); - order_id = new_rsc_order( - rsc_then, action_then, rsc_first, action_first, cons_weight, data_set); + order_id = new_rsc_order(rsc_then, action_then, rsc_first, action_first, cons_weight, data_set); crm_debug_2("order-%d (%s): %s_%s before %s_%s flags=0x%.6x", - order_id, id, rsc_then->id, action_then, rsc_first->id, action_first, - cons_weight); - + order_id, id, rsc_then->id, action_then, rsc_first->id, action_first, cons_weight); + return TRUE; } gboolean -unpack_rsc_location(xmlNode * xml_obj, pe_working_set_t *data_set) +unpack_rsc_location(xmlNode * xml_obj, pe_working_set_t * data_set) { gboolean empty = TRUE; rsc_to_node_t *location = NULL; - const char *id_lh = crm_element_value(xml_obj, "rsc"); - const char *id = crm_element_value(xml_obj, XML_ATTR_ID); - resource_t *rsc_lh = pe_find_resource(data_set->resources, id_lh); - const char *node = crm_element_value(xml_obj, "node"); - const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); - const char *domain = crm_element_value(xml_obj, XML_CIB_TAG_DOMAIN); - const char *role = crm_element_value(xml_obj, XML_RULE_ATTR_ROLE); - - if(rsc_lh == NULL) { - /* only a warn as BSC adds the constraint then the resource */ - crm_config_warn("No resource (con=%s, rsc=%s)", id, id_lh); - return FALSE; - } - - if(domain) { - GListPtr nodes = g_hash_table_lookup(data_set->domains, domain); - - if(domain == NULL) { - crm_config_err("Invalid constraint %s: Domain %s does not exist", - id, domain); - return FALSE; - } - - location = rsc2node_new(id, rsc_lh, 0, NULL, data_set); - location->node_list_rh = node_list_dup(nodes, FALSE, FALSE); - - } else if(node != NULL && score != NULL) { - int score_i = char2score(score); - node_t *match = pe_find_node(data_set->nodes, node); - - if(!match) { - return FALSE; - } - location = rsc2node_new(id, rsc_lh, score_i, match, data_set); + const char *id_lh = crm_element_value(xml_obj, "rsc"); + const char *id = crm_element_value(xml_obj, XML_ATTR_ID); + resource_t *rsc_lh = pe_find_resource(data_set->resources, id_lh); + const char *node = crm_element_value(xml_obj, "node"); + const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); + const char *domain = crm_element_value(xml_obj, XML_CIB_TAG_DOMAIN); + const char *role = crm_element_value(xml_obj, XML_RULE_ATTR_ROLE); + + if (rsc_lh == NULL) { + /* only a warn as BSC adds the constraint then the resource */ + crm_config_warn("No resource (con=%s, rsc=%s)", id, id_lh); + return FALSE; + } + + if (domain) { + GListPtr nodes = g_hash_table_lookup(data_set->domains, domain); + + if (domain == NULL) { + crm_config_err("Invalid constraint %s: Domain %s does not exist", id, domain); + return FALSE; + } + + location = rsc2node_new(id, rsc_lh, 0, NULL, data_set); + location->node_list_rh = node_list_dup(nodes, FALSE, FALSE); + + } else if (node != NULL && score != NULL) { + int score_i = char2score(score); + node_t *match = pe_find_node(data_set->nodes, node); + + if (!match) { + return FALSE; + } + location = rsc2node_new(id, rsc_lh, score_i, match, data_set); } else { - xmlNode *rule_xml = NULL; - for(rule_xml = __xml_first_child(xml_obj); rule_xml != NULL; rule_xml = __xml_next(rule_xml)) { - if(crm_str_eq((const char *)rule_xml->name, XML_TAG_RULE, TRUE)) { - empty = FALSE; - crm_debug_2("Unpacking %s/%s", id, ID(rule_xml)); - generate_location_rule(rsc_lh, rule_xml, data_set); - } - } - - if(empty) { - crm_config_err("Invalid location constraint %s:" - " rsc_location must contain at least one rule", - ID(xml_obj)); - } - } - - if(location && role) { - if(text2role(role) == RSC_ROLE_UNKNOWN) { - pe_err("Invalid constraint %s: Bad role %s", id, role); - return FALSE; - - } else { - location->role_filter = text2role(role); - if(location->role_filter == RSC_ROLE_SLAVE) { - /* Fold slave back into Started for simplicity - * At the point Slave location constraints are evaluated, - * all resources are still either stopped or started - */ - location->role_filter = RSC_ROLE_STARTED; - } - } - } - return TRUE; + xmlNode *rule_xml = NULL; + + for (rule_xml = __xml_first_child(xml_obj); rule_xml != NULL; + rule_xml = __xml_next(rule_xml)) { + if (crm_str_eq((const char *)rule_xml->name, XML_TAG_RULE, TRUE)) { + empty = FALSE; + crm_debug_2("Unpacking %s/%s", id, ID(rule_xml)); + generate_location_rule(rsc_lh, rule_xml, data_set); + } + } + + if (empty) { + crm_config_err("Invalid location constraint %s:" + " rsc_location must contain at least one rule", ID(xml_obj)); + } + } + + if (location && role) { + if (text2role(role) == RSC_ROLE_UNKNOWN) { + pe_err("Invalid constraint %s: Bad role %s", id, role); + return FALSE; + + } else { + location->role_filter = text2role(role); + if (location->role_filter == RSC_ROLE_SLAVE) { + /* Fold slave back into Started for simplicity + * At the point Slave location constraints are evaluated, + * all resources are still either stopped or started + */ + location->role_filter = RSC_ROLE_STARTED; + } + } + } + return TRUE; } static int -get_node_score(const char *rule, const char *score, gboolean raw, node_t *node) +get_node_score(const char *rule, const char *score, gboolean raw, node_t * node) { int score_f = 0; - if(score == NULL) { - pe_err("Rule %s: no score specified. Assuming 0.", rule); - - } else if(raw) { - score_f = char2score(score); - + + if (score == NULL) { + pe_err("Rule %s: no score specified. Assuming 0.", rule); + + } else if (raw) { + score_f = char2score(score); + } else { - const char *attr_score = g_hash_table_lookup( - node->details->attrs, score); - if(attr_score == NULL) { - crm_debug("Rule %s: node %s did not have a value for %s", - rule, node->details->uname, score); - score_f = -INFINITY; - - } else { - crm_debug("Rule %s: node %s had value %s for %s", - rule, node->details->uname, attr_score, score); - score_f = char2score(attr_score); - } + const char *attr_score = g_hash_table_lookup(node->details->attrs, score); + + if (attr_score == NULL) { + crm_debug("Rule %s: node %s did not have a value for %s", + rule, node->details->uname, score); + score_f = -INFINITY; + + } else { + crm_debug("Rule %s: node %s had value %s for %s", + rule, node->details->uname, attr_score, score); + score_f = char2score(attr_score); + } } return score_f; } - rsc_to_node_t * -generate_location_rule( - resource_t *rsc, xmlNode *rule_xml, pe_working_set_t *data_set) -{ +generate_location_rule(resource_t * rsc, xmlNode * rule_xml, pe_working_set_t * data_set) +{ const char *rule_id = NULL; - const char *score = NULL; + const char *score = NULL; const char *boolean = NULL; - const char *role = NULL; + const char *role = NULL; GListPtr gIter = NULL; - GListPtr match_L = NULL; - - int score_f = 0; + GListPtr match_L = NULL; + + int score_f = 0; gboolean do_and = TRUE; gboolean accept = TRUE; gboolean raw_score = TRUE; - + rsc_to_node_t *location_rule = NULL; - + rule_xml = expand_idref(rule_xml, data_set->input); rule_id = crm_element_value(rule_xml, XML_ATTR_ID); boolean = crm_element_value(rule_xml, XML_RULE_ATTR_BOOLEAN_OP); role = crm_element_value(rule_xml, XML_RULE_ATTR_ROLE); crm_debug_2("Processing rule: %s", rule_id); - if(role != NULL && text2role(role) == RSC_ROLE_UNKNOWN) { - pe_err("Bad role specified for %s: %s", rule_id, role); - return NULL; + if (role != NULL && text2role(role) == RSC_ROLE_UNKNOWN) { + pe_err("Bad role specified for %s: %s", rule_id, role); + return NULL; } - + score = crm_element_value(rule_xml, XML_RULE_ATTR_SCORE); - if(score != NULL) { - score_f = char2score(score); - + if (score != NULL) { + score_f = char2score(score); + } else { - score = crm_element_value( - rule_xml, XML_RULE_ATTR_SCORE_ATTRIBUTE); - if(score == NULL) { - score = crm_element_value( - rule_xml, XML_RULE_ATTR_SCORE_MANGLED); - } - if(score != NULL) { - raw_score = FALSE; - } - } - if(safe_str_eq(boolean, "or")) { - do_and = FALSE; - } - + score = crm_element_value(rule_xml, XML_RULE_ATTR_SCORE_ATTRIBUTE); + if (score == NULL) { + score = crm_element_value(rule_xml, XML_RULE_ATTR_SCORE_MANGLED); + } + if (score != NULL) { + raw_score = FALSE; + } + } + if (safe_str_eq(boolean, "or")) { + do_and = FALSE; + } + location_rule = rsc2node_new(rule_id, rsc, 0, NULL, data_set); - - if(location_rule == NULL) { - return NULL; - } - if(role != NULL) { - crm_debug_2("Setting role filter: %s", role); - location_rule->role_filter = text2role(role); - if(location_rule->role_filter == RSC_ROLE_SLAVE) { - /* Fold slave back into Started for simplicity - * At the point Slave location constraints are evaluated, - * all resources are still either stopped or started - */ - location_rule->role_filter = RSC_ROLE_STARTED; - } - } - if(do_and) { - GListPtr gIter = NULL; - match_L = node_list_dup(data_set->nodes, TRUE, FALSE); - for(gIter = match_L; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - node->weight = get_node_score(rule_id, score, raw_score, node); - } - } - - for(gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - - accept = test_rule( - rule_xml, node->details->attrs, RSC_ROLE_UNKNOWN, data_set->now); - - crm_debug_2("Rule %s %s on %s", ID(rule_xml), accept?"passed":"failed", node->details->uname); - - score_f = get_node_score(rule_id, score, raw_score, node); + + if (location_rule == NULL) { + return NULL; + } + if (role != NULL) { + crm_debug_2("Setting role filter: %s", role); + location_rule->role_filter = text2role(role); + if (location_rule->role_filter == RSC_ROLE_SLAVE) { + /* Fold slave back into Started for simplicity + * At the point Slave location constraints are evaluated, + * all resources are still either stopped or started + */ + location_rule->role_filter = RSC_ROLE_STARTED; + } + } + if (do_and) { + GListPtr gIter = NULL; + + match_L = node_list_dup(data_set->nodes, TRUE, FALSE); + for (gIter = match_L; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + node->weight = get_node_score(rule_id, score, raw_score, node); + } + } + + for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + accept = test_rule(rule_xml, node->details->attrs, RSC_ROLE_UNKNOWN, data_set->now); + + crm_debug_2("Rule %s %s on %s", ID(rule_xml), accept ? "passed" : "failed", + node->details->uname); + + score_f = get_node_score(rule_id, score, raw_score, node); /* if(accept && score_f == -INFINITY) { */ /* accept = FALSE; */ /* } */ - - if(accept) { - node_t *local = pe_find_node_id(match_L, node->details->id); - if(local == NULL && do_and) { - continue; - - } else if(local == NULL) { - local = node_copy(node); - match_L = g_list_append(match_L, local); - } - - if(do_and == FALSE) { - local->weight = merge_weights(local->weight, score_f); - } - crm_debug_2("node %s now has weight %d", - node->details->uname, local->weight); - - } else if(do_and && !accept) { - /* remove it */ - node_t *delete = pe_find_node_id(match_L, node->details->id); - if(delete != NULL) { - match_L = g_list_remove(match_L,delete); - crm_debug_5("node %s did not match", - node->details->uname); - } - crm_free(delete); - } - } - + + if (accept) { + node_t *local = pe_find_node_id(match_L, node->details->id); + + if (local == NULL && do_and) { + continue; + + } else if (local == NULL) { + local = node_copy(node); + match_L = g_list_append(match_L, local); + } + + if (do_and == FALSE) { + local->weight = merge_weights(local->weight, score_f); + } + crm_debug_2("node %s now has weight %d", node->details->uname, local->weight); + + } else if (do_and && !accept) { + /* remove it */ + node_t *delete = pe_find_node_id(match_L, node->details->id); + + if (delete != NULL) { + match_L = g_list_remove(match_L, delete); + crm_debug_5("node %s did not match", node->details->uname); + } + crm_free(delete); + } + } + location_rule->node_list_rh = match_L; - if(location_rule->node_list_rh == NULL) { - crm_debug_2("No matching nodes for rule %s", rule_id); - return NULL; - } + if (location_rule->node_list_rh == NULL) { + crm_debug_2("No matching nodes for rule %s", rule_id); + return NULL; + } - crm_debug_3("%s: %d nodes matched", - rule_id, g_list_length(location_rule->node_list_rh)); + crm_debug_3("%s: %d nodes matched", rule_id, g_list_length(location_rule->node_list_rh)); return location_rule; } -static gint sort_cons_priority_lh(gconstpointer a, gconstpointer b) +static gint +sort_cons_priority_lh(gconstpointer a, gconstpointer b) { - const rsc_colocation_t *rsc_constraint1 = (const rsc_colocation_t*)a; - const rsc_colocation_t *rsc_constraint2 = (const rsc_colocation_t*)b; + const rsc_colocation_t *rsc_constraint1 = (const rsc_colocation_t *)a; + const rsc_colocation_t *rsc_constraint2 = (const rsc_colocation_t *)b; - if(a == NULL) { return 1; } - if(b == NULL) { return -1; } + if (a == NULL) { + return 1; + } + if (b == NULL) { + return -1; + } CRM_ASSERT(rsc_constraint1->rsc_lh != NULL); CRM_ASSERT(rsc_constraint1->rsc_rh != NULL); - - if(rsc_constraint1->rsc_lh->priority > rsc_constraint2->rsc_lh->priority) { - return -1; + + if (rsc_constraint1->rsc_lh->priority > rsc_constraint2->rsc_lh->priority) { + return -1; } - - if(rsc_constraint1->rsc_lh->priority < rsc_constraint2->rsc_lh->priority) { - return 1; + + if (rsc_constraint1->rsc_lh->priority < rsc_constraint2->rsc_lh->priority) { + return 1; } return strcmp(rsc_constraint1->rsc_lh->id, rsc_constraint2->rsc_lh->id); } -static gint sort_cons_priority_rh(gconstpointer a, gconstpointer b) +static gint +sort_cons_priority_rh(gconstpointer a, gconstpointer b) { - const rsc_colocation_t *rsc_constraint1 = (const rsc_colocation_t*)a; - const rsc_colocation_t *rsc_constraint2 = (const rsc_colocation_t*)b; + const rsc_colocation_t *rsc_constraint1 = (const rsc_colocation_t *)a; + const rsc_colocation_t *rsc_constraint2 = (const rsc_colocation_t *)b; - if(a == NULL) { return 1; } - if(b == NULL) { return -1; } + if (a == NULL) { + return 1; + } + if (b == NULL) { + return -1; + } CRM_ASSERT(rsc_constraint1->rsc_lh != NULL); CRM_ASSERT(rsc_constraint1->rsc_rh != NULL); - - if(rsc_constraint1->rsc_rh->priority > rsc_constraint2->rsc_rh->priority) { - return -1; + + if (rsc_constraint1->rsc_rh->priority > rsc_constraint2->rsc_rh->priority) { + return -1; } - - if(rsc_constraint1->rsc_rh->priority < rsc_constraint2->rsc_rh->priority) { - return 1; + + if (rsc_constraint1->rsc_rh->priority < rsc_constraint2->rsc_rh->priority) { + return 1; } return strcmp(rsc_constraint1->rsc_rh->id, rsc_constraint2->rsc_rh->id); } gboolean rsc_colocation_new(const char *id, const char *node_attr, int score, - resource_t *rsc_lh, resource_t *rsc_rh, - const char *state_lh, const char *state_rh, - pe_working_set_t *data_set) + resource_t * rsc_lh, resource_t * rsc_rh, + const char *state_lh, const char *state_rh, pe_working_set_t * data_set) { - rsc_colocation_t *new_con = NULL; - if(rsc_lh == NULL){ - crm_config_err("No resource found for LHS %s", id); - return FALSE; + rsc_colocation_t *new_con = NULL; + + if (rsc_lh == NULL) { + crm_config_err("No resource found for LHS %s", id); + return FALSE; - } else if(rsc_rh == NULL){ - crm_config_err("No resource found for RHS of %s", id); - return FALSE; + } else if (rsc_rh == NULL) { + crm_config_err("No resource found for RHS of %s", id); + return FALSE; } crm_malloc0(new_con, sizeof(rsc_colocation_t)); - if(new_con == NULL) { - return FALSE; + if (new_con == NULL) { + return FALSE; } - if(state_lh == NULL - || safe_str_eq(state_lh, RSC_ROLE_STARTED_S)) { - state_lh = RSC_ROLE_UNKNOWN_S; + if (state_lh == NULL || safe_str_eq(state_lh, RSC_ROLE_STARTED_S)) { + state_lh = RSC_ROLE_UNKNOWN_S; } - if(state_rh == NULL - || safe_str_eq(state_rh, RSC_ROLE_STARTED_S)) { - state_rh = RSC_ROLE_UNKNOWN_S; - } + if (state_rh == NULL || safe_str_eq(state_rh, RSC_ROLE_STARTED_S)) { + state_rh = RSC_ROLE_UNKNOWN_S; + } - new_con->id = id; - new_con->rsc_lh = rsc_lh; - new_con->rsc_rh = rsc_rh; - new_con->score = score; + new_con->id = id; + new_con->rsc_lh = rsc_lh; + new_con->rsc_rh = rsc_rh; + new_con->score = score; new_con->role_lh = text2role(state_lh); new_con->role_rh = text2role(state_rh); new_con->node_attribute = node_attr; - if(node_attr == NULL) { - node_attr = "#"XML_ATTR_UNAME; + if (node_attr == NULL) { + node_attr = "#" XML_ATTR_UNAME; } - + crm_debug_3("%s ==> %s (%s %d)", rsc_lh->id, rsc_rh->id, node_attr, score); - - rsc_lh->rsc_cons = g_list_insert_sorted( - rsc_lh->rsc_cons, new_con, sort_cons_priority_rh); - rsc_rh->rsc_cons_lhs = g_list_insert_sorted( - rsc_rh->rsc_cons_lhs, new_con, sort_cons_priority_lh); + rsc_lh->rsc_cons = g_list_insert_sorted(rsc_lh->rsc_cons, new_con, sort_cons_priority_rh); + + rsc_rh->rsc_cons_lhs = + g_list_insert_sorted(rsc_rh->rsc_cons_lhs, new_con, sort_cons_priority_lh); + + data_set->colocation_constraints = g_list_append(data_set->colocation_constraints, new_con); - data_set->colocation_constraints = g_list_append( - data_set->colocation_constraints, new_con); - return TRUE; } /* LHS before RHS */ int -new_rsc_order(resource_t *lh_rsc, const char *lh_task, - resource_t *rh_rsc, const char *rh_task, - enum pe_ordering type, pe_working_set_t *data_set) +new_rsc_order(resource_t * lh_rsc, const char *lh_task, + resource_t * rh_rsc, const char *rh_task, + enum pe_ordering type, pe_working_set_t * data_set) { char *lh_key = NULL; char *rh_key = NULL; - CRM_CHECK(lh_rsc != NULL, return -1); + CRM_CHECK(lh_rsc != NULL, return -1); CRM_CHECK(lh_task != NULL, return -1); - CRM_CHECK(rh_rsc != NULL, return -1); + CRM_CHECK(rh_rsc != NULL, return -1); CRM_CHECK(rh_task != NULL, return -1); - + lh_key = generate_op_key(lh_rsc->id, lh_task, 0); rh_key = generate_op_key(rh_rsc->id, rh_task, 0); - - return custom_action_order(lh_rsc, lh_key, NULL, - rh_rsc, rh_key, NULL, type, data_set); + + return custom_action_order(lh_rsc, lh_key, NULL, rh_rsc, rh_key, NULL, type, data_set); } /* LHS before RHS */ int -custom_action_order( - resource_t *lh_rsc, char *lh_action_task, action_t *lh_action, - resource_t *rh_rsc, char *rh_action_task, action_t *rh_action, - enum pe_ordering type, pe_working_set_t *data_set) +custom_action_order(resource_t * lh_rsc, char *lh_action_task, action_t * lh_action, + resource_t * rh_rsc, char *rh_action_task, action_t * rh_action, + enum pe_ordering type, pe_working_set_t * data_set) { order_constraint_t *order = NULL; - if(lh_rsc == NULL && lh_action) { - lh_rsc = lh_action->rsc; + + if (lh_rsc == NULL && lh_action) { + lh_rsc = lh_action->rsc; } - if(rh_rsc == NULL && rh_action) { - rh_rsc = rh_action->rsc; + if (rh_rsc == NULL && rh_action) { + rh_rsc = rh_action->rsc; } - if((lh_action == NULL && lh_rsc == NULL) - || (rh_action == NULL && rh_rsc == NULL)){ - crm_config_err("Invalid inputs %p.%p %p.%p", - lh_rsc, lh_action, rh_rsc, rh_action); - crm_free(lh_action_task); - crm_free(rh_action_task); - return -1; + if ((lh_action == NULL && lh_rsc == NULL) + || (rh_action == NULL && rh_rsc == NULL)) { + crm_config_err("Invalid inputs %p.%p %p.%p", lh_rsc, lh_action, rh_rsc, rh_action); + crm_free(lh_action_task); + crm_free(rh_action_task); + return -1; } - + crm_malloc0(order, sizeof(order_constraint_t)); - order->id = data_set->order_id++; - order->type = type; - order->lh_rsc = lh_rsc; - order->rh_rsc = rh_rsc; - order->lh_action = lh_action; - order->rh_action = rh_action; + order->id = data_set->order_id++; + order->type = type; + order->lh_rsc = lh_rsc; + order->rh_rsc = rh_rsc; + order->lh_action = lh_action; + order->rh_action = rh_action; order->lh_action_task = lh_action_task; order->rh_action_task = rh_action_task; - if(order->lh_action_task == NULL && lh_action) { - order->lh_action_task = crm_strdup(lh_action->uuid); + if (order->lh_action_task == NULL && lh_action) { + order->lh_action_task = crm_strdup(lh_action->uuid); } - - if(order->rh_action_task == NULL && rh_action) { - order->rh_action_task = crm_strdup(rh_action->uuid); + + if (order->rh_action_task == NULL && rh_action) { + order->rh_action_task = crm_strdup(rh_action->uuid); } - - if(order->lh_rsc == NULL && lh_action) { - order->lh_rsc = lh_action->rsc; + + if (order->lh_rsc == NULL && lh_action) { + order->lh_rsc = lh_action->rsc; } - if(order->rh_rsc == NULL && rh_action) { - order->rh_rsc = rh_action->rsc; + if (order->rh_rsc == NULL && rh_action) { + order->rh_rsc = rh_action->rsc; } - - data_set->ordering_constraints = g_list_prepend( - data_set->ordering_constraints, order); - + + data_set->ordering_constraints = g_list_prepend(data_set->ordering_constraints, order); + return order->id; } -enum pe_ordering get_flags( - const char *id, enum pe_order_kind kind, - const char *action_first, const char *action_then, gboolean invert) { +enum pe_ordering +get_flags(const char *id, enum pe_order_kind kind, + const char *action_first, const char *action_then, gboolean invert) +{ enum pe_ordering flags = pe_order_optional; - if(invert && kind == pe_order_kind_mandatory) { - crm_debug_2("Upgrade %s: implies left", id); - flags |= pe_order_implies_first; - - } else if(kind == pe_order_kind_mandatory) { - crm_debug_2("Upgrade %s: implies right", id); - flags |= pe_order_implies_then; - if(safe_str_eq(action_first, RSC_START) - || safe_str_eq(action_first, RSC_PROMOTE)) { - crm_debug_2("Upgrade %s: runnable", id); - flags |= pe_order_runnable_left; - } - - } else if(kind == pe_order_kind_serialize) { - flags |= pe_order_serialize_only; - } - + if (invert && kind == pe_order_kind_mandatory) { + crm_debug_2("Upgrade %s: implies left", id); + flags |= pe_order_implies_first; + + } else if (kind == pe_order_kind_mandatory) { + crm_debug_2("Upgrade %s: implies right", id); + flags |= pe_order_implies_then; + if (safe_str_eq(action_first, RSC_START) + || safe_str_eq(action_first, RSC_PROMOTE)) { + crm_debug_2("Upgrade %s: runnable", id); + flags |= pe_order_runnable_left; + } + + } else if (kind == pe_order_kind_serialize) { + flags |= pe_order_serialize_only; + } + return flags; } - static gboolean -unpack_order_set(xmlNode *set, enum pe_order_kind kind, resource_t **rsc, - action_t **begin, action_t **end, action_t **inv_begin, action_t **inv_end, - const char *symmetrical, pe_working_set_t *data_set) +unpack_order_set(xmlNode * set, enum pe_order_kind kind, resource_t ** rsc, + action_t ** begin, action_t ** end, action_t ** inv_begin, action_t ** inv_end, + const char *symmetrical, pe_working_set_t * data_set) { xmlNode *xml_rsc = NULL; GListPtr set_iter = NULL; GListPtr resources = NULL; - + resource_t *last = NULL; resource_t *resource = NULL; int local_kind = kind; gboolean sequential = FALSE; enum pe_ordering flags = pe_order_optional; - + char *key = NULL; const char *id = ID(set); const char *action = crm_element_value(set, "action"); const char *sequential_s = crm_element_value(set, "sequential"); const char *kind_s = crm_element_value(set, XML_ORDER_ATTR_KIND); /* - char *pseudo_id = NULL; - char *end_id = NULL; - char *begin_id = NULL; - */ + char *pseudo_id = NULL; + char *end_id = NULL; + char *begin_id = NULL; + */ - if(action == NULL) { - action = RSC_START; + if (action == NULL) { + action = RSC_START; } - if(kind_s) { - local_kind = get_ordering_type(set); + if (kind_s) { + local_kind = get_ordering_type(set); } - if(sequential_s == NULL) { - sequential_s = "1"; + if (sequential_s == NULL) { + sequential_s = "1"; } - + sequential = crm_is_true(sequential_s); flags = get_flags(id, local_kind, action, action, FALSE); - for(xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(id, resource, ID(xml_rsc)); - resources = g_list_append(resources, resource); - } + for (xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(id, resource, ID(xml_rsc)); + resources = g_list_append(resources, resource); + } } - if(g_list_length(resources) == 1) { - crm_debug_2("Single set: %s", id); - *rsc = resource; - *end = NULL; - *begin = NULL; - *inv_end = NULL; - *inv_begin = NULL; - goto done; + if (g_list_length(resources) == 1) { + crm_debug_2("Single set: %s", id); + *rsc = resource; + *end = NULL; + *begin = NULL; + *inv_end = NULL; + *inv_begin = NULL; + goto done; } /* - pseudo_id = crm_concat(id, action, '-'); - end_id = crm_concat(pseudo_id, "end", '-'); - begin_id = crm_concat(pseudo_id, "begin", '-'); - */ + pseudo_id = crm_concat(id, action, '-'); + end_id = crm_concat(pseudo_id, "end", '-'); + begin_id = crm_concat(pseudo_id, "begin", '-'); + */ *rsc = NULL; /* *end = get_pseudo_op(end_id, data_set); *begin = get_pseudo_op(begin_id, data_set); crm_free(pseudo_id); crm_free(begin_id); crm_free(end_id); - */ - + */ + set_iter = resources; - while(set_iter != NULL) { - resource = (resource_t *) set_iter->data; - set_iter = set_iter->next; - - key = generate_op_key(resource->id, action, 0); - - /* - custom_action_order(NULL, NULL, *begin, resource, crm_strdup(key), NULL, - flags|pe_order_implies_first_printed, data_set); - - custom_action_order(resource, crm_strdup(key), NULL, NULL, NULL, *end, - flags|pe_order_implies_then_printed, data_set); - */ - - if(local_kind == pe_order_kind_serialize) { - /* Serialize before everything that comes after */ - - GListPtr gIter = NULL; - for(gIter = set_iter; gIter != NULL; gIter = gIter->next) { - resource_t *then_rsc = (resource_t*)gIter->data; - char *then_key = generate_op_key(then_rsc->id, action, 0); - custom_action_order(resource, crm_strdup(key), NULL, then_rsc, then_key, NULL, - flags, data_set); - } - - } else if(sequential) { - if(last != NULL) { - new_rsc_order(last, action, resource, action, flags, data_set); - } - last = resource; - } - crm_free(key); - } - - if(crm_is_true(symmetrical) == FALSE) { - goto done; - - } else if(symmetrical && local_kind == pe_order_kind_serialize) { - crm_config_warn("Cannot invert serialized constraint set %s", id); - goto done; - - } else if(local_kind == pe_order_kind_serialize) { - goto done; - } - + while (set_iter != NULL) { + resource = (resource_t *) set_iter->data; + set_iter = set_iter->next; + + key = generate_op_key(resource->id, action, 0); + + /* + custom_action_order(NULL, NULL, *begin, resource, crm_strdup(key), NULL, + flags|pe_order_implies_first_printed, data_set); + + custom_action_order(resource, crm_strdup(key), NULL, NULL, NULL, *end, + flags|pe_order_implies_then_printed, data_set); + */ + + if (local_kind == pe_order_kind_serialize) { + /* Serialize before everything that comes after */ + + GListPtr gIter = NULL; + + for (gIter = set_iter; gIter != NULL; gIter = gIter->next) { + resource_t *then_rsc = (resource_t *) gIter->data; + char *then_key = generate_op_key(then_rsc->id, action, 0); + + custom_action_order(resource, crm_strdup(key), NULL, then_rsc, then_key, NULL, + flags, data_set); + } + + } else if (sequential) { + if (last != NULL) { + new_rsc_order(last, action, resource, action, flags, data_set); + } + last = resource; + } + crm_free(key); + } + + if (crm_is_true(symmetrical) == FALSE) { + goto done; + + } else if (symmetrical && local_kind == pe_order_kind_serialize) { + crm_config_warn("Cannot invert serialized constraint set %s", id); + goto done; + + } else if (local_kind == pe_order_kind_serialize) { + goto done; + } last = NULL; action = invert_action(action); - + /* - pseudo_id = crm_concat(id, action, '-'); - end_id = crm_concat(pseudo_id, "end", '-'); - begin_id = crm_concat(pseudo_id, "begin", '-'); - - *inv_end = get_pseudo_op(end_id, data_set); - *inv_begin = get_pseudo_op(begin_id, data_set); - - crm_free(pseudo_id); - crm_free(begin_id); - crm_free(end_id); - */ - + pseudo_id = crm_concat(id, action, '-'); + end_id = crm_concat(pseudo_id, "end", '-'); + begin_id = crm_concat(pseudo_id, "begin", '-'); + + *inv_end = get_pseudo_op(end_id, data_set); + *inv_begin = get_pseudo_op(begin_id, data_set); + + crm_free(pseudo_id); + crm_free(begin_id); + crm_free(end_id); + */ + flags = get_flags(id, local_kind, action, action, TRUE); set_iter = resources; - while(set_iter != NULL) { - resource = (resource_t *) set_iter->data; - set_iter = set_iter->next; + while (set_iter != NULL) { + resource = (resource_t *) set_iter->data; + set_iter = set_iter->next; - /* - key = generate_op_key(resource->id, action, 0); + /* + key = generate_op_key(resource->id, action, 0); - custom_action_order(NULL, NULL, *inv_begin, resource, crm_strdup(key), NULL, - flags|pe_order_implies_first_printed, data_set); + custom_action_order(NULL, NULL, *inv_begin, resource, crm_strdup(key), NULL, + flags|pe_order_implies_first_printed, data_set); - custom_action_order(resource, key, NULL, NULL, NULL, *inv_end, - flags|pe_order_implies_then_printed, data_set); - */ - - if(sequential) { - if(last != NULL) { - new_rsc_order(resource, action, last, action, flags, data_set); - } - last = resource; - } + custom_action_order(resource, key, NULL, NULL, NULL, *inv_end, + flags|pe_order_implies_then_printed, data_set); + */ + + if (sequential) { + if (last != NULL) { + new_rsc_order(resource, action, last, action, flags, data_set); + } + last = resource; + } } done: g_list_free(resources); return TRUE; } -static gboolean order_rsc_sets( - const char *id, xmlNode *set1, xmlNode *set2, enum pe_order_kind kind, pe_working_set_t *data_set, gboolean invert) { - +static gboolean +order_rsc_sets(const char *id, xmlNode * set1, xmlNode * set2, enum pe_order_kind kind, + pe_working_set_t * data_set, gboolean invert) +{ + xmlNode *xml_rsc = NULL; resource_t *rsc_1 = NULL; resource_t *rsc_2 = NULL; - + const char *action_1 = crm_element_value(set1, "action"); const char *action_2 = crm_element_value(set2, "action"); const char *sequential_1 = crm_element_value(set1, "sequential"); const char *sequential_2 = crm_element_value(set2, "sequential"); enum pe_ordering flags = pe_order_none; if (action_1 == NULL) { - action_1 = RSC_START; + action_1 = RSC_START; }; if (action_2 == NULL) { - action_2 = RSC_START; + action_2 = RSC_START; }; if (invert == FALSE) { - flags = get_flags(id, kind, action_1, action_2, FALSE); + flags = get_flags(id, kind, action_1, action_2, FALSE); } else { - action_1 = invert_action(action_1); - action_2 = invert_action(action_2); - flags = get_flags(id, kind, action_2, action_1, TRUE); - } - - if(crm_is_true(sequential_1)) { - if(invert == FALSE) { - /* get the last one */ - const char *rid = NULL; - for(xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - rid = ID(xml_rsc); - } - } - EXPAND_CONSTRAINT_IDREF(id, rsc_1, rid); - - } else { - /* get the first one */ - for(xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); - break; - } - } - } - } - - if(crm_is_true(sequential_2)) { - if(invert == FALSE) { - /* get the first one */ - for(xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc)); - break; - } - } - - } else { - /* get the last one */ - const char *rid = NULL; - for(xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - rid = ID(xml_rsc); - } - } - EXPAND_CONSTRAINT_IDREF(id, rsc_2, rid); - } - } - - if(rsc_1 != NULL && rsc_2 != NULL) { - new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set); - - } else if(rsc_1 != NULL) { - for(xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc)); - new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set); - } - } - - } else if(rsc_2 != NULL) { - xmlNode *xml_rsc = NULL; - for(xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); - new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set); - } - } + action_1 = invert_action(action_1); + action_2 = invert_action(action_2); + flags = get_flags(id, kind, action_2, action_1, TRUE); + } + + if (crm_is_true(sequential_1)) { + if (invert == FALSE) { + /* get the last one */ + const char *rid = NULL; + + for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + rid = ID(xml_rsc); + } + } + EXPAND_CONSTRAINT_IDREF(id, rsc_1, rid); + + } else { + /* get the first one */ + for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); + break; + } + } + } + } + + if (crm_is_true(sequential_2)) { + if (invert == FALSE) { + /* get the first one */ + for (xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc)); + break; + } + } + + } else { + /* get the last one */ + const char *rid = NULL; + + for (xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + rid = ID(xml_rsc); + } + } + EXPAND_CONSTRAINT_IDREF(id, rsc_2, rid); + } + } + + if (rsc_1 != NULL && rsc_2 != NULL) { + new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set); + + } else if (rsc_1 != NULL) { + for (xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc)); + new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set); + } + } + + } else if (rsc_2 != NULL) { + xmlNode *xml_rsc = NULL; + + for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); + new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set); + } + } } else { - for(xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - xmlNode *xml_rsc_2 = NULL; - EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); - - for(xml_rsc_2 = __xml_first_child(set2); xml_rsc_2 != NULL; xml_rsc_2 = __xml_next(xml_rsc_2)) { - if(crm_str_eq((const char *)xml_rsc_2->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc_2)); - new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set); - } - } - } - } + for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + xmlNode *xml_rsc_2 = NULL; + + EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); + + for (xml_rsc_2 = __xml_first_child(set2); xml_rsc_2 != NULL; + xml_rsc_2 = __xml_next(xml_rsc_2)) { + if (crm_str_eq((const char *)xml_rsc_2->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc_2)); + new_rsc_order(rsc_1, action_1, rsc_2, action_2, flags, data_set); + } + } + } + } } return TRUE; } gboolean -unpack_rsc_order(xmlNode *xml_obj, pe_working_set_t *data_set) +unpack_rsc_order(xmlNode * xml_obj, pe_working_set_t * data_set) { gboolean any_sets = FALSE; resource_t *rsc = NULL; + /* - resource_t *last_rsc = NULL; - */ + resource_t *last_rsc = NULL; + */ action_t *set_end = NULL; action_t *set_begin = NULL; action_t *set_inv_end = NULL; action_t *set_inv_begin = NULL; - + xmlNode *set = NULL; xmlNode *last = NULL; + /* - action_t *last_end = NULL; - action_t *last_begin = NULL; - action_t *last_inv_end = NULL; - action_t *last_inv_begin = NULL; - */ - - const char *id = crm_element_value(xml_obj, XML_ATTR_ID); + action_t *last_end = NULL; + action_t *last_begin = NULL; + action_t *last_inv_end = NULL; + action_t *last_inv_begin = NULL; + */ + + const char *id = crm_element_value(xml_obj, XML_ATTR_ID); const char *invert = crm_element_value(xml_obj, XML_CONS_ATTR_SYMMETRICAL); enum pe_order_kind kind = get_ordering_type(xml_obj); - if(invert == NULL) { - invert = "true"; - } - - for(set = __xml_first_child(xml_obj); set != NULL; set = __xml_next(set)) { - if(crm_str_eq((const char *)set->name, XML_CONS_TAG_RSC_SET, TRUE)) { - any_sets = TRUE; - set = expand_idref(set, data_set->input); - if(unpack_order_set(set, kind, &rsc, &set_begin, &set_end, - &set_inv_begin, &set_inv_end, invert, data_set) == FALSE) { - return FALSE; - - /* Expand orders in order_rsc_sets() instead of via pseudo actions. */ - /* - } else if(last) { - const char *set_action = crm_element_value(set, "action"); - const char *last_action = crm_element_value(last, "action"); - enum pe_ordering flags = get_flags(id, kind, last_action, set_action, FALSE); - - - if(!set_action) { set_action = RSC_START; } - if(!last_action) { last_action = RSC_START; } - - if(rsc == NULL && last_rsc == NULL) { - order_actions(last_end, set_begin, flags); - } else { - custom_action_order( - last_rsc, null_or_opkey(last_rsc, last_action), last_end, - rsc, null_or_opkey(rsc, set_action), set_begin, - flags, data_set); - } - - if(crm_is_true(invert)) { - set_action = invert_action(set_action); - last_action = invert_action(last_action); - - flags = get_flags(id, kind, last_action, set_action, TRUE); - if(rsc == NULL && last_rsc == NULL) { - order_actions(last_inv_begin, set_inv_end, flags); - - } else { - custom_action_order( - last_rsc, null_or_opkey(last_rsc, last_action), last_inv_begin, - rsc, null_or_opkey(rsc, set_action), set_inv_end, - flags, data_set); - } - } - */ - - } else if(/* never called -- Now call it for supporting clones in resource sets */last) { - if(order_rsc_sets(id, last, set, kind, data_set, FALSE) == FALSE) { - return FALSE; - } - - if(crm_is_true(invert) && order_rsc_sets(id, set, last, kind, data_set, TRUE) == FALSE) { - return FALSE; - } - - } - last = set; - /* - last_rsc = rsc; - last_end = set_end; - last_begin = set_begin; - last_inv_end = set_inv_end; - last_inv_begin = set_inv_begin; - */ - } - } - - if(any_sets == FALSE) { - return unpack_simple_rsc_order(xml_obj, data_set); + if (invert == NULL) { + invert = "true"; + } + + for (set = __xml_first_child(xml_obj); set != NULL; set = __xml_next(set)) { + if (crm_str_eq((const char *)set->name, XML_CONS_TAG_RSC_SET, TRUE)) { + any_sets = TRUE; + set = expand_idref(set, data_set->input); + if (unpack_order_set(set, kind, &rsc, &set_begin, &set_end, + &set_inv_begin, &set_inv_end, invert, data_set) == FALSE) { + return FALSE; + + /* Expand orders in order_rsc_sets() instead of via pseudo actions. */ + /* + } else if(last) { + const char *set_action = crm_element_value(set, "action"); + const char *last_action = crm_element_value(last, "action"); + enum pe_ordering flags = get_flags(id, kind, last_action, set_action, FALSE); + + if(!set_action) { set_action = RSC_START; } + if(!last_action) { last_action = RSC_START; } + + if(rsc == NULL && last_rsc == NULL) { + order_actions(last_end, set_begin, flags); + } else { + custom_action_order( + last_rsc, null_or_opkey(last_rsc, last_action), last_end, + rsc, null_or_opkey(rsc, set_action), set_begin, + flags, data_set); + } + + if(crm_is_true(invert)) { + set_action = invert_action(set_action); + last_action = invert_action(last_action); + + flags = get_flags(id, kind, last_action, set_action, TRUE); + if(rsc == NULL && last_rsc == NULL) { + order_actions(last_inv_begin, set_inv_end, flags); + + } else { + custom_action_order( + last_rsc, null_or_opkey(last_rsc, last_action), last_inv_begin, + rsc, null_or_opkey(rsc, set_action), set_inv_end, + flags, data_set); + } + } + */ + + } else if ( /* never called -- Now call it for supporting clones in resource sets */ + last) { + if (order_rsc_sets(id, last, set, kind, data_set, FALSE) == FALSE) { + return FALSE; + } + + if (crm_is_true(invert) + && order_rsc_sets(id, set, last, kind, data_set, TRUE) == FALSE) { + return FALSE; + } + + } + last = set; + /* + last_rsc = rsc; + last_end = set_end; + last_begin = set_begin; + last_inv_end = set_inv_end; + last_inv_begin = set_inv_begin; + */ + } + } + + if (any_sets == FALSE) { + return unpack_simple_rsc_order(xml_obj, data_set); } return TRUE; } static gboolean -unpack_colocation_set(xmlNode *set, int score, pe_working_set_t *data_set) +unpack_colocation_set(xmlNode * set, int score, pe_working_set_t * data_set) { xmlNode *xml_rsc = NULL; resource_t *with = NULL; resource_t *resource = NULL; const char *set_id = ID(set); const char *role = crm_element_value(set, "role"); const char *sequential = crm_element_value(set, "sequential"); int local_score = score; const char *score_s = crm_element_value(set, XML_RULE_ATTR_SCORE); - if(score_s) { - local_score = char2score(score_s); - } - - if(sequential != NULL && crm_is_true(sequential) == FALSE) { - return TRUE; - - } else if(local_score >= 0) { - for(xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(set_id, resource, ID(xml_rsc)); - if(with != NULL) { - crm_debug_2("Colocating %s with %s", resource->id, with->id); - rsc_colocation_new(set_id, NULL, local_score, resource, with, role, role, data_set); - } - - with = resource; - } - } - + + if (score_s) { + local_score = char2score(score_s); + } + + if (sequential != NULL && crm_is_true(sequential) == FALSE) { + return TRUE; + + } else if (local_score >= 0) { + for (xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(set_id, resource, ID(xml_rsc)); + if (with != NULL) { + crm_debug_2("Colocating %s with %s", resource->id, with->id); + rsc_colocation_new(set_id, NULL, local_score, resource, with, role, role, + data_set); + } + + with = resource; + } + } + } else { - /* Anti-colocating with every prior resource is - * the only way to ensure the intuitive result - * (ie. that no-one in the set can run with anyone - * else in the set) - */ - - for(xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - xmlNode *xml_rsc_with = NULL; - EXPAND_CONSTRAINT_IDREF(set_id, resource, ID(xml_rsc)); - - for(xml_rsc_with = __xml_first_child(set); xml_rsc_with != NULL; xml_rsc_with = __xml_next(xml_rsc_with)) { - if(crm_str_eq((const char *)xml_rsc_with->name, XML_TAG_RESOURCE_REF, TRUE)) { - if(safe_str_eq(resource->id, ID(xml_rsc_with))) { - break; - } else if(resource == NULL) { - crm_config_err("%s: No resource found for %s", set_id, ID(xml_rsc_with)); - return FALSE; - } - EXPAND_CONSTRAINT_IDREF(set_id, with, ID(xml_rsc_with)); - crm_debug_2("Anti-Colocating %s with %s", resource->id, with->id); - rsc_colocation_new(set_id, NULL, local_score, resource, with, role, role, data_set); - } - } - } - } - } - + /* Anti-colocating with every prior resource is + * the only way to ensure the intuitive result + * (ie. that no-one in the set can run with anyone + * else in the set) + */ + + for (xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + xmlNode *xml_rsc_with = NULL; + + EXPAND_CONSTRAINT_IDREF(set_id, resource, ID(xml_rsc)); + + for (xml_rsc_with = __xml_first_child(set); xml_rsc_with != NULL; + xml_rsc_with = __xml_next(xml_rsc_with)) { + if (crm_str_eq((const char *)xml_rsc_with->name, XML_TAG_RESOURCE_REF, TRUE)) { + if (safe_str_eq(resource->id, ID(xml_rsc_with))) { + break; + } else if (resource == NULL) { + crm_config_err("%s: No resource found for %s", set_id, + ID(xml_rsc_with)); + return FALSE; + } + EXPAND_CONSTRAINT_IDREF(set_id, with, ID(xml_rsc_with)); + crm_debug_2("Anti-Colocating %s with %s", resource->id, with->id); + rsc_colocation_new(set_id, NULL, local_score, resource, with, role, role, + data_set); + } + } + } + } + } + return TRUE; -} +} -static gboolean colocate_rsc_sets( - const char *id, xmlNode *set1, xmlNode *set2, int score, pe_working_set_t *data_set) +static gboolean +colocate_rsc_sets(const char *id, xmlNode * set1, xmlNode * set2, int score, + pe_working_set_t * data_set) { xmlNode *xml_rsc = NULL; resource_t *rsc_1 = NULL; resource_t *rsc_2 = NULL; - + const char *role_1 = crm_element_value(set1, "role"); const char *role_2 = crm_element_value(set2, "role"); const char *sequential_1 = crm_element_value(set1, "sequential"); const char *sequential_2 = crm_element_value(set2, "sequential"); - if(crm_is_true(sequential_1)) { - /* get the first one */ - for(xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); - break; - } - } - } - - if(crm_is_true(sequential_2)) { - /* get the last one */ - const char *rid = NULL; - for(xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - rid = ID(xml_rsc); - } - } - EXPAND_CONSTRAINT_IDREF(id, rsc_2, rid); - } - - if(rsc_1 != NULL && rsc_2 != NULL) { - rsc_colocation_new(id, NULL, score, rsc_1, rsc_2, role_1, role_2, data_set); - - } else if(rsc_1 != NULL) { - for(xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc)); - rsc_colocation_new(id, NULL, score, rsc_1, rsc_2, role_1, role_2, data_set); - } - } - - } else if(rsc_2 != NULL) { - for(xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); - rsc_colocation_new(id, NULL, score, rsc_1, rsc_2, role_1, role_2, data_set); - } - } - + if (crm_is_true(sequential_1)) { + /* get the first one */ + for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); + break; + } + } + } + + if (crm_is_true(sequential_2)) { + /* get the last one */ + const char *rid = NULL; + + for (xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + rid = ID(xml_rsc); + } + } + EXPAND_CONSTRAINT_IDREF(id, rsc_2, rid); + } + + if (rsc_1 != NULL && rsc_2 != NULL) { + rsc_colocation_new(id, NULL, score, rsc_1, rsc_2, role_1, role_2, data_set); + + } else if (rsc_1 != NULL) { + for (xml_rsc = __xml_first_child(set2); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc)); + rsc_colocation_new(id, NULL, score, rsc_1, rsc_2, role_1, role_2, data_set); + } + } + + } else if (rsc_2 != NULL) { + for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); + rsc_colocation_new(id, NULL, score, rsc_1, rsc_2, role_1, role_2, data_set); + } + } } else { - for(xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - xmlNode *xml_rsc_2 = NULL; - EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); - - for(xml_rsc_2 = __xml_first_child(set2); xml_rsc_2 != NULL; xml_rsc_2 = __xml_next(xml_rsc_2)) { - if(crm_str_eq((const char *)xml_rsc_2->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc_2)); - rsc_colocation_new(id, NULL, score, rsc_1, rsc_2, role_1, role_2, data_set); - } - } - } - } + for (xml_rsc = __xml_first_child(set1); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + xmlNode *xml_rsc_2 = NULL; + + EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc)); + + for (xml_rsc_2 = __xml_first_child(set2); xml_rsc_2 != NULL; + xml_rsc_2 = __xml_next(xml_rsc_2)) { + if (crm_str_eq((const char *)xml_rsc_2->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc_2)); + rsc_colocation_new(id, NULL, score, rsc_1, rsc_2, role_1, role_2, data_set); + } + } + } + } } return TRUE; } -static gboolean unpack_simple_colocation(xmlNode *xml_obj, pe_working_set_t *data_set) +static gboolean +unpack_simple_colocation(xmlNode * xml_obj, pe_working_set_t * data_set) { int score_i = 0; - const char *id = crm_element_value(xml_obj, XML_ATTR_ID); - const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); - - const char *id_lh = crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE); - const char *id_rh = crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET); + const char *id = crm_element_value(xml_obj, XML_ATTR_ID); + const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); + + const char *id_lh = crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE); + const char *id_rh = crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET); const char *state_lh = crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE_ROLE); const char *state_rh = crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET_ROLE); const char *instance_lh = crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE_INSTANCE); const char *instance_rh = crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET_INSTANCE); - const char *attr = crm_element_value(xml_obj, XML_COLOC_ATTR_NODE_ATTR); + const char *attr = crm_element_value(xml_obj, XML_COLOC_ATTR_NODE_ATTR); const char *symmetrical = crm_element_value(xml_obj, XML_CONS_ATTR_SYMMETRICAL); - + resource_t *rsc_lh = pe_find_resource(data_set->resources, id_lh); resource_t *rsc_rh = pe_find_resource(data_set->resources, id_rh); - - if(rsc_lh == NULL) { - crm_config_err("Invalid constraint '%s': No resource named '%s'", id, id_lh); - return FALSE; - - } else if(rsc_rh == NULL) { - crm_config_err("Invalid constraint '%s': No resource named '%s'", id, id_rh); - return FALSE; - } else if(instance_lh && rsc_lh->variant < pe_clone) { - crm_config_err("Invalid constraint '%s': Resource '%s' is not a clone but instance %s was requested", id, id_lh, instance_lh); - return FALSE; + if (rsc_lh == NULL) { + crm_config_err("Invalid constraint '%s': No resource named '%s'", id, id_lh); + return FALSE; + + } else if (rsc_rh == NULL) { + crm_config_err("Invalid constraint '%s': No resource named '%s'", id, id_rh); + return FALSE; - } else if(instance_rh && rsc_rh->variant < pe_clone) { - crm_config_err("Invalid constraint '%s': Resource '%s' is not a clone but instance %s was requested", id, id_rh, instance_rh); - return FALSE; + } else if (instance_lh && rsc_lh->variant < pe_clone) { + crm_config_err + ("Invalid constraint '%s': Resource '%s' is not a clone but instance %s was requested", + id, id_lh, instance_lh); + return FALSE; + + } else if (instance_rh && rsc_rh->variant < pe_clone) { + crm_config_err + ("Invalid constraint '%s': Resource '%s' is not a clone but instance %s was requested", + id, id_rh, instance_rh); + return FALSE; } - if(instance_lh) { - rsc_lh = find_clone_instance(rsc_lh, instance_lh, data_set); - if(rsc_lh == NULL) { - crm_config_warn("Invalid constraint '%s': No instance '%s' of '%s'", id, instance_lh, id_lh); - return FALSE; - } + if (instance_lh) { + rsc_lh = find_clone_instance(rsc_lh, instance_lh, data_set); + if (rsc_lh == NULL) { + crm_config_warn("Invalid constraint '%s': No instance '%s' of '%s'", id, instance_lh, + id_lh); + return FALSE; + } } - if(instance_rh) { - rsc_rh = find_clone_instance(rsc_rh, instance_rh, data_set); - if(rsc_rh == NULL) { - crm_config_warn("Invalid constraint '%s': No instance '%s' of '%s'", id, instance_rh, id_rh); - return FALSE; - } + if (instance_rh) { + rsc_rh = find_clone_instance(rsc_rh, instance_rh, data_set); + if (rsc_rh == NULL) { + crm_config_warn("Invalid constraint '%s': No instance '%s' of '%s'", id, instance_rh, + id_rh); + return FALSE; + } } - if(crm_is_true(symmetrical)) { - crm_config_warn("The %s colocation constraint attribute has been removed." - " It didn't do what you think it did anyway.", - XML_CONS_ATTR_SYMMETRICAL); + if (crm_is_true(symmetrical)) { + crm_config_warn("The %s colocation constraint attribute has been removed." + " It didn't do what you think it did anyway.", XML_CONS_ATTR_SYMMETRICAL); } - if(score) { - score_i = char2score(score); + if (score) { + score_i = char2score(score); } - + rsc_colocation_new(id, attr, score_i, rsc_lh, rsc_rh, state_lh, state_rh, data_set); return TRUE; } gboolean -unpack_rsc_colocation(xmlNode *xml_obj, pe_working_set_t *data_set) +unpack_rsc_colocation(xmlNode * xml_obj, pe_working_set_t * data_set) { int score_i = 0; xmlNode *set = NULL; xmlNode *last = NULL; gboolean any_sets = FALSE; - const char *id = crm_element_value(xml_obj, XML_ATTR_ID); + const char *id = crm_element_value(xml_obj, XML_ATTR_ID); const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE); - if(score) { - score_i = char2score(score); + if (score) { + score_i = char2score(score); } - - for(set = __xml_first_child(xml_obj); set != NULL; set = __xml_next(set)) { - if(crm_str_eq((const char *)set->name, XML_CONS_TAG_RSC_SET, TRUE)) { - any_sets = TRUE; - set = expand_idref(set, data_set->input); - if(unpack_colocation_set(set, score_i, data_set) == FALSE) { - return FALSE; - } else if(last && colocate_rsc_sets(id, last, set, score_i, data_set) == FALSE) { - return FALSE; - } - last = set; - } + for (set = __xml_first_child(xml_obj); set != NULL; set = __xml_next(set)) { + if (crm_str_eq((const char *)set->name, XML_CONS_TAG_RSC_SET, TRUE)) { + any_sets = TRUE; + set = expand_idref(set, data_set->input); + if (unpack_colocation_set(set, score_i, data_set) == FALSE) { + return FALSE; + + } else if (last && colocate_rsc_sets(id, last, set, score_i, data_set) == FALSE) { + return FALSE; + } + last = set; + } } - - if(any_sets == FALSE) { - return unpack_simple_colocation(xml_obj, data_set); + + if (any_sets == FALSE) { + return unpack_simple_colocation(xml_obj, data_set); } return TRUE; } gboolean -rsc_ticket_new(const char *id, resource_t *rsc_lh, ticket_t *ticket, - const char *state_lh, const char *loss_policy, pe_working_set_t *data_set) +rsc_ticket_new(const char *id, resource_t * rsc_lh, ticket_t * ticket, + const char *state_lh, const char *loss_policy, pe_working_set_t * data_set) { rsc_ticket_t *new_rsc_ticket = NULL; - - if(rsc_lh == NULL){ - crm_config_err("No resource found for LHS %s", id); - return FALSE; + if (rsc_lh == NULL) { + crm_config_err("No resource found for LHS %s", id); + return FALSE; } crm_malloc0(new_rsc_ticket, sizeof(rsc_ticket_t)); - if(new_rsc_ticket == NULL) { - return FALSE; + if (new_rsc_ticket == NULL) { + return FALSE; } - if(state_lh == NULL - || safe_str_eq(state_lh, RSC_ROLE_STARTED_S)) { - state_lh = RSC_ROLE_UNKNOWN_S; + if (state_lh == NULL || safe_str_eq(state_lh, RSC_ROLE_STARTED_S)) { + state_lh = RSC_ROLE_UNKNOWN_S; } - new_rsc_ticket->id = id; + new_rsc_ticket->id = id; new_rsc_ticket->ticket = ticket; - new_rsc_ticket->rsc_lh = rsc_lh; + new_rsc_ticket->rsc_lh = rsc_lh; new_rsc_ticket->role_lh = text2role(state_lh); - if(safe_str_eq(loss_policy, "fence")) { - crm_debug("On loss of ticket '%s': Fence the nodes running %s (%s)", - new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, role2text(new_rsc_ticket->role_lh)); - new_rsc_ticket->loss_policy = loss_ticket_fence; - - } else if(safe_str_eq(loss_policy, "freeze")) { - crm_debug("On loss of ticket '%s': Freeze %s (%s)", - new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, role2text(new_rsc_ticket->role_lh)); - new_rsc_ticket->loss_policy = loss_ticket_freeze; - - } else if(safe_str_eq(loss_policy, "demote")) { - crm_debug("On loss of ticket '%s': Demote %s (%s)", - new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, role2text(new_rsc_ticket->role_lh)); - new_rsc_ticket->loss_policy = loss_ticket_demote; - - } else if(safe_str_eq(loss_policy, "stop")) { - crm_debug("On loss of ticket '%s': Stop %s (%s)", - new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, role2text(new_rsc_ticket->role_lh)); - new_rsc_ticket->loss_policy = loss_ticket_stop; + if (safe_str_eq(loss_policy, "fence")) { + crm_debug("On loss of ticket '%s': Fence the nodes running %s (%s)", + new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, + role2text(new_rsc_ticket->role_lh)); + new_rsc_ticket->loss_policy = loss_ticket_fence; + + } else if (safe_str_eq(loss_policy, "freeze")) { + crm_debug("On loss of ticket '%s': Freeze %s (%s)", + new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, + role2text(new_rsc_ticket->role_lh)); + new_rsc_ticket->loss_policy = loss_ticket_freeze; + + } else if (safe_str_eq(loss_policy, "demote")) { + crm_debug("On loss of ticket '%s': Demote %s (%s)", + new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, + role2text(new_rsc_ticket->role_lh)); + new_rsc_ticket->loss_policy = loss_ticket_demote; + + } else if (safe_str_eq(loss_policy, "stop")) { + crm_debug("On loss of ticket '%s': Stop %s (%s)", + new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, + role2text(new_rsc_ticket->role_lh)); + new_rsc_ticket->loss_policy = loss_ticket_stop; } else { - if(new_rsc_ticket->role_lh == RSC_ROLE_MASTER) { - crm_debug("On loss of ticket '%s': Default to demote %s (%s)", - new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, role2text(new_rsc_ticket->role_lh)); - new_rsc_ticket->loss_policy = loss_ticket_demote; + if (new_rsc_ticket->role_lh == RSC_ROLE_MASTER) { + crm_debug("On loss of ticket '%s': Default to demote %s (%s)", + new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, + role2text(new_rsc_ticket->role_lh)); + new_rsc_ticket->loss_policy = loss_ticket_demote; - } else { - crm_debug("On loss of ticket '%s': Default to stop %s (%s)", - new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, role2text(new_rsc_ticket->role_lh)); - new_rsc_ticket->loss_policy = loss_ticket_stop; - } + } else { + crm_debug("On loss of ticket '%s': Default to stop %s (%s)", + new_rsc_ticket->ticket->id, new_rsc_ticket->rsc_lh->id, + role2text(new_rsc_ticket->role_lh)); + new_rsc_ticket->loss_policy = loss_ticket_stop; + } } crm_debug_3("%s (%s) ==> %s", rsc_lh->id, role2text(new_rsc_ticket->role_lh), ticket->id); - + rsc_lh->rsc_tickets = g_list_append(rsc_lh->rsc_tickets, new_rsc_ticket); data_set->ticket_constraints = g_list_append(data_set->ticket_constraints, new_rsc_ticket); - + return TRUE; } static gboolean -unpack_rsc_ticket_set(xmlNode *set, ticket_t *ticket, const char *loss_policy, pe_working_set_t *data_set) +unpack_rsc_ticket_set(xmlNode * set, ticket_t * ticket, const char *loss_policy, + pe_working_set_t * data_set) { xmlNode *xml_rsc = NULL; resource_t *resource = NULL; const char *set_id = ID(set); const char *role = crm_element_value(set, "role"); - if(set == NULL) { - crm_config_err("No resource_set object to process."); - return FALSE; + if (set == NULL) { + crm_config_err("No resource_set object to process."); + return FALSE; } - if(set_id == NULL) { - crm_config_err("resource_set must have an id"); - return FALSE; + if (set_id == NULL) { + crm_config_err("resource_set must have an id"); + return FALSE; } - if(ticket == NULL) { - crm_config_err("No dependented ticket specified for '%s'", set_id); - return FALSE; + if (ticket == NULL) { + crm_config_err("No dependented ticket specified for '%s'", set_id); + return FALSE; } - for(xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { - if(crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { - EXPAND_CONSTRAINT_IDREF(set_id, resource, ID(xml_rsc)); - crm_debug_2("Resource '%s' depends on ticket '%s'", resource->id, ticket->id); - rsc_ticket_new(set_id, resource, ticket, role, loss_policy, data_set); - } + for (xml_rsc = __xml_first_child(set); xml_rsc != NULL; xml_rsc = __xml_next(xml_rsc)) { + if (crm_str_eq((const char *)xml_rsc->name, XML_TAG_RESOURCE_REF, TRUE)) { + EXPAND_CONSTRAINT_IDREF(set_id, resource, ID(xml_rsc)); + crm_debug_2("Resource '%s' depends on ticket '%s'", resource->id, ticket->id); + rsc_ticket_new(set_id, resource, ticket, role, loss_policy, data_set); + } } - + return TRUE; -} +} static gboolean -unpack_simple_rsc_ticket(xmlNode *xml_obj, pe_working_set_t *data_set) +unpack_simple_rsc_ticket(xmlNode * xml_obj, pe_working_set_t * data_set) { - const char *id = crm_element_value(xml_obj, XML_ATTR_ID); + const char *id = crm_element_value(xml_obj, XML_ATTR_ID); const char *ticket_str = crm_element_value(xml_obj, XML_TICKET_ATTR_TICKET); const char *loss_policy = crm_element_value(xml_obj, XML_TICKET_ATTR_LOSS_POLICY); ticket_t *ticket = NULL; - - const char *id_lh = crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE); + + const char *id_lh = crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE); const char *state_lh = crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE_ROLE); const char *instance_lh = crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE_INSTANCE); resource_t *rsc_lh = NULL; - if(xml_obj == NULL) { - crm_config_err("No rsc_ticket constraint object to process."); - return FALSE; + if (xml_obj == NULL) { + crm_config_err("No rsc_ticket constraint object to process."); + return FALSE; } - - if(id == NULL) { - crm_config_err("%s constraint must have an id", crm_element_name(xml_obj)); - return FALSE; + + if (id == NULL) { + crm_config_err("%s constraint must have an id", crm_element_name(xml_obj)); + return FALSE; } - - if(ticket_str == NULL) { - crm_config_err("Invalid constraint '%s': No ticket specified", id); - return FALSE; + + if (ticket_str == NULL) { + crm_config_err("Invalid constraint '%s': No ticket specified", id); + return FALSE; } else { - ticket = g_hash_table_lookup(data_set->tickets, ticket_str); + ticket = g_hash_table_lookup(data_set->tickets, ticket_str); } - if(ticket == NULL) { - crm_config_err("Invalid constraint '%s': No ticket named '%s'", id, ticket_str); - return FALSE; + if (ticket == NULL) { + crm_config_err("Invalid constraint '%s': No ticket named '%s'", id, ticket_str); + return FALSE; } - if(id_lh == NULL) { - crm_config_err("Invalid constraint '%s': No resource specified", id); - return FALSE; + if (id_lh == NULL) { + crm_config_err("Invalid constraint '%s': No resource specified", id); + return FALSE; } else { - rsc_lh = pe_find_resource(data_set->resources, id_lh); + rsc_lh = pe_find_resource(data_set->resources, id_lh); } - if(rsc_lh == NULL) { - crm_config_err("Invalid constraint '%s': No resource named '%s'", id, id_lh); - return FALSE; - - } else if(instance_lh && rsc_lh->variant < pe_clone) { - crm_config_err("Invalid constraint '%s': Resource '%s' is not a clone but instance %s was requested", id, id_lh, instance_lh); - return FALSE; + if (rsc_lh == NULL) { + crm_config_err("Invalid constraint '%s': No resource named '%s'", id, id_lh); + return FALSE; + + } else if (instance_lh && rsc_lh->variant < pe_clone) { + crm_config_err + ("Invalid constraint '%s': Resource '%s' is not a clone but instance %s was requested", + id, id_lh, instance_lh); + return FALSE; } - if(instance_lh) { - rsc_lh = find_clone_instance(rsc_lh, instance_lh, data_set); - if(rsc_lh == NULL) { - crm_config_warn("Invalid constraint '%s': No instance '%s' of '%s'", id, instance_lh, id_lh); - return FALSE; - } + if (instance_lh) { + rsc_lh = find_clone_instance(rsc_lh, instance_lh, data_set); + if (rsc_lh == NULL) { + crm_config_warn("Invalid constraint '%s': No instance '%s' of '%s'", id, instance_lh, + id_lh); + return FALSE; + } } rsc_ticket_new(id, rsc_lh, ticket, state_lh, loss_policy, data_set); return TRUE; } gboolean -unpack_rsc_ticket(xmlNode *xml_obj, pe_working_set_t *data_set) +unpack_rsc_ticket(xmlNode * xml_obj, pe_working_set_t * data_set) { xmlNode *set = NULL; gboolean any_sets = FALSE; - const char *id = crm_element_value(xml_obj, XML_ATTR_ID); + const char *id = crm_element_value(xml_obj, XML_ATTR_ID); const char *ticket_str = crm_element_value(xml_obj, XML_TICKET_ATTR_TICKET); const char *loss_policy = crm_element_value(xml_obj, XML_TICKET_ATTR_LOSS_POLICY); ticket_t *ticket = NULL; - if(xml_obj == NULL) { - crm_config_err("No rsc_ticket constraint object to process."); - return FALSE; + if (xml_obj == NULL) { + crm_config_err("No rsc_ticket constraint object to process."); + return FALSE; } - - if(id == NULL) { - crm_config_err("%s constraint must have an id", crm_element_name(xml_obj)); - return FALSE; + + if (id == NULL) { + crm_config_err("%s constraint must have an id", crm_element_name(xml_obj)); + return FALSE; } - - if(ticket_str == NULL) { - crm_config_err("Invalid constraint '%s': No ticket specified", id); - return FALSE; + + if (ticket_str == NULL) { + crm_config_err("Invalid constraint '%s': No ticket specified", id); + return FALSE; } else { - ticket = g_hash_table_lookup(data_set->tickets, ticket_str); + ticket = g_hash_table_lookup(data_set->tickets, ticket_str); } - if(ticket == NULL) { - crm_malloc0(ticket, sizeof(ticket_t)); - if(ticket == NULL) { - crm_config_err("Cannot allocate ticket '%s'", ticket_str); - return FALSE; - } + if (ticket == NULL) { + crm_malloc0(ticket, sizeof(ticket_t)); + if (ticket == NULL) { + crm_config_err("Cannot allocate ticket '%s'", ticket_str); + return FALSE; + } - ticket->id = crm_strdup(ticket_str); - ticket->granted = FALSE; - ticket->last_granted = -1; + ticket->id = crm_strdup(ticket_str); + ticket->granted = FALSE; + ticket->last_granted = -1; - g_hash_table_insert(data_set->tickets, crm_strdup(ticket->id), ticket); + g_hash_table_insert(data_set->tickets, crm_strdup(ticket->id), ticket); } - for(set = __xml_first_child(xml_obj); set != NULL; set = __xml_next(set)) { - if(crm_str_eq((const char *)set->name, XML_CONS_TAG_RSC_SET, TRUE)) { - any_sets = TRUE; - set = expand_idref(set, data_set->input); - if(unpack_rsc_ticket_set(set, ticket, loss_policy, data_set) == FALSE) { - return FALSE; - } - } + for (set = __xml_first_child(xml_obj); set != NULL; set = __xml_next(set)) { + if (crm_str_eq((const char *)set->name, XML_CONS_TAG_RSC_SET, TRUE)) { + any_sets = TRUE; + set = expand_idref(set, data_set->input); + if (unpack_rsc_ticket_set(set, ticket, loss_policy, data_set) == FALSE) { + return FALSE; + } + } } - - if(any_sets == FALSE) { - return unpack_simple_rsc_ticket(xml_obj, data_set); + + if (any_sets == FALSE) { + return unpack_simple_rsc_ticket(xml_obj, data_set); } return TRUE; } -gboolean is_active(rsc_to_node_t *cons) +gboolean +is_active(rsc_to_node_t * cons) { return TRUE; } diff --git a/pengine/graph.c b/pengine/graph.c index e1990e62a0..d9a3901a5e 100644 --- a/pengine/graph.c +++ b/pengine/graph.c @@ -1,787 +1,805 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include -gboolean update_action(action_t *action); -gboolean rsc_update_action(action_t *first, action_t *then, enum pe_ordering type); +gboolean update_action(action_t * action); +gboolean rsc_update_action(action_t * first, action_t * then, enum pe_ordering type); -static enum pe_action_flags get_action_flags(action_t *action, node_t *node) +static enum pe_action_flags +get_action_flags(action_t * action, node_t * node) { enum pe_action_flags flags = action->flags; - if(action->rsc) { - flags = action->rsc->cmds->action_flags(action, NULL); - - if(action->rsc->variant >= pe_clone && node) { - - /* We only care about activity on $node */ - enum pe_action_flags clone_flags = action->rsc->cmds->action_flags(action, node); - - /* Go to great lengths to ensure the correct value for pe_action_runnable... - * - * If we are a clone, then for _ordering_ constraints, its only relevant - * if we are runnable _anywhere_. - * - * This only applies to _runnable_ though, and only for ordering constraints. - * If this function is ever used during colocation, then we'll need additional logic - * - * Not very satisfying, but its logical and appears to work well. - */ - if(is_not_set(clone_flags, pe_action_runnable) - && is_set(flags, pe_action_runnable)) { - crm_trace("Fixing up runnable flag for %s", action->uuid); - set_bit_inplace(clone_flags, pe_action_runnable); - } - flags = clone_flags; - } + + if (action->rsc) { + flags = action->rsc->cmds->action_flags(action, NULL); + + if (action->rsc->variant >= pe_clone && node) { + + /* We only care about activity on $node */ + enum pe_action_flags clone_flags = action->rsc->cmds->action_flags(action, node); + + /* Go to great lengths to ensure the correct value for pe_action_runnable... + * + * If we are a clone, then for _ordering_ constraints, its only relevant + * if we are runnable _anywhere_. + * + * This only applies to _runnable_ though, and only for ordering constraints. + * If this function is ever used during colocation, then we'll need additional logic + * + * Not very satisfying, but its logical and appears to work well. + */ + if (is_not_set(clone_flags, pe_action_runnable) + && is_set(flags, pe_action_runnable)) { + crm_trace("Fixing up runnable flag for %s", action->uuid); + set_bit_inplace(clone_flags, pe_action_runnable); + } + flags = clone_flags; + } } return flags; } static char * -convert_non_atomic_uuid(char *old_uuid, resource_t *rsc, gboolean allow_notify, gboolean free_original) +convert_non_atomic_uuid(char *old_uuid, resource_t * rsc, gboolean allow_notify, + gboolean free_original) { int interval = 0; char *uuid = NULL; char *rid = NULL; char *raw_task = NULL; int task = no_action; crm_debug_3("Processing %s", old_uuid); - if(old_uuid == NULL) { - return NULL; + if (old_uuid == NULL) { + return NULL; - } else if(strstr(old_uuid, "notify") != NULL) { - goto done; /* no conversion */ + } else if (strstr(old_uuid, "notify") != NULL) { + goto done; /* no conversion */ - } else if(rsc->variant < pe_group) { - goto done; /* no conversion */ + } else if (rsc->variant < pe_group) { + goto done; /* no conversion */ } CRM_ASSERT(parse_op_key(old_uuid, &rid, &raw_task, &interval)); - if(interval > 0) { - goto done; /* no conversion */ - } - + if (interval > 0) { + goto done; /* no conversion */ + } + task = text2task(raw_task); - switch(task) { - case stop_rsc: - case start_rsc: - case action_notify: - case action_promote: - case action_demote: - break; - case stopped_rsc: - case started_rsc: - case action_notified: - case action_promoted: - case action_demoted: - task--; - break; - case monitor_rsc: - case shutdown_crm: - case stonith_node: - task = no_action; - break; - default: - crm_err("Unknown action: %s", raw_task); - task = no_action; - break; - } - - if(task != no_action) { - if(is_set(rsc->flags, pe_rsc_notify) && allow_notify) { - uuid = generate_notify_key(rid, "confirmed-post", task2text(task+1)); - - } else { - uuid = generate_op_key(rid, task2text(task+1), 0); - } - crm_debug_2("Converted %s -> %s", old_uuid, uuid); - } - + switch (task) { + case stop_rsc: + case start_rsc: + case action_notify: + case action_promote: + case action_demote: + break; + case stopped_rsc: + case started_rsc: + case action_notified: + case action_promoted: + case action_demoted: + task--; + break; + case monitor_rsc: + case shutdown_crm: + case stonith_node: + task = no_action; + break; + default: + crm_err("Unknown action: %s", raw_task); + task = no_action; + break; + } + + if (task != no_action) { + if (is_set(rsc->flags, pe_rsc_notify) && allow_notify) { + uuid = generate_notify_key(rid, "confirmed-post", task2text(task + 1)); + + } else { + uuid = generate_op_key(rid, task2text(task + 1), 0); + } + crm_debug_2("Converted %s -> %s", old_uuid, uuid); + } + done: - if(uuid == NULL) { - uuid = crm_strdup(old_uuid); + if (uuid == NULL) { + uuid = crm_strdup(old_uuid); } - if(free_original) { - crm_free(old_uuid); + if (free_original) { + crm_free(old_uuid); } - + crm_free(raw_task); crm_free(rid); return uuid; } -static action_t *rsc_expand_action(action_t *action) +static action_t * +rsc_expand_action(action_t * action) { action_t *result = action; - if(action->rsc && action->rsc->variant >= pe_group) { - /* Expand 'start' -> 'started' */ - char *uuid = NULL; - gboolean notify = FALSE; - if(action->rsc->parent == NULL) { - /* Only outter-most resources have notification actions */ - notify = is_set(action->rsc->flags, pe_rsc_notify); - } - - uuid = convert_non_atomic_uuid(action->uuid, action->rsc, notify, FALSE); - if(uuid) { - crm_trace("Converting %s to %s %d", action->uuid, uuid, is_set(action->rsc->flags, pe_rsc_notify)); - result = find_first_action(action->rsc->actions, uuid, NULL, NULL); - if(result == NULL) { - crm_err("Couldn't expand %s", action->uuid); - result = action; - } - crm_free(uuid); - } + + if (action->rsc && action->rsc->variant >= pe_group) { + /* Expand 'start' -> 'started' */ + char *uuid = NULL; + gboolean notify = FALSE; + + if (action->rsc->parent == NULL) { + /* Only outter-most resources have notification actions */ + notify = is_set(action->rsc->flags, pe_rsc_notify); + } + + uuid = convert_non_atomic_uuid(action->uuid, action->rsc, notify, FALSE); + if (uuid) { + crm_trace("Converting %s to %s %d", action->uuid, uuid, + is_set(action->rsc->flags, pe_rsc_notify)); + result = find_first_action(action->rsc->actions, uuid, NULL, NULL); + if (result == NULL) { + crm_err("Couldn't expand %s", action->uuid); + result = action; + } + crm_free(uuid); + } } return result; } -static enum pe_graph_flags graph_update_action(action_t *first, action_t *then, node_t *node, enum pe_action_flags flags, enum pe_ordering type) +static enum pe_graph_flags +graph_update_action(action_t * first, action_t * then, node_t * node, enum pe_action_flags flags, + enum pe_ordering type) { enum pe_graph_flags changed = pe_graph_none; gboolean processed = FALSE; /* TODO: Do as many of these in parallel as possible */ - - if(type & pe_order_implies_then) { - crm_trace("implies right: %s then %s", first->uuid, then->uuid); - processed = TRUE; - if(then->rsc) { - changed |= then->rsc->cmds->update_actions( - first, then, node, flags & pe_action_optional, pe_action_optional, pe_order_implies_then); - - } else if(is_set(flags, pe_action_optional) == FALSE) { - if(update_action_flags(then, pe_action_optional|pe_action_clear)) { - changed |= pe_graph_updated_then; - } - } - } - - if((type & pe_order_restart) && then->rsc) { - enum pe_action_flags restart = (pe_action_optional|pe_action_runnable); - crm_trace("restart: %s then %s", first->uuid, then->uuid); - processed = TRUE; - changed |= then->rsc->cmds->update_actions( - first, then, node, flags & restart, restart, pe_order_restart); - } - - if(type & pe_order_implies_first) { - crm_trace("implies left: %s then %s", first->uuid, then->uuid); - processed = TRUE; - if(first->rsc) { - changed |= first->rsc->cmds->update_actions( - first, then, node, flags & pe_action_optional, pe_action_optional, pe_order_implies_first); - - } else if(is_set(flags, pe_action_optional) == FALSE) { - if(update_action_flags(first, pe_action_runnable|pe_action_clear)) { - changed |= pe_graph_updated_first; - } - } - } - - if(type & pe_order_runnable_left) { - crm_trace("runnable: %s then %s", first->uuid, then->uuid); - processed = TRUE; - if(then->rsc) { - changed |= then->rsc->cmds->update_actions( - first, then, node, flags & pe_action_runnable, pe_action_runnable, pe_order_runnable_left); - - } else if(is_set(flags, pe_action_runnable) == FALSE) { - if(update_action_flags(then, pe_action_runnable|pe_action_clear)) { - changed |= pe_graph_updated_then; - } - } - } - - if(type & pe_order_optional) { - crm_trace("optional: %s then %s", first->uuid, then->uuid); - processed = TRUE; - if(then->rsc) { - changed |= then->rsc->cmds->update_actions( - first, then, node, flags & pe_action_runnable, pe_action_runnable, pe_order_optional); - } - } - - if((type & pe_order_implies_then_printed) && (flags & pe_action_optional) == 0) { - processed = TRUE; - crm_trace("%s implies %s printed", first->uuid, then->uuid); - update_action_flags(then, pe_action_print_always); /* dont care about changed */ - } - - if((type & pe_order_implies_first_printed) && (flags & pe_action_optional) == 0) { - processed = TRUE; - crm_trace("%s implies %s printed", then->uuid, first->uuid); - update_action_flags(first, pe_action_print_always); /* dont care about changed */ - } - - if(processed == FALSE) { - crm_trace("Constraint 0x%.6x not applicable", type); + + if (type & pe_order_implies_then) { + crm_trace("implies right: %s then %s", first->uuid, then->uuid); + processed = TRUE; + if (then->rsc) { + changed |= + then->rsc->cmds->update_actions(first, then, node, flags & pe_action_optional, + pe_action_optional, pe_order_implies_then); + + } else if (is_set(flags, pe_action_optional) == FALSE) { + if (update_action_flags(then, pe_action_optional | pe_action_clear)) { + changed |= pe_graph_updated_then; + } + } + } + + if ((type & pe_order_restart) && then->rsc) { + enum pe_action_flags restart = (pe_action_optional | pe_action_runnable); + + crm_trace("restart: %s then %s", first->uuid, then->uuid); + processed = TRUE; + changed |= + then->rsc->cmds->update_actions(first, then, node, flags & restart, restart, + pe_order_restart); + } + + if (type & pe_order_implies_first) { + crm_trace("implies left: %s then %s", first->uuid, then->uuid); + processed = TRUE; + if (first->rsc) { + changed |= + first->rsc->cmds->update_actions(first, then, node, flags & pe_action_optional, + pe_action_optional, pe_order_implies_first); + + } else if (is_set(flags, pe_action_optional) == FALSE) { + if (update_action_flags(first, pe_action_runnable | pe_action_clear)) { + changed |= pe_graph_updated_first; + } + } + } + + if (type & pe_order_runnable_left) { + crm_trace("runnable: %s then %s", first->uuid, then->uuid); + processed = TRUE; + if (then->rsc) { + changed |= + then->rsc->cmds->update_actions(first, then, node, flags & pe_action_runnable, + pe_action_runnable, pe_order_runnable_left); + + } else if (is_set(flags, pe_action_runnable) == FALSE) { + if (update_action_flags(then, pe_action_runnable | pe_action_clear)) { + changed |= pe_graph_updated_then; + } + } + } + + if (type & pe_order_optional) { + crm_trace("optional: %s then %s", first->uuid, then->uuid); + processed = TRUE; + if (then->rsc) { + changed |= + then->rsc->cmds->update_actions(first, then, node, flags & pe_action_runnable, + pe_action_runnable, pe_order_optional); + } + } + + if ((type & pe_order_implies_then_printed) && (flags & pe_action_optional) == 0) { + processed = TRUE; + crm_trace("%s implies %s printed", first->uuid, then->uuid); + update_action_flags(then, pe_action_print_always); /* dont care about changed */ + } + + if ((type & pe_order_implies_first_printed) && (flags & pe_action_optional) == 0) { + processed = TRUE; + crm_trace("%s implies %s printed", then->uuid, first->uuid); + update_action_flags(first, pe_action_print_always); /* dont care about changed */ + } + + if (processed == FALSE) { + crm_trace("Constraint 0x%.6x not applicable", type); } return changed; } gboolean -update_action(action_t *then) +update_action(action_t * then) { GListPtr lpc = NULL; enum pe_graph_flags changed = pe_graph_none; crm_trace("Processing %s (%s %s %s)", - then->uuid, - is_set(then->flags, pe_action_optional)?"optional":"required", - is_set(then->flags, pe_action_runnable)?"runnable":"unrunnable", - is_set(then->flags, pe_action_pseudo)?"pseudo":then->node?then->node->details->uname:""); - for(lpc = then->actions_before; lpc != NULL; lpc = lpc->next) { - action_wrapper_t *other = (action_wrapper_t*)lpc->data; - action_t *first = other->action; - - node_t *then_node = then->node; - node_t *first_node = first->node; - - enum pe_action_flags then_flags = 0; - enum pe_action_flags first_flags = 0; - - if(first->rsc - && first->rsc->variant == pe_group - && safe_str_eq(first->task, RSC_START)) { - first_node = first->rsc->fns->location(first->rsc, NULL, FALSE); - if(first_node) { - crm_trace("First: Found node %s for %s", first_node->details->uname, first->uuid); - } - } - - if(then->rsc - && then->rsc->variant == pe_group - && safe_str_eq(then->task, RSC_START)) { - then_node = then->rsc->fns->location(then->rsc, NULL, FALSE); - if(then_node) { - crm_trace("Then: Found node %s for %s", then_node->details->uname, then->uuid); - } - } - - clear_bit_inplace(changed, pe_graph_updated_first); - - if(first->rsc != then->rsc - && first->rsc != NULL - && then->rsc != NULL - && first->rsc != then->rsc->parent) { - first = rsc_expand_action(first); - } - if(first != other->action) { - crm_trace("Ordering %s afer %s instead of %s", then->uuid, first->uuid, other->action->uuid); - } - - first_flags = get_action_flags(first, then_node); - then_flags = get_action_flags(then, first_node); - - crm_trace("Checking %s (%s %s %s) against %s (%s %s %s) 0x%.6x", - then->uuid, - is_set(then_flags, pe_action_optional)?"optional":"required", - is_set(then_flags, pe_action_runnable)?"runnable":"unrunnable", - is_set(then_flags, pe_action_pseudo)?"pseudo":then->node?then->node->details->uname:"", - first->uuid, - is_set(first_flags, pe_action_optional)?"optional":"required", - is_set(first_flags, pe_action_runnable)?"runnable":"unrunnable", - is_set(first_flags, pe_action_pseudo)?"pseudo":first->node?first->node->details->uname:"", - other->type); - - if(first == other->action) { - clear_bit_inplace(first_flags, pe_action_pseudo); - changed |= graph_update_action(first, then, then->node, first_flags, other->type); - - } else if(order_actions(first, then, other->type)) { - /* Start again to get the new actions_before list */ - changed |= (pe_graph_updated_then|pe_graph_disable); - } - - if(changed & pe_graph_disable) { - crm_trace("Disabled constraint %s -> %s", other->action->uuid, then->uuid); - clear_bit_inplace(changed, pe_graph_disable); - other->type = pe_order_none; - } - - if(changed & pe_graph_updated_first) { - GListPtr lpc2 = NULL; - crm_trace("Updated %s (first %s %s %s), processing dependants ", - first->uuid, - is_set(first->flags, pe_action_optional)?"optional":"required", - is_set(first->flags, pe_action_runnable)?"runnable":"unrunnable", - is_set(first->flags, pe_action_pseudo)?"pseudo":first->node?first->node->details->uname:""); - for(lpc2 = first->actions_after; lpc2 != NULL; lpc2 = lpc2->next) { - action_wrapper_t *other = (action_wrapper_t*)lpc2->data; - update_action(other->action); - } - update_action(first); - } - } - - if(changed & pe_graph_updated_then) { - crm_trace("Updated %s (then %s %s %s), processing dependants ", - then->uuid, - is_set(then->flags, pe_action_optional)?"optional":"required", - is_set(then->flags, pe_action_runnable)?"runnable":"unrunnable", - is_set(then->flags, pe_action_pseudo)?"pseudo":then->node?then->node->details->uname:""); - - update_action(then); - for(lpc = then->actions_after; lpc != NULL; lpc = lpc->next) { - action_wrapper_t *other = (action_wrapper_t*)lpc->data; - update_action(other->action); - } - } - + then->uuid, + is_set(then->flags, pe_action_optional) ? "optional" : "required", + is_set(then->flags, pe_action_runnable) ? "runnable" : "unrunnable", + is_set(then->flags, + pe_action_pseudo) ? "pseudo" : then->node ? then->node->details->uname : ""); + for (lpc = then->actions_before; lpc != NULL; lpc = lpc->next) { + action_wrapper_t *other = (action_wrapper_t *) lpc->data; + action_t *first = other->action; + + node_t *then_node = then->node; + node_t *first_node = first->node; + + enum pe_action_flags then_flags = 0; + enum pe_action_flags first_flags = 0; + + if (first->rsc && first->rsc->variant == pe_group && safe_str_eq(first->task, RSC_START)) { + first_node = first->rsc->fns->location(first->rsc, NULL, FALSE); + if (first_node) { + crm_trace("First: Found node %s for %s", first_node->details->uname, first->uuid); + } + } + + if (then->rsc && then->rsc->variant == pe_group && safe_str_eq(then->task, RSC_START)) { + then_node = then->rsc->fns->location(then->rsc, NULL, FALSE); + if (then_node) { + crm_trace("Then: Found node %s for %s", then_node->details->uname, then->uuid); + } + } + + clear_bit_inplace(changed, pe_graph_updated_first); + + if (first->rsc != then->rsc + && first->rsc != NULL && then->rsc != NULL && first->rsc != then->rsc->parent) { + first = rsc_expand_action(first); + } + if (first != other->action) { + crm_trace("Ordering %s afer %s instead of %s", then->uuid, first->uuid, + other->action->uuid); + } + + first_flags = get_action_flags(first, then_node); + then_flags = get_action_flags(then, first_node); + + crm_trace("Checking %s (%s %s %s) against %s (%s %s %s) 0x%.6x", + then->uuid, + is_set(then_flags, pe_action_optional) ? "optional" : "required", + is_set(then_flags, pe_action_runnable) ? "runnable" : "unrunnable", + is_set(then_flags, + pe_action_pseudo) ? "pseudo" : then->node ? then->node->details-> + uname : "", first->uuid, is_set(first_flags, + pe_action_optional) ? "optional" : "required", + is_set(first_flags, pe_action_runnable) ? "runnable" : "unrunnable", + is_set(first_flags, + pe_action_pseudo) ? "pseudo" : first->node ? first->node->details-> + uname : "", other->type); + + if (first == other->action) { + clear_bit_inplace(first_flags, pe_action_pseudo); + changed |= graph_update_action(first, then, then->node, first_flags, other->type); + + } else if (order_actions(first, then, other->type)) { + /* Start again to get the new actions_before list */ + changed |= (pe_graph_updated_then | pe_graph_disable); + } + + if (changed & pe_graph_disable) { + crm_trace("Disabled constraint %s -> %s", other->action->uuid, then->uuid); + clear_bit_inplace(changed, pe_graph_disable); + other->type = pe_order_none; + } + + if (changed & pe_graph_updated_first) { + GListPtr lpc2 = NULL; + + crm_trace("Updated %s (first %s %s %s), processing dependants ", + first->uuid, + is_set(first->flags, pe_action_optional) ? "optional" : "required", + is_set(first->flags, pe_action_runnable) ? "runnable" : "unrunnable", + is_set(first->flags, + pe_action_pseudo) ? "pseudo" : first->node ? first->node->details-> + uname : ""); + for (lpc2 = first->actions_after; lpc2 != NULL; lpc2 = lpc2->next) { + action_wrapper_t *other = (action_wrapper_t *) lpc2->data; + + update_action(other->action); + } + update_action(first); + } + } + + if (changed & pe_graph_updated_then) { + crm_trace("Updated %s (then %s %s %s), processing dependants ", + then->uuid, + is_set(then->flags, pe_action_optional) ? "optional" : "required", + is_set(then->flags, pe_action_runnable) ? "runnable" : "unrunnable", + is_set(then->flags, + pe_action_pseudo) ? "pseudo" : then->node ? then->node->details-> + uname : ""); + + update_action(then); + for (lpc = then->actions_after; lpc != NULL; lpc = lpc->next) { + action_wrapper_t *other = (action_wrapper_t *) lpc->data; + + update_action(other->action); + } + } + return FALSE; } - gboolean -shutdown_constraints( - node_t *node, action_t *shutdown_op, pe_working_set_t *data_set) +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 */ GListPtr lpc = NULL; - for(lpc = node->details->running_rsc; lpc != NULL; lpc = lpc->next) { - resource_t *rsc = (resource_t*)lpc->data; - 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_optional, data_set); + for (lpc = node->details->running_rsc; lpc != NULL; lpc = lpc->next) { + resource_t *rsc = (resource_t *) lpc->data; + + 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_optional, data_set); } - return TRUE; + return TRUE; } gboolean -stonith_constraints( - node_t *node, action_t *stonith_op, pe_working_set_t *data_set) +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) { - GListPtr lpc = NULL; - for(lpc = data_set->resources; lpc != NULL; lpc = lpc->next) { - resource_t *rsc = (resource_t*)lpc->data; - rsc_stonith_ordering(rsc, stonith_op, data_set); - } - } - + if (stonith_op != NULL) { + GListPtr lpc = NULL; + + for (lpc = data_set->resources; lpc != NULL; lpc = lpc->next) { + resource_t *rsc = (resource_t *) lpc->data; + + rsc_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) +action2xml(action_t * action, gboolean as_input) { gboolean needs_node_info = TRUE; - xmlNode * action_xml = NULL; - xmlNode * args_xml = NULL; + xmlNode *action_xml = NULL; + xmlNode *args_xml = NULL; char *action_id_s = NULL; - - if(action == NULL) { - return 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); + 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_CLEAR_FAILCOUNT)) { - action_xml = create_xml_node(NULL, XML_GRAPH_TAG_CRM_EVENT); + } 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, CRM_OP_CLEAR_FAILCOUNT)) { + 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(is_set(action->flags, pe_action_pseudo)) { - action_xml = create_xml_node(NULL, XML_GRAPH_TAG_PSEUDO_EVENT); - needs_node_info = FALSE; + } else if (is_set(action->flags, pe_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_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); - + 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); + 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 (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(is_set(action->flags, pe_action_failure_is_fatal) == FALSE) { - add_hash_param(action->meta, - XML_ATTR_TE_ALLOWFAIL, XML_BOOLEAN_TRUE); + if (is_set(action->flags, pe_action_failure_is_fatal) == FALSE) { + add_hash_param(action->meta, XML_ATTR_TE_ALLOWFAIL, XML_BOOLEAN_TRUE); } - - if(as_input) { - return action_xml; + + if (as_input) { + return action_xml; } - if(action->rsc) { - if(is_set(action->flags, pe_action_pseudo) == FALSE) { - int lpc = 0; - - xmlNode *rsc_xml = create_xml_node( - action_xml, crm_element_name(action->rsc->xml)); + if (action->rsc) { + if (is_set(action->flags, pe_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 + }; - 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); - 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); + } - } 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])); - } - } + 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) { - g_hash_table_foreach(action->rsc->parameters, hash2smartfield, args_xml); + g_hash_table_foreach(action->extra, hash2field, args_xml); + if (action->rsc != NULL) { + g_hash_table_foreach(action->rsc->parameters, hash2smartfield, args_xml); } g_hash_table_foreach(action->meta, hash2metafield, args_xml); - if(action->rsc != NULL) { - resource_t *parent = action->rsc; - while(parent != NULL) { - parent->cmds->append_meta(parent, args_xml); - parent = parent->parent; - } - - } else if(safe_str_eq(action->task, CRM_OP_FENCE)) { - g_hash_table_foreach(action->node->details->attrs, hash2metafield, args_xml); - } - - sorted_xml(args_xml, action_xml, FALSE); + if (action->rsc != NULL) { + resource_t *parent = action->rsc; + + while (parent != NULL) { + parent->cmds->append_meta(parent, args_xml); + parent = parent->parent; + } + + } else if (safe_str_eq(action->task, CRM_OP_FENCE)) { + g_hash_table_foreach(action->node->details->attrs, hash2metafield, args_xml); + } + + 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) +should_dump_action(action_t * action) { int log_filter = LOG_DEBUG_5; CRM_CHECK(action != NULL, return FALSE); - if(is_set(action->flags, pe_action_dumped)) { - do_crm_log_unlikely(log_filter, "action %d (%s) was already dumped", - action->id, action->uuid); - return FALSE; - - } else if(is_set(action->flags, pe_action_runnable) == FALSE) { - do_crm_log_unlikely(log_filter, "action %d (%s) was not runnable", - action->id, action->uuid); - return FALSE; - - } else if(is_set(action->flags, pe_action_optional) && is_set(action->flags, pe_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(is_set(action->flags, pe_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 (is_set(action->flags, pe_action_dumped)) { + do_crm_log_unlikely(log_filter, "action %d (%s) was already dumped", + action->id, action->uuid); + return FALSE; + + } else if (is_set(action->flags, pe_action_runnable) == FALSE) { + do_crm_log_unlikely(log_filter, "action %d (%s) was not runnable", + action->id, action->uuid); + return FALSE; + + } else if (is_set(action->flags, pe_action_optional) + && is_set(action->flags, pe_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 (is_set(action->flags, pe_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; + /* 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) +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; + 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(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; } - - 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) +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_first_printed; type &= ~pe_order_implies_then_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(is_set(wrapper->action->flags, pe_action_runnable) == FALSE - && 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(is_set(action->flags, pe_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->rsc - && wrapper->action->rsc != action->rsc - && is_set(wrapper->action->rsc->flags, pe_rsc_failed) - && is_not_set(wrapper->action->rsc->flags, pe_rsc_managed) - && strstr(wrapper->action->uuid, "_stop_0") - && action->rsc && action->rsc->variant >= pe_clone) { - crm_warn("Ignoring requirement that %s comeplete before %s:" - " unmanaged failed resources cannot prevent clone shutdown", - wrapper->action->uuid, action->uuid); - return FALSE; - - } else if(is_set(wrapper->action->flags, pe_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; + + 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 (is_set(wrapper->action->flags, pe_action_runnable) == FALSE + && 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 (is_set(action->flags, pe_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->rsc + && wrapper->action->rsc != action->rsc + && is_set(wrapper->action->rsc->flags, pe_rsc_failed) + && is_not_set(wrapper->action->rsc->flags, pe_rsc_managed) + && strstr(wrapper->action->uuid, "_stop_0") + && action->rsc && action->rsc->variant >= pe_clone) { + crm_warn("Ignoring requirement that %s comeplete before %s:" + " unmanaged failed resources cannot prevent clone shutdown", + wrapper->action->uuid, action->uuid); + return FALSE; + + } else if (is_set(wrapper->action->flags, pe_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 - } else if(is_set(wrapper->action->flags, pe_action_runnable) - && is_set(wrapper->action->flags, pe_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; + } else if (is_set(wrapper->action->flags, pe_action_runnable) + && is_set(wrapper->action->flags, pe_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(is_set(wrapper->action->flags, pe_action_optional) == TRUE && is_set(wrapper->action->flags, pe_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, - is_set(wrapper->action->flags, pe_action_pseudo), - is_set(wrapper->action->flags, pe_action_runnable), - is_set(wrapper->action->flags, pe_action_optional), - is_set(wrapper->action->flags, pe_action_print_always), - wrapper->type); - return FALSE; - } - + } else if (is_set(wrapper->action->flags, pe_action_optional) == TRUE + && is_set(wrapper->action->flags, pe_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, + is_set(wrapper->action->flags, pe_action_pseudo), + is_set(wrapper->action->flags, pe_action_runnable), + is_set(wrapper->action->flags, pe_action_optional), + is_set(wrapper->action->flags, pe_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, - is_set(wrapper->action->flags, pe_action_pseudo), - is_set(wrapper->action->flags, pe_action_runnable), - is_set(wrapper->action->flags, pe_action_optional), - is_set(wrapper->action->flags, pe_action_print_always), - wrapper->type, action->uuid); + wrapper->action->id, + wrapper->action->uuid, + wrapper->action->node, + is_set(wrapper->action->flags, pe_action_pseudo), + is_set(wrapper->action->flags, pe_action_runnable), + is_set(wrapper->action->flags, pe_action_optional), + is_set(wrapper->action->flags, pe_action_print_always), + wrapper->type, action->uuid); return TRUE; } - + void -graph_element_from_action(action_t *action, pe_working_set_t *data_set) +graph_element_from_action(action_t * action, pe_working_set_t * data_set) { GListPtr lpc = NULL; int last_action = -1; int synapse_priority = 0; - xmlNode * syn = NULL; - xmlNode * set = NULL; - xmlNode * in = NULL; - xmlNode * input = NULL; - xmlNode * xml_action = NULL; + xmlNode *syn = NULL; + xmlNode *set = NULL; + xmlNode *in = NULL; + xmlNode *input = NULL; + xmlNode *xml_action = NULL; - if(should_dump_action(action) == FALSE) { - return; + if (should_dump_action(action) == FALSE) { + return; } - + set_bit_inplace(action->flags, pe_action_dumped); - + syn = create_xml_node(data_set->graph, "synapse"); set = create_xml_node(syn, "action_set"); - in = create_xml_node(syn, "inputs"); + 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->rsc != NULL) { + synapse_priority = action->rsc->priority; } - if(action->priority > synapse_priority) { - synapse_priority = action->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); + 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); - - for(lpc = action->actions_before; lpc != NULL; lpc = lpc->next) { - action_wrapper_t *wrapper = (action_wrapper_t*)lpc->data; - 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); + action->actions_before = g_list_sort(action->actions_before, sort_action_id); + + for (lpc = action->actions_before; lpc != NULL; lpc = lpc->next) { + action_wrapper_t *wrapper = (action_wrapper_t *) lpc->data; + + 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/group.c b/pengine/group.c index 75d68d46c5..4c9254ccaa 100644 --- a/pengine/group.c +++ b/pengine/group.c @@ -1,488 +1,515 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #define VARIANT_GROUP 1 #include node_t * -group_color(resource_t *rsc, node_t *prefer, pe_working_set_t *data_set) +group_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set) { node_t *node = NULL; node_t *group_node = NULL; GListPtr gIter = NULL; group_variant_data_t *group_data = NULL; + get_group_variant_data(group_data, rsc); - if(is_not_set(rsc->flags, pe_rsc_provisional)) { - return rsc->allocated_to; + if (is_not_set(rsc->flags, pe_rsc_provisional)) { + return rsc->allocated_to; } crm_debug_2("Processing %s", rsc->id); - if(is_set(rsc->flags, pe_rsc_allocating)) { - crm_debug("Dependency loop detected involving %s", rsc->id); - return NULL; + if (is_set(rsc->flags, pe_rsc_allocating)) { + crm_debug("Dependency loop detected involving %s", rsc->id); + return NULL; } - - if(group_data->first_child == NULL) { - /* nothign to allocate */ - clear_bit(rsc->flags, pe_rsc_provisional); - return NULL; + + if (group_data->first_child == NULL) { + /* nothign to allocate */ + clear_bit(rsc->flags, pe_rsc_provisional); + return NULL; } - + set_bit(rsc->flags, pe_rsc_allocating); rsc->role = group_data->first_child->role; - - group_data->first_child->rsc_cons = g_list_concat( - group_data->first_child->rsc_cons, rsc->rsc_cons); + + group_data->first_child->rsc_cons = + g_list_concat(group_data->first_child->rsc_cons, rsc->rsc_cons); rsc->rsc_cons = NULL; - group_data->first_child->rsc_cons_lhs = g_list_concat( - group_data->first_child->rsc_cons_lhs, rsc->rsc_cons_lhs); + group_data->first_child->rsc_cons_lhs = + g_list_concat(group_data->first_child->rsc_cons_lhs, rsc->rsc_cons_lhs); rsc->rsc_cons_lhs = NULL; - + gIter = rsc->rsc_tickets; - for(; gIter != NULL; gIter = gIter->next) { - rsc_ticket_t *rsc_ticket = (rsc_ticket_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + rsc_ticket_t *rsc_ticket = (rsc_ticket_t *) gIter->data; - if(rsc_ticket->ticket->granted == FALSE) { - rsc_ticket_constraint(rsc, rsc_ticket, data_set); - } + if (rsc_ticket->ticket->granted == FALSE) { + rsc_ticket_constraint(rsc, rsc_ticket, data_set); + } } - dump_node_scores(show_scores?0:scores_log_level, rsc, __PRETTY_FUNCTION__, rsc->allowed_nodes); - + dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __PRETTY_FUNCTION__, + rsc->allowed_nodes); + gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - node = child_rsc->cmds->allocate(child_rsc, prefer, data_set); - if(group_node == NULL) { - group_node = node; - } + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + node = child_rsc->cmds->allocate(child_rsc, prefer, data_set); + if (group_node == NULL) { + group_node = node; + } } - rsc->next_role = group_data->first_child->next_role; + rsc->next_role = group_data->first_child->next_role; clear_bit(rsc->flags, pe_rsc_allocating); clear_bit(rsc->flags, pe_rsc_provisional); - if(group_data->colocated) { - return group_node; - } + if (group_data->colocated) { + return group_node; + } return NULL; } -void group_update_pseudo_status(resource_t *parent, resource_t *child); +void group_update_pseudo_status(resource_t * parent, resource_t * child); -void group_create_actions(resource_t *rsc, pe_working_set_t *data_set) +void +group_create_actions(resource_t * rsc, pe_working_set_t * data_set) { action_t *op = NULL; const char *value = NULL; GListPtr gIter = rsc->children; crm_debug_2("Creating actions for %s", rsc->id); - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - child_rsc->cmds->create_actions(child_rsc, data_set); - group_update_pseudo_status(rsc, child_rsc); + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->create_actions(child_rsc, data_set); + group_update_pseudo_status(rsc, child_rsc); } - op = start_action(rsc, NULL, TRUE/* !group_data->child_starting */); - set_bit_inplace(op->flags, pe_action_pseudo|pe_action_runnable); + op = start_action(rsc, NULL, TRUE /* !group_data->child_starting */ ); + set_bit_inplace(op->flags, pe_action_pseudo | pe_action_runnable); op = custom_action(rsc, started_key(rsc), - RSC_STARTED, NULL, - TRUE/* !group_data->child_starting */, TRUE, data_set); - set_bit_inplace(op->flags, pe_action_pseudo|pe_action_runnable); + RSC_STARTED, NULL, TRUE /* !group_data->child_starting */ , TRUE, data_set); + set_bit_inplace(op->flags, pe_action_pseudo | pe_action_runnable); + + op = stop_action(rsc, NULL, TRUE /* !group_data->child_stopping */ ); + set_bit_inplace(op->flags, pe_action_pseudo | pe_action_runnable); - op = stop_action(rsc, NULL, TRUE/* !group_data->child_stopping */); - set_bit_inplace(op->flags, pe_action_pseudo|pe_action_runnable); - op = custom_action(rsc, stopped_key(rsc), - RSC_STOPPED, NULL, - TRUE/* !group_data->child_stopping */, TRUE, data_set); - set_bit_inplace(op->flags, pe_action_pseudo|pe_action_runnable); + RSC_STOPPED, NULL, TRUE /* !group_data->child_stopping */ , TRUE, data_set); + set_bit_inplace(op->flags, pe_action_pseudo | pe_action_runnable); value = g_hash_table_lookup(rsc->meta, "stateful"); - if(crm_is_true(value)) { - op = custom_action(rsc, demote_key(rsc), RSC_DEMOTE, NULL, TRUE, TRUE, data_set); - set_bit_inplace(op->flags, pe_action_pseudo); set_bit_inplace(op->flags, pe_action_runnable); - op = custom_action(rsc, demoted_key(rsc), RSC_DEMOTED, NULL, TRUE, TRUE, data_set); - set_bit_inplace(op->flags, pe_action_pseudo); set_bit_inplace(op->flags, pe_action_runnable); - - op = custom_action(rsc, promote_key(rsc), RSC_PROMOTE, NULL, TRUE, TRUE, data_set); - set_bit_inplace(op->flags, pe_action_pseudo); set_bit_inplace(op->flags, pe_action_runnable); - op = custom_action(rsc, promoted_key(rsc), RSC_PROMOTED, NULL, TRUE, TRUE, data_set); - set_bit_inplace(op->flags, pe_action_pseudo); set_bit_inplace(op->flags, pe_action_runnable); + if (crm_is_true(value)) { + op = custom_action(rsc, demote_key(rsc), RSC_DEMOTE, NULL, TRUE, TRUE, data_set); + set_bit_inplace(op->flags, pe_action_pseudo); + set_bit_inplace(op->flags, pe_action_runnable); + op = custom_action(rsc, demoted_key(rsc), RSC_DEMOTED, NULL, TRUE, TRUE, data_set); + set_bit_inplace(op->flags, pe_action_pseudo); + set_bit_inplace(op->flags, pe_action_runnable); + + op = custom_action(rsc, promote_key(rsc), RSC_PROMOTE, NULL, TRUE, TRUE, data_set); + set_bit_inplace(op->flags, pe_action_pseudo); + set_bit_inplace(op->flags, pe_action_runnable); + op = custom_action(rsc, promoted_key(rsc), RSC_PROMOTED, NULL, TRUE, TRUE, data_set); + set_bit_inplace(op->flags, pe_action_pseudo); + set_bit_inplace(op->flags, pe_action_runnable); } } void -group_update_pseudo_status(resource_t *parent, resource_t *child) +group_update_pseudo_status(resource_t * parent, resource_t * child) { GListPtr gIter = child->actions; group_variant_data_t *group_data = NULL; + get_group_variant_data(group_data, parent); - if(group_data->ordered == FALSE) { - /* If this group is not ordered, then leave the meta-actions as optional */ - return; - } - - if(group_data->child_stopping && group_data->child_starting) { - return; + if (group_data->ordered == FALSE) { + /* If this group is not ordered, then leave the meta-actions as optional */ + return; } - for(; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - - if(is_set(action->flags, pe_action_optional)) { - continue; - } - if(safe_str_eq(RSC_STOP, action->task) && is_set(action->flags, pe_action_runnable)) { - group_data->child_stopping = TRUE; - crm_debug_3("Based on %s the group is stopping", action->uuid); + if (group_data->child_stopping && group_data->child_starting) { + return; + } - } else if(safe_str_eq(RSC_START, action->task) && is_set(action->flags, pe_action_runnable)) { - group_data->child_starting = TRUE; - crm_debug_3("Based on %s the group is starting", action->uuid); - } + for (; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + if (is_set(action->flags, pe_action_optional)) { + continue; + } + if (safe_str_eq(RSC_STOP, action->task) && is_set(action->flags, pe_action_runnable)) { + group_data->child_stopping = TRUE; + crm_debug_3("Based on %s the group is stopping", action->uuid); + + } else if (safe_str_eq(RSC_START, action->task) + && is_set(action->flags, pe_action_runnable)) { + group_data->child_starting = TRUE; + crm_debug_3("Based on %s the group is starting", action->uuid); + } } } -void group_internal_constraints(resource_t *rsc, pe_working_set_t *data_set) +void +group_internal_constraints(resource_t * rsc, pe_working_set_t * data_set) { GListPtr gIter = rsc->children; resource_t *last_rsc = NULL; resource_t *top = uber_parent(rsc); group_variant_data_t *group_data = NULL; + get_group_variant_data(group_data, rsc); - new_rsc_order(rsc, RSC_STOPPED, rsc, RSC_START, pe_order_optional, data_set); - new_rsc_order(rsc, RSC_START, rsc, RSC_STARTED, pe_order_runnable_left, data_set); - new_rsc_order(rsc, RSC_STOP, rsc, RSC_STOPPED, pe_order_runnable_left, data_set); - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - int stop = pe_order_none; - int stopped = pe_order_implies_then_printed; - int start = pe_order_implies_then|pe_order_runnable_left; - int started = pe_order_runnable_left|pe_order_implies_then|pe_order_implies_then_printed; - - child_rsc->cmds->internal_constraints(child_rsc, data_set); - - if(last_rsc == NULL) { - if(group_data->ordered) { - stop |= pe_order_optional; - stopped = pe_order_implies_then; - } - - } else if(group_data->colocated) { - rsc_colocation_new( - "group:internal_colocation", NULL, INFINITY, - child_rsc, last_rsc, NULL, NULL, data_set); - } - - if(top->variant == pe_master) { - new_rsc_order(rsc, RSC_DEMOTE, child_rsc, RSC_DEMOTE, - stop|pe_order_implies_first_printed, data_set); - - new_rsc_order(child_rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, stopped, data_set); - - new_rsc_order(child_rsc, RSC_PROMOTE, rsc, RSC_PROMOTED, started, data_set); - - new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, - pe_order_implies_first_printed, data_set); - - } - - order_start_start(rsc, child_rsc, pe_order_implies_first_printed); - order_stop_stop(rsc, child_rsc, stop|pe_order_implies_first_printed); - - new_rsc_order(child_rsc, RSC_STOP, rsc, RSC_STOPPED, stopped, data_set); - - new_rsc_order(child_rsc, RSC_START, rsc, RSC_STARTED, started, data_set); - - if(group_data->ordered == FALSE) { - order_start_start(rsc, child_rsc, start|pe_order_implies_first_printed); - if(top->variant == pe_master) { - new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, - start|pe_order_implies_first_printed, data_set); - } - - } else if(last_rsc != NULL) { - child_rsc->restart_type = pe_restart_restart; - - order_start_start(last_rsc, child_rsc, start); - order_stop_stop(child_rsc, last_rsc, pe_order_optional); - - if(top->variant == pe_master) { - new_rsc_order(last_rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, start, data_set); - new_rsc_order(child_rsc, RSC_DEMOTE, last_rsc, RSC_DEMOTE, pe_order_optional, data_set); - } - - } else { - /* If anyone in the group is starting, then - * pe_order_implies_then will cause _everyone_ in the group - * to be sent a start action - * But this is safe since starting something that is already - * started is required to be "safe" - */ - int flags = pe_order_none; - - order_start_start(rsc, child_rsc, flags); - if(top->variant == pe_master) { - new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, flags, data_set); - } - - } - - last_rsc = child_rsc; + new_rsc_order(rsc, RSC_STOPPED, rsc, RSC_START, pe_order_optional, data_set); + new_rsc_order(rsc, RSC_START, rsc, RSC_STARTED, pe_order_runnable_left, data_set); + new_rsc_order(rsc, RSC_STOP, rsc, RSC_STOPPED, pe_order_runnable_left, data_set); + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + int stop = pe_order_none; + int stopped = pe_order_implies_then_printed; + int start = pe_order_implies_then | pe_order_runnable_left; + int started = + pe_order_runnable_left | pe_order_implies_then | pe_order_implies_then_printed; + + child_rsc->cmds->internal_constraints(child_rsc, data_set); + + if (last_rsc == NULL) { + if (group_data->ordered) { + stop |= pe_order_optional; + stopped = pe_order_implies_then; + } + + } else if (group_data->colocated) { + rsc_colocation_new("group:internal_colocation", NULL, INFINITY, + child_rsc, last_rsc, NULL, NULL, data_set); + } + + if (top->variant == pe_master) { + new_rsc_order(rsc, RSC_DEMOTE, child_rsc, RSC_DEMOTE, + stop | pe_order_implies_first_printed, data_set); + + new_rsc_order(child_rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, stopped, data_set); + + new_rsc_order(child_rsc, RSC_PROMOTE, rsc, RSC_PROMOTED, started, data_set); + + new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, + pe_order_implies_first_printed, data_set); + + } + + order_start_start(rsc, child_rsc, pe_order_implies_first_printed); + order_stop_stop(rsc, child_rsc, stop | pe_order_implies_first_printed); + + new_rsc_order(child_rsc, RSC_STOP, rsc, RSC_STOPPED, stopped, data_set); + + new_rsc_order(child_rsc, RSC_START, rsc, RSC_STARTED, started, data_set); + + if (group_data->ordered == FALSE) { + order_start_start(rsc, child_rsc, start | pe_order_implies_first_printed); + if (top->variant == pe_master) { + new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, + start | pe_order_implies_first_printed, data_set); + } + + } else if (last_rsc != NULL) { + child_rsc->restart_type = pe_restart_restart; + + order_start_start(last_rsc, child_rsc, start); + order_stop_stop(child_rsc, last_rsc, pe_order_optional); + + if (top->variant == pe_master) { + new_rsc_order(last_rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, start, data_set); + new_rsc_order(child_rsc, RSC_DEMOTE, last_rsc, RSC_DEMOTE, pe_order_optional, + data_set); + } + + } else { + /* If anyone in the group is starting, then + * pe_order_implies_then will cause _everyone_ in the group + * to be sent a start action + * But this is safe since starting something that is already + * started is required to be "safe" + */ + int flags = pe_order_none; + + order_start_start(rsc, child_rsc, flags); + if (top->variant == pe_master) { + new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, flags, data_set); + } + + } + + last_rsc = child_rsc; } - if(group_data->ordered && last_rsc != NULL) { - int stop_stop_flags = pe_order_implies_then; - int stop_stopped_flags = pe_order_optional; - - order_stop_stop(rsc, last_rsc, stop_stop_flags); - new_rsc_order(last_rsc, RSC_STOP, rsc, RSC_STOPPED, stop_stopped_flags, data_set); - - if(top->variant == pe_master) { - new_rsc_order(rsc, RSC_DEMOTE, last_rsc, RSC_DEMOTE, stop_stop_flags, data_set); - new_rsc_order(last_rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, stop_stopped_flags, data_set); - } + if (group_data->ordered && last_rsc != NULL) { + int stop_stop_flags = pe_order_implies_then; + int stop_stopped_flags = pe_order_optional; + + order_stop_stop(rsc, last_rsc, stop_stop_flags); + new_rsc_order(last_rsc, RSC_STOP, rsc, RSC_STOPPED, stop_stopped_flags, data_set); + + if (top->variant == pe_master) { + new_rsc_order(rsc, RSC_DEMOTE, last_rsc, RSC_DEMOTE, stop_stop_flags, data_set); + new_rsc_order(last_rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, stop_stopped_flags, data_set); + } } } - -void group_rsc_colocation_lh( - resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) +void +group_rsc_colocation_lh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint) { GListPtr gIter = NULL; group_variant_data_t *group_data = NULL; - - if(rsc_lh == NULL) { - pe_err("rsc_lh was NULL for %s", constraint->id); - return; - - } else if(rsc_rh == NULL) { - pe_err("rsc_rh was NULL for %s", constraint->id); - return; + + if (rsc_lh == NULL) { + pe_err("rsc_lh was NULL for %s", constraint->id); + return; + + } else if (rsc_rh == NULL) { + pe_err("rsc_rh was NULL for %s", constraint->id); + return; } - + gIter = rsc_lh->children; crm_debug_4("Processing constraints from %s", rsc_lh->id); get_group_variant_data(group_data, rsc_lh); - if(group_data->colocated) { - group_data->first_child->cmds->rsc_colocation_lh( - group_data->first_child, rsc_rh, constraint); - return; - - } else if(constraint->score >= INFINITY) { - crm_config_err("%s: Cannot perform manditory colocation" - " between non-colocated group and %s", - rsc_lh->id, rsc_rh->id); - return; - } - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - child_rsc->cmds->rsc_colocation_lh(child_rsc, rsc_rh, constraint); + if (group_data->colocated) { + group_data->first_child->cmds->rsc_colocation_lh(group_data->first_child, rsc_rh, + constraint); + return; + + } else if (constraint->score >= INFINITY) { + crm_config_err("%s: Cannot perform manditory colocation" + " between non-colocated group and %s", rsc_lh->id, rsc_rh->id); + return; + } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->rsc_colocation_lh(child_rsc, rsc_rh, constraint); } } -void group_rsc_colocation_rh( - resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) +void +group_rsc_colocation_rh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint) { GListPtr gIter = rsc_rh->children; group_variant_data_t *group_data = NULL; + get_group_variant_data(group_data, rsc_rh); CRM_CHECK(rsc_lh->variant == pe_native, return); crm_debug_3("Processing RH of constraint %s", constraint->id); print_resource(LOG_DEBUG_3, "LHS", rsc_lh, TRUE); - if(is_set(rsc_rh->flags, pe_rsc_provisional)) { - return; - - } else if(group_data->colocated && group_data->first_child) { - if(constraint->score >= INFINITY) { - /* Ensure RHS is _fully_ up before can start LHS */ - group_data->last_child->cmds->rsc_colocation_rh( - rsc_lh, group_data->last_child, constraint); - } else { - /* A partially active RHS is fine */ - group_data->first_child->cmds->rsc_colocation_rh( - rsc_lh, group_data->first_child, constraint); - } - - return; - - } else if(constraint->score >= INFINITY) { - crm_config_err("%s: Cannot perform manditory colocation with" - " non-colocated group: %s", rsc_lh->id, rsc_rh->id); - return; - } - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint); + if (is_set(rsc_rh->flags, pe_rsc_provisional)) { + return; + + } else if (group_data->colocated && group_data->first_child) { + if (constraint->score >= INFINITY) { + /* Ensure RHS is _fully_ up before can start LHS */ + group_data->last_child->cmds->rsc_colocation_rh(rsc_lh, group_data->last_child, + constraint); + } else { + /* A partially active RHS is fine */ + group_data->first_child->cmds->rsc_colocation_rh(rsc_lh, group_data->first_child, + constraint); + } + + return; + + } else if (constraint->score >= INFINITY) { + crm_config_err("%s: Cannot perform manditory colocation with" + " non-colocated group: %s", rsc_lh->id, rsc_rh->id); + return; + } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint); } } -enum pe_action_flags group_action_flags(action_t *action, node_t *node) +enum pe_action_flags +group_action_flags(action_t * action, node_t * node) { GListPtr gIter = NULL; enum pe_action_flags flags = (pe_action_optional | pe_action_runnable | pe_action_pseudo); - for(gIter = action->rsc->children; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - enum action_tasks task = get_complex_task(child, action->task, TRUE); - const char *task_s = task2text(task); - action_t *child_action = find_first_action(child->actions, NULL, task_s, node); - - if(child_action) { - enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node); - if(is_set(flags, pe_action_optional) && is_set(child_flags, pe_action_optional) == FALSE) { - crm_trace("%s is manditory because of %s", action->uuid, child_action->uuid); - clear_bit_inplace(flags, pe_action_optional); - clear_bit_inplace(action->flags, pe_action_optional); - } - if(safe_str_neq(task_s, action->task) - && is_set(flags, pe_action_runnable) && is_set(child_flags, pe_action_runnable) == FALSE) { - crm_trace("%s is not runnable because of %s", action->uuid, child_action->uuid); - clear_bit_inplace(flags, pe_action_runnable); - clear_bit_inplace(action->flags, pe_action_runnable); - } - - } else if(task != stop_rsc) { - crm_trace("%s is not runnable because of %s (not found in %s)", action->uuid, task_s, child->id); - clear_bit_inplace(flags, pe_action_runnable); - } + for (gIter = action->rsc->children; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + enum action_tasks task = get_complex_task(child, action->task, TRUE); + const char *task_s = task2text(task); + action_t *child_action = find_first_action(child->actions, NULL, task_s, node); + + if (child_action) { + enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node); + + if (is_set(flags, pe_action_optional) + && is_set(child_flags, pe_action_optional) == FALSE) { + crm_trace("%s is manditory because of %s", action->uuid, child_action->uuid); + clear_bit_inplace(flags, pe_action_optional); + clear_bit_inplace(action->flags, pe_action_optional); + } + if (safe_str_neq(task_s, action->task) + && is_set(flags, pe_action_runnable) + && is_set(child_flags, pe_action_runnable) == FALSE) { + crm_trace("%s is not runnable because of %s", action->uuid, child_action->uuid); + clear_bit_inplace(flags, pe_action_runnable); + clear_bit_inplace(action->flags, pe_action_runnable); + } + + } else if (task != stop_rsc) { + crm_trace("%s is not runnable because of %s (not found in %s)", action->uuid, task_s, + child->id); + clear_bit_inplace(flags, pe_action_runnable); + } } - + return flags; } -enum pe_graph_flags group_update_actions( - action_t *first, action_t *then, node_t *node, enum pe_action_flags flags, enum pe_action_flags filter, enum pe_ordering type) +enum pe_graph_flags +group_update_actions(action_t * first, action_t * then, node_t * node, enum pe_action_flags flags, + enum pe_action_flags filter, enum pe_ordering type) { GListPtr gIter = then->rsc->children; enum pe_graph_flags changed = pe_graph_none; + CRM_ASSERT(then->rsc != NULL); changed |= native_update_actions(first, then, node, flags, filter, type); - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - action_t *child_action = find_first_action(child->actions, NULL, then->task, node); - if(child_action) { - changed |= child->cmds->update_actions(first, child_action, node, flags, filter, type); - } + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + action_t *child_action = find_first_action(child->actions, NULL, then->task, node); + + if (child_action) { + changed |= child->cmds->update_actions(first, child_action, node, flags, filter, type); + } } return changed; } -void group_rsc_location(resource_t *rsc, rsc_to_node_t *constraint) +void +group_rsc_location(resource_t * rsc, rsc_to_node_t * constraint) { GListPtr gIter = rsc->children; GListPtr saved = constraint->node_list_rh; GListPtr zero = node_list_dup(constraint->node_list_rh, TRUE, FALSE); gboolean reset_scores = TRUE; group_variant_data_t *group_data = NULL; + get_group_variant_data(group_data, rsc); - crm_debug("Processing rsc_location %s for %s", - constraint->id, rsc->id); + crm_debug("Processing rsc_location %s for %s", constraint->id, rsc->id); native_rsc_location(rsc, constraint); - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; - child_rsc->cmds->rsc_location(child_rsc, constraint); - if(group_data->colocated && reset_scores) { - reset_scores = FALSE; - constraint->node_list_rh = zero; - } + child_rsc->cmds->rsc_location(child_rsc, constraint); + if (group_data->colocated && reset_scores) { + reset_scores = FALSE; + constraint->node_list_rh = zero; + } } constraint->node_list_rh = saved; slist_basic_destroy(zero); } -void group_expand(resource_t *rsc, pe_working_set_t *data_set) +void +group_expand(resource_t * rsc, pe_working_set_t * data_set) { GListPtr gIter = rsc->children; group_variant_data_t *group_data = NULL; + get_group_variant_data(group_data, rsc); crm_debug_3("Processing actions from %s", rsc->id); CRM_CHECK(rsc != NULL, return); native_expand(rsc, data_set); - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - child_rsc->cmds->expand(child_rsc, data_set); + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->expand(child_rsc, data_set); } } GHashTable * -group_merge_weights( - resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, int factor, gboolean allow_rollback, gboolean only_positive) +group_merge_weights(resource_t * rsc, const char *rhs, GHashTable * nodes, const char *attr, + int factor, gboolean allow_rollback, gboolean only_positive) { GListPtr gIter = rsc->rsc_cons_lhs; group_variant_data_t *group_data = NULL; + get_group_variant_data(group_data, rsc); - - if(is_set(rsc->flags, pe_rsc_merging)) { - crm_info("Breaking dependency loop with %s at %s", rsc->id, rhs); - return nodes; + + if (is_set(rsc->flags, pe_rsc_merging)) { + crm_info("Breaking dependency loop with %s at %s", rsc->id, rhs); + return nodes; } set_bit(rsc->flags, pe_rsc_merging); - nodes = group_data->first_child->cmds->merge_weights( - group_data->first_child, rhs, nodes, attr, factor, allow_rollback, only_positive); - - for(; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - nodes = native_merge_weights( - constraint->rsc_lh, rsc->id, nodes, - constraint->node_attribute, - constraint->score/INFINITY, allow_rollback, only_positive); + nodes = + group_data->first_child->cmds->merge_weights(group_data->first_child, rhs, nodes, attr, + factor, allow_rollback, only_positive); + + for (; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + nodes = native_merge_weights(constraint->rsc_lh, rsc->id, nodes, + constraint->node_attribute, + constraint->score / INFINITY, allow_rollback, only_positive); } clear_bit(rsc->flags, pe_rsc_merging); return nodes; } -void group_append_meta(resource_t *rsc, xmlNode *xml) +void +group_append_meta(resource_t * rsc, xmlNode * xml) { } diff --git a/pengine/main.c b/pengine/main.c index ac31ef0d2a..fc4dd05d33 100644 --- a/pengine/main.c +++ b/pengine/main.c @@ -1,213 +1,211 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #if HAVE_LIBXML2 # include #endif #define OPTARGS "hVc" char *ipc_server = NULL; GMainLoop *mainloop = NULL; -void usage(const char* cmd, int exit_status); +void usage(const char *cmd, int exit_status); void pengine_shutdown(int nsig); -extern gboolean process_pe_message(xmlNode *msg, xmlNode *xml_data, IPC_Channel *sender); +extern gboolean process_pe_message(xmlNode * msg, xmlNode * xml_data, IPC_Channel * sender); static gboolean -pe_msg_callback(IPC_Channel *client, gpointer user_data) +pe_msg_callback(IPC_Channel * client, gpointer user_data) { xmlNode *msg = NULL; gboolean stay_connected = TRUE; - - while(IPC_ISRCONN(client)) { - if(client->ops->is_message_pending(client) == 0) { - break; - } - - msg = xmlfromIPC(client, MAX_IPC_DELAY); - if (msg != NULL) { - xmlNode *data = get_message_xml(msg, F_CRM_DATA); - process_pe_message(msg, data, client); - free_xml(msg); - } + + while (IPC_ISRCONN(client)) { + if (client->ops->is_message_pending(client) == 0) { + break; + } + + msg = xmlfromIPC(client, MAX_IPC_DELAY); + if (msg != NULL) { + xmlNode *data = get_message_xml(msg, F_CRM_DATA); + + process_pe_message(msg, data, client); + free_xml(msg); + } } - + if (client->ch_status != IPC_CONNECT) { - stay_connected = FALSE; + stay_connected = FALSE; } return stay_connected; } -static void pe_connection_destroy(gpointer user_data) +static void +pe_connection_destroy(gpointer user_data) { return; } static gboolean -pe_client_connect(IPC_Channel *client, gpointer user_data) +pe_client_connect(IPC_Channel * client, gpointer user_data) { crm_debug_3("Invoked"); if (client == NULL) { - crm_err("Channel was NULL"); + crm_err("Channel was NULL"); } else if (client->ch_status == IPC_DISCONNECT) { - crm_err("Channel was disconnected"); + crm_err("Channel was disconnected"); } else { - client->ops->set_recv_qlen(client, 1024); - client->ops->set_send_qlen(client, 1024); - G_main_add_IPC_Channel( - G_PRIORITY_LOW, client, FALSE, pe_msg_callback, NULL, pe_connection_destroy); + client->ops->set_recv_qlen(client, 1024); + client->ops->set_send_qlen(client, 1024); + G_main_add_IPC_Channel(G_PRIORITY_LOW, client, FALSE, pe_msg_callback, NULL, + pe_connection_destroy); } - + return TRUE; } int -main(int argc, char ** argv) +main(int argc, char **argv) { - int flag; - int argerr = 0; - gboolean allow_cores = TRUE; - IPC_Channel *old_instance = NULL; - - crm_system_name = CRM_SYSTEM_PENGINE; - mainloop_add_signal(SIGTERM, pengine_shutdown); - - while ((flag = getopt(argc, argv, OPTARGS)) != EOF) { - switch(flag) { - case 'V': - alter_debug(DEBUG_INC); - break; - case 'h': /* Help message */ - usage(crm_system_name, LSB_EXIT_OK); - break; - case 'c': - allow_cores = TRUE; - break; - default: - ++argerr; - break; - } - } - - if(argc - optind == 1 && safe_str_eq("metadata", argv[optind])) { - pe_metadata(); - return 0; - } - - if (optind > argc) { - ++argerr; - } - - if (argerr) { - usage(crm_system_name,LSB_EXIT_GENERIC); - } - - crm_log_init(NULL, LOG_NOTICE, TRUE, FALSE, argc, argv); - - if(crm_is_writable(PE_STATE_DIR, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == FALSE) { - crm_err("Bad permissions on "PE_STATE_DIR". Terminating"); - fprintf(stderr,"ERROR: Bad permissions on "PE_STATE_DIR". See logs for details\n"); - fflush(stderr); - return 100; - } - - ipc_server = crm_strdup(CRM_SYSTEM_PENGINE); - - /* find any previous instances and shut them down */ - crm_debug("Checking for old instances of %s", crm_system_name); - old_instance = init_client_ipc_comms_nodispatch(CRM_SYSTEM_PENGINE); - while(old_instance != NULL) { - xmlNode *cmd = create_request( - CRM_OP_QUIT, NULL, NULL, CRM_SYSTEM_PENGINE, CRM_SYSTEM_PENGINE, NULL); - - crm_warn("Terminating previous PE instance"); - send_ipc_message(old_instance, cmd); - free_xml(cmd); - - sleep(2); - - old_instance->ops->destroy(old_instance); - old_instance = init_client_ipc_comms_nodispatch(CRM_SYSTEM_PENGINE); - } - - crm_debug("Init server comms"); - if(init_server_ipc_comms(ipc_server, pe_client_connect, - default_ipc_connection_destroy)) { - crm_err("Couldn't start IPC server"); - return 1; - } - - /* Create the mainloop and run it... */ - crm_info("Starting %s", crm_system_name); - - mainloop = g_main_new(FALSE); - g_main_run(mainloop); - + int flag; + int argerr = 0; + gboolean allow_cores = TRUE; + IPC_Channel *old_instance = NULL; + + crm_system_name = CRM_SYSTEM_PENGINE; + mainloop_add_signal(SIGTERM, pengine_shutdown); + + while ((flag = getopt(argc, argv, OPTARGS)) != EOF) { + switch (flag) { + case 'V': + alter_debug(DEBUG_INC); + break; + case 'h': /* Help message */ + usage(crm_system_name, LSB_EXIT_OK); + break; + case 'c': + allow_cores = TRUE; + break; + default: + ++argerr; + break; + } + } + + if (argc - optind == 1 && safe_str_eq("metadata", argv[optind])) { + pe_metadata(); + return 0; + } + + if (optind > argc) { + ++argerr; + } + + if (argerr) { + usage(crm_system_name, LSB_EXIT_GENERIC); + } + + crm_log_init(NULL, LOG_NOTICE, TRUE, FALSE, argc, argv); + + if (crm_is_writable(PE_STATE_DIR, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == FALSE) { + crm_err("Bad permissions on " PE_STATE_DIR ". Terminating"); + fprintf(stderr, "ERROR: Bad permissions on " PE_STATE_DIR ". See logs for details\n"); + fflush(stderr); + return 100; + } + + ipc_server = crm_strdup(CRM_SYSTEM_PENGINE); + + /* find any previous instances and shut them down */ + crm_debug("Checking for old instances of %s", crm_system_name); + old_instance = init_client_ipc_comms_nodispatch(CRM_SYSTEM_PENGINE); + while (old_instance != NULL) { + xmlNode *cmd = + create_request(CRM_OP_QUIT, NULL, NULL, CRM_SYSTEM_PENGINE, CRM_SYSTEM_PENGINE, NULL); + + crm_warn("Terminating previous PE instance"); + send_ipc_message(old_instance, cmd); + free_xml(cmd); + + sleep(2); + + old_instance->ops->destroy(old_instance); + old_instance = init_client_ipc_comms_nodispatch(CRM_SYSTEM_PENGINE); + } + + crm_debug("Init server comms"); + if (init_server_ipc_comms(ipc_server, pe_client_connect, default_ipc_connection_destroy)) { + crm_err("Couldn't start IPC server"); + return 1; + } + + /* Create the mainloop and run it... */ + crm_info("Starting %s", crm_system_name); + + mainloop = g_main_new(FALSE); + g_main_run(mainloop); + #if HAVE_LIBXML2 - crm_xml_cleanup(); + crm_xml_cleanup(); #endif - - crm_info("Exiting %s", crm_system_name); - return 0; -} + crm_info("Exiting %s", crm_system_name); + return 0; +} void -usage(const char* cmd, int exit_status) +usage(const char *cmd, int exit_status) { - FILE* stream; + FILE *stream; - stream = exit_status ? stderr : stdout; + stream = exit_status ? stderr : stdout; - fprintf(stream, "usage: %s [-srkh]" - "[-c configure file]\n", cmd); + fprintf(stream, "usage: %s [-srkh]" "[-c configure file]\n", cmd); /* fprintf(stream, "\t-d\tsets debug level\n"); */ /* fprintf(stream, "\t-s\tgets daemon status\n"); */ /* fprintf(stream, "\t-r\trestarts daemon\n"); */ /* fprintf(stream, "\t-k\tstops daemon\n"); */ /* fprintf(stream, "\t-h\thelp message\n"); */ - fflush(stream); + fflush(stream); - exit(exit_status); + exit(exit_status); } void pengine_shutdown(int nsig) { crm_free(ipc_server); exit(LSB_EXIT_OK); } - diff --git a/pengine/master.c b/pengine/master.c index 1b8a1e8268..68152aa400 100644 --- a/pengine/master.c +++ b/pengine/master.c @@ -1,969 +1,1000 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #define VARIANT_CLONE 1 #include extern gint sort_clone_instance(gconstpointer a, gconstpointer b, gpointer data_set); -extern int master_score(resource_t *rsc, node_t *node, int not_set_value); +extern int master_score(resource_t * rsc, node_t * node, int not_set_value); static void -child_promoting_constraints( - clone_variant_data_t *clone_data, enum pe_ordering type, - resource_t *rsc, resource_t *child, resource_t *last, pe_working_set_t *data_set) +child_promoting_constraints(clone_variant_data_t * clone_data, enum pe_ordering type, + resource_t * rsc, resource_t * child, resource_t * last, + pe_working_set_t * data_set) { - if(child == NULL) { - if(clone_data->ordered && last != NULL) { - crm_debug_4("Ordered version (last node)"); - /* last child promote before promoted started */ - new_rsc_order(last, RSC_PROMOTE, rsc, RSC_PROMOTED, type, data_set); - } - return; + if (child == NULL) { + if (clone_data->ordered && last != NULL) { + crm_debug_4("Ordered version (last node)"); + /* last child promote before promoted started */ + new_rsc_order(last, RSC_PROMOTE, rsc, RSC_PROMOTED, type, data_set); + } + return; } /* child promote before global promoted */ new_rsc_order(child, RSC_PROMOTE, rsc, RSC_PROMOTED, type, data_set); - + /* global promote before child promote */ new_rsc_order(rsc, RSC_PROMOTE, child, RSC_PROMOTE, type, data_set); - if(clone_data->ordered) { - crm_debug_4("Ordered version"); - if(last == NULL) { - /* global promote before first child promote */ - last = rsc; - - } /* else: child/child relative promote */ + if (clone_data->ordered) { + crm_debug_4("Ordered version"); + if (last == NULL) { + /* global promote before first child promote */ + last = rsc; - order_start_start(last, child, type); - new_rsc_order(last, RSC_PROMOTE, child, RSC_PROMOTE, type, data_set); + } + /* else: child/child relative promote */ + order_start_start(last, child, type); + new_rsc_order(last, RSC_PROMOTE, child, RSC_PROMOTE, type, data_set); } else { - crm_debug_4("Un-ordered version"); + crm_debug_4("Un-ordered version"); } } static void -child_demoting_constraints( - clone_variant_data_t *clone_data, enum pe_ordering type, - resource_t *rsc, resource_t *child, resource_t *last, pe_working_set_t *data_set) +child_demoting_constraints(clone_variant_data_t * clone_data, enum pe_ordering type, + resource_t * rsc, resource_t * child, resource_t * last, + pe_working_set_t * data_set) { - if(child == NULL) { - if(clone_data->ordered && last != NULL) { - crm_debug_4("Ordered version (last node)"); - /* global demote before first child demote */ - new_rsc_order(rsc, RSC_DEMOTE, last, RSC_DEMOTE, - pe_order_optional, data_set); - } - return; - } - + if (child == NULL) { + if (clone_data->ordered && last != NULL) { + crm_debug_4("Ordered version (last node)"); + /* global demote before first child demote */ + new_rsc_order(rsc, RSC_DEMOTE, last, RSC_DEMOTE, pe_order_optional, data_set); + } + return; + } + /* child demote before global demoted */ - new_rsc_order(child, RSC_DEMOTE, rsc, RSC_DEMOTED, - pe_order_implies_then_printed, data_set); - + new_rsc_order(child, RSC_DEMOTE, rsc, RSC_DEMOTED, pe_order_implies_then_printed, data_set); + /* global demote before child demote */ - new_rsc_order(rsc, RSC_DEMOTE, child, RSC_DEMOTE, - pe_order_implies_first_printed, data_set); - - if(clone_data->ordered && last != NULL) { - crm_debug_4("Ordered version"); + new_rsc_order(rsc, RSC_DEMOTE, child, RSC_DEMOTE, pe_order_implies_first_printed, data_set); + + if (clone_data->ordered && last != NULL) { + crm_debug_4("Ordered version"); - /* child/child relative demote */ - new_rsc_order(child, RSC_DEMOTE, last, RSC_DEMOTE, type, data_set); + /* child/child relative demote */ + new_rsc_order(child, RSC_DEMOTE, last, RSC_DEMOTE, type, data_set); - } else if(clone_data->ordered) { - crm_debug_4("Ordered version (1st node)"); - /* first child stop before global stopped */ - new_rsc_order(child, RSC_DEMOTE, rsc, RSC_DEMOTED, type, data_set); + } else if (clone_data->ordered) { + crm_debug_4("Ordered version (1st node)"); + /* first child stop before global stopped */ + new_rsc_order(child, RSC_DEMOTE, rsc, RSC_DEMOTED, type, data_set); } else { - crm_debug_4("Un-ordered version"); + crm_debug_4("Un-ordered version"); } } static void -master_update_pseudo_status( - resource_t *rsc, gboolean *demoting, gboolean *promoting) -{ +master_update_pseudo_status(resource_t * rsc, gboolean * demoting, gboolean * promoting) +{ GListPtr gIter = NULL; - if(rsc->children) { - gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - master_update_pseudo_status(child, demoting, promoting); - } - return; - } - + + if (rsc->children) { + gIter = rsc->children; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + master_update_pseudo_status(child, demoting, promoting); + } + return; + } + CRM_ASSERT(demoting != NULL); CRM_ASSERT(promoting != NULL); gIter = rsc->actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - - if(*promoting && *demoting) { - return; + for (; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; - } else if(is_set(action->flags, pe_action_optional)) { - continue; + if (*promoting && *demoting) { + return; - } else if(safe_str_eq(RSC_DEMOTE, action->task)) { - *demoting = TRUE; + } else if (is_set(action->flags, pe_action_optional)) { + continue; - } else if(safe_str_eq(RSC_PROMOTE, action->task)) { - *promoting = TRUE; - } + } else if (safe_str_eq(RSC_DEMOTE, action->task)) { + *demoting = TRUE; + + } else if (safe_str_eq(RSC_PROMOTE, action->task)) { + *promoting = TRUE; + } } } #define apply_master_location(list) do { \ gIter2 = list; \ for(; gIter2 != NULL; gIter2 = gIter2->next) { \ rsc_to_node_t *cons = (rsc_to_node_t*)gIter2->data; \ \ cons_node = NULL; \ if(cons->role_filter == RSC_ROLE_MASTER) { \ crm_debug_2("Applying %s to %s", \ cons->id, child_rsc->id); \ cons_node = pe_find_node_id( \ cons->node_list_rh, chosen->details->id); \ } \ if(cons_node != NULL) { \ int new_priority = merge_weights( \ child_rsc->priority, cons_node->weight); \ crm_debug_2("\t%s: %d->%d (%d)", child_rsc->id, \ child_rsc->priority, new_priority, cons_node->weight); \ child_rsc->priority = new_priority; \ } \ } \ } while(0) static node_t * -can_be_master(resource_t *rsc) +can_be_master(resource_t * rsc) { node_t *node = NULL; node_t *local_node = NULL; resource_t *parent = uber_parent(rsc); clone_variant_data_t *clone_data = NULL; int level = LOG_DEBUG_2; + #if 0 enum rsc_role_e role = RSC_ROLE_UNKNOWN; + role = rsc->fns->state(rsc, FALSE); crm_info("%s role: %s", rsc->id, role2text(role)); #endif - - if(rsc->children) { - GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - if(can_be_master(child) == NULL) { - do_crm_log_unlikely(level, "Child %s of %s can't be promoted", child->id, rsc->id); - return NULL; - } - } + if (rsc->children) { + GListPtr gIter = rsc->children; + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + if (can_be_master(child) == NULL) { + do_crm_log_unlikely(level, "Child %s of %s can't be promoted", child->id, rsc->id); + return NULL; + } + } } node = rsc->fns->location(rsc, NULL, FALSE); - if(node == NULL) { - do_crm_log_unlikely(level, "%s cannot be master: not allocated", rsc->id); - return NULL; - - } else if(is_not_set(rsc->flags, pe_rsc_managed)) { - if(rsc->fns->state(rsc, TRUE) == RSC_ROLE_MASTER) { - crm_notice("Forcing unmanaged master %s to remain promoted on %s", - rsc->id, node->details->uname); - - } else { - return NULL; - } - - } else if(rsc->priority < 0) { - do_crm_log_unlikely(level, "%s cannot be master: preference: %d", - rsc->id, rsc->priority); - return NULL; - - } else if(can_run_resources(node) == FALSE) { - do_crm_log_unlikely(level, "Node cant run any resources: %s", - node->details->uname); - return NULL; - } - + if (node == NULL) { + do_crm_log_unlikely(level, "%s cannot be master: not allocated", rsc->id); + return NULL; + + } else if (is_not_set(rsc->flags, pe_rsc_managed)) { + if (rsc->fns->state(rsc, TRUE) == RSC_ROLE_MASTER) { + crm_notice("Forcing unmanaged master %s to remain promoted on %s", + rsc->id, node->details->uname); + + } else { + return NULL; + } + + } else if (rsc->priority < 0) { + do_crm_log_unlikely(level, "%s cannot be master: preference: %d", rsc->id, rsc->priority); + return NULL; + + } else if (can_run_resources(node) == FALSE) { + do_crm_log_unlikely(level, "Node cant run any resources: %s", node->details->uname); + return NULL; + } + get_clone_variant_data(clone_data, parent); - local_node = pe_hash_table_lookup( - parent->allowed_nodes, node->details->id); + local_node = pe_hash_table_lookup(parent->allowed_nodes, node->details->id); - if(local_node == NULL) { - crm_err("%s cannot run on %s: node not allowed", - rsc->id, node->details->uname); - return NULL; + if (local_node == NULL) { + crm_err("%s cannot run on %s: node not allowed", rsc->id, node->details->uname); + return NULL; - } else if(local_node->count < clone_data->master_node_max - || is_not_set(rsc->flags, pe_rsc_managed)) { - return local_node; + } else if (local_node->count < clone_data->master_node_max + || is_not_set(rsc->flags, pe_rsc_managed)) { + return local_node; } else { - do_crm_log_unlikely(level, "%s cannot be master on %s: node full", - rsc->id, node->details->uname); + do_crm_log_unlikely(level, "%s cannot be master on %s: node full", + rsc->id, node->details->uname); } return NULL; } -static gint sort_master_instance(gconstpointer a, gconstpointer b, gpointer data_set) +static gint +sort_master_instance(gconstpointer a, gconstpointer b, gpointer data_set) { int rc; enum rsc_role_e role1 = RSC_ROLE_UNKNOWN; enum rsc_role_e role2 = RSC_ROLE_UNKNOWN; - const resource_t *resource1 = (const resource_t*)a; - const resource_t *resource2 = (const resource_t*)b; + const resource_t *resource1 = (const resource_t *)a; + const resource_t *resource2 = (const resource_t *)b; CRM_ASSERT(resource1 != NULL); CRM_ASSERT(resource2 != NULL); role1 = resource1->fns->state(resource1, TRUE); role2 = resource2->fns->state(resource2, TRUE); - + rc = sort_rsc_index(a, b); - if( rc != 0 ) { - crm_trace("%s %c %s (index)", resource1->id, rc<0?'<':'>', resource2->id); - return rc; + if (rc != 0) { + crm_trace("%s %c %s (index)", resource1->id, rc < 0 ? '<' : '>', resource2->id); + return rc; } - - if(role1 > role2) { - crm_trace("%s %c %s (role)", resource1->id, '<', resource2->id); - return -1; - } else if(role1 < role2) { - crm_trace("%s %c %s (role)", resource1->id, '>', resource2->id); - return 1; + if (role1 > role2) { + crm_trace("%s %c %s (role)", resource1->id, '<', resource2->id); + return -1; + + } else if (role1 < role2) { + crm_trace("%s %c %s (role)", resource1->id, '>', resource2->id); + return 1; } - + return sort_clone_instance(a, b, data_set); } -static void master_promotion_order(resource_t *rsc, pe_working_set_t *data_set) +static void +master_promotion_order(resource_t * rsc, pe_working_set_t * data_set) { GListPtr gIter = NULL; node_t *node = NULL; node_t *chosen = NULL; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); - if(clone_data->merged_master_weights) { - return; + if (clone_data->merged_master_weights) { + return; } clone_data->merged_master_weights = TRUE; crm_debug_2("Merging weights for %s", rsc->id); set_bit(rsc->flags, pe_rsc_merging); gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; - crm_debug_2("Sort index: %s = %d", child->id, child->sort_index); + crm_debug_2("Sort index: %s = %d", child->id, child->sort_index); } dump_node_scores(LOG_DEBUG_3, rsc, "Before", rsc->allowed_nodes); gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - - chosen = child->fns->location(child, NULL, FALSE); - if(chosen == NULL || child->sort_index < 0) { - crm_debug_3("Skipping %s", child->id); - continue; - } - - node = (node_t*)pe_hash_table_lookup( - rsc->allowed_nodes, chosen->details->id); - CRM_ASSERT(node != NULL); - /* adds in master preferences and rsc_location.role=Master */ - crm_trace("Adding %s to %s from %s", score2char(child->sort_index), node->details->uname, child->id); - node->weight = merge_weights(child->sort_index, node->weight); - } - + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + chosen = child->fns->location(child, NULL, FALSE); + if (chosen == NULL || child->sort_index < 0) { + crm_debug_3("Skipping %s", child->id); + continue; + } + + node = (node_t *) pe_hash_table_lookup(rsc->allowed_nodes, chosen->details->id); + CRM_ASSERT(node != NULL); + /* adds in master preferences and rsc_location.role=Master */ + crm_trace("Adding %s to %s from %s", score2char(child->sort_index), node->details->uname, + child->id); + node->weight = merge_weights(child->sort_index, node->weight); + } + dump_node_scores(LOG_DEBUG_3, rsc, "Middle", rsc->allowed_nodes); gIter = rsc->rsc_cons; - for(; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - - /* (re-)adds location preferences of resources that the - * master instance should/must be colocated with - */ - if(constraint->role_lh == RSC_ROLE_MASTER) { - crm_debug_2("RHS: %s with %s: %d", constraint->rsc_lh->id, constraint->rsc_rh->id, constraint->score); - rsc->allowed_nodes = constraint->rsc_rh->cmds->merge_weights( - constraint->rsc_rh, rsc->id, rsc->allowed_nodes, - constraint->node_attribute, constraint->score/INFINITY, constraint->score==INFINITY?FALSE:TRUE, FALSE); - } - } - + for (; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + /* (re-)adds location preferences of resources that the + * master instance should/must be colocated with + */ + if (constraint->role_lh == RSC_ROLE_MASTER) { + crm_debug_2("RHS: %s with %s: %d", constraint->rsc_lh->id, constraint->rsc_rh->id, + constraint->score); + rsc->allowed_nodes = + constraint->rsc_rh->cmds->merge_weights(constraint->rsc_rh, rsc->id, + rsc->allowed_nodes, + constraint->node_attribute, + constraint->score / INFINITY, + constraint->score == + INFINITY ? FALSE : TRUE, FALSE); + } + } + gIter = rsc->rsc_cons_lhs; - for(; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - - /* (re-)adds location preferences of resource that wish to be - * colocated with the master instance - */ - if(constraint->role_rh == RSC_ROLE_MASTER) { - crm_debug_2("LHS: %s with %s: %d", constraint->rsc_lh->id, constraint->rsc_rh->id, constraint->score); - rsc->allowed_nodes = constraint->rsc_lh->cmds->merge_weights( - constraint->rsc_lh, rsc->id, rsc->allowed_nodes, - constraint->node_attribute, constraint->score/INFINITY, TRUE, TRUE); - } + for (; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + /* (re-)adds location preferences of resource that wish to be + * colocated with the master instance + */ + if (constraint->role_rh == RSC_ROLE_MASTER) { + crm_debug_2("LHS: %s with %s: %d", constraint->rsc_lh->id, constraint->rsc_rh->id, + constraint->score); + rsc->allowed_nodes = + constraint->rsc_lh->cmds->merge_weights(constraint->rsc_lh, rsc->id, + rsc->allowed_nodes, + constraint->node_attribute, + constraint->score / INFINITY, TRUE, TRUE); + } } gIter = rsc->rsc_tickets; - for(; gIter != NULL; gIter = gIter->next) { - rsc_ticket_t *rsc_ticket = (rsc_ticket_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + rsc_ticket_t *rsc_ticket = (rsc_ticket_t *) gIter->data; - if(rsc_ticket->role_lh == RSC_ROLE_MASTER && rsc_ticket->ticket->granted == FALSE) { - resource_location(rsc, NULL, -INFINITY, "__stateful_without_ticket__", data_set); - } + if (rsc_ticket->role_lh == RSC_ROLE_MASTER && rsc_ticket->ticket->granted == FALSE) { + resource_location(rsc, NULL, -INFINITY, "__stateful_without_ticket__", data_set); + } } dump_node_scores(LOG_DEBUG_3, rsc, "After", rsc->allowed_nodes); /* write them back and sort */ - + gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; - chosen = child->fns->location(child, NULL, FALSE); - if(is_not_set(child->flags, pe_rsc_managed) && child->next_role == RSC_ROLE_MASTER) { - child->sort_index = INFINITY; + chosen = child->fns->location(child, NULL, FALSE); + if (is_not_set(child->flags, pe_rsc_managed) && child->next_role == RSC_ROLE_MASTER) { + child->sort_index = INFINITY; - } else if(chosen == NULL || child->sort_index < 0) { - crm_debug_2("%s: %d", child->id, child->sort_index); + } else if (chosen == NULL || child->sort_index < 0) { + crm_debug_2("%s: %d", child->id, child->sort_index); - } else { - node = (node_t*)pe_hash_table_lookup( - rsc->allowed_nodes, chosen->details->id); - CRM_ASSERT(node != NULL); - - child->sort_index = node->weight; - } - crm_debug_2("Set sort index: %s = %d", child->id, child->sort_index); + } else { + node = (node_t *) pe_hash_table_lookup(rsc->allowed_nodes, chosen->details->id); + CRM_ASSERT(node != NULL); + + child->sort_index = node->weight; + } + crm_debug_2("Set sort index: %s = %d", child->id, child->sort_index); } rsc->children = g_list_sort_with_data(rsc->children, sort_master_instance, data_set); clear_bit(rsc->flags, pe_rsc_merging); } int -master_score(resource_t *rsc, node_t *node, int not_set_value) +master_score(resource_t * rsc, node_t * node, int not_set_value) { char *attr_name; char *name = rsc->id; const char *attr_value = NULL; int score = not_set_value, len = 0; - if(rsc->children) { - GListPtr gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - int c_score = master_score(child, node, not_set_value); - - if(score == not_set_value) { - score = c_score; - } else { - score += c_score; - } - } - return score; - } - - if(rsc->fns->state(rsc, TRUE) < RSC_ROLE_STARTED) { - return score; - } - - if(node != NULL) { - node_t *match = pe_find_node_id(rsc->running_on, node->details->id); - if(match == NULL) { - crm_debug_2("%s is not active on %s - ignoring", - rsc->id, node->details->uname); - return score; - } - - match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id); - if(match == NULL) { - return score; - - } else if(match->weight < 0) { - crm_trace("%s on %s has score: %d - ignoring", - rsc->id, match->details->uname, match->weight); - return score; - } - } - - if(rsc->clone_name) { - /* Use the name the lrm knows this resource as, - * since that's what crm_master would have used too - */ - name = rsc->clone_name; + if (rsc->children) { + GListPtr gIter = rsc->children; + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + int c_score = master_score(child, node, not_set_value); + + if (score == not_set_value) { + score = c_score; + } else { + score += c_score; + } + } + return score; + } + + if (rsc->fns->state(rsc, TRUE) < RSC_ROLE_STARTED) { + return score; + } + + if (node != NULL) { + node_t *match = pe_find_node_id(rsc->running_on, node->details->id); + + if (match == NULL) { + crm_debug_2("%s is not active on %s - ignoring", rsc->id, node->details->uname); + return score; + } + + match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id); + if (match == NULL) { + return score; + + } else if (match->weight < 0) { + crm_trace("%s on %s has score: %d - ignoring", + rsc->id, match->details->uname, match->weight); + return score; + } + } + + if (rsc->clone_name) { + /* Use the name the lrm knows this resource as, + * since that's what crm_master would have used too + */ + name = rsc->clone_name; } len = 8 + strlen(name); crm_malloc0(attr_name, len); sprintf(attr_name, "master-%s", name); - if(node) { - attr_value = g_hash_table_lookup(node->details->attrs, attr_name); - crm_trace("%s: %s[%s] = %s", - rsc->id, attr_name, node->details->uname, crm_str(attr_value)); + if (node) { + attr_value = g_hash_table_lookup(node->details->attrs, attr_name); + crm_trace("%s: %s[%s] = %s", rsc->id, attr_name, node->details->uname, crm_str(attr_value)); } - - if(attr_value != NULL) { - score = char2score(attr_value); + + if (attr_value != NULL) { + score = char2score(attr_value); } crm_free(attr_name); return score; } #define max(a, b) achildren; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); - - if(clone_data->applied_master_prefs) { - /* Make sure we only do this once */ - return; + + if (clone_data->applied_master_prefs) { + /* Make sure we only do this once */ + return; } - + clone_data->applied_master_prefs = TRUE; - - for(; gIter != NULL; gIter = gIter->next) { - GHashTableIter iter; - node_t *node = NULL; - resource_t *child_rsc = (resource_t*)gIter->data; - - g_hash_table_iter_init (&iter, child_rsc->allowed_nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - if(can_run_resources(node) == FALSE) { - /* This node will never be promoted to master, - * so don't apply the master score as that may - * lead to clone shuffling - */ - continue; - } - - score = master_score(child_rsc, node, 0); - if(score > 0) { - new_score = merge_weights(node->weight, score); - if(new_score != node->weight) { - crm_debug_2("\t%s: Updating preference for %s (%d->%d)", - child_rsc->id, node->details->uname, node->weight, new_score); - node->weight = new_score; - } - } - - new_score = max(child_rsc->priority, score); - if(new_score != child_rsc->priority) { - crm_debug_2("\t%s: Updating priority (%d->%d)", - child_rsc->id, child_rsc->priority, new_score); - child_rsc->priority = new_score; - } - } + + for (; gIter != NULL; gIter = gIter->next) { + GHashTableIter iter; + node_t *node = NULL; + resource_t *child_rsc = (resource_t *) gIter->data; + + g_hash_table_iter_init(&iter, child_rsc->allowed_nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + if (can_run_resources(node) == FALSE) { + /* This node will never be promoted to master, + * so don't apply the master score as that may + * lead to clone shuffling + */ + continue; + } + + score = master_score(child_rsc, node, 0); + if (score > 0) { + new_score = merge_weights(node->weight, score); + if (new_score != node->weight) { + crm_debug_2("\t%s: Updating preference for %s (%d->%d)", + child_rsc->id, node->details->uname, node->weight, new_score); + node->weight = new_score; + } + } + + new_score = max(child_rsc->priority, score); + if (new_score != child_rsc->priority) { + crm_debug_2("\t%s: Updating priority (%d->%d)", + child_rsc->id, child_rsc->priority, new_score); + child_rsc->priority = new_score; + } + } } } -static void set_role_slave(resource_t *rsc, gboolean current) +static void +set_role_slave(resource_t * rsc, gboolean current) { GListPtr gIter = rsc->children; - if(current) { - if(rsc->role == RSC_ROLE_STARTED) { - rsc->role = RSC_ROLE_SLAVE; - } - + + if (current) { + if (rsc->role == RSC_ROLE_STARTED) { + rsc->role = RSC_ROLE_SLAVE; + } + } else { - GListPtr allocated = NULL; - rsc->fns->location(rsc, &allocated, FALSE); - - if(allocated) { - rsc->next_role = RSC_ROLE_SLAVE; - - } else { - rsc->next_role = RSC_ROLE_STOPPED; - } - g_list_free(allocated); - } - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - set_role_slave(child_rsc, current); + GListPtr allocated = NULL; + + rsc->fns->location(rsc, &allocated, FALSE); + + if (allocated) { + rsc->next_role = RSC_ROLE_SLAVE; + + } else { + rsc->next_role = RSC_ROLE_STOPPED; + } + g_list_free(allocated); + } + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + set_role_slave(child_rsc, current); } } -static void set_role_master(resource_t *rsc) +static void +set_role_master(resource_t * rsc) { GListPtr gIter = rsc->children; - if(rsc->next_role == RSC_ROLE_UNKNOWN) { - rsc->next_role = RSC_ROLE_MASTER; + + if (rsc->next_role == RSC_ROLE_UNKNOWN) { + rsc->next_role = RSC_ROLE_MASTER; } - - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - set_role_master(child_rsc); + + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + set_role_master(child_rsc); } } node_t * -master_color(resource_t *rsc, node_t *prefer, pe_working_set_t *data_set) +master_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set) { int promoted = 0; GListPtr gIter = NULL; GListPtr gIter2 = NULL; GHashTableIter iter; node_t *node = NULL; node_t *chosen = NULL; node_t *cons_node = NULL; enum rsc_role_e next_role = RSC_ROLE_UNKNOWN; - + clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); - if(is_not_set(rsc->flags, pe_rsc_provisional)) { - return NULL; + if (is_not_set(rsc->flags, pe_rsc_provisional)) { + return NULL; - } else if(is_set(rsc->flags, pe_rsc_allocating)) { - crm_debug("Dependency loop detected involving %s", rsc->id); - return NULL; + } else if (is_set(rsc->flags, pe_rsc_allocating)) { + crm_debug("Dependency loop detected involving %s", rsc->id); + return NULL; } - + apply_master_prefs(rsc); clone_color(rsc, prefer, data_set); - + set_bit(rsc->flags, pe_rsc_allocating); /* count now tracks the number of masters allocated */ - g_hash_table_iter_init (&iter, rsc->allowed_nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - node->count = 0; + g_hash_table_iter_init(&iter, rsc->allowed_nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + node->count = 0; } /* * assign priority - */ + */ gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - GListPtr list = NULL; - resource_t *child_rsc = (resource_t*)gIter->data; - - crm_debug_2("Assigning priority for %s: %s", child_rsc->id, role2text(child_rsc->next_role)); - - if(child_rsc->fns->state(child_rsc, TRUE) == RSC_ROLE_STARTED) { - set_role_slave(child_rsc, TRUE); - } - - chosen = child_rsc->fns->location(child_rsc, &list, FALSE); - if(g_list_length(list) > 1) { - crm_config_err("Cannot promote non-colocated child %s", child_rsc->id); - } - - g_list_free(list); - if(chosen == NULL) { - continue; - } - - next_role = child_rsc->fns->state(child_rsc, FALSE); - switch(next_role) { - case RSC_ROLE_STARTED: - case RSC_ROLE_UNKNOWN: - CRM_CHECK(chosen != NULL, break); - /* - * Default to -1 if no value is set - * - * This allows master locations to be specified - * based solely on rsc_location constraints, - * but prevents anyone from being promoted if - * neither a constraint nor a master-score is present - */ - child_rsc->priority = master_score(child_rsc, chosen, -1); - break; - - case RSC_ROLE_SLAVE: - case RSC_ROLE_STOPPED: - child_rsc->priority = -INFINITY; - break; - case RSC_ROLE_MASTER: - /* We will arrive here if we're re-creating actions after a stonith - */ - break; - default: - CRM_CHECK(FALSE/* unhandled */, - crm_err("Unknown resource role: %d for %s", - next_role, child_rsc->id)); - } - - apply_master_location(child_rsc->rsc_location); - apply_master_location(rsc->rsc_location); - - gIter2 = child_rsc->rsc_cons; - for(; gIter2 != NULL; gIter2 = gIter2->next) { - rsc_colocation_t *cons = (rsc_colocation_t*)gIter2->data; - child_rsc->cmds->rsc_colocation_lh(child_rsc, cons->rsc_rh, cons); - } - - child_rsc->sort_index = child_rsc->priority; - crm_debug_2("Assigning priority for %s: %d", child_rsc->id, child_rsc->priority); - - if(next_role == RSC_ROLE_MASTER) { - child_rsc->sort_index = INFINITY; - } - } - + for (; gIter != NULL; gIter = gIter->next) { + GListPtr list = NULL; + resource_t *child_rsc = (resource_t *) gIter->data; + + crm_debug_2("Assigning priority for %s: %s", child_rsc->id, + role2text(child_rsc->next_role)); + + if (child_rsc->fns->state(child_rsc, TRUE) == RSC_ROLE_STARTED) { + set_role_slave(child_rsc, TRUE); + } + + chosen = child_rsc->fns->location(child_rsc, &list, FALSE); + if (g_list_length(list) > 1) { + crm_config_err("Cannot promote non-colocated child %s", child_rsc->id); + } + + g_list_free(list); + if (chosen == NULL) { + continue; + } + + next_role = child_rsc->fns->state(child_rsc, FALSE); + switch (next_role) { + case RSC_ROLE_STARTED: + case RSC_ROLE_UNKNOWN: + CRM_CHECK(chosen != NULL, break); + /* + * Default to -1 if no value is set + * + * This allows master locations to be specified + * based solely on rsc_location constraints, + * but prevents anyone from being promoted if + * neither a constraint nor a master-score is present + */ + child_rsc->priority = master_score(child_rsc, chosen, -1); + break; + + case RSC_ROLE_SLAVE: + case RSC_ROLE_STOPPED: + child_rsc->priority = -INFINITY; + break; + case RSC_ROLE_MASTER: + /* We will arrive here if we're re-creating actions after a stonith + */ + break; + default: + CRM_CHECK(FALSE /* unhandled */ , + crm_err("Unknown resource role: %d for %s", next_role, child_rsc->id)); + } + + apply_master_location(child_rsc->rsc_location); + apply_master_location(rsc->rsc_location); + + gIter2 = child_rsc->rsc_cons; + for (; gIter2 != NULL; gIter2 = gIter2->next) { + rsc_colocation_t *cons = (rsc_colocation_t *) gIter2->data; + + child_rsc->cmds->rsc_colocation_lh(child_rsc, cons->rsc_rh, cons); + } + + child_rsc->sort_index = child_rsc->priority; + crm_debug_2("Assigning priority for %s: %d", child_rsc->id, child_rsc->priority); + + if (next_role == RSC_ROLE_MASTER) { + child_rsc->sort_index = INFINITY; + } + } + dump_node_scores(LOG_DEBUG_3, rsc, "Pre merge", rsc->allowed_nodes); master_promotion_order(rsc, data_set); /* mark the first N as masters */ gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - char *score = score2char(child_rsc->sort_index); - - chosen = child_rsc->fns->location(child_rsc, NULL, FALSE); - if(show_scores) { - fprintf(stdout, "%s promotion score on %s: %s\n", - child_rsc->id, chosen?chosen->details->uname:"none", score); - - } else { - do_crm_log_unlikely(scores_log_level, "%s promotion score on %s: %s", - child_rsc->id, chosen?chosen->details->uname:"none", score); - } - crm_free(score); - - chosen = NULL; /* nuke 'chosen' so that we don't promote more than the - * required number of instances - */ - - if(child_rsc->sort_index < 0) { - crm_debug_2("Not supposed to promote child: %s", child_rsc->id); - - } else if(promoted < clone_data->master_max || is_not_set(rsc->flags, pe_rsc_managed)) { - chosen = can_be_master(child_rsc); - } - - crm_debug("%s master score: %d", child_rsc->id, child_rsc->priority); - - if(chosen == NULL) { - set_role_slave(child_rsc, FALSE); - continue; - } - - chosen->count++; - crm_info("Promoting %s (%s %s)", - child_rsc->id, role2text(child_rsc->role), chosen->details->uname); - set_role_master(child_rsc); - promoted++; - } - + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + char *score = score2char(child_rsc->sort_index); + + chosen = child_rsc->fns->location(child_rsc, NULL, FALSE); + if (show_scores) { + fprintf(stdout, "%s promotion score on %s: %s\n", + child_rsc->id, chosen ? chosen->details->uname : "none", score); + + } else { + do_crm_log_unlikely(scores_log_level, "%s promotion score on %s: %s", + child_rsc->id, chosen ? chosen->details->uname : "none", score); + } + crm_free(score); + + chosen = NULL; /* nuke 'chosen' so that we don't promote more than the + * required number of instances + */ + + if (child_rsc->sort_index < 0) { + crm_debug_2("Not supposed to promote child: %s", child_rsc->id); + + } else if (promoted < clone_data->master_max || is_not_set(rsc->flags, pe_rsc_managed)) { + chosen = can_be_master(child_rsc); + } + + crm_debug("%s master score: %d", child_rsc->id, child_rsc->priority); + + if (chosen == NULL) { + set_role_slave(child_rsc, FALSE); + continue; + } + + chosen->count++; + crm_info("Promoting %s (%s %s)", + child_rsc->id, role2text(child_rsc->role), chosen->details->uname); + set_role_master(child_rsc); + promoted++; + } + clone_data->masters_allocated = promoted; crm_info("%s: Promoted %d instances of a possible %d to master", - rsc->id, promoted, clone_data->master_max); + rsc->id, promoted, clone_data->master_max); clear_bit(rsc->flags, pe_rsc_provisional); clear_bit(rsc->flags, pe_rsc_allocating); return NULL; } -void master_create_actions(resource_t *rsc, pe_working_set_t *data_set) +void +master_create_actions(resource_t * rsc, pe_working_set_t * data_set) { action_t *action = NULL; GListPtr gIter = rsc->children; action_t *action_complete = NULL; gboolean any_promoting = FALSE; gboolean any_demoting = FALSE; resource_t *last_promote_rsc = NULL; resource_t *last_demote_rsc = NULL; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); - + crm_debug("Creating actions for %s", rsc->id); /* create actions as normal */ clone_create_actions(rsc, data_set); - for(; gIter != NULL; gIter = gIter->next) { - gboolean child_promoting = FALSE; - gboolean child_demoting = FALSE; - resource_t *child_rsc = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + gboolean child_promoting = FALSE; + gboolean child_demoting = FALSE; + resource_t *child_rsc = (resource_t *) gIter->data; - crm_debug_2("Creating actions for %s", child_rsc->id); - child_rsc->cmds->create_actions(child_rsc, data_set); - master_update_pseudo_status( - child_rsc, &child_demoting, &child_promoting); + crm_debug_2("Creating actions for %s", child_rsc->id); + child_rsc->cmds->create_actions(child_rsc, data_set); + master_update_pseudo_status(child_rsc, &child_demoting, &child_promoting); - any_demoting = any_demoting || child_demoting; - any_promoting = any_promoting || child_promoting; - crm_debug_2("Created actions for %s: %d %d", child_rsc->id, child_promoting, child_demoting); + any_demoting = any_demoting || child_demoting; + any_promoting = any_promoting || child_promoting; + crm_debug_2("Created actions for %s: %d %d", child_rsc->id, child_promoting, + child_demoting); } - + /* promote */ action = promote_action(rsc, NULL, !any_promoting); - action_complete = custom_action( - rsc, promoted_key(rsc), - RSC_PROMOTED, NULL, !any_promoting, TRUE, data_set); + action_complete = custom_action(rsc, promoted_key(rsc), + RSC_PROMOTED, NULL, !any_promoting, TRUE, data_set); action_complete->priority = INFINITY; update_action_flags(action, pe_action_pseudo); update_action_flags(action, pe_action_runnable); update_action_flags(action_complete, pe_action_pseudo); update_action_flags(action_complete, pe_action_runnable); - if(clone_data->masters_allocated > 0) { - update_action_flags(action, pe_action_runnable); - update_action_flags(action_complete, pe_action_runnable); + if (clone_data->masters_allocated > 0) { + update_action_flags(action, pe_action_runnable); + update_action_flags(action_complete, pe_action_runnable); } - - child_promoting_constraints(clone_data, pe_order_optional, - rsc, NULL, last_promote_rsc, data_set); - if(clone_data->promote_notify == NULL) { - clone_data->promote_notify = create_notification_boundaries( - rsc, RSC_PROMOTE, action, action_complete, data_set); + child_promoting_constraints(clone_data, pe_order_optional, + rsc, NULL, last_promote_rsc, data_set); + + if (clone_data->promote_notify == NULL) { + clone_data->promote_notify = + create_notification_boundaries(rsc, RSC_PROMOTE, action, action_complete, data_set); } - + /* demote */ action = demote_action(rsc, NULL, !any_demoting); - action_complete = custom_action( - rsc, demoted_key(rsc), - RSC_DEMOTED, NULL, !any_demoting, TRUE, data_set); + action_complete = custom_action(rsc, demoted_key(rsc), + RSC_DEMOTED, NULL, !any_demoting, TRUE, data_set); action_complete->priority = INFINITY; update_action_flags(action, pe_action_pseudo); update_action_flags(action, pe_action_runnable); update_action_flags(action_complete, pe_action_pseudo); update_action_flags(action_complete, pe_action_runnable); - - child_demoting_constraints(clone_data, pe_order_optional, - rsc, NULL, last_demote_rsc, data_set); - - if(clone_data->demote_notify == NULL) { - clone_data->demote_notify = create_notification_boundaries( - rsc, RSC_DEMOTE, action, action_complete, data_set); - - if(clone_data->promote_notify) { - /* If we ever wanted groups to have notifications we'd need to move this to native_internal_constraints() one day - * Requires exposing *_notify - */ - order_actions(clone_data->stop_notify->post_done, clone_data->promote_notify->pre, pe_order_optional); - order_actions(clone_data->start_notify->post_done, clone_data->promote_notify->pre, pe_order_optional); - order_actions(clone_data->demote_notify->post_done, clone_data->promote_notify->pre, pe_order_optional); - order_actions(clone_data->demote_notify->post_done, clone_data->start_notify->pre, pe_order_optional); - order_actions(clone_data->demote_notify->post_done, clone_data->stop_notify->pre, pe_order_optional); - } - } - - /* restore the correct priority */ + + child_demoting_constraints(clone_data, pe_order_optional, rsc, NULL, last_demote_rsc, data_set); + + if (clone_data->demote_notify == NULL) { + clone_data->demote_notify = + create_notification_boundaries(rsc, RSC_DEMOTE, action, action_complete, data_set); + + if (clone_data->promote_notify) { + /* If we ever wanted groups to have notifications we'd need to move this to native_internal_constraints() one day + * Requires exposing *_notify + */ + order_actions(clone_data->stop_notify->post_done, clone_data->promote_notify->pre, + pe_order_optional); + order_actions(clone_data->start_notify->post_done, clone_data->promote_notify->pre, + pe_order_optional); + order_actions(clone_data->demote_notify->post_done, clone_data->promote_notify->pre, + pe_order_optional); + order_actions(clone_data->demote_notify->post_done, clone_data->start_notify->pre, + pe_order_optional); + order_actions(clone_data->demote_notify->post_done, clone_data->stop_notify->pre, + pe_order_optional); + } + } + + /* restore the correct priority */ gIter = rsc->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - child_rsc->priority = rsc->priority; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->priority = rsc->priority; } } void -master_internal_constraints(resource_t *rsc, pe_working_set_t *data_set) +master_internal_constraints(resource_t * rsc, pe_working_set_t * data_set) { GListPtr gIter = rsc->children; - resource_t *last_rsc = NULL; + resource_t *last_rsc = NULL; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); clone_internal_constraints(rsc, data_set); - + /* global stopped before start */ new_rsc_order(rsc, RSC_STOPPED, rsc, RSC_START, pe_order_optional, data_set); /* global stopped before promote */ new_rsc_order(rsc, RSC_STOPPED, rsc, RSC_PROMOTE, pe_order_optional, data_set); /* global demoted before start */ new_rsc_order(rsc, RSC_DEMOTED, rsc, RSC_START, pe_order_optional, data_set); /* global started before promote */ new_rsc_order(rsc, RSC_STARTED, rsc, RSC_PROMOTE, pe_order_optional, data_set); /* global demoted before stop */ new_rsc_order(rsc, RSC_DEMOTED, rsc, RSC_STOP, pe_order_optional, data_set); /* global demote before demoted */ new_rsc_order(rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, pe_order_optional, data_set); /* global demoted before promote */ new_rsc_order(rsc, RSC_DEMOTED, rsc, RSC_PROMOTE, pe_order_optional, data_set); - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + /* child demote before promote */ + new_rsc_order(child_rsc, RSC_DEMOTE, child_rsc, RSC_PROMOTE, pe_order_optional, data_set); - /* child demote before promote */ - new_rsc_order(child_rsc, RSC_DEMOTE, child_rsc, RSC_PROMOTE, pe_order_optional, data_set); - - child_promoting_constraints(clone_data, pe_order_optional, - rsc, child_rsc, last_rsc, data_set); + child_promoting_constraints(clone_data, pe_order_optional, + rsc, child_rsc, last_rsc, data_set); - child_demoting_constraints(clone_data, pe_order_optional, - rsc, child_rsc, last_rsc, data_set); + child_demoting_constraints(clone_data, pe_order_optional, + rsc, child_rsc, last_rsc, data_set); - last_rsc = child_rsc; + last_rsc = child_rsc; } } -static void node_hash_update_one(GHashTable *hash, node_t *other, const char *attr, int score) +static void +node_hash_update_one(GHashTable * hash, node_t * other, const char *attr, int score) { GHashTableIter iter; node_t *node = NULL; const char *value = NULL; - - if(other == NULL) { - return; - } else if(attr == NULL) { - attr = "#"XML_ATTR_UNAME; + if (other == NULL) { + return; + + } else if (attr == NULL) { + attr = "#" XML_ATTR_UNAME; } - + value = g_hash_table_lookup(other->details->attrs, attr); - g_hash_table_iter_init (&iter, hash); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - const char *tmp = g_hash_table_lookup(node->details->attrs, attr); - if(safe_str_eq(value, tmp)) { - crm_debug_2("%s: %d + %d", node->details->uname, node->weight, other->weight); - node->weight = merge_weights(node->weight, score); - } + g_hash_table_iter_init(&iter, hash); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + const char *tmp = g_hash_table_lookup(node->details->attrs, attr); + + if (safe_str_eq(value, tmp)) { + crm_debug_2("%s: %d + %d", node->details->uname, node->weight, other->weight); + node->weight = merge_weights(node->weight, score); + } } } -void master_rsc_colocation_rh( - resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) +void +master_rsc_colocation_rh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint) { GListPtr gIter = NULL; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc_rh); - + CRM_CHECK(rsc_rh != NULL, return); - if(is_set(rsc_rh->flags, pe_rsc_provisional)) { - return; + if (is_set(rsc_rh->flags, pe_rsc_provisional)) { + return; - } else if(constraint->role_rh == RSC_ROLE_UNKNOWN) { - crm_debug_3("Handling %s as a clone colocation", constraint->id); - clone_rsc_colocation_rh(rsc_lh, rsc_rh, constraint); - return; + } else if (constraint->role_rh == RSC_ROLE_UNKNOWN) { + crm_debug_3("Handling %s as a clone colocation", constraint->id); + clone_rsc_colocation_rh(rsc_lh, rsc_rh, constraint); + return; } - + CRM_CHECK(rsc_lh != NULL, return); CRM_CHECK(rsc_lh->variant == pe_native, return); crm_debug_2("Processing constraint %s: %d", constraint->id, constraint->score); - if(constraint->role_rh == RSC_ROLE_UNKNOWN) { - - gIter = rsc_rh->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint); - } - - } else if(is_set(rsc_lh->flags, pe_rsc_provisional)) { - GListPtr rhs = NULL; - - gIter = rsc_rh->children; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - node_t *chosen = child_rsc->fns->location(child_rsc, NULL, FALSE); - enum rsc_role_e next_role = child_rsc->fns->state(child_rsc, FALSE); - crm_debug_3("Processing: %s", child_rsc->id); - if(chosen != NULL && next_role == constraint->role_rh) { - crm_debug_3("Applying: %s %s %s %d", child_rsc->id, - role2text(next_role), chosen->details->uname, constraint->score); - if(constraint->score < INFINITY) { - node_hash_update_one(rsc_lh->allowed_nodes, chosen, - constraint->node_attribute, constraint->score); - } - rhs = g_list_prepend(rhs, chosen); - } - } - - /* Only do this if its not a master-master colocation - * Doing this unconditionally would prevent the slaves from being started - */ - if(constraint->role_lh != RSC_ROLE_MASTER - || constraint->role_rh != RSC_ROLE_MASTER) { - if(constraint->score > 0) { - node_list_exclude(rsc_lh->allowed_nodes, rhs, TRUE); - } - } - g_list_free(rhs); - - } else if(constraint->role_lh == RSC_ROLE_MASTER) { - resource_t *rh_child = find_compatible_child(rsc_lh, rsc_rh, constraint->role_rh, FALSE); - if(rh_child == NULL && constraint->score >= INFINITY) { - crm_debug_2("%s can't be promoted %s", rsc_lh->id, constraint->id); - rsc_lh->priority = -INFINITY; - - } else if(rh_child != NULL) { - int new_priority = merge_weights(rsc_lh->priority, constraint->score); - crm_debug("Applying %s to %s", constraint->id, rsc_lh->id); - crm_debug("\t%s: %d->%d", rsc_lh->id, rsc_lh->priority, new_priority); - rsc_lh->priority = new_priority; - } + if (constraint->role_rh == RSC_ROLE_UNKNOWN) { + + gIter = rsc_rh->children; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint); + } + + } else if (is_set(rsc_lh->flags, pe_rsc_provisional)) { + GListPtr rhs = NULL; + + gIter = rsc_rh->children; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + node_t *chosen = child_rsc->fns->location(child_rsc, NULL, FALSE); + enum rsc_role_e next_role = child_rsc->fns->state(child_rsc, FALSE); + + crm_debug_3("Processing: %s", child_rsc->id); + if (chosen != NULL && next_role == constraint->role_rh) { + crm_debug_3("Applying: %s %s %s %d", child_rsc->id, + role2text(next_role), chosen->details->uname, constraint->score); + if (constraint->score < INFINITY) { + node_hash_update_one(rsc_lh->allowed_nodes, chosen, + constraint->node_attribute, constraint->score); + } + rhs = g_list_prepend(rhs, chosen); + } + } + + /* Only do this if its not a master-master colocation + * Doing this unconditionally would prevent the slaves from being started + */ + if (constraint->role_lh != RSC_ROLE_MASTER || constraint->role_rh != RSC_ROLE_MASTER) { + if (constraint->score > 0) { + node_list_exclude(rsc_lh->allowed_nodes, rhs, TRUE); + } + } + g_list_free(rhs); + + } else if (constraint->role_lh == RSC_ROLE_MASTER) { + resource_t *rh_child = find_compatible_child(rsc_lh, rsc_rh, constraint->role_rh, FALSE); + + if (rh_child == NULL && constraint->score >= INFINITY) { + crm_debug_2("%s can't be promoted %s", rsc_lh->id, constraint->id); + rsc_lh->priority = -INFINITY; + + } else if (rh_child != NULL) { + int new_priority = merge_weights(rsc_lh->priority, constraint->score); + + crm_debug("Applying %s to %s", constraint->id, rsc_lh->id); + crm_debug("\t%s: %d->%d", rsc_lh->id, rsc_lh->priority, new_priority); + rsc_lh->priority = new_priority; + } } return; } -void master_append_meta(resource_t *rsc, xmlNode *xml) +void +master_append_meta(resource_t * rsc, xmlNode * xml) { char *name = NULL; clone_variant_data_t *clone_data = NULL; + get_clone_variant_data(clone_data, rsc); clone_append_meta(rsc, xml); - + name = crm_meta_name(XML_RSC_ATTR_MASTER_MAX); crm_xml_add_int(xml, name, clone_data->master_max); crm_free(name); name = crm_meta_name(XML_RSC_ATTR_MASTER_NODEMAX); crm_xml_add_int(xml, name, clone_data->master_node_max); crm_free(name); } diff --git a/pengine/native.c b/pengine/native.c index 6e4e56d849..52f6f0f6be 100644 --- a/pengine/native.c +++ b/pengine/native.c @@ -1,2942 +1,2941 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include -#define DELETE_THEN_REFRESH 1 /* The crmd will remove the resource from the CIB itself, making this redundant */ +#define DELETE_THEN_REFRESH 1 /* The crmd will remove the resource from the CIB itself, making this redundant */ #define VARIANT_NATIVE 1 #include -void native_rsc_colocation_rh_must(resource_t *rsc_lh, gboolean update_lh, - resource_t *rsc_rh, gboolean update_rh); - -void native_rsc_colocation_rh_mustnot(resource_t *rsc_lh, gboolean update_lh, - resource_t *rsc_rh, gboolean update_rh); - -void Recurring(resource_t *rsc, action_t *start, node_t *node, - pe_working_set_t *data_set); -void RecurringOp(resource_t *rsc, action_t *start, node_t *node, - xmlNode *operation, pe_working_set_t *data_set); -void Recurring_Stopped(resource_t *rsc, action_t *start, node_t *node, - pe_working_set_t *data_set); -void RecurringOp_Stopped(resource_t *rsc, action_t *start, node_t *node, - xmlNode *operation, pe_working_set_t *data_set); -void pe_post_notify( - resource_t *rsc, node_t *node, action_t *op, - notify_data_t *n_data, pe_working_set_t *data_set); - -void NoRoleChange (resource_t *rsc, node_t *current, node_t *next, pe_working_set_t *data_set); -gboolean DeleteRsc (resource_t *rsc, node_t *node, gboolean optional, pe_working_set_t *data_set); -gboolean StopRsc (resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set); -gboolean StartRsc (resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set); -gboolean DemoteRsc (resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set); -gboolean PromoteRsc(resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set); -gboolean RoleError (resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set); -gboolean NullOp (resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set); +void native_rsc_colocation_rh_must(resource_t * rsc_lh, gboolean update_lh, + resource_t * rsc_rh, gboolean update_rh); + +void native_rsc_colocation_rh_mustnot(resource_t * rsc_lh, gboolean update_lh, + resource_t * rsc_rh, gboolean update_rh); + +void Recurring(resource_t * rsc, action_t * start, node_t * node, pe_working_set_t * data_set); +void RecurringOp(resource_t * rsc, action_t * start, node_t * node, + xmlNode * operation, pe_working_set_t * data_set); +void Recurring_Stopped(resource_t * rsc, action_t * start, node_t * node, + pe_working_set_t * data_set); +void RecurringOp_Stopped(resource_t * rsc, action_t * start, node_t * node, + xmlNode * operation, pe_working_set_t * data_set); +void pe_post_notify(resource_t * rsc, node_t * node, action_t * op, + notify_data_t * n_data, pe_working_set_t * data_set); + +void NoRoleChange(resource_t * rsc, node_t * current, node_t * next, pe_working_set_t * data_set); +gboolean DeleteRsc(resource_t * rsc, node_t * node, gboolean optional, pe_working_set_t * data_set); +gboolean StopRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set); +gboolean StartRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set); +gboolean DemoteRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set); +gboolean PromoteRsc(resource_t * rsc, node_t * next, gboolean optional, + pe_working_set_t * data_set); +gboolean RoleError(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set); +gboolean NullOp(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set); /* *INDENT-OFF* */ enum rsc_role_e rsc_state_matrix[RSC_ROLE_MAX][RSC_ROLE_MAX] = { /* Current State */ /* Next State: Unknown Stopped Started Slave Master */ /* Unknown */ { RSC_ROLE_UNKNOWN, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, }, /* Stopped */ { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STARTED, RSC_ROLE_SLAVE, RSC_ROLE_SLAVE, }, /* Started */ { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_STARTED, RSC_ROLE_SLAVE, RSC_ROLE_MASTER, }, /* Slave */ { RSC_ROLE_STOPPED, RSC_ROLE_STOPPED, RSC_ROLE_UNKNOWN, RSC_ROLE_SLAVE, RSC_ROLE_MASTER, }, /* Master */ { RSC_ROLE_STOPPED, RSC_ROLE_SLAVE, RSC_ROLE_UNKNOWN, RSC_ROLE_SLAVE, RSC_ROLE_MASTER, }, }; gboolean (*rsc_action_matrix[RSC_ROLE_MAX][RSC_ROLE_MAX])(resource_t*,node_t*,gboolean,pe_working_set_t*) = { /* Current State */ /* Next State: Unknown Stopped Started Slave Master */ /* Unknown */ { RoleError, StopRsc, RoleError, RoleError, RoleError, }, /* Stopped */ { RoleError, NullOp, StartRsc, StartRsc, RoleError, }, /* Started */ { RoleError, StopRsc, NullOp, NullOp, PromoteRsc, }, /* Slave */ { RoleError, StopRsc, RoleError, NullOp, PromoteRsc, }, /* Master */ { RoleError, RoleError, RoleError, DemoteRsc, NullOp, }, }; /* *INDENT-ON* */ -struct capacity_data -{ - node_t *node; - resource_t *rsc; - gboolean is_enough; +struct capacity_data { + node_t *node; + resource_t *rsc; + gboolean is_enough; }; static void check_capacity(gpointer key, gpointer value, gpointer user_data) { int required = 0; int remaining = 0; struct capacity_data *data = user_data; required = crm_parse_int(value, "0"); remaining = crm_parse_int(g_hash_table_lookup(data->node->details->utilization, key), "0"); - + if (required > remaining) { - crm_debug("Node %s has no enough %s for resource %s: required=%d remaining=%d", - data->node->details->uname, (char *)key, data->rsc->id, required, remaining); - data->is_enough = FALSE; + crm_debug("Node %s has no enough %s for resource %s: required=%d remaining=%d", + data->node->details->uname, (char *)key, data->rsc->id, required, remaining); + data->is_enough = FALSE; } } static gboolean -have_enough_capacity(node_t *node, resource_t *rsc) +have_enough_capacity(node_t * node, resource_t * rsc) { struct capacity_data data; data.node = node; data.rsc = rsc; data.is_enough = TRUE; g_hash_table_foreach(rsc->utilization, check_capacity, &data); return data.is_enough; } static gboolean -native_choose_node(resource_t *rsc, node_t *prefer, pe_working_set_t *data_set) +native_choose_node(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set) { /* - 1. Sort by weight - 2. color.chosen_node = the node (of those with the highest wieght) - with the fewest resources - 3. remove color.chosen_node from all other colors - */ - int alloc_details = scores_log_level+1; + 1. Sort by weight + 2. color.chosen_node = the node (of those with the highest wieght) + with the fewest resources + 3. remove color.chosen_node from all other colors + */ + int alloc_details = scores_log_level + 1; GListPtr nodes = NULL; node_t *chosen = NULL; int lpc = 0; int multiple = 0; int length = 0; gboolean result = FALSE; - + if (safe_str_neq(data_set->placement_strategy, "default")) { - GListPtr gIter = NULL; - for(gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - - if (have_enough_capacity(node, rsc) == FALSE) { - crm_debug("Resource %s cannot be allocated to node %s: none of enough capacity", - rsc->id, node->details->uname); - resource_location(rsc, node, -INFINITY, "__limit_utilization_", data_set); - } - } - dump_node_scores(alloc_details, rsc, "Post-utilization", rsc->allowed_nodes); - } - + GListPtr gIter = NULL; + + for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + if (have_enough_capacity(node, rsc) == FALSE) { + crm_debug("Resource %s cannot be allocated to node %s: none of enough capacity", + rsc->id, node->details->uname); + resource_location(rsc, node, -INFINITY, "__limit_utilization_", data_set); + } + } + dump_node_scores(alloc_details, rsc, "Post-utilization", rsc->allowed_nodes); + } + length = g_hash_table_size(rsc->allowed_nodes); - if(is_not_set(rsc->flags, pe_rsc_provisional)) { - return rsc->allocated_to?TRUE:FALSE; - } - - if(prefer) { - chosen = g_hash_table_lookup(rsc->allowed_nodes, prefer->details->id); - if(chosen - && chosen->weight >= 0 - && can_run_resources(chosen)) { - crm_trace("Using preferred node %s for %s instead of choosing from %d candidates", - chosen->details->uname, rsc->id, length); - } else if(chosen && chosen->weight < 0) { - crm_trace("Preferred node %s for %s was unavailable", - chosen->details->uname, rsc->id); - chosen = NULL; - } else if(chosen && can_run_resources(chosen)) { - crm_trace("Preferred node %s for %s was unsuitable", - chosen->details->uname, rsc->id); - chosen = NULL; - } else { - crm_trace("Preferred node %s for %s was unknown", - prefer->details->uname, rsc->id); - } - } - - if(chosen == NULL && rsc->allowed_nodes) { - nodes = g_hash_table_get_values(rsc->allowed_nodes); - nodes = g_list_sort_with_data(nodes, sort_node_weight, g_list_nth_data(rsc->running_on, 0)); - - chosen = g_list_nth_data(nodes, 0); - crm_trace("Chose node %s for %s from %d candidates", chosen?chosen->details->uname:"", rsc->id, length); - - if(chosen - && chosen->weight > 0 - && can_run_resources(chosen)) { - node_t *running = g_list_nth_data(rsc->running_on, 0); - if(running && can_run_resources(running) == FALSE) { - crm_trace("Current node for %s (%s) can't run resources", - rsc->id, running->details->uname); - running = NULL; - } - - for(lpc = 1; lpc < length && running; lpc++) { - node_t *tmp = g_list_nth_data(nodes, lpc); - if(tmp->weight == chosen->weight) { - multiple++; - if(tmp->details == running->details) { - /* prefer the existing node if scores are equal */ - chosen = tmp; - } - } - } - } - } - - if(multiple > 1) { - int log_level = LOG_INFO; - char *score = score2char(chosen->weight); - if(chosen->weight >= INFINITY) { - log_level = LOG_WARNING; - } - - do_crm_log(log_level, "%d nodes with equal score (%s) for" - " running %s resources. Chose %s.", - multiple, score, rsc->id, chosen->details->uname); - crm_free(score); - } - - + if (is_not_set(rsc->flags, pe_rsc_provisional)) { + return rsc->allocated_to ? TRUE : FALSE; + } + + if (prefer) { + chosen = g_hash_table_lookup(rsc->allowed_nodes, prefer->details->id); + if (chosen && chosen->weight >= 0 && can_run_resources(chosen)) { + crm_trace("Using preferred node %s for %s instead of choosing from %d candidates", + chosen->details->uname, rsc->id, length); + } else if (chosen && chosen->weight < 0) { + crm_trace("Preferred node %s for %s was unavailable", chosen->details->uname, rsc->id); + chosen = NULL; + } else if (chosen && can_run_resources(chosen)) { + crm_trace("Preferred node %s for %s was unsuitable", chosen->details->uname, rsc->id); + chosen = NULL; + } else { + crm_trace("Preferred node %s for %s was unknown", prefer->details->uname, rsc->id); + } + } + + if (chosen == NULL && rsc->allowed_nodes) { + nodes = g_hash_table_get_values(rsc->allowed_nodes); + nodes = g_list_sort_with_data(nodes, sort_node_weight, g_list_nth_data(rsc->running_on, 0)); + + chosen = g_list_nth_data(nodes, 0); + crm_trace("Chose node %s for %s from %d candidates", + chosen ? chosen->details->uname : "", rsc->id, length); + + if (chosen && chosen->weight > 0 && can_run_resources(chosen)) { + node_t *running = g_list_nth_data(rsc->running_on, 0); + + if (running && can_run_resources(running) == FALSE) { + crm_trace("Current node for %s (%s) can't run resources", + rsc->id, running->details->uname); + running = NULL; + } + + for (lpc = 1; lpc < length && running; lpc++) { + node_t *tmp = g_list_nth_data(nodes, lpc); + + if (tmp->weight == chosen->weight) { + multiple++; + if (tmp->details == running->details) { + /* prefer the existing node if scores are equal */ + chosen = tmp; + } + } + } + } + } + + if (multiple > 1) { + int log_level = LOG_INFO; + char *score = score2char(chosen->weight); + + if (chosen->weight >= INFINITY) { + log_level = LOG_WARNING; + } + + do_crm_log(log_level, "%d nodes with equal score (%s) for" + " running %s resources. Chose %s.", + multiple, score, rsc->id, chosen->details->uname); + crm_free(score); + } + result = native_assign_node(rsc, nodes, chosen, FALSE); g_list_free(nodes); return result; } -static int node_list_attr_score(GHashTable *list, const char *attr, const char *value) +static int +node_list_attr_score(GHashTable * list, const char *attr, const char *value) { GHashTableIter iter; node_t *node = NULL; int best_score = -INFINITY; const char *best_node = NULL; - if(attr == NULL) { - attr = "#"XML_ATTR_UNAME; + if (attr == NULL) { + attr = "#" XML_ATTR_UNAME; } - g_hash_table_iter_init (&iter, list); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - int weight = node->weight; - if(can_run_resources(node) == FALSE) { - weight = -INFINITY; - } - if(weight > best_score || best_node == NULL) { - const char *tmp = g_hash_table_lookup(node->details->attrs, attr); - if(safe_str_eq(value, tmp)) { - best_score = weight; - best_node = node->details->uname; - } - } + g_hash_table_iter_init(&iter, list); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + int weight = node->weight; + + if (can_run_resources(node) == FALSE) { + weight = -INFINITY; + } + if (weight > best_score || best_node == NULL) { + const char *tmp = g_hash_table_lookup(node->details->attrs, attr); + + if (safe_str_eq(value, tmp)) { + best_score = weight; + best_node = node->details->uname; + } + } } - if(safe_str_neq(attr, "#"XML_ATTR_UNAME)) { - crm_info("Best score for %s=%s was %s with %d", - attr, value, best_node?best_node:"", best_score); + if (safe_str_neq(attr, "#" XML_ATTR_UNAME)) { + crm_info("Best score for %s=%s was %s with %d", + attr, value, best_node ? best_node : "", best_score); } - + return best_score; } - static void -node_hash_update(GHashTable *list1, GHashTable *list2, const char *attr, int factor, gboolean only_positive) +node_hash_update(GHashTable * list1, GHashTable * list2, const char *attr, int factor, + gboolean only_positive) { int score = 0; int new_score = 0; GHashTableIter iter; node_t *node = NULL; - if(attr == NULL) { - attr = "#"XML_ATTR_UNAME; - } - - g_hash_table_iter_init (&iter, list1); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - CRM_CHECK(node != NULL, continue); - score = node_list_attr_score(list2, attr, g_hash_table_lookup(node->details->attrs, attr)); - new_score = merge_weights(factor*score, node->weight); - - if(factor < 0 && score < 0) { - /* Negative preference for a node with a negative score - * should not become a positive preference - * - * TODO: Decide if we want to filter only if weight == -INFINITY - * - */ - crm_trace("%s: Filtering %d + %d*%d (factor * score)", - node->details->uname, node->weight, factor, score); - - } else if(only_positive && new_score < 0 && node->weight > 0) { - node->weight = 1; - crm_trace("%s: Filtering %d + %d*%d (score > 0)", - node->details->uname, node->weight, factor, score); - - } else if(only_positive && new_score < 0 && node->weight == 0) { - crm_trace("%s: Filtering %d + %d*%d (score == 0)", - node->details->uname, node->weight, factor, score); - - } else { - crm_trace("%s: %d + %d*%d", - node->details->uname, node->weight, factor, score); - node->weight = new_score; - } + if (attr == NULL) { + attr = "#" XML_ATTR_UNAME; + } + + g_hash_table_iter_init(&iter, list1); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + CRM_CHECK(node != NULL, continue); + score = node_list_attr_score(list2, attr, g_hash_table_lookup(node->details->attrs, attr)); + new_score = merge_weights(factor * score, node->weight); + + if (factor < 0 && score < 0) { + /* Negative preference for a node with a negative score + * should not become a positive preference + * + * TODO: Decide if we want to filter only if weight == -INFINITY + * + */ + crm_trace("%s: Filtering %d + %d*%d (factor * score)", + node->details->uname, node->weight, factor, score); + + } else if (only_positive && new_score < 0 && node->weight > 0) { + node->weight = 1; + crm_trace("%s: Filtering %d + %d*%d (score > 0)", + node->details->uname, node->weight, factor, score); + + } else if (only_positive && new_score < 0 && node->weight == 0) { + crm_trace("%s: Filtering %d + %d*%d (score == 0)", + node->details->uname, node->weight, factor, score); + + } else { + crm_trace("%s: %d + %d*%d", node->details->uname, node->weight, factor, score); + node->weight = new_score; + } } } static GHashTable * -node_hash_dup(GHashTable *hash) +node_hash_dup(GHashTable * hash) { /* Hack! */ GListPtr list = g_hash_table_get_values(hash); GHashTable *result = node_hash_from_list(list); + g_list_free(list); return result; } GHashTable * -native_merge_weights(resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, - int factor, gboolean allow_rollback, gboolean only_positive) +native_merge_weights(resource_t * rsc, const char *rhs, GHashTable * nodes, const char *attr, + int factor, gboolean allow_rollback, gboolean only_positive) { enum pe_weights flags = pe_weights_none; - if(only_positive) { - set_bit_inplace(flags, pe_weights_positive); + + if (only_positive) { + set_bit_inplace(flags, pe_weights_positive); } - if(allow_rollback) { - set_bit_inplace(flags, pe_weights_rollback); + if (allow_rollback) { + set_bit_inplace(flags, pe_weights_rollback); } return rsc_merge_weights(rsc, rhs, nodes, attr, factor, flags); } - - GHashTable * -rsc_merge_weights( - resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, int factor, enum pe_weights flags) +rsc_merge_weights(resource_t * rsc, const char *rhs, GHashTable * nodes, const char *attr, + int factor, enum pe_weights flags) { GHashTable *work = NULL; int multiplier = 1; - if(factor < 0) { - multiplier = -1; + + if (factor < 0) { + multiplier = -1; } - if(is_set(rsc->flags, pe_rsc_merging)) { - crm_info("%s: Breaking dependency loop at %s", rhs, rsc->id); - return nodes; + if (is_set(rsc->flags, pe_rsc_merging)) { + crm_info("%s: Breaking dependency loop at %s", rhs, rsc->id); + return nodes; } set_bit(rsc->flags, pe_rsc_merging); - if(is_set(flags, pe_weights_init)) { - if(rsc->variant == pe_group && rsc->children) { - GListPtr last = rsc->children; - while(last->next != NULL) { - last = last->next; - } - - crm_trace("Merging %s as a group %p %p", rsc->id, rsc->children, last); - work = rsc_merge_weights(last->data, rhs, NULL, attr, factor, flags); - - } else { - work = node_hash_dup(rsc->allowed_nodes); - } - clear_bit_inplace(flags, pe_weights_init); - + if (is_set(flags, pe_weights_init)) { + if (rsc->variant == pe_group && rsc->children) { + GListPtr last = rsc->children; + + while (last->next != NULL) { + last = last->next; + } + + crm_trace("Merging %s as a group %p %p", rsc->id, rsc->children, last); + work = rsc_merge_weights(last->data, rhs, NULL, attr, factor, flags); + + } else { + work = node_hash_dup(rsc->allowed_nodes); + } + clear_bit_inplace(flags, pe_weights_init); + } else { - crm_trace("%s: Combining scores from %s", rhs, rsc->id); - work = node_hash_dup(nodes); - node_hash_update(work, rsc->allowed_nodes, attr, factor, is_set(flags, pe_weights_positive)); + crm_trace("%s: Combining scores from %s", rhs, rsc->id); + work = node_hash_dup(nodes); + node_hash_update(work, rsc->allowed_nodes, attr, factor, + is_set(flags, pe_weights_positive)); } - - if(is_set(flags, pe_weights_rollback) && can_run_any(work) == FALSE) { - crm_info("%s: Rolling back scores from %s", rhs, rsc->id); - g_hash_table_destroy(work); - clear_bit(rsc->flags, pe_rsc_merging); - return nodes; + + if (is_set(flags, pe_weights_rollback) && can_run_any(work) == FALSE) { + crm_info("%s: Rolling back scores from %s", rhs, rsc->id); + g_hash_table_destroy(work); + clear_bit(rsc->flags, pe_rsc_merging); + return nodes; } - if(can_run_any(work)) { - GListPtr gIter = NULL; - if(is_set(flags, pe_weights_forward)) { - gIter = rsc->rsc_cons; - } else { - gIter = rsc->rsc_cons_lhs; - } + if (can_run_any(work)) { + GListPtr gIter = NULL; + + if (is_set(flags, pe_weights_forward)) { + gIter = rsc->rsc_cons; + } else { + gIter = rsc->rsc_cons_lhs; + } - for(; gIter != NULL; gIter = gIter->next) { - resource_t *other = NULL; - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *other = NULL; + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; - if(is_set(flags, pe_weights_forward)) { - other = constraint->rsc_rh; - } else { - other = constraint->rsc_lh; - } - - crm_trace("Applying %s (%s)", constraint->id, other->id); - work = rsc_merge_weights(other, rhs, work, constraint->node_attribute, - multiplier*constraint->score/INFINITY, flags); - dump_node_scores(LOG_TRACE, NULL, rhs, work); - } + if (is_set(flags, pe_weights_forward)) { + other = constraint->rsc_rh; + } else { + other = constraint->rsc_lh; + } + + crm_trace("Applying %s (%s)", constraint->id, other->id); + work = rsc_merge_weights(other, rhs, work, constraint->node_attribute, + multiplier * constraint->score / INFINITY, flags); + dump_node_scores(LOG_TRACE, NULL, rhs, work); + } } - if(nodes) { - g_hash_table_destroy(nodes); + if (nodes) { + g_hash_table_destroy(nodes); } clear_bit(rsc->flags, pe_rsc_merging); return work; } node_t * -native_color(resource_t *rsc, node_t *prefer, pe_working_set_t *data_set) +native_color(resource_t * rsc, node_t * prefer, pe_working_set_t * data_set) { GListPtr gIter = NULL; - int alloc_details = scores_log_level+1; + int alloc_details = scores_log_level + 1; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); - if(rsc->parent && is_not_set(rsc->parent->flags, pe_rsc_allocating)) { - /* never allocate children on their own */ - crm_debug("Escalating allocation of %s to its parent: %s", - rsc->id, rsc->parent->id); - rsc->parent->cmds->allocate(rsc->parent, prefer, data_set); + + if (rsc->parent && is_not_set(rsc->parent->flags, pe_rsc_allocating)) { + /* never allocate children on their own */ + crm_debug("Escalating allocation of %s to its parent: %s", rsc->id, rsc->parent->id); + rsc->parent->cmds->allocate(rsc->parent, prefer, data_set); } - - if(is_not_set(rsc->flags, pe_rsc_provisional)) { - return rsc->allocated_to; + + if (is_not_set(rsc->flags, pe_rsc_provisional)) { + return rsc->allocated_to; } - if(is_set(rsc->flags, pe_rsc_allocating)) { - crm_debug("Dependency loop detected involving %s", rsc->id); - return NULL; + if (is_set(rsc->flags, pe_rsc_allocating)) { + crm_debug("Dependency loop detected involving %s", rsc->id); + return NULL; } set_bit(rsc->flags, pe_rsc_allocating); print_resource(alloc_details, "Allocating: ", rsc, FALSE); dump_node_scores(alloc_details, rsc, "Pre-allloc", rsc->allowed_nodes); - for(gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - - GHashTable *archive = NULL; - resource_t *rsc_rh = constraint->rsc_rh; - crm_debug_2("%s: Pre-Processing %s (%s, %d, %s)", - rsc->id, constraint->id, rsc_rh->id, - constraint->score, role2text(constraint->role_lh)); - if(constraint->role_lh >= RSC_ROLE_MASTER - || (constraint->score < 0 && constraint->score > -INFINITY)) { - archive = node_hash_dup(rsc->allowed_nodes); - } - rsc_rh->cmds->allocate(rsc_rh, NULL, data_set); - rsc->cmds->rsc_colocation_lh(rsc, rsc_rh, constraint); - if(archive && can_run_any(rsc->allowed_nodes) == FALSE) { - crm_info("%s: Rolling back scores from %s", rsc->id, rsc_rh->id); - g_hash_table_destroy(rsc->allowed_nodes); - rsc->allowed_nodes = archive; - archive = NULL; - } - if(archive) { - g_hash_table_destroy(archive); - } + for (gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + GHashTable *archive = NULL; + resource_t *rsc_rh = constraint->rsc_rh; + + crm_debug_2("%s: Pre-Processing %s (%s, %d, %s)", + rsc->id, constraint->id, rsc_rh->id, + constraint->score, role2text(constraint->role_lh)); + if (constraint->role_lh >= RSC_ROLE_MASTER + || (constraint->score < 0 && constraint->score > -INFINITY)) { + archive = node_hash_dup(rsc->allowed_nodes); + } + rsc_rh->cmds->allocate(rsc_rh, NULL, data_set); + rsc->cmds->rsc_colocation_lh(rsc, rsc_rh, constraint); + if (archive && can_run_any(rsc->allowed_nodes) == FALSE) { + crm_info("%s: Rolling back scores from %s", rsc->id, rsc_rh->id); + g_hash_table_destroy(rsc->allowed_nodes); + rsc->allowed_nodes = archive; + archive = NULL; + } + if (archive) { + g_hash_table_destroy(archive); + } } dump_node_scores(alloc_details, rsc, "Post-coloc", rsc->allowed_nodes); - for(gIter = rsc->rsc_cons_lhs; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - - rsc->allowed_nodes = constraint->rsc_lh->cmds->merge_weights( - constraint->rsc_lh, rsc->id, rsc->allowed_nodes, - constraint->node_attribute, constraint->score/INFINITY, TRUE, FALSE); + for (gIter = rsc->rsc_cons_lhs; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + rsc->allowed_nodes = + constraint->rsc_lh->cmds->merge_weights(constraint->rsc_lh, rsc->id, rsc->allowed_nodes, + constraint->node_attribute, + constraint->score / INFINITY, TRUE, FALSE); } - for(gIter = rsc->rsc_tickets; gIter != NULL; gIter = gIter->next) { - rsc_ticket_t *rsc_ticket = (rsc_ticket_t*)gIter->data; + for (gIter = rsc->rsc_tickets; gIter != NULL; gIter = gIter->next) { + rsc_ticket_t *rsc_ticket = (rsc_ticket_t *) gIter->data; - if(rsc_ticket->ticket->granted == FALSE) { - rsc_ticket_constraint(rsc, rsc_ticket, data_set); - } + if (rsc_ticket->ticket->granted == FALSE) { + rsc_ticket_constraint(rsc, rsc_ticket, data_set); + } } - + print_resource(LOG_DEBUG_2, "Allocating: ", rsc, FALSE); - if(rsc->next_role == RSC_ROLE_STOPPED) { - crm_debug_2("Making sure %s doesn't get allocated", rsc->id); - /* make sure it doesnt come up again */ - resource_location( - rsc, NULL, -INFINITY, XML_RSC_ATTR_TARGET_ROLE, data_set); - } - - dump_node_scores(show_scores?0:scores_log_level, rsc, __PRETTY_FUNCTION__, rsc->allowed_nodes); - if(is_set(data_set->flags, pe_flag_stonith_enabled) - && is_set(data_set->flags, pe_flag_have_stonith_resource) == FALSE) { - clear_bit(rsc->flags, pe_rsc_managed); - } - - if(is_not_set(rsc->flags, pe_rsc_managed)) { - const char *reason = NULL; - node_t *assign_to = NULL; - rsc->next_role = rsc->role; - if(rsc->running_on == NULL) { - reason = "inactive"; - } else if(rsc->role == RSC_ROLE_MASTER) { - assign_to = rsc->running_on->data; - reason = "master"; - } else if(is_set(rsc->flags, pe_rsc_failed)) { - reason = "failed"; - } else { - assign_to = rsc->running_on->data; - reason = "active"; - } - crm_info("Unmanaged resource %s allocated to %s: %s", rsc->id, - assign_to?assign_to->details->uname:"'nowhere'", reason); - native_assign_node(rsc, NULL, assign_to, TRUE); - - } else if(is_set(data_set->flags, pe_flag_stop_everything) - && safe_str_neq(class, "stonith")) { - crm_debug("Forcing %s to stop", rsc->id); - native_assign_node(rsc, NULL, NULL, TRUE); - - } else if(is_set(rsc->flags, pe_rsc_provisional) - && native_choose_node(rsc, prefer, data_set) ) { - crm_debug_3("Allocated resource %s to %s", - rsc->id, rsc->allocated_to->details->uname); - - } else if(rsc->allocated_to == NULL) { - if(is_not_set(rsc->flags, pe_rsc_orphan)) { - crm_info("Resource %s cannot run anywhere", rsc->id); - } else if(rsc->running_on != NULL) { - crm_info("Stopping orphan resource %s", rsc->id); - } - + if (rsc->next_role == RSC_ROLE_STOPPED) { + crm_debug_2("Making sure %s doesn't get allocated", rsc->id); + /* make sure it doesnt come up again */ + resource_location(rsc, NULL, -INFINITY, XML_RSC_ATTR_TARGET_ROLE, data_set); + } + + dump_node_scores(show_scores ? 0 : scores_log_level, rsc, __PRETTY_FUNCTION__, + rsc->allowed_nodes); + if (is_set(data_set->flags, pe_flag_stonith_enabled) + && is_set(data_set->flags, pe_flag_have_stonith_resource) == FALSE) { + clear_bit(rsc->flags, pe_rsc_managed); + } + + if (is_not_set(rsc->flags, pe_rsc_managed)) { + const char *reason = NULL; + node_t *assign_to = NULL; + + rsc->next_role = rsc->role; + if (rsc->running_on == NULL) { + reason = "inactive"; + } else if (rsc->role == RSC_ROLE_MASTER) { + assign_to = rsc->running_on->data; + reason = "master"; + } else if (is_set(rsc->flags, pe_rsc_failed)) { + reason = "failed"; + } else { + assign_to = rsc->running_on->data; + reason = "active"; + } + crm_info("Unmanaged resource %s allocated to %s: %s", rsc->id, + assign_to ? assign_to->details->uname : "'nowhere'", reason); + native_assign_node(rsc, NULL, assign_to, TRUE); + + } else if (is_set(data_set->flags, pe_flag_stop_everything) + && safe_str_neq(class, "stonith")) { + crm_debug("Forcing %s to stop", rsc->id); + native_assign_node(rsc, NULL, NULL, TRUE); + + } else if (is_set(rsc->flags, pe_rsc_provisional) + && native_choose_node(rsc, prefer, data_set)) { + crm_debug_3("Allocated resource %s to %s", rsc->id, rsc->allocated_to->details->uname); + + } else if (rsc->allocated_to == NULL) { + if (is_not_set(rsc->flags, pe_rsc_orphan)) { + crm_info("Resource %s cannot run anywhere", rsc->id); + } else if (rsc->running_on != NULL) { + crm_info("Stopping orphan resource %s", rsc->id); + } + } else { - crm_debug("Pre-Allocated resource %s to %s", - rsc->id, rsc->allocated_to->details->uname); + crm_debug("Pre-Allocated resource %s to %s", rsc->id, rsc->allocated_to->details->uname); } - + clear_bit(rsc->flags, pe_rsc_allocating); print_resource(LOG_DEBUG_3, "Allocated ", rsc, TRUE); return rsc->allocated_to; } -static gboolean is_op_dup( - resource_t *rsc, const char *name, const char *interval) +static gboolean +is_op_dup(resource_t * rsc, const char *name, const char *interval) { gboolean dup = FALSE; const char *id = NULL; const char *value = NULL; xmlNode *operation = NULL; - for(operation = __xml_first_child(rsc->ops_xml); operation != NULL; operation = __xml_next(operation)) { - if(crm_str_eq((const char *)operation->name, "op", TRUE)) { - value = crm_element_value(operation, "name"); - if(safe_str_neq(value, name)) { - continue; - } - - value = crm_element_value(operation, XML_LRM_ATTR_INTERVAL); - if(value == NULL) { - value = "0"; - } - - if(safe_str_neq(value, interval)) { - continue; - } - - if(id == NULL) { - id = ID(operation); - - } else { - crm_config_err("Operation %s is a duplicate of %s", ID(operation), id); - crm_config_err("Do not use the same (name, interval) combination more than once per resource"); - dup = TRUE; - } - } - } - + + for (operation = __xml_first_child(rsc->ops_xml); operation != NULL; + operation = __xml_next(operation)) { + if (crm_str_eq((const char *)operation->name, "op", TRUE)) { + value = crm_element_value(operation, "name"); + if (safe_str_neq(value, name)) { + continue; + } + + value = crm_element_value(operation, XML_LRM_ATTR_INTERVAL); + if (value == NULL) { + value = "0"; + } + + if (safe_str_neq(value, interval)) { + continue; + } + + if (id == NULL) { + id = ID(operation); + + } else { + crm_config_err("Operation %s is a duplicate of %s", ID(operation), id); + crm_config_err + ("Do not use the same (name, interval) combination more than once per resource"); + dup = TRUE; + } + } + } + return dup; } void -RecurringOp(resource_t *rsc, action_t *start, node_t *node, - xmlNode *operation, pe_working_set_t *data_set) +RecurringOp(resource_t * rsc, action_t * start, node_t * node, + xmlNode * operation, pe_working_set_t * data_set) { char *key = NULL; const char *name = NULL; const char *value = NULL; const char *interval = NULL; const char *node_uname = NULL; unsigned long long interval_ms = 0; action_t *mon = NULL; gboolean is_optional = TRUE; GListPtr possible_matches = NULL; /* Only process for the operations without role="Stopped" */ value = crm_element_value(operation, "role"); if (value && text2role(value) == RSC_ROLE_STOPPED) { - return; + return; } - + crm_debug_2("Creating recurring action %s for %s in role %s on %s", - ID(operation), rsc->id, role2text(rsc->next_role), node?node->details->uname:"n/a"); - - if(node != NULL) { - node_uname = node->details->uname; + ID(operation), rsc->id, role2text(rsc->next_role), + node ? node->details->uname : "n/a"); + + if (node != NULL) { + node_uname = node->details->uname; } interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL); interval_ms = crm_get_interval(interval); - - if(interval_ms == 0) { - return; + + if (interval_ms == 0) { + return; } - + name = crm_element_value(operation, "name"); - if(is_op_dup(rsc, name, interval)) { - return; + if (is_op_dup(rsc, name, interval)) { + return; } - if(safe_str_eq(name, RSC_STOP) - || safe_str_eq(name, RSC_START) - || safe_str_eq(name, RSC_DEMOTE) - || safe_str_eq(name, RSC_PROMOTE) - ) { - crm_config_err("Invalid recurring action %s wth name: '%s'", - ID(operation), name); - return; + if (safe_str_eq(name, RSC_STOP) + || safe_str_eq(name, RSC_START) + || safe_str_eq(name, RSC_DEMOTE) + || safe_str_eq(name, RSC_PROMOTE) + ) { + crm_config_err("Invalid recurring action %s wth name: '%s'", ID(operation), name); + return; } key = generate_op_key(rsc->id, name, interval_ms); - if(find_rsc_op_entry(rsc, key) == NULL) { - /* disabled */ - crm_free(key); - return; - } - - if(start != NULL) { - crm_debug_3("Marking %s %s due to %s", - key, is_set(start->flags, pe_action_optional)?"optional":"manditory", - start->uuid); - is_optional = (rsc->cmds->action_flags(start, NULL) & pe_action_optional); + if (find_rsc_op_entry(rsc, key) == NULL) { + /* disabled */ + crm_free(key); + return; + } + + if (start != NULL) { + crm_debug_3("Marking %s %s due to %s", + key, is_set(start->flags, pe_action_optional) ? "optional" : "manditory", + start->uuid); + is_optional = (rsc->cmds->action_flags(start, NULL) & pe_action_optional); } else { - crm_debug_2("Marking %s optional", key); - is_optional = TRUE; + crm_debug_2("Marking %s optional", key); + is_optional = TRUE; } /* start a monitor for an already active resource */ possible_matches = find_actions_exact(rsc->actions, key, node); - if(possible_matches == NULL) { - is_optional = FALSE; - crm_debug_3("Marking %s manditory: not active", key); + if (possible_matches == NULL) { + is_optional = FALSE; + crm_debug_3("Marking %s manditory: not active", key); } else { - g_list_free(possible_matches); - } - - if((rsc->next_role == RSC_ROLE_MASTER && value == NULL) - || (value != NULL && text2role(value) != rsc->next_role)) { - int log_level = LOG_DEBUG_2; - const char *result = "Ignoring"; - if(is_optional) { - char *local_key = crm_strdup(key); - log_level = LOG_INFO; - result = "Cancelling"; - /* its running : cancel it */ - - mon = custom_action( - rsc, local_key, RSC_CANCEL, node, - FALSE, TRUE, data_set); - - crm_free(mon->task); - mon->task = crm_strdup(RSC_CANCEL); - add_hash_param(mon->meta, XML_LRM_ATTR_INTERVAL, interval); - add_hash_param(mon->meta, XML_LRM_ATTR_TASK, name); - - local_key = NULL; - - switch(rsc->role) { - case RSC_ROLE_SLAVE: - case RSC_ROLE_STARTED: - if(rsc->next_role == RSC_ROLE_MASTER) { - local_key = promote_key(rsc); - - } else if(rsc->next_role == RSC_ROLE_STOPPED) { - local_key = stop_key(rsc); - } - - break; - case RSC_ROLE_MASTER: - local_key = demote_key(rsc); - break; - default: - break; - } - - if(local_key) { - custom_action_order(rsc, NULL, mon, rsc, local_key, NULL, - pe_order_runnable_left, data_set); - } - - mon = NULL; - } - - do_crm_log(log_level, "%s action %s (%s vs. %s)", - result , key, value?value:role2text(RSC_ROLE_SLAVE), - role2text(rsc->next_role)); - - crm_free(key); - key = NULL; - return; - } - - mon = custom_action(rsc, key, name, node, - is_optional, TRUE, data_set); + g_list_free(possible_matches); + } + + if ((rsc->next_role == RSC_ROLE_MASTER && value == NULL) + || (value != NULL && text2role(value) != rsc->next_role)) { + int log_level = LOG_DEBUG_2; + const char *result = "Ignoring"; + + if (is_optional) { + char *local_key = crm_strdup(key); + + log_level = LOG_INFO; + result = "Cancelling"; + /* its running : cancel it */ + + mon = custom_action(rsc, local_key, RSC_CANCEL, node, FALSE, TRUE, data_set); + + crm_free(mon->task); + mon->task = crm_strdup(RSC_CANCEL); + add_hash_param(mon->meta, XML_LRM_ATTR_INTERVAL, interval); + add_hash_param(mon->meta, XML_LRM_ATTR_TASK, name); + + local_key = NULL; + + switch (rsc->role) { + case RSC_ROLE_SLAVE: + case RSC_ROLE_STARTED: + if (rsc->next_role == RSC_ROLE_MASTER) { + local_key = promote_key(rsc); + + } else if (rsc->next_role == RSC_ROLE_STOPPED) { + local_key = stop_key(rsc); + } + + break; + case RSC_ROLE_MASTER: + local_key = demote_key(rsc); + break; + default: + break; + } + + if (local_key) { + custom_action_order(rsc, NULL, mon, rsc, local_key, NULL, + pe_order_runnable_left, data_set); + } + + mon = NULL; + } + + do_crm_log(log_level, "%s action %s (%s vs. %s)", + result, key, value ? value : role2text(RSC_ROLE_SLAVE), + role2text(rsc->next_role)); + + crm_free(key); + key = NULL; + return; + } + + mon = custom_action(rsc, key, name, node, is_optional, TRUE, data_set); key = mon->uuid; - if(is_optional) { - crm_debug_2("%s\t %s (optional)", - crm_str(node_uname), mon->uuid); - } - - if(start == NULL || is_set(start->flags, pe_action_runnable) == FALSE) { - crm_debug("%s\t %s (cancelled : start un-runnable)", - crm_str(node_uname), mon->uuid); - update_action_flags(mon, pe_action_runnable|pe_action_clear); - - } else if(node == NULL - || node->details->online == FALSE - || node->details->unclean) { - crm_debug("%s\t %s (cancelled : no node available)", - crm_str(node_uname), mon->uuid); - update_action_flags(mon, pe_action_runnable|pe_action_clear); - - } else if(is_set(mon->flags, pe_action_optional) == FALSE) { - crm_notice(" Start recurring %s (%llus) for %s on %s", mon->task, interval_ms/1000, rsc->id, crm_str(node_uname)); - } - - if(rsc->next_role == RSC_ROLE_MASTER) { - char *running_master = crm_itoa(EXECRA_RUNNING_MASTER); - add_hash_param(mon->meta, XML_ATTR_TE_TARGET_RC, running_master); - crm_free(running_master); - } - - if(node == NULL || is_set(rsc->flags, pe_rsc_managed)) { - custom_action_order(rsc, start_key(rsc), NULL, - NULL, crm_strdup(key), mon, - pe_order_implies_then|pe_order_runnable_left, data_set); - - if(rsc->next_role == RSC_ROLE_MASTER) { - custom_action_order( - rsc, promote_key(rsc), NULL, - rsc, NULL, mon, - pe_order_optional|pe_order_runnable_left, data_set); - - } else if(rsc->role == RSC_ROLE_MASTER) { - custom_action_order( - rsc, demote_key(rsc), NULL, - rsc, NULL, mon, - pe_order_optional|pe_order_runnable_left, data_set); - } + if (is_optional) { + crm_debug_2("%s\t %s (optional)", crm_str(node_uname), mon->uuid); + } + + if (start == NULL || is_set(start->flags, pe_action_runnable) == FALSE) { + crm_debug("%s\t %s (cancelled : start un-runnable)", crm_str(node_uname), mon->uuid); + update_action_flags(mon, pe_action_runnable | pe_action_clear); + + } else if (node == NULL || node->details->online == FALSE || node->details->unclean) { + crm_debug("%s\t %s (cancelled : no node available)", crm_str(node_uname), mon->uuid); + update_action_flags(mon, pe_action_runnable | pe_action_clear); + + } else if (is_set(mon->flags, pe_action_optional) == FALSE) { + crm_notice(" Start recurring %s (%llus) for %s on %s", mon->task, interval_ms / 1000, + rsc->id, crm_str(node_uname)); + } + + if (rsc->next_role == RSC_ROLE_MASTER) { + char *running_master = crm_itoa(EXECRA_RUNNING_MASTER); + + add_hash_param(mon->meta, XML_ATTR_TE_TARGET_RC, running_master); + crm_free(running_master); + } + + if (node == NULL || is_set(rsc->flags, pe_rsc_managed)) { + custom_action_order(rsc, start_key(rsc), NULL, + NULL, crm_strdup(key), mon, + pe_order_implies_then | pe_order_runnable_left, data_set); + + if (rsc->next_role == RSC_ROLE_MASTER) { + custom_action_order(rsc, promote_key(rsc), NULL, + rsc, NULL, mon, + pe_order_optional | pe_order_runnable_left, data_set); + + } else if (rsc->role == RSC_ROLE_MASTER) { + custom_action_order(rsc, demote_key(rsc), NULL, + rsc, NULL, mon, + pe_order_optional | pe_order_runnable_left, data_set); + } } } void -Recurring(resource_t *rsc, action_t *start, node_t *node, - pe_working_set_t *data_set) +Recurring(resource_t * rsc, action_t * start, node_t * node, pe_working_set_t * data_set) { - if(is_not_set(data_set->flags, pe_flag_maintenance_mode)) { - xmlNode *operation = NULL; - for(operation = __xml_first_child(rsc->ops_xml); operation != NULL; operation = __xml_next(operation)) { - if(crm_str_eq((const char *)operation->name, "op", TRUE)) { - RecurringOp(rsc, start, node, operation, data_set); - } - } + if (is_not_set(data_set->flags, pe_flag_maintenance_mode)) { + xmlNode *operation = NULL; + + for (operation = __xml_first_child(rsc->ops_xml); operation != NULL; + operation = __xml_next(operation)) { + if (crm_str_eq((const char *)operation->name, "op", TRUE)) { + RecurringOp(rsc, start, node, operation, data_set); + } + } } } void -RecurringOp_Stopped(resource_t *rsc, action_t *start, node_t *node, - xmlNode *operation, pe_working_set_t *data_set) +RecurringOp_Stopped(resource_t * rsc, action_t * start, node_t * node, + xmlNode * operation, pe_working_set_t * data_set) { char *key = NULL; const char *name = NULL; const char *role = NULL; const char *interval = NULL; const char *node_uname = NULL; unsigned long long interval_ms = 0; GListPtr possible_matches = NULL; GListPtr gIter = NULL; /* TODO: Support of non-unique clone */ - if(is_set(rsc->flags, pe_rsc_unique) == FALSE) { - return; + if (is_set(rsc->flags, pe_rsc_unique) == FALSE) { + return; } - + /* Only process for the operations with role="Stopped" */ role = crm_element_value(operation, "role"); if (role == NULL || text2role(role) != RSC_ROLE_STOPPED) { - return; + return; } - crm_debug_2("Creating recurring actions %s for %s in role %s on nodes where it'll not be running", - ID(operation), rsc->id, role2text(rsc->next_role)); + crm_debug_2 + ("Creating recurring actions %s for %s in role %s on nodes where it'll not be running", + ID(operation), rsc->id, role2text(rsc->next_role)); - if(node != NULL) { - node_uname = node->details->uname; + if (node != NULL) { + node_uname = node->details->uname; } interval = crm_element_value(operation, XML_LRM_ATTR_INTERVAL); interval_ms = crm_get_interval(interval); - - if(interval_ms == 0) { - return; + + if (interval_ms == 0) { + return; } - + name = crm_element_value(operation, "name"); - if(is_op_dup(rsc, name, interval)) { - return; + if (is_op_dup(rsc, name, interval)) { + return; } - if(safe_str_eq(name, RSC_STOP) - || safe_str_eq(name, RSC_START) - || safe_str_eq(name, RSC_DEMOTE) - || safe_str_eq(name, RSC_PROMOTE) - ) { - crm_config_err("Invalid recurring action %s wth name: '%s'", - ID(operation), name); - return; + if (safe_str_eq(name, RSC_STOP) + || safe_str_eq(name, RSC_START) + || safe_str_eq(name, RSC_DEMOTE) + || safe_str_eq(name, RSC_PROMOTE) + ) { + crm_config_err("Invalid recurring action %s wth name: '%s'", ID(operation), name); + return; } key = generate_op_key(rsc->id, name, interval_ms); - if(find_rsc_op_entry(rsc, key) == NULL) { - /* disabled */ - crm_free(key); - return; + if (find_rsc_op_entry(rsc, key) == NULL) { + /* disabled */ + crm_free(key); + return; } /* if the monitor exists on the node where the resource will be running, cancel it */ - if(node != NULL) { - possible_matches = find_actions_exact(rsc->actions, key, node); - if(possible_matches) { - action_t *cancel_op = NULL; - char *local_key = crm_strdup(key); - - g_list_free(possible_matches); - - cancel_op = custom_action( - rsc, local_key, RSC_CANCEL, node, - FALSE, TRUE, data_set); - - crm_free(cancel_op->task); - cancel_op->task = crm_strdup(RSC_CANCEL); - add_hash_param(cancel_op->meta, XML_LRM_ATTR_INTERVAL, interval); - add_hash_param(cancel_op->meta, XML_LRM_ATTR_TASK, name); - - local_key = NULL; - - if(rsc->next_role == RSC_ROLE_STARTED || rsc->next_role == RSC_ROLE_SLAVE) { - /* rsc->role == RSC_ROLE_STOPPED: cancel the monitor before start */ - /* rsc->role == RSC_ROLE_STARTED: for a migration, cancel the monitor on the target node before start */ - custom_action_order(rsc, NULL, cancel_op, rsc, start_key(rsc), NULL, - pe_order_runnable_left, data_set); - } - - do_crm_log(LOG_INFO, "Cancel action %s (%s vs. %s) on %s", - key, role, role2text(rsc->next_role), crm_str(node_uname)); - } - } - - for(gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { - node_t *stop_node = (node_t*)gIter->data; - const char *stop_node_uname = stop_node->details->uname; - gboolean is_optional = TRUE; - gboolean probe_is_optional = TRUE; - gboolean stop_is_optional = TRUE; - action_t *stopped_mon = NULL; - char *rc_inactive = NULL; - GListPtr probe_complete_ops = NULL; - GListPtr stop_ops = NULL; - GListPtr local_gIter = NULL; - char *stop_op_key = NULL; - - if(node_uname && safe_str_eq(stop_node_uname, node_uname)) { - continue; - } - - crm_debug_2("Creating recurring action %s for %s on %s", + if (node != NULL) { + possible_matches = find_actions_exact(rsc->actions, key, node); + if (possible_matches) { + action_t *cancel_op = NULL; + char *local_key = crm_strdup(key); + + g_list_free(possible_matches); + + cancel_op = custom_action(rsc, local_key, RSC_CANCEL, node, FALSE, TRUE, data_set); + + crm_free(cancel_op->task); + cancel_op->task = crm_strdup(RSC_CANCEL); + add_hash_param(cancel_op->meta, XML_LRM_ATTR_INTERVAL, interval); + add_hash_param(cancel_op->meta, XML_LRM_ATTR_TASK, name); + + local_key = NULL; + + if (rsc->next_role == RSC_ROLE_STARTED || rsc->next_role == RSC_ROLE_SLAVE) { + /* rsc->role == RSC_ROLE_STOPPED: cancel the monitor before start */ + /* rsc->role == RSC_ROLE_STARTED: for a migration, cancel the monitor on the target node before start */ + custom_action_order(rsc, NULL, cancel_op, rsc, start_key(rsc), NULL, + pe_order_runnable_left, data_set); + } + + do_crm_log(LOG_INFO, "Cancel action %s (%s vs. %s) on %s", + key, role, role2text(rsc->next_role), crm_str(node_uname)); + } + } + + for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) { + node_t *stop_node = (node_t *) gIter->data; + const char *stop_node_uname = stop_node->details->uname; + gboolean is_optional = TRUE; + gboolean probe_is_optional = TRUE; + gboolean stop_is_optional = TRUE; + action_t *stopped_mon = NULL; + char *rc_inactive = NULL; + GListPtr probe_complete_ops = NULL; + GListPtr stop_ops = NULL; + GListPtr local_gIter = NULL; + char *stop_op_key = NULL; + + if (node_uname && safe_str_eq(stop_node_uname, node_uname)) { + continue; + } + + crm_debug_2("Creating recurring action %s for %s on %s", ID(operation), rsc->id, crm_str(stop_node_uname)); - /* start a monitor for an already stopped resource */ - possible_matches = find_actions_exact(rsc->actions, key, stop_node); - if(possible_matches == NULL) { - crm_debug_3("Marking %s manditory on %s: not active", key, crm_str(stop_node_uname)); - is_optional = FALSE; - } else { - crm_debug_3("Marking %s optional on %s: already active", key, crm_str(stop_node_uname)); - is_optional = TRUE; - g_list_free(possible_matches); - } - - stopped_mon = custom_action(rsc, crm_strdup(key), name, stop_node, - is_optional, TRUE, data_set); - - rc_inactive = crm_itoa(EXECRA_NOT_RUNNING); - add_hash_param(stopped_mon->meta, XML_ATTR_TE_TARGET_RC, rc_inactive); - crm_free(rc_inactive); - - probe_complete_ops = find_actions(data_set->actions, CRM_OP_PROBED, NULL); - for(local_gIter = probe_complete_ops; local_gIter != NULL; local_gIter = local_gIter->next) { - action_t *probe_complete = (action_t*)local_gIter->data; - - if (probe_complete->node == NULL) { - if(is_set(probe_complete->flags, pe_action_optional) == FALSE) { - probe_is_optional = FALSE; - } - - if(is_set(probe_complete->flags, pe_action_runnable) == FALSE) { - crm_debug("%s\t %s (cancelled : probe un-runnable)", - crm_str(stop_node_uname), stopped_mon->uuid); - update_action_flags(stopped_mon, pe_action_runnable|pe_action_clear); - } - - if(is_set(rsc->flags, pe_rsc_managed)) { - custom_action_order(NULL, NULL, probe_complete, - NULL, crm_strdup(key), stopped_mon, - pe_order_optional, data_set); - } - break; - } - } - - if(probe_complete_ops) { - g_list_free(probe_complete_ops); - } - - stop_op_key = stop_key(rsc); - stop_ops = find_actions_exact(rsc->actions, stop_op_key, stop_node); - - for(local_gIter = stop_ops; local_gIter != NULL; local_gIter = local_gIter->next) { - action_t *stop = (action_t*)local_gIter->data; - - if(is_set(stop->flags, pe_action_optional) == FALSE) { - stop_is_optional = FALSE; - } - - if(is_set(stop->flags, pe_action_runnable) == FALSE) { - crm_debug("%s\t %s (cancelled : stop un-runnable)", - crm_str(stop_node_uname), stopped_mon->uuid); - update_action_flags(stopped_mon, pe_action_runnable|pe_action_clear); - } - - if(is_set(rsc->flags, pe_rsc_managed)) { - custom_action_order(rsc, crm_strdup(stop_op_key), stop, - NULL, crm_strdup(key), stopped_mon, - pe_order_implies_then|pe_order_runnable_left, data_set); - } - - } - - if(stop_ops) { - g_list_free(stop_ops); - } - crm_free(stop_op_key); - - if(is_optional == FALSE && probe_is_optional && stop_is_optional - && is_set(rsc->flags, pe_rsc_managed) == FALSE) { - crm_debug_3("Marking %s optional on %s due to unmanaged", - key, crm_str(stop_node_uname)); - update_action_flags(stopped_mon, pe_action_optional); - } - - if(is_set(stopped_mon->flags, pe_action_optional)) { - crm_debug_2("%s\t %s (optional)", - crm_str(stop_node_uname), stopped_mon->uuid); - } - - if(stop_node->details->online == FALSE - || stop_node->details->unclean) { - crm_debug("%s\t %s (cancelled : no node available)", - crm_str(stop_node_uname), stopped_mon->uuid); - update_action_flags(stopped_mon, pe_action_runnable|pe_action_clear); - } - - if(is_set(stopped_mon->flags, pe_action_runnable) - && is_set(stopped_mon->flags, pe_action_optional) == FALSE) { - crm_notice(" Start recurring %s (%llus) for %s on %s", stopped_mon->task, interval_ms/1000, rsc->id, crm_str(stop_node_uname)); - } - } - + /* start a monitor for an already stopped resource */ + possible_matches = find_actions_exact(rsc->actions, key, stop_node); + if (possible_matches == NULL) { + crm_debug_3("Marking %s manditory on %s: not active", key, crm_str(stop_node_uname)); + is_optional = FALSE; + } else { + crm_debug_3("Marking %s optional on %s: already active", key, crm_str(stop_node_uname)); + is_optional = TRUE; + g_list_free(possible_matches); + } + + stopped_mon = custom_action(rsc, crm_strdup(key), name, stop_node, + is_optional, TRUE, data_set); + + rc_inactive = crm_itoa(EXECRA_NOT_RUNNING); + add_hash_param(stopped_mon->meta, XML_ATTR_TE_TARGET_RC, rc_inactive); + crm_free(rc_inactive); + + probe_complete_ops = find_actions(data_set->actions, CRM_OP_PROBED, NULL); + for (local_gIter = probe_complete_ops; local_gIter != NULL; local_gIter = local_gIter->next) { + action_t *probe_complete = (action_t *) local_gIter->data; + + if (probe_complete->node == NULL) { + if (is_set(probe_complete->flags, pe_action_optional) == FALSE) { + probe_is_optional = FALSE; + } + + if (is_set(probe_complete->flags, pe_action_runnable) == FALSE) { + crm_debug("%s\t %s (cancelled : probe un-runnable)", + crm_str(stop_node_uname), stopped_mon->uuid); + update_action_flags(stopped_mon, pe_action_runnable | pe_action_clear); + } + + if (is_set(rsc->flags, pe_rsc_managed)) { + custom_action_order(NULL, NULL, probe_complete, + NULL, crm_strdup(key), stopped_mon, + pe_order_optional, data_set); + } + break; + } + } + + if (probe_complete_ops) { + g_list_free(probe_complete_ops); + } + + stop_op_key = stop_key(rsc); + stop_ops = find_actions_exact(rsc->actions, stop_op_key, stop_node); + + for (local_gIter = stop_ops; local_gIter != NULL; local_gIter = local_gIter->next) { + action_t *stop = (action_t *) local_gIter->data; + + if (is_set(stop->flags, pe_action_optional) == FALSE) { + stop_is_optional = FALSE; + } + + if (is_set(stop->flags, pe_action_runnable) == FALSE) { + crm_debug("%s\t %s (cancelled : stop un-runnable)", + crm_str(stop_node_uname), stopped_mon->uuid); + update_action_flags(stopped_mon, pe_action_runnable | pe_action_clear); + } + + if (is_set(rsc->flags, pe_rsc_managed)) { + custom_action_order(rsc, crm_strdup(stop_op_key), stop, + NULL, crm_strdup(key), stopped_mon, + pe_order_implies_then | pe_order_runnable_left, data_set); + } + + } + + if (stop_ops) { + g_list_free(stop_ops); + } + crm_free(stop_op_key); + + if (is_optional == FALSE && probe_is_optional && stop_is_optional + && is_set(rsc->flags, pe_rsc_managed) == FALSE) { + crm_debug_3("Marking %s optional on %s due to unmanaged", + key, crm_str(stop_node_uname)); + update_action_flags(stopped_mon, pe_action_optional); + } + + if (is_set(stopped_mon->flags, pe_action_optional)) { + crm_debug_2("%s\t %s (optional)", crm_str(stop_node_uname), stopped_mon->uuid); + } + + if (stop_node->details->online == FALSE || stop_node->details->unclean) { + crm_debug("%s\t %s (cancelled : no node available)", + crm_str(stop_node_uname), stopped_mon->uuid); + update_action_flags(stopped_mon, pe_action_runnable | pe_action_clear); + } + + if (is_set(stopped_mon->flags, pe_action_runnable) + && is_set(stopped_mon->flags, pe_action_optional) == FALSE) { + crm_notice(" Start recurring %s (%llus) for %s on %s", stopped_mon->task, + interval_ms / 1000, rsc->id, crm_str(stop_node_uname)); + } + } + crm_free(key); } void -Recurring_Stopped(resource_t *rsc, action_t *start, node_t *node, - pe_working_set_t *data_set) +Recurring_Stopped(resource_t * rsc, action_t * start, node_t * node, pe_working_set_t * data_set) { - if(is_not_set(data_set->flags, pe_flag_maintenance_mode)) { - xmlNode *operation = NULL; - for(operation = __xml_first_child(rsc->ops_xml); operation != NULL; operation = __xml_next(operation)) { - if(crm_str_eq((const char *)operation->name, "op", TRUE)) { - RecurringOp_Stopped(rsc, start, node, operation, data_set); - } - } + if (is_not_set(data_set->flags, pe_flag_maintenance_mode)) { + xmlNode *operation = NULL; + + for (operation = __xml_first_child(rsc->ops_xml); operation != NULL; + operation = __xml_next(operation)) { + if (crm_str_eq((const char *)operation->name, "op", TRUE)) { + RecurringOp_Stopped(rsc, start, node, operation, data_set); + } + } } } -void native_create_actions(resource_t *rsc, pe_working_set_t *data_set) +void +native_create_actions(resource_t * rsc, pe_working_set_t * data_set) { action_t *start = NULL; node_t *chosen = NULL; GListPtr gIter = NULL; enum rsc_role_e role = RSC_ROLE_UNKNOWN; enum rsc_role_e next_role = RSC_ROLE_UNKNOWN; crm_debug_2("Createing actions for %s: %s->%s", rsc->id, - role2text(rsc->role), role2text(rsc->next_role)); - + role2text(rsc->role), role2text(rsc->next_role)); + chosen = rsc->allocated_to; - if(chosen != NULL && rsc->next_role == RSC_ROLE_UNKNOWN) { - rsc->next_role = RSC_ROLE_STARTED; + if (chosen != NULL && rsc->next_role == RSC_ROLE_UNKNOWN) { + rsc->next_role = RSC_ROLE_STARTED; - } else if(rsc->next_role == RSC_ROLE_UNKNOWN) { - rsc->next_role = RSC_ROLE_STOPPED; + } else if (rsc->next_role == RSC_ROLE_UNKNOWN) { + rsc->next_role = RSC_ROLE_STOPPED; } get_rsc_attributes(rsc->parameters, rsc, chosen, data_set); - for(gIter = rsc->dangling_migrations; gIter != NULL; gIter = gIter->next) { - node_t *current = (node_t*)gIter->data; - - action_t *stop = stop_action(rsc, current, FALSE); - set_bit_inplace(stop->flags, pe_action_dangle); - crm_trace("Forcing a cleanup of %s on %s", rsc->id, current->details->uname); - - if(is_set(data_set->flags, pe_flag_remove_after_stop)) { - DeleteRsc(rsc, current, FALSE, data_set); - } - } - - if(g_list_length(rsc->running_on) > 1) { - const char *type = crm_element_value(rsc->xml, XML_ATTR_TYPE); - const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); - - pe_proc_err("Resource %s (%s::%s) is active on %d nodes %s", - rsc->id, class, type, g_list_length(rsc->running_on), - recovery2text(rsc->recovery_type)); - cl_log(LOG_WARNING, "See %s for more information.", - "http://clusterlabs.org/wiki/FAQ#Resource_is_Too_Active"); - - if(rsc->recovery_type == recovery_stop_start) { - if(rsc->role == RSC_ROLE_MASTER) { - DemoteRsc(rsc, NULL, FALSE, data_set); - } - StopRsc(rsc, NULL, FALSE, data_set); - rsc->role = RSC_ROLE_STOPPED; - } - - } else if(rsc->running_on != NULL) { - node_t *current = rsc->running_on->data; - NoRoleChange(rsc, current, chosen, data_set); - - } else if(rsc->role == RSC_ROLE_STOPPED && rsc->next_role == RSC_ROLE_STOPPED) { - char *key = start_key(rsc); - GListPtr possible_matches = find_actions(rsc->actions, key, NULL); - GListPtr gIter = NULL; - for(gIter = possible_matches; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - - update_action_flags(action, pe_action_optional); + for (gIter = rsc->dangling_migrations; gIter != NULL; gIter = gIter->next) { + node_t *current = (node_t *) gIter->data; + + action_t *stop = stop_action(rsc, current, FALSE); + + set_bit_inplace(stop->flags, pe_action_dangle); + crm_trace("Forcing a cleanup of %s on %s", rsc->id, current->details->uname); + + if (is_set(data_set->flags, pe_flag_remove_after_stop)) { + DeleteRsc(rsc, current, FALSE, data_set); + } + } + + if (g_list_length(rsc->running_on) > 1) { + const char *type = crm_element_value(rsc->xml, XML_ATTR_TYPE); + const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); + + pe_proc_err("Resource %s (%s::%s) is active on %d nodes %s", + rsc->id, class, type, g_list_length(rsc->running_on), + recovery2text(rsc->recovery_type)); + cl_log(LOG_WARNING, "See %s for more information.", + "http://clusterlabs.org/wiki/FAQ#Resource_is_Too_Active"); + + if (rsc->recovery_type == recovery_stop_start) { + if (rsc->role == RSC_ROLE_MASTER) { + DemoteRsc(rsc, NULL, FALSE, data_set); + } + StopRsc(rsc, NULL, FALSE, data_set); + rsc->role = RSC_ROLE_STOPPED; + } + + } else if (rsc->running_on != NULL) { + node_t *current = rsc->running_on->data; + + NoRoleChange(rsc, current, chosen, data_set); + + } else if (rsc->role == RSC_ROLE_STOPPED && rsc->next_role == RSC_ROLE_STOPPED) { + char *key = start_key(rsc); + GListPtr possible_matches = find_actions(rsc->actions, key, NULL); + GListPtr gIter = NULL; + + for (gIter = possible_matches; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + update_action_flags(action, pe_action_optional); /* action->pseudo = TRUE; */ - } - - g_list_free(possible_matches); - crm_debug_2("Stopping a stopped resource"); - crm_free(key); - goto do_recurring; - - } else if(rsc->role != RSC_ROLE_STOPPED) { - /* A cheap trick to account for the fact that Master/Slave groups may not be - * completely running when we set their role to Slave - */ - crm_debug_2("Resetting %s.role = %s (was %s)", - rsc->id, role2text(RSC_ROLE_STOPPED), role2text(rsc->role)); - rsc->role = RSC_ROLE_STOPPED; + } + + g_list_free(possible_matches); + crm_debug_2("Stopping a stopped resource"); + crm_free(key); + goto do_recurring; + + } else if (rsc->role != RSC_ROLE_STOPPED) { + /* A cheap trick to account for the fact that Master/Slave groups may not be + * completely running when we set their role to Slave + */ + crm_debug_2("Resetting %s.role = %s (was %s)", + rsc->id, role2text(RSC_ROLE_STOPPED), role2text(rsc->role)); + rsc->role = RSC_ROLE_STOPPED; } role = rsc->role; - while(role != rsc->next_role) { - next_role = rsc_state_matrix[role][rsc->next_role]; - crm_debug_2("Executing: %s->%s (%s)", - role2text(role), role2text(next_role), rsc->id); - if(rsc_action_matrix[role][next_role]( - rsc, chosen, FALSE, data_set) == FALSE) { - break; - } - role = next_role; + while (role != rsc->next_role) { + next_role = rsc_state_matrix[role][rsc->next_role]; + crm_debug_2("Executing: %s->%s (%s)", role2text(role), role2text(next_role), rsc->id); + if (rsc_action_matrix[role][next_role] (rsc, chosen, FALSE, data_set) == FALSE) { + break; + } + role = next_role; } do_recurring: - if(rsc->next_role != RSC_ROLE_STOPPED || is_set(rsc->flags, pe_rsc_managed) == FALSE) { - start = start_action(rsc, chosen, TRUE); - Recurring(rsc, start, chosen, data_set); - Recurring_Stopped(rsc, start, chosen, data_set); + if (rsc->next_role != RSC_ROLE_STOPPED || is_set(rsc->flags, pe_rsc_managed) == FALSE) { + start = start_action(rsc, chosen, TRUE); + Recurring(rsc, start, chosen, data_set); + Recurring_Stopped(rsc, start, chosen, data_set); } else { - Recurring_Stopped(rsc, NULL, NULL, data_set); + Recurring_Stopped(rsc, NULL, NULL, data_set); } } -void native_internal_constraints(resource_t *rsc, pe_working_set_t *data_set) +void +native_internal_constraints(resource_t * rsc, pe_working_set_t * data_set) { /* This function is on the critical path and worth optimizing as much as possible */ resource_t *top = uber_parent(rsc); - int type = pe_order_optional|pe_order_implies_then|pe_order_restart; + int type = pe_order_optional | pe_order_implies_then | pe_order_restart; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); custom_action_order(rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL, - rsc, generate_op_key(rsc->id, RSC_START, 0), NULL, - type, data_set); - - if(top->variant == pe_master) { - custom_action_order(rsc, generate_op_key(rsc->id, RSC_DEMOTE, 0), NULL, - rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL, - pe_order_optional, data_set); - - custom_action_order(rsc, generate_op_key(rsc->id, RSC_START, 0), NULL, - rsc, generate_op_key(rsc->id, RSC_PROMOTE, 0), NULL, - pe_order_runnable_left, data_set); - } - - if(is_not_set(rsc->flags, pe_rsc_managed)) { - crm_debug_3("Skipping fencing constraints for unmanaged resource: %s", rsc->id); - return; - } - - if(safe_str_neq(class, "stonith")) { - action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set); - custom_action_order( - rsc, stop_key(rsc), NULL, - NULL, crm_strdup(all_stopped->task), all_stopped, - pe_order_implies_then|pe_order_runnable_left, data_set); - } - + rsc, generate_op_key(rsc->id, RSC_START, 0), NULL, type, data_set); + + if (top->variant == pe_master) { + custom_action_order(rsc, generate_op_key(rsc->id, RSC_DEMOTE, 0), NULL, + rsc, generate_op_key(rsc->id, RSC_STOP, 0), NULL, + pe_order_optional, data_set); + + custom_action_order(rsc, generate_op_key(rsc->id, RSC_START, 0), NULL, + rsc, generate_op_key(rsc->id, RSC_PROMOTE, 0), NULL, + pe_order_runnable_left, data_set); + } + + if (is_not_set(rsc->flags, pe_rsc_managed)) { + crm_debug_3("Skipping fencing constraints for unmanaged resource: %s", rsc->id); + return; + } + + if (safe_str_neq(class, "stonith")) { + action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set); + + custom_action_order(rsc, stop_key(rsc), NULL, + NULL, crm_strdup(all_stopped->task), all_stopped, + pe_order_implies_then | pe_order_runnable_left, data_set); + } + if (g_hash_table_size(rsc->utilization) > 0 - && safe_str_neq(data_set->placement_strategy, "default")) { - GHashTableIter iter; - node_t *next = NULL; - GListPtr gIter = NULL; - - crm_trace("Creating utilization constraints for %s - strategy: %s", - rsc->id, data_set->placement_strategy); - - for(gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) { - node_t *current = (node_t*)gIter->data; - - char *load_stopped_task = crm_concat(LOAD_STOPPED, current->details->uname, '_'); - action_t *load_stopped = get_pseudo_op(load_stopped_task, data_set); - if(load_stopped->node == NULL) { - load_stopped->node = node_copy(current); - update_action_flags(load_stopped, pe_action_optional|pe_action_clear); - } - - custom_action_order( - rsc, stop_key(rsc), NULL, - NULL, load_stopped_task, load_stopped, - pe_order_optional, data_set); - } - - g_hash_table_iter_init (&iter, rsc->allowed_nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&next)) { - char *load_stopped_task = crm_concat(LOAD_STOPPED, next->details->uname, '_'); - action_t *load_stopped = get_pseudo_op(load_stopped_task, data_set); - if(load_stopped->node == NULL) { - load_stopped->node = node_copy(next); - update_action_flags(load_stopped, pe_action_optional|pe_action_clear); - } - - custom_action_order( - NULL, crm_strdup(load_stopped_task), load_stopped, - rsc, start_key(rsc), NULL, - pe_order_optional, data_set); - - custom_action_order( - NULL, crm_strdup(load_stopped_task), load_stopped, - rsc, generate_op_key(rsc->id, RSC_MIGRATE, 0), NULL, - pe_order_optional, data_set); - - crm_free(load_stopped_task); - } + && safe_str_neq(data_set->placement_strategy, "default")) { + GHashTableIter iter; + node_t *next = NULL; + GListPtr gIter = NULL; + + crm_trace("Creating utilization constraints for %s - strategy: %s", + rsc->id, data_set->placement_strategy); + + for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) { + node_t *current = (node_t *) gIter->data; + + char *load_stopped_task = crm_concat(LOAD_STOPPED, current->details->uname, '_'); + action_t *load_stopped = get_pseudo_op(load_stopped_task, data_set); + + if (load_stopped->node == NULL) { + load_stopped->node = node_copy(current); + update_action_flags(load_stopped, pe_action_optional | pe_action_clear); + } + + custom_action_order(rsc, stop_key(rsc), NULL, + NULL, load_stopped_task, load_stopped, pe_order_optional, data_set); + } + + g_hash_table_iter_init(&iter, rsc->allowed_nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&next)) { + char *load_stopped_task = crm_concat(LOAD_STOPPED, next->details->uname, '_'); + action_t *load_stopped = get_pseudo_op(load_stopped_task, data_set); + + if (load_stopped->node == NULL) { + load_stopped->node = node_copy(next); + update_action_flags(load_stopped, pe_action_optional | pe_action_clear); + } + + custom_action_order(NULL, crm_strdup(load_stopped_task), load_stopped, + rsc, start_key(rsc), NULL, pe_order_optional, data_set); + + custom_action_order(NULL, crm_strdup(load_stopped_task), load_stopped, + rsc, generate_op_key(rsc->id, RSC_MIGRATE, 0), NULL, + pe_order_optional, data_set); + + crm_free(load_stopped_task); + } } } -void native_rsc_colocation_lh( - resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) +void +native_rsc_colocation_lh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint) { - if(rsc_lh == NULL) { - pe_err("rsc_lh was NULL for %s", constraint->id); - return; - - } else if(constraint->rsc_rh == NULL) { - pe_err("rsc_rh was NULL for %s", constraint->id); - return; - } - - crm_debug_2("Processing colocation constraint between %s and %s", - rsc_lh->id, rsc_rh->id); - - rsc_rh->cmds->rsc_colocation_rh(rsc_lh, rsc_rh, constraint); + if (rsc_lh == NULL) { + pe_err("rsc_lh was NULL for %s", constraint->id); + return; + + } else if (constraint->rsc_rh == NULL) { + pe_err("rsc_rh was NULL for %s", constraint->id); + return; + } + + crm_debug_2("Processing colocation constraint between %s and %s", rsc_lh->id, rsc_rh->id); + + rsc_rh->cmds->rsc_colocation_rh(rsc_lh, rsc_rh, constraint); } static gboolean -filter_colocation_constraint( - resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) +filter_colocation_constraint(resource_t * rsc_lh, resource_t * rsc_rh, + rsc_colocation_t * constraint) { int level = LOG_DEBUG_4; - if(constraint->score == 0){ - return FALSE; - } - - if(constraint->score > 0 - && constraint->role_lh != RSC_ROLE_UNKNOWN - && constraint->role_lh != rsc_lh->next_role) { - do_crm_log_unlikely(level, "LH: Skipping constraint: \"%s\" state filter", - role2text(constraint->role_rh)); - return FALSE; - } - - if(constraint->score > 0 - && constraint->role_rh != RSC_ROLE_UNKNOWN - && constraint->role_rh != rsc_rh->next_role) { - do_crm_log_unlikely(level, "RH: Skipping constraint: \"%s\" state filter", - role2text(constraint->role_rh)); - return FALSE; - } - - if(constraint->score < 0 - && constraint->role_lh != RSC_ROLE_UNKNOWN - && constraint->role_lh == rsc_lh->next_role) { - do_crm_log_unlikely(level, "LH: Skipping -ve constraint: \"%s\" state filter", - role2text(constraint->role_rh)); - return FALSE; - } - - if(constraint->score < 0 - && constraint->role_rh != RSC_ROLE_UNKNOWN - && constraint->role_rh == rsc_rh->next_role) { - do_crm_log_unlikely(level, "RH: Skipping -ve constraint: \"%s\" state filter", - role2text(constraint->role_rh)); - return FALSE; + + if (constraint->score == 0) { + return FALSE; + } + + if (constraint->score > 0 + && constraint->role_lh != RSC_ROLE_UNKNOWN && constraint->role_lh != rsc_lh->next_role) { + do_crm_log_unlikely(level, "LH: Skipping constraint: \"%s\" state filter", + role2text(constraint->role_rh)); + return FALSE; + } + + if (constraint->score > 0 + && constraint->role_rh != RSC_ROLE_UNKNOWN && constraint->role_rh != rsc_rh->next_role) { + do_crm_log_unlikely(level, "RH: Skipping constraint: \"%s\" state filter", + role2text(constraint->role_rh)); + return FALSE; + } + + if (constraint->score < 0 + && constraint->role_lh != RSC_ROLE_UNKNOWN && constraint->role_lh == rsc_lh->next_role) { + do_crm_log_unlikely(level, "LH: Skipping -ve constraint: \"%s\" state filter", + role2text(constraint->role_rh)); + return FALSE; + } + + if (constraint->score < 0 + && constraint->role_rh != RSC_ROLE_UNKNOWN && constraint->role_rh == rsc_rh->next_role) { + do_crm_log_unlikely(level, "RH: Skipping -ve constraint: \"%s\" state filter", + role2text(constraint->role_rh)); + return FALSE; } return TRUE; } static void -colocation_match( - resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) +colocation_match(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint) { const char *tmp = NULL; const char *value = NULL; const char *attribute = "#id"; GHashTable *work = NULL; gboolean do_check = FALSE; GHashTableIter iter; node_t *node = NULL; - if(constraint->node_attribute != NULL) { - attribute = constraint->node_attribute; + if (constraint->node_attribute != NULL) { + attribute = constraint->node_attribute; } - if(rsc_rh->allocated_to) { - value = g_hash_table_lookup( - rsc_rh->allocated_to->details->attrs, attribute); - do_check = TRUE; + if (rsc_rh->allocated_to) { + value = g_hash_table_lookup(rsc_rh->allocated_to->details->attrs, attribute); + do_check = TRUE; - } else if(constraint->score < 0) { - /* nothing to do: - * anti-colocation with something thats not running - */ - return; + } else if (constraint->score < 0) { + /* nothing to do: + * anti-colocation with something thats not running + */ + return; } work = node_hash_dup(rsc_lh->allowed_nodes); - - g_hash_table_iter_init (&iter, work); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - tmp = g_hash_table_lookup(node->details->attrs, attribute); - if(do_check && safe_str_eq(tmp, value)) { - if(constraint->score < INFINITY) { - crm_debug_2("%s: %s.%s += %d", constraint->id, rsc_lh->id, - node->details->uname, constraint->score); - node->weight = merge_weights( - constraint->score, node->weight); - } - - } else if(do_check == FALSE || constraint->score >= INFINITY) { - crm_debug_2("%s: %s.%s -= %d (%s)", constraint->id, rsc_lh->id, - node->details->uname, constraint->score, do_check?"failed":"unallocated"); - node->weight = merge_weights(-constraint->score, node->weight); - } - } - - if(can_run_any(work) - || constraint->score <= -INFINITY - || constraint->score >= INFINITY) { - g_hash_table_destroy(rsc_lh->allowed_nodes); - rsc_lh->allowed_nodes = work; - work = NULL; + + g_hash_table_iter_init(&iter, work); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + tmp = g_hash_table_lookup(node->details->attrs, attribute); + if (do_check && safe_str_eq(tmp, value)) { + if (constraint->score < INFINITY) { + crm_debug_2("%s: %s.%s += %d", constraint->id, rsc_lh->id, + node->details->uname, constraint->score); + node->weight = merge_weights(constraint->score, node->weight); + } + + } else if (do_check == FALSE || constraint->score >= INFINITY) { + crm_debug_2("%s: %s.%s -= %d (%s)", constraint->id, rsc_lh->id, + node->details->uname, constraint->score, + do_check ? "failed" : "unallocated"); + node->weight = merge_weights(-constraint->score, node->weight); + } + } + + if (can_run_any(work) + || constraint->score <= -INFINITY || constraint->score >= INFINITY) { + g_hash_table_destroy(rsc_lh->allowed_nodes); + rsc_lh->allowed_nodes = work; + work = NULL; } else { - char *score = score2char(constraint->score); - crm_info("%s: Rolling back scores from %s (%d, %s)", - rsc_lh->id, rsc_rh->id, do_check, score); - crm_free(score); + char *score = score2char(constraint->score); + + crm_info("%s: Rolling back scores from %s (%d, %s)", + rsc_lh->id, rsc_rh->id, do_check, score); + crm_free(score); } - if(work) { - g_hash_table_destroy(work); + if (work) { + g_hash_table_destroy(work); } } -void native_rsc_colocation_rh( - resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) +void +native_rsc_colocation_rh(resource_t * rsc_lh, resource_t * rsc_rh, rsc_colocation_t * constraint) { crm_debug_2("%sColocating %s with %s (%s, weight=%d)", - constraint->score >= 0?"":"Anti-", - rsc_lh->id, rsc_rh->id, constraint->id, constraint->score); - - if(filter_colocation_constraint(rsc_lh, rsc_rh, constraint) == FALSE) { - return; - } - - if(is_set(rsc_rh->flags, pe_rsc_provisional)) { - return; - - } else if(is_not_set(rsc_lh->flags, pe_rsc_provisional)) { - /* error check */ - struct node_shared_s *details_lh; - struct node_shared_s *details_rh; - if((constraint->score > -INFINITY) && (constraint->score < INFINITY)) { - return; - } - - details_rh = rsc_rh->allocated_to?rsc_rh->allocated_to->details:NULL; - details_lh = rsc_lh->allocated_to?rsc_lh->allocated_to->details:NULL; - - if(constraint->score == INFINITY && details_lh != details_rh) { - crm_err("%s and %s are both allocated" - " but to different nodes: %s vs. %s", - rsc_lh->id, rsc_rh->id, - details_lh?details_lh->uname:"n/a", - details_rh?details_rh->uname:"n/a"); - - } else if(constraint->score == -INFINITY && details_lh == details_rh) { - crm_err("%s and %s are both allocated" - " but to the SAME node: %s", - rsc_lh->id, rsc_rh->id, - details_rh?details_rh->uname:"n/a"); - } - - return; - + constraint->score >= 0 ? "" : "Anti-", + rsc_lh->id, rsc_rh->id, constraint->id, constraint->score); + + if (filter_colocation_constraint(rsc_lh, rsc_rh, constraint) == FALSE) { + return; + } + + if (is_set(rsc_rh->flags, pe_rsc_provisional)) { + return; + + } else if (is_not_set(rsc_lh->flags, pe_rsc_provisional)) { + /* error check */ + struct node_shared_s *details_lh; + struct node_shared_s *details_rh; + + if ((constraint->score > -INFINITY) && (constraint->score < INFINITY)) { + return; + } + + details_rh = rsc_rh->allocated_to ? rsc_rh->allocated_to->details : NULL; + details_lh = rsc_lh->allocated_to ? rsc_lh->allocated_to->details : NULL; + + if (constraint->score == INFINITY && details_lh != details_rh) { + crm_err("%s and %s are both allocated" + " but to different nodes: %s vs. %s", + rsc_lh->id, rsc_rh->id, + details_lh ? details_lh->uname : "n/a", details_rh ? details_rh->uname : "n/a"); + + } else if (constraint->score == -INFINITY && details_lh == details_rh) { + crm_err("%s and %s are both allocated" + " but to the SAME node: %s", + rsc_lh->id, rsc_rh->id, details_rh ? details_rh->uname : "n/a"); + } + + return; + } else { - colocation_match(rsc_lh, rsc_rh, constraint); + colocation_match(rsc_lh, rsc_rh, constraint); } } static gboolean -filter_rsc_ticket( - resource_t *rsc_lh, rsc_ticket_t *rsc_ticket) +filter_rsc_ticket(resource_t * rsc_lh, rsc_ticket_t * rsc_ticket) { int level = LOG_DEBUG_4; - if(rsc_ticket->role_lh != RSC_ROLE_UNKNOWN - && rsc_ticket->role_lh != rsc_lh->role) { - do_crm_log_unlikely(level, "LH: Skipping constraint: \"%s\" state filter", - role2text(rsc_ticket->role_lh)); - return FALSE; + if (rsc_ticket->role_lh != RSC_ROLE_UNKNOWN && rsc_ticket->role_lh != rsc_lh->role) { + do_crm_log_unlikely(level, "LH: Skipping constraint: \"%s\" state filter", + role2text(rsc_ticket->role_lh)); + return FALSE; } - + return TRUE; } -void rsc_ticket_constraint( - resource_t *rsc_lh, rsc_ticket_t *rsc_ticket, pe_working_set_t *data_set) +void +rsc_ticket_constraint(resource_t * rsc_lh, rsc_ticket_t * rsc_ticket, pe_working_set_t * data_set) { - if(rsc_ticket == NULL) { - pe_err("rsc_ticket was NULL"); - return; + if (rsc_ticket == NULL) { + pe_err("rsc_ticket was NULL"); + return; } - if(rsc_lh == NULL) { - pe_err("rsc_lh was NULL for %s", rsc_ticket->id); - return; + if (rsc_lh == NULL) { + pe_err("rsc_lh was NULL for %s", rsc_ticket->id); + return; } - if(rsc_ticket->ticket->granted == TRUE) { - return; + if (rsc_ticket->ticket->granted == TRUE) { + return; } - - if(rsc_lh->children) { - GListPtr gIter = rsc_lh->children; - crm_debug_4("Processing ticket dependencies from %s", rsc_lh->id); + if (rsc_lh->children) { + GListPtr gIter = rsc_lh->children; + + crm_debug_4("Processing ticket dependencies from %s", rsc_lh->id); - for(; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - rsc_ticket_constraint(child_rsc, rsc_ticket, data_set); - } - return; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + rsc_ticket_constraint(child_rsc, rsc_ticket, data_set); + } + return; } crm_debug_2("%s: Processing ticket dependency on %s (%s, %s)", - rsc_lh->id, rsc_ticket->ticket->id, rsc_ticket->id, role2text(rsc_ticket->role_lh)); - - if(g_list_length(rsc_lh->running_on) > 0) { - GListPtr gIter = NULL; - - switch(rsc_ticket->loss_policy) { - case loss_ticket_stop: - resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set); - break; - - case loss_ticket_demote: - /*Promotion score will be set to -INFINITY in master_promotion_order() */ - if(rsc_ticket->role_lh != RSC_ROLE_MASTER) { - resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set); - } - break; - - case loss_ticket_fence: - if(filter_rsc_ticket(rsc_lh, rsc_ticket) == FALSE) { - return; - } - - resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set); - - for(gIter = rsc_lh->running_on; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - - crm_warn("Node %s will be fenced for deadman", node->details->uname); - node->details->unclean = TRUE; - } - break; - - case loss_ticket_freeze: - if(filter_rsc_ticket(rsc_lh, rsc_ticket) == FALSE) { - return; - } - if (g_list_length(rsc_lh->running_on) > 0) { - clear_bit(rsc_lh->flags, pe_rsc_managed); - } - break; - } + rsc_lh->id, rsc_ticket->ticket->id, rsc_ticket->id, role2text(rsc_ticket->role_lh)); + + if (g_list_length(rsc_lh->running_on) > 0) { + GListPtr gIter = NULL; + + switch (rsc_ticket->loss_policy) { + case loss_ticket_stop: + resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set); + break; + + case loss_ticket_demote: + /*Promotion score will be set to -INFINITY in master_promotion_order() */ + if (rsc_ticket->role_lh != RSC_ROLE_MASTER) { + resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set); + } + break; + + case loss_ticket_fence: + if (filter_rsc_ticket(rsc_lh, rsc_ticket) == FALSE) { + return; + } + + resource_location(rsc_lh, NULL, -INFINITY, "__loss_of_ticket__", data_set); + + for (gIter = rsc_lh->running_on; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + crm_warn("Node %s will be fenced for deadman", node->details->uname); + node->details->unclean = TRUE; + } + break; + + case loss_ticket_freeze: + if (filter_rsc_ticket(rsc_lh, rsc_ticket) == FALSE) { + return; + } + if (g_list_length(rsc_lh->running_on) > 0) { + clear_bit(rsc_lh->flags, pe_rsc_managed); + } + break; + } } else { - if(rsc_ticket->role_lh != RSC_ROLE_MASTER || rsc_ticket->loss_policy == loss_ticket_stop) { - resource_location(rsc_lh, NULL, -INFINITY, "__no_ticket__", data_set); - } + if (rsc_ticket->role_lh != RSC_ROLE_MASTER || rsc_ticket->loss_policy == loss_ticket_stop) { + resource_location(rsc_lh, NULL, -INFINITY, "__no_ticket__", data_set); + } } } -const char *convert_non_atomic_task(char *raw_task, resource_t *rsc, gboolean allow_notify); +const char *convert_non_atomic_task(char *raw_task, resource_t * rsc, gboolean allow_notify); const char * -convert_non_atomic_task(char *raw_task, resource_t *rsc, gboolean allow_notify) +convert_non_atomic_task(char *raw_task, resource_t * rsc, gboolean allow_notify) { int task = no_action; const char *atomic_task = raw_task; crm_trace("Processing %s for %s", crm_str(raw_task), rsc->id); - if(raw_task == NULL) { - return NULL; + if (raw_task == NULL) { + return NULL; - } else if(strstr(raw_task, "notify") != NULL) { - goto done; /* no conversion */ + } else if (strstr(raw_task, "notify") != NULL) { + goto done; /* no conversion */ - } else if(rsc->variant < pe_group) { - goto done; /* no conversion */ + } else if (rsc->variant < pe_group) { + goto done; /* no conversion */ } task = text2task(raw_task); - switch(task) { - case stop_rsc: - case start_rsc: - case action_notify: - case action_promote: - case action_demote: - break; - case stopped_rsc: - case started_rsc: - case action_notified: - case action_promoted: - case action_demoted: - task--; - break; - case monitor_rsc: - case shutdown_crm: - case stonith_node: - goto done; - break; - default: - crm_trace("Unknown action: %s", raw_task); - goto done; - break; - } - - if(task != no_action) { - if(is_set(rsc->flags, pe_rsc_notify) && allow_notify) { - /* atomic_task = generate_notify_key(rid, "confirmed-post", task2text(task+1)); */ - crm_err("Not handled"); - - } else { - atomic_task = task2text(task+1); - } - crm_trace("Converted %s -> %s", raw_task, atomic_task); - } - + switch (task) { + case stop_rsc: + case start_rsc: + case action_notify: + case action_promote: + case action_demote: + break; + case stopped_rsc: + case started_rsc: + case action_notified: + case action_promoted: + case action_demoted: + task--; + break; + case monitor_rsc: + case shutdown_crm: + case stonith_node: + goto done; + break; + default: + crm_trace("Unknown action: %s", raw_task); + goto done; + break; + } + + if (task != no_action) { + if (is_set(rsc->flags, pe_rsc_notify) && allow_notify) { + /* atomic_task = generate_notify_key(rid, "confirmed-post", task2text(task+1)); */ + crm_err("Not handled"); + + } else { + atomic_task = task2text(task + 1); + } + crm_trace("Converted %s -> %s", raw_task, atomic_task); + } + done: return atomic_task; } -enum pe_action_flags native_action_flags(action_t *action, node_t *node) +enum pe_action_flags +native_action_flags(action_t * action, node_t * node) { return action->flags; } -enum pe_graph_flags native_update_actions( - action_t *first, action_t *then, node_t *node, enum pe_action_flags flags, enum pe_action_flags filter, enum pe_ordering type) +enum pe_graph_flags +native_update_actions(action_t * first, action_t * then, node_t * node, enum pe_action_flags flags, + enum pe_action_flags filter, enum pe_ordering type) { enum pe_graph_flags changed = pe_graph_none; enum pe_action_flags then_flags = then->flags; enum pe_action_flags first_flags = first->flags; - - if(type & pe_order_implies_first) { - if((filter & pe_action_optional) && (flags & pe_action_optional) == 0) { - clear_bit_inplace(first->flags, pe_action_optional); - } + + if (type & pe_order_implies_first) { + if ((filter & pe_action_optional) && (flags & pe_action_optional) == 0) { + clear_bit_inplace(first->flags, pe_action_optional); + } } - - if(is_set(type, pe_order_runnable_left) - && is_set(filter, pe_action_runnable) - && is_set(flags, pe_action_runnable) == FALSE) { - clear_bit_inplace(then->flags, pe_action_runnable); + + if (is_set(type, pe_order_runnable_left) + && is_set(filter, pe_action_runnable) + && is_set(flags, pe_action_runnable) == FALSE) { + clear_bit_inplace(then->flags, pe_action_runnable); } - if(is_set(type, pe_order_implies_then) - && is_set(filter, pe_action_optional) - && is_set(flags, pe_action_optional) == FALSE) { - clear_bit_inplace(then->flags, pe_action_optional); + if (is_set(type, pe_order_implies_then) + && is_set(filter, pe_action_optional) + && is_set(flags, pe_action_optional) == FALSE) { + clear_bit_inplace(then->flags, pe_action_optional); } - if(is_set(type, pe_order_restart)) { - const char *reason = NULL; - CRM_ASSERT(then->rsc == first->rsc); - CRM_ASSERT(then->rsc->variant == pe_native); + if (is_set(type, pe_order_restart)) { + const char *reason = NULL; - if((filter & pe_action_runnable) && (then->flags & pe_action_runnable) == 0) { - reason = "shutdown"; - } - - if((filter & pe_action_optional) && (then->flags & pe_action_optional) == 0) { - reason = "recover"; - } + CRM_ASSERT(then->rsc == first->rsc); + CRM_ASSERT(then->rsc->variant == pe_native); - if(reason - && is_set(first->flags, pe_action_optional) - && is_set(first->flags, pe_action_runnable)) { - crm_trace("Handling %s: %s -> %s", reason, first->uuid, then->uuid); - clear_bit_inplace(first->flags, pe_action_optional); - } + if ((filter & pe_action_runnable) && (then->flags & pe_action_runnable) == 0) { + reason = "shutdown"; + } + + if ((filter & pe_action_optional) && (then->flags & pe_action_optional) == 0) { + reason = "recover"; + } + + if (reason && is_set(first->flags, pe_action_optional) + && is_set(first->flags, pe_action_runnable)) { + crm_trace("Handling %s: %s -> %s", reason, first->uuid, then->uuid); + clear_bit_inplace(first->flags, pe_action_optional); + } } - if(then_flags != then->flags) { - changed |= pe_graph_updated_then; - crm_trace("Then: Flags for %s on %s are now 0x%.6x (were 0x%.6x) because of %s", - then->uuid, then->node?then->node->details->uname:"[none]", then->flags, then_flags, first->uuid); + if (then_flags != then->flags) { + changed |= pe_graph_updated_then; + crm_trace("Then: Flags for %s on %s are now 0x%.6x (were 0x%.6x) because of %s", + then->uuid, then->node ? then->node->details->uname : "[none]", then->flags, + then_flags, first->uuid); } - if(first_flags != first->flags) { - changed |= pe_graph_updated_first; - crm_trace("First: Flags for %s on %s are now 0x%.6x (were 0x%.6x) because of %s", - first->uuid, first->node?first->node->details->uname:"[none]", first->flags, first_flags, then->uuid); + if (first_flags != first->flags) { + changed |= pe_graph_updated_first; + crm_trace("First: Flags for %s on %s are now 0x%.6x (were 0x%.6x) because of %s", + first->uuid, first->node ? first->node->details->uname : "[none]", first->flags, + first_flags, then->uuid); } return changed; } -void native_rsc_location(resource_t *rsc, rsc_to_node_t *constraint) +void +native_rsc_location(resource_t * rsc, rsc_to_node_t * constraint) { GListPtr gIter = NULL; GHashTableIter iter; node_t *node = NULL; crm_debug_2("Applying %s (%s) to %s", constraint->id, - role2text(constraint->role_filter), rsc->id); + role2text(constraint->role_filter), rsc->id); /* take "lifetime" into account */ - if(constraint == NULL) { - pe_err("Constraint is NULL"); - return; - - } else if(rsc == NULL) { - pe_err("LHS of rsc_to_node (%s) is NULL", constraint->id); - return; - - } else if(constraint->role_filter > 0 - && constraint->role_filter != rsc->next_role) { - crm_debug("Constraint (%s) is not active (role : %s)", - constraint->id, role2text(constraint->role_filter)); - return; - - } else if(is_active(constraint) == FALSE) { - crm_debug_2("Constraint (%s) is not active", constraint->id); - return; - } - - if(constraint->node_list_rh == NULL) { - crm_debug_2("RHS of constraint %s is NULL", constraint->id); - return; - } - - for(gIter = constraint->node_list_rh; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - node_t *other_node = NULL; - - other_node = (node_t*)pe_hash_table_lookup( - rsc->allowed_nodes, node->details->id); - - if(other_node != NULL) { - crm_debug_4("%s + %s: %d + %d", - node->details->uname, - other_node->details->uname, - node->weight, other_node->weight); - other_node->weight = merge_weights( - other_node->weight, node->weight); - - } else { - node_t *new_node = node_copy(node); - g_hash_table_insert(rsc->allowed_nodes, (gpointer)new_node->details->id, new_node); - } + if (constraint == NULL) { + pe_err("Constraint is NULL"); + return; + + } else if (rsc == NULL) { + pe_err("LHS of rsc_to_node (%s) is NULL", constraint->id); + return; + + } else if (constraint->role_filter > 0 && constraint->role_filter != rsc->next_role) { + crm_debug("Constraint (%s) is not active (role : %s)", + constraint->id, role2text(constraint->role_filter)); + return; + + } else if (is_active(constraint) == FALSE) { + crm_debug_2("Constraint (%s) is not active", constraint->id); + return; } - g_hash_table_iter_init (&iter, rsc->allowed_nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - crm_debug_3("%s + %s : %d", rsc->id, node->details->uname, node->weight); + if (constraint->node_list_rh == NULL) { + crm_debug_2("RHS of constraint %s is NULL", constraint->id); + return; + } + + for (gIter = constraint->node_list_rh; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + node_t *other_node = NULL; + + other_node = (node_t *) pe_hash_table_lookup(rsc->allowed_nodes, node->details->id); + + if (other_node != NULL) { + crm_debug_4("%s + %s: %d + %d", + node->details->uname, + other_node->details->uname, node->weight, other_node->weight); + other_node->weight = merge_weights(other_node->weight, node->weight); + + } else { + node_t *new_node = node_copy(node); + + g_hash_table_insert(rsc->allowed_nodes, (gpointer) new_node->details->id, new_node); + } + } + + g_hash_table_iter_init(&iter, rsc->allowed_nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + crm_debug_3("%s + %s : %d", rsc->id, node->details->uname, node->weight); } } -void native_expand(resource_t *rsc, pe_working_set_t *data_set) +void +native_expand(resource_t * rsc, pe_working_set_t * data_set) { GListPtr gIter = NULL; + crm_debug_3("Processing actions from %s", rsc->id); - for(gIter = rsc->actions; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - - crm_debug_4("processing action %d for rsc=%s", - action->id, rsc->id); - graph_element_from_action(action, data_set); + for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + crm_debug_4("processing action %d for rsc=%s", action->id, rsc->id); + graph_element_from_action(action, data_set); } - for(gIter = rsc->children; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - - child_rsc->cmds->expand(child_rsc, data_set); + for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + child_rsc->cmds->expand(child_rsc, data_set); } } - void -LogActions(resource_t *rsc, pe_working_set_t *data_set) +LogActions(resource_t * rsc, pe_working_set_t * data_set) { node_t *next = NULL; node_t *current = NULL; action_t *stop = NULL; action_t *start = NULL; char *key = NULL; gboolean moving = FALSE; GListPtr possible_matches = NULL; - - if(rsc->children) { - GListPtr gIter = NULL; - for(gIter = rsc->children; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - - LogActions(child_rsc, data_set); - } - return; - } - + + if (rsc->children) { + GListPtr gIter = NULL; + + for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + LogActions(child_rsc, data_set); + } + return; + } + next = rsc->allocated_to; - if(rsc->running_on) { - current = rsc->running_on->data; - if(rsc->role == RSC_ROLE_STOPPED) { - /* - * This can occur when resources are being recovered - * We fiddle with the current role in native_create_actions() - */ - rsc->role = RSC_ROLE_STARTED; - } + if (rsc->running_on) { + current = rsc->running_on->data; + if (rsc->role == RSC_ROLE_STOPPED) { + /* + * This can occur when resources are being recovered + * We fiddle with the current role in native_create_actions() + */ + rsc->role = RSC_ROLE_STARTED; + } } - if(current == NULL && is_set(rsc->flags, pe_rsc_orphan)) { - /* Don't log stopped orphans */ - return; + if (current == NULL && is_set(rsc->flags, pe_rsc_orphan)) { + /* Don't log stopped orphans */ + return; } - - if(is_not_set(rsc->flags, pe_rsc_managed) - || (current == NULL && next == NULL)) { - crm_notice("Leave %s\t(%s%s)", - rsc->id, role2text(rsc->role), is_not_set(rsc->flags, pe_rsc_managed)?" unmanaged":""); - return; + + if (is_not_set(rsc->flags, pe_rsc_managed) + || (current == NULL && next == NULL)) { + crm_notice("Leave %s\t(%s%s)", + rsc->id, role2text(rsc->role), is_not_set(rsc->flags, + pe_rsc_managed) ? " unmanaged" : ""); + return; } - if(current != NULL && next != NULL - && safe_str_neq(current->details->id, next->details->id)) { - moving = TRUE; + if (current != NULL && next != NULL && safe_str_neq(current->details->id, next->details->id)) { + moving = TRUE; } key = stop_key(rsc); possible_matches = find_actions(rsc->actions, key, next); crm_free(key); - - if(possible_matches) { - stop = possible_matches->data; - g_list_free(possible_matches); + + if (possible_matches) { + stop = possible_matches->data; + g_list_free(possible_matches); } - + key = start_key(rsc); possible_matches = find_actions(rsc->actions, key, next); crm_free(key); - - if(possible_matches) { - start = possible_matches->data; - g_list_free(possible_matches); - } - - if(rsc->role == rsc->next_role) { - key = generate_op_key(rsc->id, RSC_MIGRATED, 0); - possible_matches = find_actions(rsc->actions, key, next); - crm_free(key); - - CRM_CHECK(next != NULL,); - if(next == NULL) { - } else if(possible_matches && current) { - crm_notice("Migrate %s\t(%s %s -> %s)", - rsc->id, role2text(rsc->role), current->details->uname, next->details->uname); - g_list_free(possible_matches); - - } else if(start == NULL || is_set(start->flags, pe_action_optional)) { - crm_notice("Leave %s\t(%s %s)", - rsc->id, role2text(rsc->role), next->details->uname); - - } else if(moving && current) { - crm_notice("Move %s\t(%s %s -> %s)", - rsc->id, role2text(rsc->role), current->details->uname, next->details->uname); - - } else if(is_set(rsc->flags, pe_rsc_failed)) { - crm_notice("Recover %s\t(%s %s)", - rsc->id, role2text(rsc->role), next->details->uname); - - } else if(start && is_set(start->flags, pe_action_runnable) == FALSE) { - crm_notice("Stop %s\t(%s %s)", - rsc->id, role2text(rsc->role), next->details->uname); - - } else { - crm_notice("Restart %s\t(%s %s)", - rsc->id, role2text(rsc->role), next->details->uname); - } - - return; - } - - if(rsc->role > RSC_ROLE_SLAVE && rsc->role > rsc->next_role) { - CRM_CHECK(current != NULL,); - if(current != NULL) { - crm_notice("Demote %s\t(%s -> %s %s)", rsc->id, - role2text(rsc->role), role2text(rsc->next_role), - current->details->uname); - if(stop != NULL - && is_not_set(stop->flags, pe_action_optional) - && rsc->next_role > RSC_ROLE_STOPPED) { - if(is_set(rsc->flags, pe_rsc_failed)) { - crm_notice("Recover %s\t(%s %s)", - rsc->id, role2text(rsc->role), next->details->uname); - } else { - crm_notice("Restart %s\t(%s %s)", - rsc->id, role2text(rsc->role), next->details->uname); - } - } - } - - } else if(rsc->next_role == RSC_ROLE_STOPPED) { - GListPtr gIter = NULL; - CRM_CHECK(current != NULL,); - for(gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) { - node_t *node = (node_t*)gIter->data; - crm_notice("Stop %s\t(%s)", rsc->id, node->details->uname); - } - } - - if(moving) { - crm_notice("Move %s\t(%s %s -> %s)", - rsc->id, role2text(rsc->next_role), current->details->uname, next->details->uname); - } - - if(rsc->role == RSC_ROLE_STOPPED) { - CRM_CHECK(next != NULL,); - if(next != NULL) { - crm_notice("Start %s\t(%s)", rsc->id, next->details->uname); - } - } - - if(rsc->next_role > RSC_ROLE_SLAVE && rsc->role < rsc->next_role) { - CRM_CHECK(next != NULL,); - if(stop != NULL - && is_not_set(stop->flags, pe_action_optional) - && rsc->role > RSC_ROLE_STOPPED) { - if(is_set(rsc->flags, pe_rsc_failed)) { - crm_notice("Recover %s\t(%s %s)", - rsc->id, role2text(rsc->role), next->details->uname); - } else { - crm_notice("Restart %s\t(%s %s)", - rsc->id, role2text(rsc->role), next->details->uname); - } - } - - crm_notice("Promote %s\t(%s -> %s %s)", rsc->id, - role2text(rsc->role), role2text(rsc->next_role), - next->details->uname); + + if (possible_matches) { + start = possible_matches->data; + g_list_free(possible_matches); + } + + if (rsc->role == rsc->next_role) { + key = generate_op_key(rsc->id, RSC_MIGRATED, 0); + possible_matches = find_actions(rsc->actions, key, next); + crm_free(key); + + CRM_CHECK(next != NULL,); + if (next == NULL) { + } else if (possible_matches && current) { + crm_notice("Migrate %s\t(%s %s -> %s)", + rsc->id, role2text(rsc->role), current->details->uname, + next->details->uname); + g_list_free(possible_matches); + + } else if (start == NULL || is_set(start->flags, pe_action_optional)) { + crm_notice("Leave %s\t(%s %s)", rsc->id, role2text(rsc->role), next->details->uname); + + } else if (moving && current) { + crm_notice("Move %s\t(%s %s -> %s)", + rsc->id, role2text(rsc->role), current->details->uname, + next->details->uname); + + } else if (is_set(rsc->flags, pe_rsc_failed)) { + crm_notice("Recover %s\t(%s %s)", rsc->id, role2text(rsc->role), next->details->uname); + + } else if (start && is_set(start->flags, pe_action_runnable) == FALSE) { + crm_notice("Stop %s\t(%s %s)", rsc->id, role2text(rsc->role), next->details->uname); + + } else { + crm_notice("Restart %s\t(%s %s)", rsc->id, role2text(rsc->role), next->details->uname); + } + + return; + } + + if (rsc->role > RSC_ROLE_SLAVE && rsc->role > rsc->next_role) { + CRM_CHECK(current != NULL,); + if (current != NULL) { + crm_notice("Demote %s\t(%s -> %s %s)", rsc->id, + role2text(rsc->role), role2text(rsc->next_role), current->details->uname); + if (stop != NULL && is_not_set(stop->flags, pe_action_optional) + && rsc->next_role > RSC_ROLE_STOPPED) { + if (is_set(rsc->flags, pe_rsc_failed)) { + crm_notice("Recover %s\t(%s %s)", + rsc->id, role2text(rsc->role), next->details->uname); + } else { + crm_notice("Restart %s\t(%s %s)", + rsc->id, role2text(rsc->role), next->details->uname); + } + } + } + + } else if (rsc->next_role == RSC_ROLE_STOPPED) { + GListPtr gIter = NULL; + + CRM_CHECK(current != NULL,); + for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) { + node_t *node = (node_t *) gIter->data; + + crm_notice("Stop %s\t(%s)", rsc->id, node->details->uname); + } + } + + if (moving) { + crm_notice("Move %s\t(%s %s -> %s)", + rsc->id, role2text(rsc->next_role), current->details->uname, + next->details->uname); + } + + if (rsc->role == RSC_ROLE_STOPPED) { + CRM_CHECK(next != NULL,); + if (next != NULL) { + crm_notice("Start %s\t(%s)", rsc->id, next->details->uname); + } + } + + if (rsc->next_role > RSC_ROLE_SLAVE && rsc->role < rsc->next_role) { + CRM_CHECK(next != NULL,); + if (stop != NULL && is_not_set(stop->flags, pe_action_optional) + && rsc->role > RSC_ROLE_STOPPED) { + if (is_set(rsc->flags, pe_rsc_failed)) { + crm_notice("Recover %s\t(%s %s)", + rsc->id, role2text(rsc->role), next->details->uname); + } else { + crm_notice("Restart %s\t(%s %s)", + rsc->id, role2text(rsc->role), next->details->uname); + } + } + + crm_notice("Promote %s\t(%s -> %s %s)", rsc->id, + role2text(rsc->role), role2text(rsc->next_role), next->details->uname); } } void -NoRoleChange(resource_t *rsc, node_t *current, node_t *next, - pe_working_set_t *data_set) +NoRoleChange(resource_t * rsc, node_t * current, node_t * next, pe_working_set_t * data_set) { GListPtr gIter = NULL; action_t *stop = NULL; - action_t *start = NULL; + action_t *start = NULL; GListPtr possible_matches = NULL; crm_debug_2("Executing: %s (role=%s)", rsc->id, role2text(rsc->next_role)); - - if(current == NULL || next == NULL) { - return; - } - - if(is_set(rsc->flags, pe_rsc_failed) - || safe_str_neq(current->details->id, next->details->id)) { - - if(rsc->next_role > RSC_ROLE_STARTED) { - gboolean optional = TRUE; - if(rsc->role == RSC_ROLE_MASTER) { - optional = FALSE; - } - DemoteRsc(rsc, current, optional, data_set); - } - if(rsc->role == RSC_ROLE_MASTER) { - DemoteRsc(rsc, current, FALSE, data_set); - } - StopRsc(rsc, current, FALSE, data_set); - StartRsc(rsc, next, FALSE, data_set); - if(rsc->next_role == RSC_ROLE_MASTER) { - PromoteRsc(rsc, next, FALSE, data_set); - } - - possible_matches = find_recurring_actions(rsc->actions, next); - for(gIter = possible_matches; gIter != NULL; gIter = gIter->next) { - action_t *match = (action_t*)gIter->data; - if(is_set(match->flags, pe_action_optional) == FALSE) { - crm_debug("Fixing recurring action: %s", - match->uuid); - update_action_flags(match, pe_action_optional); - } - } - g_list_free(possible_matches); - - } else if(is_set(rsc->flags, pe_rsc_start_pending)) { - start = start_action(rsc, next, TRUE); - if(is_set(start->flags, pe_action_runnable)) { - /* wait for StartRsc() to be called */ - rsc->role = RSC_ROLE_STOPPED; - } else { - /* wait for StopRsc() to be called */ - rsc->next_role = RSC_ROLE_STOPPED; - } - + + if (current == NULL || next == NULL) { + return; + } + + if (is_set(rsc->flags, pe_rsc_failed) + || safe_str_neq(current->details->id, next->details->id)) { + + if (rsc->next_role > RSC_ROLE_STARTED) { + gboolean optional = TRUE; + + if (rsc->role == RSC_ROLE_MASTER) { + optional = FALSE; + } + DemoteRsc(rsc, current, optional, data_set); + } + if (rsc->role == RSC_ROLE_MASTER) { + DemoteRsc(rsc, current, FALSE, data_set); + } + StopRsc(rsc, current, FALSE, data_set); + StartRsc(rsc, next, FALSE, data_set); + if (rsc->next_role == RSC_ROLE_MASTER) { + PromoteRsc(rsc, next, FALSE, data_set); + } + + possible_matches = find_recurring_actions(rsc->actions, next); + for (gIter = possible_matches; gIter != NULL; gIter = gIter->next) { + action_t *match = (action_t *) gIter->data; + + if (is_set(match->flags, pe_action_optional) == FALSE) { + crm_debug("Fixing recurring action: %s", match->uuid); + update_action_flags(match, pe_action_optional); + } + } + g_list_free(possible_matches); + + } else if (is_set(rsc->flags, pe_rsc_start_pending)) { + start = start_action(rsc, next, TRUE); + if (is_set(start->flags, pe_action_runnable)) { + /* wait for StartRsc() to be called */ + rsc->role = RSC_ROLE_STOPPED; + } else { + /* wait for StopRsc() to be called */ + rsc->next_role = RSC_ROLE_STOPPED; + } + } else { - - stop = stop_action(rsc, current, TRUE); - start = start_action(rsc, next, TRUE); - if(is_set(start->flags, pe_action_optional)) { - update_action_flags(stop, pe_action_optional); - } else { - update_action_flags(stop, pe_action_optional|pe_action_clear); - } - if(rsc->next_role > RSC_ROLE_STARTED) { - DemoteRsc(rsc, current, is_set(start->flags, pe_action_optional), data_set); - } - StopRsc(rsc, current, is_set(start->flags, pe_action_optional), data_set); - StartRsc(rsc, current, is_set(start->flags, pe_action_optional), data_set); - if(rsc->next_role == RSC_ROLE_MASTER) { - PromoteRsc(rsc, next, is_set(start->flags, pe_action_optional), data_set); - } - - if(is_set(start->flags, pe_action_runnable) == FALSE) { - rsc->next_role = RSC_ROLE_STOPPED; - } + + stop = stop_action(rsc, current, TRUE); + start = start_action(rsc, next, TRUE); + if (is_set(start->flags, pe_action_optional)) { + update_action_flags(stop, pe_action_optional); + } else { + update_action_flags(stop, pe_action_optional | pe_action_clear); + } + if (rsc->next_role > RSC_ROLE_STARTED) { + DemoteRsc(rsc, current, is_set(start->flags, pe_action_optional), data_set); + } + StopRsc(rsc, current, is_set(start->flags, pe_action_optional), data_set); + StartRsc(rsc, current, is_set(start->flags, pe_action_optional), data_set); + if (rsc->next_role == RSC_ROLE_MASTER) { + PromoteRsc(rsc, next, is_set(start->flags, pe_action_optional), data_set); + } + + if (is_set(start->flags, pe_action_runnable) == FALSE) { + rsc->next_role = RSC_ROLE_STOPPED; + } } } - gboolean -StopRsc(resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set) +StopRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set) { GListPtr gIter = NULL; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); crm_debug_2("Executing: %s", rsc->id); - if(rsc->next_role == RSC_ROLE_STOPPED - && rsc->variant == pe_native - && safe_str_eq(class, "stonith")) { - action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set); - custom_action_order( - NULL, crm_strdup(all_stopped->task), all_stopped, - rsc, stop_key(rsc), NULL, - pe_order_optional|pe_order_stonith_stop, data_set); - } - - for(gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) { - node_t *current = (node_t*)gIter->data; - - stop_action(rsc, current, optional); - - if(is_set(data_set->flags, pe_flag_remove_after_stop)) { - DeleteRsc(rsc, current, optional, data_set); - } - } - + if (rsc->next_role == RSC_ROLE_STOPPED + && rsc->variant == pe_native && safe_str_eq(class, "stonith")) { + action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set); + + custom_action_order(NULL, crm_strdup(all_stopped->task), all_stopped, + rsc, stop_key(rsc), NULL, + pe_order_optional | pe_order_stonith_stop, data_set); + } + + for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) { + node_t *current = (node_t *) gIter->data; + + stop_action(rsc, current, optional); + + if (is_set(data_set->flags, pe_flag_remove_after_stop)) { + DeleteRsc(rsc, current, optional, data_set); + } + } + return TRUE; } - gboolean -StartRsc(resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set) +StartRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set) { action_t *start = NULL; - + crm_debug_2("Executing: %s", rsc->id); start = start_action(rsc, next, TRUE); - if(is_set(start->flags, pe_action_runnable) && optional == FALSE) { - update_action_flags(start, pe_action_optional|pe_action_clear); - } + if (is_set(start->flags, pe_action_runnable) && optional == FALSE) { + update_action_flags(start, pe_action_optional | pe_action_clear); + } return TRUE; } gboolean -PromoteRsc(resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set) +PromoteRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set) { char *key = NULL; GListPtr gIter = NULL; gboolean runnable = TRUE; GListPtr action_list = NULL; + crm_debug_2("Executing: %s", rsc->id); CRM_CHECK(rsc->next_role == RSC_ROLE_MASTER, - crm_err("Next role: %s", role2text(rsc->next_role)); - return FALSE); + crm_err("Next role: %s", role2text(rsc->next_role)); return FALSE); CRM_CHECK(next != NULL, return FALSE); key = start_key(rsc); action_list = find_actions_exact(rsc->actions, key, next); crm_free(key); - for(gIter = action_list; gIter != NULL; gIter = gIter->next) { - action_t *start = (action_t*)gIter->data; - - if(is_set(start->flags, pe_action_runnable) == FALSE) { - runnable = FALSE; - } + for (gIter = action_list; gIter != NULL; gIter = gIter->next) { + action_t *start = (action_t *) gIter->data; + + if (is_set(start->flags, pe_action_runnable) == FALSE) { + runnable = FALSE; + } } g_list_free(action_list); - if(runnable) { - promote_action(rsc, next, optional); - return TRUE; - } + if (runnable) { + promote_action(rsc, next, optional); + return TRUE; + } crm_debug("%s\tPromote %s (canceled)", next->details->uname, rsc->id); key = promote_key(rsc); action_list = find_actions_exact(rsc->actions, key, next); crm_free(key); - for(gIter = action_list; gIter != NULL; gIter = gIter->next) { - action_t *promote = (action_t*)gIter->data; - update_action_flags(promote, pe_action_runnable|pe_action_clear); + for (gIter = action_list; gIter != NULL; gIter = gIter->next) { + action_t *promote = (action_t *) gIter->data; + + update_action_flags(promote, pe_action_runnable | pe_action_clear); } - + g_list_free(action_list); return TRUE; } gboolean -DemoteRsc(resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set) +DemoteRsc(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set) { GListPtr gIter = NULL; + crm_debug_2("Executing: %s", rsc->id); /* CRM_CHECK(rsc->next_role == RSC_ROLE_SLAVE, return FALSE); */ - for(gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) { - node_t *current = (node_t*)gIter->data; - - demote_action(rsc, current, optional); + for (gIter = rsc->running_on; gIter != NULL; gIter = gIter->next) { + node_t *current = (node_t *) gIter->data; + + demote_action(rsc, current, optional); } return TRUE; } gboolean -RoleError(resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set) +RoleError(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set) { crm_debug("Executing: %s", rsc->id); CRM_CHECK(FALSE, return FALSE); return FALSE; } gboolean -NullOp(resource_t *rsc, node_t *next, gboolean optional, pe_working_set_t *data_set) +NullOp(resource_t * rsc, node_t * next, gboolean optional, pe_working_set_t * data_set) { crm_debug_2("Executing: %s", rsc->id); return FALSE; } gboolean -DeleteRsc(resource_t *rsc, node_t *node, gboolean optional, pe_working_set_t *data_set) +DeleteRsc(resource_t * rsc, node_t * node, gboolean optional, pe_working_set_t * data_set) { action_t *delete = NULL; + #if DELETE_THEN_REFRESH action_t *refresh = NULL; #endif - if(is_set(rsc->flags, pe_rsc_failed)) { - crm_debug_2("Resource %s not deleted from %s: failed", - rsc->id, node->details->uname); - return FALSE; - - } else if(node == NULL) { - crm_debug_2("Resource %s not deleted: NULL node", rsc->id); - return FALSE; - - } else if(node->details->unclean || node->details->online == FALSE) { - crm_debug_2("Resource %s not deleted from %s: unrunnable", - rsc->id, node->details->uname); - return FALSE; - } - - crm_notice("Removing %s from %s", - rsc->id, node->details->uname); - + if (is_set(rsc->flags, pe_rsc_failed)) { + crm_debug_2("Resource %s not deleted from %s: failed", rsc->id, node->details->uname); + return FALSE; + + } else if (node == NULL) { + crm_debug_2("Resource %s not deleted: NULL node", rsc->id); + return FALSE; + + } else if (node->details->unclean || node->details->online == FALSE) { + crm_debug_2("Resource %s not deleted from %s: unrunnable", rsc->id, node->details->uname); + return FALSE; + } + + crm_notice("Removing %s from %s", rsc->id, node->details->uname); + delete = delete_action(rsc, node, optional); - - new_rsc_order(rsc, RSC_STOP, rsc, RSC_DELETE, - optional?pe_order_implies_then:pe_order_optional, data_set); - - new_rsc_order(rsc, RSC_DELETE, rsc, RSC_START, - optional?pe_order_implies_then:pe_order_optional, data_set); - + + new_rsc_order(rsc, RSC_STOP, rsc, RSC_DELETE, + optional ? pe_order_implies_then : pe_order_optional, data_set); + + new_rsc_order(rsc, RSC_DELETE, rsc, RSC_START, + optional ? pe_order_implies_then : pe_order_optional, data_set); + #if DELETE_THEN_REFRESH - refresh = custom_action( - NULL, crm_strdup(CRM_OP_LRM_REFRESH), CRM_OP_LRM_REFRESH, - node, FALSE, TRUE, data_set); + refresh = custom_action(NULL, crm_strdup(CRM_OP_LRM_REFRESH), CRM_OP_LRM_REFRESH, + node, FALSE, TRUE, data_set); add_hash_param(refresh->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE); order_actions(delete, refresh, pe_order_optional); #endif - + return TRUE; } #include <../lib/pengine/unpack.h> static node_t * -probe_grouped_clone(resource_t *rsc, node_t *node, pe_working_set_t *data_set) +probe_grouped_clone(resource_t * rsc, node_t * node, pe_working_set_t * data_set) { node_t *running = NULL; resource_t *top = uber_parent(rsc); - if(running == NULL && is_set(top->flags, pe_rsc_unique) == FALSE) { - /* Annoyingly we also need to check any other clone instances - * Clumsy, but it will work. - * - * An alternative would be to update known_on for every peer - * during process_rsc_state() - * - * This code desperately needs optimization - * ptest -x with 100 nodes, 100 clones and clone-max=10: - * No probes O(25s) - * Detection without clone loop O(3m) - * Detection with clone loop O(8m) - - ptest[32211]: 2010/02/18_14:27:55 CRIT: stage5: Probing for unknown resources - ptest[32211]: 2010/02/18_14:33:39 CRIT: stage5: Done - ptest[32211]: 2010/02/18_14:35:05 CRIT: stage7: Updating action states - ptest[32211]: 2010/02/18_14:35:05 CRIT: stage7: Done - - */ - char *clone_id = clone_zero(rsc->id); - resource_t *peer = pe_find_resource(top->children, clone_id); - - while(peer && running == NULL) { - running = pe_hash_table_lookup(peer->known_on, node->details->id); - if(running != NULL) { - /* we already know the status of the resource on this node */ - crm_debug_3("Skipping active clone: %s", rsc->id); - crm_free(clone_id); - return running; - } - clone_id = increment_clone(clone_id); - peer = pe_find_resource(data_set->resources, clone_id); - } - - crm_free(clone_id); + + if (running == NULL && is_set(top->flags, pe_rsc_unique) == FALSE) { + /* Annoyingly we also need to check any other clone instances + * Clumsy, but it will work. + * + * An alternative would be to update known_on for every peer + * during process_rsc_state() + * + * This code desperately needs optimization + * ptest -x with 100 nodes, 100 clones and clone-max=10: + * No probes O(25s) + * Detection without clone loop O(3m) + * Detection with clone loop O(8m) + + ptest[32211]: 2010/02/18_14:27:55 CRIT: stage5: Probing for unknown resources + ptest[32211]: 2010/02/18_14:33:39 CRIT: stage5: Done + ptest[32211]: 2010/02/18_14:35:05 CRIT: stage7: Updating action states + ptest[32211]: 2010/02/18_14:35:05 CRIT: stage7: Done + + */ + char *clone_id = clone_zero(rsc->id); + resource_t *peer = pe_find_resource(top->children, clone_id); + + while (peer && running == NULL) { + running = pe_hash_table_lookup(peer->known_on, node->details->id); + if (running != NULL) { + /* we already know the status of the resource on this node */ + crm_debug_3("Skipping active clone: %s", rsc->id); + crm_free(clone_id); + return running; + } + clone_id = increment_clone(clone_id); + peer = pe_find_resource(data_set->resources, clone_id); + } + + crm_free(clone_id); } return running; } gboolean -native_create_probe(resource_t *rsc, node_t *node, action_t *complete, - gboolean force, pe_working_set_t *data_set) +native_create_probe(resource_t * rsc, node_t * node, action_t * complete, + gboolean force, pe_working_set_t * data_set) { char *key = NULL; action_t *probe = NULL; node_t *running = NULL; resource_t *top = uber_parent(rsc); - + static const char *rc_master = NULL; static const char *rc_inactive = NULL; - if(rc_inactive == NULL) { - rc_inactive = crm_itoa(EXECRA_NOT_RUNNING); - rc_master = crm_itoa(EXECRA_RUNNING_MASTER); + if (rc_inactive == NULL) { + rc_inactive = crm_itoa(EXECRA_NOT_RUNNING); + rc_master = crm_itoa(EXECRA_RUNNING_MASTER); } CRM_CHECK(node != NULL, return FALSE); - if(force == FALSE && is_not_set(data_set->flags, pe_flag_startup_probes)) { - crm_debug_2("Skipping active resource detection for %s", rsc->id); - return FALSE; + if (force == FALSE && is_not_set(data_set->flags, pe_flag_startup_probes)) { + crm_debug_2("Skipping active resource detection for %s", rsc->id); + return FALSE; } - - if(rsc->children) { - GListPtr gIter = NULL; - gboolean any_created = FALSE; - - for(gIter = rsc->children; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - any_created = child_rsc->cmds->create_probe( - child_rsc, node, complete, force, data_set) || any_created; - } - return any_created; + if (rsc->children) { + GListPtr gIter = NULL; + gboolean any_created = FALSE; + + for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + any_created = child_rsc->cmds->create_probe(child_rsc, node, complete, force, data_set) + || any_created; + } + + return any_created; } - if(is_set(rsc->flags, pe_rsc_orphan)) { - crm_debug_2("Skipping orphan: %s", rsc->id); - return FALSE; + if (is_set(rsc->flags, pe_rsc_orphan)) { + crm_debug_2("Skipping orphan: %s", rsc->id); + return FALSE; } running = g_hash_table_lookup(rsc->known_on, node->details->id); - if(running == NULL && is_set(rsc->flags, pe_rsc_unique) == FALSE) { - /* Anonymous clones */ - if(rsc->parent == top) { - running = g_hash_table_lookup(rsc->parent->known_on, node->details->id); - - } else { - /* Grouped anonymous clones need extra special handling */ - running = probe_grouped_clone(rsc, node, data_set); - } - } - - if(force == FALSE && running != NULL) { - /* we already know the status of the resource on this node */ - crm_debug_3("Skipping active: %s", rsc->id); - return FALSE; - } - + if (running == NULL && is_set(rsc->flags, pe_rsc_unique) == FALSE) { + /* Anonymous clones */ + if (rsc->parent == top) { + running = g_hash_table_lookup(rsc->parent->known_on, node->details->id); + + } else { + /* Grouped anonymous clones need extra special handling */ + running = probe_grouped_clone(rsc, node, data_set); + } + } + + if (force == FALSE && running != NULL) { + /* we already know the status of the resource on this node */ + crm_debug_3("Skipping active: %s", rsc->id); + return FALSE; + } + key = generate_op_key(rsc->id, RSC_STATUS, 0); probe = custom_action(rsc, key, RSC_STATUS, node, FALSE, TRUE, data_set); - update_action_flags(probe, pe_action_optional|pe_action_clear); + update_action_flags(probe, pe_action_optional | pe_action_clear); /* * We need to know if it's running_on (not just known_on) this node * to correctly determine the target rc. */ running = pe_find_node_id(rsc->running_on, node->details->id); - if(running == NULL) { - add_hash_param(probe->meta, XML_ATTR_TE_TARGET_RC, rc_inactive); + if (running == NULL) { + add_hash_param(probe->meta, XML_ATTR_TE_TARGET_RC, rc_inactive); - } else if(rsc->role == RSC_ROLE_MASTER) { - add_hash_param(probe->meta, XML_ATTR_TE_TARGET_RC, rc_master); + } else if (rsc->role == RSC_ROLE_MASTER) { + add_hash_param(probe->meta, XML_ATTR_TE_TARGET_RC, rc_master); } crm_debug("Probing %s on %s (%s)", rsc->id, node->details->uname, role2text(rsc->role)); order_actions(probe, complete, pe_order_implies_then); - + return TRUE; } static void -native_start_constraints( - resource_t *rsc, action_t *stonith_op, gboolean is_stonith, - pe_working_set_t *data_set) +native_start_constraints(resource_t * rsc, action_t * stonith_op, gboolean is_stonith, + pe_working_set_t * data_set) { - node_t *target = stonith_op?stonith_op->node:NULL; - - if(is_stonith) { - char *key = start_key(rsc); - action_t *ready = get_pseudo_op(STONITH_UP, data_set); - - crm_debug_2("Ordering %s action before stonith events", key); - custom_action_order( - rsc, key, NULL, - NULL, crm_strdup(ready->task), ready, - pe_order_optional|pe_order_implies_then, data_set); - + node_t *target = stonith_op ? stonith_op->node : NULL; + + if (is_stonith) { + char *key = start_key(rsc); + action_t *ready = get_pseudo_op(STONITH_UP, data_set); + + crm_debug_2("Ordering %s action before stonith events", key); + custom_action_order(rsc, key, NULL, + NULL, crm_strdup(ready->task), ready, + pe_order_optional | pe_order_implies_then, data_set); + } else { - GListPtr gIter = NULL; - action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set); - action_t *stonith_done = get_pseudo_op(STONITH_DONE, data_set); - for(gIter = rsc->actions; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - - if(action->needs == rsc_req_stonith) { - order_actions(stonith_done, action, pe_order_optional); - - } else if(target != NULL - && safe_str_eq(action->task, RSC_START) - && NULL == pe_hash_table_lookup(rsc->known_on, target->details->id)) { - /* if known == NULL, then we dont know if - * the resource is active on the node - * we're about to shoot - * - * in this case, regardless of action->needs, - * the only safe option is to wait until - * the node is shot before doing anything - * to with the resource - * - * its analogous to waiting for all the probes - * for rscX to complete before starting rscX - * - * the most likely explaination is that the - * DC died and took its status with it - */ - - crm_debug("Ordering %s after %s recovery", - action->uuid, target->details->uname); - order_actions(all_stopped, action, - pe_order_optional|pe_order_runnable_left); - } - } + GListPtr gIter = NULL; + action_t *all_stopped = get_pseudo_op(ALL_STOPPED, data_set); + action_t *stonith_done = get_pseudo_op(STONITH_DONE, data_set); + + for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + if (action->needs == rsc_req_stonith) { + order_actions(stonith_done, action, pe_order_optional); + + } else if (target != NULL && safe_str_eq(action->task, RSC_START) + && NULL == pe_hash_table_lookup(rsc->known_on, target->details->id)) { + /* if known == NULL, then we dont know if + * the resource is active on the node + * we're about to shoot + * + * in this case, regardless of action->needs, + * the only safe option is to wait until + * the node is shot before doing anything + * to with the resource + * + * its analogous to waiting for all the probes + * for rscX to complete before starting rscX + * + * the most likely explaination is that the + * DC died and took its status with it + */ + + crm_debug("Ordering %s after %s recovery", action->uuid, target->details->uname); + order_actions(all_stopped, action, pe_order_optional | pe_order_runnable_left); + } + } } } static void -native_stop_constraints( - resource_t *rsc, action_t *stonith_op, gboolean is_stonith, - pe_working_set_t *data_set) +native_stop_constraints(resource_t * rsc, action_t * stonith_op, gboolean is_stonith, + pe_working_set_t * data_set) { char *key = NULL; GListPtr gIter = NULL; GListPtr action_list = NULL; resource_t *top = uber_parent(rsc); - + key = stop_key(rsc); action_list = find_actions(rsc->actions, key, stonith_op->node); crm_free(key); /* add the stonith OP as a stop pre-req and the mark the stop * as a pseudo op - since its now redundant */ - - for(gIter = action_list; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - if(action->node->details->online - && action->node->details->unclean == FALSE - && is_set(rsc->flags, pe_rsc_failed)) { - continue; - } - - if(is_set(rsc->flags, pe_rsc_failed)) { - crm_warn("Stop of failed resource %s is" - " implicit after %s is fenced", - rsc->id, action->node->details->uname); - } else { - crm_info("%s is implicit after %s is fenced", - action->uuid, action->node->details->uname); - } - - /* the stop would never complete and is - * now implied by the stonith operation - */ - update_action_flags(action, pe_action_pseudo); - update_action_flags(action, pe_action_runnable); - update_action_flags(action, pe_action_implied_by_stonith); - - if(is_stonith == FALSE) { - action_t *parent_stop = find_first_action(top->actions, NULL, RSC_STOP, NULL); - - order_actions(stonith_op, action, pe_order_optional); - order_actions(stonith_op, parent_stop, pe_order_optional); - } - - if(is_set(rsc->flags, pe_rsc_notify)) { - /* Create a second notification that will be delivered - * immediately after the node is fenced - * - * Basic problem: - * - C is a clone active on the node to be shot and stopping on another - * - R is a resource that depends on C - * - * + C.stop depends on R.stop - * + C.stopped depends on STONITH - * + C.notify depends on C.stopped - * + C.healthy depends on C.notify - * + R.stop depends on C.healthy - * - * The extra notification here changes - * + C.healthy depends on C.notify - * into: - * + C.healthy depends on C.notify' - * + C.notify' depends on STONITH' - * thus breaking the loop - */ - notify_data_t *n_data = create_notification_boundaries(rsc, RSC_STOP, NULL, stonith_op, data_set); - crm_info("Creating secondary notification for %s", action->uuid); - - collect_notification_data(rsc, TRUE, FALSE, n_data); - g_hash_table_insert(n_data->keys, crm_strdup("notify_stop_resource"), crm_strdup(rsc->id)); - g_hash_table_insert(n_data->keys, crm_strdup("notify_stop_uname"), crm_strdup(action->node->details->uname)); - create_notifications(uber_parent(rsc), n_data, data_set); - free_notification_data(n_data); - } - + + for (gIter = action_list; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + if (action->node->details->online + && action->node->details->unclean == FALSE && is_set(rsc->flags, pe_rsc_failed)) { + continue; + } + + if (is_set(rsc->flags, pe_rsc_failed)) { + crm_warn("Stop of failed resource %s is" + " implicit after %s is fenced", rsc->id, action->node->details->uname); + } else { + crm_info("%s is implicit after %s is fenced", + action->uuid, action->node->details->uname); + } + + /* the stop would never complete and is + * now implied by the stonith operation + */ + update_action_flags(action, pe_action_pseudo); + update_action_flags(action, pe_action_runnable); + update_action_flags(action, pe_action_implied_by_stonith); + + if (is_stonith == FALSE) { + action_t *parent_stop = find_first_action(top->actions, NULL, RSC_STOP, NULL); + + order_actions(stonith_op, action, pe_order_optional); + order_actions(stonith_op, parent_stop, pe_order_optional); + } + + if (is_set(rsc->flags, pe_rsc_notify)) { + /* Create a second notification that will be delivered + * immediately after the node is fenced + * + * Basic problem: + * - C is a clone active on the node to be shot and stopping on another + * - R is a resource that depends on C + * + * + C.stop depends on R.stop + * + C.stopped depends on STONITH + * + C.notify depends on C.stopped + * + C.healthy depends on C.notify + * + R.stop depends on C.healthy + * + * The extra notification here changes + * + C.healthy depends on C.notify + * into: + * + C.healthy depends on C.notify' + * + C.notify' depends on STONITH' + * thus breaking the loop + */ + notify_data_t *n_data = + create_notification_boundaries(rsc, RSC_STOP, NULL, stonith_op, data_set); + crm_info("Creating secondary notification for %s", action->uuid); + + collect_notification_data(rsc, TRUE, FALSE, n_data); + g_hash_table_insert(n_data->keys, crm_strdup("notify_stop_resource"), + crm_strdup(rsc->id)); + g_hash_table_insert(n_data->keys, crm_strdup("notify_stop_uname"), + crm_strdup(action->node->details->uname)); + create_notifications(uber_parent(rsc), n_data, data_set); + free_notification_data(n_data); + } + /* From Bug #1601, successful fencing must be an input to a failed resources stop action. However given group(rA, rB) running on nodeX and B.stop has failed, A := stop healthy resource (rA.stop) B := stop failed resource (pseudo operation B.stop) C := stonith nodeX A requires B, B requires C, C requires A This loop would prevent the cluster from making progress. This block creates the "C requires A" dependency and therefore must (at least for now) be disabled. Instead, run the block above and treat all resources on nodeX as B would be (marked as a pseudo op depending on the STONITH). TODO: Break the "A requires B" dependency in update_action() and re-enable this block } else if(is_stonith == FALSE) { crm_info("Moving healthy resource %s" " off %s before fencing", rsc->id, node->details->uname); * stop healthy resources before the * stonith op * custom_action_order( rsc, stop_key(rsc), NULL, NULL,crm_strdup(CRM_OP_FENCE),stonith_op, pe_order_optional, data_set); */ } - + g_list_free(action_list); key = demote_key(rsc); action_list = find_actions(rsc->actions, key, stonith_op->node); crm_free(key); - - for(gIter = action_list; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - if(action->node->details->online == FALSE || action->node->details->unclean == TRUE - || is_set(rsc->flags, pe_rsc_failed)) { - if(is_set(rsc->flags, pe_rsc_failed)) { - crm_info("Demote of failed resource %s is" - " implict after %s is fenced", - rsc->id, action->node->details->uname); - } else { - crm_info("%s is implicit after %s is fenced", - action->uuid, action->node->details->uname); - } - /* the stop would never complete and is - * now implied by the stonith operation - */ - crm_trace("here - 1"); - update_action_flags(action, pe_action_pseudo); - update_action_flags(action, pe_action_runnable); - if(is_stonith == FALSE) { - order_actions(stonith_op, action, pe_order_optional); - } - } - } - + + for (gIter = action_list; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + if (action->node->details->online == FALSE || action->node->details->unclean == TRUE + || is_set(rsc->flags, pe_rsc_failed)) { + if (is_set(rsc->flags, pe_rsc_failed)) { + crm_info("Demote of failed resource %s is" + " implict after %s is fenced", rsc->id, action->node->details->uname); + } else { + crm_info("%s is implicit after %s is fenced", + action->uuid, action->node->details->uname); + } + /* the stop would never complete and is + * now implied by the stonith operation + */ + crm_trace("here - 1"); + update_action_flags(action, pe_action_pseudo); + update_action_flags(action, pe_action_runnable); + if (is_stonith == FALSE) { + order_actions(stonith_op, action, pe_order_optional); + } + } + } + g_list_free(action_list); } void -rsc_stonith_ordering( - resource_t *rsc, action_t *stonith_op, pe_working_set_t *data_set) +rsc_stonith_ordering(resource_t * rsc, action_t * stonith_op, pe_working_set_t * data_set) { gboolean is_stonith = FALSE; const char *class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS); - if(rsc->children) { - GListPtr gIter = NULL; - for(gIter = rsc->children; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - rsc_stonith_ordering(child_rsc, stonith_op, data_set); - } - return; + if (rsc->children) { + GListPtr gIter = NULL; + + for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + rsc_stonith_ordering(child_rsc, stonith_op, data_set); + } + return; + } + + if (is_not_set(rsc->flags, pe_rsc_managed)) { + crm_debug_3("Skipping fencing constraints for unmanaged resource: %s", rsc->id); + return; } - - if(is_not_set(rsc->flags, pe_rsc_managed)) { - crm_debug_3("Skipping fencing constraints for unmanaged resource: %s", rsc->id); - return; - } - if(stonith_op != NULL && safe_str_eq(class, "stonith")) { - is_stonith = TRUE; + if (stonith_op != NULL && safe_str_eq(class, "stonith")) { + is_stonith = TRUE; } - + /* Start constraints */ - native_start_constraints(rsc, stonith_op, is_stonith, data_set); - + native_start_constraints(rsc, stonith_op, is_stonith, data_set); + /* Stop constraints */ - native_stop_constraints(rsc, stonith_op, is_stonith, data_set); + native_stop_constraints(rsc, stonith_op, is_stonith, data_set); } -enum stack_activity -{ - stack_stable = 0, +enum stack_activity { + stack_stable = 0, stack_starting = 1, stack_stopping = 2, - stack_middle = 4, + stack_middle = 4, }; static enum stack_activity -find_clone_activity_on(resource_t *rsc, resource_t *target, node_t *node, const char *type) +find_clone_activity_on(resource_t * rsc, resource_t * target, node_t * node, const char *type) { int mode = stack_stable; action_t *active = NULL; - if(target->children) { - GListPtr gIter = NULL; - for(gIter = target->children; gIter != NULL; gIter = gIter->next) { - resource_t *child = (resource_t*)gIter->data; - mode |= find_clone_activity_on(rsc, child, node, type); - } - return mode; + if (target->children) { + GListPtr gIter = NULL; + + for (gIter = target->children; gIter != NULL; gIter = gIter->next) { + resource_t *child = (resource_t *) gIter->data; + + mode |= find_clone_activity_on(rsc, child, node, type); + } + return mode; } active = find_first_action(target->actions, NULL, RSC_START, NULL); - if(active && is_set(active->flags, pe_action_optional) == FALSE && is_set(active->flags, pe_action_pseudo) == FALSE) { - crm_debug("%s: found scheduled %s action (%s)", rsc->id, active->uuid, type); - mode |= stack_starting; + if (active && is_set(active->flags, pe_action_optional) == FALSE + && is_set(active->flags, pe_action_pseudo) == FALSE) { + crm_debug("%s: found scheduled %s action (%s)", rsc->id, active->uuid, type); + mode |= stack_starting; } active = find_first_action(target->actions, NULL, RSC_STOP, node); - if(active && is_set(active->flags, pe_action_optional) == FALSE && is_set(active->flags, pe_action_pseudo) == FALSE) { - crm_debug("%s: found scheduled %s action (%s)", rsc->id, active->uuid, type); - mode |= stack_stopping; + if (active && is_set(active->flags, pe_action_optional) == FALSE + && is_set(active->flags, pe_action_pseudo) == FALSE) { + crm_debug("%s: found scheduled %s action (%s)", rsc->id, active->uuid, type); + mode |= stack_stopping; } return mode; } static enum stack_activity -check_stack_element(resource_t *rsc, resource_t *other_rsc, const char *type) +check_stack_element(resource_t * rsc, resource_t * other_rsc, const char *type) { resource_t *other_p = uber_parent(other_rsc); - if(other_rsc == NULL || other_rsc == rsc) { - return stack_stable; - - } else if(other_p->variant == pe_native) { - crm_notice("Cannot migrate %s due to dependency on %s (%s)", - rsc->id, other_rsc->id, type); - return stack_middle; - - } else if(other_rsc == rsc->parent) { - int mode = 0; - GListPtr gIter = NULL; - for(gIter = other_rsc->rsc_cons; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - if(constraint->score > 0) { - mode |= check_stack_element(rsc, constraint->rsc_rh, type); - } - } - return mode; - - } else if(other_p->variant == pe_group) { - crm_notice("Cannot migrate %s due to dependency on group %s (%s)", - rsc->id, other_rsc->id, type); - return stack_middle; - - } /* else: >= clone */ - + + if (other_rsc == NULL || other_rsc == rsc) { + return stack_stable; + + } else if (other_p->variant == pe_native) { + crm_notice("Cannot migrate %s due to dependency on %s (%s)", rsc->id, other_rsc->id, type); + return stack_middle; + + } else if (other_rsc == rsc->parent) { + int mode = 0; + GListPtr gIter = NULL; + + for (gIter = other_rsc->rsc_cons; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + + if (constraint->score > 0) { + mode |= check_stack_element(rsc, constraint->rsc_rh, type); + } + } + return mode; + + } else if (other_p->variant == pe_group) { + crm_notice("Cannot migrate %s due to dependency on group %s (%s)", + rsc->id, other_rsc->id, type); + return stack_middle; + + } + + /* else: >= clone */ /* - - ## Assumption - A depends on clone(B) - - ## Resource Activity During Move - - N1 N2 N3 - --- --- --- - t0 A.stop - t1 B.stop B.stop - t2 B.start B.start - t3 A.start - - ## Resource Activity During Migration - - N1 N2 N3 - --- --- --- - t0 B.start B.start - t1 A.stop (1) - t2 A.start (2) - t3 B.stop B.stop - - Node 1: Rewritten to be a migrate-to operation - Node 2: Rewritten to be a migrate-from operation - - # Constraints - - The following constraints already exist in the system. - The 'ok' and 'fail' column refers to whether they still hold for migration. - - a) A.stop -> A.start - ok - b) B.stop -> B.start - fail - - c) A.stop -> B.stop - ok - d) B.start -> A.start - ok - - e) B.stop -> A.start - fail - f) A.stop -> B.start - fail - - ## Scenarios - B unchanged - ok - B stopping only - fail - possible after fixing 'e' - B starting only - fail - possible after fixing 'f' - B stoping and starting - fail - constraint 'b' is unfixable - B restarting only on N2 - fail - as-per previous only rarer - - */ - + + ## Assumption + A depends on clone(B) + + ## Resource Activity During Move + + N1 N2 N3 + --- --- --- + t0 A.stop + t1 B.stop B.stop + t2 B.start B.start + t3 A.start + + ## Resource Activity During Migration + + N1 N2 N3 + --- --- --- + t0 B.start B.start + t1 A.stop (1) + t2 A.start (2) + t3 B.stop B.stop + + Node 1: Rewritten to be a migrate-to operation + Node 2: Rewritten to be a migrate-from operation + + # Constraints + + The following constraints already exist in the system. + The 'ok' and 'fail' column refers to whether they still hold for migration. + + a) A.stop -> A.start - ok + b) B.stop -> B.start - fail + + c) A.stop -> B.stop - ok + d) B.start -> A.start - ok + + e) B.stop -> A.start - fail + f) A.stop -> B.start - fail + + ## Scenarios + B unchanged - ok + B stopping only - fail - possible after fixing 'e' + B starting only - fail - possible after fixing 'f' + B stoping and starting - fail - constraint 'b' is unfixable + B restarting only on N2 - fail - as-per previous only rarer + + */ /* Only allow migration when the clone is either stable, only starting or only stopping */ return find_clone_activity_on(rsc, other_rsc, NULL, type); } static gboolean -at_stack_bottom(resource_t *rsc) +at_stack_bottom(resource_t * rsc) { char *key = NULL; action_t *start = NULL; action_t *other = NULL; int mode = stack_stable; GListPtr action_list = NULL; GListPtr gIter = NULL; key = start_key(rsc); action_list = find_actions(rsc->actions, key, NULL); crm_free(key); - + crm_debug_3("%s: processing", rsc->id); CRM_CHECK(action_list != NULL, return FALSE); - + start = action_list->data; g_list_free(action_list); - for(gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - resource_t *target = constraint->rsc_rh; - crm_debug_4("Checking %s: %s == %s (%d)", constraint->id, rsc->id, target->id, constraint->score); - if(constraint->score > 0) { - mode |= check_stack_element(rsc, target, "coloc"); - if(mode & stack_middle) { - return FALSE; - - } else if((mode & stack_stopping) && (mode & stack_starting)) { - crm_notice("Cannot migrate %s due to colocation activity (last was %s)", - rsc->id, target->id); - return FALSE; - } - } - } - - for(gIter = start->actions_before; gIter != NULL; gIter = gIter->next) { - action_wrapper_t *other_w = (action_wrapper_t*)gIter->data; - - other = other_w->action; - - if(other_w->type & pe_order_serialize_only) { - crm_debug_3("%s: depends on %s (serialize ordering)", - rsc->id, other->uuid); - continue; - } - - crm_debug_2("%s: Checking %s ordering", rsc->id, other->uuid); - - if(is_set(other->flags, pe_action_optional) == FALSE) { - mode |= check_stack_element(rsc, other->rsc, "order"); - if(mode & stack_middle) { - return FALSE; - - } else if((mode & stack_stopping) && (mode & stack_starting)) { - crm_notice("Cannot migrate %s due to ordering activity (last was %s)", - rsc->id, other->rsc->id); - return FALSE; - } - } + for (gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + resource_t *target = constraint->rsc_rh; + + crm_debug_4("Checking %s: %s == %s (%d)", constraint->id, rsc->id, target->id, + constraint->score); + if (constraint->score > 0) { + mode |= check_stack_element(rsc, target, "coloc"); + if (mode & stack_middle) { + return FALSE; + + } else if ((mode & stack_stopping) && (mode & stack_starting)) { + crm_notice("Cannot migrate %s due to colocation activity (last was %s)", + rsc->id, target->id); + return FALSE; + } + } + } + + for (gIter = start->actions_before; gIter != NULL; gIter = gIter->next) { + action_wrapper_t *other_w = (action_wrapper_t *) gIter->data; + + other = other_w->action; + + if (other_w->type & pe_order_serialize_only) { + crm_debug_3("%s: depends on %s (serialize ordering)", rsc->id, other->uuid); + continue; + } + + crm_debug_2("%s: Checking %s ordering", rsc->id, other->uuid); + + if (is_set(other->flags, pe_action_optional) == FALSE) { + mode |= check_stack_element(rsc, other->rsc, "order"); + if (mode & stack_middle) { + return FALSE; + + } else if ((mode & stack_stopping) && (mode & stack_starting)) { + crm_notice("Cannot migrate %s due to ordering activity (last was %s)", + rsc->id, other->rsc->id); + return FALSE; + } + } } return TRUE; } void -rsc_migrate_reload(resource_t *rsc, pe_working_set_t *data_set) +rsc_migrate_reload(resource_t * rsc, pe_working_set_t * data_set) { char *key = NULL; GListPtr gIter = NULL; int level = LOG_DEBUG; GListPtr action_list = NULL; - + action_t *stop = NULL; action_t *start = NULL; action_t *other = NULL; action_t *action = NULL; const char *value = NULL; - if(rsc->children) { - for(gIter = rsc->children; gIter != NULL; gIter = gIter->next) { - resource_t *child_rsc = (resource_t*)gIter->data; - rsc_migrate_reload(child_rsc, data_set); - } - other = NULL; - return; - } else if(rsc->variant > pe_native) { - return; - } - - do_crm_log_unlikely(level+1, "Processing %s", rsc->id); - - if(is_not_set(rsc->flags, pe_rsc_managed) - || is_set(rsc->flags, pe_rsc_failed) - || is_set(rsc->flags, pe_rsc_start_pending) - || rsc->next_role < RSC_ROLE_STARTED - || g_list_length(rsc->running_on) != 1) { - do_crm_log_unlikely( - level+1, "%s: general resource state: flags=0x%.16llx", - rsc->id, rsc->flags); - return; + if (rsc->children) { + for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) { + resource_t *child_rsc = (resource_t *) gIter->data; + + rsc_migrate_reload(child_rsc, data_set); + } + other = NULL; + return; + } else if (rsc->variant > pe_native) { + return; + } + + do_crm_log_unlikely(level + 1, "Processing %s", rsc->id); + + if (is_not_set(rsc->flags, pe_rsc_managed) + || is_set(rsc->flags, pe_rsc_failed) + || is_set(rsc->flags, pe_rsc_start_pending) + || rsc->next_role < RSC_ROLE_STARTED || g_list_length(rsc->running_on) != 1) { + do_crm_log_unlikely(level + 1, "%s: general resource state: flags=0x%.16llx", + rsc->id, rsc->flags); + return; } value = g_hash_table_lookup(rsc->meta, XML_OP_ATTR_ALLOW_MIGRATE); - if(crm_is_true(value)) { - set_bit(rsc->flags, pe_rsc_can_migrate); - } + if (crm_is_true(value)) { + set_bit(rsc->flags, pe_rsc_can_migrate); + } - if(rsc->next_role > RSC_ROLE_SLAVE) { - clear_bit(rsc->flags, pe_rsc_can_migrate); - do_crm_log_unlikely( - level+1, "%s: resource role: role=%s", rsc->id, role2text(rsc->next_role)); + if (rsc->next_role > RSC_ROLE_SLAVE) { + clear_bit(rsc->flags, pe_rsc_can_migrate); + do_crm_log_unlikely(level + 1, "%s: resource role: role=%s", rsc->id, + role2text(rsc->next_role)); } - + key = start_key(rsc); action_list = find_actions(rsc->actions, key, NULL); crm_free(key); - - if(action_list == NULL || action_list->data == NULL) { - do_crm_log_unlikely(level, "%s: no start action", rsc->id); - return; + + if (action_list == NULL || action_list->data == NULL) { + do_crm_log_unlikely(level, "%s: no start action", rsc->id); + return; } - + start = action_list->data; g_list_free(action_list); - if(is_not_set(rsc->flags, pe_rsc_can_migrate) /* Coverity: False positive */ - && is_set(start->flags, pe_action_allow_reload_conversion) == FALSE) { - do_crm_log_unlikely(level+1, "%s: no need to continue", rsc->id); - return; + if (is_not_set(rsc->flags, pe_rsc_can_migrate) /* Coverity: False positive */ + &&is_set(start->flags, pe_action_allow_reload_conversion) == FALSE) { + do_crm_log_unlikely(level + 1, "%s: no need to continue", rsc->id); + return; } - + key = stop_key(rsc); action_list = find_actions(rsc->actions, key, NULL); crm_free(key); - - if(action_list == NULL || action_list->data == NULL) { - do_crm_log_unlikely(level, "%s: no stop action", rsc->id); - return; + + if (action_list == NULL || action_list->data == NULL) { + do_crm_log_unlikely(level, "%s: no stop action", rsc->id); + return; } - + stop = action_list->data; g_list_free(action_list); - + action = start; - if(action->node == NULL - || is_set(action->flags, pe_action_pseudo) - || is_set(action->flags, pe_action_optional) - || is_set(action->flags, pe_action_runnable) == FALSE) { - do_crm_log_unlikely(level, "%s: %s", rsc->id, action->task); - return; - } - + if (action->node == NULL || is_set(action->flags, pe_action_pseudo) + || is_set(action->flags, pe_action_optional) + || is_set(action->flags, pe_action_runnable) == FALSE) { + do_crm_log_unlikely(level, "%s: %s", rsc->id, action->task); + return; + } + action = stop; - if(action->node == NULL - || is_set(action->flags, pe_action_pseudo) - || is_set(action->flags, pe_action_optional) - || is_set(action->flags, pe_action_runnable) == FALSE) { - do_crm_log_unlikely(level, "%s: %s", rsc->id, action->task); - return; - } - - if(is_set(rsc->flags, pe_rsc_can_migrate)) { - if(start->node == NULL - || stop->node == NULL - || stop->node->details == start->node->details) { - clear_bit(rsc->flags, pe_rsc_can_migrate); - - } else if(at_stack_bottom(rsc) == FALSE) { - clear_bit(rsc->flags, pe_rsc_can_migrate); - } - } - - if(is_set(rsc->flags, pe_rsc_can_migrate) && start->node && stop->node) { - action_t *to = NULL; - action_t *from = NULL; - action_t *done = get_pseudo_op(STONITH_DONE, data_set); - - crm_info("Migrating %s from %s to %s", rsc->id, - stop->node?stop->node->details->uname:"unknown", - start->node?start->node->details->uname:"unknown"); - - /* Preserve the stop to ensure the end state is sane on that node, - * Make the start a pseudo op - * Create migrate_to, have it depend on everything the stop did - * Create migrate_from - * *-> migrate_to -> migrate_from -> stop -> start - */ - - update_action_flags(start, pe_action_pseudo); /* easier than trying to delete it from the graph - * but perhaps we should have it run anyway - */ - - to = custom_action(rsc, generate_op_key(rsc->id, RSC_MIGRATE, 0), RSC_MIGRATE, stop->node, FALSE, TRUE, data_set); - from = custom_action(rsc, generate_op_key(rsc->id, RSC_MIGRATED, 0), RSC_MIGRATED, start->node, FALSE, TRUE, data_set); - - /* This is slightly sub-optimal if 'to' fails, but always - * run both halves of the migration before terminating the - * transition. - * - * This can be removed if/when we update unpack_rsc_op() to - * 'correctly' handle partial migrations. - * - * Without this, we end up stopping both sides - */ - from->priority = INFINITY; - - order_actions(to, from, pe_order_optional); - order_actions(from, stop, pe_order_optional); - order_actions(done, to, pe_order_optional); - - add_hash_param(to->meta, XML_LRM_ATTR_MIGRATE_SOURCE, stop->node->details->uname); - add_hash_param(to->meta, XML_LRM_ATTR_MIGRATE_TARGET, start->node->details->uname); - - add_hash_param(from->meta, XML_LRM_ATTR_MIGRATE_SOURCE, stop->node->details->uname); - add_hash_param(from->meta, XML_LRM_ATTR_MIGRATE_TARGET, start->node->details->uname); - - /* Create the correct ordering ajustments based on find_clone_activity_on(); */ - - for(gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) { - rsc_colocation_t *constraint = (rsc_colocation_t*)gIter->data; - resource_t *target = constraint->rsc_rh; - crm_info("Repairing %s: %s == %s (%d)", constraint->id, rsc->id, target->id, constraint->score); - - if(constraint->score > 0) { - int mode = check_stack_element(rsc, target, "coloc"); - action_t *clone_stop = find_first_action(target->actions, NULL, RSC_STOP, NULL); - action_t *clone_start = find_first_action(target->actions, NULL, RSC_STARTED, NULL); - - CRM_ASSERT(clone_stop != NULL); - CRM_ASSERT(clone_start != NULL); - CRM_ASSERT((mode & stack_middle) == 0); - CRM_ASSERT(((mode & stack_stopping) && (mode & stack_starting)) == 0); - - if(mode & stack_stopping) { + if (action->node == NULL || is_set(action->flags, pe_action_pseudo) + || is_set(action->flags, pe_action_optional) + || is_set(action->flags, pe_action_runnable) == FALSE) { + do_crm_log_unlikely(level, "%s: %s", rsc->id, action->task); + return; + } + + if (is_set(rsc->flags, pe_rsc_can_migrate)) { + if (start->node == NULL + || stop->node == NULL || stop->node->details == start->node->details) { + clear_bit(rsc->flags, pe_rsc_can_migrate); + + } else if (at_stack_bottom(rsc) == FALSE) { + clear_bit(rsc->flags, pe_rsc_can_migrate); + } + } + + if (is_set(rsc->flags, pe_rsc_can_migrate) && start->node && stop->node) { + action_t *to = NULL; + action_t *from = NULL; + action_t *done = get_pseudo_op(STONITH_DONE, data_set); + + crm_info("Migrating %s from %s to %s", rsc->id, + stop->node ? stop->node->details->uname : "unknown", + start->node ? start->node->details->uname : "unknown"); + + /* Preserve the stop to ensure the end state is sane on that node, + * Make the start a pseudo op + * Create migrate_to, have it depend on everything the stop did + * Create migrate_from + * *-> migrate_to -> migrate_from -> stop -> start + */ + + update_action_flags(start, pe_action_pseudo); /* easier than trying to delete it from the graph + * but perhaps we should have it run anyway + */ + + to = custom_action(rsc, generate_op_key(rsc->id, RSC_MIGRATE, 0), RSC_MIGRATE, stop->node, + FALSE, TRUE, data_set); + from = + custom_action(rsc, generate_op_key(rsc->id, RSC_MIGRATED, 0), RSC_MIGRATED, start->node, + FALSE, TRUE, data_set); + + /* This is slightly sub-optimal if 'to' fails, but always + * run both halves of the migration before terminating the + * transition. + * + * This can be removed if/when we update unpack_rsc_op() to + * 'correctly' handle partial migrations. + * + * Without this, we end up stopping both sides + */ + from->priority = INFINITY; + + order_actions(to, from, pe_order_optional); + order_actions(from, stop, pe_order_optional); + order_actions(done, to, pe_order_optional); + + add_hash_param(to->meta, XML_LRM_ATTR_MIGRATE_SOURCE, stop->node->details->uname); + add_hash_param(to->meta, XML_LRM_ATTR_MIGRATE_TARGET, start->node->details->uname); + + add_hash_param(from->meta, XML_LRM_ATTR_MIGRATE_SOURCE, stop->node->details->uname); + add_hash_param(from->meta, XML_LRM_ATTR_MIGRATE_TARGET, start->node->details->uname); + + /* Create the correct ordering ajustments based on find_clone_activity_on(); */ + + for (gIter = rsc->rsc_cons; gIter != NULL; gIter = gIter->next) { + rsc_colocation_t *constraint = (rsc_colocation_t *) gIter->data; + resource_t *target = constraint->rsc_rh; + + crm_info("Repairing %s: %s == %s (%d)", constraint->id, rsc->id, target->id, + constraint->score); + + if (constraint->score > 0) { + int mode = check_stack_element(rsc, target, "coloc"); + action_t *clone_stop = find_first_action(target->actions, NULL, RSC_STOP, NULL); + action_t *clone_start = find_first_action(target->actions, NULL, RSC_STARTED, NULL); + + CRM_ASSERT(clone_stop != NULL); + CRM_ASSERT(clone_start != NULL); + CRM_ASSERT((mode & stack_middle) == 0); + CRM_ASSERT(((mode & stack_stopping) && (mode & stack_starting)) == 0); + + if (mode & stack_stopping) { #if 0 - crm_debug("Creating %s.start -> %s.stop ordering", rsc->id, target->id); - order_actions(from, clone_stop, pe_order_optional); + crm_debug("Creating %s.start -> %s.stop ordering", rsc->id, target->id); + order_actions(from, clone_stop, pe_order_optional); #endif - GListPtr lpc2 = NULL; - for(lpc2 = start->actions_before; lpc2 != NULL; lpc2 = lpc2->next) { - action_wrapper_t *other_w = (action_wrapper_t*)lpc2->data; - - /* Needed if the clone's started pseudo-action ever gets printed in the graph */ - if(other_w->action == clone_start) { - crm_debug("Breaking %s -> %s ordering", other_w->action->uuid, start->uuid); - other_w->type = pe_order_none; - } - } - - } else if(mode & stack_starting) { + GListPtr lpc2 = NULL; + + for (lpc2 = start->actions_before; lpc2 != NULL; lpc2 = lpc2->next) { + action_wrapper_t *other_w = (action_wrapper_t *) lpc2->data; + + /* Needed if the clone's started pseudo-action ever gets printed in the graph */ + if (other_w->action == clone_start) { + crm_debug("Breaking %s -> %s ordering", other_w->action->uuid, + start->uuid); + other_w->type = pe_order_none; + } + } + + } else if (mode & stack_starting) { #if 0 - crm_debug("Creating %s.started -> %s.stop ordering", target->id, rsc->id); - order_actions(clone_start, to, pe_order_optional); -#endif - GListPtr lpc2 = NULL; - for(lpc2 = clone_stop->actions_before; lpc2 != NULL; lpc2 = lpc2->next) { - action_wrapper_t *other_w = (action_wrapper_t*)lpc2->data; - - /* Needed if the clone's stop pseudo-action ever gets printed in the graph */ - if(other_w->action == stop) { - crm_debug("Breaking %s -> %s ordering", other_w->action->uuid, clone_stop->uuid); - other_w->type = pe_order_none; - } - } - } - } - } + crm_debug("Creating %s.started -> %s.stop ordering", target->id, rsc->id); + order_actions(clone_start, to, pe_order_optional); +#endif + GListPtr lpc2 = NULL; + + for (lpc2 = clone_stop->actions_before; lpc2 != NULL; lpc2 = lpc2->next) { + action_wrapper_t *other_w = (action_wrapper_t *) lpc2->data; + + /* Needed if the clone's stop pseudo-action ever gets printed in the graph */ + if (other_w->action == stop) { + crm_debug("Breaking %s -> %s ordering", other_w->action->uuid, + clone_stop->uuid); + other_w->type = pe_order_none; + } + } + } + } + } #if 0 - /* Implied now that start/stop are not morphed into migrate ops */ - - /* Anything that needed stop to complete, now also needs start to have completed */ - for(gIter = stop->actions_after; gIter != NULL; gIter = gIter->next) { - action_wrapper_t *other_w = (action_wrapper_t*)gIter->data; - other = other_w->action; - if(is_set(other->flags, pe_action_optional) || other->rsc != NULL) { - continue; - } - crm_debug("Ordering %s before %s (stop)", from->uuid, other->uuid); - order_actions(from, other, other_w->type); - } + /* Implied now that start/stop are not morphed into migrate ops */ + + /* Anything that needed stop to complete, now also needs start to have completed */ + for (gIter = stop->actions_after; gIter != NULL; gIter = gIter->next) { + action_wrapper_t *other_w = (action_wrapper_t *) gIter->data; + + other = other_w->action; + if (is_set(other->flags, pe_action_optional) || other->rsc != NULL) { + continue; + } + crm_debug("Ordering %s before %s (stop)", from->uuid, other->uuid); + order_actions(from, other, other_w->type); + } #endif - /* migrate_to also needs anything that the stop needed to have completed too */ - for(gIter = stop->actions_before; gIter != NULL; gIter = gIter->next) { - action_wrapper_t *other_w = (action_wrapper_t*)gIter->data; - - other = other_w->action; - if(other->rsc == NULL) { - /* nothing */ - - } else if(is_set(other->flags, pe_action_optional) || other->rsc == rsc || other->rsc == rsc->parent) { - continue; - } - crm_debug("Ordering %s before %s (stop)", other_w->action->uuid, stop->uuid); - order_actions(other, to, other_w->type); - } - - /* migrate_to also needs anything that the start needed to have completed too */ - for(gIter = start->actions_before; gIter != NULL; gIter = gIter->next) { - action_wrapper_t *other_w = (action_wrapper_t*)gIter->data; - - other = other_w->action; - if(other->rsc == NULL) { - /* nothing */ - } else if(is_set(other->flags, pe_action_optional) || other->rsc == rsc || other->rsc == rsc->parent) { - continue; - } - crm_debug("Ordering %s before %s (start)", other_w->action->uuid, stop->uuid); - order_actions(other, to, other_w->type); - } - - } else if(start->node - && stop->node - && is_set(start->flags, pe_action_allow_reload_conversion) - && stop->node->details == start->node->details) { - action_t *rewrite = NULL; - - update_action_flags(start, pe_action_pseudo); /* easier than trying to delete it from the graph */ - - action = NULL; - key = promote_key(rsc); - action_list = find_actions(rsc->actions, key, NULL); - if(action_list) { - action = action_list->data; - } - if(action && is_set(action->flags, pe_action_optional) == FALSE) { - update_action_flags(action, pe_action_pseudo); - } - g_list_free(action_list); - crm_free(key); - - action = NULL; - key = demote_key(rsc); - action_list = find_actions(rsc->actions, key, NULL); - if(action_list) { - action = action_list->data; - } - g_list_free(action_list); - crm_free(key); - - if(action && is_set(action->flags, pe_action_optional) == FALSE) { - rewrite = action; - update_action_flags(stop, pe_action_pseudo); - - } else { - rewrite = stop; - } - crm_info("Rewriting %s of %s on %s as a reload", - rewrite->task, rsc->id, stop->node->details->uname); - - crm_free(rewrite->uuid); - crm_free(rewrite->task); - rewrite->task = crm_strdup("reload"); - rewrite->uuid = generate_op_key(rsc->id, rewrite->task, 0); - + /* migrate_to also needs anything that the stop needed to have completed too */ + for (gIter = stop->actions_before; gIter != NULL; gIter = gIter->next) { + action_wrapper_t *other_w = (action_wrapper_t *) gIter->data; + + other = other_w->action; + if (other->rsc == NULL) { + /* nothing */ + + } else if (is_set(other->flags, pe_action_optional) || other->rsc == rsc + || other->rsc == rsc->parent) { + continue; + } + crm_debug("Ordering %s before %s (stop)", other_w->action->uuid, stop->uuid); + order_actions(other, to, other_w->type); + } + + /* migrate_to also needs anything that the start needed to have completed too */ + for (gIter = start->actions_before; gIter != NULL; gIter = gIter->next) { + action_wrapper_t *other_w = (action_wrapper_t *) gIter->data; + + other = other_w->action; + if (other->rsc == NULL) { + /* nothing */ + } else if (is_set(other->flags, pe_action_optional) || other->rsc == rsc + || other->rsc == rsc->parent) { + continue; + } + crm_debug("Ordering %s before %s (start)", other_w->action->uuid, stop->uuid); + order_actions(other, to, other_w->type); + } + + } else if (start->node && stop->node && is_set(start->flags, pe_action_allow_reload_conversion) + && stop->node->details == start->node->details) { + action_t *rewrite = NULL; + + update_action_flags(start, pe_action_pseudo); /* easier than trying to delete it from the graph */ + + action = NULL; + key = promote_key(rsc); + action_list = find_actions(rsc->actions, key, NULL); + if (action_list) { + action = action_list->data; + } + if (action && is_set(action->flags, pe_action_optional) == FALSE) { + update_action_flags(action, pe_action_pseudo); + } + g_list_free(action_list); + crm_free(key); + + action = NULL; + key = demote_key(rsc); + action_list = find_actions(rsc->actions, key, NULL); + if (action_list) { + action = action_list->data; + } + g_list_free(action_list); + crm_free(key); + + if (action && is_set(action->flags, pe_action_optional) == FALSE) { + rewrite = action; + update_action_flags(stop, pe_action_pseudo); + + } else { + rewrite = stop; + } + crm_info("Rewriting %s of %s on %s as a reload", + rewrite->task, rsc->id, stop->node->details->uname); + + crm_free(rewrite->uuid); + crm_free(rewrite->task); + rewrite->task = crm_strdup("reload"); + rewrite->uuid = generate_op_key(rsc->id, rewrite->task, 0); + } else { - do_crm_log_unlikely(level+1, "%s nothing to do", rsc->id); + do_crm_log_unlikely(level + 1, "%s nothing to do", rsc->id); } } -void native_append_meta(resource_t *rsc, xmlNode *xml) +void +native_append_meta(resource_t * rsc, xmlNode * xml) { char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_INCARNATION); - if(value) { - char *name = NULL; - name = crm_meta_name(XML_RSC_ATTR_INCARNATION); - crm_xml_add(xml, name, value); - crm_free(name); + + if (value) { + char *name = NULL; + + name = crm_meta_name(XML_RSC_ATTR_INCARNATION); + crm_xml_add(xml, name, value); + crm_free(name); } } - diff --git a/pengine/pengine.c b/pengine/pengine.c index 6230a24067..93a9219cf7 100644 --- a/pengine/pengine.c +++ b/pengine/pengine.c @@ -1,313 +1,308 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include -xmlNode * do_calculations( - pe_working_set_t *data_set, xmlNode *xml_input, ha_time_t *now); +xmlNode *do_calculations(pe_working_set_t * data_set, xmlNode * xml_input, ha_time_t * now); gboolean show_scores = FALSE; int scores_log_level = LOG_DEBUG_2; gboolean show_utilization = FALSE; int utilization_log_level = LOG_DEBUG_2; extern int transition_id; #define get_series() was_processing_error?1:was_processing_warning?2:3 -typedef struct series_s -{ - int id; - const char *name; - const char *param; - int wrap; +typedef struct series_s { + int id; + const char *name; + const char *param; + int wrap; } series_t; series_t series[] = { - { 0, "pe-unknown", "_dont_match_anything_", -1 }, - { 0, "pe-error", "pe-error-series-max", -1 }, - { 0, "pe-warn", "pe-warn-series-max", 200 }, - { 0, "pe-input", "pe-input-series-max", 400 }, + {0, "pe-unknown", "_dont_match_anything_", -1}, + {0, "pe-error", "pe-error-series-max", -1}, + {0, "pe-warn", "pe-warn-series-max", 200}, + {0, "pe-input", "pe-input-series-max", 400}, }; gboolean -process_pe_message(xmlNode *msg, xmlNode *xml_data, IPC_Channel *sender) +process_pe_message(xmlNode * msg, xmlNode * xml_data, IPC_Channel * sender) { - static char *filename = NULL; - static char *last_digest = NULL; - - gboolean send_via_disk = FALSE; - const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO); - const char *op = crm_element_value(msg, F_CRM_TASK); - const char *ref = crm_element_value(msg, XML_ATTR_REFERENCE); - - crm_debug_3("Processing %s op (ref=%s)...", op, ref); - - if(op == NULL){ - /* error */ - - } else if(strcasecmp(op, CRM_OP_HELLO) == 0) { - /* ignore */ - - } else if(safe_str_eq(crm_element_value(msg, F_CRM_MSG_TYPE), - XML_ATTR_RESPONSE)) { - /* ignore */ - - } else if(sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_PENGINE) != 0) { - crm_debug_3("Bad sys-to %s", crm_str(sys_to)); - return FALSE; - - } else if(strcasecmp(op, CRM_OP_PECALC) == 0) { - int seq = -1; - int series_id = 0; - int series_wrap = 0; - char *digest = NULL; - char *graph_file = NULL; - const char *value = NULL; - pe_working_set_t data_set; - xmlNode *converted = NULL; - xmlNode *reply = NULL; - gboolean is_repoke = FALSE; - gboolean process = TRUE; + static char *filename = NULL; + static char *last_digest = NULL; + + gboolean send_via_disk = FALSE; + const char *sys_to = crm_element_value(msg, F_CRM_SYS_TO); + const char *op = crm_element_value(msg, F_CRM_TASK); + const char *ref = crm_element_value(msg, XML_ATTR_REFERENCE); + + crm_debug_3("Processing %s op (ref=%s)...", op, ref); + + if (op == NULL) { + /* error */ + + } else if (strcasecmp(op, CRM_OP_HELLO) == 0) { + /* ignore */ + + } else if (safe_str_eq(crm_element_value(msg, F_CRM_MSG_TYPE), XML_ATTR_RESPONSE)) { + /* ignore */ + + } else if (sys_to == NULL || strcasecmp(sys_to, CRM_SYSTEM_PENGINE) != 0) { + crm_debug_3("Bad sys-to %s", crm_str(sys_to)); + return FALSE; + + } else if (strcasecmp(op, CRM_OP_PECALC) == 0) { + int seq = -1; + int series_id = 0; + int series_wrap = 0; + char *digest = NULL; + char *graph_file = NULL; + const char *value = NULL; + pe_working_set_t data_set; + xmlNode *converted = NULL; + xmlNode *reply = NULL; + gboolean is_repoke = FALSE; + gboolean process = TRUE; + #if HAVE_BZLIB_H - gboolean compress = TRUE; + gboolean compress = TRUE; #else - gboolean compress = FALSE; + gboolean compress = FALSE; #endif - crm_config_error = FALSE; - crm_config_warning = FALSE; - - was_processing_error = FALSE; - was_processing_warning = FALSE; - - graph_file = crm_strdup(CRM_STATE_DIR"/graph.XXXXXX"); - graph_file = mktemp(graph_file); - - set_working_set_defaults(&data_set); - - digest = calculate_xml_versioned_digest(xml_data, FALSE, FALSE, CRM_FEATURE_SET); - converted = copy_xml(xml_data); - if(cli_config_update(&converted, NULL, TRUE) == FALSE) { - data_set.graph = create_xml_node(NULL, XML_TAG_GRAPH); - crm_xml_add_int(data_set.graph, "transition_id", 0); - crm_xml_add_int(data_set.graph, "cluster-delay", 0); - process = FALSE; - - } else if(safe_str_eq(digest, last_digest)) { - crm_trace("Input has not changed since last time, not saving to disk"); - is_repoke = TRUE; - - } else { - crm_free(last_digest); - last_digest = digest; - } - - if(process) { - do_calculations(&data_set, converted, NULL); - } - - series_id = get_series(); - series_wrap = series[series_id].wrap; - value = pe_pref(data_set.config_hash, series[series_id].param); - - if(value != NULL) { - series_wrap = crm_int_helper(value, NULL); - if(errno != 0) { - series_wrap = series[series_id].wrap; - } - - } else { - crm_config_warn("No value specified for cluster" - " preference: %s", - series[series_id].param); - } - - seq = get_last_sequence(PE_STATE_DIR, series[series_id].name); - - data_set.input = NULL; - reply = create_reply(msg, data_set.graph); - CRM_ASSERT(reply != NULL); - - if(is_repoke == FALSE) { - crm_free(filename); - filename = generate_series_filename( - PE_STATE_DIR, series[series_id].name, seq, compress); - } - - crm_xml_add(reply, F_CRM_TGRAPH_INPUT, filename); - crm_xml_add_int(reply, "graph-errors", was_processing_error); - crm_xml_add_int(reply, "graph-warnings", was_processing_warning); - crm_xml_add_int(reply, "config-errors", crm_config_error); - crm_xml_add_int(reply, "config-warnings", crm_config_warning); - - if(send_ipc_message(sender, reply) == FALSE) { - if(sender && sender->ops->get_chan_status(sender) == IPC_CONNECT) { - send_via_disk = TRUE; - crm_err("Answer could not be sent via IPC, send via the disk instead"); - crm_notice("Writing the TE graph to %s", graph_file); - if(write_xml_file(data_set.graph, graph_file, FALSE) < 0) { - crm_err("TE graph could not be written to disk"); - } - } else { - crm_info("Peer disconnected, discarding transition graph"); - } - } - - free_xml(reply); - cleanup_alloc_calculations(&data_set); - - if(is_repoke == FALSE && series_wrap != 0) { - write_xml_file(xml_data, filename, compress); - write_last_sequence( - PE_STATE_DIR, series[series_id].name, seq+1, series_wrap); - } - - if(was_processing_error) { - crm_err("Transition %d:" - " ERRORs found during PE processing." - " PEngine Input stored in: %s", - transition_id, filename); - - } else if(was_processing_warning) { - crm_warn("Transition %d:" - " WARNINGs found during PE processing." - " PEngine Input stored in: %s", - transition_id, filename); - - } else { - crm_notice("Transition %d: PEngine Input stored in: %s", - transition_id, filename); - } - - if(crm_config_error) { - crm_notice("Configuration ERRORs found during PE processing." - " Please run \"crm_verify -L\" to identify issues."); - - } else if(crm_config_warning) { - crm_notice("Configuration WARNINGs found during PE processing." - " Please run \"crm_verify -L\" to identify issues."); - } - - if(send_via_disk) { - reply = create_reply(msg, NULL); - crm_xml_add(reply, F_CRM_TGRAPH, graph_file); - crm_xml_add(reply, F_CRM_TGRAPH_INPUT, filename); - CRM_ASSERT(reply != NULL); - if(send_ipc_message(sender, reply) == FALSE) { - crm_err("Answer could not be sent"); - } - free_xml(reply); - } - - free_xml(converted); - crm_free(graph_file); - - } else if(strcasecmp(op, CRM_OP_QUIT) == 0) { - crm_warn("Received quit message, terminating"); - exit(0); - } - - return TRUE; + crm_config_error = FALSE; + crm_config_warning = FALSE; + + was_processing_error = FALSE; + was_processing_warning = FALSE; + + graph_file = crm_strdup(CRM_STATE_DIR "/graph.XXXXXX"); + graph_file = mktemp(graph_file); + + set_working_set_defaults(&data_set); + + digest = calculate_xml_versioned_digest(xml_data, FALSE, FALSE, CRM_FEATURE_SET); + converted = copy_xml(xml_data); + if (cli_config_update(&converted, NULL, TRUE) == FALSE) { + data_set.graph = create_xml_node(NULL, XML_TAG_GRAPH); + crm_xml_add_int(data_set.graph, "transition_id", 0); + crm_xml_add_int(data_set.graph, "cluster-delay", 0); + process = FALSE; + + } else if (safe_str_eq(digest, last_digest)) { + crm_trace("Input has not changed since last time, not saving to disk"); + is_repoke = TRUE; + + } else { + crm_free(last_digest); + last_digest = digest; + } + + if (process) { + do_calculations(&data_set, converted, NULL); + } + + series_id = get_series(); + series_wrap = series[series_id].wrap; + value = pe_pref(data_set.config_hash, series[series_id].param); + + if (value != NULL) { + series_wrap = crm_int_helper(value, NULL); + if (errno != 0) { + series_wrap = series[series_id].wrap; + } + + } else { + crm_config_warn("No value specified for cluster" + " preference: %s", series[series_id].param); + } + + seq = get_last_sequence(PE_STATE_DIR, series[series_id].name); + + data_set.input = NULL; + reply = create_reply(msg, data_set.graph); + CRM_ASSERT(reply != NULL); + + if (is_repoke == FALSE) { + crm_free(filename); + filename = + generate_series_filename(PE_STATE_DIR, series[series_id].name, seq, compress); + } + + crm_xml_add(reply, F_CRM_TGRAPH_INPUT, filename); + crm_xml_add_int(reply, "graph-errors", was_processing_error); + crm_xml_add_int(reply, "graph-warnings", was_processing_warning); + crm_xml_add_int(reply, "config-errors", crm_config_error); + crm_xml_add_int(reply, "config-warnings", crm_config_warning); + + if (send_ipc_message(sender, reply) == FALSE) { + if (sender && sender->ops->get_chan_status(sender) == IPC_CONNECT) { + send_via_disk = TRUE; + crm_err("Answer could not be sent via IPC, send via the disk instead"); + crm_notice("Writing the TE graph to %s", graph_file); + if (write_xml_file(data_set.graph, graph_file, FALSE) < 0) { + crm_err("TE graph could not be written to disk"); + } + } else { + crm_info("Peer disconnected, discarding transition graph"); + } + } + + free_xml(reply); + cleanup_alloc_calculations(&data_set); + + if (is_repoke == FALSE && series_wrap != 0) { + write_xml_file(xml_data, filename, compress); + write_last_sequence(PE_STATE_DIR, series[series_id].name, seq + 1, series_wrap); + } + + if (was_processing_error) { + crm_err("Transition %d:" + " ERRORs found during PE processing." + " PEngine Input stored in: %s", transition_id, filename); + + } else if (was_processing_warning) { + crm_warn("Transition %d:" + " WARNINGs found during PE processing." + " PEngine Input stored in: %s", transition_id, filename); + + } else { + crm_notice("Transition %d: PEngine Input stored in: %s", transition_id, filename); + } + + if (crm_config_error) { + crm_notice("Configuration ERRORs found during PE processing." + " Please run \"crm_verify -L\" to identify issues."); + + } else if (crm_config_warning) { + crm_notice("Configuration WARNINGs found during PE processing." + " Please run \"crm_verify -L\" to identify issues."); + } + + if (send_via_disk) { + reply = create_reply(msg, NULL); + crm_xml_add(reply, F_CRM_TGRAPH, graph_file); + crm_xml_add(reply, F_CRM_TGRAPH_INPUT, filename); + CRM_ASSERT(reply != NULL); + if (send_ipc_message(sender, reply) == FALSE) { + crm_err("Answer could not be sent"); + } + free_xml(reply); + } + + free_xml(converted); + crm_free(graph_file); + + } else if (strcasecmp(op, CRM_OP_QUIT) == 0) { + crm_warn("Received quit message, terminating"); + exit(0); + } + + return TRUE; } xmlNode * -do_calculations(pe_working_set_t *data_set, xmlNode *xml_input, ha_time_t *now) +do_calculations(pe_working_set_t * data_set, xmlNode * xml_input, ha_time_t * now) { - GListPtr gIter = NULL; - int rsc_log_level = LOG_INFO; + GListPtr gIter = NULL; + int rsc_log_level = LOG_INFO; + /* pe_debug_on(); */ - CRM_ASSERT(xml_input || is_set(data_set->flags, pe_flag_have_status)); - - if(is_set(data_set->flags, pe_flag_have_status) == FALSE) { - set_working_set_defaults(data_set); - data_set->input = xml_input; - data_set->now = now; - if(data_set->now == NULL) { - data_set->now = new_ha_date(TRUE); - } - } else { - crm_trace("Already have status - reusing"); - } - - crm_debug_5("Calculate cluster status"); - stage0(data_set); - - gIter = data_set->resources; - for(; gIter != NULL; gIter = gIter->next) { - resource_t *rsc = (resource_t*)gIter->data; - - if(is_set(rsc->flags, pe_rsc_orphan) && rsc->role == RSC_ROLE_STOPPED) { - continue; - } - rsc->fns->print(rsc, NULL, pe_print_log, &rsc_log_level); - } - - crm_trace("Applying placement constraints"); - stage2(data_set); - - crm_trace("Create internal constraints"); - stage3(data_set); - - crm_trace("Check actions"); - stage4(data_set); - - crm_trace("Allocate resources"); - stage5(data_set); - - crm_trace("Processing fencing and shutdown cases"); - stage6(data_set); - - crm_trace("Applying ordering constraints"); - stage7(data_set); - - crm_trace("Create transition graph"); - stage8(data_set); - - crm_trace("=#=#=#=#= Summary =#=#=#=#="); - crm_trace("\t========= Set %d (Un-runnable) =========", -1); - if(crm_log_level > LOG_DEBUG) { - gIter = data_set->actions; - for(; gIter != NULL; gIter = gIter->next) { - action_t *action = (action_t*)gIter->data; - if(is_set(action->flags, pe_action_optional) == FALSE - && is_set(action->flags, pe_action_runnable) == FALSE - && is_set(action->flags, pe_action_pseudo) == FALSE) { - log_action(LOG_DEBUG_2, "\t", action, TRUE); - } - } - } - - return data_set->graph; + CRM_ASSERT(xml_input || is_set(data_set->flags, pe_flag_have_status)); + + if (is_set(data_set->flags, pe_flag_have_status) == FALSE) { + set_working_set_defaults(data_set); + data_set->input = xml_input; + data_set->now = now; + if (data_set->now == NULL) { + data_set->now = new_ha_date(TRUE); + } + } else { + crm_trace("Already have status - reusing"); + } + + crm_debug_5("Calculate cluster status"); + stage0(data_set); + + gIter = data_set->resources; + for (; gIter != NULL; gIter = gIter->next) { + resource_t *rsc = (resource_t *) gIter->data; + + if (is_set(rsc->flags, pe_rsc_orphan) && rsc->role == RSC_ROLE_STOPPED) { + continue; + } + rsc->fns->print(rsc, NULL, pe_print_log, &rsc_log_level); + } + + crm_trace("Applying placement constraints"); + stage2(data_set); + + crm_trace("Create internal constraints"); + stage3(data_set); + + crm_trace("Check actions"); + stage4(data_set); + + crm_trace("Allocate resources"); + stage5(data_set); + + crm_trace("Processing fencing and shutdown cases"); + stage6(data_set); + + crm_trace("Applying ordering constraints"); + stage7(data_set); + + crm_trace("Create transition graph"); + stage8(data_set); + + crm_trace("=#=#=#=#= Summary =#=#=#=#="); + crm_trace("\t========= Set %d (Un-runnable) =========", -1); + if (crm_log_level > LOG_DEBUG) { + gIter = data_set->actions; + for (; gIter != NULL; gIter = gIter->next) { + action_t *action = (action_t *) gIter->data; + + if (is_set(action->flags, pe_action_optional) == FALSE + && is_set(action->flags, pe_action_runnable) == FALSE + && is_set(action->flags, pe_action_pseudo) == FALSE) { + log_action(LOG_DEBUG_2, "\t", action, TRUE); + } + } + } + + return data_set->graph; } diff --git a/pengine/ptest.c b/pengine/ptest.c index 37d5cfcc52..296d9b0cc4 100644 --- a/pengine/ptest.c +++ b/pengine/ptest.c @@ -1,499 +1,507 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_LIBXML2 # include #endif gboolean use_stdin = FALSE; gboolean do_simulation = FALSE; gboolean inhibit_exit = FALSE; gboolean all_actions = FALSE; -extern xmlNode * do_calculations( - pe_working_set_t *data_set, xmlNode *xml_input, ha_time_t *now); -extern void cleanup_calculations(pe_working_set_t *data_set); +extern xmlNode *do_calculations(pe_working_set_t * data_set, xmlNode * xml_input, ha_time_t * now); +extern void cleanup_calculations(pe_working_set_t * data_set); char *use_date = NULL; FILE *dot_strm = NULL; + #define DOT_PREFIX "PE_DOT: " /* #define DOT_PREFIX "" */ #define dot_write(fmt...) if(dot_strm != NULL) { \ fprintf(dot_strm, fmt); \ fprintf(dot_strm, "\n"); \ } else { \ crm_debug(DOT_PREFIX""fmt); \ } static void init_dotfile(void) { dot_write(" digraph \"g\" {"); /* dot_write(" size = \"30,30\""); */ /* dot_write(" graph ["); */ /* dot_write(" fontsize = \"12\""); */ /* dot_write(" fontname = \"Times-Roman\""); */ /* dot_write(" fontcolor = \"black\""); */ /* dot_write(" bb = \"0,0,398.922306,478.927856\""); */ /* dot_write(" color = \"black\""); */ /* dot_write(" ]"); */ /* dot_write(" node ["); */ /* dot_write(" fontsize = \"12\""); */ /* dot_write(" fontname = \"Times-Roman\""); */ /* dot_write(" fontcolor = \"black\""); */ /* dot_write(" shape = \"ellipse\""); */ /* dot_write(" color = \"black\""); */ /* dot_write(" ]"); */ /* dot_write(" edge ["); */ /* dot_write(" fontsize = \"12\""); */ /* dot_write(" fontname = \"Times-Roman\""); */ /* dot_write(" fontcolor = \"black\""); */ /* dot_write(" color = \"black\""); */ /* dot_write(" ]"); */ } static char * -create_action_name(action_t *action) +create_action_name(action_t * action) { char *action_name = NULL; const char *action_host = NULL; - if(action->node) { - action_host = action->node->details->uname; - action_name = crm_concat(action->uuid, action_host, ' '); - } else if(is_set(action->flags, pe_action_pseudo)) { - action_name = crm_strdup(action->uuid); - + if (action->node) { + action_host = action->node->details->uname; + action_name = crm_concat(action->uuid, action_host, ' '); + + } else if (is_set(action->flags, pe_action_pseudo)) { + action_name = crm_strdup(action->uuid); + } else { - action_host = ""; - action_name = crm_concat(action->uuid, action_host, ' '); + action_host = ""; + action_name = crm_concat(action->uuid, action_host, ' '); } - if(safe_str_eq(action->task, RSC_CANCEL)) { - char *tmp_action_name = action_name; - action_name = crm_concat("Cancel", tmp_action_name, ' '); - crm_free(tmp_action_name); + if (safe_str_eq(action->task, RSC_CANCEL)) { + char *tmp_action_name = action_name; + + action_name = crm_concat("Cancel", tmp_action_name, ' '); + crm_free(tmp_action_name); } - + return action_name; } gboolean USE_LIVE_CIB = FALSE; /* *INDENT-OFF* */ static struct crm_option long_options[] = { /* Top-level Options */ {"help", 0, 0, '?', "This text"}, {"version", 0, 0, '$', "Version information" }, {"verbose", 0, 0, 'V', "Increase debug output\n"}, {"simulate", 0, 0, 'S', "Simulate the transition's execution to find invalid graphs\n"}, {"show-scores", 0, 0, 's', "Display resource allocation scores"}, {"show-utilization", 0, 0, 'U', "Display utilization information"}, {"all-actions", 0, 0, 'a', "Display all possible actions - even ones not part of the transition graph"}, {"live-check", 0, 0, 'L', "Connect to the CIB and use the current contents as input"}, {"xml-text", 1, 0, 'X', "Retrieve XML from the supplied string"}, {"xml-file", 1, 0, 'x', "Retrieve XML from the named file"}, /* {"xml-pipe", 0, 0, 'p', "Retrieve XML from stdin\n"}, */ {"save-input", 1, 0, 'I', "\tSave the input to the named file"}, {"save-graph", 1, 0, 'G', "\tSave the transition graph (XML format) to the named file"}, {"save-dotfile",1, 0, 'D', "Save the transition graph (DOT format) to the named file\n"}, {0, 0, 0, 0} }; /* *INDENT-ON* */ int main(int argc, char **argv) { GListPtr lpc = NULL; gboolean process = TRUE; gboolean all_good = TRUE; enum transition_status graph_rc = -1; crm_graph_t *transition = NULL; ha_time_t *a_date = NULL; - cib_t * cib_conn = NULL; - - xmlNode * cib_object = NULL; + cib_t *cib_conn = NULL; + + xmlNode *cib_object = NULL; int argerr = 0; int flag; - + char *msg_buffer = NULL; gboolean optional = FALSE; pe_working_set_t data_set; - + const char *source = NULL; const char *xml_file = NULL; const char *dot_file = NULL; const char *graph_file = NULL; const char *input_file = NULL; - /* disable glib's fancy allocators that can't be free'd */ + /* disable glib's fancy allocators that can't be free'd */ GMemVTable vtable; vtable.malloc = malloc; vtable.realloc = realloc; vtable.free = free; vtable.calloc = calloc; - vtable.try_malloc = malloc; + vtable.try_malloc = malloc; vtable.try_realloc = realloc; g_mem_set_vtable(&vtable); crm_log_init_quiet(NULL, LOG_CRIT, FALSE, FALSE, argc, argv); crm_set_options(NULL, "[-?Vv] -[Xxp] {other options}", long_options, - "Calculate the cluster's response to the supplied cluster state\n"); - + "Calculate the cluster's response to the supplied cluster state\n"); + while (1) { - int option_index = 0; - flag = crm_get_option(argc, argv, &option_index); - if (flag == -1) - break; - - switch(flag) { - case 'S': - do_simulation = TRUE; - break; - case 'a': - all_actions = TRUE; - break; - case 'w': - inhibit_exit = TRUE; - break; - case 'X': - use_stdin = TRUE; - break; - case 's': - show_scores = TRUE; - break; - case 'U': - show_utilization = TRUE; - break; - case 'x': - xml_file = optarg; - break; - case 'd': - use_date = optarg; - break; - case 'D': - dot_file = optarg; - break; - case 'G': - graph_file = optarg; - break; - case 'I': - input_file = optarg; - break; - case 'V': - cl_log_enable_stderr(TRUE); - alter_debug(DEBUG_INC); - break; - case 'L': - USE_LIVE_CIB = TRUE; - break; - case '$': - case '?': - crm_help(flag, 0); - break; - default: - fprintf(stderr, "Option -%c is not yet supported\n", flag); - ++argerr; - break; - } + int option_index = 0; + + flag = crm_get_option(argc, argv, &option_index); + if (flag == -1) + break; + + switch (flag) { + case 'S': + do_simulation = TRUE; + break; + case 'a': + all_actions = TRUE; + break; + case 'w': + inhibit_exit = TRUE; + break; + case 'X': + use_stdin = TRUE; + break; + case 's': + show_scores = TRUE; + break; + case 'U': + show_utilization = TRUE; + break; + case 'x': + xml_file = optarg; + break; + case 'd': + use_date = optarg; + break; + case 'D': + dot_file = optarg; + break; + case 'G': + graph_file = optarg; + break; + case 'I': + input_file = optarg; + break; + case 'V': + cl_log_enable_stderr(TRUE); + alter_debug(DEBUG_INC); + break; + case 'L': + USE_LIVE_CIB = TRUE; + break; + case '$': + case '?': + crm_help(flag, 0); + break; + default: + fprintf(stderr, "Option -%c is not yet supported\n", flag); + ++argerr; + break; + } } - + if (optind < argc) { - printf("non-option ARGV-elements: "); - while (optind < argc) { - printf("%s ", argv[optind++]); - } - printf("\n"); + printf("non-option ARGV-elements: "); + while (optind < argc) { + printf("%s ", argv[optind++]); + } + printf("\n"); } - + if (optind > argc) { - ++argerr; + ++argerr; } - + if (argerr) { - crm_err("%d errors in option parsing", argerr); - crm_help('?', 1); + crm_err("%d errors in option parsing", argerr); + crm_help('?', 1); } - - update_all_trace_data(); /* again, so we see which trace points got updated */ - - if(USE_LIVE_CIB) { - int rc = cib_ok; - source = "live cib"; - cib_conn = cib_new(); - rc = cib_conn->cmds->signon(cib_conn, "ptest", cib_command); - - if(rc == cib_ok) { - crm_info("Reading XML from: live cluster"); - cib_object = get_cib_copy(cib_conn); - - } else { - fprintf(stderr, "Live CIB query failed: %s\n", - cib_error2string(rc)); - return 3; - } - if(cib_object == NULL) { - fprintf(stderr, "Live CIB query failed: empty result\n"); - return 3; - } - - } else if(xml_file != NULL) { - source = xml_file; - cib_object = filename2xml(xml_file); - - } else if(use_stdin) { - source = "stdin"; - cib_object = filename2xml(NULL); + + update_all_trace_data(); /* again, so we see which trace points got updated */ + + if (USE_LIVE_CIB) { + int rc = cib_ok; + + source = "live cib"; + cib_conn = cib_new(); + rc = cib_conn->cmds->signon(cib_conn, "ptest", cib_command); + + if (rc == cib_ok) { + crm_info("Reading XML from: live cluster"); + cib_object = get_cib_copy(cib_conn); + + } else { + fprintf(stderr, "Live CIB query failed: %s\n", cib_error2string(rc)); + return 3; + } + if (cib_object == NULL) { + fprintf(stderr, "Live CIB query failed: empty result\n"); + return 3; + } + + } else if (xml_file != NULL) { + source = xml_file; + cib_object = filename2xml(xml_file); + + } else if (use_stdin) { + source = "stdin"; + cib_object = filename2xml(NULL); } - if(cib_object == NULL && source) { - fprintf(stderr, "Could not parse configuration input from: %s\n", source); - return 4; + if (cib_object == NULL && source) { + fprintf(stderr, "Could not parse configuration input from: %s\n", source); + return 4; - } else if(cib_object == NULL) { - fprintf(stderr, "No configuration specified\n"); - crm_help('?', 1); + } else if (cib_object == NULL) { + fprintf(stderr, "No configuration specified\n"); + crm_help('?', 1); } - - if(get_object_root(XML_CIB_TAG_STATUS, cib_object) == NULL) { - create_xml_node(cib_object, XML_CIB_TAG_STATUS); + + if (get_object_root(XML_CIB_TAG_STATUS, cib_object) == NULL) { + create_xml_node(cib_object, XML_CIB_TAG_STATUS); } - if(cli_config_update(&cib_object, NULL, FALSE) == FALSE) { - free_xml(cib_object); - return cib_STALE; + if (cli_config_update(&cib_object, NULL, FALSE) == FALSE) { + free_xml(cib_object); + return cib_STALE; } - if(validate_xml(cib_object, NULL, FALSE) != TRUE) { - free_xml(cib_object); - return cib_dtd_validation; + if (validate_xml(cib_object, NULL, FALSE) != TRUE) { + free_xml(cib_object); + return cib_dtd_validation; } - - if(input_file != NULL) { - FILE *input_strm = fopen(input_file, "w"); - if(input_strm == NULL) { - crm_perror(LOG_ERR,"Could not open %s for writing", input_file); - } else { - msg_buffer = dump_xml_formatted(cib_object); - if(fprintf(input_strm, "%s\n", msg_buffer) < 0) { - crm_perror(LOG_ERR,"Write to %s failed", input_file); - } - fflush(input_strm); - fclose(input_strm); - crm_free(msg_buffer); - } + + if (input_file != NULL) { + FILE *input_strm = fopen(input_file, "w"); + + if (input_strm == NULL) { + crm_perror(LOG_ERR, "Could not open %s for writing", input_file); + } else { + msg_buffer = dump_xml_formatted(cib_object); + if (fprintf(input_strm, "%s\n", msg_buffer) < 0) { + crm_perror(LOG_ERR, "Write to %s failed", input_file); + } + fflush(input_strm); + fclose(input_strm); + crm_free(msg_buffer); + } } - - if(use_date != NULL) { - a_date = parse_date(&use_date); - log_date(LOG_WARNING, "Set fake 'now' to", - a_date, ha_log_date|ha_log_time); - log_date(LOG_WARNING, "Set fake 'now' to (localtime)", - a_date, ha_log_date|ha_log_time|ha_log_local); + + if (use_date != NULL) { + a_date = parse_date(&use_date); + log_date(LOG_WARNING, "Set fake 'now' to", a_date, ha_log_date | ha_log_time); + log_date(LOG_WARNING, "Set fake 'now' to (localtime)", + a_date, ha_log_date | ha_log_time | ha_log_local); } set_working_set_defaults(&data_set); - if(process) { - if(show_scores && show_utilization) { - fprintf(stdout, "Allocation scores and utilization information:\n"); - } else if(show_scores) { - fprintf(stdout, "Allocation scores:\n"); - } else if(show_utilization) { - fprintf(stdout, "Utilization information:\n"); - } - do_calculations(&data_set, cib_object, a_date); + if (process) { + if (show_scores && show_utilization) { + fprintf(stdout, "Allocation scores and utilization information:\n"); + } else if (show_scores) { + fprintf(stdout, "Allocation scores:\n"); + } else if (show_utilization) { + fprintf(stdout, "Utilization information:\n"); + } + do_calculations(&data_set, cib_object, a_date); } - + msg_buffer = dump_xml_formatted(data_set.graph); - if(safe_str_eq(graph_file, "-")) { - fprintf(stdout, "%s\n", msg_buffer); - fflush(stdout); - } else if(graph_file != NULL) { - FILE *graph_strm = fopen(graph_file, "w"); - if(graph_strm == NULL) { - crm_perror(LOG_ERR,"Could not open %s for writing", graph_file); - } else { - if(fprintf(graph_strm, "%s\n\n", msg_buffer) < 0) { - crm_perror(LOG_ERR,"Write to %s failed", graph_file); - } - fflush(graph_strm); - fclose(graph_strm); - } + if (safe_str_eq(graph_file, "-")) { + fprintf(stdout, "%s\n", msg_buffer); + fflush(stdout); + } else if (graph_file != NULL) { + FILE *graph_strm = fopen(graph_file, "w"); + + if (graph_strm == NULL) { + crm_perror(LOG_ERR, "Could not open %s for writing", graph_file); + } else { + if (fprintf(graph_strm, "%s\n\n", msg_buffer) < 0) { + crm_perror(LOG_ERR, "Write to %s failed", graph_file); + } + fflush(graph_strm); + fclose(graph_strm); + } } crm_free(msg_buffer); - if(dot_file != NULL) { - dot_strm = fopen(dot_file, "w"); - if(dot_strm == NULL) { - crm_perror(LOG_ERR,"Could not open %s for writing", dot_file); - } + if (dot_file != NULL) { + dot_strm = fopen(dot_file, "w"); + if (dot_strm == NULL) { + crm_perror(LOG_ERR, "Could not open %s for writing", dot_file); + } } - if(dot_strm == NULL) { - goto simulate; + if (dot_strm == NULL) { + goto simulate; } - + init_dotfile(); - for(lpc = data_set.actions; lpc != NULL; lpc = lpc->next) { - action_t *action = (action_t*)lpc->data; - const char *style = "filled"; - const char *font = "black"; - const char *color = "black"; - const char *fill = NULL; - char *action_name = create_action_name(action); - crm_debug_3("Action %d: %p", action->id, action); - - if(is_set(action->flags, pe_action_pseudo)) { - font = "orange"; - } - - style = "dashed"; - if(is_set(action->flags, pe_action_dumped)) { - style = "bold"; - color = "green"; - - } else if(action->rsc != NULL - && is_not_set(action->rsc->flags, pe_rsc_managed)) { - color = "purple"; - if(all_actions == FALSE) { - goto dont_write; - } - - } else if(is_set(action->flags, pe_action_optional)) { - color = "blue"; - if(all_actions == FALSE) { - goto dont_write; - } - - } else { - color = "red"; - CRM_CHECK(is_set(action->flags, pe_action_runnable) == FALSE, ;); - } - - set_bit_inplace(action->flags, pe_action_dumped); - dot_write("\"%s\" [ style=%s color=\"%s\" fontcolor=\"%s\" %s%s]", - action_name, style, color, font, fill?"fillcolor=":"", fill?fill:""); - dont_write: - crm_free(action_name); + for (lpc = data_set.actions; lpc != NULL; lpc = lpc->next) { + action_t *action = (action_t *) lpc->data; + const char *style = "filled"; + const char *font = "black"; + const char *color = "black"; + const char *fill = NULL; + char *action_name = create_action_name(action); + + crm_debug_3("Action %d: %p", action->id, action); + + if (is_set(action->flags, pe_action_pseudo)) { + font = "orange"; + } + + style = "dashed"; + if (is_set(action->flags, pe_action_dumped)) { + style = "bold"; + color = "green"; + + } else if (action->rsc != NULL && is_not_set(action->rsc->flags, pe_rsc_managed)) { + color = "purple"; + if (all_actions == FALSE) { + goto dont_write; + } + + } else if (is_set(action->flags, pe_action_optional)) { + color = "blue"; + if (all_actions == FALSE) { + goto dont_write; + } + + } else { + color = "red"; + CRM_CHECK(is_set(action->flags, pe_action_runnable) == FALSE,; + ); + } + + set_bit_inplace(action->flags, pe_action_dumped); + dot_write("\"%s\" [ style=%s color=\"%s\" fontcolor=\"%s\" %s%s]", + action_name, style, color, font, fill ? "fillcolor=" : "", fill ? fill : ""); + dont_write: + crm_free(action_name); } - - for(lpc = data_set.actions; lpc != NULL; lpc = lpc->next) { - action_t *action = (action_t*)lpc->data; - - GListPtr lpc2 = NULL; - for(lpc2 = action->actions_before; lpc2 != NULL; lpc2 = lpc2->next) { - action_wrapper_t *before = (action_wrapper_t*)lpc2->data; - - char *before_name = NULL; - char *after_name = NULL; - const char *style = "dashed"; - optional = TRUE; - if(before->state == pe_link_dumped) { - optional = FALSE; - style = "bold"; - } else if(is_set(action->flags, pe_action_pseudo) - && (before->type & pe_order_stonith_stop)) { - continue; - } else if(before->state == pe_link_dup) { - continue; - } else if(before->type == pe_order_none) { - continue; - } else if(is_set(before->action->flags, pe_action_dumped) && is_set(action->flags, pe_action_dumped)) { - optional = FALSE; - } - - if(all_actions || optional == FALSE) { - before_name = create_action_name(before->action); - after_name = create_action_name(action); - dot_write("\"%s\" -> \"%s\" [ style = %s]", - before_name, after_name, style); - crm_free(before_name); - crm_free(after_name); - } - } + for (lpc = data_set.actions; lpc != NULL; lpc = lpc->next) { + action_t *action = (action_t *) lpc->data; + + GListPtr lpc2 = NULL; + + for (lpc2 = action->actions_before; lpc2 != NULL; lpc2 = lpc2->next) { + action_wrapper_t *before = (action_wrapper_t *) lpc2->data; + + char *before_name = NULL; + char *after_name = NULL; + const char *style = "dashed"; + + optional = TRUE; + if (before->state == pe_link_dumped) { + optional = FALSE; + style = "bold"; + } else if (is_set(action->flags, pe_action_pseudo) + && (before->type & pe_order_stonith_stop)) { + continue; + } else if (before->state == pe_link_dup) { + continue; + } else if (before->type == pe_order_none) { + continue; + } else if (is_set(before->action->flags, pe_action_dumped) + && is_set(action->flags, pe_action_dumped)) { + optional = FALSE; + } + + if (all_actions || optional == FALSE) { + before_name = create_action_name(before->action); + after_name = create_action_name(action); + dot_write("\"%s\" -> \"%s\" [ style = %s]", before_name, after_name, style); + crm_free(before_name); + crm_free(after_name); + } + } } dot_write("}"); - if(dot_strm != NULL) { - fflush(dot_strm); - fclose(dot_strm); + if (dot_strm != NULL) { + fflush(dot_strm); + fclose(dot_strm); } simulate: - - if(do_simulation == FALSE) { - goto cleanup; + + if (do_simulation == FALSE) { + goto cleanup; } - + transition = unpack_graph(data_set.graph, "ptest"); print_graph(LOG_DEBUG, transition); do { - graph_rc = run_graph(transition); - - } while(graph_rc == transition_active); + graph_rc = run_graph(transition); + + } while (graph_rc == transition_active); - if(graph_rc != transition_complete) { - crm_crit("Transition failed: %s", transition_status(graph_rc)); - print_graph(LOG_ERR, transition); + if (graph_rc != transition_complete) { + crm_crit("Transition failed: %s", transition_status(graph_rc)); + print_graph(LOG_ERR, transition); } destroy_graph(transition); - CRM_CHECK(graph_rc == transition_complete, all_good = FALSE; crm_err("An invalid transition was produced")); + CRM_CHECK(graph_rc == transition_complete, all_good = FALSE; + crm_err("An invalid transition was produced")); cleanup: cleanup_alloc_calculations(&data_set); crm_log_deinit(); /* required for MallocDebug.app */ - if(inhibit_exit) { - GMainLoop* mainloop = g_main_new(FALSE); - g_main_run(mainloop); + if (inhibit_exit) { + GMainLoop *mainloop = g_main_new(FALSE); + + g_main_run(mainloop); } - if(all_good) { - return 0; + if (all_good) { + return 0; } return graph_rc; } diff --git a/pengine/utils.c b/pengine/utils.c index 98bf1230b9..e0d95103d3 100644 --- a/pengine/utils.c +++ b/pengine/utils.c @@ -1,610 +1,612 @@ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include void -pe_free_ordering(GListPtr constraints) +pe_free_ordering(GListPtr constraints) { - GListPtr iterator = constraints; - while(iterator != NULL) { - order_constraint_t *order = iterator->data; - iterator = iterator->next; - - crm_free(order->lh_action_task); - crm_free(order->rh_action_task); - crm_free(order); - } - if(constraints != NULL) { - g_list_free(constraints); - } -} + GListPtr iterator = constraints; + + while (iterator != NULL) { + order_constraint_t *order = iterator->data; + iterator = iterator->next; + + crm_free(order->lh_action_task); + crm_free(order->rh_action_task); + crm_free(order); + } + if (constraints != NULL) { + g_list_free(constraints); + } +} void pe_free_rsc_to_node(GListPtr constraints) { - GListPtr iterator = constraints; - while(iterator != NULL) { - rsc_to_node_t *cons = iterator->data; - iterator = iterator->next; - - slist_basic_destroy(cons->node_list_rh); - crm_free(cons); - } - if(constraints != NULL) { - g_list_free(constraints); - } -} + GListPtr iterator = constraints; + while (iterator != NULL) { + rsc_to_node_t *cons = iterator->data; + + iterator = iterator->next; + + slist_basic_destroy(cons->node_list_rh); + crm_free(cons); + } + if (constraints != NULL) { + g_list_free(constraints); + } +} rsc_to_node_t * -rsc2node_new(const char *id, resource_t *rsc, - int node_weight, node_t *foo_node, pe_working_set_t *data_set) +rsc2node_new(const char *id, resource_t * rsc, + int node_weight, node_t * foo_node, pe_working_set_t * data_set) { rsc_to_node_t *new_con = NULL; - if(rsc == NULL || id == NULL) { - pe_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc); - return NULL; + if (rsc == NULL || id == NULL) { + pe_err("Invalid constraint %s for rsc=%p", crm_str(id), rsc); + return NULL; - } else if(foo_node == NULL) { - CRM_CHECK(node_weight == 0, return NULL); + } else if (foo_node == NULL) { + CRM_CHECK(node_weight == 0, return NULL); } - + crm_malloc0(new_con, sizeof(rsc_to_node_t)); - if(new_con != NULL) { - new_con->id = id; - new_con->rsc_lh = rsc; - new_con->node_list_rh = NULL; - new_con->role_filter = RSC_ROLE_UNKNOWN; - - if(foo_node != NULL) { - node_t *copy = node_copy(foo_node); - copy->weight = merge_weights(node_weight, foo_node->weight); - new_con->node_list_rh = g_list_prepend(NULL, copy); - } - - data_set->placement_constraints = g_list_prepend( - data_set->placement_constraints, new_con); - rsc->rsc_location = g_list_prepend(rsc->rsc_location, new_con); - } - + if (new_con != NULL) { + new_con->id = id; + new_con->rsc_lh = rsc; + new_con->node_list_rh = NULL; + new_con->role_filter = RSC_ROLE_UNKNOWN; + + if (foo_node != NULL) { + node_t *copy = node_copy(foo_node); + + copy->weight = merge_weights(node_weight, foo_node->weight); + new_con->node_list_rh = g_list_prepend(NULL, copy); + } + + data_set->placement_constraints = g_list_prepend(data_set->placement_constraints, new_con); + rsc->rsc_location = g_list_prepend(rsc->rsc_location, new_con); + } + return new_con; } gboolean -can_run_resources(const node_t *node) +can_run_resources(const node_t * node) { - if(node == NULL) { - return FALSE; + if (node == NULL) { + return FALSE; } - -#if 0 - if(node->weight < 0) { - return FALSE; +#if 0 + if (node->weight < 0) { + return FALSE; } #endif - - if(node->details->online == FALSE - || node->details->shutdown - || node->details->unclean - || node->details->standby) { - crm_debug_2("%s: online=%d, unclean=%d, standby=%d", - node->details->uname, node->details->online, - node->details->unclean, node->details->standby); - return FALSE; + + if (node->details->online == FALSE + || node->details->shutdown || node->details->unclean || node->details->standby) { + crm_debug_2("%s: online=%d, unclean=%d, standby=%d", + node->details->uname, node->details->online, + node->details->unclean, node->details->standby); + return FALSE; } return TRUE; } -struct compare_data -{ - const node_t *node1; - const node_t *node2; - int result; +struct compare_data { + const node_t *node1; + const node_t *node2; + int result; }; static void do_compare_capacity1(gpointer key, gpointer value, gpointer user_data) { int node1_capacity = 0; int node2_capacity = 0; struct compare_data *data = user_data; node1_capacity = crm_parse_int(value, "0"); - node2_capacity = crm_parse_int(g_hash_table_lookup(data->node2->details->utilization, key), "0"); + node2_capacity = + crm_parse_int(g_hash_table_lookup(data->node2->details->utilization, key), "0"); if (node1_capacity > node2_capacity) { - data->result--; + data->result--; } else if (node1_capacity < node2_capacity) { - data->result++; + data->result++; } } static void do_compare_capacity2(gpointer key, gpointer value, gpointer user_data) { int node1_capacity = 0; int node2_capacity = 0; struct compare_data *data = user_data; if (g_hash_table_lookup_extended(data->node1->details->utilization, key, NULL, NULL)) { - return; + return; } node1_capacity = 0; node2_capacity = crm_parse_int(value, "0"); if (node1_capacity > node2_capacity) { - data->result--; + data->result--; } else if (node1_capacity < node2_capacity) { - data->result++; + data->result++; } } /* rc < 0 if 'node1' has more capacity remaining * rc > 0 if 'node1' has less capacity remaining */ static int -compare_capacity(const node_t *node1, const node_t *node2) +compare_capacity(const node_t * node1, const node_t * node2) { struct compare_data data; data.node1 = node1; data.node2 = node2; data.result = 0; g_hash_table_foreach(node1->details->utilization, do_compare_capacity1, &data); g_hash_table_foreach(node2->details->utilization, do_compare_capacity2, &data); return data.result; } /* return -1 if 'a' is more preferred * return 1 if 'b' is more preferred */ -gint sort_node_weight(gconstpointer a, gconstpointer b, gpointer data) +gint +sort_node_weight(gconstpointer a, gconstpointer b, gpointer data) { int level = LOG_DEBUG_3; - const node_t *node1 = (const node_t*)a; - const node_t *node2 = (const node_t*)b; - const node_t *active = (node_t*)data; + const node_t *node1 = (const node_t *)a; + const node_t *node2 = (const node_t *)b; + const node_t *active = (node_t *) data; int node1_weight = 0; int node2_weight = 0; int result = 0; - - if(a == NULL) { return 1; } - if(b == NULL) { return -1; } - + + if (a == NULL) { + return 1; + } + if (b == NULL) { + return -1; + } + node1_weight = node1->weight; node2_weight = node2->weight; - - if(can_run_resources(node1) == FALSE) { - node1_weight = -INFINITY; + + if (can_run_resources(node1) == FALSE) { + node1_weight = -INFINITY; } - if(can_run_resources(node2) == FALSE) { - node2_weight = -INFINITY; + if (can_run_resources(node2) == FALSE) { + node2_weight = -INFINITY; } - if(node1_weight > node2_weight) { - do_crm_log_unlikely(level, "%s (%d) > %s (%d) : weight", - node1->details->uname, node1_weight, - node2->details->uname, node2_weight); - return -1; + if (node1_weight > node2_weight) { + do_crm_log_unlikely(level, "%s (%d) > %s (%d) : weight", + node1->details->uname, node1_weight, + node2->details->uname, node2_weight); + return -1; } - - if(node1_weight < node2_weight) { - do_crm_log_unlikely(level, "%s (%d) < %s (%d) : weight", - node1->details->uname, node1_weight, - node2->details->uname, node2_weight); - return 1; + + if (node1_weight < node2_weight) { + do_crm_log_unlikely(level, "%s (%d) < %s (%d) : weight", + node1->details->uname, node1_weight, + node2->details->uname, node2_weight); + return 1; } do_crm_log_unlikely(level, "%s (%d) == %s (%d) : weight", - node1->details->uname, node1_weight, - node2->details->uname, node2_weight); + node1->details->uname, node1_weight, node2->details->uname, node2_weight); if (safe_str_eq(pe_dataset->placement_strategy, "minimal")) { - goto equal; + goto equal; } if (safe_str_eq(pe_dataset->placement_strategy, "balanced")) { - result = compare_capacity(node1, node2); - if (result != 0) { - return result; - } + result = compare_capacity(node1, node2); + if (result != 0) { + return result; + } } - + /* now try to balance resources across the cluster */ - if(node1->details->num_resources - < node2->details->num_resources) { - do_crm_log_unlikely(level, "%s (%d) < %s (%d) : resources", - node1->details->uname, node1->details->num_resources, - node2->details->uname, node2->details->num_resources); - return -1; - - } else if(node1->details->num_resources - > node2->details->num_resources) { - do_crm_log_unlikely(level, "%s (%d) > %s (%d) : resources", - node1->details->uname, node1->details->num_resources, - node2->details->uname, node2->details->num_resources); - return 1; - } - - if(active && active->details == node1->details) { - do_crm_log_unlikely(level, "%s (%d) > %s (%d) : active", - node1->details->uname, node1->details->num_resources, - node2->details->uname, node2->details->num_resources); - return -1; - } else if(active && active->details == node2->details) { - do_crm_log_unlikely(level, "%s (%d) > %s (%d) : active", - node1->details->uname, node1->details->num_resources, - node2->details->uname, node2->details->num_resources); - return 1; - } - equal: + if (node1->details->num_resources < node2->details->num_resources) { + do_crm_log_unlikely(level, "%s (%d) < %s (%d) : resources", + node1->details->uname, node1->details->num_resources, + node2->details->uname, node2->details->num_resources); + return -1; + + } else if (node1->details->num_resources > node2->details->num_resources) { + do_crm_log_unlikely(level, "%s (%d) > %s (%d) : resources", + node1->details->uname, node1->details->num_resources, + node2->details->uname, node2->details->num_resources); + return 1; + } + + if (active && active->details == node1->details) { + do_crm_log_unlikely(level, "%s (%d) > %s (%d) : active", + node1->details->uname, node1->details->num_resources, + node2->details->uname, node2->details->num_resources); + return -1; + } else if (active && active->details == node2->details) { + do_crm_log_unlikely(level, "%s (%d) > %s (%d) : active", + node1->details->uname, node1->details->num_resources, + node2->details->uname, node2->details->num_resources); + return 1; + } + equal: do_crm_log_unlikely(level, "%s = %s", node1->details->uname, node2->details->uname); return strcmp(node1->details->uname, node2->details->uname); } -struct calculate_data -{ - node_t *node; - gboolean allocate; +struct calculate_data { + node_t *node; + gboolean allocate; }; static void do_calculate_utilization(gpointer key, gpointer value, gpointer user_data) { const char *capacity = NULL; char *remain_capacity = NULL; struct calculate_data *data = user_data; capacity = g_hash_table_lookup(data->node->details->utilization, key); if (capacity) { - if (data->allocate) { - remain_capacity = crm_itoa(crm_parse_int(capacity, "0") - crm_parse_int(value, "0")); - } else { - remain_capacity = crm_itoa(crm_parse_int(capacity, "0") + crm_parse_int(value, "0")); - } - g_hash_table_replace(data->node->details->utilization, crm_strdup(key), remain_capacity); + if (data->allocate) { + remain_capacity = crm_itoa(crm_parse_int(capacity, "0") - crm_parse_int(value, "0")); + } else { + remain_capacity = crm_itoa(crm_parse_int(capacity, "0") + crm_parse_int(value, "0")); + } + g_hash_table_replace(data->node->details->utilization, crm_strdup(key), remain_capacity); } } /* Specify 'allocate' to TRUE when allocating * Otherwise to FALSE when deallocating */ static void -calculate_utilization(node_t *node, resource_t *rsc, gboolean allocate) +calculate_utilization(node_t * node, resource_t * rsc, gboolean allocate) { struct calculate_data data; data.node = node; data.allocate = allocate; g_hash_table_foreach(rsc->utilization, do_calculate_utilization, &data); if (allocate) { - dump_rsc_utilization(show_utilization?0:utilization_log_level, __FUNCTION__, rsc, node); + dump_rsc_utilization(show_utilization ? 0 : utilization_log_level, __FUNCTION__, rsc, node); } } void -native_deallocate(resource_t *rsc) +native_deallocate(resource_t * rsc) { - if(rsc->allocated_to) { - node_t *old = rsc->allocated_to; + if (rsc->allocated_to) { + node_t *old = rsc->allocated_to; - crm_info("Deallocating %s from %s", rsc->id, old->details->uname); - set_bit_inplace(rsc->flags, pe_rsc_provisional); - rsc->allocated_to = NULL; + crm_info("Deallocating %s from %s", rsc->id, old->details->uname); + set_bit_inplace(rsc->flags, pe_rsc_provisional); + rsc->allocated_to = NULL; - old->details->allocated_rsc = g_list_remove( - old->details->allocated_rsc, rsc); - old->details->num_resources--; - /* old->count--; */ - calculate_utilization(old, rsc, FALSE); - crm_free(old); + old->details->allocated_rsc = g_list_remove(old->details->allocated_rsc, rsc); + old->details->num_resources--; + /* old->count--; */ + calculate_utilization(old, rsc, FALSE); + crm_free(old); } } gboolean -native_assign_node(resource_t *rsc, GListPtr nodes, node_t *chosen, gboolean force) +native_assign_node(resource_t * rsc, GListPtr nodes, node_t * chosen, gboolean force) { CRM_ASSERT(rsc->variant == pe_native); - - if(force == FALSE - && chosen != NULL - && (can_run_resources(chosen) == FALSE || chosen->weight < 0)) { - crm_debug("All nodes for resource %s are unavailable" - ", unclean or shutting down (%s: %d, %d)", - rsc->id, chosen->details->uname, can_run_resources(chosen), chosen->weight); - rsc->next_role = RSC_ROLE_STOPPED; - chosen = NULL; + + if (force == FALSE + && chosen != NULL && (can_run_resources(chosen) == FALSE || chosen->weight < 0)) { + crm_debug("All nodes for resource %s are unavailable" + ", unclean or shutting down (%s: %d, %d)", + rsc->id, chosen->details->uname, can_run_resources(chosen), chosen->weight); + rsc->next_role = RSC_ROLE_STOPPED; + chosen = NULL; } /* todo: update the old node for each resource to reflect its * new resource count */ native_deallocate(rsc); clear_bit(rsc->flags, pe_rsc_provisional); - - if(chosen == NULL) { - char *key = NULL; - GListPtr gIter = NULL; - GListPtr possible_matches = NULL; - crm_debug("Could not allocate a node for %s", rsc->id); - rsc->next_role = RSC_ROLE_STOPPED; - - key = generate_op_key(rsc->id, RSC_STOP, 0); - possible_matches = find_actions(rsc->actions, key, NULL); + if (chosen == NULL) { + char *key = NULL; + GListPtr gIter = NULL; + GListPtr possible_matches = NULL; + + crm_debug("Could not allocate a node for %s", rsc->id); + rsc->next_role = RSC_ROLE_STOPPED; + + key = generate_op_key(rsc->id, RSC_STOP, 0); + possible_matches = find_actions(rsc->actions, key, NULL); + + for (gIter = possible_matches; gIter != NULL; gIter = gIter->next) { + action_t *stop = (action_t *) gIter->data; - for(gIter = possible_matches; gIter != NULL; gIter = gIter->next) { - action_t *stop = (action_t*)gIter->data; - update_action_flags(stop, pe_action_optional|pe_action_clear); - } + update_action_flags(stop, pe_action_optional | pe_action_clear); + } - g_list_free(possible_matches); - crm_free(key); + g_list_free(possible_matches); + crm_free(key); - key = generate_op_key(rsc->id, RSC_START, 0); - possible_matches = find_actions(rsc->actions, key, NULL); + key = generate_op_key(rsc->id, RSC_START, 0); + possible_matches = find_actions(rsc->actions, key, NULL); - for(gIter = possible_matches; gIter != NULL; gIter = gIter->next) { - action_t *start = (action_t*)gIter->data; - - update_action_flags(start, pe_action_runnable|pe_action_clear); - } + for (gIter = possible_matches; gIter != NULL; gIter = gIter->next) { + action_t *start = (action_t *) gIter->data; - g_list_free(possible_matches); - crm_free(key); + update_action_flags(start, pe_action_runnable | pe_action_clear); + } - return FALSE; + g_list_free(possible_matches); + crm_free(key); + + return FALSE; } crm_debug("Assigning %s to %s", chosen->details->uname, rsc->id); rsc->allocated_to = node_copy(chosen); chosen->details->allocated_rsc = g_list_prepend(chosen->details->allocated_rsc, rsc); chosen->details->num_resources++; chosen->count++; calculate_utilization(chosen, rsc, TRUE); return TRUE; } gboolean -order_actions( - action_t *lh_action, action_t *rh_action, enum pe_ordering order) +order_actions(action_t * lh_action, action_t * rh_action, enum pe_ordering order) { GListPtr gIter = NULL; action_wrapper_t *wrapper = NULL; GListPtr list = NULL; static int load_stopped_strlen = 0; - if(order == pe_order_none) { - return FALSE; + if (order == pe_order_none) { + return FALSE; } - if(lh_action == NULL || rh_action == NULL) { - return FALSE; + if (lh_action == NULL || rh_action == NULL) { + return FALSE; } - + if (!load_stopped_strlen) { - load_stopped_strlen = strlen(LOAD_STOPPED); + load_stopped_strlen = strlen(LOAD_STOPPED); } if (strncmp(lh_action->uuid, LOAD_STOPPED, load_stopped_strlen) == 0 - || strncmp(rh_action->uuid, LOAD_STOPPED, load_stopped_strlen) == 0) { - - if(safe_str_eq(rh_action->task, RSC_MIGRATE)) { - /* A live migration: rh_action is a migrate_to */ - - if(lh_action->node == NULL || rh_action->rsc->allocated_to == NULL - /* Ignore the order: The load_stopped is not on the node where the resource will be migrated to. */ - || lh_action->node->details != rh_action->rsc->allocated_to->details){ - return FALSE; - } - - } else if (lh_action->node == NULL || rh_action->node == NULL - /* Ignore the order: The load_stopped is not on the node where the other action will be executed. */ - || lh_action->node->details != rh_action->node->details) { - return FALSE; - } - } - - crm_debug_3("Ordering Action %s before %s", - lh_action->uuid, rh_action->uuid); + || strncmp(rh_action->uuid, LOAD_STOPPED, load_stopped_strlen) == 0) { + + if (safe_str_eq(rh_action->task, RSC_MIGRATE)) { + /* A live migration: rh_action is a migrate_to */ + + if (lh_action->node == NULL || rh_action->rsc->allocated_to == NULL + /* Ignore the order: The load_stopped is not on the node where the resource will be migrated to. */ + || lh_action->node->details != rh_action->rsc->allocated_to->details) { + return FALSE; + } + + } else if (lh_action->node == NULL || rh_action->node == NULL + /* Ignore the order: The load_stopped is not on the node where the other action will be executed. */ + || lh_action->node->details != rh_action->node->details) { + return FALSE; + } + } + + crm_debug_3("Ordering Action %s before %s", lh_action->uuid, rh_action->uuid); log_action(LOG_DEBUG_4, "LH (order_actions)", lh_action, FALSE); log_action(LOG_DEBUG_4, "RH (order_actions)", rh_action, FALSE); /* Filter dups, otherwise update_action_states() has too much work to do */ gIter = lh_action->actions_after; - for(; gIter != NULL; gIter = gIter->next) { - action_wrapper_t *after = (action_wrapper_t*)gIter->data; - - if(after->action == rh_action && (after->type & order)) { - return FALSE; - } - } - + for (; gIter != NULL; gIter = gIter->next) { + action_wrapper_t *after = (action_wrapper_t *) gIter->data; + + if (after->action == rh_action && (after->type & order)) { + return FALSE; + } + } + crm_malloc0(wrapper, sizeof(action_wrapper_t)); wrapper->action = rh_action; wrapper->type = order; - + list = lh_action->actions_after; list = g_list_prepend(list, wrapper); lh_action->actions_after = list; wrapper = NULL; /* order |= pe_order_implies_then; */ /* order ^= pe_order_implies_then; */ - + crm_malloc0(wrapper, sizeof(action_wrapper_t)); wrapper->action = lh_action; wrapper->type = order; list = rh_action->actions_before; list = g_list_prepend(list, wrapper); rh_action->actions_before = list; return TRUE; } - void -log_action(unsigned int log_level, const char *pre_text, action_t *action, gboolean details) +log_action(unsigned int log_level, const char *pre_text, action_t * action, gboolean details) { const char *node_uname = NULL; const char *node_uuid = NULL; - - if(action == NULL) { - do_crm_log_unlikely(log_level, "%s%s: ", - pre_text==NULL?"":pre_text, - pre_text==NULL?"":": "); - return; + if (action == NULL) { + + do_crm_log_unlikely(log_level, "%s%s: ", + pre_text == NULL ? "" : pre_text, pre_text == NULL ? "" : ": "); + return; } + if (is_set(action->flags, pe_action_pseudo)) { + node_uname = NULL; + node_uuid = NULL; - if(is_set(action->flags, pe_action_pseudo)) { - node_uname = NULL; - node_uuid = NULL; - - } else if(action->node != NULL) { - node_uname = action->node->details->uname; - node_uuid = action->node->details->id; + } else if (action->node != NULL) { + node_uname = action->node->details->uname; + node_uuid = action->node->details->id; } else { - node_uname = ""; - node_uuid = NULL; - } - - switch(text2task(action->task)) { - case stonith_node: - case shutdown_crm: - do_crm_log_unlikely(log_level, - "%s%s%sAction %d: %s%s%s%s%s%s", - pre_text==NULL?"":pre_text, - pre_text==NULL?"":": ", - is_set(action->flags, pe_action_pseudo)?"Pseduo ":is_set(action->flags, pe_action_optional)?"Optional ":is_set(action->flags, pe_action_runnable)?is_set(action->flags, pe_action_processed)?"":"(Provisional) ":"!!Non-Startable!! ", - action->id, action->uuid, - node_uname?"\ton ":"", - node_uname?node_uname:"", - node_uuid?"\t\t(":"", - node_uuid?node_uuid:"", - node_uuid?")":""); - break; - default: - do_crm_log_unlikely(log_level, - "%s%s%sAction %d: %s %s%s%s%s%s%s", - pre_text==NULL?"":pre_text, - pre_text==NULL?"":": ", - is_set(action->flags, pe_action_optional)?"Optional ":is_set(action->flags, pe_action_pseudo)?"Pseduo ":is_set(action->flags, pe_action_runnable)?is_set(action->flags, pe_action_processed)?"":"(Provisional) ":"!!Non-Startable!! ", - action->id, action->uuid, - safe_val3("", action, rsc, id), - node_uname?"\ton ":"", - node_uname?node_uname:"", - node_uuid?"\t\t(":"", - node_uuid?node_uuid:"", - node_uuid?")":""); - - break; - } - - if(details) { - GListPtr gIter = NULL; - - do_crm_log_unlikely(log_level+1, "\t\t====== Preceding Actions"); - - gIter = action->actions_before; - for(; gIter != NULL; gIter = gIter->next) { - action_wrapper_t *other = (action_wrapper_t*)gIter->data; - log_action(log_level+1, "\t\t", other->action, FALSE); - } - - do_crm_log_unlikely(log_level+1, "\t\t====== Subsequent Actions"); - - gIter = action->actions_after; - for(; gIter != NULL; gIter = gIter->next) { - action_wrapper_t *other = (action_wrapper_t*)gIter->data; - log_action(log_level+1, "\t\t", other->action, FALSE); - } - - do_crm_log_unlikely(log_level+1, "\t\t====== End"); + node_uname = ""; + node_uuid = NULL; + } + + switch (text2task(action->task)) { + case stonith_node: + case shutdown_crm: + do_crm_log_unlikely(log_level, + "%s%s%sAction %d: %s%s%s%s%s%s", + pre_text == NULL ? "" : pre_text, + pre_text == NULL ? "" : ": ", + is_set(action->flags, + pe_action_pseudo) ? "Pseduo " : is_set(action->flags, + pe_action_optional) ? + "Optional " : is_set(action->flags, + pe_action_runnable) ? is_set(action->flags, + pe_action_processed) + ? "" : "(Provisional) " : "!!Non-Startable!! ", action->id, + action->uuid, node_uname ? "\ton " : "", + node_uname ? node_uname : "", node_uuid ? "\t\t(" : "", + node_uuid ? node_uuid : "", node_uuid ? ")" : ""); + break; + default: + do_crm_log_unlikely(log_level, + "%s%s%sAction %d: %s %s%s%s%s%s%s", + pre_text == NULL ? "" : pre_text, + pre_text == NULL ? "" : ": ", + is_set(action->flags, + pe_action_optional) ? "Optional " : is_set(action->flags, + pe_action_pseudo) + ? "Pseduo " : is_set(action->flags, + pe_action_runnable) ? is_set(action->flags, + pe_action_processed) + ? "" : "(Provisional) " : "!!Non-Startable!! ", action->id, + action->uuid, safe_val3("", action, rsc, id), + node_uname ? "\ton " : "", node_uname ? node_uname : "", + node_uuid ? "\t\t(" : "", node_uuid ? node_uuid : "", + node_uuid ? ")" : ""); + + break; + } + + if (details) { + GListPtr gIter = NULL; + + do_crm_log_unlikely(log_level + 1, "\t\t====== Preceding Actions"); + + gIter = action->actions_before; + for (; gIter != NULL; gIter = gIter->next) { + action_wrapper_t *other = (action_wrapper_t *) gIter->data; + + log_action(log_level + 1, "\t\t", other->action, FALSE); + } + + do_crm_log_unlikely(log_level + 1, "\t\t====== Subsequent Actions"); + + gIter = action->actions_after; + for (; gIter != NULL; gIter = gIter->next) { + action_wrapper_t *other = (action_wrapper_t *) gIter->data; + + log_action(log_level + 1, "\t\t", other->action, FALSE); + } + + do_crm_log_unlikely(log_level + 1, "\t\t====== End"); } else { - do_crm_log_unlikely(log_level, "\t\t(seen=%d, before=%d, after=%d)", - action->seen_count, - g_list_length(action->actions_before), - g_list_length(action->actions_after)); + do_crm_log_unlikely(log_level, "\t\t(seen=%d, before=%d, after=%d)", + action->seen_count, + g_list_length(action->actions_before), + g_list_length(action->actions_after)); } } -action_t *get_pseudo_op(const char *name, pe_working_set_t *data_set) +action_t * +get_pseudo_op(const char *name, pe_working_set_t * data_set) { action_t *op = NULL; const char *op_s = name; GListPtr possible_matches = NULL; possible_matches = find_actions(data_set->actions, name, NULL); - if(possible_matches != NULL) { - if(g_list_length(possible_matches) > 1) { - pe_warn("Action %s exists %d times", - name, g_list_length(possible_matches)); - } - - op = g_list_nth_data(possible_matches, 0); - g_list_free(possible_matches); + if (possible_matches != NULL) { + if (g_list_length(possible_matches) > 1) { + pe_warn("Action %s exists %d times", name, g_list_length(possible_matches)); + } + + op = g_list_nth_data(possible_matches, 0); + g_list_free(possible_matches); } else { - op = custom_action(NULL, crm_strdup(op_s), op_s, - NULL, TRUE, TRUE, data_set); - update_action_flags(op, pe_action_pseudo); - update_action_flags(op, pe_action_runnable); + op = custom_action(NULL, crm_strdup(op_s), op_s, NULL, TRUE, TRUE, data_set); + update_action_flags(op, pe_action_pseudo); + update_action_flags(op, pe_action_runnable); } return op; } -gboolean can_run_any(GHashTable *nodes) +gboolean +can_run_any(GHashTable * nodes) { GHashTableIter iter; node_t *node = NULL; - if(nodes == NULL) { - return FALSE; + + if (nodes == NULL) { + return FALSE; } - g_hash_table_iter_init (&iter, nodes); - while (g_hash_table_iter_next (&iter, NULL, (void**)&node)) { - if(can_run_resources(node) && node->weight >= 0) { - return TRUE; - } + g_hash_table_iter_init(&iter, nodes); + while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) { + if (can_run_resources(node) && node->weight >= 0) { + return TRUE; + } } return FALSE; } -