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