This source file includes following definitions.
- order_instance_promotion
- order_instance_demotion
- check_for_role_change
- apply_promoted_locations
- node_to_be_promoted_on
- cmp_promotable_instance
- add_sort_index_to_node_weight
- apply_coloc_to_dependent
- apply_coloc_to_primary
- set_sort_index_to_node_weight
- sort_promotable_instances
- find_active_anon_instance
- anonymous_known_on
- is_allowed
- promotion_score_applies
- promotion_attr_value
- promotion_score
- pcmk__add_promotion_scores
- set_current_role_unpromoted
- set_next_role_unpromoted
- set_next_role_promoted
- show_promotion_score
- set_instance_priority
- set_instance_role
- pcmk__set_instance_roles
- create_promotable_instance_actions
- reset_instance_priorities
- pcmk__create_promotable_actions
- pcmk__order_promotable_instances
- update_dependent_allowed_nodes
- pcmk__update_dependent_with_promotable
- pcmk__update_promotable_dependent_priority
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <crm/msg_xml.h>
13 #include <pacemaker-internal.h>
14
15 #include "libpacemaker_private.h"
16
17
18
19
20
21
22
23
24
25 static void
26 order_instance_promotion(pe_resource_t *clone, pe_resource_t *child,
27 pe_resource_t *last)
28 {
29
30 pcmk__order_resource_actions(clone, RSC_PROMOTE, child, RSC_PROMOTE,
31 pe_order_optional);
32 pcmk__order_resource_actions(child, RSC_PROMOTE, clone, RSC_PROMOTED,
33 pe_order_optional);
34
35
36 if ((last != NULL) && pe__clone_is_ordered(clone)) {
37 pcmk__order_resource_actions(last, RSC_PROMOTE, child, RSC_PROMOTE,
38 pe_order_optional);
39 }
40 }
41
42
43
44
45
46
47
48
49
50 static void
51 order_instance_demotion(pe_resource_t *clone, pe_resource_t *child,
52 pe_resource_t *last)
53 {
54
55 pcmk__order_resource_actions(clone, RSC_DEMOTE, child, RSC_DEMOTE,
56 pe_order_implies_first_printed);
57 pcmk__order_resource_actions(child, RSC_DEMOTE, clone, RSC_DEMOTED,
58 pe_order_implies_then_printed);
59
60
61 if ((last != NULL) && pe__clone_is_ordered(clone)) {
62 pcmk__order_resource_actions(child, RSC_DEMOTE, last, RSC_DEMOTE,
63 pe_order_optional);
64 }
65 }
66
67
68
69
70
71
72
73
74
75 static void
76 check_for_role_change(const pe_resource_t *rsc, bool *demoting, bool *promoting)
77 {
78 const GList *iter = NULL;
79
80
81 if (rsc->children != NULL) {
82 for (iter = rsc->children; iter != NULL; iter = iter->next) {
83 check_for_role_change((const pe_resource_t *) iter->data,
84 demoting, promoting);
85 }
86 return;
87 }
88
89 for (iter = rsc->actions; iter != NULL; iter = iter->next) {
90 const pe_action_t *action = (const pe_action_t *) iter->data;
91
92 if (*promoting && *demoting) {
93 return;
94
95 } else if (pcmk_is_set(action->flags, pe_action_optional)) {
96 continue;
97
98 } else if (pcmk__str_eq(RSC_DEMOTE, action->task, pcmk__str_none)) {
99 *demoting = true;
100
101 } else if (pcmk__str_eq(RSC_PROMOTE, action->task, pcmk__str_none)) {
102 *promoting = true;
103 }
104 }
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119 static void
120 apply_promoted_locations(pe_resource_t *child,
121 const GList *location_constraints,
122 const pe_node_t *chosen)
123 {
124 for (const GList *iter = location_constraints; iter; iter = iter->next) {
125 const pe__location_t *location = iter->data;
126 pe_node_t *weighted_node = NULL;
127
128 if (location->role_filter == RSC_ROLE_PROMOTED) {
129 weighted_node = pe_find_node_id(location->node_list_rh,
130 chosen->details->id);
131 }
132 if (weighted_node != NULL) {
133 int new_priority = pcmk__add_scores(child->priority,
134 weighted_node->weight);
135
136 pe_rsc_trace(child,
137 "Applying location %s to %s promotion priority on %s: "
138 "%s + %s = %s",
139 location->id, child->id, pe__node_name(weighted_node),
140 pcmk_readable_score(child->priority),
141 pcmk_readable_score(weighted_node->weight),
142 pcmk_readable_score(new_priority));
143 child->priority = new_priority;
144 }
145 }
146 }
147
148
149
150
151
152
153
154
155
156 static pe_node_t *
157 node_to_be_promoted_on(const pe_resource_t *rsc)
158 {
159 pe_node_t *node = NULL;
160 pe_node_t *local_node = NULL;
161 const pe_resource_t *parent = NULL;
162
163
164 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
165 pe_resource_t *child = (pe_resource_t *) iter->data;
166
167 if (node_to_be_promoted_on(child) == NULL) {
168 pe_rsc_trace(rsc,
169 "%s can't be promoted because member %s can't",
170 rsc->id, child->id);
171 return NULL;
172 }
173 }
174
175 node = rsc->fns->location(rsc, NULL, FALSE);
176 if (node == NULL) {
177 pe_rsc_trace(rsc, "%s can't be promoted because it won't be active",
178 rsc->id);
179 return NULL;
180
181 } else if (!pcmk_is_set(rsc->flags, pe_rsc_managed)) {
182 if (rsc->fns->state(rsc, TRUE) == RSC_ROLE_PROMOTED) {
183 crm_notice("Unmanaged instance %s will be left promoted on %s",
184 rsc->id, pe__node_name(node));
185 } else {
186 pe_rsc_trace(rsc, "%s can't be promoted because it is unmanaged",
187 rsc->id);
188 return NULL;
189 }
190
191 } else if (rsc->priority < 0) {
192 pe_rsc_trace(rsc,
193 "%s can't be promoted because its promotion priority %d "
194 "is negative",
195 rsc->id, rsc->priority);
196 return NULL;
197
198 } else if (!pcmk__node_available(node, false, true)) {
199 pe_rsc_trace(rsc, "%s can't be promoted because %s can't run resources",
200 rsc->id, pe__node_name(node));
201 return NULL;
202 }
203
204 parent = pe__const_top_resource(rsc, false);
205 local_node = pe_hash_table_lookup(parent->allowed_nodes, node->details->id);
206
207 if (local_node == NULL) {
208
209
210
211
212 if (pcmk_is_set(rsc->flags, pe_rsc_managed)) {
213 crm_warn("%s can't be promoted because %s is not allowed on %s "
214 "(scheduler bug?)",
215 rsc->id, parent->id, pe__node_name(node));
216 }
217 return NULL;
218
219 } else if ((local_node->count >= pe__clone_promoted_node_max(parent))
220 && pcmk_is_set(rsc->flags, pe_rsc_managed)) {
221 pe_rsc_trace(rsc,
222 "%s can't be promoted because %s has "
223 "maximum promoted instances already",
224 rsc->id, pe__node_name(node));
225 return NULL;
226 }
227
228 return local_node;
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242 static gint
243 cmp_promotable_instance(gconstpointer a, gconstpointer b)
244 {
245 const pe_resource_t *rsc1 = (const pe_resource_t *) a;
246 const pe_resource_t *rsc2 = (const pe_resource_t *) b;
247
248 enum rsc_role_e role1 = RSC_ROLE_UNKNOWN;
249 enum rsc_role_e role2 = RSC_ROLE_UNKNOWN;
250
251 CRM_ASSERT((rsc1 != NULL) && (rsc2 != NULL));
252
253
254 if (rsc1->sort_index > rsc2->sort_index) {
255 pe_rsc_trace(rsc1,
256 "%s has higher promotion priority than %s "
257 "(sort index %d > %d)",
258 rsc1->id, rsc2->id, rsc1->sort_index, rsc2->sort_index);
259 return -1;
260 } else if (rsc1->sort_index < rsc2->sort_index) {
261 pe_rsc_trace(rsc1,
262 "%s has lower promotion priority than %s "
263 "(sort index %d < %d)",
264 rsc1->id, rsc2->id, rsc1->sort_index, rsc2->sort_index);
265 return 1;
266 }
267
268
269 role1 = rsc1->fns->state(rsc1, TRUE);
270 role2 = rsc2->fns->state(rsc2, TRUE);
271 if (role1 > role2) {
272 pe_rsc_trace(rsc1,
273 "%s has higher promotion priority than %s "
274 "(higher current role)",
275 rsc1->id, rsc2->id);
276 return -1;
277 } else if (role1 < role2) {
278 pe_rsc_trace(rsc1,
279 "%s has lower promotion priority than %s "
280 "(lower current role)",
281 rsc1->id, rsc2->id);
282 return 1;
283 }
284
285
286 return pcmk__cmp_instance(a, b);
287 }
288
289
290
291
292
293
294
295
296
297
298
299
300 static void
301 add_sort_index_to_node_weight(gpointer data, gpointer user_data)
302 {
303 const pe_resource_t *child = (const pe_resource_t *) data;
304 pe_resource_t *clone = (pe_resource_t *) user_data;
305
306 pe_node_t *node = NULL;
307 const pe_node_t *chosen = NULL;
308
309 if (child->sort_index < 0) {
310 pe_rsc_trace(clone, "Not adding sort index of %s: negative", child->id);
311 return;
312 }
313
314 chosen = child->fns->location(child, NULL, FALSE);
315 if (chosen == NULL) {
316 pe_rsc_trace(clone, "Not adding sort index of %s: inactive", child->id);
317 return;
318 }
319
320 node = (pe_node_t *) pe_hash_table_lookup(clone->allowed_nodes,
321 chosen->details->id);
322 CRM_ASSERT(node != NULL);
323
324 node->weight = pcmk__add_scores(child->sort_index, node->weight);
325 pe_rsc_trace(clone,
326 "Added cumulative priority of %s (%s) to score on %s (now %s)",
327 child->id, pcmk_readable_score(child->sort_index),
328 pe__node_name(node), pcmk_readable_score(node->weight));
329 }
330
331
332
333
334
335
336
337
338 static void
339 apply_coloc_to_dependent(gpointer data, gpointer user_data)
340 {
341 pcmk__colocation_t *constraint = (pcmk__colocation_t *) data;
342 pe_resource_t *clone = (pe_resource_t *) user_data;
343 pe_resource_t *primary = constraint->primary;
344 uint32_t flags = pcmk__coloc_select_default;
345 float factor = constraint->score / (float) INFINITY;
346
347 if (constraint->dependent_role != RSC_ROLE_PROMOTED) {
348 return;
349 }
350 if (constraint->score < INFINITY) {
351 flags = pcmk__coloc_select_active;
352 }
353 pe_rsc_trace(clone, "Applying colocation %s (promoted %s with %s) @%s",
354 constraint->id, constraint->dependent->id,
355 constraint->primary->id,
356 pcmk_readable_score(constraint->score));
357 primary->cmds->add_colocated_node_scores(primary, clone->id,
358 &clone->allowed_nodes,
359 constraint->node_attribute, factor,
360 flags);
361 }
362
363
364
365
366
367
368
369
370 static void
371 apply_coloc_to_primary(gpointer data, gpointer user_data)
372 {
373 pcmk__colocation_t *constraint = (pcmk__colocation_t *) data;
374 pe_resource_t *clone = (pe_resource_t *) user_data;
375 pe_resource_t *dependent = constraint->dependent;
376 const float factor = constraint->score / (float) INFINITY;
377 const uint32_t flags = pcmk__coloc_select_active
378 |pcmk__coloc_select_nonnegative;
379
380 if ((constraint->primary_role != RSC_ROLE_PROMOTED)
381 || !pcmk__colocation_has_influence(constraint, NULL)) {
382 return;
383 }
384
385 pe_rsc_trace(clone, "Applying colocation %s (%s with promoted %s) @%s",
386 constraint->id, constraint->dependent->id,
387 constraint->primary->id,
388 pcmk_readable_score(constraint->score));
389 dependent->cmds->add_colocated_node_scores(dependent, clone->id,
390 &clone->allowed_nodes,
391 constraint->node_attribute,
392 factor, flags);
393 }
394
395
396
397
398
399
400
401
402 static void
403 set_sort_index_to_node_weight(gpointer data, gpointer user_data)
404 {
405 pe_resource_t *child = (pe_resource_t *) data;
406 const pe_resource_t *clone = (const pe_resource_t *) user_data;
407
408 pe_node_t *chosen = child->fns->location(child, NULL, FALSE);
409
410 if (!pcmk_is_set(child->flags, pe_rsc_managed)
411 && (child->next_role == RSC_ROLE_PROMOTED)) {
412 child->sort_index = INFINITY;
413 pe_rsc_trace(clone,
414 "Final sort index for %s is INFINITY (unmanaged promoted)",
415 child->id);
416
417 } else if ((chosen == NULL) || (child->sort_index < 0)) {
418 pe_rsc_trace(clone,
419 "Final sort index for %s is %d (ignoring node weight)",
420 child->id, child->sort_index);
421
422 } else {
423 const pe_node_t *node = NULL;
424
425 node = pe_hash_table_lookup(clone->allowed_nodes, chosen->details->id);
426 CRM_ASSERT(node != NULL);
427
428 child->sort_index = node->weight;
429 pe_rsc_trace(clone,
430 "Merging weights for %s: final sort index for %s is %d",
431 clone->id, child->id, child->sort_index);
432 }
433 }
434
435
436
437
438
439
440
441 static void
442 sort_promotable_instances(pe_resource_t *clone)
443 {
444 if (pe__set_clone_flag(clone, pe__clone_promotion_constrained)
445 == pcmk_rc_already) {
446 return;
447 }
448 pe__set_resource_flags(clone, pe_rsc_merging);
449
450 for (GList *iter = clone->children; iter != NULL; iter = iter->next) {
451 pe_resource_t *child = (pe_resource_t *) iter->data;
452
453 pe_rsc_trace(clone,
454 "Merging weights for %s: initial sort index for %s is %d",
455 clone->id, child->id, child->sort_index);
456 }
457 pe__show_node_weights(true, clone, "Before", clone->allowed_nodes,
458 clone->cluster);
459
460
461
462
463
464 g_list_foreach(clone->children, add_sort_index_to_node_weight, clone);
465 g_list_foreach(clone->rsc_cons, apply_coloc_to_dependent, clone);
466 g_list_foreach(clone->rsc_cons_lhs, apply_coloc_to_primary, clone);
467
468
469 pcmk__require_promotion_tickets(clone);
470
471 pe__show_node_weights(true, clone, "After", clone->allowed_nodes,
472 clone->cluster);
473
474
475 g_list_foreach(clone->children, set_sort_index_to_node_weight, clone);
476
477
478 clone->children = g_list_sort(clone->children, cmp_promotable_instance);
479 pe__clear_resource_flags(clone, pe_rsc_merging);
480 }
481
482
483
484
485
486
487
488
489
490
491
492 static pe_resource_t *
493 find_active_anon_instance(const pe_resource_t *clone, const char *id,
494 const pe_node_t *node)
495 {
496 for (GList *iter = clone->children; iter; iter = iter->next) {
497 pe_resource_t *child = iter->data;
498 pe_resource_t *active = NULL;
499
500
501 active = clone->fns->find_rsc(child, id, node,
502 pe_find_clone|pe_find_current);
503 if (active != NULL) {
504 return active;
505 }
506 }
507 return NULL;
508 }
509
510
511
512
513
514
515
516
517
518
519
520 static bool
521 anonymous_known_on(const pe_resource_t *clone, const char *id,
522 const pe_node_t *node)
523 {
524 for (GList *iter = clone->children; iter; iter = iter->next) {
525 pe_resource_t *child = iter->data;
526
527
528
529
530 child = clone->fns->find_rsc(child, id, NULL, pe_find_clone);
531 CRM_LOG_ASSERT(child != NULL);
532 if (child != NULL) {
533 if (g_hash_table_lookup(child->known_on, node->details->id)) {
534 return true;
535 }
536 }
537 }
538 return false;
539 }
540
541
542
543
544
545
546
547
548
549
550 static bool
551 is_allowed(const pe_resource_t *rsc, const pe_node_t *node)
552 {
553 pe_node_t *allowed = pe_hash_table_lookup(rsc->allowed_nodes,
554 node->details->id);
555
556 return (allowed != NULL) && (allowed->weight >= 0);
557 }
558
559
560
561
562
563
564
565
566
567
568 static bool
569 promotion_score_applies(const pe_resource_t *rsc, const pe_node_t *node)
570 {
571 char *id = clone_strip(rsc->id);
572 const pe_resource_t *parent = pe__const_top_resource(rsc, false);
573 pe_resource_t *active = NULL;
574 const char *reason = "allowed";
575
576
577 if (!pcmk_is_set(rsc->flags, pe_rsc_unique)) {
578
579
580 active = find_active_anon_instance(parent, id, node);
581 if (active == rsc) {
582 reason = "active";
583 goto check_allowed;
584 }
585
586
587
588
589 if ((active == NULL) && anonymous_known_on(parent, id, node)) {
590 reason = "probed";
591 goto check_allowed;
592 }
593 }
594
595
596
597
598
599 if ((rsc->running_on == NULL) && (g_hash_table_size(rsc->known_on) == 0)) {
600 reason = "none probed";
601 goto check_allowed;
602 }
603
604
605
606
607 if ((pe_hash_table_lookup(rsc->known_on, node->details->id) != NULL)
608 || (pe_find_node_id(rsc->running_on, node->details->id) != NULL)) {
609 reason = "known";
610 } else {
611 pe_rsc_trace(rsc,
612 "Ignoring %s promotion score (for %s) on %s: not probed",
613 rsc->id, id, pe__node_name(node));
614 free(id);
615 return false;
616 }
617
618 check_allowed:
619 if (is_allowed(rsc, node)) {
620 pe_rsc_trace(rsc, "Counting %s promotion score (for %s) on %s: %s",
621 rsc->id, id, pe__node_name(node), reason);
622 free(id);
623 return true;
624 }
625
626 pe_rsc_trace(rsc, "Ignoring %s promotion score (for %s) on %s: not allowed",
627 rsc->id, id, pe__node_name(node));
628 free(id);
629 return false;
630 }
631
632
633
634
635
636
637
638
639
640
641
642 static const char *
643 promotion_attr_value(const pe_resource_t *rsc, const pe_node_t *node,
644 const char *name)
645 {
646 char *attr_name = NULL;
647 const char *attr_value = NULL;
648
649 CRM_CHECK((rsc != NULL) && (node != NULL) && (name != NULL), return NULL);
650
651 attr_name = pcmk_promotion_score_name(name);
652 attr_value = pe_node_attribute_calculated(node, attr_name, rsc);
653 free(attr_name);
654 return attr_value;
655 }
656
657
658
659
660
661
662
663
664
665
666
667 static int
668 promotion_score(const pe_resource_t *rsc, const pe_node_t *node,
669 bool *is_default)
670 {
671 char *name = NULL;
672 const char *attr_value = NULL;
673
674 if (is_default != NULL) {
675 *is_default = true;
676 }
677
678 CRM_CHECK((rsc != NULL) && (node != NULL), return 0);
679
680
681
682
683 if (rsc->children != NULL) {
684 int score = 0;
685
686 for (const GList *iter = rsc->children;
687 iter != NULL; iter = iter->next) {
688
689 const pe_resource_t *child = (const pe_resource_t *) iter->data;
690 bool child_default = false;
691 int child_score = promotion_score(child, node, &child_default);
692
693 if (!child_default && (is_default != NULL)) {
694 *is_default = false;
695 }
696 score += child_score;
697 }
698 return score;
699 }
700
701 if (!promotion_score_applies(rsc, node)) {
702 return 0;
703 }
704
705
706
707
708
709 name = (rsc->clone_name == NULL)? rsc->id : rsc->clone_name;
710
711 attr_value = promotion_attr_value(rsc, node, name);
712 if (attr_value != NULL) {
713 pe_rsc_trace(rsc, "Promotion score for %s on %s = %s",
714 name, pe__node_name(node), pcmk__s(attr_value, "(unset)"));
715 } else if (!pcmk_is_set(rsc->flags, pe_rsc_unique)) {
716
717
718
719
720 name = clone_strip(rsc->id);
721 if (strcmp(rsc->id, name) != 0) {
722 attr_value = promotion_attr_value(rsc, node, name);
723 pe_rsc_trace(rsc, "Promotion score for %s on %s (for %s) = %s",
724 name, pe__node_name(node), rsc->id,
725 pcmk__s(attr_value, "(unset)"));
726 }
727 free(name);
728 }
729
730 if (attr_value == NULL) {
731 return 0;
732 }
733
734 if (is_default != NULL) {
735 *is_default = false;
736 }
737 return char2score(attr_value);
738 }
739
740
741
742
743
744
745
746 void
747 pcmk__add_promotion_scores(pe_resource_t *rsc)
748 {
749 if (pe__set_clone_flag(rsc, pe__clone_promotion_added) == pcmk_rc_already) {
750 return;
751 }
752
753 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
754 pe_resource_t *child_rsc = (pe_resource_t *) iter->data;
755
756 GHashTableIter iter;
757 pe_node_t *node = NULL;
758 int score, new_score;
759
760 g_hash_table_iter_init(&iter, child_rsc->allowed_nodes);
761 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
762 if (!pcmk__node_available(node, false, false)) {
763
764
765
766 continue;
767 }
768
769 score = promotion_score(child_rsc, node, NULL);
770 if (score > 0) {
771 new_score = pcmk__add_scores(node->weight, score);
772 if (new_score != node->weight) {
773 node->weight = new_score;
774 pe_rsc_trace(rsc,
775 "Added %s promotion priority (%s) to score "
776 "on %s (now %s)",
777 child_rsc->id, pcmk_readable_score(score),
778 pe__node_name(node),
779 pcmk_readable_score(new_score));
780 }
781 }
782
783 if (score > child_rsc->priority) {
784 pe_rsc_trace(rsc,
785 "Updating %s priority to promotion score (%d->%d)",
786 child_rsc->id, child_rsc->priority, score);
787 child_rsc->priority = score;
788 }
789 }
790 }
791 }
792
793
794
795
796
797
798
799
800 static void
801 set_current_role_unpromoted(void *data, void *user_data)
802 {
803 pe_resource_t *rsc = (pe_resource_t *) data;
804
805 if (rsc->role == RSC_ROLE_STARTED) {
806
807 rsc->role = RSC_ROLE_UNPROMOTED;
808 }
809 g_list_foreach(rsc->children, set_current_role_unpromoted, NULL);
810 }
811
812
813
814
815
816
817
818
819 static void
820 set_next_role_unpromoted(void *data, void *user_data)
821 {
822 pe_resource_t *rsc = (pe_resource_t *) data;
823 GList *assigned = NULL;
824
825 rsc->fns->location(rsc, &assigned, FALSE);
826 if (assigned == NULL) {
827 pe__set_next_role(rsc, RSC_ROLE_STOPPED, "stopped instance");
828 } else {
829 pe__set_next_role(rsc, RSC_ROLE_UNPROMOTED, "unpromoted instance");
830 g_list_free(assigned);
831 }
832 g_list_foreach(rsc->children, set_next_role_unpromoted, NULL);
833 }
834
835
836
837
838
839
840
841
842 static void
843 set_next_role_promoted(void *data, gpointer user_data)
844 {
845 pe_resource_t *rsc = (pe_resource_t *) data;
846
847 if (rsc->next_role == RSC_ROLE_UNKNOWN) {
848 pe__set_next_role(rsc, RSC_ROLE_PROMOTED, "promoted instance");
849 }
850 g_list_foreach(rsc->children, set_next_role_promoted, NULL);
851 }
852
853
854
855
856
857
858
859 static void
860 show_promotion_score(pe_resource_t *instance)
861 {
862 pe_node_t *chosen = instance->fns->location(instance, NULL, FALSE);
863
864 if (pcmk_is_set(instance->cluster->flags, pe_flag_show_scores)
865 && !pcmk__is_daemon && (instance->cluster->priv != NULL)) {
866
867 pcmk__output_t *out = instance->cluster->priv;
868
869 out->message(out, "promotion-score", instance, chosen,
870 pcmk_readable_score(instance->sort_index));
871 } else {
872 pe_rsc_debug(pe__const_top_resource(instance, false),
873 "%s promotion score on %s: sort=%s priority=%s",
874 instance->id,
875 ((chosen == NULL)? "none" : pe__node_name(chosen)),
876 pcmk_readable_score(instance->sort_index),
877 pcmk_readable_score(instance->priority));
878 }
879 }
880
881
882
883
884
885
886
887
888 static void
889 set_instance_priority(gpointer data, gpointer user_data)
890 {
891 pe_resource_t *instance = (pe_resource_t *) data;
892 const pe_resource_t *clone = (const pe_resource_t *) user_data;
893 const pe_node_t *chosen = NULL;
894 enum rsc_role_e next_role = RSC_ROLE_UNKNOWN;
895 GList *list = NULL;
896
897 pe_rsc_trace(clone, "Assigning priority for %s: %s", instance->id,
898 role2text(instance->next_role));
899
900 if (instance->fns->state(instance, TRUE) == RSC_ROLE_STARTED) {
901 set_current_role_unpromoted(instance, NULL);
902 }
903
904
905 chosen = instance->fns->location(instance, &list, FALSE);
906 if (pcmk__list_of_multiple(list)) {
907 pcmk__config_err("Cannot promote non-colocated child %s",
908 instance->id);
909 }
910 g_list_free(list);
911 if (chosen == NULL) {
912 return;
913 }
914
915 next_role = instance->fns->state(instance, FALSE);
916 switch (next_role) {
917 case RSC_ROLE_STARTED:
918 case RSC_ROLE_UNKNOWN:
919
920 {
921 bool is_default = false;
922
923 instance->priority = promotion_score(instance, chosen,
924 &is_default);
925 if (is_default) {
926
927
928
929
930
931
932
933 instance->priority = -1;
934 }
935 }
936 break;
937
938 case RSC_ROLE_UNPROMOTED:
939 case RSC_ROLE_STOPPED:
940
941 instance->priority = -INFINITY;
942 break;
943
944 case RSC_ROLE_PROMOTED:
945
946 break;
947
948 default:
949 CRM_CHECK(FALSE, crm_err("Unknown resource role %d for %s",
950 next_role, instance->id));
951 }
952
953
954 apply_promoted_locations(instance, instance->rsc_location, chosen);
955 apply_promoted_locations(instance, clone->rsc_location, chosen);
956
957
958 list = pcmk__this_with_colocations(instance);
959 for (GList *iter = list; iter != NULL; iter = iter->next) {
960 pcmk__colocation_t *cons = (pcmk__colocation_t *) iter->data;
961
962 instance->cmds->apply_coloc_score(instance, cons->primary, cons, true);
963 }
964 g_list_free(list);
965
966 instance->sort_index = instance->priority;
967 if (next_role == RSC_ROLE_PROMOTED) {
968 instance->sort_index = INFINITY;
969 }
970 pe_rsc_trace(clone, "Assigning %s priority = %d",
971 instance->id, instance->priority);
972 }
973
974
975
976
977
978
979
980
981 static void
982 set_instance_role(gpointer data, gpointer user_data)
983 {
984 pe_resource_t *instance = (pe_resource_t *) data;
985 int *count = (int *) user_data;
986
987 const pe_resource_t *clone = pe__const_top_resource(instance, false);
988 pe_node_t *chosen = NULL;
989
990 show_promotion_score(instance);
991
992 if (instance->sort_index < 0) {
993 pe_rsc_trace(clone, "Not supposed to promote instance %s",
994 instance->id);
995
996 } else if ((*count < pe__clone_promoted_max(instance))
997 || !pcmk_is_set(clone->flags, pe_rsc_managed)) {
998 chosen = node_to_be_promoted_on(instance);
999 }
1000
1001 if (chosen == NULL) {
1002 set_next_role_unpromoted(instance, NULL);
1003 return;
1004 }
1005
1006 if ((instance->role < RSC_ROLE_PROMOTED)
1007 && !pcmk_is_set(instance->cluster->flags, pe_flag_have_quorum)
1008 && (instance->cluster->no_quorum_policy == no_quorum_freeze)) {
1009 crm_notice("Clone instance %s cannot be promoted without quorum",
1010 instance->id);
1011 set_next_role_unpromoted(instance, NULL);
1012 return;
1013 }
1014
1015 chosen->count++;
1016 pe_rsc_info(clone, "Choosing %s (%s) on %s for promotion",
1017 instance->id, role2text(instance->role),
1018 pe__node_name(chosen));
1019 set_next_role_promoted(instance, NULL);
1020 (*count)++;
1021 }
1022
1023
1024
1025
1026
1027
1028
1029 void
1030 pcmk__set_instance_roles(pe_resource_t *rsc)
1031 {
1032 int promoted = 0;
1033 GHashTableIter iter;
1034 pe_node_t *node = NULL;
1035
1036
1037 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1038 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
1039 node->count = 0;
1040 }
1041
1042
1043 g_list_foreach(rsc->children, set_instance_priority, rsc);
1044 sort_promotable_instances(rsc);
1045
1046
1047 g_list_foreach(rsc->children, set_instance_role, &promoted);
1048 pe_rsc_info(rsc, "%s: Promoted %d instances of a possible %d",
1049 rsc->id, promoted, pe__clone_promoted_max(rsc));
1050 }
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061 static void
1062 create_promotable_instance_actions(pe_resource_t *clone,
1063 bool *any_promoting, bool *any_demoting)
1064 {
1065 for (GList *iter = clone->children; iter != NULL; iter = iter->next) {
1066 pe_resource_t *instance = (pe_resource_t *) iter->data;
1067
1068 instance->cmds->create_actions(instance);
1069 check_for_role_change(instance, any_demoting, any_promoting);
1070 }
1071 }
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083 static void
1084 reset_instance_priorities(pe_resource_t *clone)
1085 {
1086 for (GList *iter = clone->children; iter != NULL; iter = iter->next) {
1087 pe_resource_t *instance = (pe_resource_t *) iter->data;
1088
1089 instance->priority = clone->priority;
1090 }
1091 }
1092
1093
1094
1095
1096
1097
1098
1099 void
1100 pcmk__create_promotable_actions(pe_resource_t *clone)
1101 {
1102 bool any_promoting = false;
1103 bool any_demoting = false;
1104
1105
1106 create_promotable_instance_actions(clone, &any_promoting, &any_demoting);
1107
1108
1109 pe__create_promotable_pseudo_ops(clone, any_promoting, any_demoting);
1110
1111
1112 reset_instance_priorities(clone);
1113 }
1114
1115
1116
1117
1118
1119
1120
1121 void
1122 pcmk__order_promotable_instances(pe_resource_t *clone)
1123 {
1124 pe_resource_t *previous = NULL;
1125
1126 pcmk__promotable_restart_ordering(clone);
1127
1128 for (GList *iter = clone->children; iter != NULL; iter = iter->next) {
1129 pe_resource_t *instance = (pe_resource_t *) iter->data;
1130
1131
1132 pcmk__order_resource_actions(instance, RSC_DEMOTE,
1133 instance, RSC_PROMOTE,
1134 pe_order_optional);
1135
1136 order_instance_promotion(clone, instance, previous);
1137 order_instance_demotion(clone, instance, previous);
1138 previous = instance;
1139 }
1140 }
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150 static void
1151 update_dependent_allowed_nodes(pe_resource_t *dependent,
1152 const pe_node_t *primary_node,
1153 const pcmk__colocation_t *colocation)
1154 {
1155 GHashTableIter iter;
1156 pe_node_t *node = NULL;
1157 const char *primary_value = NULL;
1158 const char *attr = NULL;
1159
1160 if (colocation->score >= INFINITY) {
1161 return;
1162 }
1163
1164
1165 attr = colocation->node_attribute;
1166 if (attr == NULL) {
1167 attr = CRM_ATTR_UNAME;
1168 }
1169 primary_value = pe_node_attribute_raw(primary_node, attr);
1170
1171 pe_rsc_trace(colocation->primary,
1172 "Applying %s (%s with %s on %s by %s @%d) to %s",
1173 colocation->id, colocation->dependent->id,
1174 colocation->primary->id, pe__node_name(primary_node), attr,
1175 colocation->score, dependent->id);
1176
1177 g_hash_table_iter_init(&iter, dependent->allowed_nodes);
1178 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
1179 const char *dependent_value = pe_node_attribute_raw(node, attr);
1180
1181 if (pcmk__str_eq(primary_value, dependent_value, pcmk__str_casei)) {
1182 node->weight = pcmk__add_scores(node->weight, colocation->score);
1183 pe_rsc_trace(colocation->primary,
1184 "Added %s score (%s) to %s (now %s)",
1185 colocation->id, pcmk_readable_score(colocation->score),
1186 pe__node_name(node),
1187 pcmk_readable_score(node->weight));
1188 }
1189 }
1190 }
1191
1192
1193
1194
1195
1196
1197
1198
1199 void
1200 pcmk__update_dependent_with_promotable(const pe_resource_t *primary,
1201 pe_resource_t *dependent,
1202 const pcmk__colocation_t *colocation)
1203 {
1204 GList *affected_nodes = NULL;
1205
1206
1207
1208
1209
1210 for (GList *iter = primary->children; iter != NULL; iter = iter->next) {
1211 pe_resource_t *instance = (pe_resource_t *) iter->data;
1212 pe_node_t *node = instance->fns->location(instance, NULL, FALSE);
1213
1214 if (node == NULL) {
1215 continue;
1216 }
1217 if (instance->fns->state(instance, FALSE) == colocation->primary_role) {
1218 update_dependent_allowed_nodes(dependent, node, colocation);
1219 affected_nodes = g_list_prepend(affected_nodes, node);
1220 }
1221 }
1222
1223
1224
1225
1226
1227
1228
1229
1230 if ((colocation->score >= INFINITY)
1231 && ((colocation->dependent_role != RSC_ROLE_PROMOTED)
1232 || (colocation->primary_role != RSC_ROLE_PROMOTED))) {
1233
1234 pe_rsc_trace(colocation->primary,
1235 "Applying %s (mandatory %s with %s) to %s",
1236 colocation->id, colocation->dependent->id,
1237 colocation->primary->id, dependent->id);
1238 node_list_exclude(dependent->allowed_nodes, affected_nodes,
1239 TRUE);
1240 }
1241 g_list_free(affected_nodes);
1242 }
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252 void
1253 pcmk__update_promotable_dependent_priority(const pe_resource_t *primary,
1254 pe_resource_t *dependent,
1255 const pcmk__colocation_t *colocation)
1256 {
1257 pe_resource_t *primary_instance = NULL;
1258
1259
1260 primary_instance = pcmk__find_compatible_instance(dependent, primary,
1261 colocation->primary_role,
1262 false);
1263
1264 if (primary_instance != NULL) {
1265
1266 int new_priority = pcmk__add_scores(dependent->priority,
1267 colocation->score);
1268
1269 pe_rsc_trace(colocation->primary,
1270 "Applying %s (%s with %s) to %s priority (%s + %s = %s)",
1271 colocation->id, colocation->dependent->id,
1272 colocation->primary->id, dependent->id,
1273 pcmk_readable_score(dependent->priority),
1274 pcmk_readable_score(colocation->score),
1275 pcmk_readable_score(new_priority));
1276 dependent->priority = new_priority;
1277
1278 } else if (colocation->score >= INFINITY) {
1279
1280 pe_rsc_trace(colocation->primary,
1281 "Applying %s (%s with %s) to %s: can't be promoted",
1282 colocation->id, colocation->dependent->id,
1283 colocation->primary->id, dependent->id);
1284 dependent->priority = -INFINITY;
1285 }
1286 }