14 static GList *find_colocated_rscs(GList *colocated_rscs,
pe_resource_t * rsc,
17 static GList *group_find_colocated_rscs(GList *colocated_rscs,
pe_resource_t * rsc,
20 static void group_add_unallocated_utilization(GHashTable * all_utilization,
pe_resource_t * rsc,
30 utilization_value(
const char *s)
46 do_compare_capacity1(gpointer key, gpointer value, gpointer user_data)
48 int node1_capacity = 0;
49 int node2_capacity = 0;
50 struct compare_data *
data = user_data;
52 node1_capacity = utilization_value(value);
53 node2_capacity = utilization_value(g_hash_table_lookup(data->node2->details->utilization, key));
55 if (node1_capacity > node2_capacity) {
57 }
else if (node1_capacity < node2_capacity) {
63 do_compare_capacity2(gpointer key, gpointer value, gpointer user_data)
65 int node1_capacity = 0;
66 int node2_capacity = 0;
67 struct compare_data *data = user_data;
69 if (g_hash_table_lookup_extended(data->node1->details->utilization, key, NULL, NULL)) {
74 node2_capacity = utilization_value(value);
76 if (node1_capacity > node2_capacity) {
78 }
else if (node1_capacity < node2_capacity) {
89 struct compare_data data;
101 struct calculate_data {
102 GHashTable *current_utilization;
107 do_calculate_utilization(gpointer key, gpointer value, gpointer user_data)
109 const char *current = NULL;
111 struct calculate_data *data = user_data;
113 current = g_hash_table_lookup(data->current_utilization, key);
115 result = pcmk__itoa(utilization_value(current) + utilization_value(value));
116 g_hash_table_replace(data->current_utilization, strdup(key), result);
118 }
else if (current) {
119 result = pcmk__itoa(utilization_value(current) - utilization_value(value));
120 g_hash_table_replace(data->current_utilization, strdup(key), result);
129 GHashTable * utilization, gboolean plus)
131 struct calculate_data data;
133 data.current_utilization = current_utilization;
136 g_hash_table_foreach(utilization, do_calculate_utilization, &data);
140 struct capacity_data {
147 check_capacity(gpointer key, gpointer value, gpointer user_data)
151 struct capacity_data *data = user_data;
153 required = utilization_value(value);
154 remaining = utilization_value(g_hash_table_lookup(data->node->details->utilization, key));
156 if (required > remaining) {
160 crm_debug(
"Node %s does not have enough %s for %s: required=%d remaining=%d",
161 data->node->details->uname, (
char *)key, data->rsc_id, required, remaining);
162 data->is_enough = FALSE;
167 have_enough_capacity(
pe_node_t * node,
const char * rsc_id, GHashTable * utilization)
169 struct capacity_data data;
172 data.rsc_id = rsc_id;
173 data.is_enough = TRUE;
175 g_hash_table_foreach(utilization, check_capacity, &data);
177 return data.is_enough;
182 native_add_unallocated_utilization(GHashTable * all_utilization,
pe_resource_t * rsc)
192 add_unallocated_utilization(GHashTable * all_utilization,
pe_resource_t * rsc,
200 pe_rsc_trace(orig_rsc,
"%s: Adding %s as colocated utilization",
201 orig_rsc->
id, rsc->
id);
202 native_add_unallocated_utilization(all_utilization, rsc);
205 pe_rsc_trace(orig_rsc,
"%s: Adding %s as colocated utilization",
206 orig_rsc->
id, rsc->
id);
207 group_add_unallocated_utilization(all_utilization, rsc, all_rscs);
209 }
else if (pe_rsc_is_clone(rsc)) {
210 GList *gIter1 = NULL;
211 gboolean existing = FALSE;
215 for (; gIter1 != NULL; gIter1 = gIter1->next) {
217 GList *gIter2 = NULL;
219 if (g_list_find(all_rscs, child)) {
225 for (; gIter2 != NULL; gIter2 = gIter2->next) {
228 if (g_list_find(all_rscs, grandchild)) {
229 pe_rsc_trace(orig_rsc,
"%s: Adding %s as colocated utilization",
230 orig_rsc->
id, child->
id);
231 add_unallocated_utilization(all_utilization, child, all_rscs, orig_rsc);
240 if (!existing && (rsc->
children != NULL)) {
243 pe_rsc_trace(orig_rsc,
"%s: Adding %s as colocated utilization",
244 orig_rsc->
id,
ID(first_child->
xml));
245 add_unallocated_utilization(all_utilization, first_child, all_rscs, orig_rsc);
251 sum_unallocated_utilization(
pe_resource_t * rsc, GList *colocated_rscs)
254 GList *all_rscs = NULL;
257 all_rscs = g_list_copy(colocated_rscs);
258 if (g_list_find(all_rscs, rsc) == FALSE) {
259 all_rscs = g_list_append(all_rscs, rsc);
262 for (gIter = all_rscs; gIter != NULL; gIter = gIter->next) {
269 pe_rsc_trace(rsc,
"%s: Processing unallocated colocated %s", rsc->
id, listed_rsc->
id);
270 add_unallocated_utilization(all_utilization, listed_rsc, all_rscs, rsc);
273 g_list_free(all_rscs);
275 return all_utilization;
284 return colocated_rscs;
286 }
else if (g_list_find(colocated_rscs, rsc)) {
287 return colocated_rscs;
290 crm_trace(
"%s: %s is supposed to be colocated with %s", orig_rsc->
id, rsc->
id, orig_rsc->
id);
291 colocated_rscs = g_list_append(colocated_rscs, rsc);
293 for (gIter = rsc->
rsc_cons; gIter != NULL; gIter = gIter->next) {
298 if (rsc_rh == orig_rsc) {
307 colocated_rscs = group_find_colocated_rscs(colocated_rscs, rsc_rh, orig_rsc);
310 colocated_rscs = find_colocated_rscs(colocated_rscs, rsc_rh, orig_rsc);
315 for (gIter = rsc->
rsc_cons_lhs; gIter != NULL; gIter = gIter->next) {
320 if (rsc_lh == orig_rsc) {
324 if (pe_rsc_is_clone(rsc_lh) == FALSE && pe_rsc_is_clone(rsc)) {
334 colocated_rscs = group_find_colocated_rscs(colocated_rscs, rsc_lh, orig_rsc);
337 colocated_rscs = find_colocated_rscs(colocated_rscs, rsc_lh, orig_rsc);
342 return colocated_rscs;
348 CRM_CHECK(rsc && prefer && data_set,
return);
351 GList *colocated_rscs = NULL;
352 gboolean any_capable = FALSE;
355 colocated_rscs = find_colocated_rscs(colocated_rscs, rsc, rsc);
356 if (colocated_rscs) {
357 GHashTable *unallocated_utilization = NULL;
362 unallocated_utilization = sum_unallocated_utilization(rsc, colocated_rscs);
365 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
370 if (have_enough_capacity(node, rscs_id, unallocated_utilization)) {
374 if (most_capable_node == NULL ||
377 most_capable_node = node;
383 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
388 if (have_enough_capacity(node, rscs_id, unallocated_utilization) == FALSE) {
390 "Resource %s and its colocated resources"
391 " cannot be allocated to node %s: not enough capacity",
397 }
else if (*prefer == NULL) {
398 *prefer = most_capable_node;
401 if (unallocated_utilization) {
402 g_hash_table_destroy(unallocated_utilization);
405 g_list_free(colocated_rscs);
409 if (any_capable == FALSE) {
411 while (g_hash_table_iter_next(&iter, NULL, (
void **)&node)) {
416 if (have_enough_capacity(node, rsc->
id, rsc->
utilization) == FALSE) {
418 "Resource %s cannot be allocated to node %s:"
419 " not enough capacity",
429 #define VARIANT_GROUP 1
435 group_variant_data_t *group_data = NULL;
437 get_group_variant_data(group_data, rsc);
438 if (group_data->colocated || pe_rsc_is_clone(rsc->
parent)) {
441 for (; gIter != NULL; gIter = gIter->next) {
444 colocated_rscs = find_colocated_rscs(colocated_rscs, child_rsc, orig_rsc);
448 if (group_data->first_child) {
449 colocated_rscs = find_colocated_rscs(colocated_rscs, group_data->first_child, orig_rsc);
453 colocated_rscs = find_colocated_rscs(colocated_rscs, rsc, orig_rsc);
455 return colocated_rscs;
459 group_add_unallocated_utilization(GHashTable * all_utilization,
pe_resource_t * rsc,
462 group_variant_data_t *group_data = NULL;
464 get_group_variant_data(group_data, rsc);
465 if (group_data->colocated || pe_rsc_is_clone(rsc->
parent)) {
468 for (; gIter != NULL; gIter = gIter->next) {
472 g_list_find(all_rscs, child_rsc) == FALSE) {
473 native_add_unallocated_utilization(all_utilization, child_rsc);
478 if (group_data->first_child &&
480 g_list_find(all_rscs, group_data->first_child) == FALSE) {
481 native_add_unallocated_utilization(all_utilization, group_data->first_child);
#define CRM_CHECK(expr, failure_action)
#define pe_rsc_debug(rsc, fmt, args...)
#define pe__show_node_weights(level, rsc, text, nodes, data_set)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
void resource_location(pe_resource_t *rsc, pe_node_t *node, int score, const char *tag, pe_working_set_t *data_set)
gboolean can_run_resources(const pe_node_t *node)
void calculate_utilization(GHashTable *current_utilization, GHashTable *utilization, gboolean plus)
#define pe_rsc_provisional
#define crm_debug(fmt, args...)
#define crm_trace(fmt, args...)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void process_utilization(pe_resource_t *rsc, pe_node_t **prefer, pe_working_set_t *data_set)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
struct pe_node_shared_s * details
enum pe_obj_types variant
const char * placement_strategy
enum filter_colocation_res filter_colocation_constraint(pe_resource_t *rsc_lh, pe_resource_t *rsc_rh, pcmk__colocation_t *constraint, gboolean preview)
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
#define pe_rsc_trace(rsc, fmt, args...)
int compare_capacity(const pe_node_t *node1, const pe_node_t *node2)
GHashTable * allowed_nodes