diff -r c81e55653fba include/crm/msg_xml.h
--- a/include/crm/msg_xml.h Fri Oct 16 14:26:27 2009 +0200
+++ b/include/crm/msg_xml.h Fri Nov 06 15:20:33 2009 +0800
@@ -130,6 +130,7 @@
#define XML_TAG_ATTRS "attributes"
#define XML_TAG_PARAMS "parameters"
#define XML_TAG_PARAM "param"
+#define XML_TAG_UTILIZATION "utilization"
#define XML_TAG_RESOURCE_REF "resource_ref"
#define XML_CIB_TAG_RESOURCE "primitive"
diff -r c81e55653fba include/crm/pengine/status.h
--- a/include/crm/pengine/status.h Fri Oct 16 14:26:27 2009 +0200
+++ b/include/crm/pengine/status.h Fri Nov 06 15:20:33 2009 +0800
@@ -58,6 +58,8 @@
#define pe_flag_start_failure_fatal 0x00001000ULL
#define pe_flag_remove_after_stop 0x00002000ULL
+#define pe_flag_limit_utilization 0x00010000ULL
+
typedef struct pe_working_set_s
{
@@ -116,6 +118,8 @@
GHashTable *attrs; /* char* => char* */
enum node_type type;
+
+ GHashTable *utilization;
};
struct node_s {
@@ -186,6 +190,7 @@
GHashTable *meta;
GHashTable *parameters;
+ GHashTable *utilization;
GListPtr children; /* resource_t* */
};
diff -r c81e55653fba lib/pengine/common.c
--- a/lib/pengine/common.c Fri Oct 16 14:26:27 2009 +0200
+++ b/lib/pengine/common.c Fri Nov 06 15:20:33 2009 +0800
@@ -147,6 +147,10 @@
{ "node-health-red", NULL, "integer", NULL, "-INFINITY", &check_number,
"The score 'red' translates to in rsc_location constraints",
"Only used when node-health-strategy is set to custom or progressive." },
+
+ /*Resource utilization*/
+ { "limit-utilization", NULL, "boolean", NULL, "false", &check_boolean,
+ "Limit the resource utilization of nodes to avoid being overloaded", NULL},
};
void
diff -r c81e55653fba lib/pengine/complex.c
--- a/lib/pengine/complex.c Fri Oct 16 14:26:27 2009 +0200
+++ b/lib/pengine/complex.c Fri Nov 06 15:20:33 2009 +0800
@@ -371,6 +371,12 @@
if(safe_str_eq(class, "stonith")) {
set_bit_inplace(data_set->flags, pe_flag_have_stonith_resource);
}
+
+ (*rsc)->utilization = g_hash_table_new_full(
+ g_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
+
+ unpack_instance_attributes(data_set->input, (*rsc)->xml, XML_TAG_UTILIZATION, NULL,
+ (*rsc)->utilization, NULL, FALSE, data_set->now);
/* data_set->resources = g_list_append(data_set->resources, (*rsc)); */
return TRUE;
@@ -451,6 +457,9 @@
if(rsc->meta != NULL) {
g_hash_table_destroy(rsc->meta);
}
+ if(rsc->utilization != NULL) {
+ g_hash_table_destroy(rsc->utilization);
+ }
if(rsc->parent == NULL && is_set(rsc->flags, pe_rsc_orphan)) {
free_xml(rsc->xml);
}
diff -r c81e55653fba lib/pengine/status.c
--- a/lib/pengine/status.c Fri Oct 16 14:26:27 2009 +0200
+++ b/lib/pengine/status.c Fri Nov 06 15:20:33 2009 +0800
@@ -159,6 +159,9 @@
if(details->attrs != NULL) {
g_hash_table_destroy(details->attrs);
}
+ if(details->utilization != NULL) {
+ g_hash_table_destroy(details->utilization);
+ }
pe_free_shallow_adv(details->running_rsc, FALSE);
pe_free_shallow_adv(details->allocated_rsc, FALSE);
crm_free(details);
diff -r c81e55653fba lib/pengine/unpack.c
--- a/lib/pengine/unpack.c Fri Oct 16 14:26:27 2009 +0200
+++ b/lib/pengine/unpack.c Fri Nov 06 15:20:33 2009 +0800
@@ -165,6 +165,10 @@
crm_info("Node scores: 'red' = %s, 'yellow' = %s, 'green' = %s",
score2char(node_score_red),score2char(node_score_yellow),
score2char(node_score_green));
+
+ set_config_flag(data_set, "limit-utilization", pe_flag_limit_utilization);
+ crm_debug_2("Limit resource utilization: %s",
+ is_set(data_set->flags, pe_flag_limit_utilization)?"true":"false");
return TRUE;
}
@@ -233,6 +237,9 @@
new_node->details->attrs = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
+ new_node->details->utilization = g_hash_table_new_full(
+ g_str_hash, g_str_equal,
+ g_hash_destroy_str, g_hash_destroy_str);
/* if(data_set->have_quorum == FALSE */
/* && data_set->no_quorum_policy == no_quorum_stop) { */
@@ -258,6 +265,10 @@
}
add_node_attrs(xml_obj, new_node, FALSE, data_set);
+ unpack_instance_attributes(
+ data_set->input, xml_obj, XML_TAG_UTILIZATION, NULL,
+ new_node->details->utilization, NULL, FALSE, data_set->now);
+
data_set->nodes = g_list_append(data_set->nodes, new_node);
crm_debug_3("Done with node %s",
crm_element_value(xml_obj, XML_ATTR_UNAME));
diff -r c81e55653fba pengine/native.c
--- a/pengine/native.c Fri Oct 16 14:26:27 2009 +0200
+++ b/pengine/native.c Fri Nov 06 15:20:33 2009 +0800
@@ -250,6 +250,11 @@
native_color(resource_t *rsc, pe_working_set_t *data_set)
{
int alloc_details = scores_log_level+1;
+ GHashTableIter iter;
+ const char *key = NULL;
+ const char *value = NULL;
+ const char *capacity = NULL;
+
if(rsc->parent && is_not_set(rsc->parent->flags, pe_rsc_allocating)) {
/* never allocate children on their own */
crm_debug("Escalating allocation of %s to its parent: %s",
@@ -289,6 +294,24 @@
constraint->rsc_lh, rsc->id, rsc->allowed_nodes,
constraint->node_attribute, constraint->score/INFINITY, TRUE);
);
+
+ if (is_set(data_set->flags, pe_flag_limit_utilization)) {
+ slist_iter(
+ node, node_t, data_set->nodes, lpc,
+ g_hash_table_iter_init(&iter, rsc->utilization);
+ while (g_hash_table_iter_next(&iter, (gpointer)&key, (gpointer)&value)) {
+ capacity = g_hash_table_lookup(node->details->utilization, key);
+ if (capacity == NULL ||
+ crm_parse_int(capacity, "0") < crm_parse_int(value, "0")) {
+ crm_debug("Resource %s cannot be allocated to node %s: none of enough capacity",
+ rsc->id, node->details->uname);
+ resource_location(rsc, node, -INFINITY, "__limit_utilization_", data_set);
+ break;
+ }
+ }
+ );
+ dump_node_scores(alloc_details, rsc, "Post-utilization", rsc->allowed_nodes);
+ }
print_resource(LOG_DEBUG_2, "Allocating: ", rsc, FALSE);
if(rsc->next_role == RSC_ROLE_STOPPED) {
diff -r c81e55653fba pengine/utils.c
--- a/pengine/utils.c Fri Oct 16 14:26:27 2009 +0200
+++ b/pengine/utils.c Fri Nov 06 15:20:33 2009 +0800
@@ -256,6 +256,12 @@
gboolean
native_assign_node(resource_t *rsc, GListPtr nodes, node_t *chosen, gboolean force)
{
+ GHashTableIter iter;
+ const char *key = NULL;
+ const char *value = NULL;
+ const char *capacity = NULL;
+ char *remain_capacity = NULL;
+
CRM_ASSERT(rsc->variant == pe_native);
clear_bit(rsc->flags, pe_rsc_provisional);
@@ -284,6 +290,15 @@
old->details->allocated_rsc, rsc);
old->details->num_resources--;
old->count--;
+
+ g_hash_table_iter_init(&iter, rsc->utilization);
+ while (g_hash_table_iter_next(&iter, (gpointer)&key, (gpointer)&value)) {
+ capacity = g_hash_table_lookup(old->details->utilization, key);
+ if (capacity) {
+ remain_capacity = crm_itoa(crm_parse_int(capacity, "0") + crm_parse_int(value, "0"));
+ g_hash_table_replace(old->details->utilization, crm_strdup(key), remain_capacity);
+ }
+ }
}
crm_debug("Assigning %s to %s", chosen->details->uname, rsc->id);
@@ -293,6 +308,15 @@
chosen->details->allocated_rsc = g_list_append(chosen->details->allocated_rsc, rsc);
chosen->details->num_resources++;
chosen->count++;
+
+ g_hash_table_iter_init(&iter, rsc->utilization);
+ while (g_hash_table_iter_next(&iter, (gpointer)&key, (gpointer)&value)) {
+ capacity = g_hash_table_lookup(chosen->details->utilization, key);
+ if (capacity) {
+ remain_capacity = crm_itoa(crm_parse_int(capacity, "0") - crm_parse_int(value, "0"));
+ g_hash_table_replace(chosen->details->utilization, crm_strdup(key), remain_capacity);
+ }
+ }
return TRUE;
}
diff -r c81e55653fba xml/pacemaker.rng.in
--- a/xml/pacemaker.rng.in Fri Oct 16 14:26:27 2009 +0200
+++ b/xml/pacemaker.rng.in Fri Nov 06 15:20:33 2009 +0800
@@ -104,9 +104,14 @@
-
-
-
+
+
+
+
+
+
+
+
diff -r c81e55653fba xml/resources.rng.in
--- a/xml/resources.rng.in Fri Oct 16 14:26:27 2009 +0200
+++ b/xml/resources.rng.in Fri Nov 06 15:20:33 2009 +0800
@@ -39,6 +39,11 @@
+
+
+
+
+