diff --git a/crm/pengine/group.c b/crm/pengine/group.c index b8e233f933..88833bf5ed 100644 --- a/crm/pengine/group.c +++ b/crm/pengine/group.c @@ -1,540 +1,541 @@ -/* $Id: group.c,v 1.43 2005/09/26 07:44:44 andrew Exp $ */ +/* $Id: group.c,v 1.44 2005/10/17 10:57:11 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include extern gboolean rsc_colocation_new( const char *id, enum con_strength strength, resource_t *rsc_lh, resource_t *rsc_rh, const char *state_lh, const char *state_rh); typedef struct group_variant_data_s { int num_children; GListPtr child_list; /* resource_t* */ resource_t *self; resource_t *first_child; resource_t *last_child; gboolean child_starting; gboolean child_stopping; } group_variant_data_t; #define get_group_variant_data(data, rsc) \ CRM_ASSERT(rsc->variant == pe_group); \ CRM_ASSERT(rsc->variant_opaque != NULL); \ data = (group_variant_data_t *)rsc->variant_opaque; \ void group_unpack(resource_t *rsc, pe_working_set_t *data_set) { crm_data_t *xml_obj = rsc->xml; crm_data_t *xml_self = create_xml_node(NULL, XML_CIB_TAG_RESOURCE); group_variant_data_t *group_data = NULL; resource_t *self = NULL; crm_debug_3("Processing resource %s...", rsc->id); /* rsc->id = "dummy_group_rsc_id"; */ crm_malloc0(group_data, sizeof(group_variant_data_t)); group_data->num_children = 0; group_data->self = NULL; group_data->child_list = NULL; group_data->first_child = NULL; group_data->last_child = NULL; /* this is a bit of a hack - but simplifies everything else */ copy_in_properties(xml_self, xml_obj); /* set_id(xml_self, "self", -1); */ if(common_unpack(xml_self, &self, NULL, data_set)) { group_data->self = self; self->restart_type = pe_restart_restart; } else { crm_log_xml_err(xml_self, "Couldnt unpack dummy child"); return; } xml_child_iter( xml_obj, xml_native_rsc, XML_CIB_TAG_RESOURCE, resource_t *new_rsc = NULL; set_id(xml_native_rsc, group_data->self->id, -1); if(common_unpack(xml_native_rsc, &new_rsc, group_data->self->parameters, data_set)) { + new_rsc->parent = rsc; group_data->num_children++; group_data->child_list = g_list_append( group_data->child_list, new_rsc); if(group_data->first_child == NULL) { group_data->first_child = new_rsc; } else { rsc_colocation_new( "pe_group_internal_colo", pecs_must, group_data->first_child, new_rsc, NULL, NULL); } group_data->last_child = new_rsc; crm_action_debug_3( print_resource("Added", new_rsc, FALSE)); } else { pe_err("Failed unpacking resource %s", crm_element_value(xml_obj, XML_ATTR_ID)); } ); crm_debug_3("Added %d children to resource %s...", group_data->num_children, group_data->self->id); rsc->variant_opaque = group_data; } resource_t * group_find_child(resource_t *rsc, const char *id) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); return pe_find_resource(group_data->child_list, id); } int group_num_allowed_nodes(resource_t *rsc) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); return group_data->self->fns->num_allowed_nodes(group_data->self); } color_t * group_color(resource_t *rsc, pe_working_set_t *data_set) { color_t *group_color = NULL; group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); CRM_ASSERT(data_set != NULL); CRM_ASSERT(group_data->self != NULL); group_color = color_resource(group_data->first_child, data_set); CRM_DEV_ASSERT(group_color != NULL); native_assign_color(rsc, group_color); return group_color; } void group_update_pseudo_status(resource_t *parent, resource_t *child); void group_create_actions(resource_t *rsc, pe_working_set_t *data_set) { action_t *op = NULL; group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, child_rsc->fns->create_actions(child_rsc, data_set); group_update_pseudo_status(rsc, child_rsc); ); op = start_action(group_data->self, NULL, !group_data->child_starting); op->pseudo = TRUE; op = custom_action(group_data->self, started_key(group_data->self), CRMD_ACTION_STARTED, NULL, !group_data->child_starting, TRUE, data_set); op->pseudo = TRUE; op = stop_action(group_data->self, NULL, !group_data->child_stopping); op->pseudo = TRUE; op = custom_action(group_data->self, stopped_key(group_data->self), CRMD_ACTION_STOPPED, NULL, !group_data->child_stopping, TRUE, data_set); op->pseudo = TRUE; } void group_update_pseudo_status(resource_t *parent, resource_t *child) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, parent); if(group_data->child_stopping && group_data->child_starting) { return; } slist_iter( action, action_t, child->actions, lpc, if(action->optional) { continue; } if(safe_str_eq(CRMD_ACTION_STOP, action->task)) { group_data->child_stopping = TRUE; } else if(safe_str_eq(CRMD_ACTION_START, action->task)) { group_data->child_starting = TRUE; } ); } void group_internal_constraints(resource_t *rsc, pe_working_set_t *data_set) { resource_t *last_rsc = NULL; group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); custom_action_order( group_data->self, stopped_key(group_data->self), NULL, group_data->self, start_key(group_data->self), NULL, pe_ordering_optional, data_set); custom_action_order( group_data->self, stop_key(group_data->self), NULL, group_data->self, stopped_key(group_data->self), NULL, pe_ordering_optional, data_set); custom_action_order( group_data->self, start_key(group_data->self), NULL, group_data->self, started_key(group_data->self), NULL, pe_ordering_optional, data_set); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, order_restart(child_rsc); if(last_rsc != NULL) { order_start_start( last_rsc, child_rsc, pe_ordering_optional); order_stop_stop( child_rsc, last_rsc, pe_ordering_optional); /* recovery */ child_rsc->restart_type = pe_restart_restart; order_start_start( last_rsc, child_rsc, pe_ordering_recover); order_stop_stop( child_rsc, last_rsc, pe_ordering_recover); } else { custom_action_order( child_rsc, stop_key(child_rsc), NULL, group_data->self, stopped_key(group_data->self), NULL, pe_ordering_optional, data_set); order_start_start(group_data->self, child_rsc, pe_ordering_optional); } last_rsc = child_rsc; ); if(last_rsc != NULL) { custom_action_order( last_rsc, start_key(last_rsc), NULL, group_data->self, started_key(group_data->self), NULL, pe_ordering_optional, data_set); order_stop_stop( group_data->self, last_rsc, pe_ordering_optional); } } void group_rsc_colocation_lh( resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) { 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; } crm_debug_4("Processing constraints from %s", rsc_lh->id); get_group_variant_data(group_data, rsc_lh); CRM_DEV_ASSERT(group_data->self != NULL); if(crm_assert_failed) { return; } group_data->first_child->fns->rsc_colocation_lh(group_data->first_child, rsc_rh, constraint); } void group_rsc_colocation_rh( resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc_rh); CRM_DEV_ASSERT(group_data->self != NULL); if(crm_assert_failed) { return; } CRM_DEV_ASSERT(rsc_lh->variant == pe_native); crm_debug_3("Processing RH of constraint %s", constraint->id); crm_action_debug_3(print_resource("LHS", rsc_lh, TRUE)); group_data->first_child->fns->rsc_colocation_rh(rsc_lh, group_data->first_child, constraint); } void group_rsc_order_lh(resource_t *rsc, order_constraint_t *order) { char *stop_id = NULL; char *start_id = NULL; group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); crm_debug_3("Processing LH of ordering constraint %d", order->id); if(group_data->self == NULL) { return; } stop_id = stop_key(group_data->self); start_id = start_key(group_data->self); if(safe_str_eq(order->lh_action_task, start_id)) { crm_free(order->lh_action_task); order->lh_action_task = started_key(group_data->self); } else if(safe_str_eq(order->lh_action_task, stop_id)) { crm_free(order->lh_action_task); order->lh_action_task = stopped_key(group_data->self); } crm_free(start_id); crm_free(stop_id); group_data->self->fns->rsc_order_lh(group_data->self, order); } void group_rsc_order_rh( action_t *lh_action, resource_t *rsc, order_constraint_t *order) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); crm_debug_3("Processing RH of ordering constraint %d", order->id); if(group_data->self == NULL) { return; } group_data->self->fns->rsc_order_rh(lh_action, group_data->self, order); } void group_rsc_location(resource_t *rsc, rsc_to_node_t *constraint) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); crm_debug_3("Processing actions from %s", group_data->self->id); group_data->self->fns->rsc_location(group_data->self, constraint); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, child_rsc->fns->rsc_location(child_rsc, constraint); ); } void group_expand(resource_t *rsc, pe_working_set_t *data_set) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); crm_debug_3("Processing actions from %s", group_data->self->id); group_data->self->fns->expand(group_data->self, data_set); if(group_data->self == NULL) { return; } slist_iter( child_rsc, resource_t, group_data->child_list, lpc, child_rsc->fns->expand(child_rsc, data_set); ); } gboolean group_active(resource_t *rsc, gboolean all) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, gboolean child_active = child_rsc->fns->active(child_rsc, all); if(all == FALSE && child_active) { return TRUE; } else if(child_active == FALSE) { return FALSE; } ); if(all) { return TRUE; } else { return FALSE; } } void group_print( resource_t *rsc, const char *pre_text, long options, void *print_data) { const char *child_text = NULL; group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); if(pre_text != NULL) { child_text = " "; } else { child_text = " "; } status_print("%sResource Group: %s\n", pre_text?pre_text:"", group_data->self->id); if(options & pe_print_html) { status_print("
    \n"); } slist_iter( child_rsc, resource_t, group_data->child_list, lpc, if(options & pe_print_html) { status_print("
  • \n"); } child_rsc->fns->print( child_rsc, child_text, options, print_data); if(options & pe_print_html) { status_print("
  • \n"); } ); if(options & pe_print_html) { status_print("
