pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
pcmk_sched_clone.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 <crm/msg_xml.h>
13 #include <pacemaker-internal.h>
14 
15 #include "libpacemaker_private.h"
16 
26 pe_node_t *
28 {
29  CRM_ASSERT(pe_rsc_is_clone(rsc));
30 
31  if (!pcmk_is_set(rsc->flags, pe_rsc_provisional)) {
32  return NULL; // Assignment has already been done
33  }
34 
35  // Detect assignment loops
36  if (pcmk_is_set(rsc->flags, pe_rsc_allocating)) {
37  pe_rsc_debug(rsc, "Breaking assignment loop involving %s", rsc->id);
38  return NULL;
39  }
41 
42  // If this clone is promotable, consider nodes' promotion scores
43  if (pcmk_is_set(rsc->flags, pe_rsc_promotable)) {
45  }
46 
47  /* If this clone is colocated with any other resources, assign those first.
48  * Since the this_with_colocations() method boils down to a copy of rsc_cons
49  * for clones, we can use that here directly for efficiency.
50  */
51  for (GList *iter = rsc->rsc_cons; iter != NULL; iter = iter->next) {
52  pcmk__colocation_t *constraint = (pcmk__colocation_t *) iter->data;
53 
54  pe_rsc_trace(rsc, "%s: Assigning colocation %s primary %s first",
55  rsc->id, constraint->id, constraint->primary->id);
56  constraint->primary->cmds->assign(constraint->primary, prefer);
57  }
58 
59  /* If any resources are colocated with this one, consider their preferences.
60  * Because the with_this_colocations() method boils down to a copy of
61  * rsc_cons_lhs for clones, we can use that here directly for efficiency.
62  */
63  g_list_foreach(rsc->rsc_cons_lhs, pcmk__add_dependent_scores, rsc);
64 
66  rsc, __func__, rsc->allowed_nodes, rsc->cluster);
67 
68  rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance);
70  pe__clone_node_max(rsc));
71 
72  if (pcmk_is_set(rsc->flags, pe_rsc_promotable)) {
74  }
75 
77  pe_rsc_trace(rsc, "Assigned clone %s", rsc->id);
78  return NULL;
79 }
80 
81 static pe_action_t *
82 find_rsc_action(pe_resource_t *rsc, const char *task)
83 {
84  pe_action_t *match = NULL;
85  GList *actions = pe__resource_actions(rsc, NULL, task, FALSE);
86 
87  for (GList *item = actions; item != NULL; item = item->next) {
88  pe_action_t *op = (pe_action_t *) item->data;
89 
91  if (match != NULL) {
92  // More than one match, don't return any
93  match = NULL;
94  break;
95  }
96  match = op;
97  }
98  }
99  g_list_free(actions);
100  return match;
101 }
102 
109 static void
110 order_instance_starts_stops(pe_resource_t *rsc)
111 {
112  pe_action_t *last_stop = NULL;
113  pe_action_t *last_start = NULL;
114 
115  // Instances must be ordered by ascending instance number, so sort them
116  rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance_number);
117 
118  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
119  pe_resource_t *child = (pe_resource_t *) iter->data;
120  pe_action_t *action = NULL;
121 
122  // Order this instance's stop after previous instance's stop
123  // @TODO: Should instances be stopped in reverse order instead?
124  action = find_rsc_action(child, RSC_STOP);
125  if (action != NULL) {
126  if (last_stop != NULL) {
128  }
129  last_stop = action;
130  }
131 
132  // Order this instance's start after previous instance's start
133  action = find_rsc_action(child, RSC_START);
134  if (action != NULL) {
135  if (last_start != NULL) {
136  order_actions(last_start, action, pe_order_optional);
137  }
138  last_start = action;
139  }
140  }
141 }
142 
143 void
145 {
146  pe_rsc_debug(rsc, "Creating actions for clone %s", rsc->id);
148  if (pe__clone_is_ordered(rsc)) {
149  order_instance_starts_stops(rsc);
150  }
151  if (pcmk_is_set(rsc->flags, pe_rsc_promotable)) {
153  }
154 }
155 
156 void
158 {
159  pe_resource_t *last_rsc = NULL;
160  GList *gIter;
161  bool ordered = pe__clone_is_ordered(rsc);
162 
163  pe_rsc_trace(rsc, "Internal constraints for %s", rsc->id);
170 
171  if (pcmk_is_set(rsc->flags, pe_rsc_promotable)) {
176  }
177 
178  if (ordered) {
179  /* we have to maintain a consistent sorted child list when building order constraints */
180  rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance_number);
181  }
182  for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
183  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
184 
185  child_rsc->cmds->internal_constraints(child_rsc);
186 
187  pcmk__order_starts(rsc, child_rsc,
191  if (ordered && (last_rsc != NULL)) {
192  pcmk__order_starts(last_rsc, child_rsc, pe_order_optional);
193  }
194 
198  if (ordered && (last_rsc != NULL)) {
199  pcmk__order_stops(child_rsc, last_rsc, pe_order_optional);
200  }
201 
202  last_rsc = child_rsc;
203  }
204  if (pcmk_is_set(rsc->flags, pe_rsc_promotable)) {
206  }
207 }
208 
222 void
224  const pe_resource_t *primary,
225  const pcmk__colocation_t *colocation,
226  bool for_dependent)
227 {
228  GList *gIter = NULL;
229  gboolean do_interleave = FALSE;
230  const char *interleave_s = NULL;
231 
232  /* This should never be called for the clone itself as a dependent. Instead,
233  * we add its colocation constraints to its instances and call the
234  * apply_coloc_score() for the instances as dependents.
235  */
236  CRM_ASSERT(!for_dependent);
237 
238  CRM_CHECK((colocation != NULL) && (dependent != NULL) && (primary != NULL),
239  return);
240  CRM_CHECK(dependent->variant == pe_native, return);
241 
242  pe_rsc_trace(primary, "Processing constraint %s: %s -> %s %d",
243  colocation->id, dependent->id, primary->id, colocation->score);
244 
245  if (pcmk_is_set(primary->flags, pe_rsc_promotable)) {
246  if (pcmk_is_set(primary->flags, pe_rsc_provisional)) {
247  // We haven't placed the primary yet, so we can't apply colocation
248  pe_rsc_trace(primary, "%s is still provisional", primary->id);
249  return;
250 
251  } else if (colocation->primary_role == RSC_ROLE_UNKNOWN) {
252  // This isn't a role-specfic colocation, so handle normally
253  pe_rsc_trace(primary, "Handling %s as a clone colocation",
254  colocation->id);
255 
256  } else if (pcmk_is_set(dependent->flags, pe_rsc_provisional)) {
257  // We're placing the dependent
258  pcmk__update_dependent_with_promotable(primary, dependent,
259  colocation);
260  return;
261 
262  } else if (colocation->dependent_role == RSC_ROLE_PROMOTED) {
263  // We're choosing roles for the dependent
265  colocation);
266  return;
267  }
268  }
269 
270  // Only the dependent needs to be marked for interleave
271  interleave_s = g_hash_table_lookup(colocation->dependent->meta,
273  if (crm_is_true(interleave_s)
274  && (colocation->dependent->variant > pe_group)) {
275  /* @TODO Do we actually care about multiple primary copies sharing a
276  * dependent copy anymore?
277  */
278  if (copies_per_node(colocation->dependent) != copies_per_node(colocation->primary)) {
279  pcmk__config_err("Cannot interleave %s and %s because they do not "
280  "support the same number of instances per node",
281  colocation->dependent->id,
282  colocation->primary->id);
283 
284  } else {
285  do_interleave = TRUE;
286  }
287  }
288 
289  if (pcmk_is_set(primary->flags, pe_rsc_provisional)) {
290  pe_rsc_trace(primary, "%s is still provisional", primary->id);
291  return;
292 
293  } else if (do_interleave) {
294  pe_resource_t *primary_instance = NULL;
295 
296  primary_instance = pcmk__find_compatible_instance(dependent, primary,
298  false);
299  if (primary_instance != NULL) {
300  pe_rsc_debug(primary, "Pairing %s with %s",
301  dependent->id, primary_instance->id);
302  dependent->cmds->apply_coloc_score(dependent, primary_instance,
303  colocation, true);
304 
305  } else if (colocation->score >= INFINITY) {
306  crm_notice("Cannot pair %s with instance of %s",
307  dependent->id, primary->id);
308  pcmk__assign_resource(dependent, NULL, true);
309 
310  } else {
311  pe_rsc_debug(primary, "Cannot pair %s with instance of %s",
312  dependent->id, primary->id);
313  }
314 
315  return;
316 
317  } else if (colocation->score >= INFINITY) {
318  GList *affected_nodes = NULL;
319 
320  gIter = primary->children;
321  for (; gIter != NULL; gIter = gIter->next) {
322  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
323  pe_node_t *chosen = child_rsc->fns->location(child_rsc, NULL, FALSE);
324 
325  if (chosen != NULL && is_set_recursive(child_rsc, pe_rsc_block, TRUE) == FALSE) {
326  pe_rsc_trace(primary, "Allowing %s: %s %d",
327  colocation->id, pe__node_name(chosen),
328  chosen->weight);
329  affected_nodes = g_list_prepend(affected_nodes, chosen);
330  }
331  }
332 
333  node_list_exclude(dependent->allowed_nodes, affected_nodes, FALSE);
334  g_list_free(affected_nodes);
335  return;
336  }
337 
338  gIter = primary->children;
339  for (; gIter != NULL; gIter = gIter->next) {
340  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
341 
342  child_rsc->cmds->apply_coloc_score(dependent, child_rsc, colocation,
343  false);
344  }
345 }
346 
347 // Clone implementation of resource_alloc_functions_t:with_this_colocations()
348 void
350  const pe_resource_t *orig_rsc, GList **list)
351 {
352  CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
353 
354  if (rsc == orig_rsc) { // Colocations are wanted for clone itself
356  } else {
357  pcmk__add_collective_constraints(list, orig_rsc, rsc, true);
358  }
359 }
360 
361 // Clone implementation of resource_alloc_functions_t:this_with_colocations()
362 void
364  const pe_resource_t *orig_rsc, GList **list)
365 {
366  CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
367 
368  if (rsc == orig_rsc) { // Colocations are wanted for clone itself
370  } else {
371  pcmk__add_collective_constraints(list, orig_rsc, rsc, false);
372  }
373 }
374 
375 enum pe_action_flags
377 {
378  return pcmk__collective_action_flags(action, action->rsc->children, node);
379 }
380 
381 void
383 {
384  GList *gIter = rsc->children;
385 
386  pe_rsc_trace(rsc, "Processing location constraint %s for %s", constraint->id, rsc->id);
387 
388  pcmk__apply_location(rsc, constraint);
389 
390  for (; gIter != NULL; gIter = gIter->next) {
391  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
392 
393  child_rsc->cmds->apply_location(child_rsc, constraint);
394  }
395 }
396 
403 void
405 {
406  GList *gIter = NULL;
407 
408  g_list_foreach(rsc->actions, (GFunc) rsc->cmds->action_flags, NULL);
409 
411 
412  /* Now that the notifcations have been created we can expand the children */
413 
414  gIter = rsc->children;
415  for (; gIter != NULL; gIter = gIter->next) {
416  pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
417 
418  child_rsc->cmds->add_actions_to_graph(child_rsc);
419  }
420 
422 
423  /* The notifications are in the graph now, we can destroy the notify_data */
425 }
426 
427 // Check whether a resource or any of its children is known on node
428 static bool
429 rsc_known_on(const pe_resource_t *rsc, const pe_node_t *node)
430 {
431  if (rsc->children) {
432  for (GList *child_iter = rsc->children; child_iter != NULL;
433  child_iter = child_iter->next) {
434 
435  pe_resource_t *child = (pe_resource_t *) child_iter->data;
436 
437  if (rsc_known_on(child, node)) {
438  return TRUE;
439  }
440  }
441 
442  } else if (rsc->known_on) {
443  GHashTableIter iter;
444  pe_node_t *known_node = NULL;
445 
446  g_hash_table_iter_init(&iter, rsc->known_on);
447  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &known_node)) {
448  if (node->details == known_node->details) {
449  return TRUE;
450  }
451  }
452  }
453  return FALSE;
454 }
455 
456 // Look for an instance of clone that is known on node
457 static pe_resource_t *
458 find_instance_on(const pe_resource_t *clone, const pe_node_t *node)
459 {
460  for (GList *gIter = clone->children; gIter != NULL; gIter = gIter->next) {
461  pe_resource_t *child = (pe_resource_t *) gIter->data;
462 
463  if (rsc_known_on(child, node)) {
464  return child;
465  }
466  }
467  return NULL;
468 }
469 
470 // For anonymous clones, only a single instance needs to be probed
471 static bool
472 probe_anonymous_clone(pe_resource_t *rsc, pe_node_t *node,
474 {
475  // First, check if we probed an instance on this node last time
476  pe_resource_t *child = find_instance_on(rsc, node);
477 
478  // Otherwise, check if we plan to start an instance on this node
479  if (child == NULL) {
480  for (GList *child_iter = rsc->children; child_iter && !child;
481  child_iter = child_iter->next) {
482 
483  pe_node_t *local_node = NULL;
484  pe_resource_t *child_rsc = (pe_resource_t *) child_iter->data;
485 
486  if (child_rsc) { /* make clang analyzer happy */
487  local_node = child_rsc->fns->location(child_rsc, NULL, FALSE);
488  if (local_node && (local_node->details == node->details)) {
489  child = child_rsc;
490  }
491  }
492  }
493  }
494 
495  // Otherwise, use the first clone instance
496  if (child == NULL) {
497  child = rsc->children->data;
498  }
499  CRM_ASSERT(child);
500  return child->cmds->create_probe(child, node);
501 }
502 
513 bool
515 {
516  CRM_ASSERT(rsc);
517 
518  rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance_number);
519  if (rsc->children == NULL) {
520  pe_warn("Clone %s has no children", rsc->id);
521  return false;
522  }
523 
524  if (rsc->exclusive_discover) {
525  pe_node_t *allowed = g_hash_table_lookup(rsc->allowed_nodes, node->details->id);
526  if (allowed && allowed->rsc_discover_mode != pe_discover_exclusive) {
527  /* exclusive discover is enabled and this node is not marked
528  * as a node this resource should be discovered on
529  *
530  * remove the node from allowed_nodes so that the
531  * notification contains only nodes that we might ever run
532  * on
533  */
534  g_hash_table_remove(rsc->allowed_nodes, node->details->id);
535 
536  /* Bit of a shortcut - might as well take it */
537  return false;
538  }
539  }
540 
541  if (pcmk_is_set(rsc->flags, pe_rsc_unique)) {
542  return pcmk__probe_resource_list(rsc->children, node);
543  } else {
544  return probe_anonymous_clone(rsc, node, rsc->cluster);
545  }
546 }
547 
548 void
549 clone_append_meta(const pe_resource_t *rsc, xmlNode *xml)
550 {
551  char *name = NULL;
552 
554  crm_xml_add(xml, name, pe__rsc_bool_str(rsc, pe_rsc_unique));
555  free(name);
556 
558  crm_xml_add(xml, name, pe__rsc_bool_str(rsc, pe_rsc_notify));
559  free(name);
560 
562  crm_xml_add_int(xml, name, pe__clone_max(rsc));
563  free(name);
564 
567  free(name);
568 
569  if (pcmk_is_set(rsc->flags, pe_rsc_promotable)) {
570  int promoted_max = pe__clone_promoted_max(rsc);
571  int promoted_node_max = pe__clone_promoted_node_max(rsc);
572 
574  crm_xml_add_int(xml, name, promoted_max);
575  free(name);
576 
578  crm_xml_add_int(xml, name, promoted_node_max);
579  free(name);
580 
581  /* @COMPAT Maintain backward compatibility with resource agents that
582  * expect the old names (deprecated since 2.0.0).
583  */
585  crm_xml_add_int(xml, name, promoted_max);
586  free(name);
587 
589  crm_xml_add_int(xml, name, promoted_node_max);
590  free(name);
591  }
592 }
593 
594 // Clone implementation of resource_alloc_functions_t:add_utilization()
595 void
597  const pe_resource_t *orig_rsc, GList *all_rscs,
598  GHashTable *utilization)
599 {
600  bool existing = false;
601  pe_resource_t *child = NULL;
602 
603  if (!pcmk_is_set(rsc->flags, pe_rsc_provisional)) {
604  return;
605  }
606 
607  // Look for any child already existing in the list
608  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
609  child = (pe_resource_t *) iter->data;
610  if (g_list_find(all_rscs, child)) {
611  existing = true; // Keep checking remaining children
612  } else {
613  // If this is a clone of a group, look for group's members
614  for (GList *member_iter = child->children; member_iter != NULL;
615  member_iter = member_iter->next) {
616 
617  pe_resource_t *member = (pe_resource_t *) member_iter->data;
618 
619  if (g_list_find(all_rscs, member) != NULL) {
620  // Add *child's* utilization, not group member's
621  child->cmds->add_utilization(child, orig_rsc, all_rscs,
622  utilization);
623  existing = true;
624  break;
625  }
626  }
627  }
628  }
629 
630  if (!existing && (rsc->children != NULL)) {
631  // If nothing was found, still add first child's utilization
632  child = (pe_resource_t *) rsc->children->data;
633 
634  child->cmds->add_utilization(child, orig_rsc, all_rscs, utilization);
635  }
636 }
637 
638 // Clone implementation of resource_alloc_functions_t:shutdown_lock()
639 void
641 {
642  return; // Clones currently don't support shutdown locks
643 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:235
#define PCMK_XA_PROMOTED_MAX_LEGACY
Definition: msg_xml.h:54
#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 crm_notice(fmt, args...)
Definition: logging.h:379
GHashTable * known_on
Definition: pe_types.h:399
G_GNUC_INTERNAL void pcmk__add_rsc_actions_to_graph(pe_resource_t *rsc)
#define pe_rsc_debug(rsc, fmt, args...)
Definition: internal.h:49
#define INFINITY
Definition: crm.h:99
GList * rsc_cons
Definition: pe_types.h:389
#define pe__show_node_weights(level, rsc, text, nodes, data_set)
Definition: internal.h:385
const char * name
Definition: cib.c:24
void(* internal_constraints)(pe_resource_t *rsc)
void pe__free_clone_notification_data(pe_resource_t *clone)
Definition: clone.c:1418
G_GNUC_INTERNAL pe_resource_t * pcmk__find_compatible_instance(const pe_resource_t *match_rsc, const pe_resource_t *rsc, enum rsc_role_e role, bool current)
GList * children
Definition: pe_types.h:409
resource_alloc_functions_t * cmds
Definition: pe_types.h:359
int pe__clone_promoted_max(const pe_resource_t *clone)
Definition: clone.c:96
#define pcmk__order_stops(rsc1, rsc2, flags)
void pcmk__clone_shutdown_lock(pe_resource_t *rsc)
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:398
gboolean exclusive_discover
Definition: pe_types.h:377
void clone_create_actions(pe_resource_t *rsc)
#define pcmk__config_err(fmt...)
GHashTable * meta
Definition: pe_types.h:405
#define pe_rsc_unique
Definition: pe_types.h:278
#define pe_rsc_notify
Definition: pe_types.h:277
G_GNUC_INTERNAL void pcmk__set_instance_roles(pe_resource_t *rsc)
resource_object_functions_t * fns
Definition: pe_types.h:358
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:302
pe_resource_t * dependent
void node_list_exclude(GHashTable *list, GList *list2, gboolean merge_scores)
Definition: utils.c:108
GList * rsc_cons_lhs
Definition: pe_types.h:388
#define RSC_START
Definition: crm.h:199
#define XML_RSC_ATTR_INCARNATION_MAX
Definition: msg_xml.h:242
void(* add_actions_to_graph)(pe_resource_t *rsc)
int pe__clone_max(const pe_resource_t *clone)
Definition: clone.c:62
void clone_internal_constraints(pe_resource_t *rsc)
char * crm_meta_name(const char *field)
Definition: utils.c:468
const char * action
Definition: pcmk_fence.c:30
void pcmk__clone_with_colocations(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)
#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 PCMK_XA_PROMOTED_NODE_MAX_LEGACY
Definition: msg_xml.h:55
#define pe_rsc_provisional
Definition: pe_types.h:282
pe_node_t *(* location)(const pe_resource_t *, GList **, int)
Definition: pe_types.h:55
#define pe_warn(fmt...)
Definition: internal.h:57
pe_action_flags
Definition: pe_types.h:316
int pe__clone_node_max(const pe_resource_t *clone)
Definition: clone.c:79
enum pe_action_flags clone_action_flags(pe_action_t *action, const pe_node_t *node)
pe_resource_t * primary
G_GNUC_INTERNAL void pcmk__order_promotable_instances(pe_resource_t *clone)
G_GNUC_INTERNAL bool pcmk__probe_resource_list(GList *rscs, pe_node_t *node)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:121
int pe__clone_promoted_node_max(const pe_resource_t *clone)
Definition: clone.c:113
struct pe_node_shared_s * details
Definition: pe_types.h:268
G_GNUC_INTERNAL gint pcmk__cmp_instance(gconstpointer a, gconstpointer b)
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition: utils.c:488
unsigned long long flags
Definition: pe_types.h:373
#define pe_rsc_promotable
Definition: pe_types.h:280
pe_working_set_t * data_set
GList * actions
Definition: pe_types.h:391
#define XML_RSC_ATTR_INCARNATION_NODEMAX
Definition: msg_xml.h:244
bool is_set_recursive(const pe_resource_t *rsc, long long flag, bool any)
Definition: clone.c:555
G_GNUC_INTERNAL void pcmk__add_with_this_list(GList **list, GList *addition)
G_GNUC_INTERNAL gint pcmk__cmp_instance_number(gconstpointer a, gconstpointer b)
#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
int rsc_discover_mode
Definition: pe_types.h:269
#define XML_RSC_ATTR_NOTIFY
Definition: msg_xml.h:251
const char * id
Definition: pe_types.h:231
#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)
#define XML_RSC_ATTR_UNIQUE
Definition: msg_xml.h:250
G_GNUC_INTERNAL void pcmk__update_dependent_with_promotable(const pe_resource_t *primary, pe_resource_t *dependent, const pcmk__colocation_t *colocation)
Update dependent for a colocation with a promotable clone.
G_GNUC_INTERNAL void pcmk__apply_location(pe_resource_t *rsc, pe__location_t *constraint)
#define XML_RSC_ATTR_PROMOTED_MAX
Definition: msg_xml.h:246
bool(* create_probe)(pe_resource_t *rsc, pe_node_t *node)
#define RSC_STARTED
Definition: crm.h:200
void pcmk__clone_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__add_dependent_scores(gpointer data, gpointer user_data)
#define CRM_ASSERT(expr)
Definition: results.h:42
void clone_rsc_location(pe_resource_t *rsc, pe__location_t *constraint)
bool pe__clone_is_ordered(const pe_resource_t *clone)
Definition: clone.c:1289
#define RSC_PROMOTE
Definition: crm.h:205
G_GNUC_INTERNAL void pcmk__create_promotable_actions(pe_resource_t *clone)
G_GNUC_INTERNAL void pcmk__update_promotable_dependent_priority(const pe_resource_t *primary, pe_resource_t *dependent, const pcmk__colocation_t *colocation)
G_GNUC_INTERNAL bool pcmk__assign_resource(pe_resource_t *rsc, pe_node_t *node, bool force)
G_GNUC_INTERNAL void pcmk__create_instance_actions(pe_resource_t *rsc, GList *instances)
pe_node_t * pcmk__clone_assign(pe_resource_t *rsc, const pe_node_t *prefer)
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:83
G_GNUC_INTERNAL void pcmk__add_promotion_scores(pe_resource_t *rsc)
void clone_expand(pe_resource_t *rsc)
#define XML_RSC_ATTR_PROMOTED_NODEMAX
Definition: msg_xml.h:247
#define pe_rsc_block
Definition: pe_types.h:274
enum pe_action_flags flags
Definition: pe_types.h:442
G_GNUC_INTERNAL void pcmk__assign_instances(pe_resource_t *collective, GList *instances, int max_total, int max_per_node)
pe_working_set_t * cluster
Definition: pe_types.h:353
#define RSC_STOPPED
Definition: crm.h:203
bool clone_create_probe(pe_resource_t *rsc, pe_node_t *node)
void pe__create_clone_notifications(pe_resource_t *clone)
Definition: clone.c:1399
gboolean crm_is_true(const char *s)
Definition: strings.c:416
void(* apply_location)(pe_resource_t *rsc, pe__location_t *location)
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:50
unsigned long long flags
Definition: pe_types.h:169
#define XML_RSC_ATTR_INTERLEAVE
Definition: msg_xml.h:240
GList * pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node, const char *task, bool require_node)
Find all actions of given type for a resource.
Definition: pe_actions.c:1400
G_GNUC_INTERNAL void pcmk__add_collective_constraints(GList **list, const pe_resource_t *instance, const pe_resource_t *collective, bool with_this)
#define pe_flag_show_scores
Definition: pe_types.h:150
void clone_append_meta(const pe_resource_t *rsc, xmlNode *xml)
void pcmk__clone_add_utilization(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
int copies_per_node(pe_resource_t *rsc)
char * id
Definition: pe_types.h:347
GHashTable * allowed_nodes
Definition: pe_types.h:400
G_GNUC_INTERNAL enum pe_action_flags pcmk__collective_action_flags(pe_action_t *action, const GList *instances, const pe_node_t *node)
void pcmk__with_clone_colocations(const pe_resource_t *rsc, const pe_resource_t *orig_rsc, GList **list)