diff --git a/crm/pengine/Makefile.am b/crm/pengine/Makefile.am index 832c125419..e36b1e0d08 100644 --- a/crm/pengine/Makefile.am +++ b/crm/pengine/Makefile.am @@ -1,74 +1,74 @@ # # Copyright (C) 2004 Andrew Beekhof # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program 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 program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ -I$(top_builddir)/libltdl -I$(top_srcdir)/libltdl \ -I$(top_builddir)/linux-ha -I$(top_srcdir)/linux-ha \ -I$(top_builddir) -I$(top_srcdir) hadir = $(sysconfdir)/ha.d halibdir = $(libdir)/@HB_PKG@ commmoddir = $(halibdir)/modules/comm havarlibdir = $(localstatedir)/lib/@HB_PKG@ PIDFILE = $(localstatedir)/run/crmd.pid XML_FLAGS = `xml2-config --cflags` XML_LIBS = `xml2-config --libs` # sockets with path crmdir = $(havarlibdir)/crm apigid = @HA_APIGID@ crmuid = @HA_CCMUID@ COMMONLIBS = $(CRM_DEBUG_LIBS) \ $(top_builddir)/lib/clplumbing/libplumb.la \ $(top_builddir)/$(CRM_DIR)/common/libcrmcommon.la \ $(top_builddir)/$(CRM_DIR)/cib/libcib.la \ $(top_builddir)/lib/apphb/libapphb.la \ $(GLIBLIB) \ $(LIBRT) LIBRT = @LIBRT@ AM_CFLAGS = @CFLAGS@ \ -DPIDFILE='"$(PIDFILE)"' \ $(CRM_DEBUG_FLAGS) ## libraries lib_LTLIBRARIES = ## binary progs halib_PROGRAMS = ptest ## SOURCES noinst_HEADERS = -ptest_SOURCES = ptest.c pengine.c +ptest_SOURCES = pengine.c putils.c ptest.c ptest_CFLAGS = $(XML_FLAGS) -DHA_VARLIBDIR='"@HA_VARLIBDIR@"' ptest_LDFLAGS = $(XML_LIBS) ptest_LDADD = $(COMMONLIBS) # clean-generic: rm -f *.log *.debug *~ install-exec-local: uninstall-local: diff --git a/crm/pengine/pengine.c b/crm/pengine/pengine.c index 43ac3921a6..f96d3d56d0 100755 --- a/crm/pengine/pengine.c +++ b/crm/pengine/pengine.c @@ -1,1192 +1,1045 @@ -#include - #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 sorted_rsc, - GSListPtr colors); +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 stage1(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); -/* rsc_list = g_slist_alloc(); */ -/* node_list = create_slist(); */ -/* cons_list = g_slist_alloc(); */ -/* colors = g_slist_alloc(); */ -/* stonith_list = g_slist_alloc(); */ - unpack_nodes(cib_nodes->children); unpack_resources(cib_resources->children); unpack_status(cib_status); unpack_constraints(cib_constraints->children); apply_node_constraints(cons_list, node_list, rsc_list); - // filter_nodes(rsc_list); + //filter_nodes(rsc_list); return TRUE; } void -color_resource(resource_t *lh_resource, GSListPtr sorted_rsc, GSListPtr colors) +color_resource(resource_t *lh_resource, GSListPtr colors) { int lpc = 0; - GSListPtr intersection = NULL; - cl_log(LOG_DEBUG, "Coloring resource"); - print_resource(lh_resource, FALSE); + print_resource("Coloring", lh_resource, FALSE); lh_resource->constraints = g_slist_sort(lh_resource->constraints, sort_cons_strength); - cl_log(LOG_DEBUG, "Pre-processing"); + cl_log(LOG_DEBUG, "=== Pre-processing"); //------ Pre-processing for(; 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 *other_color = NULL; color_t *local_color = NULL; - cl_log(LOG_DEBUG, "Processing constraint %d", lpc); - print_cons(constraint, FALSE); + rsc_constraint_t *constraint = (rsc_constraint_t*) + g_slist_nth_data(lh_resource->constraints, lpc); + + 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); - 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; - } - 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; - } - + 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) */ - lh_resource->candidate_colors = g_slist_sort(lh_resource->candidate_colors, sort_color_weight); - cl_log(LOG_DEBUG, "Choose a color from %d possibilities", g_slist_length(lh_resource->candidate_colors )); - for(lpc = 0; - lpc < g_slist_length(lh_resource->candidate_colors) - && lh_resource->provisional; - lpc++) { - color_t *this_color = (color_t*)g_slist_nth_data(lh_resource->candidate_colors, lpc); - print_color(this_color, FALSE); - intersection = node_list_and(this_color->details->candidate_nodes, - lh_resource->allowed_nodes); - - cl_log(LOG_DEBUG, "Checking the node intersection %d", g_slist_length(intersection)); - - 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; - } - } + 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"); current_color = create_color(lh_resource->allowed_nodes); lh_resource->color = current_color; lh_resource->provisional = FALSE; } - cl_log(LOG_DEBUG, "Post-processing"); + 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; 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); - 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, sorted_rsc, colors); - } - // else check for error - break; - - // x * should * should_not = x - case should: - /* will be taken care of in the pre-processing stage of coloring rsc_rh - if(constraint->rsc_rh->provisional == TRUE) { - other_color->weight = other_color->weight * 2.0; - } - */ - break; - case should_not: - /* will be taken care of in the pre-processing stage of coloring rsc_rh - if(constraint->rsc_rh->provisional == TRUE) { - other_color->weight = other_color->weight * 0.5; - } - */ - break; - case must_not: - /* will be taken care of in the pre-processing stage of coloring rsc_rh - if(constraint->rsc_rh->provisional == FALSE) { - g_slist_remove(constraint->rsc_rh->candidate_colors, other_color); - } - */ - if(constraint->rsc_rh->provisional == TRUE) { - // check for error - } - break; - default: - // error - break; - } - + strict_postproc(constraint, local_color, other_color); } - + + print_resource("Colored", lh_resource, FALSE); } gboolean stage2(GSListPtr sorted_rsc, GSListPtr sorted_nodes, GSListPtr operations) { - resource_t *lh_resource = NULL; int lpc = 0; - // Set initial color // Set color.candidate_nodes = all active nodes current_color = cl_malloc(sizeof(color_t)); - cl_log(LOG_DEBUG, "setup"); 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); this_resource->color = current_color; this_resource->provisional = TRUE; } cl_log(LOG_DEBUG, "initialized resources to default color"); // Take (next) highest resource for(lpc = 0; lpc < g_slist_length(sorted_rsc); lpc++) { - cl_log(LOG_DEBUG, "Processing resource %d", lpc); - lh_resource = (resource_t*)g_slist_nth_data(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, sorted_rsc, colors); + 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)) + { + // we can create a few more + } + + return TRUE; +} + +gboolean +stage4(GSListPtr colors) { int lpc = 0; color_t *color_n = NULL; color_t *color_n_plus_1 = NULL; - GSListPtr xor = NULL; - GSListPtr minus = 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); - cl_log(LOG_DEBUG, "Choose node for..."); - print_color(color_n, FALSE); - print_color(color_n_plus_1, FALSE); + print_color("Choose node for...", color_n, FALSE); +// print_color(color_n_plus_1, FALSE); if(color_n == NULL) { continue; } - xor = node_list_xor(color_n_nodes, + GSListPtr xor = node_list_xor(color_n_nodes, color_n_plus_1_nodes); - minus = node_list_minus(color_n_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"); choose_node_from_list(colors, color_n, color_n_nodes); } else { 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) { - cl_log(LOG_DEBUG, "Choose node for last color..."); - print_color(color_n, FALSE); + print_color("Choose node for last color...", color_n, 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 */ - color_t *color_n = NULL; - node_t *other_node = NULL; 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_n = (color_t*)g_slist_nth_data(colors, lpc); - other_node = pe_find_node(color_n->details->candidate_nodes, + 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; } -/* only for rsc_to_rsc constraints */ -rsc_constraint_t * -invert_constraint(rsc_constraint_t *constraint) -{ - rsc_constraint_t *inverted_con = NULL; - cl_log(LOG_DEBUG, "Inverting constraint"); - inverted_con = - cl_malloc(sizeof(rsc_constraint_t)); - - inverted_con->id = cl_strdup(constraint->id); - inverted_con->type = constraint->type; - inverted_con->strength = constraint->strength; - inverted_con->is_placement = constraint->is_placement; - - // swap the direction - inverted_con->rsc_lh = constraint->rsc_rh; - inverted_con->rsc_rh = constraint->rsc_lh; - - inverted_con->node_rh = NULL; - inverted_con->modifier = modifier_none; - inverted_con->weight = 0.0; - - cl_log(LOG_DEBUG, "Inverted constraint"); - print_cons(inverted_con, FALSE); - return inverted_con; -} - -rsc_constraint_t * -copy_constraint(rsc_constraint_t *constraint) -{ - rsc_constraint_t *copied_con = - cl_malloc(sizeof(rsc_constraint_t)); - - copied_con->id = cl_strdup(constraint->id); - copied_con->type = constraint->type; - copied_con->strength = constraint->strength; - copied_con->is_placement = constraint->is_placement; - - // swap the direction - copied_con->rsc_lh = constraint->rsc_lh; - copied_con->rsc_rh = constraint->rsc_rh; - - copied_con->node_rh = constraint->node_rh; - copied_con->modifier = constraint->modifier; - copied_con->weight = constraint->weight; - - return copied_con; -} - - -/* are the contents of list1 and list2 equal */ -/* nodes with weight < 0 are ignored */ -gboolean -node_list_eq(GSListPtr list1, GSListPtr list2) -{ - GSListPtr result = NULL; - - if(g_slist_length(list1) != g_slist_length(list2)) { - return FALSE; - } - - // do stuff - - return g_slist_length(result) != 0; -} - -/* the intersection of list1 and list2 */ -/* nodes with weight < 0 are ignored */ -GSListPtr -node_list_and(GSListPtr list1, GSListPtr list2) -{ - GSListPtr result = NULL; - int lpc = 0; - node_t *node = NULL; - node_t *new_node = NULL; - node_t *other_node = NULL; - - cl_log(LOG_DEBUG, "Len 1: %d, len 2: %d", g_slist_length(list1), g_slist_length(list2)); - for(lpc = 0; lpc < g_slist_length(list1); lpc++) { - node = (node_t*)g_slist_nth_data(list1, lpc); - new_node = node_copy(node); - other_node = (node_t*)find_list_node(list2, node->id); - - if(node == NULL || other_node == NULL) { - continue; - - // merge node weights - } else if(node->weight < 0 || other_node->weight < 0) { - new_node->weight = -1; - } else { - new_node->weight = - node->weight + other_node->weight; - if(new_node->weight != 0) { - new_node->weight = new_node->weight /2.0; - } - } - result = g_slist_append(result, new_node); - - } - - - return result; -} - -node_t * -find_list_node(GSListPtr list, const char *id) -{ - node_t *thing = NULL; - int lpc = 0; - - for(lpc = 0; lpc < g_slist_length(list); lpc++) { - thing = (node_t *)g_slist_nth_data(list, lpc); - if(safe_str_eq(thing->id, id)) { - return thing; - } - } - return NULL; -} - -/* list1 - list2 */ -/* nodes with weight < 0 are ignored */ -GSListPtr -node_list_minus(GSListPtr list1, GSListPtr list2) -{ - GSListPtr result = NULL; - int lpc = 0; - node_t *node = NULL; - node_t *other_node = NULL; - node_t *new_node = NULL; - - for(lpc = 0; lpc < g_slist_length(list1); lpc++) { - node = (node_t*)g_slist_nth_data(list1, lpc); - other_node = (node_t*)find_list_node(list2, node->id); - - if(node == NULL || other_node != NULL) { - continue; - - // merge node weights - } - new_node = node_copy(node); - result = g_slist_append(result, new_node); - - } - - cl_log(LOG_DEBUG, "Minus result len: %d", g_slist_length(result)); - return result; -} - -/* list1 + list2 - (intersection of list1 and list2) */ -/* nodes with weight < 0 are ignored */ -GSListPtr -node_list_xor(GSListPtr list1, GSListPtr list2) -{ - GSListPtr result = NULL; - int lpc = 0; - node_t *node = NULL; - node_t *other_node = NULL; - node_t *new_node = NULL; - - for(lpc = 0; lpc < g_slist_length(list1); lpc++) { - node = (node_t*)g_slist_nth_data(list1, lpc); - other_node = (node_t*)find_list_node(list2, node->id); - - if(node == NULL || other_node != NULL) { - continue; - - // merge node weights - } - new_node = node_copy(node); - result = g_slist_append(result, new_node); - - } - - for(lpc = 0; lpc < g_slist_length(list2); lpc++) { - node_t *node = (node_t*)g_slist_nth_data(list2, lpc); - node_t *other_node = (node_t*)find_list_node(list1, node->id); - - if(node == NULL || other_node != NULL) { - continue; - - // merge node weights - } - new_node = node_copy(node); - result = g_slist_append(result, new_node); - } - - cl_log(LOG_DEBUG, "Xor result len: %d", g_slist_length(result)); - return result; -} - -GSListPtr -node_list_dup(GSListPtr list1) -{ - GSListPtr result = NULL; - int lpc = 0; - if(list1 == NULL) { - return NULL; - } - for(lpc = 0; lpc < g_slist_length(list1); lpc++) { - node_t *this_node = (node_t*)g_slist_nth_data(list1, lpc); - node_t *new_node = node_copy(this_node); - if(new_node != NULL) { - result = g_slist_append(result, new_node); - } - } - - return result; -} - -node_t * -node_copy(node_t *this_node) -{ - node_t *new_node = NULL; - - if(this_node == NULL) { - print_node(this_node); - return NULL; - } - new_node = cl_malloc(sizeof(node_t)); - new_node->id = cl_strdup(this_node->id); - new_node->weight = this_node->weight; - new_node->fixed = this_node->fixed; - - return new_node; -} - -static int color_id = 0; -color_t * -create_color(GSListPtr nodes) -{ - int lpc = 0; - color_t *new_color = cl_malloc(sizeof(color_t)); - new_color->id = color_id++; - new_color->local_weight = 0; // not used here - new_color->details = cl_malloc(sizeof(struct color_shared_s)); - new_color->details->chosen_node = NULL; - new_color->details->candidate_nodes = node_list_dup(nodes); - - colors = g_slist_append(colors, new_color); - - print_color(new_color, FALSE); - /* Add any new color to the list of candidate_colors for - * resources that havent been decided yet - */ - for(lpc = 0; lpc < g_slist_length(rsc_list); lpc++) { - resource_t *rh_resource = - (resource_t*)g_slist_nth_data(rsc_list, lpc); - add_color_to_rsc(rh_resource, new_color); - } - - - - return new_color; -} - - -void -add_color_to_rsc(resource_t *rsc, color_t *color) -{ - color_t *color_copy = NULL; - if(rsc->provisional) { - color_copy = cl_malloc(sizeof(color_t)); - color_copy->id = color->id; - color_copy->local_weight = 1.0; - color_copy->details = color->details; - rsc->candidate_colors = g_slist_append(rsc->candidate_colors, color_copy); - } -} - gboolean unpack_nodes(xmlNodePtr nodes) { - int lpc = 1; - node_t *new_node = NULL; - xmlNodePtr xml_obj = NULL; - const char *id = NULL; - cl_log(LOG_DEBUG, "Begining unpack... %s", __FUNCTION__); cl_log(LOG_DEBUG, "Number of nodes... %d", g_slist_length(node_list)); + int lpc = 1; while(nodes != NULL) { 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; - xml_obj = nodes; - id = xmlGetProp(xml_obj, "id"); if(id == NULL) { cl_log(LOG_ERR, "Must specify id tag in "); continue; } - new_node = cl_malloc(sizeof(node_t)); + 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); node_list = g_slist_append(node_list, new_node); cl_log(LOG_DEBUG, "Number of nodes... %d", g_slist_length(node_list)); } 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) { - resource_t *new_rsc = NULL; 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..."); if(id == NULL) { cl_log(LOG_ERR, "Must specify id tag in "); continue; } - new_rsc = NULL; - new_rsc = cl_malloc(sizeof(resource_t)); - new_rsc = cl_malloc(sizeof(resource_t)); + 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); 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) { - const char *id = NULL; - xmlNodePtr xml_obj = NULL; - rsc_constraint_t *new_con = NULL; - rsc_constraint_t *inverted_con = NULL; - const char *id_lh = NULL; - resource_t *rsc_lh = NULL; - const char *strength = NULL; - const char *type = NULL; - const char *id_rh = NULL; - const char *mod = NULL; - const char *weight = NULL; - rsc_constraint_t *cons_copy = NULL; - float weight_f; - resource_t *rsc_rh; - int lpc = 0; - cl_log(LOG_DEBUG, "Begining unpack... %s", __FUNCTION__); while(constraints != NULL) { - id = xmlGetProp(constraints, "id"); - xml_obj = constraints; + 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", id); - - new_con = cl_malloc(sizeof(rsc_constraint_t)); - inverted_con = NULL; - id_lh = xmlGetProp(xml_obj, "from"); - cl_log(LOG_DEBUG, "Looking up resource..."); - 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); - continue; - } - new_con->id = cl_strdup(id); - new_con->rsc_lh = rsc_lh; + cl_log(LOG_DEBUG, "Processing constraint %s %s", + xml_obj->name,id); if(safe_str_eq("rsc_to_rsc", xml_obj->name)) { - new_con->type = rsc_to_rsc; - 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 - } - - 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_rh = NULL; - - - id_rh = xmlGetProp(xml_obj, "to"); - 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); - continue; - } - 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); + unpack_rsc_to_rsc(xml_obj); } else if(safe_str_eq("rsc_to_node", xml_obj->name)) { - xmlNodePtr node_ref = xml_obj->children; - new_con->type = rsc_to_node; - new_con->rsc_rh = NULL; - - mod = xmlGetProp(xml_obj, "modifier"); - weight = xmlGetProp(xml_obj, "weight"); - weight_f = atof(weight); - new_con->weight = weight_f; - - cl_log(LOG_DEBUG, "Mod: %s", mod); + unpack_rsc_to_node(xml_obj); + + } else if(safe_str_eq("rsc_to_attr", xml_obj->name)) { + unpack_rsc_to_attr(xml_obj); - 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) { - id_rh = xmlGetProp(node_ref, "name"); - cons_copy = copy_constraint(new_con); - cons_copy->node_rh = pe_find_node(rsc_lh->allowed_nodes, id_rh); - - if(cons_copy->node_rh == NULL) { - // error - cl_log(LOG_ERR, - "node %s (from %s) not found", - id_rh, node_ref->name); - } else { - cons_list = g_slist_insert_sorted(cons_list, cons_copy, sort_cons_strength); - } - - /* dont add it to the resource, - * the information is in the resouce's node list - */ - node_ref = node_ref->next; - } - cl_free(new_con->id); - cl_free(new_con); - } else { - // error + 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)); + print_cons("", resource, FALSE)); return TRUE; } gboolean apply_node_constraints(GSListPtr constraints, GSListPtr resources, GSListPtr nodes) { - resource_t *rsc_lh = NULL; - GSListPtr rsc_cons_list = NULL; - int lpc = 0; - 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); - cl_log(LOG_DEBUG, "Processing constraint %d", lpc); + 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; } - rsc_lh = cons->rsc_lh; + 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; } - rsc_cons_list = cons->rsc_lh->constraints; + 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"); continue; - } else if(cons->type == rsc_to_node) { - if(cons->node_rh == NULL) { + } 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 if(cons->node_rh->fixed) { - // warning - cl_log(LOG_WARNING, - "Constraint %s is irrelevant as the" - " weight of node %s is fixed as %f.", - cons->id, - cons->node_rh->id, - cons->node_rh->weight); } else { - node_t *node_rh = - pe_find_node(cons->rsc_lh->allowed_nodes, - cons->node_rh->id); - cl_log(LOG_DEBUG, - "Constraint %s: node %s weight %s %f.", - cons->id, - cons->node_rh->id, - modifier2text(cons->modifier), - cons->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; - - } + 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; } -gboolean -filter_nodes(resource_t *rsc) -{ - int lpc2 = 0; - node_t *node = NULL; - - cl_log(LOG_DEBUG, "Filtering nodes... %s", __FUNCTION__); - - print_resource(rsc, FALSE); - - for(lpc2 = 0; lpc2 < g_slist_length(rsc->allowed_nodes); lpc2++) { - node = g_slist_nth_data(rsc->allowed_nodes, lpc2); - print_node(node); - if(node == NULL) { - cl_log(LOG_ERR, "Invalid NULL node"); - - } else if(node->weight < 0.0) { - cl_log(LOG_DEBUG, "removing:"); - print_node(node); - rsc->allowed_nodes = g_slist_remove(rsc->allowed_nodes,node); - } - - } - - return TRUE; -} - -resource_t * -pe_find_resource(GSListPtr rsc_list, const char *id_rh) -{ - int lpc = 0; - for(lpc = 0; lpc < g_slist_length(rsc_list); lpc++) { - resource_t *rsc = g_slist_nth_data(rsc_list, lpc); - if(rsc != NULL && safe_str_eq(rsc->id, id_rh)){ - cl_log(LOG_DEBUG, "Resource %s found at %d...", - id_rh, lpc); - return rsc; - } - } - // error - return NULL; -} -node_t * -pe_find_node(GSListPtr nodes, const char *id) -{ - int lpc = 0; - - for(lpc = 0; lpc < g_slist_length(nodes); lpc++) { - node_t *node = g_slist_nth_data(nodes, lpc); - if(safe_str_eq(node->id, id)) { - return node; - } - } - // error - return NULL; -} // 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__); 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, "rsc_state"); status = status->next; - if(id == NULL) { + + cl_log(LOG_DEBUG, "Processing node %s", id); + + if(id == NULL){ // error continue; } + 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); + + 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"); + if(safe_str_eq(exp_state, "active") && safe_str_eq(state, "active")) { // process resource, make +ve preference - - 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"))) { - - rsc_constraint_t *new_cons = cl_malloc(sizeof(rsc_constraint_t)); - new_cons->id = cl_strdup(""); // genereate one - new_cons->rsc_lh = pe_find_resource(rsc_list, rsc_id); - new_cons->type = rsc_to_node; - new_cons->weight = 100.0; - new_cons->node_rh = pe_find_node(new_cons->rsc_lh->allowed_nodes, node_id); - new_cons->modifier = inc; - - cons_list = g_slist_append(cons_list, new_cons); - - } else if(safe_str_eq(rsc_state, "stop_fail")) { - // do soemthing - } // else no preference - - lrm_state = lrm_state->next; - } - } else { + add_positive_preference(lrm_state); + + } else if(0) { // 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; } } if(safe_str_eq(exp_state, "down") - && safe_str_eq(state, "shutdown")) { + && 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 // remove any running resources from being allocated } if(safe_str_eq(state, "unclean")) { stonith_list = g_slist_append(stonith_list, node); } } } cons_list = g_slist_sort(cons_list, sort_cons_strength); return TRUE; } +gboolean +is_active(rsc_constraint_t *cons) +{ + return TRUE; +} + -color_t * -find_color(GSListPtr candidate_colors, color_t *other_color) + +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) { + 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; - slist_iter(color, color_t, candidate_colors, lpc, - if(color->id == other_color->id) { - return color; - } - ); - return NULL; + 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)); + + + 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 -is_active(rsc_constraint_t *cons) +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; } -gint sort_rsc_priority(gconstpointer a, gconstpointer b) + +gboolean +unpack_rsc_to_attr(xmlNodePtr xml_obj) { - const resource_t *resource1 = (const resource_t*)a; - const resource_t *resource2 = (const resource_t*)b; - if(a == NULL) return 1; - if(b == NULL) return -1; - - if(resource1->priority > resource2->priority) - return -1; +/* + + + + + + + + + + + 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; - if(resource1->priority < resource2->priority) - return 1; + 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); + cons_list = g_slist_append(cons_list, new_con); - return 0; + /* dont add it to the resource, + * the information is in the resouce's node list + */ + attr_exp = attr_exp->next; + } + return TRUE; } -gint sort_cons_strength(gconstpointer a, gconstpointer b) +gboolean +update_node_weight(rsc_constraint_t *cons, node_t *node) { - const rsc_constraint_t *rsc_constraint1 = (const rsc_constraint_t*)a; - const rsc_constraint_t *rsc_constraint2 = (const rsc_constraint_t*)b; - - if(rsc_constraint1->strength > rsc_constraint2->strength) - return 1; + 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(rsc_constraint1->strength < rsc_constraint2->strength) - return -1; - return 0; + 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); + + 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; } -gint sort_color_weight(gconstpointer a, gconstpointer b) +gboolean +add_positive_preference(xmlNodePtr lrm_state) { - const color_t *color1 = (const color_t*)a; - const color_t *color2 = (const color_t*)b; - if(a == NULL) return 1; - if(b == NULL) return -1; - - if(color1->local_weight > color2->local_weight) - return -1; + 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); - if(color1->local_weight < color2->local_weight) - return 1; + 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); + + } else if(safe_str_eq(rsc_state, "stop_fail")) { + // do soemthing + } // else no preference - return 0; + lrm_state = lrm_state->next; + } + return TRUE; } -gint sort_node_weight(gconstpointer a, gconstpointer b) +GSListPtr +match_attrs(xmlNodePtr attr_exp, GSListPtr node_list) { - const node_t *node1 = (const node_t*)a; - const node_t *node2 = (const node_t*)b; - - if(a == NULL) return 1; - if(b == NULL) return -1; + 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); + + } + ); - if(node1->weight > node2->weight) - return -1; + return result; +} - if(node1->weight < node2->weight) - return 1; - +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; + } - return 0; + 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 d03c6d4573..6628aeee57 100644 --- a/crm/pengine/pengine.h +++ b/crm/pengine/pengine.h @@ -1,102 +1,118 @@ 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; + 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; - node_t *node_rh; + 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; }; extern gboolean stage1(xmlNodePtr cib); extern gboolean stage2(GSListPtr sorted_rsc, GSListPtr sorted_nodes, GSListPtr operations); extern gboolean stage3(GSListPtr colors); +extern gboolean stage4(GSListPtr colors); 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 void print_node(node_t *node); -extern void print_resource(resource_t *rsc, gboolean details); -extern void print_cons(rsc_constraint_t *cons, gboolean details); -extern void print_color(color_t *color, gboolean details); -extern void print_color_details(struct color_shared_s *color, gboolean details); +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 8a0aadc9df..bcbf9f2120 100644 --- a/crm/pengine/ptest.c +++ b/crm/pengine/ptest.c @@ -1,364 +1,384 @@ -/* $Id: ptest.c,v 1.2 2004/04/26 12:36:20 msoffen Exp $ */ +/* $Id: ptest.c,v 1.3 2004/04/27 19:14:18 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 - -void print_node(node_t *node); -void print_resource(resource_t *rsc, gboolean details); -void print_cons(rsc_constraint_t *cons, gboolean details); -void print_color(color_t *color, gboolean details); -void print_color_details(struct color_shared_s *color, gboolean details); - - 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, "========= Nodes ========="); slist_iter(node, node_t, node_list, lpc, - print_node(node)); + print_node(NULL, node)); cl_log(LOG_INFO, "========= Resources ========="); slist_iter(resource, resource_t, rsc_list, lpc, - print_resource(resource, FALSE)); + print_resource(NULL, resource, FALSE)); cl_log(LOG_INFO, "========= Constraints ========="); slist_iter(constraint, rsc_constraint_t, cons_list, lpc, - print_cons(constraint, FALSE)); + print_cons(NULL, constraint, FALSE)); 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(node)); + print_node(NULL, node)); cl_log(LOG_INFO, "========= Resources ========="); slist_iter(resource, resource_t, rsc_list, lpc, - print_resource(resource, FALSE)); + print_resource(NULL, resource, TRUE)); cl_log(LOG_INFO, "========= Colors ========="); slist_iter(color, color_t, colors, lpc, - print_color(color, FALSE)); + print_color(NULL, color, FALSE)); cl_log(LOG_INFO, "========= Stonith List ========="); slist_iter(node, node_t, stonith_list, lpc, - print_node(node)); + print_node(NULL, node)); - cl_log(LOG_INFO, "========= Current Color ========="); - print_color(current_color, FALSE); - - 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(color, FALSE)); + print_color(NULL, color, FALSE)); 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(node_t *node) +print_node(const char *pre_text, node_t *node) { if(node == NULL) { cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); return; } - cl_log(LOG_DEBUG, "Node %s: (weight=%f, fixed=%s)", + 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(struct color_shared_s *color, gboolean details) +print_color_details(const char *pre_text, struct color_shared_s *color, gboolean details) { if(color == NULL) { - cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); + cl_log(LOG_DEBUG, "%s %s: ", + pre_text==NULL?"":pre_text, + __FUNCTION__); return; } - cl_log(LOG_DEBUG, "Color %d: node=%s (from %d candidates)", + 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(node)); + print_node("\t", node)); } } void -print_color(color_t *color, gboolean details) +print_color(const char *pre_text, color_t *color, gboolean details) { if(color == NULL) { - cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); + cl_log(LOG_DEBUG, "%s %s: ", + pre_text==NULL?"":pre_text, + __FUNCTION__); return; } - cl_log(LOG_DEBUG, "Color %d: (weight=%f, node=%s, possible=%d)", + 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(color->details, details); + print_color_details("\t", color->details, details); } } void -print_cons(rsc_constraint_t *cons, gboolean details) +print_cons(const char *pre_text, rsc_constraint_t *cons, gboolean details) { if(cons == NULL) { - cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); + cl_log(LOG_DEBUG, "%s %s: ", + pre_text==NULL?"":pre_text, + __FUNCTION__); return; } - cl_log(LOG_DEBUG, "%s Constraint %s (%p):", + 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, %s %f (node placement rule)", + "\t%s --> %s, %f (node placement rule)", cons->rsc_lh->id, - cons->node_rh->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(resource_t *rsc, gboolean details) +print_resource(const char *pre_text, resource_t *rsc, gboolean details) { if(rsc == NULL) { - cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); + cl_log(LOG_DEBUG, "%s %s: ", + pre_text==NULL?"":pre_text, + __FUNCTION__); return; } - cl_log(LOG_DEBUG, "%sResource %s: (priority=%f, color=%d)", + cl_log(LOG_DEBUG, "%s %sResource %s: (priority=%f, color=%d)", + pre_text==NULL?"":pre_text, rsc->provisional?"Provisional ":"", rsc->id, (double)rsc->priority, rsc->color==NULL?-1:rsc->color->id); - if(details == FALSE) { - 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)); + 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) + ); } }