diff --git a/crm/pengine/pengine.c b/crm/pengine/pengine.c index f96d3d56d0..08b800d961 100755 --- a/crm/pengine/pengine.c +++ b/crm/pengine/pengine.c @@ -1,1045 +1,1093 @@ #include #include #include #include #include #include #include color_t *create_color(GSListPtr nodes); void add_color_to_rsc(resource_t *rsc, color_t *color); gint sort_rsc_priority(gconstpointer a, gconstpointer b); gint sort_cons_strength(gconstpointer a, gconstpointer b); gint sort_color_weight(gconstpointer a, gconstpointer b); gint sort_node_weight(gconstpointer a, gconstpointer b); gboolean unpack_constraints(xmlNodePtr constraints); gboolean unpack_resources(xmlNodePtr resources); gboolean unpack_nodes(xmlNodePtr nodes); gboolean unpack_status(xmlNodePtr status); gboolean apply_node_constraints(GSListPtr constraints, GSListPtr resources, GSListPtr nodes); void color_resource(resource_t *lh_resource, GSListPtr colors); gboolean is_active(rsc_constraint_t *cons); rsc_constraint_t *invert_constraint(rsc_constraint_t *constraint); gboolean filter_nodes(resource_t *rsc); color_t *find_color(GSListPtr candidate_colors, color_t *other_color); resource_t *pe_find_resource(GSListPtr rsc_list, const char *id_rh); node_t *pe_find_node(GSListPtr node_list, const char *id); gboolean choose_node_from_list(GSListPtr colors, color_t *color, GSListPtr nodes); rsc_constraint_t *copy_constraint(rsc_constraint_t *constraint); GSListPtr node_list_dup(GSListPtr list1); GSListPtr node_list_and(GSListPtr list1, GSListPtr list2); GSListPtr node_list_xor(GSListPtr list1, GSListPtr list2); GSListPtr node_list_minus(GSListPtr list1, GSListPtr list2); gboolean node_list_eq(GSListPtr list1, GSListPtr list2); node_t *node_copy(node_t *this_node) ; node_t *find_list_node(GSListPtr list, const char *id); gboolean unpack_rsc_to_attr(xmlNodePtr xml_obj); gboolean unpack_rsc_to_node(xmlNodePtr xml_obj); gboolean unpack_rsc_to_rsc (xmlNodePtr xml_obj); gboolean choose_color(resource_t *lh_resource, GSListPtr candidate_colors); gboolean strict_postproc(rsc_constraint_t *constraint, color_t *local_color, color_t *other_color); gboolean strict_preproc(rsc_constraint_t *constraint, color_t *local_color, color_t *other_color); gboolean update_node_weight(rsc_constraint_t *cons, node_t *node_rh); gboolean add_positive_preference(xmlNodePtr lrm_state); GSListPtr match_attrs(xmlNodePtr attr_exp, GSListPtr node_list); GSListPtr rsc_list = NULL; GSListPtr node_list = NULL; GSListPtr cons_list = NULL; GSListPtr colors = NULL; GSListPtr stonith_list = NULL; color_t *current_color = NULL; +gboolean pe_debug = FALSE; gboolean -stage1(xmlNodePtr cib) +stage0(xmlNodePtr cib) { xmlNodePtr cib_nodes = get_object_root("nodes", cib); xmlNodePtr cib_resources = get_object_root("resources", cib); xmlNodePtr cib_constraints = get_object_root("constraints", cib); xmlNodePtr cib_status = get_object_root("status", cib); unpack_nodes(cib_nodes->children); unpack_resources(cib_resources->children); - unpack_status(cib_status); + unpack_status(cib_status->children); unpack_constraints(cib_constraints->children); - apply_node_constraints(cons_list, node_list, rsc_list); - //filter_nodes(rsc_list); + return TRUE; +} + +gboolean +stage1(GSListPtr nodes) +{ + int lpc = 0; + // filter out unavailable nodes + slist_iter( + node, node_t, nodes, lpc, + if(node != NULL && node->weight < 0.0) { + pdebug(print_node("Removing", node)); + nodes = g_slist_remove(nodes, node); + } + ); + + node_list = nodes; + apply_node_constraints(cons_list, node_list, rsc_list); return TRUE; } void color_resource(resource_t *lh_resource, GSListPtr colors) { int lpc = 0; - print_resource("Coloring", lh_resource, FALSE); + pdebug(print_resource("Coloring", lh_resource, FALSE)); lh_resource->constraints = g_slist_sort(lh_resource->constraints, sort_cons_strength); - cl_log(LOG_DEBUG, "=== Pre-processing"); + pdebug(cl_log(LOG_DEBUG, "=== Pre-processing")); //------ Pre-processing for(; lpc < g_slist_length(lh_resource->constraints); lpc++) { color_t *other_color = NULL; color_t *local_color = NULL; rsc_constraint_t *constraint = (rsc_constraint_t*) g_slist_nth_data(lh_resource->constraints, lpc); - print_cons("Processing constraint", constraint, FALSE); + pdebug(print_cons("Processing constraint", constraint, FALSE)); if(constraint->is_placement == FALSE) { continue; } if(constraint->type != rsc_to_rsc) { continue; } if(constraint->rsc_rh == NULL) { cl_log(LOG_ERR, "rsc_rh was NULL for %s", constraint->id); continue; } other_color = constraint->rsc_rh->color; local_color = find_color(lh_resource->candidate_colors, other_color); strict_preproc(constraint, local_color, other_color); } // filter out nodes with a negative weight filter_nodes(lh_resource); /* Choose a color from the candidates or, * create a new one if no color is suitable * (this may need modification pending further napkin drawings) */ - print_resource("Choose...", lh_resource, FALSE); choose_color(lh_resource, lh_resource->candidate_colors); if(lh_resource->provisional) { // Create new color - cl_log(LOG_DEBUG, "Create a new color"); + pdebug(cl_log(LOG_DEBUG, "Create a new color")); current_color = create_color(lh_resource->allowed_nodes); lh_resource->color = current_color; lh_resource->provisional = FALSE; } - print_resource("Post-processing", lh_resource, FALSE); + pdebug(print_resource("Post-processing", lh_resource, FALSE)); //------ Post-processing for(lpc = 0; lpc < g_slist_length(lh_resource->constraints); lpc++) { - rsc_constraint_t *constraint = (rsc_constraint_t*)g_slist_nth_data(lh_resource->constraints, lpc); color_t *local_color = lh_resource->color; color_t *other_color = NULL; + rsc_constraint_t *constraint = (rsc_constraint_t*) + g_slist_nth_data(lh_resource->constraints, lpc); if(constraint->is_placement == FALSE) { continue; } else if(constraint->type != rsc_to_rsc) { continue; } other_color = find_color(constraint->rsc_rh->candidate_colors, local_color); strict_postproc(constraint, local_color, other_color); } - print_resource("Colored", lh_resource, FALSE); + pdebug(print_resource("Colored", lh_resource, FALSE)); } - gboolean stage2(GSListPtr sorted_rsc, GSListPtr sorted_nodes, GSListPtr operations) { int lpc = 0; // Set initial color // Set color.candidate_nodes = all active nodes - current_color = cl_malloc(sizeof(color_t)); - current_color = create_color(node_list); - + // Set resource.color = color (all resources) // Set resource.provisional = TRUE (all resources) - for(lpc = 0; lpc < g_slist_length(sorted_rsc); lpc++) { - resource_t *this_resource = (resource_t*)g_slist_nth_data(sorted_rsc, lpc); + slist_iter( + this_resource, resource_t, sorted_rsc, lpc, + this_resource->color = current_color; this_resource->provisional = TRUE; - } + ); - cl_log(LOG_DEBUG, "initialized resources to default color"); + pdebug(cl_log(LOG_DEBUG, "initialized resources to default color")); // Take (next) highest resource for(lpc = 0; lpc < g_slist_length(sorted_rsc); lpc++) { resource_t *lh_resource = (resource_t*)g_slist_nth_data(sorted_rsc, lpc); // if resource.provisional == FALSE, repeat if(lh_resource->provisional == FALSE) { // already processed this resource continue; } color_resource(lh_resource, colors); // next resource } return TRUE; } -#define color_n_nodes color_n->details->candidate_nodes -#define color_n_plus_1_nodes color_n_plus_1->details->candidate_nodes - gboolean stage3(GSListPtr colors) { - if(g_slist_length(colors) > g_slist_length(node_list)) - { + // not sure if this is a good ide aor not + if(g_slist_length(colors) > g_slist_length(node_list)) { + // we need to consolidate some + } else if(g_slist_length(colors) < g_slist_length(node_list)) { // we can create a few more } + + return TRUE; +} + +gboolean +stage5(GSListPtr resources) +{ + int lpc = 0; + slist_iter( + rsc, resource_t, resources, lpc, + if(safe_str_eq(rsc->cur_node_id, + rsc->color->details->chosen_node->id)){ + cl_log(LOG_DEBUG, + "No change for Resource %s (%s)", + rsc->id, + rsc->cur_node_id); + } else if(rsc->cur_node_id == NULL) { + cl_log(LOG_DEBUG, + "Starting Resource %s on %s", + rsc->id, + rsc->color->details->chosen_node->id); + } else { + cl_log(LOG_DEBUG, + "Moving Resource %s from %s to %s", + rsc->id, + rsc->cur_node_id, + rsc->color->details->chosen_node->id); + } + ); + + return TRUE; } +#define color_n_nodes color_n->details->candidate_nodes +#define color_n_plus_1_nodes color_n_plus_1->details->candidate_nodes gboolean stage4(GSListPtr colors) { int lpc = 0; color_t *color_n = NULL; color_t *color_n_plus_1 = NULL; for(lpc = 0; lpc < g_slist_length(colors); lpc++) { color_n = color_n_plus_1; color_n_plus_1 = (color_t*)g_slist_nth_data(colors, lpc); - print_color("Choose node for...", color_n, FALSE); + pdebug(print_color("Choose node for...", color_n, FALSE)); // print_color(color_n_plus_1, FALSE); if(color_n == NULL) { continue; } GSListPtr xor = node_list_xor(color_n_nodes, color_n_plus_1_nodes); GSListPtr minus = node_list_minus(color_n_nodes, color_n_plus_1_nodes); if(g_slist_length(xor) == 0 || g_slist_length(minus) == 0) { - cl_log(LOG_DEBUG, "Choose any node from our list"); + pdebug(cl_log(LOG_DEBUG, + "Choose any node from our list")); choose_node_from_list(colors, color_n, color_n_nodes); } else { - cl_log(LOG_DEBUG, "Choose a node not in n+1"); + pdebug(cl_log(LOG_DEBUG, "Choose a node not in n+1")); choose_node_from_list(colors, color_n, minus); } } // chose last color if(color_n_plus_1 != NULL) { - print_color("Choose node for last color...", color_n, FALSE); + pdebug(print_color("Choose node for last color...", + color_n_plus_1, + FALSE)); + choose_node_from_list(colors, color_n_plus_1, color_n_plus_1_nodes); } return TRUE; } gboolean choose_node_from_list(GSListPtr colors, color_t *color, GSListPtr nodes) { /* 1. Sort by weight 2. color.chosen_node = highest wieghted node 3. remove color.chosen_node from all other colors */ int lpc = 0; nodes = g_slist_sort(nodes, sort_node_weight); color->details->chosen_node = (node_t*)g_slist_nth_data(nodes, 0); if(color->details->chosen_node == NULL) { cl_log(LOG_ERR, "Could not allocate a node for color %d", color->id); return FALSE; } for(lpc = 0; lpc < g_slist_length(colors); lpc++) { color_t *color_n = (color_t*)g_slist_nth_data(colors, lpc); node_t *other_node = pe_find_node(color_n->details->candidate_nodes, color->details->chosen_node->id); color_n->details->candidate_nodes = g_slist_remove(color_n->details->candidate_nodes, other_node); } return TRUE; } gboolean unpack_nodes(xmlNodePtr nodes) { - cl_log(LOG_DEBUG, "Begining unpack... %s", __FUNCTION__); - cl_log(LOG_DEBUG, "Number of nodes... %d", g_slist_length(node_list)); + pdebug(cl_log(LOG_DEBUG, "Begining unpack... %s", __FUNCTION__)); int lpc = 1; while(nodes != NULL) { - cl_log(LOG_DEBUG, "Processing node..."); + pdebug(cl_log(LOG_DEBUG, "Processing node...")); xmlNodePtr xml_obj = nodes; xmlNodePtr attrs = xml_obj->children; if(attrs != NULL) attrs = attrs->children; const char *id = xmlGetProp(xml_obj, "id"); nodes = nodes->next; if(id == NULL) { cl_log(LOG_ERR, "Must specify id tag in "); continue; } node_t *new_node = cl_malloc(sizeof(node_t)); new_node->weight = 1.0 * lpc++; new_node->fixed = FALSE; new_node->id = cl_strdup(id); new_node->attrs = g_hash_table_new(g_str_hash, g_str_equal); while(attrs != NULL){ const char *name = xmlGetProp(attrs, "name"); const char *value = xmlGetProp(attrs, "value"); if(name != NULL && value != NULL) { g_hash_table_insert(new_node->attrs, cl_strdup(name), cl_strdup(value)); } attrs = attrs->next; } - cl_log(LOG_DEBUG, "Adding node id... %s (%p)", id, new_node); + pdebug(cl_log(LOG_DEBUG, "Adding node id... %s (%p)", + id, new_node)); - node_list = g_slist_append(node_list, new_node); - cl_log(LOG_DEBUG, "Number of nodes... %d", g_slist_length(node_list)); - + node_list = g_slist_append(node_list, new_node); } - cl_log(LOG_DEBUG, "Sorting nodes... %s", __FUNCTION__); node_list = g_slist_sort(node_list, sort_node_weight); return TRUE; } gboolean unpack_resources(xmlNodePtr resources) { - cl_log(LOG_DEBUG, "Begining unpack... %s", __FUNCTION__); + pdebug(cl_log(LOG_DEBUG, "Begining unpack... %s", __FUNCTION__)); while(resources != NULL) { xmlNodePtr xml_obj = resources; const char *id = xmlGetProp(xml_obj, "id"); const char *priority = xmlGetProp(xml_obj, "priority"); float priority_f = atof(priority); resources = resources->next; - cl_log(LOG_DEBUG, "Processing resource..."); + pdebug(cl_log(LOG_DEBUG, "Processing resource...")); if(id == NULL) { cl_log(LOG_ERR, "Must specify id tag in "); continue; } resource_t *new_rsc = cl_malloc(sizeof(resource_t)); new_rsc->xml = xml_obj; // copy first new_rsc->priority = priority_f; new_rsc->candidate_colors = NULL; new_rsc->color = NULL; new_rsc->provisional = TRUE; new_rsc->allowed_nodes = node_list_dup(node_list); new_rsc->constraints = NULL; new_rsc->id = cl_strdup(id); - cl_log(LOG_DEBUG, "Adding resource %s (%p)...", id, new_rsc); + pdebug(cl_log(LOG_DEBUG, "Adding resource %s (%p)...", + id, new_rsc)); rsc_list = g_slist_append(rsc_list, new_rsc); } rsc_list = g_slist_sort(rsc_list, sort_rsc_priority); return TRUE; } gboolean unpack_constraints(xmlNodePtr constraints) { - cl_log(LOG_DEBUG, "Begining unpack... %s", __FUNCTION__); + pdebug(cl_log(LOG_DEBUG, "Begining unpack... %s", __FUNCTION__)); while(constraints != NULL) { const char *id = xmlGetProp(constraints, "id"); xmlNodePtr xml_obj = constraints; constraints = constraints->next; if(id == NULL) { cl_log(LOG_ERR, "Constraint must have an id"); continue; } - cl_log(LOG_DEBUG, "Processing constraint %s %s", - xml_obj->name,id); + pdebug(cl_log(LOG_DEBUG, "Processing constraint %s %s", + xml_obj->name,id)); if(safe_str_eq("rsc_to_rsc", xml_obj->name)) { unpack_rsc_to_rsc(xml_obj); } else if(safe_str_eq("rsc_to_node", xml_obj->name)) { unpack_rsc_to_node(xml_obj); } else if(safe_str_eq("rsc_to_attr", xml_obj->name)) { unpack_rsc_to_attr(xml_obj); } else { cl_log(LOG_ERR, "Unsupported constraint type: %s", xml_obj->name); } } - int lpc = 0; - cl_log(LOG_INFO, "========= Constraints ========="); - slist_iter(resource, rsc_constraint_t, cons_list, lpc, - print_cons("", resource, FALSE)); - return TRUE; } gboolean apply_node_constraints(GSListPtr constraints, GSListPtr resources, GSListPtr nodes) { - cl_log(LOG_DEBUG, "Applying constraints... %s", __FUNCTION__); + pdebug(cl_log(LOG_DEBUG, "Applying constraints... %s", __FUNCTION__)); int lpc = 0; for(lpc = 0; lpc < g_slist_length(constraints); lpc++) { rsc_constraint_t *cons = (rsc_constraint_t *) g_slist_nth_data(constraints, lpc); - print_cons("Applying", cons, FALSE); + pdebug(print_cons("Applying", cons, FALSE)); // take "lifetime" into account if(cons == NULL) { cl_log(LOG_ERR, "Constraint (%d) is NULL", lpc); continue; } else if(is_active(cons) == FALSE) { cl_log(LOG_INFO, "Constraint (%d) is not active", lpc); // warning continue; } resource_t *rsc_lh = cons->rsc_lh; if(rsc_lh == NULL) { cl_log(LOG_ERR, "LHS of rsc_to_node (%s) is NULL", cons->id); continue; } GSListPtr rsc_cons_list = cons->rsc_lh->constraints; rsc_lh->constraints = g_slist_append(rsc_cons_list, cons); if(cons->type == rsc_to_rsc) { // nothing - cl_log(LOG_DEBUG, "nothing to do"); + pdebug(cl_log(LOG_DEBUG, "nothing to do")); continue; } else if(cons->type == rsc_to_node || cons->type == rsc_to_attr) { if(cons->node_list_rh == NULL) { cl_log(LOG_ERR, "RHS of rsc_to_node (%s) is NULL", cons->id); continue; } else { int llpc = 0; slist_iter(node_rh, node_t, cons->node_list_rh, llpc, update_node_weight(cons, node_rh)); } /* dont add it to the resource, * the information is in the resouce's node list */ } else { // error } } return TRUE; } // remove nodes that are down, stopping // create +ve rsc_to_node constraints between resources and the nodes they are running on // anything else? gboolean unpack_status(xmlNodePtr status) { - cl_log(LOG_DEBUG, "Begining unpack... %s", __FUNCTION__); - + pdebug(cl_log(LOG_DEBUG, "Begining unpack of %s... %s", status->name, __FUNCTION__)); while(status != NULL) { const char *id = xmlGetProp(status, "id"); const char *state = xmlGetProp(status, "state"); const char *exp_state = xmlGetProp(status, "exp_state"); xmlNodePtr lrm_state = find_xml_node(status, "lrm"); xmlNodePtr attrs = find_xml_node(status, "attributes"); - lrm_state = find_xml_node(lrm_state, "lrm_resource"); + lrm_state = find_xml_node(lrm_state, "lrm_resources"); lrm_state = find_xml_node(lrm_state, "rsc_state"); status = status->next; - cl_log(LOG_DEBUG, "Processing node %s", id); + pdebug(cl_log(LOG_DEBUG, "Processing node %s", id)); if(id == NULL){ // error continue; } - cl_log(LOG_DEBUG, "Processing node attrs"); + pdebug(cl_log(LOG_DEBUG, "Processing node attrs")); node_t *this_node = pe_find_node(node_list, id); while(attrs != NULL){ const char *name = xmlGetProp(attrs, "name"); const char *value = xmlGetProp(attrs, "value"); - cl_log(LOG_DEBUG, "Adding %s => %s", - name, value); + pdebug(cl_log(LOG_DEBUG, "Adding %s => %s", + name, value)); if(name != NULL && value != NULL) { g_hash_table_insert(this_node->attrs, cl_strdup(name), cl_strdup(value)); } attrs = attrs->next; } - cl_log(LOG_DEBUG, "Processing node lrm state"); + pdebug(cl_log(LOG_DEBUG, "Processing node lrm state")); if(safe_str_eq(exp_state, "active") && safe_str_eq(state, "active")) { // process resource, make +ve preference add_positive_preference(lrm_state); - } else if(0) { + } else { + pdebug(cl_log(LOG_DEBUG, "remove %s", __FUNCTION__)); // remove node from contention - node_t *node = NULL; - int lpc = 0; - for(; lpc < g_slist_length(node_list); lpc++) { - node_t *node = (node_t*)g_slist_nth_data(node_list, lpc); - if(safe_str_eq(node->id, id)){ - node->weight = -1; - node->fixed = TRUE; - } - } - + this_node->weight = -1; + this_node->fixed = TRUE; + + pdebug(cl_log(LOG_DEBUG, "state %s, expected %s", + state, exp_state)); + if(safe_str_eq(exp_state, "down") && safe_str_eq(state, "shutdown")){ // create shutdown req } else if(safe_str_eq(exp_state, "active") && safe_str_neq(state, "active")) { - // create stonith - // mark unclean + // mark unclean in the xml + state = "unclean"; + // remove any running resources from being allocated } if(safe_str_eq(state, "unclean")) { - stonith_list = g_slist_append(stonith_list, node); + stonith_list = g_slist_append(stonith_list, node_copy(this_node)); } - } - } cons_list = g_slist_sort(cons_list, sort_cons_strength); return TRUE; } gboolean is_active(rsc_constraint_t *cons) { return TRUE; } gboolean strict_preproc(rsc_constraint_t *constraint, color_t *local_color, color_t *other_color) { resource_t * lh_resource = constraint->rsc_lh; switch(constraint->strength) { case must: /// not yet... break; // x * should * should_not = x case should: if(constraint->rsc_rh->provisional == FALSE) { local_color->local_weight = local_color->local_weight * 2.0; } break; case should_not: if(constraint->rsc_rh->provisional == FALSE) { local_color->local_weight = local_color->local_weight * 0.5; } - if(g_slist_length(lh_resource->candidate_colors)==1) { + if(g_slist_length(colors) < g_slist_length(node_list) +// && g_slist_length(lh_resource->candidate_colors)==1 + ) { +// create_color(lh_resource->allowed_nodes); +// } else if(g_slist_length(lh_resource->candidate_colors)==1) { create_color(lh_resource->allowed_nodes); - } + } + break; case must_not: if(constraint->rsc_rh->provisional == FALSE) { lh_resource->candidate_colors = g_slist_remove( lh_resource->candidate_colors, local_color); } break; default: // error break; } return TRUE; } gboolean strict_postproc(rsc_constraint_t *constraint, color_t *local_color, color_t *other_color) { switch(constraint->strength) { case must: if(constraint->rsc_rh->provisional == TRUE) { constraint->rsc_rh->color = other_color; constraint->rsc_rh->provisional = FALSE; color_resource(constraint->rsc_rh, colors); } // else check for error break; case should: break; case should_not: break; case must_not: if(constraint->rsc_rh->provisional == TRUE) { // check for error } break; default: // error break; } return TRUE; } gboolean choose_color(resource_t *lh_resource, GSListPtr candidate_colors) { int lpc = 0; GSListPtr sorted_colors = g_slist_sort(candidate_colors, sort_color_weight); lh_resource->candidate_colors = sorted_colors; - cl_log(LOG_DEBUG, - "Choose a color from %d possibilities", - g_slist_length(sorted_colors)); + pdebug(cl_log(LOG_DEBUG, + "Choose a color from %d possibilities", + g_slist_length(sorted_colors))); for(lpc = 0; lh_resource->provisional && lpc < g_slist_length(sorted_colors); lpc++) { color_t *this_color = (color_t*) g_slist_nth_data(sorted_colors, lpc); GSListPtr intersection = node_list_and(this_color->details->candidate_nodes, lh_resource->allowed_nodes); if(g_slist_length(intersection) != 0) { // TODO: merge node weights g_slist_free(this_color->details->candidate_nodes); this_color->details->candidate_nodes = intersection; lh_resource->color = this_color; lh_resource->provisional = FALSE; } } return !lh_resource->provisional; } gboolean unpack_rsc_to_node(xmlNodePtr xml_obj) { xmlNodePtr node_ref = xml_obj->children; rsc_constraint_t *new_con = cl_malloc(sizeof(rsc_constraint_t)); const char *id_lh = xmlGetProp(xml_obj, "from"); const char *id = xmlGetProp(xml_obj, "id"); const char *mod = xmlGetProp(xml_obj, "modifier"); const char *weight = xmlGetProp(xml_obj, "weight"); float weight_f = atof(weight); resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh); if(rsc_lh == NULL) { cl_log(LOG_ERR, "No resource (con=%s, rsc=%s)", id, id_lh); } new_con->id = cl_strdup(id); new_con->rsc_lh = rsc_lh; new_con->type = rsc_to_node; new_con->rsc_rh = NULL; new_con->weight = weight_f; if(safe_str_eq(mod, "set")){ new_con->modifier = set; } else if(safe_str_eq(mod, "inc")){ new_con->modifier = inc; } else if(safe_str_eq(mod, "dec")){ new_con->modifier = dec; } else { // error } /* */ // while(node_ref != NULL) { const char *id_rh = xmlGetProp(node_ref, "name"); node_t *node_rh = pe_find_node(node_list, id_rh); if(node_rh == NULL) { // error cl_log(LOG_ERR, "node %s (from %s) not found", id_rh, node_ref->name); continue; } new_con->node_list_rh = g_slist_append(new_con->node_list_rh, node_rh); /* dont add it to the resource, * the information is in the resouce's node list */ node_ref = node_ref->next; } cons_list = g_slist_append(cons_list, new_con); return TRUE; } gboolean unpack_rsc_to_attr(xmlNodePtr xml_obj) { /* Translation: give any node a +ve weight of 20.0 to run rsc2 if: attr "cpu" is set _and_ "kernel"="2.6", _or_ attr "hdd" is set _and_ "kernel"="2.4" Further translation: 2 constraints that give any node a +ve weight of 20.0 to run rsc2 cons1: attr "cpu" is set and "kernel"="2.6" cons2: attr "hdd" is set and "kernel"="2.4" */ xmlNodePtr attr_exp = xml_obj->children; const char *id_lh = xmlGetProp(xml_obj, "from"); const char *mod = xmlGetProp(xml_obj, "modifier"); const char *weight = xmlGetProp(xml_obj, "weight"); const char *id = xmlGetProp(attr_exp, "id"); float weight_f = atof(weight); enum con_modifier a_modifier = modifier_none; resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh); if(rsc_lh == NULL) { cl_log(LOG_ERR, "No resource (con=%s, rsc=%s)", id, id_lh); return FALSE; } if(safe_str_eq(mod, "set")){ a_modifier = set; } else if(safe_str_eq(mod, "inc")){ a_modifier = inc; } else if(safe_str_eq(mod, "dec")){ a_modifier = dec; } else { // error } if(attr_exp == NULL) { cl_log(LOG_WARNING, "no attrs for constraint %s", id); } while(attr_exp != NULL) { const char *id_rh = xmlGetProp(attr_exp, "name"); const char *id = xmlGetProp(attr_exp, "id"); rsc_constraint_t *new_con = cl_malloc(sizeof(rsc_constraint_t)); new_con->id = cl_strdup(id); new_con->rsc_lh = rsc_lh; new_con->type = rsc_to_attr; new_con->rsc_rh = NULL; new_con->weight = weight_f; new_con->modifier = a_modifier; new_con->node_list_rh = match_attrs(attr_exp, node_list); if(new_con->node_list_rh == NULL) { // error cl_log(LOG_ERR, "node %s (from %s) not found", id_rh, attr_exp->name); } - print_cons("Added", new_con, FALSE); + pdebug(print_cons("Added", new_con, FALSE)); cons_list = g_slist_append(cons_list, new_con); /* dont add it to the resource, * the information is in the resouce's node list */ attr_exp = attr_exp->next; } return TRUE; } gboolean update_node_weight(rsc_constraint_t *cons, node_t *node) { node_t *node_rh = pe_find_node(cons->rsc_lh->allowed_nodes, node->id); if(node_rh == NULL) { node_t *node_tmp = pe_find_node(node_list, node->id); node_rh = node_copy(node_tmp); cons->rsc_lh->allowed_nodes = g_slist_append(cons->rsc_lh->allowed_nodes, node_rh); } if(node_rh == NULL) { // error return FALSE; } if(node_rh->fixed) { // warning cl_log(LOG_WARNING, "Constraint %s is irrelevant as the" " weight of node %s is fixed as %f.", cons->id, node_rh->id, node_rh->weight); return TRUE; } - cl_log(LOG_DEBUG, - "Constraint %s: node %s weight %s %f.", - cons->id, - node_rh->id, - modifier2text(cons->modifier), - node_rh->weight); + pdebug(cl_log(LOG_DEBUG, + "Constraint %s: node %s weight %s %f.", + cons->id, + node_rh->id, + modifier2text(cons->modifier), + node_rh->weight)); switch(cons->modifier) { case set: node_rh->weight = cons->weight; node_rh->fixed = TRUE; break; case inc: node_rh->weight += cons->weight; break; case dec: node_rh->weight -= cons->weight; break; case modifier_none: // warning break; } return TRUE; } gboolean add_positive_preference(xmlNodePtr lrm_state) { + pdebug(cl_log(LOG_DEBUG, "here %s", __FUNCTION__)); + while(lrm_state != NULL) { const char *rsc_id = xmlGetProp(lrm_state, "rsc_id"); const char *node_id = xmlGetProp(lrm_state, "node_id"); const char *rsc_state = xmlGetProp(lrm_state, "rsc_state"); if((safe_str_eq(rsc_state, "starting")) || (safe_str_eq(rsc_state, "started"))) { node_t *node_rh; rsc_constraint_t *new_cons = cl_malloc(sizeof(rsc_constraint_t)); new_cons->id = cl_strdup(""); // genereate one new_cons->type = rsc_to_node; new_cons->weight = 100.0; new_cons->modifier = inc; new_cons->rsc_lh = pe_find_resource(rsc_list, rsc_id); node_rh = pe_find_node(node_list, node_id); new_cons->node_list_rh = g_slist_append(NULL, node_rh); - cons_list = g_slist_append(cons_list, new_cons); - + pdebug(print_cons("Added", new_cons, FALSE)); + + new_cons->rsc_lh->cur_node_id = cl_strdup(node_id); + } else if(safe_str_eq(rsc_state, "stop_fail")) { // do soemthing } // else no preference lrm_state = lrm_state->next; } return TRUE; } GSListPtr match_attrs(xmlNodePtr attr_exp, GSListPtr node_list) { int lpc = 0; GSListPtr result = NULL; slist_iter( node, node_t, node_list, lpc, xmlNodePtr node_match = attr_exp->children; gboolean accept = TRUE; while(accept && node_match != NULL) { const char *type =xmlGetProp(node_match, "type"); const char *value=xmlGetProp(node_match, "value"); const char *name =xmlGetProp(node_match, "target"); node_match = node_match->next; if(name == NULL || type == NULL) { // error continue; } const char *h_val = (const char*) g_hash_table_lookup(node->attrs, name); if(h_val != NULL && safe_str_eq(type, "has_attr")){ accept = TRUE; } else if(h_val == NULL && safe_str_eq(type, "not_attr")) { accept = TRUE; } else if(h_val != NULL && safe_str_eq(type, "attr_value") && safe_str_eq(h_val, value)) { accept = TRUE; } else { accept = FALSE; } } if(accept) { result = g_slist_append(result, node); } ); return result; } gboolean unpack_rsc_to_rsc(xmlNodePtr xml_obj) { rsc_constraint_t *new_con = cl_malloc(sizeof(rsc_constraint_t)); rsc_constraint_t *inverted_con = NULL; const char *id_lh = xmlGetProp(xml_obj, "from"); const char *id = xmlGetProp(xml_obj, "id"); resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh); if(rsc_lh == NULL) { cl_log(LOG_ERR, "No resource (con=%s, rsc=%s)", id, id_lh); return FALSE; } new_con->id = cl_strdup(id); new_con->rsc_lh = rsc_lh; new_con->type = rsc_to_rsc; const char *strength = xmlGetProp(xml_obj, "strength"); if(safe_str_eq(strength, "must")) { new_con->strength = must; } else if(safe_str_eq(strength, "should")) { new_con->strength = should; } else if(safe_str_eq(strength, "should_not")) { new_con->strength = should_not; } else if(safe_str_eq(strength, "must_not")) { new_con->strength = must_not; } else { // error } const char *type = xmlGetProp(xml_obj, "type"); if(safe_str_eq(type, "ordering")) { new_con->is_placement = FALSE; } else if (safe_str_eq(type, "placement")) { new_con->is_placement = TRUE; } else { // error } new_con->node_list_rh = NULL; const char *id_rh = xmlGetProp(xml_obj, "to"); resource_t *rsc_rh = pe_find_resource(rsc_list, id_rh); if(rsc_rh == NULL) { cl_log(LOG_ERR, "No rh resource found with id %s", id_rh); return FALSE; } new_con->rsc_rh = rsc_rh; inverted_con = invert_constraint(new_con); cons_list = g_slist_insert_sorted(cons_list, inverted_con, sort_cons_strength); cons_list = g_slist_insert_sorted(cons_list, new_con, sort_cons_strength); return TRUE; } diff --git a/crm/pengine/pengine.h b/crm/pengine/pengine.h index 6628aeee57..ede0b65999 100644 --- a/crm/pengine/pengine.h +++ b/crm/pengine/pengine.h @@ -1,118 +1,128 @@ typedef GSList* GSListPtr; typedef struct node_s node_t; typedef struct color_s color_t; typedef struct rsc_constraint_s rsc_constraint_t; typedef struct resource_s resource_t; enum con_type { none, rsc_to_rsc, rsc_to_node, rsc_to_attr, base_weight }; enum con_strength { must, should, should_not, must_not }; enum con_modifier { modifier_none, set, inc, dec }; struct node_s { char *id; float weight; gboolean fixed; GHashTable *attrs; }; struct color_shared_s { int id; GSListPtr candidate_nodes; node_t *chosen_node; }; struct color_s { int id; struct color_shared_s *details; float local_weight; }; struct rsc_constraint_s { char *id; resource_t *rsc_lh; enum con_type type; // rsc_to_rsc gboolean is_placement; resource_t *rsc_rh; enum con_strength strength; // rsc_to_node float weight; GSListPtr node_list_rh; enum con_modifier modifier; }; struct resource_s { char *id; xmlNodePtr xml; int priority; GSListPtr candidate_colors; color_t *color; gboolean provisional; GSListPtr allowed_nodes; GSListPtr constraints; + char *cur_node_id; }; -extern gboolean stage1(xmlNodePtr cib); +extern gboolean stage0(xmlNodePtr cib); +extern gboolean stage1(GSListPtr nodes); extern gboolean stage2(GSListPtr sorted_rsc, GSListPtr sorted_nodes, GSListPtr operations); extern gboolean stage3(GSListPtr colors); extern gboolean stage4(GSListPtr colors); +extern gboolean stage5(GSListPtr resources); + extern GSListPtr rsc_list; extern GSListPtr node_list; extern GSListPtr cons_list; extern GSListPtr colors; extern GSListPtr stonith_list; extern color_t *current_color; #define slist_iter(w, x, y, z, a) for(z = 0; z < g_slist_length(y); z++) { \ x *w = (x*)g_slist_nth_data(y, z); \ a; \ } + +extern gboolean pe_debug; +#define pdebug(x) if(pe_debug) { \ + x; \ + } + extern void print_node(const char *pre_text, node_t *node); extern void print_resource(const char *pre_text, resource_t *rsc, gboolean details); extern void print_cons(const char *pre_text, rsc_constraint_t *cons, gboolean details); extern void print_color(const char *pre_text, color_t *color, gboolean details); extern void print_color_details(const char *pre_text, struct color_shared_s *color, gboolean details); extern const char *contype2text(enum con_type type); extern const char *strength2text(enum con_strength strength); extern const char *modifier2text(enum con_modifier modifier); diff --git a/crm/pengine/ptest.c b/crm/pengine/ptest.c index bcbf9f2120..9cf9bc79d4 100644 --- a/crm/pengine/ptest.c +++ b/crm/pengine/ptest.c @@ -1,384 +1,396 @@ -/* $Id: ptest.c,v 1.3 2004/04/27 19:14:18 andrew Exp $ */ +/* $Id: ptest.c,v 1.4 2004/04/27 21:40:10 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define OPTARGS "V?i:o:D:C:S:HA:U:M:I:EWRFt:m:a:d:w:c:r:p:s:" #include #include #include int main(int argc, char **argv) { xmlNodePtr cib_object = NULL; int lpc = 0; int argerr = 0; int flag; cl_log_set_entity("ptest"); cl_log_enable_stderr(TRUE); cl_log_set_facility(LOG_USER); xmlInitParser(); while (1) { int option_index = 0; static struct option long_options[] = { // Top-level Options {"daemon", 0, 0, 0}, {0, 0, 0, 0} }; flag = getopt_long(argc, argv, OPTARGS, long_options, &option_index); if (flag == -1) break; switch(flag) { case 0: printf("option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); break; /* a sample test for multiple instance if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); */ case 'V': printf("option %d", flag); break; default: printf("?? getopt returned character code 0%o ??\n", flag); ++argerr; break; } } if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); printf("\n"); } if (optind > argc) { ++argerr; } if (argerr) { cl_log(LOG_ERR, "%d errors in option parsing", argerr); } cl_log(LOG_INFO, "=#=#=#=#= Getting XML =#=#=#=#="); cib_object = file2xml(stdin); - cl_log(LOG_INFO, "=#=#=#=#= Stage 1 =#=#=#=#="); - stage1(cib_object); - + cl_log(LOG_INFO, "=#=#=#=#= Stage 0 =#=#=#=#="); + stage0(cib_object); cl_log(LOG_INFO, "========= Nodes ========="); slist_iter(node, node_t, node_list, lpc, print_node(NULL, node)); cl_log(LOG_INFO, "========= Resources ========="); slist_iter(resource, resource_t, rsc_list, lpc, print_resource(NULL, resource, FALSE)); cl_log(LOG_INFO, "========= Constraints ========="); slist_iter(constraint, rsc_constraint_t, cons_list, lpc, print_cons(NULL, constraint, FALSE)); + cl_log(LOG_INFO, "=#=#=#=#= Stage 1 =#=#=#=#="); + stage1(node_list); + + cl_log(LOG_INFO, "========= Nodes ========="); + slist_iter(node, node_t, node_list, lpc, + print_node(NULL, node)); + + cl_log(LOG_INFO, "========= Resources ========="); + slist_iter(resource, resource_t, rsc_list, lpc, + print_resource(NULL, resource, TRUE)); cl_log(LOG_INFO, "=#=#=#=#= Stage 2 =#=#=#=#="); stage2(rsc_list, node_list, NULL); cl_log(LOG_INFO, "========= Nodes ========="); slist_iter(node, node_t, node_list, lpc, print_node(NULL, node)); cl_log(LOG_INFO, "========= Resources ========="); slist_iter(resource, resource_t, rsc_list, lpc, - print_resource(NULL, resource, TRUE)); - + print_resource(NULL, resource, TRUE)); cl_log(LOG_INFO, "========= Colors ========="); slist_iter(color, color_t, colors, lpc, print_color(NULL, color, FALSE)); cl_log(LOG_INFO, "========= Stonith List ========="); slist_iter(node, node_t, stonith_list, lpc, print_node(NULL, node)); cl_log(LOG_INFO, "=#=#=#=#= Stage 3 =#=#=#=#="); stage3(colors); cl_log(LOG_INFO, "========= Colors ========="); slist_iter(color, color_t, colors, lpc, print_color(NULL, color, FALSE)); cl_log(LOG_INFO, "=#=#=#=#= Stage 4 =#=#=#=#="); stage4(colors); cl_log(LOG_INFO, "========= Colors ========="); slist_iter(color, color_t, colors, lpc, print_color(NULL, color, FALSE)); + cl_log(LOG_INFO, "=#=#=#=#= Stage 5 =#=#=#=#="); + stage5(rsc_list); + return 0; } const char * contype2text(enum con_type type) { const char *result = ""; switch(type) { case none: result = "none"; break; case rsc_to_rsc: result = "rsc_to_rsc"; break; case rsc_to_node: result = "rsc_to_node"; break; case rsc_to_attr: result = "rsc_to_attr"; break; case base_weight: result = "base_weight"; break; } return result; }; const char * strength2text(enum con_strength strength) { const char *result = ""; switch(strength) { case must: result = "must"; break; case should: result = "should"; break; case should_not: result = "should_not"; break; case must_not: result = "must_not"; break; } return result; }; const char * modifier2text(enum con_modifier modifier) { const char *result = ""; switch(modifier) { case modifier_none: result = "modifier_none"; break; case set: result = "set"; break; case inc: result = "inc"; break; case dec: result = "dec"; break; } return result; }; void print_node(const char *pre_text, node_t *node) { if(node == NULL) { cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); return; } cl_log(LOG_DEBUG, "%s Node %s: (weight=%f, fixed=%s)", pre_text==NULL?"":pre_text, node->id, node->weight, node->fixed?"True":"False"); }; void print_color_details(const char *pre_text, struct color_shared_s *color, gboolean details) { if(color == NULL) { cl_log(LOG_DEBUG, "%s %s: ", pre_text==NULL?"":pre_text, __FUNCTION__); return; } cl_log(LOG_DEBUG, "%s Color %d: node=%s (from %d candidates)", pre_text==NULL?"":pre_text, color->id, color->chosen_node->id, g_slist_length(color->candidate_nodes)); if(details) { int lpc = 0; slist_iter(node, node_t, color->candidate_nodes, lpc, print_node("\t", node)); } } void print_color(const char *pre_text, color_t *color, gboolean details) { if(color == NULL) { cl_log(LOG_DEBUG, "%s %s: ", pre_text==NULL?"":pre_text, __FUNCTION__); return; } cl_log(LOG_DEBUG, "%s Color %d: (weight=%f, node=%s, possible=%d)", pre_text==NULL?"":pre_text, color->id, color->local_weight, color->details->chosen_node==NULL?"":color->details->chosen_node->id, g_slist_length(color->details->candidate_nodes)); if(details) { print_color_details("\t", color->details, details); } } void print_cons(const char *pre_text, rsc_constraint_t *cons, gboolean details) { if(cons == NULL) { cl_log(LOG_DEBUG, "%s %s: ", pre_text==NULL?"":pre_text, __FUNCTION__); return; } cl_log(LOG_DEBUG, "%s %s Constraint %s (%p):", pre_text==NULL?"":pre_text, contype2text(cons->type), cons->id, cons); if(details == FALSE) { switch(cons->type) { case none: cl_log(LOG_ERR, "must specify a type"); break; case rsc_to_rsc: cl_log(LOG_DEBUG, "\t%s --> %s, %s (%s rule)", cons->rsc_lh==NULL?"null":cons->rsc_lh->id, cons->rsc_rh==NULL?"null":cons->rsc_rh->id, strength2text(cons->strength), cons->is_placement?"placement":"ordering"); break; case rsc_to_node: case rsc_to_attr: cl_log(LOG_DEBUG, "\t%s --> %s, %f (node placement rule)", cons->rsc_lh->id, modifier2text(cons->modifier), cons->weight); int lpc = 0; slist_iter( node, node_t, cons->node_list_rh, lpc, print_node("\t\t-->", node) ); break; case base_weight: cl_log(LOG_ERR, "not supported"); break; } } }; void print_resource(const char *pre_text, resource_t *rsc, gboolean details) { if(rsc == NULL) { cl_log(LOG_DEBUG, "%s %s: ", pre_text==NULL?"":pre_text, __FUNCTION__); return; } - cl_log(LOG_DEBUG, "%s %sResource %s: (priority=%f, color=%d)", + cl_log(LOG_DEBUG, "%s %sResource %s: (priority=%f, color=%d, now=%s)", pre_text==NULL?"":pre_text, rsc->provisional?"Provisional ":"", rsc->id, (double)rsc->priority, - rsc->color==NULL?-1:rsc->color->id); + rsc->color==NULL?-1:rsc->color->id, + rsc->cur_node_id); cl_log(LOG_DEBUG, "\t%d candidate colors, %d allowed nodes and %d constraints", g_slist_length(rsc->candidate_colors), g_slist_length(rsc->allowed_nodes), g_slist_length(rsc->constraints)); if(details) { int lpc = 0; slist_iter( color, color_t, rsc->candidate_colors, lpc, print_color("\t", color, FALSE) ); } }