pacemaker  2.1.5-b7adf64e51
Scalable High-Availability cluster resource manager
pcmk_sched_group.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2022 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 
25 static void
26 expand_group_colocations(pe_resource_t *rsc)
27 {
28  pe_resource_t *member = NULL;
29  bool any_unmanaged = false;
30  GList *item = NULL;
31 
32  if (rsc->children == NULL) {
33  return;
34  }
35 
36  // Treat "group with R" colocations as "first member with R"
37  member = (pe_resource_t *) rsc->children->data;
38  for (item = rsc->rsc_cons; item != NULL; item = item->next) {
39  pcmk__add_this_with(member, (pcmk__colocation_t *) (item->data));
40  }
41 
42 
43  /* The above works for the whole group because each group member is
44  * colocated with the previous one.
45  *
46  * However, there is a special case when a group has a mandatory colocation
47  * with a resource that can't start. In that case,
48  * pcmk__block_colocation_dependents() will ensure that dependent resources
49  * in mandatory colocations (i.e. the first member for groups) can't start
50  * either. But if any group member is unmanaged and already started, the
51  * internal group colocations are no longer sufficient to make that apply to
52  * later members.
53  *
54  * To handle that case, add mandatory colocations to each member after the
55  * first.
56  */
57  any_unmanaged = !pcmk_is_set(member->flags, pe_rsc_managed);
58  for (item = rsc->children->next; item != NULL; item = item->next) {
59  member = item->data;
60  if (any_unmanaged) {
61  for (GList *cons_iter = rsc->rsc_cons; cons_iter != NULL;
62  cons_iter = cons_iter->next) {
63 
64  pcmk__colocation_t *constraint = (pcmk__colocation_t *) cons_iter->data;
65 
66  if (constraint->score == INFINITY) {
67  pcmk__add_this_with(member, constraint);
68  }
69  }
70  } else if (!pcmk_is_set(member->flags, pe_rsc_managed)) {
71  any_unmanaged = true;
72  }
73  }
74 
75  g_list_free(rsc->rsc_cons);
76  rsc->rsc_cons = NULL;
77 
78  // Treat "R with group" colocations as "R with last member"
79  member = pe__last_group_member(rsc);
80  for (item = rsc->rsc_cons_lhs; item != NULL; item = item->next) {
81  pcmk__add_with_this(member, (pcmk__colocation_t *) (item->data));
82  }
83  g_list_free(rsc->rsc_cons_lhs);
84  rsc->rsc_cons_lhs = NULL;
85 }
86 
96 pe_node_t *
98 {
99  pe_node_t *first_assigned_node = NULL;
100  pe_resource_t *first_member = NULL;
101 
102  CRM_ASSERT(rsc != NULL);
103 
104  if (!pcmk_is_set(rsc->flags, pe_rsc_provisional)) {
105  return rsc->allocated_to; // Assignment already done
106  }
107  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
108  pe_rsc_debug(rsc, "Assignment dependency loop detected involving %s",
109  rsc->id);
110  return NULL;
111  }
112 
113  if (rsc->children == NULL) {
114  // No members to assign
116  return NULL;
117  }
118 
120  first_member = (pe_resource_t *) rsc->children->data;
121  rsc->role = first_member->role;
122 
123  expand_group_colocations(rsc);
124 
126  rsc, __func__, rsc->allowed_nodes, rsc->cluster);
127 
128  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
129  pe_resource_t *member = (pe_resource_t *) iter->data;
130  pe_node_t *node = NULL;
131 
132  pe_rsc_trace(rsc, "Assigning group %s member %s",
133  rsc->id, member->id);
134  node = member->cmds->assign(member, prefer);
135  if (first_assigned_node == NULL) {
136  first_assigned_node = node;
137  }
138  }
139 
140  pe__set_next_role(rsc, first_member->next_role, "first group member");
142 
144  return NULL;
145  }
146  return first_assigned_node;
147 }
148 
158 static pe_action_t *
159 create_group_pseudo_op(pe_resource_t *group, const char *action)
160 {
161  pe_action_t *op = custom_action(group, pcmk__op_key(group->id, action, 0),
162  action, NULL, TRUE, TRUE, group->cluster);
164  return op;
165 }
166 
173 void
175 {
176  CRM_ASSERT(rsc != NULL);
177 
178  pe_rsc_trace(rsc, "Creating actions for group %s", rsc->id);
179 
180  // Create actions for individual group members
181  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
182  pe_resource_t *member = (pe_resource_t *) iter->data;
183 
184  member->cmds->create_actions(member);
185  }
186 
187  // Create pseudo-actions for group itself to serve as ordering points
188  create_group_pseudo_op(rsc, RSC_START);
189  create_group_pseudo_op(rsc, RSC_STARTED);
190  create_group_pseudo_op(rsc, RSC_STOP);
191  create_group_pseudo_op(rsc, RSC_STOPPED);
192  if (crm_is_true(g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_PROMOTABLE))) {
193  create_group_pseudo_op(rsc, RSC_DEMOTE);
194  create_group_pseudo_op(rsc, RSC_DEMOTED);
195  create_group_pseudo_op(rsc, RSC_PROMOTE);
196  create_group_pseudo_op(rsc, RSC_PROMOTED);
197  }
198 }
199 
200 // User data for member_internal_constraints()
201 struct member_data {
202  // These could be derived from member but this avoids some function calls
203  bool ordered;
204  bool colocated;
205  bool promotable;
206 
207  pe_resource_t *last_active;
208  pe_resource_t *previous_member;
209 };
210 
218 static void
219 member_internal_constraints(gpointer data, gpointer user_data)
220 {
221  pe_resource_t *member = (pe_resource_t *) data;
222  struct member_data *member_data = (struct member_data *) user_data;
223 
224  // For ordering demote vs demote or stop vs stop
225  uint32_t down_flags = pe_order_implies_first_printed;
226 
227  // For ordering demote vs demoted or stop vs stopped
228  uint32_t post_down_flags = pe_order_implies_then_printed;
229 
230  // Create the individual member's implicit constraints
231  member->cmds->internal_constraints(member);
232 
233  if (member_data->previous_member == NULL) {
234  // This is first member
235  if (member_data->ordered) {
237  post_down_flags = pe_order_implies_then;
238  }
239 
240  } else if (member_data->colocated) {
241  // Colocate this member with the previous one
242  pcmk__new_colocation("group:internal_colocation", NULL, INFINITY,
243  member, member_data->previous_member, NULL, NULL,
245  member->cluster);
246  }
247 
248  if (member_data->promotable) {
249  // Demote group -> demote member -> group is demoted
251  member, RSC_DEMOTE, down_flags);
253  member->parent, RSC_DEMOTED,
254  post_down_flags);
255 
256  // Promote group -> promote member -> group is promoted
258  member->parent, RSC_PROMOTED,
263  member, RSC_PROMOTE,
265  }
266 
267  // Stop group -> stop member -> group is stopped
268  pcmk__order_stops(member->parent, member, down_flags);
270  post_down_flags);
271 
272  // Start group -> start member -> group is started
278 
279  if (!member_data->ordered) {
280  pcmk__order_starts(member->parent, member,
284  if (member_data->promotable) {
286  RSC_PROMOTE,
290  }
291 
292  } else if (member_data->previous_member == NULL) {
293  pcmk__order_starts(member->parent, member, pe_order_none);
294  if (member_data->promotable) {
297  }
298 
299  } else {
300  // Order this member relative to the previous one
301  pcmk__order_starts(member_data->previous_member, member,
303  pcmk__order_stops(member, member_data->previous_member,
305  if (member_data->promotable) {
306  pcmk__order_resource_actions(member_data->previous_member,
307  RSC_PROMOTE, member, RSC_PROMOTE,
311  member_data->previous_member,
313  }
314  }
315 
316  // Make sure partially active groups shut down in sequence
317  if (member->running_on != NULL) {
318  if (member_data->ordered && (member_data->previous_member != NULL)
319  && (member_data->previous_member->running_on == NULL)
320  && (member_data->last_active != NULL)
321  && (member_data->last_active->running_on != NULL)) {
322  pcmk__order_stops(member, member_data->last_active, pe_order_optional);
323  }
324  member_data->last_active = member;
325  }
326 
327  member_data->previous_member = member;
328 }
329 
336 void
338 {
339  struct member_data member_data = { false, };
340 
341  CRM_ASSERT(rsc != NULL);
342 
343  /* Order group pseudo-actions relative to each other for restarting:
344  * stop group -> group is stopped -> start group -> group is started
345  */
352 
353  member_data.ordered = pe__group_flag_is_set(rsc, pe__group_ordered);
354  member_data.colocated = pe__group_flag_is_set(rsc, pe__group_colocated);
355  member_data.promotable = pcmk_is_set(uber_parent(rsc)->flags, pe_rsc_promotable);
356  g_list_foreach(rsc->children, member_internal_constraints, &member_data);
357 }
358 
371 static void
372 colocate_group_with(pe_resource_t *dependent, const pe_resource_t *primary,
373  const pcmk__colocation_t *colocation)
374 {
375  pe_resource_t *member = NULL;
376 
377  if (dependent->children == NULL) {
378  return;
379  }
380 
381  pe_rsc_trace(primary, "Processing %s (group %s with %s) for dependent",
382  colocation->id, dependent->id, primary->id);
383 
384  if (pe__group_flag_is_set(dependent, pe__group_colocated)) {
385  // Colocate first member (internal colocations will handle the rest)
386  member = (pe_resource_t *) dependent->children->data;
387  member->cmds->apply_coloc_score(member, primary, colocation, true);
388  return;
389  }
390 
391  if (colocation->score >= INFINITY) {
392  pcmk__config_err("%s: Cannot perform mandatory colocation between "
393  "non-colocated group and %s",
394  dependent->id, primary->id);
395  return;
396  }
397 
398  // Colocate each member individually
399  for (GList *iter = dependent->children; iter != NULL; iter = iter->next) {
400  member = (pe_resource_t *) iter->data;
401  member->cmds->apply_coloc_score(member, primary, colocation, true);
402  }
403 }
404 
417 static void
418 colocate_with_group(pe_resource_t *dependent, const pe_resource_t *primary,
419  const pcmk__colocation_t *colocation)
420 {
421  pe_resource_t *member = NULL;
422 
423  pe_rsc_trace(primary,
424  "Processing colocation %s (%s with group %s) for primary",
425  colocation->id, dependent->id, primary->id);
426 
427  if (pcmk_is_set(primary->flags, pe_rsc_provisional)) {
428  return;
429  }
430 
432 
433  if (colocation->score >= INFINITY) {
434  /* For mandatory colocations, the entire group must be assignable
435  * (and in the specified role if any), so apply the colocation based
436  * on the last member.
437  */
438  member = pe__last_group_member(primary);
439  } else if (primary->children != NULL) {
440  /* For optional colocations, whether the group is partially or fully
441  * up doesn't matter, so apply the colocation based on the first
442  * member.
443  */
444  member = (pe_resource_t *) primary->children->data;
445  }
446  if (member == NULL) {
447  return; // Nothing to colocate with
448  }
449 
450  member->cmds->apply_coloc_score(dependent, member, colocation, false);
451  return;
452  }
453 
454  if (colocation->score >= INFINITY) {
455  pcmk__config_err("%s: Cannot perform mandatory colocation with"
456  " non-colocated group %s",
457  dependent->id, primary->id);
458  return;
459  }
460 
461  // Colocate dependent with each member individually
462  for (GList *iter = primary->children; iter != NULL; iter = iter->next) {
463  member = (pe_resource_t *) iter->data;
464  member->cmds->apply_coloc_score(dependent, member, colocation, false);
465  }
466 }
467 
481 void
483  const pe_resource_t *primary,
484  const pcmk__colocation_t *colocation,
485  bool for_dependent)
486 {
487  CRM_ASSERT((dependent != NULL) && (primary != NULL)
488  && (colocation != NULL));
489 
490  if (for_dependent) {
491  colocate_group_with(dependent, primary, colocation);
492 
493  } else {
494  // Method should only be called for primitive dependents
495  CRM_ASSERT(dependent->variant == pe_native);
496 
497  colocate_with_group(dependent, primary, colocation);
498  }
499 }
500 
510 enum pe_action_flags
512 {
513  // Default flags for a group action
517 
518  CRM_ASSERT(action != NULL);
519 
520  // Update flags considering each member's own flags for same action
521  for (GList *iter = action->rsc->children; iter != NULL; iter = iter->next) {
522  pe_resource_t *member = (pe_resource_t *) iter->data;
523 
524  // Check whether member has the same action
525  enum action_tasks task = get_complex_task(member, action->task, TRUE);
526  const char *task_s = task2text(task);
527  pe_action_t *member_action = find_first_action(member->actions, NULL,
528  task_s, node);
529 
530  if (member_action != NULL) {
531  enum pe_action_flags member_flags;
532 
533  member_flags = member->cmds->action_flags(member_action, node);
534 
535  // Group action is mandatory if any member action is
537  && !pcmk_is_set(member_flags, pe_action_optional)) {
538  pe_rsc_trace(action->rsc, "%s is mandatory because %s is",
539  action->uuid, member_action->uuid);
540  pe__clear_raw_action_flags(flags, "group action",
543  }
544 
545  // Group action is unrunnable if any member action is
546  if (!pcmk__str_eq(task_s, action->task, pcmk__str_none)
548  && !pcmk_is_set(member_flags, pe_action_runnable)) {
549 
550  pe_rsc_trace(action->rsc, "%s is unrunnable because %s is",
551  action->uuid, member_action->uuid);
552  pe__clear_raw_action_flags(flags, "group action",
555  }
556 
557  /* Group (pseudo-)actions other than stop or demote are unrunnable
558  * unless every member will do it.
559  */
560  } else if ((task != stop_rsc) && (task != action_demote)) {
561  pe_rsc_trace(action->rsc,
562  "%s is not runnable because %s will not %s",
563  action->uuid, member->id, task_s);
564  pe__clear_raw_action_flags(flags, "group action",
566  }
567  }
568 
569  return flags;
570 }
571 
594 uint32_t
596  const pe_node_t *node, uint32_t flags,
597  uint32_t filter, uint32_t type,
599 {
600  uint32_t changed = pcmk__updated_none;
601 
602  CRM_ASSERT((first != NULL) && (then != NULL) && (data_set != NULL));
603 
604  // Group method can be called only for group action as "then" action
605  CRM_ASSERT(then->rsc != NULL);
606 
607  // Update the actions for the group itself
608  changed |= pcmk__update_ordered_actions(first, then, node, flags, filter,
609  type, data_set);
610 
611  // Update the actions for each group member
612  for (GList *iter = then->rsc->children; iter != NULL; iter = iter->next) {
613  pe_resource_t *member = (pe_resource_t *) iter->data;
614 
615  pe_action_t *member_action = find_first_action(member->actions, NULL,
616  then->task, node);
617 
618  if (member_action != NULL) {
619  changed |= member->cmds->update_ordered_actions(first,
620  member_action, node,
621  flags, filter, type,
622  data_set);
623  }
624  }
625  return changed;
626 }
627 
635 void
637 {
638  GList *node_list_orig = NULL;
639  GList *node_list_copy = NULL;
640  bool reset_scores = true;
641 
642  CRM_ASSERT((rsc != NULL) && (location != NULL));
643 
644  node_list_orig = location->node_list_rh;
645  node_list_copy = pcmk__copy_node_list(node_list_orig, true);
646  reset_scores = pe__group_flag_is_set(rsc, pe__group_colocated);
647 
648  // Apply the constraint for the group itself (updates node scores)
649  pcmk__apply_location(rsc, location);
650 
651  // Apply the constraint for each member
652  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
653  pe_resource_t *member = (pe_resource_t *) iter->data;
654 
655  member->cmds->apply_location(member, location);
656 
657  if (reset_scores) {
658  /* The first member of colocated groups needs to use the original
659  * node scores, but subsequent members should work on a copy, since
660  * the first member's scores already incorporate theirs.
661  */
662  reset_scores = false;
663  location->node_list_rh = node_list_copy;
664  }
665  }
666 
667  location->node_list_rh = node_list_orig;
668  g_list_free_full(node_list_copy, free);
669 }
670 
671 // Group implementation of resource_alloc_functions_t:colocated_resources()
672 GList *
674  GList *colocated_rscs)
675 {
676  pe_resource_t *member = NULL;
677 
678  CRM_ASSERT(rsc != NULL);
679 
680  if (orig_rsc == NULL) {
681  orig_rsc = rsc;
682  }
683 
685  || pe_rsc_is_clone(rsc->parent)) {
686  /* This group has colocated members and/or is cloned -- either way,
687  * add every child's colocated resources to the list.
688  */
689  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
690  member = (pe_resource_t *) iter->data;
691  colocated_rscs = member->cmds->colocated_resources(member, orig_rsc,
692  colocated_rscs);
693  }
694 
695  } else if (rsc->children != NULL) {
696  /* This group's members are not colocated, and the group is not cloned,
697  * so just add the first child's colocations to the list.
698  */
699  member = (pe_resource_t *) rsc->children->data;
700  colocated_rscs = member->cmds->colocated_resources(member, orig_rsc,
701  colocated_rscs);
702  }
703 
704  // Now consider colocations where the group itself is specified
705  colocated_rscs = pcmk__colocated_resources(rsc, orig_rsc, colocated_rscs);
706 
707  return colocated_rscs;
708 }
709 
710 // Group implementation of resource_alloc_functions_t:add_utilization()
711 void
713  const pe_resource_t *orig_rsc, GList *all_rscs,
714  GHashTable *utilization)
715 {
716  pe_resource_t *member = NULL;
717 
718  CRM_ASSERT((rsc != NULL) && (orig_rsc != NULL) && (utilization != NULL));
719 
720  if (!pcmk_is_set(rsc->flags, pe_rsc_provisional)) {
721  return;
722  }
723 
724  pe_rsc_trace(orig_rsc, "%s: Adding group %s as colocated utilization",
725  orig_rsc->id, rsc->id);
727  || pe_rsc_is_clone(rsc->parent)) {
728  // Every group member will be on same node, so sum all members
729  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
730  member = (pe_resource_t *) iter->data;
731 
732  if (pcmk_is_set(member->flags, pe_rsc_provisional)
733  && (g_list_find(all_rscs, member) == NULL)) {
734  member->cmds->add_utilization(member, orig_rsc, all_rscs,
735  utilization);
736  }
737  }
738 
739  } else if (rsc->children != NULL) {
740  // Just add first member's utilization
741  member = (pe_resource_t *) rsc->children->data;
742  if ((member != NULL)
744  && (g_list_find(all_rscs, member) == NULL)) {
745 
746  member->cmds->add_utilization(member, orig_rsc, all_rscs,
747  utilization);
748  }
749  }
750 }
751 
752 // Group implementation of resource_alloc_functions_t:shutdown_lock()
753 void
755 {
756  CRM_ASSERT(rsc != NULL);
757 
758  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
759  pe_resource_t *member = (pe_resource_t *) iter->data;
760 
761  member->cmds->shutdown_lock(member);
762  }
763 }
GList * pcmk__copy_node_list(const GList *list, bool reset)
const char * task2text(enum action_tasks task)
Definition: common.c:401
#define pcmk__order_starts(rsc1, rsc2, flags)
#define RSC_STOP
Definition: crm.h:202
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:46
char data[0]
Definition: cpg.c:55
#define INFINITY
Definition: crm.h:99
GList * rsc_cons
Definition: pe_types.h:364
#define pe__set_action_flags(action, flags_to_set)
Definition: internal.h:86
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:394
G_GNUC_INTERNAL GList * pcmk__colocated_resources(pe_resource_t *rsc, pe_resource_t *orig_rsc, GList *colocated_rscs)
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:377
GList * children
Definition: pe_types.h:384
resource_alloc_functions_t * cmds
Definition: pe_types.h:341
#define pcmk__order_stops(rsc1, rsc2, flags)
pe_resource_t * rsc
Definition: pe_types.h:406
enum rsc_role_e next_role
Definition: pe_types.h:378
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:1296
#define pcmk__config_err(fmt...)
GHashTable * meta
Definition: pe_types.h:380
#define pe_rsc_critical
Definition: pe_types.h:274
GList * rsc_cons_lhs
Definition: pe_types.h:363
enum crm_ais_msg_types type
Definition: cpg.c:48
#define RSC_START
Definition: crm.h:199
G_GNUC_INTERNAL void pcmk__add_with_this(pe_resource_t *rsc, pcmk__colocation_t *colocation)
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:370
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:74
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:266
void pcmk__group_create_actions(pe_resource_t *rsc)
#define XML_RSC_ATTR_PROMOTABLE
Definition: msg_xml.h:232
pe_action_flags
Definition: pe_types.h:298
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:912
GList * pcmk__group_colocated_resources(pe_resource_t *rsc, pe_resource_t *orig_rsc, GList *colocated_rscs)
char * task
Definition: pe_types.h:410
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:95
enum action_tasks get_complex_task(pe_resource_t *rsc, const char *name, gboolean allow_non_atomic)
Definition: pe_actions.c:1262
GList *(* colocated_resources)(pe_resource_t *rsc, pe_resource_t *orig_rsc, GList *colocated_rscs)
#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:355
#define pe_rsc_promotable
Definition: pe_types.h:264
pe_working_set_t * data_set
void(* create_actions)(pe_resource_t *rsc)
GList * actions
Definition: pe_types.h:366
char * uuid
Definition: pe_types.h:411
#define pe_rsc_allocating
Definition: pe_types.h:267
enum pe_obj_types variant
Definition: pe_types.h:338
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
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:45
#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
#define CRM_ASSERT(expr)
Definition: results.h:42
#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:1120
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:80
GList * running_on
Definition: pe_types.h:373
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:335
#define RSC_STOPPED
Definition: crm.h:203
G_GNUC_INTERNAL void pcmk__add_this_with(pe_resource_t *rsc, pcmk__colocation_t *colocation)
#define RSC_PROMOTED
Definition: crm.h:206
pe_node_t * pcmk__group_assign(pe_resource_t *rsc, const pe_node_t *prefer)
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:47
#define pe__set_order_flags(order_flags, flags_to_set)
Definition: internal.h:138
unsigned long long flags
Definition: pe_types.h:153
bool pe__group_flag_is_set(const pe_resource_t *group, uint32_t flags)
Definition: group.c:57
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:940
#define pe_flag_show_scores
Definition: pe_types.h:134
#define pe__clear_raw_action_flags(action_flags, action_name, flags_to_clear)
Definition: internal.h:111
#define pe_rsc_managed
Definition: pe_types.h:257
uint64_t flags
Definition: remote.c:215
action_tasks
Definition: common.h:61
pe_resource_t * parent
Definition: pe_types.h:336
#define RSC_DEMOTE
Definition: crm.h:207
char * id
Definition: pe_types.h:329
GHashTable * allowed_nodes
Definition: pe_types.h:375