\n"); } } void group_free(resource_t *rsc) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); crm_debug_3("Freeing %s", group_data->self->id); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, crm_debug_3("Freeing child %s", child_rsc->id); child_rsc->fns->free(child_rsc); ); crm_debug_3("Freeing child list"); pe_free_shallow_adv(group_data->child_list, FALSE); free_xml(group_data->self->xml); if(group_data->self != NULL) { group_data->self->fns->free(group_data->self); } common_free(rsc); } void group_agent_constraints(resource_t *rsc) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, child_rsc->fns->agent_constraints(child_rsc); ); } enum rsc_role_e group_resource_state(resource_t *rsc) { enum rsc_role_e group_role = RSC_ROLE_UNKNOWN; group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, if(child_rsc->next_role > group_role) { group_role = rsc->next_role; } if(child_rsc->failed) { rsc->failed = TRUE; } ); return group_role; } void group_create_notify_element(resource_t *rsc, action_t *op, notify_data_t *n_data, pe_working_set_t *data_set) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, child_rsc->fns->create_notify_element( child_rsc, op, n_data, data_set); ); } gboolean group_create_probe(resource_t *rsc, node_t *node, action_t *complete, pe_working_set_t *data_set) { gboolean any_created = FALSE; group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, any_created = child_rsc->fns->create_probe( child_rsc, node, complete, data_set) || any_created; ); return any_created; } diff --git a/crm/pengine/native.c b/crm/pengine/native.c index a2bd892055..da34fa7fb7 100644 --- a/crm/pengine/native.c +++ b/crm/pengine/native.c @@ -1,1839 +1,1846 @@ -/* $Id: native.c,v 1.93 2005/10/13 12:18:48 andrew Exp $ */ +/* $Id: native.c,v 1.94 2005/10/17 10:57:11 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include extern color_t *add_color(resource_t *rh_resource, color_t *color); gboolean native_choose_color(resource_t *lh_resource, color_t *no_color); void native_update_node_weight(resource_t *rsc, rsc_to_node_t *cons, node_t *cons_node, GListPtr nodes); 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 filter_nodes(resource_t *rsc); int num_allowed_nodes4color(color_t *color); void create_notifications(resource_t *rsc, pe_working_set_t *data_set); void create_recurring_actions(resource_t *rsc, action_t *start, node_t *node, pe_working_set_t *data_set); void pe_pre_notify( resource_t *rsc, node_t *node, action_t *op, notify_data_t *n_data, 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 StopRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set); gboolean StartRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set); gboolean DemoteRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set); gboolean PromoteRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set); gboolean RoleError(resource_t *rsc, node_t *next, pe_working_set_t *data_set); gboolean NullOp(resource_t *rsc, node_t *next, pe_working_set_t *data_set); 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_UNKNOWN, }, /* 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*,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, RoleError, }, /* Slave */ { RoleError, StopRsc, RoleError, NullOp, PromoteRsc, }, /* Master */ { RoleError, RoleError, RoleError, DemoteRsc, NullOp, }, }; typedef struct native_variant_data_s { /* GListPtr allowed_nodes; /\* node_t* *\/ */ } native_variant_data_t; #define get_native_variant_data(data, rsc) \ CRM_ASSERT(rsc->variant == pe_native); \ CRM_ASSERT(rsc->variant_opaque != NULL); \ data = (native_variant_data_t *)rsc->variant_opaque; void native_add_running(resource_t *rsc, node_t *node, pe_working_set_t *data_set) { CRM_DEV_ASSERT(node != NULL); if(crm_assert_failed) { return; } slist_iter( a_node, node_t, rsc->running_on, lpc, CRM_DEV_ASSERT(a_node != NULL); if(safe_str_eq(a_node->details->id, node->details->id)) { return; } ); rsc->running_on = g_list_append(rsc->running_on, node); - node->details->running_rsc = g_list_append( - node->details->running_rsc, rsc); - - if(rsc->is_managed == FALSE) { + if(rsc->variant == pe_native) { + node->details->running_rsc = g_list_append( + node->details->running_rsc, rsc); + } + + if(rsc->variant != pe_native) { + } else if(rsc->is_managed == FALSE) { crm_info("resource %s isnt managed", rsc->id); rsc2node_new( "not_managed_default", rsc, INFINITY, node, data_set); return; } else if(rsc->stickiness > 0 || rsc->stickiness < 0) { rsc2node_new("stickiness", rsc, rsc->stickiness, node,data_set); crm_info("Resource %s: preferring current location (%s/%s)", rsc->id, node->details->uname, node->details->id); } - if(g_list_length(rsc->running_on) > 1) { + if(rsc->variant == pe_native && g_list_length(rsc->running_on) > 1) { pe_warn("Resource %s is (potentially) active on %d nodes." " Latest: %s/%s", rsc->id, g_list_length(rsc->running_on), node->details->uname, node->details->id); if(rsc->recovery_type == recovery_stop_only) { native_assign_color(rsc, data_set->no_color); } else if(rsc->recovery_type == recovery_block) { rsc->is_managed = FALSE; } } else { crm_debug_2("Resource %s is active on: %s", rsc->id, node->details->uname); } + if(rsc->parent != NULL) { + native_add_running(rsc->parent, node, data_set); + } + } void native_unpack(resource_t *rsc, pe_working_set_t *data_set) { native_variant_data_t *native_data = NULL; crm_debug_3("Processing resource %s...", rsc->id); crm_malloc0(native_data, sizeof(native_variant_data_t)); rsc->allowed_nodes = NULL; rsc->running_on = NULL; rsc->variant_opaque = native_data; } resource_t * native_find_child(resource_t *rsc, const char *id) { return NULL; } int native_num_allowed_nodes(resource_t *rsc) { int num_nodes = 0; if(rsc->color) { crm_debug_4("Colored case"); num_nodes = num_allowed_nodes4color(rsc->color); } else if(rsc->candidate_colors) { /* TODO: sort colors first */ color_t *color = g_list_nth_data(rsc->candidate_colors, 0); crm_debug_4("Candidate colors case"); num_nodes = num_allowed_nodes4color(color); } else { crm_debug_4("Default case"); slist_iter( this_node, node_t, rsc->allowed_nodes, lpc, crm_debug_3("Rsc %s Checking %s: %d", rsc->id, this_node->details->uname, this_node->weight); if(this_node->details->shutdown || this_node->details->online == FALSE) { this_node->weight = -INFINITY; } if(this_node->weight < 0) { continue; /* } else if(this_node->details->unclean) { */ /* continue; */ } num_nodes++; ); } crm_debug_2("Resource %s can run on %d nodes", rsc->id, num_nodes); return num_nodes; } int num_allowed_nodes4color(color_t *color) { int num_nodes = 0; if(color->details->pending == FALSE) { if(color->details->chosen_node) { return 1; } return 0; } slist_iter( this_node, node_t, color->details->candidate_nodes, lpc, crm_debug_3("Checking %s: %d", this_node->details->uname, this_node->weight); if(this_node->details->shutdown || this_node->details->online == FALSE) { this_node->weight = -INFINITY; } if(this_node->weight < 0) { continue; /* } else if(this_node->details->unclean) { */ /* continue; */ } num_nodes++; ); return num_nodes; } color_t * native_color(resource_t *rsc, pe_working_set_t *data_set) { color_t *new_color = NULL; if(rsc->provisional == FALSE) { return rsc->color; } else if( native_choose_color(rsc, data_set->no_color) ) { crm_debug_3("Colored resource %s with color %d", rsc->id, rsc->color->id); new_color = rsc->color; } else { if(rsc->allowed_nodes != NULL) { /* filter out nodes with a negative weight */ filter_nodes(rsc); new_color = create_color(data_set, rsc, rsc->allowed_nodes); native_assign_color(rsc, new_color); } if(new_color == NULL) { pe_warn("Resource %s cannot run anywhere", rsc->id); print_resource("ERROR: No color", rsc, FALSE); native_assign_color(rsc, data_set->no_color); new_color = data_set->no_color; } } rsc->provisional = FALSE; return new_color; } void create_recurring_actions(resource_t *rsc, action_t *start, node_t *node, pe_working_set_t *data_set) { char *key = NULL; const char *name = NULL; const char *value = NULL; const char *node_uname = NULL; int interval_ms = 0; action_t *mon = NULL; gboolean is_optional = TRUE; GListPtr possible_matches = NULL; crm_debug_2("Creating recurring actions for %s", rsc->id); if(node != NULL) { node_uname = node->details->uname; } xml_child_iter( rsc->ops_xml, operation, "op", name = crm_element_value(operation, "name"); value = crm_element_value(operation, "interval"); interval_ms = crm_get_msec(value); if(interval_ms <= 0) { continue; } value = crm_element_value(operation, "role"); if(start != NULL && value != NULL && text2role(value) != start->rsc->next_role) { crm_debug_2("Skipping action %s::%s(%s) : %s", start->rsc->id, name, value, role2text(start->rsc->next_role)); continue; } key = generate_op_key(rsc->id, name, interval_ms); possible_matches = find_actions(rsc->actions, key, node); if(start != NULL) { is_optional = start->optional; } else { is_optional = TRUE; } /* start a monitor for an already active resource */ if(possible_matches == NULL) { is_optional = FALSE; } mon = custom_action(rsc, key, name, node, is_optional, TRUE, data_set); if(start == NULL || start->runnable == FALSE) { crm_warn(" %s:\t(%s) (cancelled : start un-runnable)", mon->uuid, crm_str(node_uname)); mon->runnable = FALSE; } else if(node == NULL || node->details->online == FALSE || node->details->unclean) { crm_warn(" %s:\t(%s) (cancelled : no node available)", mon->uuid, crm_str(node_uname)); mon->runnable = FALSE; } else if(mon->optional == FALSE) { crm_info(" %s:\t(%s)", mon->uuid, crm_str(node_uname)); } custom_action_order(rsc, start_key(rsc), NULL, NULL, crm_strdup(key), mon, pe_ordering_manditory, data_set); ); } void native_create_actions(resource_t *rsc, pe_working_set_t *data_set) { action_t *start = NULL; node_t *chosen = NULL; enum rsc_role_e role = RSC_ROLE_UNKNOWN; enum rsc_role_e next_role = RSC_ROLE_UNKNOWN; if(rsc->color != NULL) { chosen = rsc->color->details->chosen_node; } unpack_instance_attributes( rsc->xml, XML_TAG_ATTR_SETS, chosen, rsc->parameters, NULL, 0, data_set); crm_info("%s: %s->%s", rsc->id, role2text(rsc->role), role2text(rsc->next_role)); if(g_list_length(rsc->running_on) > 1) { if(rsc->recovery_type == recovery_stop_start) { pe_err("Attempting recovery of resource %s", rsc->id); StopRsc(rsc, NULL, 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); slist_iter( action, action_t, possible_matches, lpc, action->optional = TRUE; /* action->pseudo = TRUE; */ ); crm_debug_2("Stopping a stopped resource"); crm_free(key); return; } role = rsc->role; while(role != rsc->next_role) { next_role = rsc_state_matrix[role][rsc->next_role]; crm_debug("Executing: %s->%s (%s)", role2text(role), role2text(next_role), rsc->id); if(rsc_action_matrix[role][next_role]( rsc, chosen, data_set) == FALSE) { break; } role = next_role; } if(rsc->next_role != RSC_ROLE_STOPPED && rsc->is_managed) { start = start_action(rsc, chosen, TRUE); create_recurring_actions(rsc, start, chosen, data_set); } } void native_internal_constraints(resource_t *rsc, pe_working_set_t *data_set) { order_restart(rsc); } 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->fns->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) { if(constraint->strength == pecs_ignore || constraint->strength == pecs_startstop){ crm_debug_4("Skipping constraint type %d", constraint->strength); return FALSE; } if(constraint->state_lh != NULL && text2role(constraint->state_lh) != rsc_lh->next_role) { crm_debug_4("RH: Skipping constraint: \"%s\" state filter", constraint->state_rh); return FALSE; } if(constraint->state_rh != NULL && text2role(constraint->state_rh) != rsc_rh->next_role) { crm_debug_4("RH: Skipping constraint: \"%s\" state filter", constraint->state_rh); return FALSE; } return TRUE; } void native_rsc_colocation_rh( resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) { gboolean do_check = FALSE; gboolean update_lh = FALSE; gboolean update_rh = FALSE; crm_debug_2("%sColocating %s with %s (%s)", constraint->strength == pecs_must?"":"Anti-", rsc_lh->id, rsc_rh->id, constraint->id); if(filter_colocation_constraint(rsc_lh, rsc_rh, constraint) == FALSE) { return; } if(rsc_lh->provisional && rsc_rh->provisional) { if(constraint->strength == pecs_must) { /* update effective_priorities */ crm_debug_3("Priority update"); native_rsc_colocation_rh_must( rsc_lh, update_lh, rsc_rh, update_rh); } else { /* nothing */ crm_debug_4( "Skipping constraint, both sides provisional"); } return; } else if( (!rsc_lh->provisional) && (!rsc_rh->provisional) && (!rsc_lh->color->details->pending) && (!rsc_rh->color->details->pending) ) { /* error check */ do_check = TRUE; if(rsc_lh->effective_priority < rsc_rh->effective_priority) { update_lh = TRUE; } else if(rsc_lh->effective_priority > rsc_rh->effective_priority) { update_rh = TRUE; } else { update_lh = TRUE; update_rh = TRUE; } } else if(rsc_lh->provisional == FALSE && rsc_lh->color->details->pending == FALSE) { /* update _them_ : postproc color version */ update_rh = TRUE; } else if(rsc_rh->provisional == FALSE && rsc_rh->color->details->pending == FALSE) { /* update _us_ : postproc color alt version */ update_lh = TRUE; } else if(rsc_lh->provisional == FALSE) { /* update _them_ : preproc version */ update_rh = TRUE; } else if(rsc_rh->provisional == FALSE) { /* update _us_ : postproc version */ update_lh = TRUE; } else { pe_warn("Un-expected combination of inputs"); return; } if(update_lh) { crm_debug_4("Updating LHS"); } if(update_rh) { crm_debug_4("Updating RHS"); } if(do_check) { if(native_constraint_violated( rsc_lh, rsc_rh, constraint) == FALSE) { crm_debug_4("Constraint satisfied"); return; } /* else constraint cant be satisified */ pe_warn("Constraint %s could not be satisfied", constraint->id); if(update_lh) { pe_warn("Marking resource %s unrunnable as a result", rsc_lh->id); rsc_lh->runnable = FALSE; } if(update_rh) { pe_warn("Marking resource %s unrunnable as a result", rsc_rh->id); rsc_rh->runnable = FALSE; } } if(constraint->strength == pecs_must) { native_rsc_colocation_rh_must( rsc_lh, update_lh, rsc_rh, update_rh); return; } else if(constraint->strength != pecs_must_not) { /* unknown type */ pe_err("Unknown constraint type %d", constraint->strength); return; } native_rsc_colocation_rh_mustnot(rsc_lh, update_lh,rsc_rh, update_rh); } void native_rsc_order_lh(resource_t *lh_rsc, order_constraint_t *order) { GListPtr lh_actions = NULL; action_t *lh_action = order->lh_action; crm_debug_3("Processing LH of ordering constraint %d", order->id); if(lh_action != NULL) { lh_actions = g_list_append(NULL, lh_action); } else if(lh_action == NULL && lh_rsc != NULL) { #if 0 /* this should be safe to remove */ if(order->strength == pecs_must) { crm_debug_4("No LH-Side (%s/%s) found for constraint..." " creating", lh_rsc->id, order->lh_action_task); pe_err("BROKEN CODE"); custom_action( lh_rsc, order->lh_action_task, NULL, NULL); } #endif lh_actions = find_actions( lh_rsc->actions, order->lh_action_task, NULL); if(lh_actions == NULL) { crm_debug_4("No LH-Side (%s/%s) found for constraint", lh_rsc->id, order->lh_action_task); if(order->rh_rsc != NULL) { crm_debug_4("RH-Side was: (%s/%s)", order->rh_rsc->id, order->rh_action_task); } else if(order->rh_action != NULL && order->rh_action->rsc != NULL) { crm_debug_4("RH-Side was: (%s/%s)", order->rh_action->rsc->id, order->rh_action_task); } else if(order->rh_action != NULL) { crm_debug_4("RH-Side was: %s", order->rh_action_task); } else { crm_debug_4("RH-Side was NULL"); } return; } } else { pe_warn("No LH-Side (%s) specified for constraint", order->lh_action_task); if(order->rh_rsc != NULL) { crm_debug_4("RH-Side was: (%s/%s)", order->rh_rsc->id, order->rh_action_task); } else if(order->rh_action != NULL && order->rh_action->rsc != NULL) { crm_debug_4("RH-Side was: (%s/%s)", order->rh_action->rsc->id, order->rh_action_task); } else if(order->rh_action != NULL) { crm_debug_4("RH-Side was: %s", order->rh_action_task); } else { crm_debug_4("RH-Side was NULL"); } return; } slist_iter( lh_action_iter, action_t, lh_actions, lpc, resource_t *rh_rsc = order->rh_rsc; if(rh_rsc == NULL && order->rh_action) { rh_rsc = order->rh_action->rsc; } if(rh_rsc) { rh_rsc->fns->rsc_order_rh( lh_action_iter, rh_rsc, order); } else if(order->rh_action) { order_actions(lh_action_iter, order->rh_action, order); } ); pe_free_shallow_adv(lh_actions, FALSE); } void native_rsc_order_rh( action_t *lh_action, resource_t *rsc, order_constraint_t *order) { GListPtr rh_actions = NULL; action_t *rh_action = order->rh_action; crm_debug_3("Processing RH of ordering constraint %d", order->id); if(rh_action != NULL) { rh_actions = g_list_append(NULL, rh_action); } else if(rh_action == NULL && rsc != NULL) { rh_actions = find_actions( rsc->actions, order->rh_action_task, NULL); if(rh_actions == NULL) { crm_debug_4("No RH-Side (%s/%s) found for constraint..." " ignoring", rsc->id, order->rh_action_task); crm_debug_4("LH-Side was: (%s/%s)", order->lh_rsc?order->lh_rsc->id:order->lh_action?order->lh_action->rsc->id:"", order->lh_action_task); return; } } else if(rh_action == NULL) { crm_debug_4("No RH-Side (%s) specified for constraint..." " ignoring", order->rh_action_task); crm_debug_4("LH-Side was: (%s/%s)", order->lh_rsc?order->lh_rsc->id:order->lh_action?order->lh_action->rsc->id:"", order->lh_action_task); return; } slist_iter( rh_action_iter, action_t, rh_actions, lpc, order_actions(lh_action, rh_action_iter, order); ); pe_free_shallow_adv(rh_actions, FALSE); } void native_rsc_location(resource_t *rsc, rsc_to_node_t *constraint) { GListPtr or_list; crm_debug("Applying %s (%s) to %s", constraint->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; } crm_action_debug_3(print_resource("before update", rsc,TRUE)); or_list = node_list_or( rsc->allowed_nodes, constraint->node_list_rh, FALSE); pe_free_shallow(rsc->allowed_nodes); rsc->allowed_nodes = or_list; slist_iter(node_rh, node_t, constraint->node_list_rh, lpc, native_update_node_weight(rsc, constraint, node_rh, rsc->allowed_nodes)); crm_action_debug_3(print_resource("after update", rsc, TRUE)); } void native_expand(resource_t *rsc, pe_working_set_t *data_set) { slist_iter( action, action_t, rsc->actions, lpc, crm_debug_4("processing action %d for rsc=%s", action->id, rsc->id); graph_element_from_action(action, data_set); ); } gboolean native_active(resource_t *rsc, gboolean all) { slist_iter( a_node, node_t, rsc->running_on, lpc, if(a_node->details->online == FALSE) { crm_debug("Resource %s: node %s is offline", rsc->id, a_node->details->uname); } else if(a_node->details->unclean) { crm_debug("Resource %s: node %s is unclean", rsc->id, a_node->details->uname); } else { crm_debug("Resource %s active on %s", rsc->id, a_node->details->uname); return TRUE; } ); return FALSE; } struct print_data_s { long options; void *print_data; }; static void native_print_attr(gpointer key, gpointer value, gpointer user_data) { long options = ((struct print_data_s*)user_data)->options; void *print_data = ((struct print_data_s*)user_data)->print_data; status_print("Option: %s = %s\n", (char*)key, (char*)value); } void native_print( resource_t *rsc, const char *pre_text, long options, void *print_data) { node_t *node = NULL; const char *prov = crm_element_value(rsc->xml,XML_AGENT_ATTR_PROVIDER); if(rsc->running_on != NULL) { node = rsc->running_on->data; } if(options & pe_print_html) { if(rsc->is_managed == FALSE) { status_print(""); } else if(rsc->failed) { status_print(""); } else if(rsc->variant == pe_native && g_list_length(rsc->running_on) == 0) { status_print(""); } else if(g_list_length(rsc->running_on) > 1) { status_print(""); } else { status_print(""); } } if(options & pe_print_rsconly) { const char *desc = NULL; desc = crm_element_value(rsc->xml, XML_ATTR_DESC); status_print("%s%s (%s%s%s:%s)%s%s", pre_text?pre_text:"", rsc->id, prov?prov:"", prov?"::":"", crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS), crm_element_value(rsc->xml, XML_ATTR_TYPE), desc?": ":"", desc?desc:""); } else { status_print("%s%s (%s%s%s:%s):\t%s", pre_text?pre_text:"", rsc->id, prov?prov:"", prov?"::":"", crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS), crm_element_value(rsc->xml, XML_ATTR_TYPE), (rsc->variant!=pe_native)?"":node==NULL?"NOT ACTIVE":node->details->uname); #if CURSES_ENABLED if(options & pe_print_ncurses) { move(-1, 0); } #endif } if(options & pe_print_html) { status_print(" "); } if(rsc->is_managed == FALSE) { status_print(" (unmanaged) "); } if((options & pe_print_rsconly) == 0) { } else if(g_list_length(rsc->running_on) > 1) { if(options & pe_print_html) { status_print("
    \n"); } else if((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print("["); } slist_iter(node, node_t, rsc->running_on, lpc, if(options & pe_print_html) { status_print("
  • \n"); } else if((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print(" "); } else if((options & pe_print_log)) { status_print("\t-"); } status_print("%s", node->details->uname); if(options & pe_print_html) { status_print("
  • \n"); } ); if(options & pe_print_html) { status_print("
\n"); } else if((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print(" ]"); } } if(options & pe_print_html) { status_print("
\n"); } else if((options & pe_print_printf) || (options & pe_print_ncurses)) { status_print("\n"); } if(options & pe_print_details) { struct print_data_s pdata; pdata.options = options; pdata.print_data = print_data; g_hash_table_foreach(rsc->parameters, native_print_attr, &pdata); } if(options & pe_print_dev) { status_print("%s\t(%s%svariant=%s, priority=%f)", pre_text, rsc->provisional?"provisional, ":"", rsc->runnable?"":"non-startable, ", crm_element_name(rsc->xml), (double)rsc->priority); status_print("%s\t%d candidate colors, %d allowed nodes," " %d rsc_cons", pre_text, g_list_length(rsc->candidate_colors), g_list_length(rsc->allowed_nodes), g_list_length(rsc->rsc_cons)); } if(options & pe_print_max_details) { status_print("%s\t=== Actions.\n", pre_text); slist_iter( action, action_t, rsc->actions, lpc, log_action(LOG_DEBUG_4, "\trsc action: ", action, FALSE); ); status_print("%s\t=== Colors\n", pre_text); slist_iter( color, color_t, rsc->candidate_colors, lpc, print_color("\t", color, FALSE) ); status_print("%s\t=== Allowed Nodes\n", pre_text); slist_iter( node, node_t, rsc->allowed_nodes, lpc, print_node("\t", node, FALSE); ); } } void native_free(resource_t *rsc) { crm_debug_4("Freeing Allowed Nodes"); crm_free(rsc->color); common_free(rsc); } void native_rsc_colocation_rh_must(resource_t *rsc_lh, gboolean update_lh, resource_t *rsc_rh, gboolean update_rh) { gboolean do_merge = FALSE; GListPtr old_list = NULL; GListPtr merged_node_list = NULL; int max_pri = rsc_lh->effective_priority; if(max_pri < rsc_rh->effective_priority) { max_pri = rsc_rh->effective_priority; } rsc_lh->effective_priority = max_pri; rsc_rh->effective_priority = max_pri; crm_debug_2("Colocating %s with %s." " Update LHS: %s, Update RHS: %s", rsc_lh->id, rsc_rh->id, update_lh?"true":"false", update_rh?"true":"false"); if(rsc_lh->color && rsc_rh->color) { do_merge = TRUE; merged_node_list = node_list_and( rsc_lh->color->details->candidate_nodes, rsc_rh->color->details->candidate_nodes, TRUE); } else if(rsc_lh->color) { do_merge = TRUE; merged_node_list = node_list_and( rsc_lh->color->details->candidate_nodes, rsc_rh->allowed_nodes, TRUE); } else if(rsc_rh->color) { do_merge = TRUE; merged_node_list = node_list_and( rsc_lh->allowed_nodes, rsc_rh->color->details->candidate_nodes, TRUE); } if(update_lh && rsc_rh != rsc_lh) { CRM_DEV_ASSERT(rsc_lh->color != rsc_rh->color); crm_free(rsc_lh->color); rsc_lh->runnable = rsc_rh->runnable; rsc_lh->provisional = rsc_rh->provisional; CRM_DEV_ASSERT(rsc_rh->color != NULL); native_assign_color(rsc_lh, rsc_rh->color); } if(update_rh && rsc_rh != rsc_lh) { CRM_DEV_ASSERT(rsc_lh->color != rsc_rh->color); crm_free(rsc_rh->color); rsc_rh->runnable = rsc_lh->runnable; rsc_rh->provisional = rsc_lh->provisional; CRM_DEV_ASSERT(rsc_lh->color != NULL); native_assign_color(rsc_rh, rsc_lh->color); } if((update_rh || update_lh) && do_merge) { crm_debug_4("Merging candidate nodes"); old_list = rsc_rh->color->details->candidate_nodes; rsc_rh->color->details->candidate_nodes = merged_node_list; pe_free_shallow(old_list); } crm_debug_4("Finished processing pecs_must constraint"); } void native_rsc_colocation_rh_mustnot(resource_t *rsc_lh, gboolean update_lh, resource_t *rsc_rh, gboolean update_rh) { color_t *color_lh = NULL; color_t *color_rh = NULL; crm_debug_4("Processing pecs_must_not constraint"); /* pecs_must_not */ if(update_lh) { color_rh = rsc_rh->color; if(rsc_lh->provisional && color_rh != NULL) { color_lh = add_color(rsc_lh, color_rh); color_lh->local_weight = -INFINITY; crm_debug_2("LH: Removed color %d from resource %s", color_lh->id, rsc_lh->id); crm_action_debug_3( print_color("Removed LH", color_lh, FALSE)); crm_action_debug_3( print_resource("Modified LH", rsc_lh, TRUE)); } else if(rsc_lh->provisional) { } else if(rsc_lh->color && rsc_lh->color->details->pending) { node_t *node_lh = NULL; color_lh = rsc_lh->color; node_lh = pe_find_node_id( color_lh->details->candidate_nodes, safe_val5(NULL, color_rh, details, chosen_node, details, id)); if(node_lh != NULL) { node_lh->weight = -INFINITY; crm_debug_2("LH: Removed node %s from color %d", node_lh->details->uname, color_lh->id); crm_action_debug_3( print_node("Removed LH", node_lh, FALSE)); crm_action_debug_3( print_color("Modified LH", color_lh, FALSE)); } } else { /* error, rsc marked as unrunnable above */ pe_warn("lh else"); } } if(update_rh) { color_lh = rsc_lh->color; if(rsc_rh->provisional && color_lh != NULL) { color_rh = add_color(rsc_lh, color_lh); color_rh->local_weight = -INFINITY; crm_debug_2("RH: Removed color %d from resource %s", color_rh->id, rsc_rh->id); crm_action_debug_3( print_color("Removed RH", color_rh, FALSE)); crm_action_debug_3( print_resource("Modified RH", rsc_rh, TRUE)); } else if(rsc_rh->provisional) { } else if(rsc_rh->color && rsc_rh->color->details->pending) { node_t *node_rh = NULL; color_rh = rsc_rh->color; node_rh = pe_find_node_id( color_rh->details->candidate_nodes, safe_val5(NULL, color_lh, details, chosen_node, details, id)); if(node_rh != NULL) { node_rh->weight = -INFINITY; crm_debug_2("RH: Removed node %s from color %d", node_rh->details->uname, color_rh->id); crm_action_debug_3( print_node("Removed RH", node_rh, FALSE)); crm_action_debug_3( print_color("Modified RH", color_rh, FALSE)); } } else { /* error, rsc marked as unrunnable above */ pe_warn("rh else"); } } } void native_agent_constraints(resource_t *rsc) { } gboolean native_choose_color(resource_t *rsc, color_t *no_color) { GListPtr sorted_colors = NULL; if(rsc->runnable == FALSE) { native_assign_color(rsc, no_color); } if(rsc->provisional == FALSE) { return !rsc->provisional; } sorted_colors = g_list_sort( rsc->candidate_colors, sort_color_weight); rsc->candidate_colors = sorted_colors; crm_debug("Choose a color from %d possibilities", g_list_length(sorted_colors)); slist_iter( this_color, color_t, rsc->candidate_colors, lpc, GListPtr intersection = NULL; GListPtr minus = NULL; int len = 0; if(this_color == NULL) { pe_err("color was NULL"); continue; } else if(this_color->local_weight < 0) { /* no valid color available */ crm_debug("no valid color available"); break; } else if(rsc->effective_priority < this_color->details->highest_priority) { minus = node_list_minus( this_color->details->candidate_nodes, rsc->allowed_nodes, TRUE); len = g_list_length(minus); pe_free_shallow(minus); } else { intersection = node_list_and( this_color->details->candidate_nodes, rsc->allowed_nodes, TRUE); len = g_list_length(intersection); pe_free_shallow(intersection); } if(len > 0) { crm_debug("Assigning color to %s", rsc->id); native_assign_color(rsc, this_color); break; } ); return !rsc->provisional; } void native_assign_color(resource_t *rsc, color_t *color) { color_t *local_color = add_color(rsc, color); GListPtr intersection = NULL; GListPtr old_list = NULL; rsc->provisional = FALSE; CRM_DEV_ASSERT(local_color != NULL); if (crm_assert_failed) { pe_err("local color was NULL"); return; } local_color->details->allocated_resources = g_list_append(local_color->details->allocated_resources,rsc); if(rsc->variant == pe_native) { (local_color->details->num_resources)++; rsc->color = copy_color(local_color); crm_debug_3("Created intersection for color %d", local_color->id); intersection = node_list_and( local_color->details->candidate_nodes, rsc->allowed_nodes, FALSE); old_list = local_color->details->candidate_nodes; pe_free_shallow(old_list); local_color->details->candidate_nodes = intersection; } crm_debug("Colored resource %s with color %d", rsc->id, local_color->id); crm_action_debug_3( print_resource("Colored Resource", rsc, TRUE)); return; } void native_update_node_weight(resource_t *rsc, rsc_to_node_t *cons, node_t *cons_node, GListPtr nodes) { node_t *node_rh = NULL; CRM_DEV_ASSERT(cons_node != NULL); node_rh = pe_find_node_id( rsc->allowed_nodes, cons_node->details->id); if(node_rh == NULL) { pe_err("Node not found - adding %s to %s", cons_node->details->id, rsc->id); node_rh = node_copy(cons_node); rsc->allowed_nodes = g_list_append( rsc->allowed_nodes, node_rh); node_rh = pe_find_node_id( rsc->allowed_nodes, cons_node->details->id); CRM_DEV_ASSERT(node_rh != NULL); return; } CRM_DEV_ASSERT(node_rh != NULL); if(node_rh == NULL) { pe_err("Node not found - cant update"); return; } if(node_rh->weight >= INFINITY && cons_node->weight <= -INFINITY) { pe_err("Constraint \"%s\" mixes +/- INFINITY (%s)", cons->id, rsc->id); } else if(node_rh->details->shutdown == TRUE || node_rh->details->online == FALSE || node_rh->details->unclean == TRUE) { } else if(node_rh->weight <= -INFINITY && cons_node->weight >= INFINITY) { pe_err("Constraint \"%s\" mixes +/- INFINITY (%s)", cons->id, rsc->id); } if(node_rh->fixed) { /* warning */ crm_debug_2("Constraint %s is irrelevant as the" " weight of node %s is fixed as %d (%s).", cons->id, node_rh->details->uname, node_rh->weight, rsc->id); return; } node_rh->weight = merge_weights(node_rh->weight, cons_node->weight); if(node_rh->weight <= -INFINITY) { crm_debug_3("Constraint %s (-INFINITY): node %s weight %d (%s).", cons->id, node_rh->details->uname, node_rh->weight, rsc->id); } else if(node_rh->weight >= INFINITY) { crm_debug_3("Constraint %s (+INFINITY): node %s weight %d (%s).", cons->id, node_rh->details->uname, node_rh->weight, rsc->id); } else { crm_debug_3("Constraint %s (%d): node %s weight %d (%s).", cons->id, cons_node->weight, node_rh->details->uname, node_rh->weight, rsc->id); } if(node_rh->weight < 0) { node_rh->fixed = TRUE; } crm_action_debug_3(print_node("Updated", node_rh, FALSE)); return; } gboolean native_constraint_violated( resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint) { GListPtr result = NULL; color_t *color_lh = NULL; color_t *color_rh = NULL; GListPtr candidate_nodes_lh = NULL; GListPtr candidate_nodes_rh = NULL; gboolean matched = FALSE; color_lh = rsc_lh->color; color_rh = rsc_rh->color; if(constraint->strength == pecs_must_not) { matched = TRUE; } if(rsc_lh->provisional || rsc_rh->provisional) { return FALSE; } if(color_lh->details->pending && color_rh->details->pending) { candidate_nodes_lh = color_lh->details->candidate_nodes; candidate_nodes_rh = color_rh->details->candidate_nodes; } else if(color_lh->details->pending == FALSE && color_rh->details->pending == FALSE) { if(color_lh == NULL && color_rh == NULL) { return matched; } else if(color_lh == NULL || color_rh == NULL) { return !matched; } else if(color_lh->details->chosen_node == NULL && color_rh->details->chosen_node == NULL) { return matched; } else if(color_lh->details->chosen_node == NULL || color_rh->details->chosen_node == NULL) { return !matched; } else if(safe_str_eq( color_lh->details->chosen_node->details->id, color_rh->details->chosen_node->details->id)) { return matched; } return !matched; } else if(color_lh->details->pending) { candidate_nodes_lh = color_lh->details->candidate_nodes; candidate_nodes_rh = g_list_append( NULL, color_rh->details->chosen_node); } else if(color_rh->details->pending) { candidate_nodes_rh = color_rh->details->candidate_nodes; candidate_nodes_lh = g_list_append( NULL, color_lh->details->chosen_node); } result = node_list_and(candidate_nodes_lh, candidate_nodes_rh, TRUE); if(g_list_length(result) == 0 && constraint->strength == pecs_must) { /* free result */ return TRUE; } return FALSE; } /* * Remove any nodes with a -ve weight */ void filter_nodes(resource_t *rsc) { crm_action_debug_3(print_resource("Filtering nodes for", rsc, FALSE)); slist_iter( node, node_t, rsc->allowed_nodes, lpc, if(node == NULL) { pe_err("Invalid NULL node"); } else if(node->weight < 0.0 || node->details->shutdown || node->details->online == FALSE || node->details->type == node_ping) { crm_action_debug_3(print_node("Removing", node, FALSE)); rsc->allowed_nodes = g_list_remove(rsc->allowed_nodes, node); crm_free(node); lpc = -1; /* restart the loop */ } ); } enum rsc_role_e native_resource_state(resource_t *rsc) { if(rsc->next_role != RSC_ROLE_UNKNOWN) { return rsc->next_role; } if(rsc->role != RSC_ROLE_UNKNOWN) { return rsc->role; } return RSC_ROLE_STOPPED; } void create_notifications(resource_t *rsc, pe_working_set_t *data_set) { if(rsc->notify == FALSE) { return; } /* slist_iter( */ /* action, action_t, rsc->actions, lpc, */ /* ); */ } static void register_activity(resource_t *rsc, enum action_tasks task, node_t *node, notify_data_t *n_data) { notify_entry_t *entry = NULL; crm_malloc0(entry, sizeof(notify_entry_t)); entry->rsc = rsc; entry->node = node; switch(task) { case start_rsc: n_data->start = g_list_append(n_data->start, entry); break; case stop_rsc: n_data->stop = g_list_append(n_data->stop, entry); break; case action_promote: n_data->promote = g_list_append(n_data->promote, entry); break; case action_demote: n_data->demote = g_list_append(n_data->demote, entry); break; default: crm_err("Unsupported notify action: %s", task2text(task)); break; } } static void register_state(resource_t *rsc, node_t *on_node, notify_data_t *n_data) { notify_entry_t *entry = NULL; crm_malloc0(entry, sizeof(notify_entry_t)); entry->rsc = rsc; entry->node = on_node; crm_err("%s state: %s", rsc->id, role2text(rsc->next_role)); switch(rsc->next_role) { case RSC_ROLE_STOPPED: /* n_data->inactive = g_list_append(n_data->inactive, entry); */ crm_free(entry); break; case RSC_ROLE_STARTED: n_data->active = g_list_append(n_data->active, entry); break; case RSC_ROLE_SLAVE: n_data->slave = g_list_append(n_data->slave, entry); break; case RSC_ROLE_MASTER: n_data->master = g_list_append(n_data->master, entry); break; default: crm_err("Unsupported notify role"); break; } } void native_create_notify_element(resource_t *rsc, action_t *op, notify_data_t *n_data, pe_working_set_t *data_set) { node_t *next_node = NULL; gboolean registered = FALSE; char *op_key = NULL; GListPtr possible_matches = NULL; enum action_tasks task = text2task(op->task); if(op->pre_notify == NULL || op->post_notify == NULL) { /* no notifications required */ crm_debug_4("No notificaitons required for %s", op->task); return; } next_node = rsc->color->details->chosen_node; op_key = generate_op_key(rsc->id, op->task, 0); possible_matches = find_actions(rsc->actions, op_key, NULL); crm_debug_2("Creating notificaitons for: %s (%s->%s)", op->uuid, role2text(rsc->role), role2text(rsc->next_role)); if(rsc->role == rsc->next_role) { register_state(rsc, next_node, n_data); } slist_iter( local_op, action_t, possible_matches, lpc, if(local_op->optional == FALSE) { registered = TRUE; register_activity(rsc, task, local_op->node, n_data); } ); /* stop / demote */ if(rsc->role != RSC_ROLE_STOPPED) { if(task == stop_rsc || task == action_demote) { slist_iter( current_node, node_t, rsc->running_on, lpc, pe_pre_notify(rsc, current_node, op, n_data, data_set); if(task == action_demote || registered == FALSE) { pe_post_notify(rsc, current_node, op, n_data, data_set); } ); } } /* start / promote */ if(rsc->next_role != RSC_ROLE_STOPPED) { CRM_DEV_ASSERT(next_node != NULL); if(task == start_rsc || task == action_promote) { if(task != start_rsc || registered == FALSE) { pe_pre_notify(rsc, next_node, op, n_data, data_set); } pe_post_notify(rsc, next_node, op, n_data, data_set); } } crm_free(op_key); pe_free_shallow_adv(possible_matches, FALSE); } static void dup_attr(gpointer key, gpointer value, gpointer user_data) { g_hash_table_replace(user_data, crm_strdup(key), crm_strdup(value)); } static void 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; action_wrapper_t *wrapper = NULL; const char *value = NULL; const char *task = NULL; if(op == NULL || confirm == NULL) { crm_debug_2("Op=%p confirm=%p", op, confirm); return; } CRM_DEV_ASSERT(node != NULL); value = g_hash_table_lookup(op->extra, "notify_type"); task = g_hash_table_lookup(op->extra, "notify_operation"); crm_debug_2("Creating actions for %s: %s (%s-%s)", op->uuid, rsc->id, value, task); key = generate_notify_key(rsc->id, value, task); trigger = custom_action(rsc, key, op->task, node, op->optional, TRUE, data_set); g_hash_table_foreach(op->extra, dup_attr, trigger->extra); trigger->notify_keys = n_data->keys; /* pseudo_notify before notify */ crm_debug_3("Ordering %s before %s (%d->%d)", op->uuid, trigger->uuid, trigger->id, op->id); crm_malloc0(wrapper, sizeof(action_wrapper_t)); wrapper->action = op; wrapper->type = pe_ordering_manditory; trigger->actions_before=g_list_append(trigger->actions_before, wrapper); wrapper = NULL; crm_malloc0(wrapper, sizeof(action_wrapper_t)); wrapper->action = trigger; wrapper->type = pe_ordering_manditory; op->actions_after = g_list_append(op->actions_after, wrapper); value = g_hash_table_lookup(op->extra, "notify_confirm"); if(crm_is_true(value)) { /* notify before pseudo_notified */ crm_debug_3("Ordering %s before %s (%d->%d)", trigger->uuid, confirm->uuid, confirm->id, trigger->id); wrapper = NULL; crm_malloc0(wrapper, sizeof(action_wrapper_t)); wrapper->action = trigger; wrapper->type = pe_ordering_manditory; confirm->actions_before = g_list_append( confirm->actions_before, wrapper); wrapper = NULL; crm_malloc0(wrapper, sizeof(action_wrapper_t)); wrapper->action = confirm; wrapper->type = pe_ordering_manditory; trigger->actions_after = g_list_append( trigger->actions_after, wrapper); } } void pe_pre_notify(resource_t *rsc, node_t *node, action_t *op, notify_data_t *n_data, pe_working_set_t *data_set) { crm_debug_2("%s: %s", rsc->id, op->uuid); pe_notify(rsc, node, op->pre_notify, op->pre_notified, n_data, 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) { crm_debug_2("%s: %s", rsc->id, op->uuid); pe_notify(rsc, node, op->post_notify, op->post_notified, n_data, data_set); } void NoRoleChange(resource_t *rsc, node_t *current, node_t *next, pe_working_set_t *data_set) { action_t *start = NULL; action_t *stop = NULL; action_t *delete = NULL; crm_debug("Executing: %s (role=%s)",rsc->id, role2text(rsc->next_role)); if(current == NULL || next == NULL) { return; } /* use StartRsc/StopRsc */ if(safe_str_neq(current->details->id, next->details->id)) { crm_info("Move resource %s\t(%s -> %s)", rsc->id, current->details->uname, next->details->uname); stop = stop_action(rsc, current, FALSE); start = start_action(rsc, next, FALSE); if(rsc->failed == FALSE && stop->runnable) { delete = delete_action(rsc, current); custom_action_order( rsc, NULL, stop, rsc, NULL, delete, pe_ordering_manditory, data_set); } } else { if(rsc->failed) { crm_info("Recover resource %s\t(%s)", rsc->id, next->details->uname); stop = stop_action(rsc, current, FALSE); start = start_action(rsc, next, FALSE); /* /\* make the restart required *\/ */ /* order_stop_start(rsc, rsc, pe_ordering_manditory); */ } else if(rsc->start_pending) { start = start_action(rsc, next, TRUE); if(start->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); stop->optional = start->optional; if(start->runnable == FALSE) { rsc->next_role = RSC_ROLE_STOPPED; } else if(start->optional) { crm_info("Leave resource %s\t(%s)", rsc->id, next->details->uname); } else { crm_info("Restart resource %s\t(%s)", rsc->id, next->details->uname); } } } } gboolean StopRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set) { action_t *stop = NULL; action_t *delete = NULL; crm_debug_2("Executing: %s", rsc->id); slist_iter( current, node_t, rsc->running_on, lpc, crm_info("Stop resource %s\t(%s)", rsc->id, current->details->uname); stop = stop_action(rsc, current, FALSE); if(rsc->failed == FALSE && stop->runnable) { char *probe = generate_op_key( rsc->id, CRMD_ACTION_STATUS, 0); delete = delete_action(rsc, current); custom_action_order( rsc, NULL, stop, rsc, NULL, delete, pe_ordering_manditory, data_set); custom_action_order( rsc, probe, NULL, rsc, NULL, delete, pe_ordering_manditory, data_set); } ); return TRUE; } gboolean StartRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set) { action_t *start = NULL; crm_debug_2("Executing: %s", rsc->id); start = start_action(rsc, next, TRUE); if(start->runnable) { crm_info("Start resource %s\t(%s)", rsc->id, next->details->uname); start->optional = FALSE; } return TRUE; } gboolean PromoteRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set) { crm_debug_2("Executing: %s", rsc->id); CRM_DEV_ASSERT(rsc->next_role == RSC_ROLE_MASTER); crm_info("Promote resource %s\t(%s)", rsc->id, next->details->uname); promote_action(rsc, next, FALSE); return TRUE; } gboolean DemoteRsc(resource_t *rsc, node_t *next, pe_working_set_t *data_set) { crm_debug_2("Executing: %s", rsc->id); CRM_DEV_ASSERT(rsc->next_role == RSC_ROLE_SLAVE); slist_iter( current, node_t, rsc->running_on, lpc, crm_info("Demote resource %s\t(%s)", rsc->id, current->details->uname); demote_action(rsc, current, FALSE); ); return TRUE; } gboolean RoleError(resource_t *rsc, node_t *next, pe_working_set_t *data_set) { crm_debug("Executing: %s", rsc->id); CRM_DEV_ASSERT(FALSE); return FALSE; } gboolean NullOp(resource_t *rsc, node_t *next, pe_working_set_t *data_set) { crm_debug("Executing: %s", rsc->id); return FALSE; } gboolean native_create_probe(resource_t *rsc, node_t *node, action_t *complete, pe_working_set_t *data_set) { char *key = NULL; char *target_rc = NULL; action_t *probe = NULL; node_t *running = pe_find_node_id(rsc->running_on, node->details->id); if(running != NULL) { /* we already know the status of the resource on this node */ return FALSE; } target_rc = crm_itoa(EXECRA_NOT_RUNNING); key = generate_op_key(rsc->id, CRMD_ACTION_STATUS, 0); probe = custom_action(rsc, key, CRMD_ACTION_STATUS, node, FALSE, TRUE, data_set); g_hash_table_insert(probe->extra, crm_strdup(XML_ATTR_TE_TARGET_RC), target_rc); g_hash_table_insert(probe->extra, crm_strdup(XML_ATTR_LRM_PROBE), crm_strdup(XML_BOOLEAN_TRUE)); custom_action_order(rsc, NULL, probe, rsc, NULL, complete, pe_ordering_manditory, data_set); return TRUE; }