diff -Nur pacemaker.orig/pengine/allocate.c pacemaker.mark/pengine/allocate.c --- pacemaker.orig/pengine/allocate.c 2009-04-08 02:49:50.000000000 -0500 +++ pacemaker.mark/pengine/allocate.c 2009-05-13 09:51:38.000000000 -0500 @@ -524,6 +524,228 @@ ); } +struct health_info_s { + int red_value; + int yellow_value; + int green_value; + int system_health; +}; + +typedef struct health_info_s health_info_t; + +void calculate_system_health (gpointer gKey, gpointer gValue, gpointer user_data); + +void +calculate_system_health (gpointer gKey, gpointer gValue, gpointer user_data) +{ + const char *key = (const char *)gKey; + const char *value = (const char *)gValue; + health_info_t *defaults = (health_info_t *)user_data; + char *health_value_end = NULL; + long int health_value = 0; + int health_valid_valid = 0; + + if (!gKey || !gValue || !user_data) { + return; + } + + errno = 0; + health_value = strtol (value, &health_value_end, 10); + if ( (errno == 0) + && (*health_value_end == '\0') + && (health_value >= INT_MIN && health_value <= INT_MAX) + ) { + health_valid_valid = 1; + } + + if (0 == strncmp (key, "#health", 7)) { + gboolean invalid = FALSE; + + if (safe_str_eq (value, "green")) { + /* Add green's value to the total health */ + defaults->system_health = merge_weights (defaults->green_value, defaults->system_health); + } else if (safe_str_eq (value, "yellow")) { + /* Add yellow's value to the total health */ + defaults->system_health = merge_weights (defaults->yellow_value, defaults->system_health); + } else if (safe_str_eq (value, "red")) { + /* Add red's value to total health */ + defaults->system_health = merge_weights (defaults->red_value, defaults->system_health); + } else if (health_valid_valid) { + /* Add specified value to the total health */ + defaults->system_health = merge_weights ((int)health_value, defaults->system_health); + } else { + /* Error! */ + crm_err ("Unknown health key (%s), value (%s)", key, value); + invalid = TRUE; + } + + if (!invalid) { + crm_debug_2 ("health key (%s), value (%s)", key, value); + } + } +} + +gboolean initialize_health_value (int *value, int def, const char *search, pe_working_set_t *data_set); + +gboolean +initialize_health_value (int *value, int def, const char *search, pe_working_set_t *data_set) +{ + xmlNode *node = NULL; + const char *attr_value = NULL; + + if (!value || !search || !data_set) { + return FALSE; + } + + *value = def; + + node = get_xpath_object (search, data_set->input, LOG_DEBUG); + + crm_debug_2 ("node = %lx, search = %s", (long unsigned int)node, search); + + if (!node) { + return FALSE; + } + + attr_value = crm_element_value (node, XML_NVPAIR_ATTR_VALUE); + + if (!attr_value) { + return FALSE; + } + + crm_debug_2 ("attr_value = %s", attr_value); + + *value = char2score (attr_value); + + return TRUE; +} + +gboolean apply_system_health_migrate_health_info (pe_working_set_t *data_set, health_info_t *health_info); + +gboolean +apply_system_health_migrate_health_info (pe_working_set_t *data_set, health_info_t *health_info) +{ + slist_iter( + rsc, resource_t, data_set->resources, lpc, + + crm_debug_2 ("resource = %s", rsc->id); + + slist_iter( + + node, node_t, data_set->nodes, lpc, + + const char *id = "SystemHealth"; + + health_info->system_health = 0; + + /* Search through the node hash table for system health entries. */ + g_hash_table_foreach ( + node->details->attrs, + calculate_system_health, + (gpointer)health_info); + + crm_info ("node %s has a total system health value of %d", + node->details->uname, + health_info->system_health); + + if (health_info->system_health != 0) { + rsc2node_new (id, rsc, health_info->system_health, node, data_set); + } + + ); + ); +} + +gboolean apply_system_health (pe_working_set_t *data_set); + +gboolean +apply_system_health(pe_working_set_t *data_set) +{ + xmlNode *node_health_strategy = NULL; + const char *health_strategy = NULL; + health_info_t health_info; + + node_health_strategy = get_xpath_object("//nvpair[@name='pe-node-health-strategy']", data_set->input, LOG_DEBUG); + + crm_debug_2 ("node_health_strategy = %lx", (long unsigned int)node_health_strategy); + + if (node_health_strategy) { + health_strategy = crm_element_value (node_health_strategy, XML_NVPAIR_ATTR_VALUE); + } + + if (!health_strategy) { + + /* Defaults to "none" which is do nothing. + */ + crm_info ("pe-node-health-strategy was not specified, defaulting to \"none\""); + + return TRUE; + + } else if (safe_str_eq (health_strategy, "none")) { + + /* Do nothing. + */ + crm_info ("pe-node-health-strategy was \"none\""); + + return TRUE; + + } else if (safe_str_eq (health_strategy, "custom")) { + + /* Requires the admin to configure the rsc_location + * constraints manually. + */ + crm_info ("pe-node-health-strategy was \"custom\""); + + return TRUE; + + } else if (safe_str_eq (health_strategy, "migrate-on-red")) { + + /* Resources on nodes which have health values of red are + * weighted away from that node. + */ + crm_info ("pe-node-health-strategy was \"migrate-on-red\""); + + initialize_health_value (&health_info.red_value, + -INFINITY, + "//nvpair[@name='pe-node-health-score-red']", + data_set); + initialize_health_value (&health_info.yellow_value, + 0, + "//nvpair[@name='pe-node-health-score-yellow']", + data_set); + initialize_health_value (&health_info.green_value, + 0, + "//nvpair[@name='pe-node-health-score-green']", + data_set); + + return apply_system_health_migrate_health_info (data_set, &health_info); + + } else if (safe_str_eq (health_strategy, "migrate-on-not-green")) { + + /* Resources on nodes which have health values of red or yellow + * are weighted away from that node. + */ + crm_info ("pe-node-health-strategy was \"migrate-on-not-green\""); + + initialize_health_value (&health_info.red_value, + -INFINITY, + "//nvpair[@name='pe-node-health-score-red']", + data_set); + initialize_health_value (&health_info.yellow_value, + -INFINITY, + "//nvpair[@name='pe-node-health-score-yellow']", + data_set); + initialize_health_value (&health_info.green_value, + 0, + "//nvpair[@name='pe-node-health-score-green']", + data_set); + + return apply_system_health_migrate_health_info (data_set, &health_info); + } + + return FALSE; +} + gboolean stage0(pe_working_set_t *data_set) { @@ -539,6 +761,8 @@ set_alloc_actions(data_set); unpack_constraints(cib_constraints, data_set); + apply_system_health(data_set); + return TRUE; }