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