diff --git a/crm/pengine/Makefile.am b/crm/pengine/Makefile.am index 225a58a221..832c125419 100644 --- a/crm/pengine/Makefile.am +++ b/crm/pengine/Makefile.am @@ -1,42 +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 -hadir = $(sysconfdir)/ha.d -halibdir = $(libdir)/@HB_PKG@ -commmoddir = $(halibdir)/modules/comm -havarlibdir = $(localstatedir)/lib/@HB_PKG@ -PIDFILE = $(localstatedir)/run/crmd.pid +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 +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 = -## Perl scripts -halib_SCRIPTS = pengine +## binary progs +halib_PROGRAMS = ptest ## SOURCES -#noinst_HEADERS = config.h control.h crmd.h -noinst_HEADERS = +noinst_HEADERS = + +ptest_SOURCES = ptest.c pengine.c + +ptest_CFLAGS = $(XML_FLAGS) -DHA_VARLIBDIR='"@HA_VARLIBDIR@"' +ptest_LDFLAGS = $(XML_LIBS) +ptest_LDADD = $(COMMONLIBS) + +# clean-generic: - rm -f *.log *.debug *.xml *~ + rm -f *.log *.debug *~ install-exec-local: uninstall-local: diff --git a/crm/pengine/pengine.c b/crm/pengine/pengine.c index 002e028312..54695a2715 100755 --- a/crm/pengine/pengine.c +++ b/crm/pengine/pengine.c @@ -1,1000 +1,1136 @@ #include #include #include #include #include #include -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, - 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; -}; - -struct color_shared_s { - int id; - GSListPtr candidate_nodes; - node_t *chosen_node; -}; - +#include -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; - 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; -}; - - -color_t *create_color(GSListPtr nodes, int new_id); +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 stage1(xmlNodePtr cib); -gboolean stage2(GSListPtr sorted_rsc, - GSListPtr sorted_nodes, - GSListPtr operations); -gboolean stage3(GSListPtr colors); 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); gboolean is_active(rsc_constraint_t *cons); rsc_constraint_t *invert_constraint(rsc_constraint_t *constraint); -gboolean filter_nodes(GSListPtr rsc_list); +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, resource_t *rsc, const char *id); +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); 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 = g_slist_alloc(); - cons_list = g_slist_alloc(); - colors = g_slist_alloc(); - stonith_list = g_slist_alloc(); +/* 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); - unpack_resources(cib_resources); + unpack_nodes(cib_nodes->children); + unpack_resources(cib_resources->children); unpack_status(cib_status); - unpack_constraints(cib_constraints); + 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) { - int lpc = 0; - - g_slist_sort(lh_resource->constraints, sort_cons_strength); + int lpc = 0; + + cl_log(LOG_DEBUG, "Coloring resource"); + print_resource(lh_resource, FALSE); + + lh_resource->constraints = g_slist_sort(lh_resource->constraints, sort_cons_strength); + 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); + 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); 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; + 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; + local_color->local_weight * 0.5; } break; case must_not: - /* should be redundant if(constraint->rsc_rh->provisional == FALSE) { - g_slist_remove(lh_resource->candidate_colors, local_color); + lh_resource->candidate_colors = g_slist_remove(lh_resource->candidate_colors, local_color); } - */ break; default: // error break; } } // filter out nodes with a negative weight - filter_nodes(lh_resource->allowed_nodes); + 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) */ - g_slist_sort(lh_resource->candidate_colors, sort_color_weight); + 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); + color_t *this_color = (color_t*)g_slist_nth_data(lh_resource->candidate_colors, lpc); + print_color(this_color, FALSE); GSListPtr 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; } } if(lh_resource->provisional) { // Create new color - current_color = create_color(lh_resource->allowed_nodes, - current_color->id + 1); + 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"); + //------ 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); + 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; } } } gboolean stage2(GSListPtr sorted_rsc, GSListPtr sorted_nodes, GSListPtr operations) { - int lpc = 0; + int lpc = 0; // Set initial color // Set color.candidate_nodes = all active nodes current_color = cl_malloc(sizeof(color_t)); - current_color->id = 0; - current_color->local_weight = 1.0; - current_color->details->chosen_node = NULL; - current_color->details->candidate_nodes = node_list_dup(sorted_nodes); - g_slist_append(colors, current_color); + 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); + resource_t *this_resource = (resource_t*)g_slist_nth_data(sorted_rsc, lpc); this_resource->color = current_color; - g_slist_append(this_resource->candidate_colors, 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++) { - resource_t *lh_resource = (resource_t*)g_slist_nth_data(sorted_rsc, lpc); + cl_log(LOG_DEBUG, "Processing resource %d", 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); // next resource } return TRUE; } #define color_n_nodes color_n->details->candidate_nodes -#define color_n_plus_1_nodes color_n->details->candidate_nodes +#define color_n_plus_1_nodes color_n_plus_1->details->candidate_nodes gboolean stage3(GSListPtr colors) { - int lpc = 0; + 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); + cl_log(LOG_DEBUG, "Choose node for..."); + print_color(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) { - choose_node_from_list(colors, color_n, xor); + 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 { - GSListPtr minus = node_list_minus(color_n_nodes, - color_n_plus_1_nodes); - if(g_slist_length(minus) == 0) { - choose_node_from_list(colors, color_n, minus); - - } else { - minus = node_list_minus(color_n_plus_1_nodes, - color_n_nodes); - choose_node_from_list(colors, color_n, minus); - } - + cl_log(LOG_DEBUG, "Choose a node not in n+1"); + choose_node_from_list(colors, color_n, minus); } - // chose last color + } + + // chose last color + if(color_n_plus_1 != NULL) { + cl_log(LOG_DEBUG, "Choose node for last color..."); + print_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 */ - int lpc = 0; - g_slist_sort(nodes, sort_node_weight); + 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); - g_slist_remove(color_n->details->candidate_nodes, - color->details->chosen_node); + 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) { + cl_log(LOG_DEBUG, "Inverting constraint"); rsc_constraint_t *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 = g_slist_alloc(); + 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 = g_slist_alloc(); + GSListPtr result = NULL; int lpc = 0; - // merge node weights - for(lpc = 0; lpc < g_slist_length(list2); lpc++) { - node_t *new_node = NULL; - node_t *other_node = NULL; - node_t *node = (node_t*)g_slist_nth_data(list2, lpc); - int index = g_slist_index(result, node); - if(index < 0) { + + 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_t *node = (node_t*)g_slist_nth_data(list1, lpc); + node_t *new_node = node_copy(node); + node_t *other_node = (node_t*)find_list_node(list2, node->id); + + if(node == NULL || other_node == NULL) { continue; - } - new_node = node_copy(node); - other_node = (node_t*)g_slist_nth_data(list2, index); - if(node->weight < 0 || other_node->weight < 0) { + + // 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) / 2.0; + node->weight + other_node->weight; + if(new_node->weight != 0) { + new_node->weight = new_node->weight /2.0; + } } - g_slist_append(result, new_node); + result = g_slist_append(result, new_node); } return result; } +node_t * +find_list_node(GSListPtr list, const char *id) +{ + int lpc = 0; + for(lpc = 0; lpc < g_slist_length(list); lpc++) { + node_t *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 = g_slist_alloc(); + GSListPtr result = NULL; int lpc = 0; - g_slist_concat(result, list1); - - for(lpc = 0; lpc < g_slist_length(list2); lpc++) { - node_t *node = (node_t*)g_slist_nth_data(list2, lpc); - g_slist_remove(result, node); + for(lpc = 0; lpc < g_slist_length(list1); lpc++) { + node_t *node = (node_t*)g_slist_nth_data(list1, lpc); + node_t *other_node = (node_t*)find_list_node(list2, node->id); + + if(node == NULL || other_node != NULL) { + continue; + + // merge node weights + } + node_t *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 = g_slist_alloc(); - GSListPtr and = node_list_and(list1, list2); + GSListPtr result = NULL; int lpc = 0; - // merge weights - g_slist_concat(result, list1); - g_slist_concat(result, list2); + for(lpc = 0; lpc < g_slist_length(list1); lpc++) { + node_t *node = (node_t*)g_slist_nth_data(list1, lpc); + node_t *other_node = (node_t*)find_list_node(list2, node->id); - for(lpc = 0; lpc < g_slist_length(and); lpc++) { - node_t *node = (node_t*)g_slist_nth_data(and, lpc); - // twice, it may have been in list1 and list2 - g_slist_remove(result, node); - g_slist_remove(result, node); + if(node == NULL || other_node != NULL) { + continue; + + // merge node weights + } + node_t *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 + } + node_t *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 = g_slist_alloc(); + 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 *this_node = (node_t*)g_slist_nth_data(list1, lpc); node_t *new_node = node_copy(this_node); - g_slist_append(result, new_node); + if(new_node != NULL) { + result = g_slist_append(result, new_node); + } } return result; } node_t * node_copy(node_t *this_node) { + if(this_node == NULL) { + print_node(this_node); + return NULL; + } node_t *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 new_id) +create_color(GSListPtr nodes) { - int lpc = 0; + int lpc = 0; color_t *new_color = cl_malloc(sizeof(color_t)); - new_color->id = new_id; + 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); - g_slist_append(colors, new_color); + 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); + 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) { if(rsc->provisional) { color_t *color_copy = cl_malloc(sizeof(color_t)); color_copy->id = color->id; color_copy->local_weight = 1.0; color_copy->details = color->details; - g_slist_append(rsc->candidate_colors, color_copy); + rsc->candidate_colors = g_slist_append(rsc->candidate_colors, color_copy); } } 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)); + int lpc = 1; while(nodes != NULL) { - const char *id = xmlGetProp(nodes, "id"); + cl_log(LOG_DEBUG, "Processing node..."); + xmlNodePtr xml_obj = nodes; + const char *id = xmlGetProp(xml_obj, "id"); + nodes = nodes->next; + if(id == NULL) { - // error + cl_log(LOG_ERR, "Must specify id tag in "); continue; } node_t *new_node = cl_malloc(sizeof(node_t)); - new_node->weight = 1.0; + new_node->weight = 1.0 * lpc++; + new_node->fixed = FALSE; new_node->id = cl_strdup(id); + 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)); - g_slist_append(node_list, new_node); - - nodes = nodes->next; } - g_slist_sort(node_list, sort_node_weight); + 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__); while(resources != NULL) { - const char *id = xmlGetProp(resources, "id"); - const char *priority = xmlGetProp(resources, "priority"); + 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) { - // error + cl_log(LOG_ERR, "Must specify id tag in "); continue; } resource_t *new_rsc = cl_malloc(sizeof(resource_t)); - new_rsc->xml = resources; // copy first + new_rsc->xml = xml_obj; // copy first new_rsc->priority = priority_f; - new_rsc->candidate_colors = g_slist_alloc(); + new_rsc->candidate_colors = NULL; new_rsc->color = NULL; new_rsc->provisional = TRUE; - new_rsc->allowed_nodes = g_slist_alloc(); - new_rsc->constraints = g_slist_alloc(); + new_rsc->allowed_nodes = node_list_dup(node_list); + new_rsc->constraints = NULL; new_rsc->id = cl_strdup(id); - g_slist_append(rsc_list, new_rsc); + cl_log(LOG_DEBUG, "Adding resource %s (%p)...", id, new_rsc); + rsc_list = g_slist_append(rsc_list, new_rsc); - resources = resources->next; } - g_slist_sort(rsc_list, sort_rsc_priority); + rsc_list = g_slist_sort(rsc_list, sort_rsc_priority); return TRUE; } gboolean -unpack_constraints(xmlNodePtr constraints) +unpack_constraints(xmlNodePtr constraints) { + 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) { - // error + cl_log(LOG_ERR, "Constraint must have an id"); continue; } - rsc_constraint_t *new_con =cl_malloc(sizeof(rsc_constraint_t)); + cl_log(LOG_DEBUG, "Processing constraint %s", id); + rsc_constraint_t *new_con = cl_malloc(sizeof(rsc_constraint_t)); rsc_constraint_t *inverted_con = NULL; - resource_t *rsc_lh = - pe_find_resource(rsc_list, - xmlGetProp(constraints, "rsc_id_1")); + const char *id_lh = xmlGetProp(xml_obj, "from"); + cl_log(LOG_DEBUG, "Looking up resource..."); + 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); + continue; + } new_con->id = cl_strdup(id); - - if(safe_str_eq("rsc_to_rsc", constraints->name)) { + new_con->rsc_lh = rsc_lh; + if(safe_str_eq("rsc_to_rsc", xml_obj->name)) { new_con->type = rsc_to_rsc; - const char *strength = xmlGetProp(constraints, "strength"); + 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(constraints, "type"); + 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_rh = NULL; - resource_t *rsc_rh = pe_find_resource(rsc_list, xmlGetProp(constraints, "rsc_id_2")); + 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); + continue; + } new_con->rsc_rh = rsc_rh; inverted_con = invert_constraint(new_con); - g_slist_insert_sorted(cons_list, new_con, sort_cons_strength); + 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); - } else if(safe_str_eq("rsc_to_node", constraints->name)) { + } 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; - new_con->node_rh = pe_find_node(node_list, rsc_lh, - xmlGetProp(constraints, "node_id")); - if(new_con->node_rh->fixed) { - // warning + const char *mod = xmlGetProp(xml_obj, "modifier"); + const char *weight = xmlGetProp(xml_obj, "weight"); + float weight_f = atof(weight); + new_con->weight = weight_f; + + cl_log(LOG_DEBUG, "Mod: %s", mod); + + 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 { - const char *mod = xmlGetProp(constraints, "modifier"); - const char *weight = xmlGetProp(constraints, "weight"); - float weight_f = atof(weight); - 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"); + rsc_constraint_t *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; } - - /* dont add it to the resource, - * the information is in the resouce's node list - */ + cl_free(new_con->id); + cl_free(new_con); } else { // error } - g_slist_insert_sorted(cons_list, new_con, sort_cons_strength); - constraints = constraints->next; } + 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) { - 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); - + rsc_constraint_t *cons = (rsc_constraint_t *) + g_slist_nth_data(constraints, lpc); + + cl_log(LOG_DEBUG, "Processing constraint %d", lpc); // take "lifetime" into account - if(is_active(cons) == FALSE) { + 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; - g_slist_append(rsc_lh->constraints, cons); + 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"); + continue; + } else if(cons->type == rsc_to_node) { - if(cons->node_rh->fixed) { + if(cons->node_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: - cons->node_rh->weight = cons->weight; - cons->node_rh->fixed = TRUE; + node_rh->weight = cons->weight; + node_rh->fixed = TRUE; break; case inc: - cons->node_rh->weight += cons->weight; + node_rh->weight += cons->weight; break; case dec: - cons->node_rh->weight -= cons->weight; + node_rh->weight -= cons->weight; + break; + case modifier_none: + // warning break; - case modifier_none: - // warning - break; } } /* dont add it to the resource, * the information is in the resouce's node list */ } else { // error } } return TRUE; } gboolean -filter_nodes(GSListPtr rsc_list) +filter_nodes(resource_t *rsc) { - int lpc = 0; - for(lpc = 0; lpc < g_slist_length(rsc_list); lpc++) { - resource_t *rsc = g_slist_nth_data(rsc_list, lpc); - int lpc2 = 0; - - for(lpc2 = 0; lpc2 < g_slist_length(rsc->allowed_nodes); lpc2++) { - node_t *node = g_slist_nth_data(rsc->allowed_nodes, lpc2); - if(node->weight < 0.0) { - g_slist_remove(rsc->allowed_nodes,node); - } - + cl_log(LOG_DEBUG, "Filtering nodes... %s", __FUNCTION__); + + int lpc2 = 0; + print_resource(rsc, FALSE); + + for(lpc2 = 0; lpc2 < g_slist_length(rsc->allowed_nodes); lpc2++) { + node_t *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; + int lpc = 0; for(lpc = 0; lpc < g_slist_length(rsc_list); lpc++) { resource_t *rsc = g_slist_nth_data(rsc_list, lpc); - if(safe_str_eq(rsc->id, id_rh)){ + 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 node_list, resource_t *rsc, const char *id) +pe_find_node(GSListPtr nodes, const char *id) { - int lpc = 0; + int lpc = 0; - for(lpc = 0; lpc < g_slist_length(rsc->allowed_nodes); lpc++) { - node_t *node = g_slist_nth_data(rsc->allowed_nodes, lpc); + 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; } } - - for(lpc = 0; lpc < g_slist_length(node_list); lpc++) { - node_t *node = g_slist_nth_data(node_list, lpc); - if(safe_str_eq(node->id, id)) { - return node_copy(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"); lrm_state = find_xml_node(lrm_state, "lrm_resource"); lrm_state = find_xml_node(lrm_state, "rsc_state"); - + status = status->next; if(id == NULL) { // error continue; } 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(node_list, new_cons->rsc_lh, node_id); + new_cons->node_rh = pe_find_node(new_cons->rsc_lh->allowed_nodes, node_id); new_cons->modifier = inc; - g_slist_append(cons_list, new_cons); + 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 { // 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); + 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")) { // 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")) { - g_slist_append(stonith_list, node); + stonith_list = g_slist_append(stonith_list, node); } } - status = status->next; } - g_slist_sort(cons_list, sort_cons_strength); + cons_list = g_slist_sort(cons_list, sort_cons_strength); return TRUE; } color_t * find_color(GSListPtr candidate_colors, color_t *other_color) { - // figure out what this does - return NULL; + int lpc = 0; + slist_iter(color, color_t, candidate_colors, lpc, + if(color->id == other_color->id) { + return color; + } + ); + return NULL; } gboolean is_active(rsc_constraint_t *cons) { - return TRUE; + return TRUE; } gint sort_rsc_priority(gconstpointer a, gconstpointer b) { - resource_t *resource1 = (resource_t*)a; - resource_t *resource2 = (resource_t*)b; + 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; + if(resource1->priority > resource2->priority) + return -1; - if(resource1->priority < resource2->priority) - return -1; + if(resource1->priority < resource2->priority) + return 1; - return 0; + return 0; } gint sort_cons_strength(gconstpointer a, gconstpointer b) { - rsc_constraint_t *rsc_constraint1 = (rsc_constraint_t*)a; - rsc_constraint_t *rsc_constraint2 = (rsc_constraint_t*)b; + 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; + if(rsc_constraint1->strength > rsc_constraint2->strength) + return 1; - if(rsc_constraint1->strength < rsc_constraint2->strength) - return -1; - return 0; + if(rsc_constraint1->strength < rsc_constraint2->strength) + return -1; + return 0; } gint sort_color_weight(gconstpointer a, gconstpointer b) { - color_t *color1 = (color_t*)a; - color_t *color2 = (color_t*)b; + 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->weight > color2->weight) - return 1; + if(color1->local_weight > color2->local_weight) + return -1; - if(color1->weight < color2->weight) - return -1; + if(color1->local_weight < color2->local_weight) + return 1; - return 0; + return 0; } gint sort_node_weight(gconstpointer a, gconstpointer b) { - node_t *node1 = (node_t*)a; - node_t *node2 = (node_t*)b; - - if(node1->weight > node2->weight) - return 1; + 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; + + if(node1->weight > node2->weight) + return -1; - if(node1->weight < node2->weight) - return -1; + if(node1->weight < node2->weight) + return 1; - return 0; + return 0; } - diff --git a/crm/pengine/pengine.h b/crm/pengine/pengine.h new file mode 100644 index 0000000000..d03c6d4573 --- /dev/null +++ b/crm/pengine/pengine.h @@ -0,0 +1,102 @@ +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, + 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; +}; + +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; + 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 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 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 new file mode 100644 index 0000000000..634a7247bf --- /dev/null +++ b/crm/pengine/ptest.c @@ -0,0 +1,363 @@ +/* $Id: ptest.c,v 1.1 2004/04/23 15:32:11 andrew Exp $ */ + +/* + * Copyright (C) 2004 Andrew Beekhof + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include +#include +#include +#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) +{ + 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 =#=#=#=#="); + + xmlNodePtr cib_object = file2xml(stdin); + + cl_log(LOG_INFO, "=#=#=#=#= Stage 1 =#=#=#=#="); + stage1(cib_object); + + int lpc = 0; + + cl_log(LOG_INFO, "========= Nodes ========="); + slist_iter(node, node_t, node_list, lpc, + print_node(node)); + + cl_log(LOG_INFO, "========= Resources ========="); + slist_iter(resource, resource_t, rsc_list, lpc, + print_resource(resource, FALSE)); + + + cl_log(LOG_INFO, "========= Constraints ========="); + slist_iter(constraint, rsc_constraint_t, cons_list, lpc, + print_cons(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)); + + cl_log(LOG_INFO, "========= Resources ========="); + slist_iter(resource, resource_t, rsc_list, lpc, + print_resource(resource, FALSE)); + + + cl_log(LOG_INFO, "========= Colors ========="); + slist_iter(color, color_t, colors, lpc, + print_color(color, FALSE)); + + cl_log(LOG_INFO, "========= Stonith List ========="); + slist_iter(node, node_t, stonith_list, lpc, + print_node(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(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 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) +{ + if(node == NULL) { + cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); + return; + } + cl_log(LOG_DEBUG, "Node %s: (weight=%f, fixed=%s)", + node->id, + node->weight, + node->fixed?"True":"False"); +}; + +void +print_color_details(struct color_shared_s *color, gboolean details) +{ + if(color == NULL) { + cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); + return; + } + cl_log(LOG_DEBUG, "Color %d: node=%s (from %d candidates)", + 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)); + } +} + +void +print_color(color_t *color, gboolean details) +{ + if(color == NULL) { + cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); + return; + } + cl_log(LOG_DEBUG, "Color %d: (weight=%f, node=%s, possible=%d)", + 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); + } +} +void +print_cons(rsc_constraint_t *cons, gboolean details) +{ + if(cons == NULL) { + cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); + return; + } + cl_log(LOG_DEBUG, "%s Constraint %s (%p):", + 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: + cl_log(LOG_DEBUG, + "\t%s --> %s, %s %f (node placement rule)", + cons->rsc_lh->id, + cons->node_rh->id, + modifier2text(cons->modifier), + cons->weight); + break; + case base_weight: + cl_log(LOG_ERR, "not supported"); + break; + } + } +}; + +void +print_resource(resource_t *rsc, gboolean details) +{ + if(rsc == NULL) { + cl_log(LOG_DEBUG, "%s: ", __FUNCTION__); + return; + } + cl_log(LOG_DEBUG, "%sResource %s: (priority=%f, color=%d)", + 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)); + } +} + +