pacemaker  2.1.1-52dc28db4
Scalable High-Availability cluster resource manager
pcmk_sched_group.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2021 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 
18 #define VARIANT_GROUP 1
19 #include <lib/pengine/variant.h>
20 
27 static void
28 expand_group_colocations(pe_resource_t *rsc)
29 {
30  group_variant_data_t *group_data = NULL;
31  pe_resource_t *member = NULL;
32  bool any_unmanaged = false;
33 
34  get_group_variant_data(group_data, rsc);
35 
36  // Treat "group with R" colocations as "first member with R"
37  member = group_data->first_child;
38  member->rsc_cons = g_list_concat(member->rsc_cons, rsc->rsc_cons);
39 
40 
41  /* The above works for the whole group because each group member is
42  * colocated with the previous one.
43  *
44  * However, there is a special case when a group has a mandatory colocation
45  * with a resource that can't start. In that case, update_colo_start_chain()
46  * will ensure that dependent resources in mandatory colocations (i.e. the
47  * first member for groups) can't start either. But if any group member is
48  * unmanaged and already started, the internal group colocations are no
49  * longer sufficient to make that apply to later members.
50  *
51  * To handle that case, add mandatory colocations to each member after the
52  * first.
53  */
54  any_unmanaged = !pcmk_is_set(member->flags, pe_rsc_managed);
55  for (GList *item = rsc->children->next; item != NULL; item = item->next) {
56  member = item->data;
57  if (any_unmanaged) {
58  for (GList *cons_iter = rsc->rsc_cons; cons_iter != NULL;
59  cons_iter = cons_iter->next) {
60 
61  pcmk__colocation_t *constraint = (pcmk__colocation_t *) cons_iter->data;
62 
63  if (constraint->score == INFINITY) {
64  member->rsc_cons = g_list_prepend(member->rsc_cons, constraint);
65  }
66  }
67  } else if (!pcmk_is_set(member->flags, pe_rsc_managed)) {
68  any_unmanaged = true;
69  }
70  }
71 
72  rsc->rsc_cons = NULL;
73 
74  // Treat "R with group" colocations as "R with last member"
75  member = group_data->last_child;
76  member->rsc_cons_lhs = g_list_concat(member->rsc_cons_lhs,
77  rsc->rsc_cons_lhs);
78  rsc->rsc_cons_lhs = NULL;
79 }
80 
81 pe_node_t *
83  pe_working_set_t *data_set)
84 {
85  pe_node_t *node = NULL;
86  pe_node_t *group_node = NULL;
87  GList *gIter = NULL;
88  group_variant_data_t *group_data = NULL;
89 
90  get_group_variant_data(group_data, rsc);
91 
92  if (!pcmk_is_set(rsc->flags, pe_rsc_provisional)) {
93  return rsc->allocated_to;
94  }
95  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
96  pe_rsc_debug(rsc, "Dependency loop detected involving %s", rsc->id);
97  return NULL;
98  }
99 
100  if (group_data->first_child == NULL) {
101  // Nothing to allocate
103  return NULL;
104  }
105 
107  rsc->role = group_data->first_child->role;
108 
109  expand_group_colocations(rsc);
110 
112  rsc, __func__, rsc->allowed_nodes, data_set);
113 
114  gIter = rsc->children;
115  for (; gIter != NULL; gIter = gIter->next) {
116  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
117 
118  pe_rsc_trace(rsc, "Allocating group %s member %s",
119  rsc->id, child_rsc->id);
120  node = child_rsc->cmds->allocate(child_rsc, prefer, data_set);
121  if (group_node == NULL) {
122  group_node = node;
123  }
124  }
125 
126  pe__set_next_role(rsc, group_data->first_child->next_role,
127  "first group member");
129 
130  if (group_data->colocated) {
131  return group_node;
132  }
133  return NULL;
134 }
135 
137 
138 void
140 {
141  pe_action_t *op = NULL;
142  const char *value = NULL;
143  GList *gIter = rsc->children;
144 
145  pe_rsc_trace(rsc, "Creating actions for %s", rsc->id);
146 
147  for (; gIter != NULL; gIter = gIter->next) {
148  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
149 
150  child_rsc->cmds->create_actions(child_rsc, data_set);
151  group_update_pseudo_status(rsc, child_rsc);
152  }
153 
154  op = start_action(rsc, NULL, TRUE /* !group_data->child_starting */ );
156 
157  op = custom_action(rsc, started_key(rsc),
158  RSC_STARTED, NULL, TRUE /* !group_data->child_starting */ , TRUE, data_set);
160 
161  op = stop_action(rsc, NULL, TRUE /* !group_data->child_stopping */ );
163 
164  op = custom_action(rsc, stopped_key(rsc),
165  RSC_STOPPED, NULL, TRUE /* !group_data->child_stopping */ , TRUE, data_set);
167 
168  value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_PROMOTABLE);
169  if (crm_is_true(value)) {
170  op = custom_action(rsc, demote_key(rsc), RSC_DEMOTE, NULL, TRUE, TRUE, data_set);
172 
173  op = custom_action(rsc, demoted_key(rsc), RSC_DEMOTED, NULL, TRUE, TRUE, data_set);
175 
176  op = custom_action(rsc, promote_key(rsc), RSC_PROMOTE, NULL, TRUE, TRUE, data_set);
178 
179  op = custom_action(rsc, promoted_key(rsc), RSC_PROMOTED, NULL, TRUE, TRUE, data_set);
181  }
182 }
183 
184 void
186 {
187  GList *gIter = child->actions;
188  group_variant_data_t *group_data = NULL;
189 
190  get_group_variant_data(group_data, parent);
191 
192  if (group_data->ordered == FALSE) {
193  /* If this group is not ordered, then leave the meta-actions as optional */
194  return;
195  }
196 
197  if (group_data->child_stopping && group_data->child_starting) {
198  return;
199  }
200 
201  for (; gIter != NULL; gIter = gIter->next) {
202  pe_action_t *action = (pe_action_t *) gIter->data;
203 
204  if (pcmk_is_set(action->flags, pe_action_optional)) {
205  continue;
206  }
207  if (pcmk__str_eq(RSC_STOP, action->task, pcmk__str_casei)
208  && pcmk_is_set(action->flags, pe_action_runnable)) {
209 
210  group_data->child_stopping = TRUE;
211  pe_rsc_trace(action->rsc, "Based on %s the group is stopping", action->uuid);
212 
213  } else if (pcmk__str_eq(RSC_START, action->task, pcmk__str_casei)
214  && pcmk_is_set(action->flags, pe_action_runnable)) {
215  group_data->child_starting = TRUE;
216  pe_rsc_trace(action->rsc, "Based on %s the group is starting", action->uuid);
217  }
218  }
219 }
220 
221 void
223 {
224  GList *gIter = rsc->children;
225  pe_resource_t *last_rsc = NULL;
226  pe_resource_t *last_active = NULL;
227  pe_resource_t *top = uber_parent(rsc);
228  group_variant_data_t *group_data = NULL;
229 
230  get_group_variant_data(group_data, rsc);
231 
232  new_rsc_order(rsc, RSC_STOPPED, rsc, RSC_START, pe_order_optional, data_set);
235 
236  for (; gIter != NULL; gIter = gIter->next) {
237  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
238  int stop = pe_order_none;
239  int stopped = pe_order_implies_then_printed;
241  int started =
243 
244  child_rsc->cmds->internal_constraints(child_rsc, data_set);
245 
246  if (last_rsc == NULL) {
247  if (group_data->ordered) {
249  stopped = pe_order_implies_then;
250  }
251 
252  } else if (group_data->colocated) {
253  pcmk__new_colocation("group:internal_colocation", NULL, INFINITY,
254  child_rsc, last_rsc, NULL, NULL,
255  pcmk_is_set(child_rsc->flags, pe_rsc_critical),
256  data_set);
257  }
258 
259  if (pcmk_is_set(top->flags, pe_rsc_promotable)) {
260  new_rsc_order(rsc, RSC_DEMOTE, child_rsc, RSC_DEMOTE,
261  stop | pe_order_implies_first_printed, data_set);
262 
263  new_rsc_order(child_rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, stopped, data_set);
264 
265  new_rsc_order(child_rsc, RSC_PROMOTE, rsc, RSC_PROMOTED, started, data_set);
266 
267  new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE,
269 
270  }
271 
273  order_stop_stop(rsc, child_rsc, stop | pe_order_implies_first_printed);
274 
275  new_rsc_order(child_rsc, RSC_STOP, rsc, RSC_STOPPED, stopped, data_set);
276 
277  new_rsc_order(child_rsc, RSC_START, rsc, RSC_STARTED, started, data_set);
278 
279  if (group_data->ordered == FALSE) {
280  order_start_start(rsc, child_rsc, start | pe_order_implies_first_printed);
281  if (pcmk_is_set(top->flags, pe_rsc_promotable)) {
282  new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE,
283  start | pe_order_implies_first_printed, data_set);
284  }
285 
286  } else if (last_rsc != NULL) {
287  order_start_start(last_rsc, child_rsc, start);
288  order_stop_stop(child_rsc, last_rsc, pe_order_optional | pe_order_restart);
289 
290  if (pcmk_is_set(top->flags, pe_rsc_promotable)) {
291  new_rsc_order(last_rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE, start, data_set);
292  new_rsc_order(child_rsc, RSC_DEMOTE, last_rsc, RSC_DEMOTE, pe_order_optional,
293  data_set);
294  }
295 
296  } else {
297  order_start_start(rsc, child_rsc, pe_order_none);
298  if (pcmk_is_set(top->flags, pe_rsc_promotable)) {
299  new_rsc_order(rsc, RSC_PROMOTE, child_rsc, RSC_PROMOTE,
300  pe_order_none, data_set);
301  }
302  }
303 
304  /* Look for partially active groups
305  * Make sure they still shut down in sequence
306  */
307  if (child_rsc->running_on) {
308  if (group_data->ordered
309  && last_rsc
310  && last_rsc->running_on == NULL && last_active && last_active->running_on) {
311  order_stop_stop(child_rsc, last_active, pe_order_optional);
312  }
313  last_active = child_rsc;
314  }
315 
316  last_rsc = child_rsc;
317  }
318 
319  if (group_data->ordered && last_rsc != NULL) {
320  int stop_stop_flags = pe_order_implies_then;
321  int stop_stopped_flags = pe_order_optional;
322 
323  order_stop_stop(rsc, last_rsc, stop_stop_flags);
324  new_rsc_order(last_rsc, RSC_STOP, rsc, RSC_STOPPED, stop_stopped_flags, data_set);
325 
326  if (pcmk_is_set(top->flags, pe_rsc_promotable)) {
327  new_rsc_order(rsc, RSC_DEMOTE, last_rsc, RSC_DEMOTE, stop_stop_flags, data_set);
328  new_rsc_order(last_rsc, RSC_DEMOTE, rsc, RSC_DEMOTED, stop_stopped_flags, data_set);
329  }
330  }
331 }
332 
333 void
335  pcmk__colocation_t *constraint,
336  pe_working_set_t *data_set)
337 {
338  GList *gIter = NULL;
339  group_variant_data_t *group_data = NULL;
340 
341  if (rsc_lh == NULL) {
342  pe_err("rsc_lh was NULL for %s", constraint->id);
343  return;
344 
345  } else if (rsc_rh == NULL) {
346  pe_err("rsc_rh was NULL for %s", constraint->id);
347  return;
348  }
349 
350  gIter = rsc_lh->children;
351  pe_rsc_trace(rsc_lh, "Processing constraints from %s", rsc_lh->id);
352 
353  get_group_variant_data(group_data, rsc_lh);
354 
355  if (group_data->colocated) {
356  group_data->first_child->cmds->rsc_colocation_lh(group_data->first_child,
357  rsc_rh, constraint,
358  data_set);
359  return;
360 
361  } else if (constraint->score >= INFINITY) {
362  pcmk__config_err("%s: Cannot perform mandatory colocation "
363  "between non-colocated group and %s",
364  rsc_lh->id, rsc_rh->id);
365  return;
366  }
367 
368  for (; gIter != NULL; gIter = gIter->next) {
369  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
370 
371  child_rsc->cmds->rsc_colocation_lh(child_rsc, rsc_rh, constraint,
372  data_set);
373  }
374 }
375 
376 void
378  pcmk__colocation_t *constraint,
379  pe_working_set_t *data_set)
380 {
381  GList *gIter = rsc_rh->children;
382  group_variant_data_t *group_data = NULL;
383 
384  get_group_variant_data(group_data, rsc_rh);
385  CRM_CHECK(rsc_lh->variant == pe_native, return);
386 
387  pe_rsc_trace(rsc_rh, "Processing RH %s of constraint %s (LH is %s)",
388  rsc_rh->id, constraint->id, rsc_lh->id);
389 
390  if (pcmk_is_set(rsc_rh->flags, pe_rsc_provisional)) {
391  return;
392 
393  } else if (group_data->colocated && group_data->first_child) {
394  if (constraint->score >= INFINITY) {
395  /* Ensure RHS is _fully_ up before can start LHS */
396  group_data->last_child->cmds->rsc_colocation_rh(rsc_lh,
397  group_data->last_child,
398  constraint,
399  data_set);
400  } else {
401  /* A partially active RHS is fine */
402  group_data->first_child->cmds->rsc_colocation_rh(rsc_lh,
403  group_data->first_child,
404  constraint,
405  data_set);
406  }
407 
408  return;
409 
410  } else if (constraint->score >= INFINITY) {
411  pcmk__config_err("%s: Cannot perform mandatory colocation with"
412  " non-colocated group %s", rsc_lh->id, rsc_rh->id);
413  return;
414  }
415 
416  for (; gIter != NULL; gIter = gIter->next) {
417  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
418 
419  child_rsc->cmds->rsc_colocation_rh(rsc_lh, child_rsc, constraint,
420  data_set);
421  }
422 }
423 
424 enum pe_action_flags
426 {
427  GList *gIter = NULL;
429 
430  for (gIter = action->rsc->children; gIter != NULL; gIter = gIter->next) {
431  pe_resource_t *child = (pe_resource_t *) gIter->data;
432  enum action_tasks task = get_complex_task(child, action->task, TRUE);
433  const char *task_s = task2text(task);
434  pe_action_t *child_action = find_first_action(child->actions, NULL, task_s, node);
435 
436  if (child_action) {
437  enum pe_action_flags child_flags = child->cmds->action_flags(child_action, node);
438 
440  && !pcmk_is_set(child_flags, pe_action_optional)) {
441  pe_rsc_trace(action->rsc, "%s is mandatory because of %s", action->uuid,
442  child_action->uuid);
443  pe__clear_raw_action_flags(flags, "group action",
446  }
447  if (!pcmk__str_eq(task_s, action->task, pcmk__str_casei)
449  && !pcmk_is_set(child_flags, pe_action_runnable)) {
450 
451  pe_rsc_trace(action->rsc, "%s is not runnable because of %s", action->uuid,
452  child_action->uuid);
453  pe__clear_raw_action_flags(flags, "group action",
456  }
457 
458  } else if (task != stop_rsc && task != action_demote) {
459  pe_rsc_trace(action->rsc, "%s is not runnable because of %s (not found in %s)",
460  action->uuid, task_s, child->id);
461  pe__clear_raw_action_flags(flags, "group action",
463  }
464  }
465 
466  return flags;
467 }
468 
469 enum pe_graph_flags
471  enum pe_action_flags flags, enum pe_action_flags filter,
472  enum pe_ordering type, pe_working_set_t *data_set)
473 {
474  GList *gIter = then->rsc->children;
475  enum pe_graph_flags changed = pe_graph_none;
476 
477  CRM_ASSERT(then->rsc != NULL);
478  changed |= native_update_actions(first, then, node, flags, filter, type,
479  data_set);
480 
481  for (; gIter != NULL; gIter = gIter->next) {
482  pe_resource_t *child = (pe_resource_t *) gIter->data;
483  pe_action_t *child_action = find_first_action(child->actions, NULL, then->task, node);
484 
485  if (child_action) {
486  changed |= child->cmds->update_actions(first, child_action, node,
487  flags, filter, type,
488  data_set);
489  }
490  }
491 
492  return changed;
493 }
494 
495 void
497 {
498  GList *gIter = rsc->children;
499  GList *saved = constraint->node_list_rh;
500  GList *zero = pcmk__copy_node_list(constraint->node_list_rh, true);
501  gboolean reset_scores = TRUE;
502  group_variant_data_t *group_data = NULL;
503 
504  get_group_variant_data(group_data, rsc);
505 
506  pe_rsc_debug(rsc, "Processing rsc_location %s for %s", constraint->id, rsc->id);
507 
508  native_rsc_location(rsc, constraint);
509 
510  for (; gIter != NULL; gIter = gIter->next) {
511  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
512 
513  child_rsc->cmds->rsc_location(child_rsc, constraint);
514  if (group_data->colocated && reset_scores) {
515  reset_scores = FALSE;
516  constraint->node_list_rh = zero;
517  }
518  }
519 
520  constraint->node_list_rh = saved;
521  g_list_free_full(zero, free);
522 }
523 
524 void
526 {
527  CRM_CHECK(rsc != NULL, return);
528 
529  pe_rsc_trace(rsc, "Processing actions from %s", rsc->id);
530  native_expand(rsc, data_set);
531 
532  for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
533  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
534 
535  child_rsc->cmds->expand(child_rsc, data_set);
536  }
537 }
538 
539 GHashTable *
541  GHashTable *nodes, const char *attr, float factor,
542  uint32_t flags)
543 {
544  GList *gIter = rsc->rsc_cons_lhs;
545  group_variant_data_t *group_data = NULL;
546 
547  get_group_variant_data(group_data, rsc);
548 
549  if (pcmk_is_set(rsc->flags, pe_rsc_merging)) {
550  pe_rsc_info(rsc, "Breaking dependency loop with %s at %s", rsc->id, rhs);
551  return nodes;
552  }
553 
555 
556  nodes =
557  group_data->first_child->cmds->merge_weights(group_data->first_child, rhs, nodes, attr,
558  factor, flags);
559 
560  for (; gIter != NULL; gIter = gIter->next) {
561  pcmk__colocation_t *constraint = (pcmk__colocation_t *) gIter->data;
562 
563  nodes = pcmk__native_merge_weights(constraint->rsc_lh, rsc->id, nodes,
564  constraint->node_attribute,
565  constraint->score / (float) INFINITY,
566  flags);
567  }
568 
570  return nodes;
571 }
572 
573 void
574 group_append_meta(pe_resource_t * rsc, xmlNode * xml)
575 {
576 }
GList * pcmk__copy_node_list(const GList *list, bool reset)
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:218
const char * task2text(enum action_tasks task)
Definition: common.c:406
#define RSC_STOP
Definition: crm.h:204
pe_resource_t * rsc_lh
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:19
#define INFINITY
Definition: crm.h:99
GList * rsc_cons
Definition: pe_types.h:358
#define pe__set_action_flags(action, flags_to_set)
Definition: internal.h:59
#define demoted_key(rsc)
Definition: internal.h:407
#define pe__show_node_weights(level, rsc, text, nodes, data_set)
Definition: internal.h:353
#define stop_action(rsc, node, optional)
Definition: internal.h:377
GHashTable * pcmk__group_merge_weights(pe_resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, uint32_t flags)
enum rsc_role_e role
Definition: pe_types.h:371
GList * children
Definition: pe_types.h:378
#define stopped_key(rsc)
Definition: internal.h:371
resource_alloc_functions_t * cmds
Definition: pe_types.h:334
void pcmk__new_colocation(const char *id, const char *node_attr, int score, pe_resource_t *rsc_lh, pe_resource_t *rsc_rh, const char *state_lh, const char *state_rh, bool influence, pe_working_set_t *data_set)
enum pe_graph_flags(* update_actions)(pe_action_t *, pe_action_t *, pe_node_t *, enum pe_action_flags, enum pe_action_flags, enum pe_ordering, pe_working_set_t *data_set)
pe_resource_t * rsc
Definition: pe_types.h:411
enum rsc_role_e next_role
Definition: pe_types.h:372
#define pcmk__config_err(fmt...)
GHashTable * meta
Definition: pe_types.h:374
void group_rsc_colocation_lh(pe_resource_t *rsc_lh, pe_resource_t *rsc_rh, pcmk__colocation_t *constraint, pe_working_set_t *data_set)
#define pe_rsc_critical
Definition: pe_types.h:265
void group_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
void(* internal_constraints)(pe_resource_t *, pe_working_set_t *)
enum pe_graph_flags native_update_actions(pe_action_t *first, pe_action_t *then, pe_node_t *node, enum pe_action_flags flags, enum pe_action_flags filter, enum pe_ordering type, pe_working_set_t *data_set)
GList * rsc_cons_lhs
Definition: pe_types.h:357
void native_expand(pe_resource_t *rsc, pe_working_set_t *data_set)
enum crm_ais_msg_types type
Definition: cpg.c:48
#define demote_key(rsc)
Definition: internal.h:402
void native_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
#define RSC_START
Definition: crm.h:201
pe_node_t *(* allocate)(pe_resource_t *, pe_node_t *, pe_working_set_t *)
pe_node_t * allocated_to
Definition: pe_types.h:364
GHashTable * pcmk__native_merge_weights(pe_resource_t *rsc, const char *rhs, GHashTable *nodes, const char *attr, float factor, uint32_t flags)
const char * action
Definition: pcmk_fence.c:30
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:47
void group_update_pseudo_status(pe_resource_t *parent, pe_resource_t *child)
#define pe_rsc_provisional
Definition: pe_types.h:258
#define XML_RSC_ATTR_PROMOTABLE
Definition: msg_xml.h:229
#define pe_rsc_merging
Definition: pe_types.h:260
pe_action_flags
Definition: pe_types.h:291
#define order_stop_stop(rsc1, rsc2, type)
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:903
void group_internal_constraints(pe_resource_t *rsc, pe_working_set_t *data_set)
void(* rsc_colocation_lh)(pe_resource_t *, pe_resource_t *, pcmk__colocation_t *, pe_working_set_t *)
char * task
Definition: pe_types.h:415
#define pe__clear_action_flags(action, flags_to_clear)
Definition: internal.h:68
enum action_tasks get_complex_task(pe_resource_t *rsc, const char *name, gboolean allow_non_atomic)
Definition: utils.c:1405
#define promote_key(rsc)
Definition: internal.h:392
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:114
unsigned long long flags
Definition: pe_types.h:349
#define pe_rsc_promotable
Definition: pe_types.h:256
void(* expand)(pe_resource_t *, pe_working_set_t *)
#define started_key(rsc)
Definition: internal.h:387
GList * actions
Definition: pe_types.h:360
pe_graph_flags
Definition: pe_types.h:283
char * uuid
Definition: pe_types.h:416
void(* rsc_colocation_rh)(pe_resource_t *, pe_resource_t *, pcmk__colocation_t *, pe_working_set_t *)
void group_create_actions(pe_resource_t *rsc, pe_working_set_t *data_set)
enum pe_action_flags(* action_flags)(pe_action_t *, pe_node_t *)
#define pe_rsc_allocating
Definition: pe_types.h:259
enum pe_obj_types variant
Definition: pe_types.h:331
int new_rsc_order(pe_resource_t *lh_rsc, const char *lh_task, pe_resource_t *rh_rsc, const char *rh_task, enum pe_ordering type, pe_working_set_t *data_set)
#define RSC_DEMOTED
Definition: crm.h:210
#define promoted_key(rsc)
Definition: internal.h:397
#define RSC_STARTED
Definition: crm.h:202
#define start_action(rsc, node, optional)
Definition: internal.h:383
#define CRM_ASSERT(expr)
Definition: results.h:42
pe_node_t * pcmk__group_allocate(pe_resource_t *rsc, pe_node_t *prefer, pe_working_set_t *data_set)
#define RSC_PROMOTE
Definition: crm.h:207
void pe__set_next_role(pe_resource_t *rsc, enum rsc_role_e role, const char *why)
Definition: complex.c:1116
void(* rsc_location)(pe_resource_t *, pe__location_t *)
void group_expand(pe_resource_t *rsc, pe_working_set_t *data_set)
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:53
GList * running_on
Definition: pe_types.h:367
void(* create_actions)(pe_resource_t *, pe_working_set_t *)
void group_append_meta(pe_resource_t *rsc, xmlNode *xml)
enum pe_graph_flags group_update_actions(pe_action_t *first, pe_action_t *then, pe_node_t *node, enum pe_action_flags flags, enum pe_action_flags filter, enum pe_ordering type, pe_working_set_t *data_set)
#define order_start_start(rsc1, rsc2, type)
const char * node_attribute
#define RSC_STOPPED
Definition: crm.h:205
#define RSC_PROMOTED
Definition: crm.h:208
gboolean crm_is_true(const char *s)
Definition: strings.c:415
void group_rsc_colocation_rh(pe_resource_t *rsc_lh, pe_resource_t *rsc_rh, pcmk__colocation_t *constraint, pe_working_set_t *data_set)
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:20
#define pe__set_order_flags(order_flags, flags_to_set)
Definition: internal.h:111
unsigned long long flags
Definition: pe_types.h:146
#define pe_err(fmt...)
Definition: internal.h:22
#define pe_flag_show_scores
Definition: pe_types.h:133
#define pe__clear_raw_action_flags(action_flags, action_name, flags_to_clear)
Definition: internal.h:84
#define pe_rsc_managed
Definition: pe_types.h:249
pe_action_t * find_first_action(GList *input, const char *uuid, const char *task, pe_node_t *on_node)
Definition: utils.c:1428
pe_ordering
Definition: pe_types.h:484
uint64_t flags
Definition: remote.c:149
action_tasks
Definition: common.h:62
#define RSC_DEMOTE
Definition: crm.h:209
#define pe_rsc_info(rsc, fmt, args...)
Definition: internal.h:18
char * id
Definition: pe_types.h:322
pe_action_t * custom_action(pe_resource_t *rsc, char *key, const char *task, pe_node_t *on_node, gboolean optional, gboolean foo, pe_working_set_t *data_set)
Definition: utils.c:415
GHashTable * allowed_nodes
Definition: pe_types.h:369
enum pe_action_flags group_action_flags(pe_action_t *action, pe_node_t *node)