This source file includes following definitions.
- pcmk__group_assign
- create_group_pseudo_op
- pcmk__group_create_actions
- member_internal_constraints
- pcmk__group_internal_constraints
- colocate_group_with
- colocate_with_group
- pcmk__group_apply_coloc_score
- pcmk__group_action_flags
- pcmk__group_update_ordered_actions
- pcmk__group_apply_location
- pcmk__group_colocated_resources
- pcmk__with_group_colocations
- pcmk__group_with_colocations
- pcmk__group_add_colocated_node_scores
- pcmk__group_add_utilization
- pcmk__group_shutdown_lock
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdbool.h>
13
14 #include <qb/qbdefs.h>
15
16 #include <crm/common/xml.h>
17
18 #include <pacemaker-internal.h>
19 #include "libpacemaker_private.h"
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 pcmk_node_t *
40 pcmk__group_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer,
41 bool stop_if_fail)
42 {
43 pcmk_node_t *first_assigned_node = NULL;
44 pcmk_resource_t *first_member = NULL;
45
46 pcmk__assert(pcmk__is_group(rsc));
47
48 if (!pcmk_is_set(rsc->flags, pcmk__rsc_unassigned)) {
49 return rsc->priv->assigned_node;
50 }
51 if (pcmk_is_set(rsc->flags, pcmk__rsc_assigning)) {
52 pcmk__rsc_debug(rsc, "Assignment dependency loop detected involving %s",
53 rsc->id);
54 return NULL;
55 }
56
57 if (rsc->priv->children == NULL) {
58
59 pcmk__clear_rsc_flags(rsc, pcmk__rsc_unassigned);
60 return NULL;
61 }
62
63 pcmk__set_rsc_flags(rsc, pcmk__rsc_assigning);
64 first_member = (pcmk_resource_t *) rsc->priv->children->data;
65 rsc->priv->orig_role = first_member->priv->orig_role;
66
67 pe__show_node_scores(!pcmk_is_set(rsc->priv->scheduler->flags,
68 pcmk__sched_output_scores),
69 rsc, __func__, rsc->priv->allowed_nodes,
70 rsc->priv->scheduler);
71
72 for (GList *iter = rsc->priv->children;
73 iter != NULL; iter = iter->next) {
74
75 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
76 pcmk_node_t *node = NULL;
77
78 pcmk__rsc_trace(rsc, "Assigning group %s member %s",
79 rsc->id, member->id);
80 node = member->priv->cmds->assign(member, prefer, stop_if_fail);
81 if (first_assigned_node == NULL) {
82 first_assigned_node = node;
83 }
84 }
85
86 pe__set_next_role(rsc, first_member->priv->next_role,
87 "first group member");
88 pcmk__clear_rsc_flags(rsc, pcmk__rsc_assigning|pcmk__rsc_unassigned);
89
90 if (!pe__group_flag_is_set(rsc, pcmk__group_colocated)) {
91 return NULL;
92 }
93 return first_assigned_node;
94 }
95
96
97
98
99
100
101
102
103
104
105 static pcmk_action_t *
106 create_group_pseudo_op(pcmk_resource_t *group, const char *action)
107 {
108 pcmk_action_t *op = custom_action(group, pcmk__op_key(group->id, action, 0),
109 action, NULL, TRUE,
110 group->priv->scheduler);
111
112 pcmk__set_action_flags(op, pcmk__action_pseudo|pcmk__action_runnable);
113 return op;
114 }
115
116
117
118
119
120
121
122 void
123 pcmk__group_create_actions(pcmk_resource_t *rsc)
124 {
125 pcmk__assert(pcmk__is_group(rsc));
126
127 pcmk__rsc_trace(rsc, "Creating actions for group %s", rsc->id);
128
129
130 for (GList *iter = rsc->priv->children;
131 iter != NULL; iter = iter->next) {
132
133 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
134
135 member->priv->cmds->create_actions(member);
136 }
137
138
139 create_group_pseudo_op(rsc, PCMK_ACTION_START);
140 create_group_pseudo_op(rsc, PCMK_ACTION_RUNNING);
141 create_group_pseudo_op(rsc, PCMK_ACTION_STOP);
142 create_group_pseudo_op(rsc, PCMK_ACTION_STOPPED);
143 if (crm_is_true(g_hash_table_lookup(rsc->priv->meta,
144 PCMK_META_PROMOTABLE))) {
145 create_group_pseudo_op(rsc, PCMK_ACTION_DEMOTE);
146 create_group_pseudo_op(rsc, PCMK_ACTION_DEMOTED);
147 create_group_pseudo_op(rsc, PCMK_ACTION_PROMOTE);
148 create_group_pseudo_op(rsc, PCMK_ACTION_PROMOTED);
149 }
150 }
151
152
153 struct member_data {
154
155 bool ordered;
156 bool colocated;
157 bool promotable;
158
159 pcmk_resource_t *last_active;
160 pcmk_resource_t *previous_member;
161 };
162
163
164
165
166
167
168
169
170 static void
171 member_internal_constraints(gpointer data, gpointer user_data)
172 {
173 pcmk_resource_t *member = (pcmk_resource_t *) data;
174 struct member_data *member_data = (struct member_data *) user_data;
175
176
177 uint32_t down_flags = pcmk__ar_then_implies_first_graphed;
178
179
180 uint32_t post_down_flags = pcmk__ar_first_implies_then_graphed;
181
182
183 member->priv->cmds->internal_constraints(member);
184
185 if (member_data->previous_member == NULL) {
186
187 if (member_data->ordered) {
188 pcmk__set_relation_flags(down_flags, pcmk__ar_ordered);
189 post_down_flags = pcmk__ar_first_implies_then;
190 }
191
192 } else if (member_data->colocated) {
193 uint32_t flags = pcmk__coloc_none;
194
195 if (pcmk_is_set(member->flags, pcmk__rsc_critical)) {
196 flags |= pcmk__coloc_influence;
197 }
198
199
200 pcmk__new_colocation("#group-members", NULL, PCMK_SCORE_INFINITY,
201 member, member_data->previous_member, NULL, NULL,
202 flags);
203 }
204
205 if (member_data->promotable) {
206
207 pcmk__order_resource_actions(member->priv->parent,
208 PCMK_ACTION_DEMOTE,
209 member, PCMK_ACTION_DEMOTE, down_flags);
210 pcmk__order_resource_actions(member, PCMK_ACTION_DEMOTE,
211 member->priv->parent,
212 PCMK_ACTION_DEMOTED, post_down_flags);
213
214
215 pcmk__order_resource_actions(member, PCMK_ACTION_PROMOTE,
216 member->priv->parent,
217 PCMK_ACTION_PROMOTED,
218 pcmk__ar_unrunnable_first_blocks
219 |pcmk__ar_first_implies_then
220 |pcmk__ar_first_implies_then_graphed);
221 pcmk__order_resource_actions(member->priv->parent,
222 PCMK_ACTION_PROMOTE,
223 member, PCMK_ACTION_PROMOTE,
224 pcmk__ar_then_implies_first_graphed);
225 }
226
227
228 pcmk__order_stops(member->priv->parent, member, down_flags);
229 pcmk__order_resource_actions(member, PCMK_ACTION_STOP,
230 member->priv->parent, PCMK_ACTION_STOPPED,
231 post_down_flags);
232
233
234 pcmk__order_starts(member->priv->parent, member,
235 pcmk__ar_then_implies_first_graphed);
236 pcmk__order_resource_actions(member, PCMK_ACTION_START,
237 member->priv->parent, PCMK_ACTION_RUNNING,
238 pcmk__ar_unrunnable_first_blocks
239 |pcmk__ar_first_implies_then
240 |pcmk__ar_first_implies_then_graphed);
241
242 if (!member_data->ordered) {
243 pcmk__order_starts(member->priv->parent, member,
244 pcmk__ar_first_implies_then
245 |pcmk__ar_unrunnable_first_blocks
246 |pcmk__ar_then_implies_first_graphed);
247 if (member_data->promotable) {
248 pcmk__order_resource_actions(member->priv->parent,
249 PCMK_ACTION_PROMOTE,
250 member, PCMK_ACTION_PROMOTE,
251 pcmk__ar_first_implies_then
252 |pcmk__ar_unrunnable_first_blocks
253 |pcmk__ar_then_implies_first_graphed);
254 }
255
256 } else if (member_data->previous_member == NULL) {
257 pcmk__order_starts(member->priv->parent, member, pcmk__ar_none);
258 if (member_data->promotable) {
259 pcmk__order_resource_actions(member->priv->parent,
260 PCMK_ACTION_PROMOTE,
261 member, PCMK_ACTION_PROMOTE,
262 pcmk__ar_none);
263 }
264
265 } else {
266
267
268 pcmk__order_starts(member_data->previous_member, member,
269 pcmk__ar_first_implies_then
270 |pcmk__ar_unrunnable_first_blocks);
271 pcmk__order_stops(member, member_data->previous_member,
272 pcmk__ar_ordered|pcmk__ar_intermediate_stop);
273
274
275
276
277
278
279
280 if ((member->priv->active_nodes != NULL)
281 && (member_data->previous_member->priv->active_nodes == NULL)) {
282 pcmk__order_resource_actions(member, PCMK_ACTION_STOP,
283 member_data->previous_member,
284 PCMK_ACTION_START,
285 pcmk__ar_then_implies_first
286 |pcmk__ar_unrunnable_first_blocks);
287 }
288
289 if (member_data->promotable) {
290 pcmk__order_resource_actions(member_data->previous_member,
291 PCMK_ACTION_PROMOTE, member,
292 PCMK_ACTION_PROMOTE,
293 pcmk__ar_first_implies_then
294 |pcmk__ar_unrunnable_first_blocks);
295 pcmk__order_resource_actions(member, PCMK_ACTION_DEMOTE,
296 member_data->previous_member,
297 PCMK_ACTION_DEMOTE, pcmk__ar_ordered);
298 }
299 }
300
301
302 if (member->priv->active_nodes != NULL) {
303 if (member_data->ordered && (member_data->previous_member != NULL)
304 && (member_data->previous_member->priv->active_nodes == NULL)
305 && (member_data->last_active != NULL)
306 && (member_data->last_active->priv->active_nodes != NULL)) {
307 pcmk__order_stops(member, member_data->last_active,
308 pcmk__ar_ordered);
309 }
310 member_data->last_active = member;
311 }
312
313 member_data->previous_member = member;
314 }
315
316
317
318
319
320
321
322 void
323 pcmk__group_internal_constraints(pcmk_resource_t *rsc)
324 {
325 struct member_data member_data = { false, };
326 const pcmk_resource_t *top = NULL;
327
328 pcmk__assert(pcmk__is_group(rsc));
329
330
331
332
333 pcmk__order_resource_actions(rsc, PCMK_ACTION_STOP,
334 rsc, PCMK_ACTION_STOPPED,
335 pcmk__ar_unrunnable_first_blocks);
336 pcmk__order_resource_actions(rsc, PCMK_ACTION_STOPPED,
337 rsc, PCMK_ACTION_START,
338 pcmk__ar_ordered);
339 pcmk__order_resource_actions(rsc, PCMK_ACTION_START,
340 rsc, PCMK_ACTION_RUNNING,
341 pcmk__ar_unrunnable_first_blocks);
342
343 top = pe__const_top_resource(rsc, false);
344
345 member_data.ordered = pe__group_flag_is_set(rsc, pcmk__group_ordered);
346 member_data.colocated = pe__group_flag_is_set(rsc, pcmk__group_colocated);
347 member_data.promotable = pcmk_is_set(top->flags, pcmk__rsc_promotable);
348 g_list_foreach(rsc->priv->children, member_internal_constraints,
349 &member_data);
350 }
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366 static int
367 colocate_group_with(pcmk_resource_t *dependent, const pcmk_resource_t *primary,
368 const pcmk__colocation_t *colocation)
369 {
370 int priority_delta = 0;
371
372 if (dependent->priv->children == NULL) {
373 return 0;
374 }
375
376 pcmk__rsc_trace(primary, "Processing %s (group %s with %s) for dependent",
377 colocation->id, dependent->id, primary->id);
378
379 if (pe__group_flag_is_set(dependent, pcmk__group_colocated)) {
380
381 pcmk_resource_t *member = dependent->priv->children->data;
382 priority_delta = member->priv->cmds->apply_coloc_score(member, primary,
383 colocation,
384 true);
385
386 } else {
387 if (colocation->score >= PCMK_SCORE_INFINITY) {
388 pcmk__config_err("%s: Cannot perform mandatory colocation between "
389 "non-colocated group and %s",
390 dependent->id, primary->id);
391 return 0;
392 }
393
394
395 for (GList *iter = dependent->priv->children; iter != NULL;
396 iter = iter->next) {
397
398 int instance_delta = 0;
399 pcmk_resource_t *member = iter->data;
400
401 instance_delta =
402 member->priv->cmds->apply_coloc_score(member, primary,
403 colocation, false);
404
405
406
407
408
409
410
411 priority_delta = pcmk__add_scores(priority_delta, instance_delta);
412 }
413 }
414
415 if (priority_delta != 0) {
416 dependent->priv->priority =
417 pcmk__add_scores(priority_delta, dependent->priv->priority);
418
419 pcmk__rsc_trace(dependent,
420 "Applied %s to %s promotion priority "
421 "(now %s after %s %d)",
422 colocation->id, dependent->id,
423 pcmk_readable_score(dependent->priv->priority),
424 ((priority_delta > 0)? "adding" : "subtracting"),
425 QB_ABS(priority_delta));
426 }
427 return priority_delta;
428 }
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444 static int
445 colocate_with_group(pcmk_resource_t *dependent, const pcmk_resource_t *primary,
446 const pcmk__colocation_t *colocation)
447 {
448 int priority_delta = 0;
449 const pcmk_resource_t *member = NULL;
450
451 pcmk__rsc_trace(primary,
452 "Processing colocation %s (%s with group %s) for primary",
453 colocation->id, dependent->id, primary->id);
454
455 if (pcmk_is_set(primary->flags, pcmk__rsc_unassigned)) {
456 return 0;
457 }
458
459 if (pe__group_flag_is_set(primary, pcmk__group_colocated)) {
460
461 if (colocation->score >= PCMK_SCORE_INFINITY) {
462
463
464
465
466 member = pe__last_group_member(primary);
467 } else if (primary->priv->children != NULL) {
468
469
470
471
472 member = (pcmk_resource_t *) primary->priv->children->data;
473 }
474 if (member == NULL) {
475 return 0;
476 }
477
478 return member->priv->cmds->apply_coloc_score(dependent, member,
479 colocation, false);
480 }
481
482 if (colocation->score >= PCMK_SCORE_INFINITY) {
483 pcmk__config_err("%s: Cannot perform mandatory colocation with"
484 " non-colocated group %s",
485 dependent->id, primary->id);
486 return 0;
487 }
488
489
490 for (const GList *iter = primary->priv->children;
491 iter != NULL; iter = iter->next) {
492
493 int instance_delta = 0;
494
495 member = iter->data;
496 instance_delta = member->priv->cmds->apply_coloc_score(dependent,
497 member,
498 colocation,
499 false);
500 priority_delta = pcmk__add_scores(priority_delta, instance_delta);
501 }
502 return priority_delta;
503 }
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520 int
521 pcmk__group_apply_coloc_score(pcmk_resource_t *dependent,
522 const pcmk_resource_t *primary,
523 const pcmk__colocation_t *colocation,
524 bool for_dependent)
525 {
526 pcmk__assert((dependent != NULL) && (primary != NULL)
527 && (colocation != NULL));
528
529 if (for_dependent) {
530 return colocate_group_with(dependent, primary, colocation);
531
532 } else {
533
534 pcmk__assert(pcmk__is_primitive(dependent));
535
536 return colocate_with_group(dependent, primary, colocation);
537 }
538 }
539
540
541
542
543
544
545
546
547
548
549 uint32_t
550 pcmk__group_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
551 {
552
553 uint32_t flags = pcmk__action_optional
554 |pcmk__action_runnable
555 |pcmk__action_pseudo;
556
557 pcmk__assert(action != NULL);
558
559
560 for (GList *iter = action->rsc->priv->children;
561 iter != NULL; iter = iter->next) {
562
563 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
564
565
566 enum pcmk__action_type task = get_complex_task(member, action->task);
567 const char *task_s = pcmk__action_text(task);
568 pcmk_action_t *member_action = NULL;
569
570 member_action = find_first_action(member->priv->actions, NULL,
571 task_s, node);
572 if (member_action != NULL) {
573 uint32_t member_flags = 0U;
574
575 member_flags = member->priv->cmds->action_flags(member_action,
576 node);
577
578
579 if (pcmk_is_set(flags, pcmk__action_optional)
580 && !pcmk_is_set(member_flags, pcmk__action_optional)) {
581 pcmk__rsc_trace(action->rsc, "%s is mandatory because %s is",
582 action->uuid, member_action->uuid);
583 pcmk__clear_raw_action_flags(flags, "group action",
584 pcmk__action_optional);
585 pcmk__clear_action_flags(action, pcmk__action_optional);
586 }
587
588
589 if (!pcmk__str_eq(task_s, action->task, pcmk__str_none)
590 && pcmk_is_set(flags, pcmk__action_runnable)
591 && !pcmk_is_set(member_flags, pcmk__action_runnable)) {
592
593 pcmk__rsc_trace(action->rsc, "%s is unrunnable because %s is",
594 action->uuid, member_action->uuid);
595 pcmk__clear_raw_action_flags(flags, "group action",
596 pcmk__action_runnable);
597 pcmk__clear_action_flags(action, pcmk__action_runnable);
598 }
599
600
601
602
603 } else if ((task != pcmk__action_stop)
604 && (task != pcmk__action_demote)) {
605 pcmk__rsc_trace(action->rsc,
606 "%s is not runnable because %s will not %s",
607 action->uuid, member->id, task_s);
608 pcmk__clear_raw_action_flags(flags, "group action",
609 pcmk__action_runnable);
610 }
611 }
612
613 return flags;
614 }
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638 uint32_t
639 pcmk__group_update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then,
640 const pcmk_node_t *node, uint32_t flags,
641 uint32_t filter, uint32_t type,
642 pcmk_scheduler_t *scheduler)
643 {
644 uint32_t changed = pcmk__updated_none;
645
646
647 pcmk__assert((first != NULL) && (then != NULL) && (then->rsc != NULL)
648 && (scheduler != NULL));
649
650
651 changed |= pcmk__update_ordered_actions(first, then, node, flags, filter,
652 type, scheduler);
653
654
655 for (GList *iter = then->rsc->priv->children;
656 iter != NULL; iter = iter->next) {
657
658 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
659 pcmk_action_t *member_action = NULL;
660
661 member_action = find_first_action(member->priv->actions, NULL,
662 then->task, node);
663 if (member_action == NULL) {
664 continue;
665 }
666 changed |= member->priv->cmds->update_ordered_actions(first,
667 member_action,
668 node, flags,
669 filter, type,
670 scheduler);
671 }
672 return changed;
673 }
674
675
676
677
678
679
680
681
682 void
683 pcmk__group_apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
684 {
685 GList *node_list_orig = NULL;
686 GList *node_list_copy = NULL;
687
688 pcmk__assert(pcmk__is_group(rsc) && (location != NULL));
689
690
691 node_list_orig = location->nodes;
692
693
694 node_list_copy = pcmk__copy_node_list(node_list_orig, true);
695
696
697
698
699
700 pcmk__apply_location(rsc, location);
701
702
703 for (GList *iter = rsc->priv->children;
704 iter != NULL; iter = iter->next) {
705
706 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
707
708 if (pe__group_flag_is_set(rsc, pcmk__group_colocated)
709 && (iter != rsc->priv->children)) {
710
711
712
713
714
715
716
717
718
719
720
721
722 location->nodes = node_list_copy;
723 }
724
725 member->priv->cmds->apply_location(member, location);
726 }
727
728 location->nodes = node_list_orig;
729 g_list_free_full(node_list_copy, free);
730 }
731
732
733 GList *
734 pcmk__group_colocated_resources(const pcmk_resource_t *rsc,
735 const pcmk_resource_t *orig_rsc,
736 GList *colocated_rscs)
737 {
738 pcmk__assert(pcmk__is_group(rsc));
739
740 if (orig_rsc == NULL) {
741 orig_rsc = rsc;
742 }
743
744 if (pe__group_flag_is_set(rsc, pcmk__group_colocated)
745 || pcmk__is_clone(rsc->priv->parent)) {
746
747
748
749
750 colocated_rscs = g_list_prepend(colocated_rscs, (gpointer) rsc);
751
752 for (const GList *iter = rsc->priv->children;
753 iter != NULL; iter = iter->next) {
754
755 const pcmk_resource_t *member = iter->data;
756
757 colocated_rscs = member->priv->cmds->colocated_resources(member,
758 orig_rsc,
759 colocated_rscs);
760 }
761
762 } else if (rsc->priv->children != NULL) {
763
764
765
766 colocated_rscs = pcmk__colocated_resources(rsc, orig_rsc,
767 colocated_rscs);
768 }
769
770 return colocated_rscs;
771 }
772
773
774 void
775 pcmk__with_group_colocations(const pcmk_resource_t *rsc,
776 const pcmk_resource_t *orig_rsc, GList **list)
777
778 {
779 const pcmk_resource_t *parent = NULL;
780
781 pcmk__assert((orig_rsc != NULL) && (list != NULL) && pcmk__is_group(rsc));
782 parent = rsc->priv->parent;
783
784
785 if (rsc->priv->children == NULL) {
786 return;
787 }
788
789
790
791
792
793 if ((orig_rsc != rsc) && (orig_rsc != pe__last_group_member(rsc))) {
794 return;
795 }
796
797 pcmk__rsc_trace(rsc, "Adding 'with %s' colocations to list for %s",
798 rsc->id, orig_rsc->id);
799
800
801 pcmk__add_with_this_list(list, rsc->priv->with_this_colocations,
802 orig_rsc);
803
804
805 if (parent != NULL) {
806 parent->priv->cmds->with_this_colocations(parent, orig_rsc, list);
807 }
808
809 if (!pe__group_flag_is_set(rsc, pcmk__group_colocated)) {
810
811 return;
812 }
813
814
815 for (const GList *iter = rsc->priv->children;
816 iter != NULL; iter = iter->next) {
817
818 const pcmk_resource_t *member = iter->data;
819
820 if (member == orig_rsc) {
821 continue;
822 }
823 member->priv->cmds->with_this_colocations(member, orig_rsc, list);
824 }
825 }
826
827
828 void
829 pcmk__group_with_colocations(const pcmk_resource_t *rsc,
830 const pcmk_resource_t *orig_rsc, GList **list)
831 {
832 const pcmk_resource_t *parent = NULL;
833 const pcmk_resource_t *member = NULL;
834
835 pcmk__assert((orig_rsc != NULL) && (list != NULL) && pcmk__is_group(rsc));
836 parent = rsc->priv->parent;
837
838
839 if (rsc->priv->children == NULL) {
840 return;
841 }
842
843
844
845
846 if ((rsc == orig_rsc) || (orig_rsc == rsc->priv->children->data)) {
847 pcmk__rsc_trace(rsc, "Adding '%s with' colocations to list for %s",
848 rsc->id, orig_rsc->id);
849
850
851 pcmk__add_this_with_list(list, rsc->priv->this_with_colocations,
852 orig_rsc);
853
854
855 if (parent != NULL) {
856 parent->priv->cmds->this_with_colocations(parent, orig_rsc, list);
857 }
858
859 if (!pe__group_flag_is_set(rsc, pcmk__group_colocated)) {
860
861 return;
862 }
863
864
865 for (const GList *iter = rsc->priv->children;
866 iter != NULL; iter = iter->next) {
867
868 member = iter->data;
869 if (member == orig_rsc) {
870 continue;
871 }
872 member->priv->cmds->this_with_colocations(member, orig_rsc, list);
873 }
874 return;
875 }
876
877
878
879
880
881
882 for (const GList *iter = rsc->priv->children;
883 iter != NULL; iter = iter->next) {
884
885 member = iter->data;
886 if (orig_rsc == member) {
887 break;
888 }
889
890 if (!pcmk_is_set(member->flags, pcmk__rsc_managed)) {
891 crm_trace("Adding mandatory '%s with' colocations to list for "
892 "member %s because earlier member %s is unmanaged",
893 rsc->id, orig_rsc->id, member->id);
894 for (const GList *cons_iter = rsc->priv->this_with_colocations;
895 cons_iter != NULL; cons_iter = cons_iter->next) {
896 const pcmk__colocation_t *colocation = NULL;
897
898 colocation = (const pcmk__colocation_t *) cons_iter->data;
899 if (colocation->score == PCMK_SCORE_INFINITY) {
900 pcmk__add_this_with(list, colocation, orig_rsc);
901 }
902 }
903
904 break;
905 }
906 }
907 }
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939 void
940 pcmk__group_add_colocated_node_scores(pcmk_resource_t *source_rsc,
941 const pcmk_resource_t *target_rsc,
942 const char *log_id, GHashTable **nodes,
943 const pcmk__colocation_t *colocation,
944 float factor, uint32_t flags)
945 {
946 pcmk_resource_t *member = NULL;
947
948 pcmk__assert(pcmk__is_group(source_rsc) && (nodes != NULL)
949 && ((colocation != NULL)
950 || ((target_rsc == NULL) && (*nodes == NULL))));
951
952 if (log_id == NULL) {
953 log_id = source_rsc->id;
954 }
955
956
957 if (pcmk_is_set(source_rsc->flags, pcmk__rsc_updating_nodes)) {
958 pcmk__rsc_info(source_rsc, "%s: Breaking dependency loop at %s",
959 log_id, source_rsc->id);
960 return;
961 }
962 pcmk__set_rsc_flags(source_rsc, pcmk__rsc_updating_nodes);
963
964
965 if (source_rsc->priv->children == NULL) {
966 return;
967 }
968
969
970
971
972
973
974
975
976
977
978
979 if (*nodes == NULL) {
980 member = pe__last_group_member(source_rsc);
981 } else {
982 member = source_rsc->priv->children->data;
983 }
984
985 pcmk__rsc_trace(source_rsc, "%s: Merging scores from group %s using member %s "
986 "(at %.6f)", log_id, source_rsc->id, member->id, factor);
987 member->priv->cmds->add_colocated_node_scores(member, target_rsc, log_id,
988 nodes, colocation, factor,
989 flags);
990 pcmk__clear_rsc_flags(source_rsc, pcmk__rsc_updating_nodes);
991 }
992
993
994 void
995 pcmk__group_add_utilization(const pcmk_resource_t *rsc,
996 const pcmk_resource_t *orig_rsc, GList *all_rscs,
997 GHashTable *utilization)
998 {
999 pcmk_resource_t *member = NULL;
1000
1001 pcmk__assert((orig_rsc != NULL) && (utilization != NULL)
1002 && pcmk__is_group(rsc));
1003
1004 if (!pcmk_is_set(rsc->flags, pcmk__rsc_unassigned)) {
1005 return;
1006 }
1007
1008 pcmk__rsc_trace(orig_rsc, "%s: Adding group %s as colocated utilization",
1009 orig_rsc->id, rsc->id);
1010 if (pe__group_flag_is_set(rsc, pcmk__group_colocated)
1011 || pcmk__is_clone(rsc->priv->parent)) {
1012
1013
1014 for (GList *iter = rsc->priv->children;
1015 iter != NULL; iter = iter->next) {
1016
1017 member = (pcmk_resource_t *) iter->data;
1018
1019 if (pcmk_is_set(member->flags, pcmk__rsc_unassigned)
1020 && (g_list_find(all_rscs, member) == NULL)) {
1021 member->priv->cmds->add_utilization(member, orig_rsc, all_rscs,
1022 utilization);
1023 }
1024 }
1025
1026 } else if (rsc->priv->children != NULL) {
1027
1028 member = (pcmk_resource_t *) rsc->priv->children->data;
1029 if ((member != NULL)
1030 && pcmk_is_set(member->flags, pcmk__rsc_unassigned)
1031 && (g_list_find(all_rscs, member) == NULL)) {
1032
1033 member->priv->cmds->add_utilization(member, orig_rsc, all_rscs,
1034 utilization);
1035 }
1036 }
1037 }
1038
1039 void
1040 pcmk__group_shutdown_lock(pcmk_resource_t *rsc)
1041 {
1042 pcmk__assert(pcmk__is_group(rsc));
1043
1044 for (GList *iter = rsc->priv->children;
1045 iter != NULL; iter = iter->next) {
1046
1047 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
1048
1049 member->priv->cmds->shutdown_lock(member);
1050 }
1051 }