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