pacemaker 2.1.8-2.1.8~rc1
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-2024 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/common/xml.h>
15
16#include <pacemaker-internal.h>
18
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(pcmk__is_group(rsc));
45
47 return rsc->allocated_to; // Assignment already done
48 }
50 pcmk__rsc_debug(rsc, "Assignment dependency loop detected involving %s",
51 rsc->id);
52 return NULL;
53 }
54
55 if (rsc->children == NULL) {
56 // No members to assign
58 return NULL;
59 }
60
62 first_member = (pcmk_resource_t *) rsc->children->data;
63 rsc->role = first_member->role;
64
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 pcmk__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");
83
85 return NULL;
86 }
87 return first_assigned_node;
88}
89
99static pcmk_action_t *
100create_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
106 return op;
107}
108
115void
117{
118 CRM_ASSERT(pcmk__is_group(rsc));
119
120 pcmk__rsc_trace(rsc, "Creating actions for group %s", rsc->id);
121
122 // Create actions for individual group members
123 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
124 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
125
126 member->cmds->create_actions(member);
127 }
128
129 // Create pseudo-actions for group itself to serve as ordering points
130 create_group_pseudo_op(rsc, PCMK_ACTION_START);
131 create_group_pseudo_op(rsc, PCMK_ACTION_RUNNING);
132 create_group_pseudo_op(rsc, PCMK_ACTION_STOP);
133 create_group_pseudo_op(rsc, PCMK_ACTION_STOPPED);
134 if (crm_is_true(g_hash_table_lookup(rsc->meta, PCMK_META_PROMOTABLE))) {
135 create_group_pseudo_op(rsc, PCMK_ACTION_DEMOTE);
136 create_group_pseudo_op(rsc, PCMK_ACTION_DEMOTED);
137 create_group_pseudo_op(rsc, PCMK_ACTION_PROMOTE);
138 create_group_pseudo_op(rsc, PCMK_ACTION_PROMOTED);
139 }
140}
141
142// User data for member_internal_constraints()
143struct member_data {
144 // These could be derived from member but this avoids some function calls
145 bool ordered;
146 bool colocated;
147 bool promotable;
148
149 pcmk_resource_t *last_active;
150 pcmk_resource_t *previous_member;
151};
152
160static void
161member_internal_constraints(gpointer data, gpointer user_data)
162{
164 struct member_data *member_data = (struct member_data *) user_data;
165
166 // For ordering demote vs demote or stop vs stop
167 uint32_t down_flags = pcmk__ar_then_implies_first_graphed;
168
169 // For ordering demote vs demoted or stop vs stopped
170 uint32_t post_down_flags = pcmk__ar_first_implies_then_graphed;
171
172 // Create the individual member's implicit constraints
173 member->cmds->internal_constraints(member);
174
175 if (member_data->previous_member == NULL) {
176 // This is first member
177 if (member_data->ordered) {
179 post_down_flags = pcmk__ar_first_implies_then;
180 }
181
182 } else if (member_data->colocated) {
183 uint32_t flags = pcmk__coloc_none;
184
185 if (pcmk_is_set(member->flags, pcmk_rsc_critical)) {
187 }
188
189 // Colocate this member with the previous one
190 pcmk__new_colocation("#group-members", NULL, PCMK_SCORE_INFINITY,
191 member, member_data->previous_member, NULL, NULL,
192 flags);
193 }
194
195 if (member_data->promotable) {
196 // Demote group -> demote member -> group is demoted
198 member, PCMK_ACTION_DEMOTE, down_flags);
201 post_down_flags);
202
203 // Promote group -> promote member -> group is promoted
210 member, PCMK_ACTION_PROMOTE,
212 }
213
214 // Stop group -> stop member -> group is stopped
215 pcmk__order_stops(member->parent, member, down_flags);
218 post_down_flags);
219
220 // Start group -> start member -> group is started
221 pcmk__order_starts(member->parent, member,
228
229 if (!member_data->ordered) {
230 pcmk__order_starts(member->parent, member,
234 if (member_data->promotable) {
236 member, PCMK_ACTION_PROMOTE,
240 }
241
242 } else if (member_data->previous_member == NULL) {
243 pcmk__order_starts(member->parent, member, pcmk__ar_none);
244 if (member_data->promotable) {
246 member, PCMK_ACTION_PROMOTE,
248 }
249
250 } else {
251 // Order this member relative to the previous one
252
253 pcmk__order_starts(member_data->previous_member, member,
256 pcmk__order_stops(member, member_data->previous_member,
258
259 /* In unusual circumstances (such as adding a new member to the middle
260 * of a group with unmanaged later members), this member may be active
261 * while the previous (new) member is inactive. In this situation, the
262 * usual restart orderings will be irrelevant, so we need to order this
263 * member's stop before the previous member's start.
264 */
265 if ((member->running_on != NULL)
266 && (member_data->previous_member->running_on == NULL)) {
268 member_data->previous_member,
272 }
273
274 if (member_data->promotable) {
275 pcmk__order_resource_actions(member_data->previous_member,
276 PCMK_ACTION_PROMOTE, member,
281 member_data->previous_member,
283 }
284 }
285
286 // Make sure partially active groups shut down in sequence
287 if (member->running_on != NULL) {
288 if (member_data->ordered && (member_data->previous_member != NULL)
289 && (member_data->previous_member->running_on == NULL)
290 && (member_data->last_active != NULL)
291 && (member_data->last_active->running_on != NULL)) {
292 pcmk__order_stops(member, member_data->last_active,
294 }
295 member_data->last_active = member;
296 }
297
298 member_data->previous_member = member;
299}
300
307void
309{
310 struct member_data member_data = { false, };
311 const pcmk_resource_t *top = NULL;
312
313 CRM_ASSERT(pcmk__is_group(rsc));
314
315 /* Order group pseudo-actions relative to each other for restarting:
316 * stop group -> group is stopped -> start group -> group is started
317 */
327
328 top = pe__const_top_resource(rsc, false);
329
330 member_data.ordered = pe__group_flag_is_set(rsc, pcmk__group_ordered);
331 member_data.colocated = pe__group_flag_is_set(rsc, pcmk__group_colocated);
332 member_data.promotable = pcmk_is_set(top->flags, pcmk_rsc_promotable);
333 g_list_foreach(rsc->children, member_internal_constraints, &member_data);
334}
335
348static void
349colocate_group_with(pcmk_resource_t *dependent, const pcmk_resource_t *primary,
350 const pcmk__colocation_t *colocation)
351{
352 pcmk_resource_t *member = NULL;
353
354 if (dependent->children == NULL) {
355 return;
356 }
357
358 pcmk__rsc_trace(primary, "Processing %s (group %s with %s) for dependent",
359 colocation->id, dependent->id, primary->id);
360
362 // Colocate first member (internal colocations will handle the rest)
363 member = (pcmk_resource_t *) dependent->children->data;
364 member->cmds->apply_coloc_score(member, primary, colocation, true);
365 return;
366 }
367
368 if (colocation->score >= PCMK_SCORE_INFINITY) {
369 pcmk__config_err("%s: Cannot perform mandatory colocation between "
370 "non-colocated group and %s",
371 dependent->id, primary->id);
372 return;
373 }
374
375 // Colocate each member individually
376 for (GList *iter = dependent->children; iter != NULL; iter = iter->next) {
377 member = (pcmk_resource_t *) iter->data;
378 member->cmds->apply_coloc_score(member, primary, colocation, true);
379 }
380}
381
394static void
395colocate_with_group(pcmk_resource_t *dependent, const pcmk_resource_t *primary,
396 const pcmk__colocation_t *colocation)
397{
398 const pcmk_resource_t *member = NULL;
399
400 pcmk__rsc_trace(primary,
401 "Processing colocation %s (%s with group %s) for primary",
402 colocation->id, dependent->id, primary->id);
403
404 if (pcmk_is_set(primary->flags, pcmk_rsc_unassigned)) {
405 return;
406 }
407
409
410 if (colocation->score >= PCMK_SCORE_INFINITY) {
411 /* For mandatory colocations, the entire group must be assignable
412 * (and in the specified role if any), so apply the colocation based
413 * on the last member.
414 */
415 member = pe__last_group_member(primary);
416 } else if (primary->children != NULL) {
417 /* For optional colocations, whether the group is partially or fully
418 * up doesn't matter, so apply the colocation based on the first
419 * member.
420 */
421 member = (pcmk_resource_t *) primary->children->data;
422 }
423 if (member == NULL) {
424 return; // Nothing to colocate with
425 }
426
427 member->cmds->apply_coloc_score(dependent, member, colocation, false);
428 return;
429 }
430
431 if (colocation->score >= PCMK_SCORE_INFINITY) {
432 pcmk__config_err("%s: Cannot perform mandatory colocation with"
433 " non-colocated group %s",
434 dependent->id, primary->id);
435 return;
436 }
437
438 // Colocate dependent with each member individually
439 for (const GList *iter = primary->children; iter != NULL;
440 iter = iter->next) {
441 member = iter->data;
442 member->cmds->apply_coloc_score(dependent, member, colocation, false);
443 }
444}
445
459void
461 const pcmk_resource_t *primary,
462 const pcmk__colocation_t *colocation,
463 bool for_dependent)
464{
465 CRM_ASSERT((dependent != NULL) && (primary != NULL)
466 && (colocation != NULL));
467
468 if (for_dependent) {
469 colocate_group_with(dependent, primary, colocation);
470
471 } else {
472 // Method should only be called for primitive dependents
473 CRM_ASSERT(pcmk__is_primitive(dependent));
474
475 colocate_with_group(dependent, primary, colocation);
476 }
477}
478
488uint32_t
490{
491 // Default flags for a group action
492 uint32_t flags = pcmk_action_optional
495
496 CRM_ASSERT(action != NULL);
497
498 // Update flags considering each member's own flags for same action
499 for (GList *iter = action->rsc->children; iter != NULL; iter = iter->next) {
500 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
501
502 // Check whether member has the same action
503 enum action_tasks task = get_complex_task(member, action->task);
504 const char *task_s = pcmk_action_text(task);
505 pcmk_action_t *member_action = find_first_action(member->actions, NULL,
506 task_s, node);
507
508 if (member_action != NULL) {
509 uint32_t member_flags = member->cmds->action_flags(member_action,
510 node);
511
512 // Group action is mandatory if any member action is
514 && !pcmk_is_set(member_flags, pcmk_action_optional)) {
515 pcmk__rsc_trace(action->rsc, "%s is mandatory because %s is",
516 action->uuid, member_action->uuid);
517 pcmk__clear_raw_action_flags(flags, "group action",
520 }
521
522 // Group action is unrunnable if any member action is
523 if (!pcmk__str_eq(task_s, action->task, pcmk__str_none)
525 && !pcmk_is_set(member_flags, pcmk_action_runnable)) {
526
527 pcmk__rsc_trace(action->rsc, "%s is unrunnable because %s is",
528 action->uuid, member_action->uuid);
529 pcmk__clear_raw_action_flags(flags, "group action",
532 }
533
534 /* Group (pseudo-)actions other than stop or demote are unrunnable
535 * unless every member will do it.
536 */
537 } else if ((task != pcmk_action_stop) && (task != pcmk_action_demote)) {
539 "%s is not runnable because %s will not %s",
540 action->uuid, member->id, task_s);
541 pcmk__clear_raw_action_flags(flags, "group action",
543 }
544 }
545
546 return flags;
547}
548
571uint32_t
573 const pcmk_node_t *node, uint32_t flags,
574 uint32_t filter, uint32_t type,
576{
577 uint32_t changed = pcmk__updated_none;
578
579 // Group method can be called only on behalf of "then" action
580 CRM_ASSERT((first != NULL) && (then != NULL) && (then->rsc != NULL)
581 && (scheduler != NULL));
582
583 // Update the actions for the group itself
584 changed |= pcmk__update_ordered_actions(first, then, node, flags, filter,
585 type, scheduler);
586
587 // Update the actions for each group member
588 for (GList *iter = then->rsc->children; iter != NULL; iter = iter->next) {
589 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
590
591 pcmk_action_t *member_action = find_first_action(member->actions, NULL,
592 then->task, node);
593
594 if (member_action != NULL) {
595 changed |= member->cmds->update_ordered_actions(first,
596 member_action, node,
597 flags, filter, type,
598 scheduler);
599 }
600 }
601 return changed;
602}
603
611void
613{
614 GList *node_list_orig = NULL;
615 GList *node_list_copy = NULL;
616 bool reset_scores = true;
617
618 CRM_ASSERT(pcmk__is_group(rsc) && (location != NULL));
619
620 node_list_orig = location->nodes;
621 node_list_copy = pcmk__copy_node_list(node_list_orig, true);
622 reset_scores = pe__group_flag_is_set(rsc, pcmk__group_colocated);
623
624 // Apply the constraint for the group itself (updates node scores)
625 pcmk__apply_location(rsc, location);
626
627 // Apply the constraint for each member
628 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
629 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
630
631 member->cmds->apply_location(member, location);
632
633 if (reset_scores) {
634 /* The first member of colocated groups needs to use the original
635 * node scores, but subsequent members should work on a copy, since
636 * the first member's scores already incorporate theirs.
637 */
638 reset_scores = false;
639 location->nodes = node_list_copy;
640 }
641 }
642
643 location->nodes = node_list_orig;
644 g_list_free_full(node_list_copy, free);
645}
646
647// Group implementation of pcmk_assignment_methods_t:colocated_resources()
648GList *
650 const pcmk_resource_t *orig_rsc,
651 GList *colocated_rscs)
652{
653 const pcmk_resource_t *member = NULL;
654
655 CRM_ASSERT(pcmk__is_group(rsc));
656
657 if (orig_rsc == NULL) {
658 orig_rsc = rsc;
659 }
660
662 || pcmk__is_clone(rsc->parent)) {
663 /* This group has colocated members and/or is cloned -- either way,
664 * add every child's colocated resources to the list. The first and last
665 * members will include the group's own colocations.
666 */
667 colocated_rscs = g_list_prepend(colocated_rscs, (gpointer) rsc);
668 for (const GList *iter = rsc->children;
669 iter != NULL; iter = iter->next) {
670
671 member = (const pcmk_resource_t *) iter->data;
672 colocated_rscs = member->cmds->colocated_resources(member, orig_rsc,
673 colocated_rscs);
674 }
675
676 } else if (rsc->children != NULL) {
677 /* This group's members are not colocated, and the group is not cloned,
678 * so just add the group's own colocations to the list.
679 */
680 colocated_rscs = pcmk__colocated_resources(rsc, orig_rsc,
681 colocated_rscs);
682 }
683
684 return colocated_rscs;
685}
686
687// Group implementation of pcmk_assignment_methods_t:with_this_colocations()
688void
690 const pcmk_resource_t *orig_rsc, GList **list)
691
692{
693 CRM_ASSERT((orig_rsc != NULL) && (list != NULL) && pcmk__is_group(rsc));
694
695 // Ignore empty groups
696 if (rsc->children == NULL) {
697 return;
698 }
699
700 /* "With this" colocations are needed only for the group itself and for its
701 * last member. (Previous members will chain via the group internal
702 * colocations.)
703 */
704 if ((orig_rsc != rsc) && (orig_rsc != pe__last_group_member(rsc))) {
705 return;
706 }
707
708 pcmk__rsc_trace(rsc, "Adding 'with %s' colocations to list for %s",
709 rsc->id, orig_rsc->id);
710
711 // Add the group's own colocations
712 pcmk__add_with_this_list(list, rsc->rsc_cons_lhs, orig_rsc);
713
714 // If cloned, add any relevant colocations with the clone
715 if (rsc->parent != NULL) {
716 rsc->parent->cmds->with_this_colocations(rsc->parent, orig_rsc,
717 list);
718 }
719
721 // @COMPAT Non-colocated groups are deprecated
722 return;
723 }
724
725 // Add explicit colocations with the group's (other) children
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// Group implementation of pcmk_assignment_methods_t:this_with_colocations()
736void
738 const pcmk_resource_t *orig_rsc, GList **list)
739{
740 const pcmk_resource_t *member = NULL;
741
742 CRM_ASSERT((orig_rsc != NULL) && (list != NULL) && pcmk__is_group(rsc));
743
744 // Ignore empty groups
745 if (rsc->children == NULL) {
746 return;
747 }
748
749 /* "This with" colocations are normally needed only for the group itself and
750 * for its first member.
751 */
752 if ((rsc == orig_rsc)
753 || (orig_rsc == (const pcmk_resource_t *) rsc->children->data)) {
754 pcmk__rsc_trace(rsc, "Adding '%s with' colocations to list for %s",
755 rsc->id, orig_rsc->id);
756
757 // Add the group's own colocations
758 pcmk__add_this_with_list(list, rsc->rsc_cons, orig_rsc);
759
760 // If cloned, add any relevant colocations involving the clone
761 if (rsc->parent != NULL) {
762 rsc->parent->cmds->this_with_colocations(rsc->parent, orig_rsc,
763 list);
764 }
765
767 // @COMPAT Non-colocated groups are deprecated
768 return;
769 }
770
771 // Add explicit colocations involving the group's (other) children
772 for (const GList *iter = rsc->children;
773 iter != NULL; iter = iter->next) {
774 member = iter->data;
775 if (member != orig_rsc) {
776 member->cmds->this_with_colocations(member, orig_rsc, list);
777 }
778 }
779 return;
780 }
781
782 /* Later group members honor the group's colocations indirectly, due to the
783 * internal group colocations that chain everything from the first member.
784 * However, if an earlier group member is unmanaged, this chaining will not
785 * happen, so the group's mandatory colocations must be explicitly added.
786 */
787 for (const GList *iter = rsc->children; iter != NULL; iter = iter->next) {
788 member = iter->data;
789 if (orig_rsc == member) {
790 break; // We've seen all earlier members, and none are unmanaged
791 }
792
793 if (!pcmk_is_set(member->flags, pcmk_rsc_managed)) {
794 crm_trace("Adding mandatory '%s with' colocations to list for "
795 "member %s because earlier member %s is unmanaged",
796 rsc->id, orig_rsc->id, member->id);
797 for (const GList *cons_iter = rsc->rsc_cons; cons_iter != NULL;
798 cons_iter = cons_iter->next) {
799 const pcmk__colocation_t *colocation = NULL;
800
801 colocation = (const pcmk__colocation_t *) cons_iter->data;
802 if (colocation->score == PCMK_SCORE_INFINITY) {
803 pcmk__add_this_with(list, colocation, orig_rsc);
804 }
805 }
806 // @TODO Add mandatory (or all?) clone constraints if cloned
807 break;
808 }
809 }
810}
811
842void
844 const pcmk_resource_t *target_rsc,
845 const char *log_id, GHashTable **nodes,
846 const pcmk__colocation_t *colocation,
847 float factor, uint32_t flags)
848{
849 pcmk_resource_t *member = NULL;
850
851 CRM_ASSERT(pcmk__is_group(source_rsc) && (nodes != NULL)
852 && ((colocation != NULL)
853 || ((target_rsc == NULL) && (*nodes == NULL))));
854
855 if (log_id == NULL) {
856 log_id = source_rsc->id;
857 }
858
859 // Avoid infinite recursion
860 if (pcmk_is_set(source_rsc->flags, pcmk_rsc_updating_nodes)) {
861 pcmk__rsc_info(source_rsc, "%s: Breaking dependency loop at %s",
862 log_id, source_rsc->id);
863 return;
864 }
866
867 // Ignore empty groups (only possible with schema validation disabled)
868 if (source_rsc->children == NULL) {
869 return;
870 }
871
872 /* Refer the operation to the first or last member as appropriate.
873 *
874 * cmp_resources() is the only caller that passes a NULL nodes table,
875 * and is also the only caller using pcmk__coloc_select_this_with.
876 * For "this with" colocations, the last member will recursively incorporate
877 * all the other members' "this with" colocations via the internal group
878 * colocations (and via the first member, the group's own colocations).
879 *
880 * For "with this" colocations, the first member works similarly.
881 */
882 if (*nodes == NULL) {
883 member = pe__last_group_member(source_rsc);
884 } else {
885 member = source_rsc->children->data;
886 }
887 pcmk__rsc_trace(source_rsc, "%s: Merging scores from group %s using member %s "
888 "(at %.6f)", log_id, source_rsc->id, member->id, factor);
889 member->cmds->add_colocated_node_scores(member, target_rsc, log_id, nodes,
890 colocation, factor, flags);
892}
893
894// Group implementation of pcmk_assignment_methods_t:add_utilization()
895void
897 const pcmk_resource_t *orig_rsc, GList *all_rscs,
898 GHashTable *utilization)
899{
900 pcmk_resource_t *member = NULL;
901
902 CRM_ASSERT((orig_rsc != NULL) && (utilization != NULL)
903 && pcmk__is_group(rsc));
904
906 return;
907 }
908
909 pcmk__rsc_trace(orig_rsc, "%s: Adding group %s as colocated utilization",
910 orig_rsc->id, rsc->id);
912 || pcmk__is_clone(rsc->parent)) {
913 // Every group member will be on same node, so sum all members
914 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
915 member = (pcmk_resource_t *) iter->data;
916
918 && (g_list_find(all_rscs, member) == NULL)) {
919 member->cmds->add_utilization(member, orig_rsc, all_rscs,
920 utilization);
921 }
922 }
923
924 } else if (rsc->children != NULL) {
925 // Just add first member's utilization
926 member = (pcmk_resource_t *) rsc->children->data;
927 if ((member != NULL)
929 && (g_list_find(all_rscs, member) == NULL)) {
930
931 member->cmds->add_utilization(member, orig_rsc, all_rscs,
932 utilization);
933 }
934 }
935}
936
937void
939{
940 CRM_ASSERT(pcmk__is_group(rsc));
941
942 for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
943 pcmk_resource_t *member = (pcmk_resource_t *) iter->data;
944
945 member->cmds->shutdown_lock(member);
946 }
947}
@ pcmk__ar_first_implies_then
@ pcmk__ar_then_implies_first
@ pcmk__ar_intermediate_stop
@ pcmk__ar_then_implies_first_graphed
If 'then' is required, 'first' must be added to the transition graph.
@ pcmk__ar_none
No relation (compare with equality rather than bit set)
@ pcmk__ar_first_implies_then_graphed
If 'first' is required and runnable, 'then' must be in graph.
@ pcmk__ar_unrunnable_first_blocks
'then' is runnable (and migratable) only if 'first' is runnable
@ pcmk__ar_ordered
Actions are ordered (optionally, if no other flags are set)
#define pcmk__set_relation_flags(ar_flags, flags_to_set)
#define PCMK_ACTION_PROMOTED
Definition actions.h:67
#define PCMK_ACTION_STOP
Definition actions.h:75
#define PCMK_ACTION_RUNNING
Definition actions.h:71
#define PCMK_ACTION_PROMOTE
Definition actions.h:66
#define PCMK_ACTION_START
Definition actions.h:72
@ pcmk_action_runnable
Definition actions.h:207
@ pcmk_action_pseudo
Definition actions.h:204
@ pcmk_action_optional
Definition actions.h:210
action_tasks
Definition actions.h:83
@ pcmk_action_demote
Definition actions.h:101
@ pcmk_action_stop
Definition actions.h:89
#define PCMK_ACTION_STOPPED
Definition actions.h:76
const char * pcmk_action_text(enum action_tasks action)
Get string equivalent of an action type.
Definition actions.c:37
#define PCMK_ACTION_DEMOTED
Definition actions.h:50
#define PCMK_ACTION_DEMOTE
Definition actions.h:49
#define pcmk__clear_raw_action_flags(action_flags, action_name, to_clear)
#define pcmk__set_action_flags(action, flags_to_set)
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
Definition actions.c:196
#define pcmk__clear_action_flags(action, flags_to_clear)
uint64_t flags
Definition remote.c:3
gboolean crm_is_true(const char *s)
Definition strings.c:488
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:100
enum crm_ais_msg_types type
Definition cpg.c:3
char data[0]
Definition cpg.c:10
@ pcmk__group_colocated
@ pcmk__group_ordered
G_GNUC_INTERNAL void pcmk__add_this_with_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
#define pcmk__order_starts(rsc1, rsc2, flags)
G_GNUC_INTERNAL void pcmk__new_colocation(const char *id, const char *node_attr, int score, pcmk_resource_t *dependent, pcmk_resource_t *primary, const char *dependent_role, const char *primary_role, uint32_t flags)
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
G_GNUC_INTERNAL uint32_t pcmk__update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
@ pcmk__coloc_none
@ pcmk__coloc_influence
G_GNUC_INTERNAL void pcmk__add_this_with(GList **list, const pcmk__colocation_t *colocation, const pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__add_with_this_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
G_GNUC_INTERNAL GList * pcmk__colocated_resources(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *colocated_rscs)
@ pcmk__updated_none
#define pcmk__order_stops(rsc1, rsc2, flags)
G_GNUC_INTERNAL void pcmk__apply_location(pcmk_resource_t *rsc, pcmk__location_t *constraint)
#define crm_trace(fmt, args...)
Definition logging.h:402
#define pcmk__config_err(fmt...)
pcmk_scheduler_t * scheduler
#define PCMK_META_PROMOTABLE
Definition options.h:101
const char * action
Definition pcmk_fence.c:30
void pcmk__group_add_colocated_node_scores(pcmk_resource_t *source_rsc, const pcmk_resource_t *target_rsc, const char *log_id, GHashTable **nodes, const pcmk__colocation_t *colocation, float factor, uint32_t flags)
void pcmk__with_group_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
void pcmk__group_internal_constraints(pcmk_resource_t *rsc)
pcmk_node_t * pcmk__group_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
void pcmk__group_apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
GList * pcmk__group_colocated_resources(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *colocated_rscs)
void pcmk__group_shutdown_lock(pcmk_resource_t *rsc)
uint32_t pcmk__group_update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
void pcmk__group_add_utilization(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
void pcmk__group_with_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
void pcmk__group_create_actions(pcmk_resource_t *rsc)
uint32_t pcmk__group_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
void pcmk__group_apply_coloc_score(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
GList * pcmk__copy_node_list(const GList *list, bool reset)
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
Definition complex.c:1032
pcmk_resource_t * pe__last_group_member(const pcmk_resource_t *group)
Definition group.c:37
#define pe__show_node_scores(level, rsc, text, nodes, scheduler)
Definition internal.h:176
pcmk_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pcmk_node_t *on_node)
void pe__set_next_role(pcmk_resource_t *rsc, enum rsc_role_e role, const char *why)
Definition complex.c:1253
pcmk_action_t * custom_action(pcmk_resource_t *rsc, char *key, const char *task, const pcmk_node_t *on_node, gboolean optional, pcmk_scheduler_t *scheduler)
Create or update an action object.
enum action_tasks get_complex_task(const pcmk_resource_t *rsc, const char *name)
bool pe__group_flag_is_set(const pcmk_resource_t *group, uint32_t flags)
Definition group.c:57
@ pcmk_rsc_promotable
Definition resources.h:106
@ pcmk_rsc_unassigned
Definition resources.h:109
@ pcmk_rsc_assigning
Definition resources.h:112
@ pcmk_rsc_critical
Definition resources.h:130
@ pcmk_rsc_updating_nodes
Definition resources.h:115
@ pcmk_rsc_managed
Definition resources.h:88
#define CRM_ASSERT(expr)
Definition results.h:42
#define pcmk__set_rsc_flags(resource, flags_to_set)
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
@ pcmk_sched_output_scores
Definition scheduler.h:173
#define pcmk__rsc_info(rsc, fmt, args...)
#define pcmk__rsc_trace(rsc, fmt, args...)
#define pcmk__rsc_debug(rsc, fmt, args...)
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition scores.h:24
@ pcmk__str_none
Location constraint object.
char * uuid
Definition actions.h:344
char * task
Definition actions.h:343
pcmk_resource_t * rsc
Definition actions.h:340
pcmk_assignment_methods_t * cmds
Definition resources.h:413
GList * running_on
Definition resources.h:456
GList * actions
Definition resources.h:444
GHashTable * meta
Definition resources.h:467
GList * rsc_cons
Definition resources.h:442
GList * rsc_cons_lhs
Definition resources.h:441
GList * children
Definition resources.h:471
pcmk_scheduler_t * cluster
Definition resources.h:408
pcmk_node_t * allocated_to
Definition resources.h:447
GHashTable * allowed_nodes
Definition resources.h:462
unsigned long long flags
Definition resources.h:428
enum rsc_role_e next_role
Definition resources.h:465
enum rsc_role_e role
Definition resources.h:464
pcmk_resource_t * parent
Definition resources.h:409
unsigned long long flags
Definition scheduler.h:211
void(* create_actions)(pcmk_resource_t *rsc)
void(* add_utilization)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
void(* shutdown_lock)(pcmk_resource_t *rsc)
void(* this_with_colocations)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
GList *(* colocated_resources)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *colocated_rscs)
uint32_t(* action_flags)(pcmk_action_t *action, const pcmk_node_t *node)
void(* with_this_colocations)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
void(* internal_constraints)(pcmk_resource_t *rsc)
pcmk_node_t *(* assign)(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
void(* apply_coloc_score)(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
void(* add_colocated_node_scores)(pcmk_resource_t *source_rsc, const pcmk_resource_t *target_rsc, const char *log_id, GHashTable **nodes, const pcmk__colocation_t *colocation, float factor, uint32_t flags)
uint32_t(* update_ordered_actions)(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
void(* apply_location)(pcmk_resource_t *rsc, pcmk__location_t *location)
Wrappers for and extensions to libxml2.