diff --git a/crm/pengine/complex.c b/crm/pengine/complex.c index bd4adbcb4d..133c40d3eb 100644 --- a/crm/pengine/complex.c +++ b/crm/pengine/complex.c @@ -1,539 +1,541 @@ -/* $Id: complex.c,v 1.57 2005/09/01 11:41:20 andrew Exp $ */ +/* $Id: complex.c,v 1.58 2005/09/05 18:37:16 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include gboolean update_node_weight(rsc_to_node_t *cons,const char *id,GListPtr nodes); gboolean is_active(rsc_to_node_t *cons); gboolean constraint_violated( resource_t *rsc_lh, resource_t *rsc_rh, rsc_colocation_t *constraint); void order_actions(action_t *lh, action_t *rh, order_constraint_t *order); gboolean has_agent(node_t *a_node, lrm_agent_t *an_agent); extern gboolean rsc_colocation_new(const char *id, enum con_strength strength, resource_t *rsc_lh, resource_t *rsc_rh); extern rsc_to_node_t *rsc2node_new( const char *id, resource_t *rsc, double weight, node_t *node, pe_working_set_t *data_set); rsc_to_node_t *generate_location_rule( resource_t *rsc, crm_data_t *location_rule, pe_working_set_t *data_set); void populate_hash(crm_data_t *nvpair_list, GHashTable *hash, const char **attrs, int attrs_length); resource_object_functions_t resource_class_functions[] = { { native_unpack, native_find_child, native_num_allowed_nodes, native_color, native_create_actions, native_internal_constraints, native_agent_constraints, native_rsc_colocation_lh, native_rsc_colocation_rh, native_rsc_order_lh, native_rsc_order_rh, native_rsc_location, native_expand, native_dump, native_printw, native_html, native_active, native_resource_state, native_create_notify_element, native_free }, { group_unpack, group_find_child, group_num_allowed_nodes, group_color, group_create_actions, group_internal_constraints, group_agent_constraints, group_rsc_colocation_lh, group_rsc_colocation_rh, group_rsc_order_lh, group_rsc_order_rh, group_rsc_location, group_expand, group_dump, group_printw, group_html, group_active, group_resource_state, group_create_notify_element, group_free }, { clone_unpack, clone_find_child, clone_num_allowed_nodes, clone_color, clone_create_actions, clone_internal_constraints, clone_agent_constraints, clone_rsc_colocation_lh, clone_rsc_colocation_rh, clone_rsc_order_lh, clone_rsc_order_rh, clone_rsc_location, clone_expand, clone_dump, clone_printw, clone_html, clone_active, clone_resource_state, clone_create_notify_element, clone_free } }; /* resource_object_functions_t resource_variants[] = resource_class_functions; */ int get_resource_type(const char *name) { if(safe_str_eq(name, XML_CIB_TAG_RESOURCE)) { return pe_native; } else if(safe_str_eq(name, XML_CIB_TAG_GROUP)) { return pe_group; } else if(safe_str_eq(name, XML_CIB_TAG_INCARNATION)) { return pe_clone; } return pe_unknown; } gboolean is_active(rsc_to_node_t *cons) { /* todo: check constraint lifetime */ return TRUE; } static void dup_attr(gpointer key, gpointer value, gpointer user_data) { add_hash_param(user_data, key, value); } gboolean common_unpack(crm_data_t * xml_obj, resource_t **rsc, GHashTable *defaults, pe_working_set_t *data_set) { int lpc = 0; const char *id = crm_element_value(xml_obj, XML_ATTR_ID); const char *value = NULL; const char *allowed_attrs[] = { XML_CIB_ATTR_PRIORITY, XML_RSC_ATTR_INCARNATION_MAX, XML_RSC_ATTR_INCARNATION_NODEMAX, "resource_stickiness" }; const char *rsc_attrs[] = { XML_RSC_ATTR_STOPFAIL, XML_RSC_ATTR_RESTART, "resource_stickiness", "multiple_active", "start_prereq", "is_managed", "notify" }; crm_log_xml_debug_2(xml_obj, "Processing resource input..."); if(id == NULL) { pe_err("Must specify id tag in "); return FALSE; } else if(rsc == NULL) { pe_err("Nowhere to unpack resource into"); return FALSE; } crm_malloc0(*rsc, sizeof(resource_t)); if(*rsc == NULL) { return FALSE; } (*rsc)->id = id; (*rsc)->xml = xml_obj; (*rsc)->ops_xml = find_xml_node(xml_obj, "operations", FALSE); (*rsc)->variant = get_resource_type(crm_element_name(xml_obj)); if((*rsc)->variant == pe_unknown) { pe_err("Unknown resource type: %s", crm_element_name(xml_obj)); crm_free(*rsc); return FALSE; } (*rsc)->fns = &resource_class_functions[(*rsc)->variant]; crm_debug_3("Unpacking resource..."); (*rsc)->parameters = g_hash_table_new_full( g_str_hash,g_str_equal, g_hash_destroy_str,g_hash_destroy_str); for(lpc = 0; lpc < DIMOF(rsc_attrs); lpc++) { value = crm_element_value(xml_obj, rsc_attrs[lpc]); if(value != NULL) { add_hash_param( (*rsc)->parameters, rsc_attrs[lpc], value); } } unpack_instance_attributes( xml_obj, XML_TAG_ATTR_SETS, NULL, (*rsc)->parameters, allowed_attrs, DIMOF(allowed_attrs), data_set); if(defaults != NULL) { g_hash_table_foreach(defaults, dup_attr, (*rsc)->parameters); } (*rsc)->runnable = TRUE; (*rsc)->provisional = TRUE; (*rsc)->start_pending = FALSE; (*rsc)->starting = FALSE; (*rsc)->stopping = FALSE; (*rsc)->candidate_colors = NULL; (*rsc)->rsc_cons = NULL; (*rsc)->actions = NULL; (*rsc)->is_managed = TRUE; (*rsc)->recovery_type = recovery_stop_start; (*rsc)->stickiness = data_set->default_resource_stickiness; value = g_hash_table_lookup((*rsc)->parameters, XML_CIB_ATTR_PRIORITY); (*rsc)->priority = atoi(value?value:"0"); (*rsc)->effective_priority = (*rsc)->priority; value = g_hash_table_lookup((*rsc)->parameters, "notify"); (*rsc)->notify = crm_is_true(value); value = g_hash_table_lookup((*rsc)->parameters, "is_managed"); if(value != NULL && crm_is_true(value) == FALSE) { (*rsc)->is_managed = FALSE; crm_warn("Resource %s is currently not managed", (*rsc)->id); #if 0 rsc_to_node_t *new_con = NULL; /* prevent this resource from running anywhere */ new_con = rsc2node_new( "is_managed_default", *rsc, -INFINITY, NULL, data_set); new_con->node_list_rh = node_list_dup(data_set->nodes, FALSE); #endif } if((*rsc)->is_managed && data_set->symmetric_cluster) { rsc_to_node_t *new_con = rsc2node_new( "symmetric_default", *rsc, 0, NULL, data_set); new_con->node_list_rh = node_list_dup(data_set->nodes, FALSE); } crm_debug_2("Options for %s", id); value = g_hash_table_lookup((*rsc)->parameters, XML_RSC_ATTR_RESTART); if(safe_str_eq(value, "restart")) { (*rsc)->restart_type = pe_restart_restart; crm_debug_2("\tDependancy restart handling: restart"); } else { (*rsc)->restart_type = pe_restart_ignore; crm_debug_2("\tDependancy restart handling: ignore"); } value = g_hash_table_lookup((*rsc)->parameters, "multiple_active"); if(safe_str_eq(value, "stop_only")) { (*rsc)->recovery_type = recovery_stop_only; crm_debug_2("\tMultiple running resource recovery: stop only"); } else if(safe_str_eq(value, "block")) { (*rsc)->recovery_type = recovery_block; crm_debug_2("\tMultiple running resource recovery: block"); } else { (*rsc)->recovery_type = recovery_stop_start; crm_debug_2("\tMultiple running resource recovery: stop/start"); } value = g_hash_table_lookup((*rsc)->parameters, "resource_stickiness"); - (*rsc)->stickiness = char2score(value); + if(value != NULL) { + (*rsc)->stickiness = char2score(value); + } if((*rsc)->stickiness > 0) { crm_debug_2("\tPlacement: prefer current location%s", value == NULL?" (default)":""); } else if((*rsc)->stickiness < 0) { crm_warn("\tPlacement: always move from the current location%s", value == NULL?" (default)":""); } else { crm_debug_2("\tPlacement: optimal%s", value == NULL?" (default)":""); } crm_debug_2("\tNotification of start/stop actions: %s", (*rsc)->notify?"required":"not required"); (*rsc)->fns->unpack(*rsc, data_set); return TRUE; } void order_actions(action_t *lh_action, action_t *rh_action, order_constraint_t *order) { action_wrapper_t *wrapper = NULL; GListPtr list = NULL; crm_debug_2("Ordering %d: Action %d before %d", order?order->id:-1, lh_action->id, rh_action->id); log_action(LOG_DEBUG_4, "LH (order_actions)", lh_action, FALSE); log_action(LOG_DEBUG_4, "RH (order_actions)", rh_action, FALSE); crm_malloc0(wrapper, sizeof(action_wrapper_t)); if(wrapper != NULL) { wrapper->action = rh_action; wrapper->type = order->type; list = lh_action->actions_after; list = g_list_append(list, wrapper); lh_action->actions_after = list; wrapper = NULL; } if(order->type != pe_ordering_recover) { crm_malloc0(wrapper, sizeof(action_wrapper_t)); if(wrapper != NULL) { wrapper->action = lh_action; wrapper->type = order->type; list = rh_action->actions_before; list = g_list_append(list, wrapper); rh_action->actions_before = list; } } } void common_html(resource_t *rsc, const char *pre_text, FILE *stream) { const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); fprintf(stream, "%s%s (%s%s%s:%s):\t", 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)); } void common_printw(resource_t *rsc, const char *pre_text, int *index) { #if CURSES_ENABLED const char *prov = crm_element_value(rsc->xml, XML_AGENT_ATTR_PROVIDER); move(*index, 0); printw("%s%s (%s%s%s:%s):\t", 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)); #else crm_err("printw support requires ncurses to be available during configure"); #endif } void common_dump(resource_t *rsc, const char *pre_text, gboolean details) { crm_debug_4("%s%s%s%sResource %s: (variant=%s, priority=%f)", pre_text==NULL?"":pre_text, pre_text==NULL?"":": ", rsc->provisional?"Provisional ":"", rsc->runnable?"":"(Non-Startable) ", rsc->id, crm_element_name(rsc->xml), (double)rsc->priority); } void common_free(resource_t *rsc) { if(rsc == NULL) { return; } crm_debug_5("Freeing %s", rsc->id); while(rsc->rsc_cons) { pe_free_rsc_colocation( (rsc_colocation_t*)rsc->rsc_cons->data); rsc->rsc_cons = rsc->rsc_cons->next; } if(rsc->rsc_cons != NULL) { g_list_free(rsc->rsc_cons); } if(rsc->parameters != NULL) { g_hash_table_destroy(rsc->parameters); } pe_free_shallow_adv(rsc->candidate_colors, TRUE); crm_free(rsc->variant_opaque); crm_free(rsc); crm_debug_5("Resource freed"); } void unpack_instance_attributes( crm_data_t *xml_obj, const char *set_name, node_t *node, GHashTable *hash, const char **attrs, int attrs_length, pe_working_set_t *data_set) { crm_data_t *attributes = NULL; if(xml_obj == NULL) { crm_debug_4("No instance attributes"); return; } if(attrs != NULL && attrs[0] == NULL) { /* none allowed */ crm_debug_2("No instance attributes allowed"); return; } crm_debug_2("Checking for attributes"); xml_child_iter( xml_obj, attr_set, set_name, /* check any rules */ if(test_ruleset(attr_set, node, data_set) == FALSE) { continue; } crm_debug_2("Adding attributes"); attributes = cl_get_struct(attr_set, XML_TAG_ATTRS); if(attributes == NULL) { pe_err("%s with no %s child", set_name, XML_TAG_ATTRS); } else { populate_hash(attributes, hash, attrs, attrs_length); } ); } void populate_hash(crm_data_t *nvpair_list, GHashTable *hash, const char **attrs, int attrs_length) { int lpc = 0; gboolean set_attr = FALSE; const char *name = NULL; const char *value = NULL; xml_child_iter( nvpair_list, an_attr, XML_CIB_TAG_NVPAIR, name = crm_element_value(an_attr, XML_NVPAIR_ATTR_NAME); set_attr = TRUE; if(attrs != NULL) { set_attr = FALSE; } for(lpc = 0; set_attr == FALSE && lpc < attrs_length && attrs[lpc] != NULL; lpc++) { if(safe_str_eq(name, attrs[lpc])) { set_attr = TRUE; } } if(set_attr) { crm_debug_4("Setting attribute: %s", name); value = crm_element_value( an_attr, XML_NVPAIR_ATTR_VALUE); add_hash_param(hash, name, value); } else { crm_debug_4("Skipping attribute: %s", name); } ); } void add_rsc_param(resource_t *rsc, const char *name, const char *value) { CRM_DEV_ASSERT(rsc != NULL); if(crm_assert_failed) { return; } add_hash_param(rsc->parameters, name, value); } void add_hash_param(GHashTable *hash, const char *name, const char *value) { CRM_DEV_ASSERT(hash != NULL); if(crm_assert_failed) { return; } crm_debug_3("adding: name=%s value=%s", crm_str(name), crm_str(value)); if(name == NULL || value == NULL) { return; } else if(g_hash_table_lookup(hash, name) == NULL) { g_hash_table_insert(hash, crm_strdup(name), crm_strdup(value)); } } const char * get_rsc_param(resource_t *rsc, const char *name) { CRM_DEV_ASSERT(rsc != NULL); if(crm_assert_failed) { return NULL; } return g_hash_table_lookup(rsc->parameters, name); } void hash2nvpair(gpointer key, gpointer value, gpointer user_data) { const char *name = key; const char *s_value = value; crm_data_t *xml_node = user_data; crm_data_t *xml_child = create_xml_node(xml_node, XML_CIB_TAG_NVPAIR); crm_xml_add(xml_child, XML_NVPAIR_ATTR_NAME, name); crm_xml_add(xml_child, XML_NVPAIR_ATTR_VALUE, s_value); crm_debug_3("dumped: name=%s value=%s", name, s_value); } diff --git a/crm/pengine/group.c b/crm/pengine/group.c index 8f077ba59e..23c9acba7e 100644 --- a/crm/pengine/group.c +++ b/crm/pengine/group.c @@ -1,586 +1,587 @@ -/* $Id: group.c,v 1.36 2005/09/01 12:25:18 andrew Exp $ */ +/* $Id: group.c,v 1.37 2005/09/05 18:37:16 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); 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); 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)) { group_data->num_children++; group_data->child_list = g_list_append( group_data->child_list, new_rsc); group_data->last_child = 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); } - rsc_colocation_new("pe_group_internal_colo", pecs_must, - group_data->self, 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; if(rsc->variant == pe_group) { group_data = (group_variant_data_t *)rsc->variant_opaque; } else { pe_err("Resource %s was not a \"group\" variant", rsc->id); return NULL; } return pe_find_resource(group_data->child_list, id); } int group_num_allowed_nodes(resource_t *rsc) { group_variant_data_t *group_data = NULL; if(rsc->variant == pe_native) { group_data = (group_variant_data_t *)rsc->variant_opaque; } else { pe_err("Resource %s was not a \"native\" variant", rsc->id); return 0; } if(group_data->self == NULL) { return 0; } 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 = group_data->self->fns->color( - group_data->self, data_set); + group_color = group_data->first_child->fns->color( + 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, 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, 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); 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); } 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->self->fns->rsc_colocation_lh(group_data->self, rsc_rh, constraint); + 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->self->fns->rsc_colocation_rh(rsc_lh, group_data->self, constraint); + 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); if(group_data->self != NULL) { 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_printw(resource_t *rsc, const char *pre_text, int *index) { #if CURSES_ENABLED 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 = " "; } move(*index, 0); printw("Resource Group: %s\n", group_data->self->id); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, (*index)++; child_rsc->fns->printw(child_rsc, child_text, index); ); #else crm_err("printw support requires ncurses to be available during configure"); #endif } void group_html(resource_t *rsc, const char *pre_text, FILE *stream) { 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 = " "; } fprintf(stream, "Resource Group: %s\n", group_data->self->id); fprintf(stream, "
    \n"); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, fprintf(stream, "
  • \n"); child_rsc->fns->html(child_rsc, child_text, stream); fprintf(stream, "
  • \n"); ); fprintf(stream, "
\n"); } void group_dump(resource_t *rsc, const char *pre_text, gboolean details) { group_variant_data_t *group_data = NULL; get_group_variant_data(group_data, rsc); if(group_data->self == NULL) { return; } common_dump(rsc, pre_text, details); group_data->self->fns->dump(group_data->self, pre_text, details); slist_iter( child_rsc, resource_t, group_data->child_list, lpc, child_rsc->fns->dump(child_rsc, pre_text, details); ); } 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); ); } rsc_state_t group_resource_state(resource_t *rsc) { rsc_state_t state = rsc_state_unknown; rsc_state_t last_state = rsc_state_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, last_state = child_rsc->fns->state(child_rsc); switch(last_state) { case rsc_state_unknown: case rsc_state_move: return last_state; break; case rsc_state_restart: CRM_DEV_ASSERT(state != rsc_state_stopping); CRM_DEV_ASSERT(state != rsc_state_stopped); /* CRM_DEV_ASSERT(state != rsc_state_active); */ state = last_state; break; case rsc_state_active: /* CRM_DEV_ASSERT(state != rsc_state_restart); */ CRM_DEV_ASSERT(state != rsc_state_stopping); if(last_state == rsc_state_unknown) { state = last_state; } break; case rsc_state_stopped: CRM_DEV_ASSERT(state != rsc_state_restart); CRM_DEV_ASSERT(state != rsc_state_starting); if(last_state == rsc_state_unknown) { state = last_state; } break; case rsc_state_starting: CRM_DEV_ASSERT(state != rsc_state_stopped); if(state != rsc_state_restart) { state = last_state; } break; case rsc_state_stopping: CRM_DEV_ASSERT(state != rsc_state_active); if(state != rsc_state_restart) { state = last_state; } break; } ); return state; } 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); ); } diff --git a/crm/pengine/regression.sh b/crm/pengine/regression.sh index b8265cd81b..a48f956294 100755 --- a/crm/pengine/regression.sh +++ b/crm/pengine/regression.sh @@ -1,186 +1,187 @@ #!/bin/bash # Copyright (C) 2004 Andrew Beekhof # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This software is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # . regression.core.sh create_mode="true" echo Generating test outputs for these tests... #do_test bad7 -do_test inc8 "Clone anti-colocation" +#do_test simple8 "Stickiness" echo "" echo Done. echo "" echo Performing the following tests... create_mode="false" do_test 594 "Bugzilla 594" do_test 662 "Bugzilla 662" do_test 696 "Bugzilla 696" do_test 726 "Bugzilla 726" do_test 735 "Bugzilla 735" do_test 764 "Bugzilla 764" do_test 797 "Bugzilla 797" do_test 829 "Bugzilla 829" echo "" do_test date-1 "Dates" echo "" do_test simple1 "Offline " do_test simple2 "Start " do_test simple3 "Start 2 " do_test simple4 "Start Failed" do_test simple6 "Stop Start " do_test simple7 "Shutdown " #do_test simple8 "Stonith " #do_test simple9 "Lower version" #do_test simple10 "Higher version" do_test simple11 "Priority (ne)" do_test simple12 "Priority (eq)" +do_test simple8 "Stickiness" echo "" do_test rsc_dep1 "Must not " do_test rsc_dep3 "Must " do_test rsc_dep5 "Must not 3 " do_test rsc_dep7 "Must 3 " do_test rsc_dep10 "Must (but cant)" do_test rsc_dep2 "Must (running) " do_test rsc_dep8 "Must (running : alt) " do_test rsc_dep4 "Must (running + move)" echo "" do_test order1 "Order start 1 " do_test order2 "Order start 2 " do_test order3 "Order stop " do_test order4 "Order (multiple) " do_test order5 "Order (move) " do_test order6 "Order (move w/ restart) " #echo "" #do_test agent1 "version: lt (empty)" #do_test agent2 "version: eq " #do_test agent3 "version: gt " echo "" do_test attrs1 "string: eq (and) " do_test attrs2 "string: lt / gt (and)" do_test attrs3 "string: ne (or) " do_test attrs4 "string: exists " do_test attrs5 "string: not_exists " do_test attrs6 "is_dc: true " do_test attrs7 "is_dc: false " echo "" do_test mon-rsc-1 "Schedule Monitor - start" do_test mon-rsc-2 "Schedule Monitor - move " do_test mon-rsc-3 "Schedule Monitor - pending start " do_test mon-rsc-4 "Schedule Monitor - move/pending start" echo "" do_test rec-rsc-0 "Resource Recover - no start " do_test rec-rsc-1 "Resource Recover - start " do_test rec-rsc-2 "Resource Recover - monitor " do_test rec-rsc-3 "Resource Recover - stop - ignore" do_test rec-rsc-4 "Resource Recover - stop - block " do_test rec-rsc-5 "Resource Recover - stop - fence " do_test rec-rsc-6 "Resource Recover - multiple - restart" do_test rec-rsc-7 "Resource Recover - multiple - stop " do_test rec-rsc-8 "Resource Recover - multiple - block " echo "" do_test quorum-1 "No quorum - ignore" do_test quorum-2 "No quorum - freeze" do_test quorum-3 "No quorum - stop " do_test quorum-4 "No quorum - start anyway" do_test quorum-5 "No quorum - start anyway (group)" do_test quorum-6 "No quorum - start anyway (clone)" echo "" do_test rec-node-1 "Node Recover - Startup - no fence" do_test rec-node-2 "Node Recover - Startup - fence " do_test rec-node-3 "Node Recover - HA down - no fence" do_test rec-node-4 "Node Recover - HA down - fence " do_test rec-node-5 "Node Recover - CRM down - no fence" do_test rec-node-6 "Node Recover - CRM down - fence " do_test rec-node-7 "Node Recover - no quorum - ignore " do_test rec-node-8 "Node Recover - no quorum - freeze " do_test rec-node-9 "Node Recover - no quorum - stop " do_test rec-node-10 "Node Recover - no quorum - stop w/fence" echo "" do_test multi1 "Multiple Active (stop/start)" #echo "" #do_test complex1 "Complex " echo "" do_test group1 "Group " do_test group2 "Group + Native " do_test group3 "Group + Group " do_test group4 "Group + Native (nothing)" do_test group5 "Group + Native (move) " do_test group6 "Group + Group (move) " do_test group7 "Group colocation" do_test group8 "Group anti-colocation" echo "" do_test inc0 "Incarnation start " do_test inc1 "Incarnation start order " do_test inc2 "Incarnation silent restart, stop, move " do_test inc3 "Inter-incarnation ordering, silent restart, stop, move" do_test inc4 "Inter-incarnation ordering, silent restart, stop, move (ordered)" do_test inc5 "Inter-incarnation ordering, silent restart, stop, move (restart 1)" do_test inc6 "Inter-incarnation ordering, silent restart, stop, move (restart 2)" do_test inc7 "Clone colocation" do_test inc8 "Clone anti-colocation" echo "" do_test managed-0 "Managed (reference)" do_test managed-1 "Not managed - down " do_test managed-2 "Not managed - up " echo "" do_test interleave-0 "Interleave (reference)" do_test interleave-1 "coloc - not interleaved" do_test interleave-2 "coloc - interleaved " do_test interleave-3 "coloc - interleaved (2)" echo "" do_test notify-0 "Notify reference" do_test notify-1 "Notify simple" do_test notify-2 "Notify simple, confirm" do_test notify-3 "Notify move, confirm" #do_test notify-2 "Notify - 764" echo "" do_test bad1 "Bad node " do_test bad2 "Bad rsc " do_test bad3 "No rsc class " do_test bad4 "Bad data " do_test bad5 "Bad data " do_test bad6 "Bad lrm_rsc " echo "" test_results diff --git a/crm/pengine/testcases/simple8.dot b/crm/pengine/testcases/simple8.dot new file mode 100644 index 0000000000..a2ecaa813f --- /dev/null +++ b/crm/pengine/testcases/simple8.dot @@ -0,0 +1,33 @@ +digraph "g" { + size = "30,30" +"rsc3_stop_0" [ style="dashed" color="blue" fontcolor="black" ] +"rsc3_start_0" [ style="dashed" color="blue" fontcolor="black" ] +"rsc4_stop_0" [ style="dashed" color="blue" fontcolor="black" ] +"rsc4_start_0" [ style="dashed" color="blue" fontcolor="black" ] +"foo:rsc1_stop_0" [ style="dashed" color="blue" fontcolor="black" ] +"foo:rsc1_start_0" [ style="dashed" color="blue" fontcolor="black" ] +"foo_start_0" [ style="dashed" color="blue" fontcolor="orange" ] +"foo_running_0" [ style="dashed" color="blue" fontcolor="orange" ] +"foo_stop_0" [ style="dashed" color="blue" fontcolor="orange" ] +"foo_stopped_0" [ style="dashed" color="blue" fontcolor="orange" ] +"bar:rsc2_stop_0" [ style="dashed" color="blue" fontcolor="black" ] +"bar:rsc2_start_0" [ style="dashed" color="blue" fontcolor="black" ] +"bar_start_0" [ style="dashed" color="blue" fontcolor="orange" ] +"bar_running_0" [ style="dashed" color="blue" fontcolor="orange" ] +"bar_stop_0" [ style="dashed" color="blue" fontcolor="orange" ] +"bar_stopped_0" [ style="dashed" color="blue" fontcolor="orange" ] +"rsc3_stop_0" -> "rsc3_start_0" [ style = dashed] +"rsc4_stop_0" -> "rsc4_start_0" [ style = dashed] +"foo_stop_0" -> "foo:rsc1_stop_0" [ style = dashed] +"foo:rsc1_stop_0" -> "foo:rsc1_start_0" [ style = dashed] +"foo_start_0" -> "foo:rsc1_start_0" [ style = dashed] +"foo_stopped_0" -> "foo_start_0" [ style = dashed] +"foo:rsc1_start_0" -> "foo_running_0" [ style = dashed] +"foo:rsc1_stop_0" -> "foo_stopped_0" [ style = dashed] +"bar_stop_0" -> "bar:rsc2_stop_0" [ style = dashed] +"bar:rsc2_stop_0" -> "bar:rsc2_start_0" [ style = dashed] +"bar_start_0" -> "bar:rsc2_start_0" [ style = dashed] +"bar_stopped_0" -> "bar_start_0" [ style = dashed] +"bar:rsc2_start_0" -> "bar_running_0" [ style = dashed] +"bar:rsc2_stop_0" -> "bar_stopped_0" [ style = dashed] +} diff --git a/crm/pengine/testcases/simple8.exp b/crm/pengine/testcases/simple8.exp new file mode 100644 index 0000000000..e072f03e6a --- /dev/null +++ b/crm/pengine/testcases/simple8.exp @@ -0,0 +1,2 @@ + +