pacemaker 2.1.6-6fdc9deea29
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_sched_group.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2023 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU General Public License version 2
7 * or later (GPLv2+) WITHOUT ANY WARRANTY.
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>
18
30{
31 pe_node_t *first_assigned_node = NULL;
32 pe_resource_t *first_member = NULL;
33
34 CRM_ASSERT(rsc != NULL);
35
37 return rsc->allocated_to; // Assignment already done
38 }
40 pe_rsc_debug(rsc, "Assignment dependency loop detected involving %s",
41 rsc->id);
42 return NULL;
43 }
44
45 if (rsc->children == NULL) {
46 // No members to assign
48 return NULL;
49 }
50
52 first_member = (pe_resource_t *) rsc->children->data;
53 rsc->role = first_member->role;
54
56 rsc, __func__, rsc->allowed_nodes, rsc->cluster);
57
58 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
59 pe_resource_t *member = (pe_resource_t *) iter->data;
60 pe_node_t *node = NULL;
61
62 pe_rsc_trace(rsc, "Assigning group %s member %s",
63 rsc->id, member->id);
64 node = member->cmds->assign(member, prefer);
65 if (first_assigned_node == NULL) {
66 first_assigned_node = node;
67 }
68 }
69
70 pe__set_next_role(rsc, first_member->next_role, "first group member");
72
74 return NULL;
75 }
76 return first_assigned_node;
77}
78
88static pe_action_t *
89create_group_pseudo_op(pe_resource_t *group, const char *action)
90{
91 pe_action_t *op = custom_action(group, pcmk__op_key(group->id, action, 0),
92 action, NULL, TRUE, TRUE, group->cluster);
94 return op;
95}
96
103void
105{
106 CRM_ASSERT(rsc != NULL);
107
108 pe_rsc_trace(rsc, "Creating actions for group %s", rsc->id);
109
110 // Create actions for individual group members
111 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
112 pe_resource_t *member = (pe_resource_t *) iter->data;
113
114 member->cmds->create_actions(member);
115 }
116
117 // Create pseudo-actions for group itself to serve as ordering points
118 create_group_pseudo_op(rsc, RSC_START);
119 create_group_pseudo_op(rsc, RSC_STARTED);
120 create_group_pseudo_op(rsc, RSC_STOP);
121 create_group_pseudo_op(rsc, RSC_STOPPED);
122 if (crm_is_true(g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_PROMOTABLE))) {
123 create_group_pseudo_op(rsc, RSC_DEMOTE);
124 create_group_pseudo_op(rsc, RSC_DEMOTED);
125 create_group_pseudo_op(rsc, RSC_PROMOTE);
126 create_group_pseudo_op(rsc, RSC_PROMOTED);
127 }
128}
129
130// User data for member_internal_constraints()
131struct member_data {
132 // These could be derived from member but this avoids some function calls
133 bool ordered;
134 bool colocated;
135 bool promotable;
136
137 pe_resource_t *last_active;
138 pe_resource_t *previous_member;
139};
140
148static void
149member_internal_constraints(gpointer data, gpointer user_data)
150{
151 pe_resource_t *member = (pe_resource_t *) data;
152 struct member_data *member_data = (struct member_data *) user_data;
153
154 // For ordering demote vs demote or stop vs stop
155 uint32_t down_flags = pe_order_implies_first_printed;
156
157 // For ordering demote vs demoted or stop vs stopped
158 uint32_t post_down_flags = pe_order_implies_then_printed;
159
160 // Create the individual member's implicit constraints
161 member->cmds->internal_constraints(member);
162
163 if (member_data->previous_member == NULL) {
164 // This is first member
165 if (member_data->ordered) {
167 post_down_flags = pe_order_implies_then;
168 }
169
170 } else if (member_data->colocated) {
171 // Colocate this member with the previous one
172 pcmk__new_colocation("group:internal_colocation", NULL, INFINITY,
173 member, member_data->previous_member, NULL, NULL,
175 member->cluster);
176 }
177
178 if (member_data->promotable) {
179 // Demote group -> demote member -> group is demoted
181 member, RSC_DEMOTE, down_flags);
183 member->parent, RSC_DEMOTED,
184 post_down_flags);
185
186 // Promote group -> promote member -> group is promoted
188 member->parent, RSC_PROMOTED,
193 member, RSC_PROMOTE,
195 }
196
197 // Stop group -> stop member -> group is stopped
198 pcmk__order_stops(member->parent, member, down_flags);
200 post_down_flags);
201
202 // Start group -> start member -> group is started
208
209 if (!member_data->ordered) {
210 pcmk__order_starts(member->parent, member,
214 if (member_data->promotable) {
220 }
221
222 } else if (member_data->previous_member == NULL) {
223 pcmk__order_starts(member->parent, member, pe_order_none);
224 if (member_data->promotable) {
227 }
228
229 } else {
230 // Order this member relative to the previous one
231
232 pcmk__order_starts(member_data->previous_member, member,
234 pcmk__order_stops(member, member_data->previous_member,
236
237 /* In unusual circumstances (such as adding a new member to the middle
238 * of a group with unmanaged later members), this member may be active
239 * while the previous (new) member is inactive. In this situation, the
240 * usual restart orderings will be irrelevant, so we need to order this
241 * member's stop before the previous member's start.
242 */
243 if ((member->running_on != NULL)
244 && (member_data->previous_member->running_on == NULL)) {
246 member_data->previous_member, RSC_START,
249 }
250
251 if (member_data->promotable) {
252 pcmk__order_resource_actions(member_data->previous_member,
253 RSC_PROMOTE, member, RSC_PROMOTE,
257 member_data->previous_member,
259 }
260 }
261
262 // Make sure partially active groups shut down in sequence
263 if (member->running_on != NULL) {
264 if (member_data->ordered && (member_data->previous_member != NULL)
265 && (member_data->previous_member->running_on == NULL)
266 && (member_data->last_active != NULL)
267 && (member_data->last_active->running_on != NULL)) {
268 pcmk__order_stops(member, member_data->last_active, pe_order_optional);
269 }
270 member_data->last_active = member;
271 }
272
273 member_data->previous_member = member;
274}
275
282void
284{
285 struct member_data member_data = { false, };
286
287 CRM_ASSERT(rsc != NULL);
288
289 /* Order group pseudo-actions relative to each other for restarting:
290 * stop group -> group is stopped -> start group -> group is started
291 */
298
299 member_data.ordered = pe__group_flag_is_set(rsc, pe__group_ordered);
300 member_data.colocated = pe__group_flag_is_set(rsc, pe__group_colocated);
301 member_data.promotable = pcmk_is_set(pe__const_top_resource(rsc, false)->flags,
303 g_list_foreach(rsc->children, member_internal_constraints, &member_data);
304}
305
318static void
319colocate_group_with(pe_resource_t *dependent, const pe_resource_t *primary,
320 const pcmk__colocation_t *colocation)
321{
322 pe_resource_t *member = NULL;
323
324 if (dependent->children == NULL) {
325 return;
326 }
327
328 pe_rsc_trace(primary, "Processing %s (group %s with %s) for dependent",
329 colocation->id, dependent->id, primary->id);
330
332 // Colocate first member (internal colocations will handle the rest)
333 member = (pe_resource_t *) dependent->children->data;
334 member->cmds->apply_coloc_score(member, primary, colocation, true);
335 return;
336 }
337
338 if (colocation->score >= INFINITY) {
339 pcmk__config_err("%s: Cannot perform mandatory colocation between "
340 "non-colocated group and %s",
341 dependent->id, primary->id);
342 return;
343 }
344
345 // Colocate each member individually
346 for (GList *iter = dependent->children; iter != NULL; iter = iter->next) {
347 member = (pe_resource_t *) iter->data;
348 member->cmds->apply_coloc_score(member, primary, colocation, true);
349 }
350}
351
364static void
365colocate_with_group(pe_resource_t *dependent, const pe_resource_t *primary,
366 const pcmk__colocation_t *colocation)
367{
368 pe_resource_t *member = NULL;
369
370 pe_rsc_trace(primary,
371 "Processing colocation %s (%s with group %s) for primary",
372 colocation->id, dependent->id, primary->id);
373
374 if (pcmk_is_set(primary->flags, pe_rsc_provisional)) {
375 return;
376 }
377
379
380 if (colocation->score >= INFINITY) {
381 /* For mandatory colocations, the entire group must be assignable
382 * (and in the specified role if any), so apply the colocation based
383 * on the last member.
384 */
385 member = pe__last_group_member(primary);
386 } else if (primary->children != NULL) {
387 /* For optional colocations, whether the group is partially or fully
388 * up doesn't matter, so apply the colocation based on the first
389 * member.
390 */
391 member = (pe_resource_t *) primary->children->data;
392 }
393 if (member == NULL) {
394 return; // Nothing to colocate with
395 }
396
397 member->cmds->apply_coloc_score(dependent, member, colocation, false);
398 return;
399 }
400
401 if (colocation->score >= INFINITY) {
402 pcmk__config_err("%s: Cannot perform mandatory colocation with"
403 " non-colocated group %s",
404 dependent->id, primary->id);
405 return;
406 }
407
408 // Colocate dependent with each member individually
409 for (GList *iter = primary->children; iter != NULL; iter = iter->next) {
410 member = (pe_resource_t *) iter->data;
411 member->cmds->apply_coloc_score(dependent, member, colocation, false);
412 }
413}
414
428void
430 const pe_resource_t *primary,
431 const pcmk__colocation_t *colocation,
432 bool for_dependent)
433{
434 CRM_ASSERT((dependent != NULL) && (primary != NULL)
435 && (colocation != NULL));
436
437 if (for_dependent) {
438 colocate_group_with(dependent, primary, colocation);
439
440 } else {
441 // Method should only be called for primitive dependents
442 CRM_ASSERT(dependent->variant == pe_native);
443
444 colocate_with_group(dependent, primary, colocation);
445 }
446}
447
459{
460 // Default flags for a group action
464
465 CRM_ASSERT(action != NULL);
466
467 // Update flags considering each member's own flags for same action
468 for (GList *iter = action->rsc->children; iter != NULL; iter = iter->next) {
469 pe_resource_t *member = (pe_resource_t *) iter->data;
470
471 // Check whether member has the same action
472 enum action_tasks task = get_complex_task(member, action->task);
473 const char *task_s = task2text(task);
474 pe_action_t *member_action = find_first_action(member->actions, NULL,
475 task_s, node);
476
477 if (member_action != NULL) {
478 enum pe_action_flags member_flags;
479
480 member_flags = member->cmds->action_flags(member_action, node);
481
482 // Group action is mandatory if any member action is
484 && !pcmk_is_set(member_flags, pe_action_optional)) {
485 pe_rsc_trace(action->rsc, "%s is mandatory because %s is",
486 action->uuid, member_action->uuid);
487 pe__clear_raw_action_flags(flags, "group action",
490 }
491
492 // Group action is unrunnable if any member action is
493 if (!pcmk__str_eq(task_s, action->task, pcmk__str_none)
495 && !pcmk_is_set(member_flags, pe_action_runnable)) {
496
497 pe_rsc_trace(action->rsc, "%s is unrunnable because %s is",
498 action->uuid, member_action->uuid);
499 pe__clear_raw_action_flags(flags, "group action",
502 }
503
504 /* Group (pseudo-)actions other than stop or demote are unrunnable
505 * unless every member will do it.
506 */
507 } else if ((task != stop_rsc) && (task != action_demote)) {
508 pe_rsc_trace(action->rsc,
509 "%s is not runnable because %s will not %s",
510 action->uuid, member->id, task_s);
511 pe__clear_raw_action_flags(flags, "group action",
513 }
514 }
515
516 return flags;
517}
518
541uint32_t
543 const pe_node_t *node, uint32_t flags,
544 uint32_t filter, uint32_t type,
546{
547 uint32_t changed = pcmk__updated_none;
548
549 CRM_ASSERT((first != NULL) && (then != NULL) && (data_set != NULL));
550
551 // Group method can be called only for group action as "then" action
552 CRM_ASSERT(then->rsc != NULL);
553
554 // Update the actions for the group itself
555 changed |= pcmk__update_ordered_actions(first, then, node, flags, filter,
556 type, data_set);
557
558 // Update the actions for each group member
559 for (GList *iter = then->rsc->children; iter != NULL; iter = iter->next) {
560 pe_resource_t *member = (pe_resource_t *) iter->data;
561
562 pe_action_t *member_action = find_first_action(member->actions, NULL,
563 then->task, node);
564
565 if (member_action != NULL) {
566 changed |= member->cmds->update_ordered_actions(first,
567 member_action, node,
568 flags, filter, type,
569 data_set);
570 }
571 }
572 return changed;
573}
574
582void
584{
585 GList *node_list_orig = NULL;
586 GList *node_list_copy = NULL;
587 bool reset_scores = true;
588
589 CRM_ASSERT((rsc != NULL) && (location != NULL));
590
591 node_list_orig = location->node_list_rh;
592 node_list_copy = pcmk__copy_node_list(node_list_orig, true);
593 reset_scores = pe__group_flag_is_set(rsc, pe__group_colocated);
594
595 // Apply the constraint for the group itself (updates node scores)
596 pcmk__apply_location(rsc, location);
597
598 // Apply the constraint for each member
599 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
600 pe_resource_t *member = (pe_resource_t *) iter->data;
601
602 member->cmds->apply_location(member, location);
603
604 if (reset_scores) {
605 /* The first member of colocated groups needs to use the original
606 * node scores, but subsequent members should work on a copy, since
607 * the first member's scores already incorporate theirs.
608 */
609 reset_scores = false;
610 location->node_list_rh = node_list_copy;
611 }
612 }
613
614 location->node_list_rh = node_list_orig;
615 g_list_free_full(node_list_copy, free);
616}
617
618// Group implementation of resource_alloc_functions_t:colocated_resources()
619GList *
621 const pe_resource_t *orig_rsc,
622 GList *colocated_rscs)
623{
624 const pe_resource_t *member = NULL;
625
626 CRM_ASSERT(rsc != NULL);
627
628 if (orig_rsc == NULL) {
629 orig_rsc = rsc;
630 }
631
633 || pe_rsc_is_clone(rsc->parent)) {
634 /* This group has colocated members and/or is cloned -- either way,
635 * add every child's colocated resources to the list. The first and last
636 * members will include the group's own colocations.
637 */
638 colocated_rscs = g_list_prepend(colocated_rscs, (gpointer) rsc);
639 for (const GList *iter = rsc->children;
640 iter != NULL; iter = iter->next) {
641
642 member = (const pe_resource_t *) iter->data;
643 colocated_rscs = member->cmds->colocated_resources(member, orig_rsc,
644 colocated_rscs);
645 }
646
647 } else if (rsc->children != NULL) {
648 /* This group's members are not colocated, and the group is not cloned,
649 * so just add the group's own colocations to the list.
650 */
651 colocated_rscs = pcmk__colocated_resources(rsc, orig_rsc, colocated_rscs);
652 }
653
654 return colocated_rscs;
655}
656
657// Group implementation of resource_alloc_functions_t:with_this_colocations()
658void
660 const pe_resource_t *orig_rsc, GList **list)
661
662{
663 CRM_CHECK((rsc != NULL) && (rsc->variant == pe_group)
664 && (orig_rsc != NULL) && (list != NULL),
665 return);
666
667 // Ignore empty groups
668 if (rsc->children == NULL) {
669 return;
670 }
671
672 /* "With this" colocations are needed only for the group itself and for its
673 * last member. Add the group's colocations plus any relevant
674 * parent colocations if cloned.
675 */
676 if ((rsc == orig_rsc) || (orig_rsc == pe__last_group_member(rsc))) {
677 crm_trace("Adding 'with %s' colocations to list for %s",
678 rsc->id, orig_rsc->id);
680 if (rsc->parent != NULL) { // Cloned group
681 rsc->parent->cmds->with_this_colocations(rsc->parent, orig_rsc,
682 list);
683 }
684 }
685}
686
687// Group implementation of resource_alloc_functions_t:this_with_colocations()
688void
690 const pe_resource_t *orig_rsc, GList **list)
691{
692 CRM_CHECK((rsc != NULL) && (rsc->variant == pe_group)
693 && (orig_rsc != NULL) && (list != NULL),
694 return);
695
696 // Ignore empty groups
697 if (rsc->children == NULL) {
698 return;
699 }
700
701 /* Colocations for the group itself, or for its first member, consist of the
702 * group's colocations plus any relevant parent colocations if cloned.
703 */
704 if ((rsc == orig_rsc)
705 || (orig_rsc == (const pe_resource_t *) rsc->children->data)) {
706 crm_trace("Adding '%s with' colocations to list for %s",
707 rsc->id, orig_rsc->id);
709 if (rsc->parent != NULL) { // Cloned group
710 rsc->parent->cmds->this_with_colocations(rsc->parent, orig_rsc,
711 list);
712 }
713 return;
714 }
715
716 /* Later group members honor the group's colocations indirectly, due to the
717 * internal group colocations that chain everything from the first member.
718 * However, if an earlier group member is unmanaged, this chaining will not
719 * happen, so the group's mandatory colocations must be explicitly added.
720 */
721 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
722 const pe_resource_t *member = (const pe_resource_t *) iter->data;
723
724 if (orig_rsc == member) {
725 break; // We've seen all earlier members, and none are unmanaged
726 }
727
728 if (!pcmk_is_set(member->flags, pe_rsc_managed)) {
729 crm_trace("Adding mandatory '%s with' colocations to list for "
730 "member %s because earlier member %s is unmanaged",
731 rsc->id, orig_rsc->id, member->id);
732 for (const GList *cons_iter = rsc->rsc_cons; cons_iter != NULL;
733 cons_iter = cons_iter->next) {
734 const pcmk__colocation_t *colocation = NULL;
735
736 colocation = (const pcmk__colocation_t *) cons_iter->data;
737 if (colocation->score == INFINITY) {
738 pcmk__add_this_with(list, colocation);
739 }
740 }
741 // @TODO Add mandatory (or all?) clone constraints if cloned
742 break;
743 }
744 }
745}
746
764void
766 GHashTable **nodes, const char *attr,
767 float factor, uint32_t flags)
768{
769 pe_resource_t *member = NULL;
770
771 CRM_CHECK((rsc != NULL) && (nodes != NULL), return);
772
773 if (log_id == NULL) {
774 log_id = rsc->id;
775 }
776
777 // Avoid infinite recursion
778 if (pcmk_is_set(rsc->flags, pe_rsc_merging)) {
779 pe_rsc_info(rsc, "%s: Breaking dependency loop at %s",
780 log_id, rsc->id);
781 return;
782 }
784
785 // Ignore empty groups (only possible with schema validation disabled)
786 if (rsc->children == NULL) {
787 return;
788 }
789
790 /* Refer the operation to the first or last member as appropriate.
791 *
792 * cmp_resources() is the only caller that passes a NULL nodes table,
793 * and is also the only caller using pcmk__coloc_select_this_with.
794 * For "this with" colocations, the last member will recursively incorporate
795 * all the other members' "this with" colocations via the internal group
796 * colocations (and via the first member, the group's own colocations).
797 *
798 * For "with this" colocations, the first member works similarly.
799 */
800 if (*nodes == NULL) {
801 member = pe__last_group_member(rsc);
802 } else {
803 member = rsc->children->data;
804 }
805 pe_rsc_trace(rsc, "%s: Merging scores from group %s using member %s "
806 "(at %.6f)", log_id, rsc->id, member->id, factor);
807 member->cmds->add_colocated_node_scores(member, log_id, nodes, attr, factor,
808 flags);
810}
811
812// Group implementation of resource_alloc_functions_t:add_utilization()
813void
815 const pe_resource_t *orig_rsc, GList *all_rscs,
816 GHashTable *utilization)
817{
818 pe_resource_t *member = NULL;
819
820 CRM_ASSERT((rsc != NULL) && (orig_rsc != NULL) && (utilization != NULL));
821
823 return;
824 }
825
826 pe_rsc_trace(orig_rsc, "%s: Adding group %s as colocated utilization",
827 orig_rsc->id, rsc->id);
829 || pe_rsc_is_clone(rsc->parent)) {
830 // Every group member will be on same node, so sum all members
831 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
832 member = (pe_resource_t *) iter->data;
833
835 && (g_list_find(all_rscs, member) == NULL)) {
836 member->cmds->add_utilization(member, orig_rsc, all_rscs,
837 utilization);
838 }
839 }
840
841 } else if (rsc->children != NULL) {
842 // Just add first member's utilization
843 member = (pe_resource_t *) rsc->children->data;
844 if ((member != NULL)
846 && (g_list_find(all_rscs, member) == NULL)) {
847
848 member->cmds->add_utilization(member, orig_rsc, all_rscs,
849 utilization);
850 }
851 }
852}
853
854// Group implementation of resource_alloc_functions_t:shutdown_lock()
855void
857{
858 CRM_ASSERT(rsc != NULL);
859
860 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
861 pe_resource_t *member = (pe_resource_t *) iter->data;
862
863 member->cmds->shutdown_lock(member);
864 }
865}
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition operations.c:42
uint64_t flags
Definition remote.c:3
gboolean crm_is_true(const char *s)
Definition strings.c:416
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:121
const char * task2text(enum action_tasks task)
Definition common.c:397
action_tasks
Definition common.h:61
@ action_demote
Definition common.h:72
@ stop_rsc
Definition common.h:64
enum crm_ais_msg_types type
Definition cpg.c:3
char data[0]
Definition cpg.c:10
#define RSC_PROMOTE
Definition crm.h:205
#define RSC_DEMOTE
Definition crm.h:207
#define RSC_STARTED
Definition crm.h:200
#define RSC_STOPPED
Definition crm.h:203
#define RSC_START
Definition crm.h:199
#define INFINITY
Definition crm.h:99
#define RSC_STOP
Definition crm.h:202
#define RSC_PROMOTED
Definition crm.h:206
#define RSC_DEMOTED
Definition crm.h:208
G_GNUC_INTERNAL void pcmk__new_colocation(const char *id, const char *node_attr, int score, pe_resource_t *dependent, pe_resource_t *primary, const char *dependent_role, const char *primary_role, bool influence, pe_working_set_t *data_set)
#define pcmk__order_starts(rsc1, rsc2, flags)
G_GNUC_INTERNAL void pcmk__add_with_this_list(GList **list, GList *addition)
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
G_GNUC_INTERNAL GList * pcmk__colocated_resources(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *colocated_rscs)
@ pcmk__updated_none
G_GNUC_INTERNAL void pcmk__add_this_with(GList **list, const pcmk__colocation_t *colocation)
#define pcmk__order_stops(rsc1, rsc2, flags)
G_GNUC_INTERNAL void pcmk__add_this_with_list(GList **list, GList *addition)
G_GNUC_INTERNAL void pcmk__apply_location(pe_resource_t *rsc, pe__location_t *constraint)
G_GNUC_INTERNAL uint32_t pcmk__update_ordered_actions(pe_action_t *first, pe_action_t *then, const pe_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pe_working_set_t *data_set)
#define CRM_CHECK(expr, failure_action)
Definition logging.h:235
#define crm_trace(fmt, args...)
Definition logging.h:381
#define pcmk__config_err(fmt...)
#define XML_RSC_ATTR_PROMOTABLE
Definition msg_xml.h:245
pe_working_set_t * data_set
const char * action
Definition pcmk_fence.c:30
void pcmk__group_shutdown_lock(pe_resource_t *rsc)
void pcmk__group_internal_constraints(pe_resource_t *rsc)
void pcmk__group_create_actions(pe_resource_t *rsc)
void pcmk__with_group_colocations(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
void pcmk__group_apply_coloc_score(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
enum pe_action_flags pcmk__group_action_flags(pe_action_t *action, const pe_node_t *node)
void pcmk__group_apply_location(pe_resource_t *rsc, pe__location_t *location)
GList * pcmk__group_colocated_resources(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *colocated_rscs)
void pcmk__group_with_colocations(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
uint32_t pcmk__group_update_ordered_actions(pe_action_t *first, pe_action_t *then, const pe_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pe_working_set_t *data_set)
void pcmk__group_add_utilization(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
pe_node_t * pcmk__group_assign(pe_resource_t *rsc, const pe_node_t *prefer)
void pcmk__group_add_colocated_node_scores(pe_resource_t *rsc, const char *log_id, GHashTable **nodes, const char *attr, float factor, uint32_t flags)
GList * pcmk__copy_node_list(const GList *list, bool reset)
#define pe_rsc_managed
Definition pe_types.h:273
@ pe_order_implies_first_printed
Definition pe_types.h:535
@ pe_order_restart
Definition pe_types.h:530
@ pe_order_implies_then
Definition pe_types.h:512
@ pe_order_none
Definition pe_types.h:507
@ pe_order_implies_then_printed
Definition pe_types.h:536
@ pe_order_optional
Definition pe_types.h:508
@ pe_order_implies_first
Definition pe_types.h:511
@ pe_order_runnable_left
Definition pe_types.h:518
#define pe_rsc_provisional
Definition pe_types.h:282
#define pe_rsc_allocating
Definition pe_types.h:283
#define pe_flag_show_scores
Definition pe_types.h:150
pe_action_flags
Definition pe_types.h:316
@ pe_action_optional
Definition pe_types.h:319
@ pe_action_runnable
Definition pe_types.h:318
@ pe_action_pseudo
Definition pe_types.h:317
#define pe_rsc_merging
Definition pe_types.h:284
@ pe_group
Definition pe_types.h:39
@ pe_native
Definition pe_types.h:38
#define pe_rsc_promotable
Definition pe_types.h:280
#define pe_rsc_critical
Definition pe_types.h:290
#define pe__show_node_weights(level, rsc, text, nodes, data_set)
Definition internal.h:385
enum action_tasks get_complex_task(const pe_resource_t *rsc, const char *name)
#define pe__clear_raw_action_flags(action_flags, action_name, flags_to_clear)
Definition internal.h:114
bool pe__group_flag_is_set(const pe_resource_t *group, uint32_t flags)
Definition group.c:57
pe_resource_t * pe__last_group_member(const pe_resource_t *group)
Definition group.c:37
@ pe__group_ordered
Definition internal.h:40
@ pe__group_colocated
Definition internal.h:41
pe_action_t * custom_action(pe_resource_t *rsc, char *key, const char *task, const pe_node_t *on_node, gboolean optional, gboolean foo, pe_working_set_t *data_set)
Create or update an action object.
Definition pe_actions.c:942
pe_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pe_node_t *on_node)
void pe__set_next_role(pe_resource_t *rsc, enum rsc_role_e role, const char *why)
Definition complex.c:1166
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition internal.h:83
#define pe_rsc_debug(rsc, fmt, args...)
Definition internal.h:49
#define pe_rsc_trace(rsc, fmt, args...)
Definition internal.h:50
#define pe__set_resource_flags(resource, flags_to_set)
Definition internal.h:77
#define pe_rsc_info(rsc, fmt, args...)
Definition internal.h:48
#define pe__clear_action_flags(action, flags_to_clear)
Definition internal.h:98
const pe_resource_t * pe__const_top_resource(const pe_resource_t *rsc, bool include_bundle)
Definition complex.c:947
#define pe__set_order_flags(order_flags, flags_to_set)
Definition internal.h:141
#define pe__set_action_flags(action, flags_to_set)
Definition internal.h:89
#define CRM_ASSERT(expr)
Definition results.h:42
@ pcmk__str_none
pe_resource_t * rsc
Definition pe_types.h:433
char * uuid
Definition pe_types.h:438
char * task
Definition pe_types.h:437
GList * running_on
Definition pe_types.h:398
GList * actions
Definition pe_types.h:391
enum pe_obj_types variant
Definition pe_types.h:356
GHashTable * meta
Definition pe_types.h:405
GList * rsc_cons
Definition pe_types.h:389
GList * rsc_cons_lhs
Definition pe_types.h:388
GList * children
Definition pe_types.h:409
pe_working_set_t * cluster
Definition pe_types.h:353
GHashTable * allowed_nodes
Definition pe_types.h:400
pe_node_t * allocated_to
Definition pe_types.h:395
unsigned long long flags
Definition pe_types.h:373
pe_resource_t * parent
Definition pe_types.h:354
resource_alloc_functions_t * cmds
Definition pe_types.h:359
enum rsc_role_e next_role
Definition pe_types.h:403
enum rsc_role_e role
Definition pe_types.h:402
unsigned long long flags
Definition pe_types.h:169
void(* apply_location)(pe_resource_t *rsc, pe__location_t *location)
uint32_t(* update_ordered_actions)(pe_action_t *first, pe_action_t *then, const pe_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pe_working_set_t *data_set)
void(* apply_coloc_score)(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
void(* add_utilization)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
void(* create_actions)(pe_resource_t *rsc)
void(* add_colocated_node_scores)(pe_resource_t *rsc, const char *log_id, GHashTable **nodes, const char *attr, float factor, uint32_t flags)
enum pe_action_flags(* action_flags)(pe_action_t *action, const pe_node_t *node)
void(* shutdown_lock)(pe_resource_t *rsc)
void(* this_with_colocations)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
GList *(* colocated_resources)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *colocated_rscs)
void(* with_this_colocations)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
void(* internal_constraints)(pe_resource_t *rsc)
pe_node_t *(* assign)(pe_resource_t *rsc, const pe_node_t *prefer)