This source file includes following definitions.
- cmp_dependent_priority
- cmp_primary_priority
- pcmk__add_this_with
- pcmk__add_this_with_list
- pcmk__add_with_this
- pcmk__add_with_this_list
- anti_colocation_order
- pcmk__new_colocation
- unpack_influence
- unpack_colocation_set
- colocate_rsc_sets
- unpack_simple_colocation
- unpack_colocation_tags
- pcmk__unpack_colocation
- mark_action_blocked
- pcmk__block_colocation_dependents
- pcmk__colocation_affects
- pcmk__apply_coloc_to_weights
- pcmk__apply_coloc_to_priority
- best_node_score_matching_attr
- add_node_scores_matching_attr
- pcmk__add_colocated_node_scores
- pcmk__add_dependent_scores
- pcmk__with_this_colocations
- pcmk__this_with_colocations
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdbool.h>
13 #include <glib.h>
14
15 #include <crm/crm.h>
16 #include <crm/pengine/status.h>
17 #include <pacemaker-internal.h>
18
19 #include "crm/common/util.h"
20 #include "crm/common/xml_internal.h"
21 #include "crm/msg_xml.h"
22 #include "libpacemaker_private.h"
23
24 #define EXPAND_CONSTRAINT_IDREF(__set, __rsc, __name) do { \
25 __rsc = pcmk__find_constraint_resource(data_set->resources, __name); \
26 if (__rsc == NULL) { \
27 pcmk__config_err("%s: No resource found for %s", __set, __name); \
28 return; \
29 } \
30 } while(0)
31
32
33 #define INFINITY_HACK (INFINITY * -100)
34
35 static gint
36 cmp_dependent_priority(gconstpointer a, gconstpointer b)
37 {
38 const pcmk__colocation_t *rsc_constraint1 = (const pcmk__colocation_t *) a;
39 const pcmk__colocation_t *rsc_constraint2 = (const pcmk__colocation_t *) b;
40
41 if (a == NULL) {
42 return 1;
43 }
44 if (b == NULL) {
45 return -1;
46 }
47
48 CRM_ASSERT(rsc_constraint1->dependent != NULL);
49 CRM_ASSERT(rsc_constraint1->primary != NULL);
50
51 if (rsc_constraint1->dependent->priority > rsc_constraint2->dependent->priority) {
52 return -1;
53 }
54
55 if (rsc_constraint1->dependent->priority < rsc_constraint2->dependent->priority) {
56 return 1;
57 }
58
59
60 if (rsc_constraint1->dependent->variant > rsc_constraint2->dependent->variant) {
61 return -1;
62 }
63 if (rsc_constraint1->dependent->variant < rsc_constraint2->dependent->variant) {
64 return 1;
65 }
66
67
68
69
70
71 if (rsc_constraint1->dependent->variant == pe_clone) {
72 if (pcmk_is_set(rsc_constraint1->dependent->flags, pe_rsc_promotable)
73 && !pcmk_is_set(rsc_constraint2->dependent->flags, pe_rsc_promotable)) {
74 return -1;
75 } else if (!pcmk_is_set(rsc_constraint1->dependent->flags, pe_rsc_promotable)
76 && pcmk_is_set(rsc_constraint2->dependent->flags, pe_rsc_promotable)) {
77 return 1;
78 }
79 }
80
81 return strcmp(rsc_constraint1->dependent->id,
82 rsc_constraint2->dependent->id);
83 }
84
85 static gint
86 cmp_primary_priority(gconstpointer a, gconstpointer b)
87 {
88 const pcmk__colocation_t *rsc_constraint1 = (const pcmk__colocation_t *) a;
89 const pcmk__colocation_t *rsc_constraint2 = (const pcmk__colocation_t *) b;
90
91 if (a == NULL) {
92 return 1;
93 }
94 if (b == NULL) {
95 return -1;
96 }
97
98 CRM_ASSERT(rsc_constraint1->dependent != NULL);
99 CRM_ASSERT(rsc_constraint1->primary != NULL);
100
101 if (rsc_constraint1->primary->priority > rsc_constraint2->primary->priority) {
102 return -1;
103 }
104
105 if (rsc_constraint1->primary->priority < rsc_constraint2->primary->priority) {
106 return 1;
107 }
108
109
110 if (rsc_constraint1->primary->variant > rsc_constraint2->primary->variant) {
111 return -1;
112 } else if (rsc_constraint1->primary->variant < rsc_constraint2->primary->variant) {
113 return 1;
114 }
115
116
117
118
119
120 if (rsc_constraint1->primary->variant == pe_clone) {
121 if (pcmk_is_set(rsc_constraint1->primary->flags, pe_rsc_promotable)
122 && !pcmk_is_set(rsc_constraint2->primary->flags, pe_rsc_promotable)) {
123 return -1;
124 } else if (!pcmk_is_set(rsc_constraint1->primary->flags, pe_rsc_promotable)
125 && pcmk_is_set(rsc_constraint2->primary->flags, pe_rsc_promotable)) {
126 return 1;
127 }
128 }
129
130 return strcmp(rsc_constraint1->primary->id, rsc_constraint2->primary->id);
131 }
132
133
134
135
136
137
138
139
140
141
142 void
143 pcmk__add_this_with(GList **list, const pcmk__colocation_t *colocation)
144 {
145 CRM_ASSERT((list != NULL) && (colocation != NULL));
146
147 crm_trace("Adding colocation %s (%s with %s%s%s @%d) "
148 "to 'this with' list",
149 colocation->id, colocation->dependent->id,
150 colocation->primary->id,
151 (colocation->node_attribute == NULL)? "" : " using ",
152 pcmk__s(colocation->node_attribute, ""),
153 colocation->score);
154 *list = g_list_insert_sorted(*list, (gpointer) colocation,
155 cmp_primary_priority);
156 }
157
158
159
160
161
162
163
164
165
166
167 void
168 pcmk__add_this_with_list(GList **list, GList *addition)
169 {
170 CRM_CHECK((list != NULL), return);
171
172 if (*list == NULL) {
173 crm_trace("Copying %u 'this with' colocations to new list",
174 g_list_length(addition));
175 *list = g_list_copy(addition);
176 } else {
177 while (addition != NULL) {
178 pcmk__add_this_with(list, addition->data);
179 addition = addition->next;
180 }
181 }
182 }
183
184
185
186
187
188
189
190
191
192
193 void
194 pcmk__add_with_this(GList **list, const pcmk__colocation_t *colocation)
195 {
196 CRM_ASSERT((list != NULL) && (colocation != NULL));
197
198 crm_trace("Adding colocation %s (%s with %s%s%s @%d) "
199 "to 'with this' list",
200 colocation->id, colocation->dependent->id,
201 colocation->primary->id,
202 (colocation->node_attribute == NULL)? "" : " using ",
203 pcmk__s(colocation->node_attribute, ""),
204 colocation->score);
205 *list = g_list_insert_sorted(*list, (gpointer) colocation,
206 cmp_dependent_priority);
207 }
208
209
210
211
212
213
214
215
216
217
218 void
219 pcmk__add_with_this_list(GList **list, GList *addition)
220 {
221 CRM_CHECK((list != NULL), return);
222
223 if (*list == NULL) {
224 crm_trace("Copying %u 'with this' colocations to new list",
225 g_list_length(addition));
226 *list = g_list_copy(addition);
227 } else {
228 while (addition != NULL) {
229 pcmk__add_with_this(list, addition->data);
230 addition = addition->next;
231 }
232 }
233 }
234
235
236
237
238
239
240
241
242
243
244 static void
245 anti_colocation_order(pe_resource_t *first_rsc, int first_role,
246 pe_resource_t *then_rsc, int then_role)
247 {
248 const char *first_tasks[] = { NULL, NULL };
249 const char *then_tasks[] = { NULL, NULL };
250
251
252 if (first_role == RSC_ROLE_PROMOTED) {
253 first_tasks[0] = CRMD_ACTION_DEMOTE;
254
255 } else {
256 first_tasks[0] = CRMD_ACTION_STOP;
257
258 if (first_role == RSC_ROLE_UNPROMOTED) {
259 first_tasks[1] = CRMD_ACTION_PROMOTE;
260 }
261 }
262
263
264 if (then_role == RSC_ROLE_PROMOTED) {
265 then_tasks[0] = CRMD_ACTION_PROMOTE;
266
267 } else {
268 then_tasks[0] = CRMD_ACTION_START;
269
270 if (then_role == RSC_ROLE_UNPROMOTED) {
271 then_tasks[1] = CRMD_ACTION_DEMOTE;
272 }
273 }
274
275 for (int first_lpc = 0;
276 (first_lpc <= 1) && (first_tasks[first_lpc] != NULL); first_lpc++) {
277
278 for (int then_lpc = 0;
279 (then_lpc <= 1) && (then_tasks[then_lpc] != NULL); then_lpc++) {
280
281 pcmk__order_resource_actions(first_rsc, first_tasks[first_lpc],
282 then_rsc, then_tasks[then_lpc],
283 pe_order_anti_colocation);
284 }
285 }
286 }
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302 void
303 pcmk__new_colocation(const char *id, const char *node_attr, int score,
304 pe_resource_t *dependent, pe_resource_t *primary,
305 const char *dependent_role, const char *primary_role,
306 bool influence, pe_working_set_t *data_set)
307 {
308 pcmk__colocation_t *new_con = NULL;
309
310 if (score == 0) {
311 crm_trace("Ignoring colocation '%s' because score is 0", id);
312 return;
313 }
314 if ((dependent == NULL) || (primary == NULL)) {
315 pcmk__config_err("Ignoring colocation '%s' because resource "
316 "does not exist", id);
317 return;
318 }
319
320 new_con = calloc(1, sizeof(pcmk__colocation_t));
321 if (new_con == NULL) {
322 return;
323 }
324
325 if (pcmk__str_eq(dependent_role, RSC_ROLE_STARTED_S,
326 pcmk__str_null_matches|pcmk__str_casei)) {
327 dependent_role = RSC_ROLE_UNKNOWN_S;
328 }
329
330 if (pcmk__str_eq(primary_role, RSC_ROLE_STARTED_S,
331 pcmk__str_null_matches|pcmk__str_casei)) {
332 primary_role = RSC_ROLE_UNKNOWN_S;
333 }
334
335 new_con->id = id;
336 new_con->dependent = dependent;
337 new_con->primary = primary;
338 new_con->score = score;
339 new_con->dependent_role = text2role(dependent_role);
340 new_con->primary_role = text2role(primary_role);
341 new_con->node_attribute = node_attr;
342 new_con->influence = influence;
343
344 if (node_attr == NULL) {
345 node_attr = CRM_ATTR_UNAME;
346 }
347
348 pe_rsc_trace(dependent, "%s ==> %s (%s %d)",
349 dependent->id, primary->id, node_attr, score);
350
351 pcmk__add_this_with(&(dependent->rsc_cons), new_con);
352 pcmk__add_with_this(&(primary->rsc_cons_lhs), new_con);
353
354 data_set->colocation_constraints = g_list_append(data_set->colocation_constraints,
355 new_con);
356
357 if (score <= -INFINITY) {
358 anti_colocation_order(dependent, new_con->dependent_role, primary,
359 new_con->primary_role);
360 anti_colocation_order(primary, new_con->primary_role, dependent,
361 new_con->dependent_role);
362 }
363 }
364
365
366
367
368
369
370
371
372
373
374
375
376 static bool
377 unpack_influence(const char *coloc_id, const pe_resource_t *rsc,
378 const char *influence_s)
379 {
380 if (influence_s != NULL) {
381 int influence_i = 0;
382
383 if (crm_str_to_boolean(influence_s, &influence_i) < 0) {
384 pcmk__config_err("Constraint '%s' has invalid value for "
385 XML_COLOC_ATTR_INFLUENCE " (using default)",
386 coloc_id);
387 } else {
388 return (influence_i != 0);
389 }
390 }
391 return pcmk_is_set(rsc->flags, pe_rsc_critical);
392 }
393
394 static void
395 unpack_colocation_set(xmlNode *set, int score, const char *coloc_id,
396 const char *influence_s, pe_working_set_t *data_set)
397 {
398 xmlNode *xml_rsc = NULL;
399 pe_resource_t *with = NULL;
400 pe_resource_t *resource = NULL;
401 const char *set_id = ID(set);
402 const char *role = crm_element_value(set, "role");
403 const char *ordering = crm_element_value(set, "ordering");
404 int local_score = score;
405 bool sequential = false;
406
407 const char *score_s = crm_element_value(set, XML_RULE_ATTR_SCORE);
408
409 if (score_s) {
410 local_score = char2score(score_s);
411 }
412 if (local_score == 0) {
413 crm_trace("Ignoring colocation '%s' for set '%s' because score is 0",
414 coloc_id, set_id);
415 return;
416 }
417
418 if (ordering == NULL) {
419 ordering = "group";
420 }
421
422 if (pcmk__xe_get_bool_attr(set, "sequential", &sequential) == pcmk_rc_ok && !sequential) {
423 return;
424
425 } else if ((local_score > 0)
426 && pcmk__str_eq(ordering, "group", pcmk__str_casei)) {
427 for (xml_rsc = first_named_child(set, XML_TAG_RESOURCE_REF);
428 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
429
430 EXPAND_CONSTRAINT_IDREF(set_id, resource, ID(xml_rsc));
431 if (with != NULL) {
432 pe_rsc_trace(resource, "Colocating %s with %s", resource->id, with->id);
433 pcmk__new_colocation(set_id, NULL, local_score, resource,
434 with, role, role,
435 unpack_influence(coloc_id, resource,
436 influence_s), data_set);
437 }
438 with = resource;
439 }
440
441 } else if (local_score > 0) {
442 pe_resource_t *last = NULL;
443
444 for (xml_rsc = first_named_child(set, XML_TAG_RESOURCE_REF);
445 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
446
447 EXPAND_CONSTRAINT_IDREF(set_id, resource, ID(xml_rsc));
448 if (last != NULL) {
449 pe_rsc_trace(resource, "Colocating %s with %s",
450 last->id, resource->id);
451 pcmk__new_colocation(set_id, NULL, local_score, last,
452 resource, role, role,
453 unpack_influence(coloc_id, last,
454 influence_s), data_set);
455 }
456
457 last = resource;
458 }
459
460 } else {
461
462
463
464
465
466 for (xml_rsc = first_named_child(set, XML_TAG_RESOURCE_REF);
467 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
468
469 xmlNode *xml_rsc_with = NULL;
470 bool influence = true;
471
472 EXPAND_CONSTRAINT_IDREF(set_id, resource, ID(xml_rsc));
473 influence = unpack_influence(coloc_id, resource, influence_s);
474
475 for (xml_rsc_with = first_named_child(set, XML_TAG_RESOURCE_REF);
476 xml_rsc_with != NULL;
477 xml_rsc_with = crm_next_same_xml(xml_rsc_with)) {
478
479 if (pcmk__str_eq(resource->id, ID(xml_rsc_with),
480 pcmk__str_casei)) {
481 break;
482 }
483 EXPAND_CONSTRAINT_IDREF(set_id, with, ID(xml_rsc_with));
484 pe_rsc_trace(resource, "Anti-Colocating %s with %s", resource->id,
485 with->id);
486 pcmk__new_colocation(set_id, NULL, local_score,
487 resource, with, role, role,
488 influence, data_set);
489 }
490 }
491 }
492 }
493
494 static void
495 colocate_rsc_sets(const char *id, xmlNode *set1, xmlNode *set2, int score,
496 const char *influence_s, pe_working_set_t *data_set)
497 {
498 xmlNode *xml_rsc = NULL;
499 pe_resource_t *rsc_1 = NULL;
500 pe_resource_t *rsc_2 = NULL;
501
502 const char *role_1 = crm_element_value(set1, "role");
503 const char *role_2 = crm_element_value(set2, "role");
504
505 int rc = pcmk_rc_ok;
506 bool sequential = false;
507
508 if (score == 0) {
509 crm_trace("Ignoring colocation '%s' between sets because score is 0",
510 id);
511 return;
512 }
513
514 rc = pcmk__xe_get_bool_attr(set1, "sequential", &sequential);
515 if (rc != pcmk_rc_ok || sequential) {
516
517 xml_rsc = first_named_child(set1, XML_TAG_RESOURCE_REF);
518 if (xml_rsc != NULL) {
519 EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc));
520 }
521 }
522
523 rc = pcmk__xe_get_bool_attr(set2, "sequential", &sequential);
524 if (rc != pcmk_rc_ok || sequential) {
525
526 const char *rid = NULL;
527
528 for (xml_rsc = first_named_child(set2, XML_TAG_RESOURCE_REF);
529 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
530
531 rid = ID(xml_rsc);
532 }
533 EXPAND_CONSTRAINT_IDREF(id, rsc_2, rid);
534 }
535
536 if ((rsc_1 != NULL) && (rsc_2 != NULL)) {
537 pcmk__new_colocation(id, NULL, score, rsc_1, rsc_2, role_1, role_2,
538 unpack_influence(id, rsc_1, influence_s),
539 data_set);
540
541 } else if (rsc_1 != NULL) {
542 bool influence = unpack_influence(id, rsc_1, influence_s);
543
544 for (xml_rsc = first_named_child(set2, XML_TAG_RESOURCE_REF);
545 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
546
547 EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc));
548 pcmk__new_colocation(id, NULL, score, rsc_1, rsc_2, role_1,
549 role_2, influence, data_set);
550 }
551
552 } else if (rsc_2 != NULL) {
553 for (xml_rsc = first_named_child(set1, XML_TAG_RESOURCE_REF);
554 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
555
556 EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc));
557 pcmk__new_colocation(id, NULL, score, rsc_1, rsc_2, role_1,
558 role_2,
559 unpack_influence(id, rsc_1, influence_s),
560 data_set);
561 }
562
563 } else {
564 for (xml_rsc = first_named_child(set1, XML_TAG_RESOURCE_REF);
565 xml_rsc != NULL; xml_rsc = crm_next_same_xml(xml_rsc)) {
566
567 xmlNode *xml_rsc_2 = NULL;
568 bool influence = true;
569
570 EXPAND_CONSTRAINT_IDREF(id, rsc_1, ID(xml_rsc));
571 influence = unpack_influence(id, rsc_1, influence_s);
572
573 for (xml_rsc_2 = first_named_child(set2, XML_TAG_RESOURCE_REF);
574 xml_rsc_2 != NULL;
575 xml_rsc_2 = crm_next_same_xml(xml_rsc_2)) {
576
577 EXPAND_CONSTRAINT_IDREF(id, rsc_2, ID(xml_rsc_2));
578 pcmk__new_colocation(id, NULL, score, rsc_1, rsc_2,
579 role_1, role_2, influence,
580 data_set);
581 }
582 }
583 }
584 }
585
586 static void
587 unpack_simple_colocation(xmlNode *xml_obj, const char *id,
588 const char *influence_s, pe_working_set_t *data_set)
589 {
590 int score_i = 0;
591
592 const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE);
593 const char *dependent_id = crm_element_value(xml_obj,
594 XML_COLOC_ATTR_SOURCE);
595 const char *primary_id = crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET);
596 const char *dependent_role = crm_element_value(xml_obj,
597 XML_COLOC_ATTR_SOURCE_ROLE);
598 const char *primary_role = crm_element_value(xml_obj,
599 XML_COLOC_ATTR_TARGET_ROLE);
600 const char *attr = crm_element_value(xml_obj, XML_COLOC_ATTR_NODE_ATTR);
601
602
603 const char *dependent_instance = crm_element_value(xml_obj,
604 XML_COLOC_ATTR_SOURCE_INSTANCE);
605
606 const char *primary_instance = crm_element_value(xml_obj,
607 XML_COLOC_ATTR_TARGET_INSTANCE);
608
609 pe_resource_t *dependent = pcmk__find_constraint_resource(data_set->resources,
610 dependent_id);
611 pe_resource_t *primary = pcmk__find_constraint_resource(data_set->resources,
612 primary_id);
613
614 if (dependent_instance != NULL) {
615 pe_warn_once(pe_wo_coloc_inst,
616 "Support for " XML_COLOC_ATTR_SOURCE_INSTANCE " is "
617 "deprecated and will be removed in a future release.");
618 }
619
620 if (primary_instance != NULL) {
621 pe_warn_once(pe_wo_coloc_inst,
622 "Support for " XML_COLOC_ATTR_TARGET_INSTANCE " is "
623 "deprecated and will be removed in a future release.");
624 }
625
626 if (dependent == NULL) {
627 pcmk__config_err("Ignoring constraint '%s' because resource '%s' "
628 "does not exist", id, dependent_id);
629 return;
630
631 } else if (primary == NULL) {
632 pcmk__config_err("Ignoring constraint '%s' because resource '%s' "
633 "does not exist", id, primary_id);
634 return;
635
636 } else if ((dependent_instance != NULL) && !pe_rsc_is_clone(dependent)) {
637 pcmk__config_err("Ignoring constraint '%s' because resource '%s' "
638 "is not a clone but instance '%s' was requested",
639 id, dependent_id, dependent_instance);
640 return;
641
642 } else if ((primary_instance != NULL) && !pe_rsc_is_clone(primary)) {
643 pcmk__config_err("Ignoring constraint '%s' because resource '%s' "
644 "is not a clone but instance '%s' was requested",
645 id, primary_id, primary_instance);
646 return;
647 }
648
649 if (dependent_instance != NULL) {
650 dependent = find_clone_instance(dependent, dependent_instance);
651 if (dependent == NULL) {
652 pcmk__config_warn("Ignoring constraint '%s' because resource '%s' "
653 "does not have an instance '%s'",
654 id, dependent_id, dependent_instance);
655 return;
656 }
657 }
658
659 if (primary_instance != NULL) {
660 primary = find_clone_instance(primary, primary_instance);
661 if (primary == NULL) {
662 pcmk__config_warn("Ignoring constraint '%s' because resource '%s' "
663 "does not have an instance '%s'",
664 "'%s'", id, primary_id, primary_instance);
665 return;
666 }
667 }
668
669 if (pcmk__xe_attr_is_true(xml_obj, XML_CONS_ATTR_SYMMETRICAL)) {
670 pcmk__config_warn("The colocation constraint '"
671 XML_CONS_ATTR_SYMMETRICAL
672 "' attribute has been removed");
673 }
674
675 if (score) {
676 score_i = char2score(score);
677 }
678
679 pcmk__new_colocation(id, attr, score_i, dependent, primary,
680 dependent_role, primary_role,
681 unpack_influence(id, dependent, influence_s), data_set);
682 }
683
684
685 static int
686 unpack_colocation_tags(xmlNode *xml_obj, xmlNode **expanded_xml,
687 pe_working_set_t *data_set)
688 {
689 const char *id = NULL;
690 const char *dependent_id = NULL;
691 const char *primary_id = NULL;
692 const char *dependent_role = NULL;
693 const char *primary_role = NULL;
694
695 pe_resource_t *dependent = NULL;
696 pe_resource_t *primary = NULL;
697
698 pe_tag_t *dependent_tag = NULL;
699 pe_tag_t *primary_tag = NULL;
700
701 xmlNode *dependent_set = NULL;
702 xmlNode *primary_set = NULL;
703 bool any_sets = false;
704
705 *expanded_xml = NULL;
706
707 CRM_CHECK(xml_obj != NULL, return EINVAL);
708
709 id = ID(xml_obj);
710 if (id == NULL) {
711 pcmk__config_err("Ignoring <%s> constraint without " XML_ATTR_ID,
712 crm_element_name(xml_obj));
713 return pcmk_rc_unpack_error;
714 }
715
716
717 *expanded_xml = pcmk__expand_tags_in_sets(xml_obj, data_set);
718 if (*expanded_xml != NULL) {
719 crm_log_xml_trace(*expanded_xml, "Expanded rsc_colocation");
720 return pcmk_rc_ok;
721 }
722
723 dependent_id = crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE);
724 primary_id = crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET);
725 if ((dependent_id == NULL) || (primary_id == NULL)) {
726 return pcmk_rc_ok;
727 }
728
729 if (!pcmk__valid_resource_or_tag(data_set, dependent_id, &dependent,
730 &dependent_tag)) {
731 pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
732 "valid resource or tag", id, dependent_id);
733 return pcmk_rc_unpack_error;
734 }
735
736 if (!pcmk__valid_resource_or_tag(data_set, primary_id, &primary,
737 &primary_tag)) {
738 pcmk__config_err("Ignoring constraint '%s' because '%s' is not a "
739 "valid resource or tag", id, primary_id);
740 return pcmk_rc_unpack_error;
741 }
742
743 if ((dependent != NULL) && (primary != NULL)) {
744
745 return pcmk_rc_ok;
746 }
747
748 if ((dependent_tag != NULL) && (primary_tag != NULL)) {
749
750 pcmk__config_err("Ignoring constraint '%s' because two templates or "
751 "tags cannot be colocated", id);
752 return pcmk_rc_unpack_error;
753 }
754
755 dependent_role = crm_element_value(xml_obj, XML_COLOC_ATTR_SOURCE_ROLE);
756 primary_role = crm_element_value(xml_obj, XML_COLOC_ATTR_TARGET_ROLE);
757
758 *expanded_xml = copy_xml(xml_obj);
759
760
761 if (!pcmk__tag_to_set(*expanded_xml, &dependent_set, XML_COLOC_ATTR_SOURCE,
762 true, data_set)) {
763 free_xml(*expanded_xml);
764 *expanded_xml = NULL;
765 return pcmk_rc_unpack_error;
766 }
767
768 if (dependent_set != NULL) {
769 if (dependent_role != NULL) {
770
771 crm_xml_add(dependent_set, "role", dependent_role);
772 xml_remove_prop(*expanded_xml, XML_COLOC_ATTR_SOURCE_ROLE);
773 }
774 any_sets = true;
775 }
776
777
778 if (!pcmk__tag_to_set(*expanded_xml, &primary_set, XML_COLOC_ATTR_TARGET,
779 true, data_set)) {
780 free_xml(*expanded_xml);
781 *expanded_xml = NULL;
782 return pcmk_rc_unpack_error;
783 }
784
785 if (primary_set != NULL) {
786 if (primary_role != NULL) {
787
788 crm_xml_add(primary_set, "role", primary_role);
789 xml_remove_prop(*expanded_xml, XML_COLOC_ATTR_TARGET_ROLE);
790 }
791 any_sets = true;
792 }
793
794 if (any_sets) {
795 crm_log_xml_trace(*expanded_xml, "Expanded rsc_colocation");
796 } else {
797 free_xml(*expanded_xml);
798 *expanded_xml = NULL;
799 }
800
801 return pcmk_rc_ok;
802 }
803
804
805
806
807
808
809
810
811 void
812 pcmk__unpack_colocation(xmlNode *xml_obj, pe_working_set_t *data_set)
813 {
814 int score_i = 0;
815 xmlNode *set = NULL;
816 xmlNode *last = NULL;
817
818 xmlNode *orig_xml = NULL;
819 xmlNode *expanded_xml = NULL;
820
821 const char *id = crm_element_value(xml_obj, XML_ATTR_ID);
822 const char *score = crm_element_value(xml_obj, XML_RULE_ATTR_SCORE);
823 const char *influence_s = crm_element_value(xml_obj,
824 XML_COLOC_ATTR_INFLUENCE);
825
826 if (score) {
827 score_i = char2score(score);
828 }
829
830 if (unpack_colocation_tags(xml_obj, &expanded_xml,
831 data_set) != pcmk_rc_ok) {
832 return;
833 }
834 if (expanded_xml) {
835 orig_xml = xml_obj;
836 xml_obj = expanded_xml;
837 }
838
839 for (set = first_named_child(xml_obj, XML_CONS_TAG_RSC_SET); set != NULL;
840 set = crm_next_same_xml(set)) {
841
842 set = expand_idref(set, data_set->input);
843 if (set == NULL) {
844 if (expanded_xml != NULL) {
845 free_xml(expanded_xml);
846 }
847 return;
848 }
849
850 unpack_colocation_set(set, score_i, id, influence_s, data_set);
851
852 if (last != NULL) {
853 colocate_rsc_sets(id, last, set, score_i, influence_s, data_set);
854 }
855 last = set;
856 }
857
858 if (expanded_xml) {
859 free_xml(expanded_xml);
860 xml_obj = orig_xml;
861 }
862
863 if (last == NULL) {
864 unpack_simple_colocation(xml_obj, id, influence_s, data_set);
865 }
866 }
867
868
869
870
871
872
873
874
875
876 static void
877 mark_action_blocked(pe_resource_t *rsc, const char *task,
878 const pe_resource_t *reason)
879 {
880 char *reason_text = crm_strdup_printf("colocation with %s", reason->id);
881
882 for (GList *gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
883 pe_action_t *action = (pe_action_t *) gIter->data;
884
885 if (pcmk_is_set(action->flags, pe_action_runnable)
886 && pcmk__str_eq(action->task, task, pcmk__str_casei)) {
887
888 pe__clear_action_flags(action, pe_action_runnable);
889 pe_action_set_reason(action, reason_text, false);
890 pcmk__block_colocation_dependents(action, rsc->cluster);
891 pcmk__update_action_for_orderings(action, rsc->cluster);
892 }
893 }
894
895
896 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
897 mark_action_blocked((pe_resource_t *) (iter->data), task, reason);
898 }
899 free(reason_text);
900 }
901
902
903
904
905
906
907
908
909
910
911
912
913 void
914 pcmk__block_colocation_dependents(pe_action_t *action,
915 pe_working_set_t *data_set)
916 {
917 GList *gIter = NULL;
918 GList *colocations = NULL;
919 pe_resource_t *rsc = NULL;
920 bool is_start = false;
921
922 if (pcmk_is_set(action->flags, pe_action_runnable)) {
923 return;
924 }
925
926 is_start = pcmk__str_eq(action->task, RSC_START, pcmk__str_none);
927 if (!is_start && !pcmk__str_eq(action->task, RSC_PROMOTE, pcmk__str_none)) {
928 return;
929 }
930
931 CRM_ASSERT(action->rsc != NULL);
932
933
934
935
936
937 rsc = uber_parent(action->rsc);
938 if (rsc->parent != NULL) {
939 rsc = rsc->parent;
940 }
941
942
943 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
944 pe_resource_t *child = (pe_resource_t *) gIter->data;
945 pe_action_t *child_action = find_first_action(child->actions, NULL,
946 action->task, NULL);
947
948 if ((child_action == NULL)
949 || pcmk_is_set(child_action->flags, pe_action_runnable)) {
950 crm_trace("Not blocking %s colocation dependents because "
951 "at least %s has runnable %s",
952 rsc->id, child->id, action->task);
953 return;
954 }
955 }
956
957 crm_trace("Blocking %s colocation dependents due to unrunnable %s %s",
958 rsc->id, action->rsc->id, action->task);
959
960
961 colocations = pcmk__with_this_colocations(rsc);
962 for (gIter = colocations; gIter != NULL; gIter = gIter->next) {
963 pcmk__colocation_t *colocation = (pcmk__colocation_t *) gIter->data;
964
965 if (colocation->score < INFINITY) {
966 continue;
967 }
968
969
970
971
972
973
974
975 if (!is_start && (colocation->primary_role != RSC_ROLE_PROMOTED)) {
976 continue;
977 }
978
979
980 if (colocation->dependent_role == RSC_ROLE_PROMOTED) {
981 mark_action_blocked(colocation->dependent, RSC_PROMOTE,
982 action->rsc);
983 } else {
984 mark_action_blocked(colocation->dependent, RSC_START, action->rsc);
985 }
986 }
987 g_list_free(colocations);
988 }
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008 enum pcmk__coloc_affects
1009 pcmk__colocation_affects(const pe_resource_t *dependent,
1010 const pe_resource_t *primary,
1011 const pcmk__colocation_t *colocation, bool preview)
1012 {
1013 if (!preview && pcmk_is_set(primary->flags, pe_rsc_provisional)) {
1014
1015 return pcmk__coloc_affects_nothing;
1016 }
1017
1018 if ((colocation->dependent_role >= RSC_ROLE_UNPROMOTED)
1019 && (dependent->parent != NULL)
1020 && pcmk_is_set(dependent->parent->flags, pe_rsc_promotable)
1021 && !pcmk_is_set(dependent->flags, pe_rsc_provisional)) {
1022
1023
1024
1025
1026
1027 return pcmk__coloc_affects_role;
1028 }
1029
1030 if (!preview && !pcmk_is_set(dependent->flags, pe_rsc_provisional)) {
1031
1032
1033
1034
1035
1036 const pe_node_t *primary_node = primary->allocated_to;
1037
1038 if (dependent->allocated_to == NULL) {
1039 crm_trace("Skipping colocation '%s': %s will not run anywhere",
1040 colocation->id, dependent->id);
1041
1042 } else if (colocation->score >= INFINITY) {
1043
1044
1045 if ((primary_node == NULL) ||
1046 (primary_node->details != dependent->allocated_to->details)) {
1047 crm_err("%s must be colocated with %s but is not (%s vs. %s)",
1048 dependent->id, primary->id,
1049 pe__node_name(dependent->allocated_to),
1050 pe__node_name(primary_node));
1051 }
1052
1053 } else if (colocation->score <= -CRM_SCORE_INFINITY) {
1054
1055
1056 if ((primary_node != NULL) &&
1057 (dependent->allocated_to->details == primary_node->details)) {
1058 crm_err("%s and %s must be anti-colocated but are allocated "
1059 "to the same node (%s)",
1060 dependent->id, primary->id, pe__node_name(primary_node));
1061 }
1062 }
1063 return pcmk__coloc_affects_nothing;
1064 }
1065
1066 if ((colocation->score > 0)
1067 && (colocation->dependent_role != RSC_ROLE_UNKNOWN)
1068 && (colocation->dependent_role != dependent->next_role)) {
1069
1070 crm_trace("Skipping colocation '%s': dependent limited to %s role "
1071 "but %s next role is %s",
1072 colocation->id, role2text(colocation->dependent_role),
1073 dependent->id, role2text(dependent->next_role));
1074 return pcmk__coloc_affects_nothing;
1075 }
1076
1077 if ((colocation->score > 0)
1078 && (colocation->primary_role != RSC_ROLE_UNKNOWN)
1079 && (colocation->primary_role != primary->next_role)) {
1080
1081 crm_trace("Skipping colocation '%s': primary limited to %s role "
1082 "but %s next role is %s",
1083 colocation->id, role2text(colocation->primary_role),
1084 primary->id, role2text(primary->next_role));
1085 return pcmk__coloc_affects_nothing;
1086 }
1087
1088 if ((colocation->score < 0)
1089 && (colocation->dependent_role != RSC_ROLE_UNKNOWN)
1090 && (colocation->dependent_role == dependent->next_role)) {
1091 crm_trace("Skipping anti-colocation '%s': dependent role %s matches",
1092 colocation->id, role2text(colocation->dependent_role));
1093 return pcmk__coloc_affects_nothing;
1094 }
1095
1096 if ((colocation->score < 0)
1097 && (colocation->primary_role != RSC_ROLE_UNKNOWN)
1098 && (colocation->primary_role == primary->next_role)) {
1099 crm_trace("Skipping anti-colocation '%s': primary role %s matches",
1100 colocation->id, role2text(colocation->primary_role));
1101 return pcmk__coloc_affects_nothing;
1102 }
1103
1104 return pcmk__coloc_affects_location;
1105 }
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118 void
1119 pcmk__apply_coloc_to_weights(pe_resource_t *dependent,
1120 const pe_resource_t *primary,
1121 const pcmk__colocation_t *colocation)
1122 {
1123 const char *attribute = CRM_ATTR_ID;
1124 const char *value = NULL;
1125 GHashTable *work = NULL;
1126 GHashTableIter iter;
1127 pe_node_t *node = NULL;
1128
1129 if (colocation->node_attribute != NULL) {
1130 attribute = colocation->node_attribute;
1131 }
1132
1133 if (primary->allocated_to != NULL) {
1134 value = pe_node_attribute_raw(primary->allocated_to, attribute);
1135
1136 } else if (colocation->score < 0) {
1137
1138 return;
1139 }
1140
1141 work = pcmk__copy_node_table(dependent->allowed_nodes);
1142
1143 g_hash_table_iter_init(&iter, work);
1144 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
1145 if (primary->allocated_to == NULL) {
1146 node->weight = pcmk__add_scores(-colocation->score, node->weight);
1147 pe_rsc_trace(dependent,
1148 "Applied %s to %s score on %s (now %s after "
1149 "subtracting %s because primary %s inactive)",
1150 colocation->id, dependent->id, pe__node_name(node),
1151 pcmk_readable_score(node->weight),
1152 pcmk_readable_score(colocation->score), primary->id);
1153
1154 } else if (pcmk__str_eq(pe_node_attribute_raw(node, attribute), value,
1155 pcmk__str_casei)) {
1156
1157
1158
1159
1160
1161
1162 if (colocation->score < CRM_SCORE_INFINITY) {
1163 node->weight = pcmk__add_scores(colocation->score,
1164 node->weight);
1165 pe_rsc_trace(dependent,
1166 "Applied %s to %s score on %s (now %s after "
1167 "adding %s)",
1168 colocation->id, dependent->id, pe__node_name(node),
1169 pcmk_readable_score(node->weight),
1170 pcmk_readable_score(colocation->score));
1171 }
1172
1173 } else if (colocation->score >= CRM_SCORE_INFINITY) {
1174
1175
1176
1177
1178
1179 node->weight = -CRM_SCORE_INFINITY;
1180 pe_rsc_trace(dependent,
1181 "Banned %s from %s because colocation %s attribute %s "
1182 "does not match",
1183 dependent->id, pe__node_name(node), colocation->id,
1184 attribute);
1185 }
1186 }
1187
1188 if ((colocation->score <= -INFINITY) || (colocation->score >= INFINITY)
1189 || pcmk__any_node_available(work)) {
1190
1191 g_hash_table_destroy(dependent->allowed_nodes);
1192 dependent->allowed_nodes = work;
1193 work = NULL;
1194
1195 } else {
1196 pe_rsc_info(dependent,
1197 "%s: Rolling back scores from %s (no available nodes)",
1198 dependent->id, primary->id);
1199 }
1200
1201 if (work != NULL) {
1202 g_hash_table_destroy(work);
1203 }
1204 }
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217 void
1218 pcmk__apply_coloc_to_priority(pe_resource_t *dependent,
1219 const pe_resource_t *primary,
1220 const pcmk__colocation_t *colocation)
1221 {
1222 const char *dependent_value = NULL;
1223 const char *primary_value = NULL;
1224 const char *attribute = CRM_ATTR_ID;
1225 int score_multiplier = 1;
1226
1227 if ((primary->allocated_to == NULL) || (dependent->allocated_to == NULL)) {
1228 return;
1229 }
1230
1231 if (colocation->node_attribute != NULL) {
1232 attribute = colocation->node_attribute;
1233 }
1234
1235 dependent_value = pe_node_attribute_raw(dependent->allocated_to, attribute);
1236 primary_value = pe_node_attribute_raw(primary->allocated_to, attribute);
1237
1238 if (!pcmk__str_eq(dependent_value, primary_value, pcmk__str_casei)) {
1239 if ((colocation->score == INFINITY)
1240 && (colocation->dependent_role == RSC_ROLE_PROMOTED)) {
1241 dependent->priority = -INFINITY;
1242 }
1243 return;
1244 }
1245
1246 if ((colocation->primary_role != RSC_ROLE_UNKNOWN)
1247 && (colocation->primary_role != primary->next_role)) {
1248 return;
1249 }
1250
1251 if (colocation->dependent_role == RSC_ROLE_UNPROMOTED) {
1252 score_multiplier = -1;
1253 }
1254
1255 dependent->priority = pcmk__add_scores(score_multiplier * colocation->score,
1256 dependent->priority);
1257 pe_rsc_trace(dependent,
1258 "Applied %s to %s promotion priority (now %s after %s %s)",
1259 colocation->id, dependent->id,
1260 pcmk_readable_score(dependent->priority),
1261 ((score_multiplier == 1)? "adding" : "subtracting"),
1262 pcmk_readable_score(colocation->score));
1263 }
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273 static int
1274 best_node_score_matching_attr(const pe_resource_t *rsc, const char *attr,
1275 const char *value)
1276 {
1277 GHashTableIter iter;
1278 pe_node_t *node = NULL;
1279 int best_score = -INFINITY;
1280 const char *best_node = NULL;
1281
1282
1283 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1284 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
1285
1286 if ((node->weight > best_score) && pcmk__node_available(node, false, false)
1287 && pcmk__str_eq(value, pe_node_attribute_raw(node, attr), pcmk__str_casei)) {
1288
1289 best_score = node->weight;
1290 best_node = node->details->uname;
1291 }
1292 }
1293
1294 if (!pcmk__str_eq(attr, CRM_ATTR_UNAME, pcmk__str_casei)) {
1295 if (best_node == NULL) {
1296 crm_info("No allowed node for %s matches node attribute %s=%s",
1297 rsc->id, attr, value);
1298 } else {
1299 crm_info("Allowed node %s for %s had best score (%d) "
1300 "of those matching node attribute %s=%s",
1301 best_node, rsc->id, best_score, attr, value);
1302 }
1303 }
1304 return best_score;
1305 }
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321 static void
1322 add_node_scores_matching_attr(GHashTable *nodes, const pe_resource_t *rsc,
1323 const char *attr, float factor,
1324 bool only_positive)
1325 {
1326 GHashTableIter iter;
1327 pe_node_t *node = NULL;
1328
1329 if (attr == NULL) {
1330 attr = CRM_ATTR_UNAME;
1331 }
1332
1333
1334 g_hash_table_iter_init(&iter, nodes);
1335 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
1336 float weight_f = 0;
1337 int weight = 0;
1338 int score = 0;
1339 int new_score = 0;
1340
1341 score = best_node_score_matching_attr(rsc, attr,
1342 pe_node_attribute_raw(node, attr));
1343
1344 if ((factor < 0) && (score < 0)) {
1345
1346
1347
1348
1349
1350 crm_trace("%s: Filtering %d + %f * %d (double negative disallowed)",
1351 pe__node_name(node), node->weight, factor, score);
1352 continue;
1353 }
1354
1355 if (node->weight == INFINITY_HACK) {
1356 crm_trace("%s: Filtering %d + %f * %d (node was marked unusable)",
1357 pe__node_name(node), node->weight, factor, score);
1358 continue;
1359 }
1360
1361 weight_f = factor * score;
1362
1363
1364 weight = (int) ((weight_f < 0)? (weight_f - 0.5) : (weight_f + 0.5));
1365
1366
1367
1368
1369
1370 if ((weight == 0) && (score != 0)) {
1371 if (factor > 0.0) {
1372 weight = 1;
1373 } else if (factor < 0.0) {
1374 weight = -1;
1375 }
1376 }
1377
1378 new_score = pcmk__add_scores(weight, node->weight);
1379
1380 if (only_positive && (new_score < 0) && (node->weight > 0)) {
1381 crm_trace("%s: Filtering %d + %f * %d = %d "
1382 "(negative disallowed, marking node unusable)",
1383 pe__node_name(node), node->weight, factor, score,
1384 new_score);
1385 node->weight = INFINITY_HACK;
1386 continue;
1387 }
1388
1389 if (only_positive && (new_score < 0) && (node->weight == 0)) {
1390 crm_trace("%s: Filtering %d + %f * %d = %d (negative disallowed)",
1391 pe__node_name(node), node->weight, factor, score,
1392 new_score);
1393 continue;
1394 }
1395
1396 crm_trace("%s: %d + %f * %d = %d", pe__node_name(node),
1397 node->weight, factor, score, new_score);
1398 node->weight = new_score;
1399 }
1400 }
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419 void
1420 pcmk__add_colocated_node_scores(pe_resource_t *rsc, const char *log_id,
1421 GHashTable **nodes, const char *attr,
1422 float factor, uint32_t flags)
1423 {
1424 GHashTable *work = NULL;
1425
1426 CRM_CHECK((rsc != NULL) && (nodes != NULL), return);
1427
1428 if (log_id == NULL) {
1429 log_id = rsc->id;
1430 }
1431
1432
1433 if (pcmk_is_set(rsc->flags, pe_rsc_merging)) {
1434 pe_rsc_info(rsc, "%s: Breaking dependency loop at %s",
1435 log_id, rsc->id);
1436 return;
1437 }
1438 pe__set_resource_flags(rsc, pe_rsc_merging);
1439
1440 if (*nodes == NULL) {
1441
1442
1443
1444 work = pcmk__copy_node_table(rsc->allowed_nodes);
1445 } else {
1446 pe_rsc_trace(rsc, "%s: Merging scores from %s (at %.6f)",
1447 log_id, rsc->id, factor);
1448 work = pcmk__copy_node_table(*nodes);
1449 add_node_scores_matching_attr(work, rsc, attr, factor,
1450 pcmk_is_set(flags,
1451 pcmk__coloc_select_nonnegative));
1452 }
1453
1454 if (work == NULL) {
1455 pe__clear_resource_flags(rsc, pe_rsc_merging);
1456 return;
1457 }
1458
1459 if (pcmk__any_node_available(work)) {
1460 GList *colocations = NULL;
1461
1462 if (pcmk_is_set(flags, pcmk__coloc_select_this_with)) {
1463 colocations = pcmk__this_with_colocations(rsc);
1464 pe_rsc_trace(rsc,
1465 "Checking additional %d optional '%s with' constraints",
1466 g_list_length(colocations), rsc->id);
1467 } else {
1468 colocations = pcmk__with_this_colocations(rsc);
1469 pe_rsc_trace(rsc,
1470 "Checking additional %d optional 'with %s' constraints",
1471 g_list_length(colocations), rsc->id);
1472 }
1473 flags |= pcmk__coloc_select_active;
1474
1475 for (GList *iter = colocations; iter != NULL; iter = iter->next) {
1476 pcmk__colocation_t *constraint = (pcmk__colocation_t *) iter->data;
1477
1478 pe_resource_t *other = NULL;
1479 float other_factor = factor * constraint->score / (float) INFINITY;
1480
1481 if (pcmk_is_set(flags, pcmk__coloc_select_this_with)) {
1482 other = constraint->primary;
1483 } else if (!pcmk__colocation_has_influence(constraint, NULL)) {
1484 continue;
1485 } else {
1486 other = constraint->dependent;
1487 }
1488
1489 pe_rsc_trace(rsc, "Optionally merging score of '%s' constraint (%s with %s)",
1490 constraint->id, constraint->dependent->id,
1491 constraint->primary->id);
1492 other->cmds->add_colocated_node_scores(other, log_id, &work,
1493 constraint->node_attribute,
1494 other_factor, flags);
1495 pe__show_node_weights(true, NULL, log_id, work, rsc->cluster);
1496 }
1497 g_list_free(colocations);
1498
1499 } else if (pcmk_is_set(flags, pcmk__coloc_select_active)) {
1500 pe_rsc_info(rsc, "%s: Rolling back optional scores from %s",
1501 log_id, rsc->id);
1502 g_hash_table_destroy(work);
1503 pe__clear_resource_flags(rsc, pe_rsc_merging);
1504 return;
1505 }
1506
1507
1508 if (pcmk_is_set(flags, pcmk__coloc_select_nonnegative)) {
1509 pe_node_t *node = NULL;
1510 GHashTableIter iter;
1511
1512 g_hash_table_iter_init(&iter, work);
1513 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
1514 if (node->weight == INFINITY_HACK) {
1515 node->weight = 1;
1516 }
1517 }
1518 }
1519
1520 if (*nodes != NULL) {
1521 g_hash_table_destroy(*nodes);
1522 }
1523 *nodes = work;
1524
1525 pe__clear_resource_flags(rsc, pe_rsc_merging);
1526 }
1527
1528
1529
1530
1531
1532
1533
1534
1535 void
1536 pcmk__add_dependent_scores(gpointer data, gpointer user_data)
1537 {
1538 pcmk__colocation_t *colocation = (pcmk__colocation_t *) data;
1539 pe_resource_t *rsc = (pe_resource_t *) user_data;
1540
1541 pe_resource_t *other = colocation->dependent;
1542 const float factor = colocation->score / (float) INFINITY;
1543 uint32_t flags = pcmk__coloc_select_active;
1544
1545 if (!pcmk__colocation_has_influence(colocation, NULL)) {
1546 return;
1547 }
1548 if (rsc->variant == pe_clone) {
1549 flags |= pcmk__coloc_select_nonnegative;
1550 }
1551 pe_rsc_trace(rsc,
1552 "%s: Incorporating attenuated %s assignment scores due "
1553 "to colocation %s", rsc->id, other->id, colocation->id);
1554 other->cmds->add_colocated_node_scores(other, rsc->id, &rsc->allowed_nodes,
1555 colocation->node_attribute, factor,
1556 flags);
1557 }
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569 GList *
1570 pcmk__with_this_colocations(const pe_resource_t *rsc)
1571 {
1572 GList *list = NULL;
1573
1574 rsc->cmds->with_this_colocations(rsc, rsc, &list);
1575 return list;
1576 }
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588 GList *
1589 pcmk__this_with_colocations(const pe_resource_t *rsc)
1590 {
1591 GList *list = NULL;
1592
1593 rsc->cmds->this_with_colocations(rsc, rsc, &list);
1594 return list;
1595 }