pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
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>
17 #include "libpacemaker_private.h"
18 
28 pe_node_t *
30 {
31  pe_node_t *first_assigned_node = NULL;
32  pe_resource_t *first_member = NULL;
33 
34  CRM_ASSERT(rsc != NULL);
35 
36  if (!pcmk_is_set(rsc->flags, pe_rsc_provisional)) {
37  return rsc->allocated_to; // Assignment already done
38  }
39  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
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 
88 static pe_action_t *
89 create_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 
103 void
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()
131 struct 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 
148 static void
149 member_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) {
216  RSC_PROMOTE,
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 
282 void
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 
318 static void
319 colocate_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 
331  if (pe__group_flag_is_set(dependent, pe__group_colocated)) {
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 
364 static void
365 colocate_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 
428 void
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 
457 enum pe_action_flags
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 
541 uint32_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 
582 void
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()
619 GList *
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()
658 void
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()
688 void
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 
764 void
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()
813 void
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 
822  if (!pcmk_is_set(rsc->flags, pe_rsc_provisional)) {
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 
834  if (pcmk_is_set(member->flags, pe_rsc_provisional)
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()
855 void
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 }
GList * pcmk__copy_node_list(const GList *list, bool reset)
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:235
const char * task2text(enum action_tasks task)
Definition: common.c:397
#define pcmk__order_starts(rsc1, rsc2, flags)
#define RSC_STOP
Definition: crm.h:202
G_GNUC_INTERNAL void pcmk__add_this_with_list(GList **list, GList *addition)
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:49
char data[0]
Definition: cpg.c:55
#define INFINITY
Definition: crm.h:99
GList * pcmk__group_colocated_resources(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *colocated_rscs)
GList * rsc_cons
Definition: pe_types.h:389
#define pe__set_action_flags(action, flags_to_set)
Definition: internal.h:89
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 pe__show_node_weights(level, rsc, text, nodes, data_set)
Definition: internal.h:385
void pcmk__group_internal_constraints(pe_resource_t *rsc)
void(* internal_constraints)(pe_resource_t *rsc)
enum rsc_role_e role
Definition: pe_types.h:402
GList * children
Definition: pe_types.h:409
resource_alloc_functions_t * cmds
Definition: pe_types.h:359
#define pcmk__order_stops(rsc1, rsc2, flags)
pe_resource_t * rsc
Definition: pe_types.h:433
enum rsc_role_e next_role
Definition: pe_types.h:403
pe_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pe_node_t *on_node)
Definition: pe_actions.c:1298
#define pcmk__config_err(fmt...)
GHashTable * meta
Definition: pe_types.h:405
void(* with_this_colocations)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
#define pe_rsc_critical
Definition: pe_types.h:290
const pe_resource_t * pe__const_top_resource(const pe_resource_t *rsc, bool include_bundle)
Definition: complex.c:947
GList * rsc_cons_lhs
Definition: pe_types.h:388
enum crm_ais_msg_types type
Definition: cpg.c:48
#define RSC_START
Definition: crm.h:199
void pcmk__group_apply_coloc_score(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
pe_node_t * allocated_to
Definition: pe_types.h:395
const char * action
Definition: pcmk_fence.c:30
void pcmk__group_apply_location(pe_resource_t *rsc, pe__location_t *location)
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 pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:77
pe_node_t *(* assign)(pe_resource_t *rsc, const pe_node_t *prefer)
enum pe_action_flags(* action_flags)(pe_action_t *action, const pe_node_t *node)
#define pe_rsc_provisional
Definition: pe_types.h:282
void pcmk__group_create_actions(pe_resource_t *rsc)
#define XML_RSC_ATTR_PROMOTABLE
Definition: msg_xml.h:245
#define pe_rsc_merging
Definition: pe_types.h:284
GList *(* colocated_resources)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *colocated_rscs)
pe_action_flags
Definition: pe_types.h:316
char * task
Definition: pe_types.h:437
void pcmk__group_add_utilization(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
#define pe__clear_action_flags(action, flags_to_clear)
Definition: internal.h:98
#define crm_trace(fmt, args...)
Definition: logging.h:383
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:121
unsigned long long flags
Definition: pe_types.h:373
#define pe_rsc_promotable
Definition: pe_types.h:280
pe_working_set_t * data_set
void(* create_actions)(pe_resource_t *rsc)
GList * actions
Definition: pe_types.h:391
void pcmk__with_group_colocations(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
G_GNUC_INTERNAL void pcmk__add_with_this_list(GList **list, GList *addition)
char * uuid
Definition: pe_types.h:438
#define pe_rsc_allocating
Definition: pe_types.h:283
enum pe_obj_types variant
Definition: pe_types.h:356
void(* add_utilization)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
#define RSC_DEMOTED
Definition: crm.h:208
void(* this_with_colocations)(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
void pcmk__group_with_colocations(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
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
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
void(* apply_coloc_score)(pe_resource_t *dependent, const pe_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
G_GNUC_INTERNAL void pcmk__apply_location(pe_resource_t *rsc, pe__location_t *constraint)
pe_resource_t * pe__last_group_member(const pe_resource_t *group)
Definition: group.c:37
#define RSC_STARTED
Definition: crm.h:200
G_GNUC_INTERNAL GList * pcmk__colocated_resources(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *colocated_rscs)
#define CRM_ASSERT(expr)
Definition: results.h:42
G_GNUC_INTERNAL void pcmk__add_this_with(GList **list, const pcmk__colocation_t *colocation)
#define RSC_PROMOTE
Definition: crm.h:205
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
GList * running_on
Definition: pe_types.h:398
enum pe_action_flags pcmk__group_action_flags(pe_action_t *action, const pe_node_t *node)
pe_working_set_t * cluster
Definition: pe_types.h:353
#define RSC_STOPPED
Definition: crm.h:203
#define RSC_PROMOTED
Definition: crm.h:206
pe_node_t * pcmk__group_assign(pe_resource_t *rsc, const pe_node_t *prefer)
enum action_tasks get_complex_task(const pe_resource_t *rsc, const char *name)
Definition: pe_actions.c:1265
gboolean crm_is_true(const char *s)
Definition: strings.c:416
void pcmk__group_shutdown_lock(pe_resource_t *rsc)
void(* shutdown_lock)(pe_resource_t *rsc)
void(* apply_location)(pe_resource_t *rsc, pe__location_t *location)
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:50
#define pe__set_order_flags(order_flags, flags_to_set)
Definition: internal.h:141
unsigned long long flags
Definition: pe_types.h:169
bool pe__group_flag_is_set(const pe_resource_t *group, uint32_t flags)
Definition: group.c:57
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)
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)
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)
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
#define pe_flag_show_scores
Definition: pe_types.h:150
#define pe__clear_raw_action_flags(action_flags, action_name, flags_to_clear)
Definition: internal.h:114
#define pe_rsc_managed
Definition: pe_types.h:273
uint64_t flags
Definition: remote.c:215
void(* add_colocated_node_scores)(pe_resource_t *rsc, const char *log_id, GHashTable **nodes, const char *attr, float factor, uint32_t flags)
action_tasks
Definition: common.h:61
pe_resource_t * parent
Definition: pe_types.h:354
#define RSC_DEMOTE
Definition: crm.h:207
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:48
char * id
Definition: pe_types.h:347
GHashTable * allowed_nodes
Definition: pe_types.h:400