pacemaker  3.0.0-d8340737c4
Scalable High-Availability cluster resource manager
pcmk_sched_clone.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2024 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU General Public License version 2
7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <crm/common/xml.h>
13 #include <pacemaker-internal.h>
14 
15 #include "libpacemaker_private.h"
16 
38  bool stop_if_fail)
39 {
40  GList *colocations = NULL;
41 
42  pcmk__assert(pcmk__is_clone(rsc));
43 
45  return NULL; // Assignment has already been done
46  }
47 
48  // Detect assignment loops
50  pcmk__rsc_debug(rsc, "Breaking assignment loop involving %s", rsc->id);
51  return NULL;
52  }
54 
55  // If this clone is promotable, consider nodes' promotion scores
58  }
59 
60  // If this clone is colocated with any other resources, assign those first
61  colocations = pcmk__this_with_colocations(rsc);
62  for (GList *iter = colocations; iter != NULL; iter = iter->next) {
63  pcmk__colocation_t *constraint = (pcmk__colocation_t *) iter->data;
64  pcmk_resource_t *primary = constraint->primary;
65 
66  pcmk__rsc_trace(rsc, "%s: Assigning colocation %s primary %s first",
67  rsc->id, constraint->id, primary->id);
68  primary->priv->cmds->assign(primary, prefer, stop_if_fail);
69  }
70  g_list_free(colocations);
71 
72  // If any resources are colocated with this one, consider their preferences
73  colocations = pcmk__with_this_colocations(rsc);
74  g_list_foreach(colocations, pcmk__add_dependent_scores, rsc);
75  g_list_free(colocations);
76 
79  rsc, __func__, rsc->priv->allowed_nodes,
80  rsc->priv->scheduler);
81 
82  rsc->priv->children = g_list_sort(rsc->priv->children, pcmk__cmp_instance);
84  pe__clone_node_max(rsc));
85 
88  }
89 
91  pcmk__rsc_trace(rsc, "Assigned clone %s", rsc->id);
92  return NULL;
93 }
94 
101 void
103 {
104  pcmk__assert(pcmk__is_clone(rsc));
105 
106  pcmk__rsc_trace(rsc, "Creating actions for clone %s", rsc->id);
110  }
111 }
112 
119 void
121 {
122  bool ordered = false;
123 
124  pcmk__assert(pcmk__is_clone(rsc));
125 
126  pcmk__rsc_trace(rsc, "Creating internal constraints for clone %s", rsc->id);
127 
128  // Restart ordering: Stop -> stopped -> start -> started
130  rsc, PCMK_ACTION_START,
133  rsc, PCMK_ACTION_RUNNING,
136  rsc, PCMK_ACTION_STOPPED,
138 
139  // Demoted -> stop and started -> promote
142  rsc, PCMK_ACTION_STOP,
145  rsc, PCMK_ACTION_PROMOTE,
147  }
148 
149  ordered = pe__clone_is_ordered(rsc);
150  if (ordered) {
151  /* Ordered clone instances must start and stop by instance number. The
152  * instances might have been previously shuffled for assignment or
153  * promotion purposes, so re-sort them.
154  */
155  rsc->priv->children = g_list_sort(rsc->priv->children,
157  }
158  for (GList *iter = rsc->priv->children;
159  iter != NULL; iter = iter->next) {
160 
161  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
162 
163  instance->priv->cmds->internal_constraints(instance);
164 
165  // Start clone -> start instance -> clone started
169  rsc, PCMK_ACTION_RUNNING,
171 
172  // Stop clone -> stop instance -> clone stopped
175  rsc, PCMK_ACTION_STOPPED,
177 
178  /* Instances of ordered clones must be started and stopped by instance
179  * number. Since only some instances may be starting or stopping, order
180  * each instance relative to every later instance.
181  */
182  if (ordered) {
183  for (GList *later = iter->next;
184  later != NULL; later = later->next) {
185  pcmk__order_starts(instance, (pcmk_resource_t *) later->data,
187  pcmk__order_stops((pcmk_resource_t *) later->data, instance,
189  }
190  }
191  }
194  }
195 }
196 
205 static bool
206 can_interleave(const pcmk__colocation_t *colocation)
207 {
208  const pcmk_resource_t *primary = colocation->primary;
209  const pcmk_resource_t *dependent = colocation->dependent;
210 
211  // Only colocations between clone or bundle resources use interleaving
212  if (dependent->priv->variant <= pcmk__rsc_variant_group) {
213  return false;
214  }
215 
216  // Only the dependent needs to be marked for interleaving
217  if (!crm_is_true(g_hash_table_lookup(dependent->priv->meta,
219  return false;
220  }
221 
222  /* @TODO Do we actually care about multiple primary instances sharing a
223  * dependent instance?
224  */
225  if (dependent->priv->fns->max_per_node(dependent)
226  != primary->priv->fns->max_per_node(primary)) {
227  pcmk__config_err("Cannot interleave %s and %s because they do not "
228  "support the same number of instances per node",
229  dependent->id, primary->id);
230  return false;
231  }
232 
233  return true;
234 }
235 
251 int
253  const pcmk_resource_t *primary,
254  const pcmk__colocation_t *colocation,
255  bool for_dependent)
256 {
257  const GList *iter = NULL;
258  int priority_delta = 0;
259 
260  /* This should never be called for the clone itself as a dependent. Instead,
261  * we add its colocation constraints to its instances and call the
262  * apply_coloc_score() method for the instances as dependents.
263  */
264  pcmk__assert(!for_dependent && (colocation != NULL)
265  && pcmk__is_clone(primary) && pcmk__is_primitive(dependent));
266 
267  if (pcmk_is_set(primary->flags, pcmk__rsc_unassigned)) {
268  pcmk__rsc_trace(primary,
269  "Delaying processing colocation %s "
270  "because cloned primary %s is still provisional",
271  colocation->id, primary->id);
272  return 0;
273  }
274 
275  pcmk__rsc_trace(primary, "Processing colocation %s (%s with clone %s @%s)",
276  colocation->id, dependent->id, primary->id,
277  pcmk_readable_score(colocation->score));
278 
279  // Apply role-specific colocations
280  if (pcmk_is_set(primary->flags, pcmk__rsc_promotable)
281  && (colocation->primary_role != pcmk_role_unknown)) {
282 
283  if (pcmk_is_set(dependent->flags, pcmk__rsc_unassigned)) {
284  // We're assigning the dependent to a node
285  pcmk__update_dependent_with_promotable(primary, dependent,
286  colocation);
287  return 0;
288  }
289 
290  if (colocation->dependent_role == pcmk_role_promoted) {
291  // We're choosing a role for the dependent
293  dependent,
294  colocation);
295  }
296  }
297 
298  // Apply interleaved colocations
299  if (can_interleave(colocation)) {
300  const pcmk_resource_t *primary_instance = NULL;
301 
302  primary_instance = pcmk__find_compatible_instance(dependent, primary,
304  false);
305  if (primary_instance != NULL) {
306  pcmk__rsc_debug(primary, "Interleaving %s with %s",
307  dependent->id, primary_instance->id);
308 
309  return dependent->priv->cmds->apply_coloc_score(dependent,
310  primary_instance,
311  colocation, true);
312  }
313 
314  if (colocation->score >= PCMK_SCORE_INFINITY) {
315  crm_notice("%s cannot run because it cannot interleave with "
316  "any instance of %s", dependent->id, primary->id);
317  pcmk__assign_resource(dependent, NULL, true, true);
318 
319  } else {
320  pcmk__rsc_debug(primary,
321  "%s will not colocate with %s "
322  "because no instance can interleave with it",
323  dependent->id, primary->id);
324  }
325 
326  return 0;
327  }
328 
329  // Apply mandatory colocations
330  if (colocation->score >= PCMK_SCORE_INFINITY) {
331  GList *primary_nodes = NULL;
332 
333  // Dependent can run only where primary will have unblocked instances
334  for (iter = primary->priv->children;
335  iter != NULL; iter = iter->next) {
336 
337  const pcmk_resource_t *instance = iter->data;
338  pcmk_node_t *chosen = NULL;
339 
340  chosen = instance->priv->fns->location(instance, NULL,
342  if ((chosen != NULL)
343  && !is_set_recursive(instance, pcmk__rsc_blocked, TRUE)) {
344  pcmk__rsc_trace(primary, "Allowing %s: %s %d",
345  colocation->id, pcmk__node_name(chosen),
346  chosen->assign->score);
347  primary_nodes = g_list_prepend(primary_nodes, chosen);
348  }
349  }
350  pcmk__colocation_intersect_nodes(dependent, primary, colocation,
351  primary_nodes, false);
352  g_list_free(primary_nodes);
353  return 0;
354  }
355 
356  // Apply optional colocations
357  for (iter = primary->priv->children; iter != NULL; iter = iter->next) {
358  const pcmk_resource_t *instance = iter->data;
359  int instance_delta = instance->priv->cmds->apply_coloc_score(dependent,
360  instance,
361  colocation,
362  false);
363 
364  priority_delta = pcmk__add_scores(priority_delta, instance_delta);
365  }
366  return priority_delta;
367 }
368 
369 // Clone implementation of pcmk__assignment_methods_t:with_this_colocations()
370 void
372  const pcmk_resource_t *orig_rsc, GList **list)
373 {
374  const pcmk_resource_t *parent = NULL;
375 
376  CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
377  parent = rsc->priv->parent;
378 
380  orig_rsc);
381 
382  if (parent != NULL) {
383  parent->priv->cmds->with_this_colocations(parent, orig_rsc, list);
384  }
385 }
386 
387 // Clone implementation of pcmk__assignment_methods_t:this_with_colocations()
388 void
390  const pcmk_resource_t *orig_rsc, GList **list)
391 {
392  const pcmk_resource_t *parent = NULL;
393 
394  CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
395  parent = rsc->priv->parent;
396 
398  orig_rsc);
399 
400  if (parent != NULL) {
401  parent->priv->cmds->this_with_colocations(parent, orig_rsc, list);
402  }
403 }
404 
414 uint32_t
416 {
417  pcmk__assert((action != NULL) && pcmk__is_clone(action->rsc));
418 
419  return pcmk__collective_action_flags(action, action->rsc->priv->children,
420  node);
421 }
422 
430 void
432 {
433  CRM_CHECK((location != NULL) && pcmk__is_clone(rsc), return);
434 
435  pcmk__apply_location(rsc, location);
436 
437  for (GList *iter = rsc->priv->children;
438  iter != NULL; iter = iter->next) {
439 
440  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
441 
442  instance->priv->cmds->apply_location(instance, location);
443  }
444 }
445 
446 // GFunc wrapper for calling the action_flags() resource method
447 static void
448 call_action_flags(gpointer data, gpointer user_data)
449 {
450  pcmk_resource_t *rsc = user_data;
451 
452  rsc->priv->cmds->action_flags((pcmk_action_t *) data, NULL);
453 }
454 
461 void
463 {
464  pcmk__assert(pcmk__is_clone(rsc));
465 
466  g_list_foreach(rsc->priv->actions, call_action_flags, rsc);
468 
469  for (GList *iter = rsc->priv->children;
470  iter != NULL; iter = iter->next) {
471 
472  pcmk_resource_t *child_rsc = (pcmk_resource_t *) iter->data;
473 
474  child_rsc->priv->cmds->add_actions_to_graph(child_rsc);
475  }
476 
479 }
480 
491 static bool
492 rsc_probed_on(const pcmk_resource_t *rsc, const pcmk_node_t *node)
493 {
494  if (rsc->priv->children != NULL) {
495  for (GList *child_iter = rsc->priv->children;
496  child_iter != NULL; child_iter = child_iter->next) {
497 
498  pcmk_resource_t *child = (pcmk_resource_t *) child_iter->data;
499 
500  if (rsc_probed_on(child, node)) {
501  return true;
502  }
503  }
504  return false;
505  }
506 
507  if (rsc->priv->probed_nodes != NULL) {
508  GHashTableIter iter;
509  pcmk_node_t *known_node = NULL;
510 
511  g_hash_table_iter_init(&iter, rsc->priv->probed_nodes);
512  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &known_node)) {
513  if (pcmk__same_node(node, known_node)) {
514  return true;
515  }
516  }
517  }
518  return false;
519 }
520 
531 static pcmk_resource_t *
532 find_probed_instance_on(const pcmk_resource_t *clone, const pcmk_node_t *node)
533 {
534  for (GList *iter = clone->priv->children;
535  iter != NULL; iter = iter->next) {
536 
537  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
538 
539  if (rsc_probed_on(instance, node)) {
540  return instance;
541  }
542  }
543  return NULL;
544 }
545 
553 static bool
554 probe_anonymous_clone(pcmk_resource_t *clone, pcmk_node_t *node)
555 {
556  // Check whether we already probed an instance on this node
557  pcmk_resource_t *child = find_probed_instance_on(clone, node);
558 
559  // Otherwise, check if we plan to start an instance on this node
560  for (GList *iter = clone->priv->children;
561  (iter != NULL) && (child == NULL); iter = iter->next) {
562 
563  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
564  const pcmk_node_t *instance_node = NULL;
565 
566  instance_node = instance->priv->fns->location(instance, NULL,
568  if (pcmk__same_node(instance_node, node)) {
569  child = instance;
570  }
571  }
572 
573  // Otherwise, use the first clone instance
574  if (child == NULL) {
575  child = clone->priv->children->data;
576  }
577 
578  // Anonymous clones only need to probe a single instance
579  return child->priv->cmds->create_probe(child, node);
580 }
581 
591 bool
593 {
594  pcmk__assert((node != NULL) && pcmk__is_clone(rsc));
595 
597  /* The clone is configured to be probed only where a location constraint
598  * exists with PCMK_XA_RESOURCE_DISCOVERY set to exclusive.
599  *
600  * This check is not strictly necessary here since the instance's
601  * create_probe() method would also check, but doing it here is more
602  * efficient (especially for unique clones with a large number of
603  * instances), and affects the CRM_meta_notify_available_uname variable
604  * passed with notify actions.
605  */
606  pcmk_node_t *allowed = g_hash_table_lookup(rsc->priv->allowed_nodes,
607  node->priv->id);
608 
609  if ((allowed == NULL)
610  || (allowed->assign->probe_mode != pcmk__probe_exclusive)) {
611  /* This node is not marked for resource discovery. Remove it from
612  * allowed nodes so that notifications contain only nodes that the
613  * clone can possibly run on.
614  */
615  pcmk__rsc_trace(rsc,
616  "Skipping probe for %s on %s because resource has "
617  "exclusive discovery but is not allowed on node",
618  rsc->id, pcmk__node_name(node));
619  g_hash_table_remove(rsc->priv->allowed_nodes, node->priv->id);
620  return false;
621  }
622  }
623 
624  rsc->priv->children = g_list_sort(rsc->priv->children,
626  if (pcmk_is_set(rsc->flags, pcmk__rsc_unique)) {
627  return pcmk__probe_resource_list(rsc->priv->children, node);
628  } else {
629  return probe_anonymous_clone(rsc, node);
630  }
631 }
632 
642 void
644 {
645  char *name = NULL;
646 
647  pcmk__assert(pcmk__is_clone(rsc) && (xml != NULL));
648 
650  crm_xml_add(xml, name, pcmk__flag_text(rsc->flags, pcmk__rsc_unique));
651  free(name);
652 
654  crm_xml_add(xml, name, pcmk__flag_text(rsc->flags, pcmk__rsc_notify));
655  free(name);
656 
658  crm_xml_add_int(xml, name, pe__clone_max(rsc));
659  free(name);
660 
663  free(name);
664 
666  int promoted_max = pe__clone_promoted_max(rsc);
667  int promoted_node_max = pe__clone_promoted_node_max(rsc);
668 
670  crm_xml_add_int(xml, name, promoted_max);
671  free(name);
672 
674  crm_xml_add_int(xml, name, promoted_node_max);
675  free(name);
676 
677  /* @COMPAT Maintain backward compatibility with resource agents that
678  * expect the old names (deprecated since 2.0.0).
679  */
681  crm_xml_add_int(xml, name, promoted_max);
682  free(name);
683 
685  crm_xml_add_int(xml, name, promoted_node_max);
686  free(name);
687  }
688 }
689 
690 // Clone implementation of pcmk__assignment_methods_t:add_utilization()
691 void
693  const pcmk_resource_t *orig_rsc, GList *all_rscs,
694  GHashTable *utilization)
695 {
696  bool existing = false;
697  pcmk_resource_t *child = NULL;
698 
699  pcmk__assert(pcmk__is_clone(rsc) && (orig_rsc != NULL)
700  && (utilization != NULL));
701 
702  if (!pcmk_is_set(rsc->flags, pcmk__rsc_unassigned)) {
703  return;
704  }
705 
706  // Look for any child already existing in the list
707  for (GList *iter = rsc->priv->children;
708  iter != NULL; iter = iter->next) {
709 
710  child = (pcmk_resource_t *) iter->data;
711  if (g_list_find(all_rscs, child)) {
712  existing = true; // Keep checking remaining children
713  } else {
714  // If this is a clone of a group, look for group's members
715  for (GList *member_iter = child->priv->children;
716  member_iter != NULL; member_iter = member_iter->next) {
717 
718  pcmk_resource_t *member = (pcmk_resource_t *) member_iter->data;
719 
720  if (g_list_find(all_rscs, member) != NULL) {
721  // Add *child's* utilization, not group member's
722  child->priv->cmds->add_utilization(child, orig_rsc,
723  all_rscs, utilization);
724  existing = true;
725  break;
726  }
727  }
728  }
729  }
730 
731  if (!existing && (rsc->priv->children != NULL)) {
732  // If nothing was found, still add first child's utilization
733  child = (pcmk_resource_t *) rsc->priv->children->data;
734 
735  child->priv->cmds->add_utilization(child, orig_rsc, all_rscs,
736  utilization);
737  }
738 }
739 
740 // Clone implementation of pcmk__assignment_methods_t:shutdown_lock()
741 void
743 {
744  pcmk__assert(pcmk__is_clone(rsc));
745  return; // Clones currently don't support shutdown locks
746 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:213
enum pcmk__probe_mode probe_mode
#define pcmk__order_starts(rsc1, rsc2, flags)
void pcmk__clone_with_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
G_GNUC_INTERNAL uint32_t pcmk__collective_action_flags(pcmk_action_t *action, const GList *instances, const pcmk_node_t *node)
#define crm_notice(fmt, args...)
Definition: logging.h:365
&#39;then&#39; is runnable (and migratable) only if &#39;first&#39; is runnable
G_GNUC_INTERNAL void pcmk__apply_location(pcmk_resource_t *rsc, pcmk__location_t *constraint)
char data[0]
Definition: cpg.c:58
pcmk_resource_t * parent
const char * name
Definition: cib.c:26
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition: scores.c:102
G_GNUC_INTERNAL bool pcmk__probe_resource_list(GList *rscs, pcmk_node_t *node)
#define pcmk__rsc_trace(rsc, fmt, args...)
#define pcmk__order_stops(rsc1, rsc2, flags)
uint32_t pcmk__clone_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
#define pcmk__set_rsc_flags(resource, flags_to_set)
#define pcmk__config_err(fmt...)
G_GNUC_INTERNAL pcmk_resource_t * pcmk__find_compatible_instance(const pcmk_resource_t *match_rsc, const pcmk_resource_t *rsc, enum rsc_role_e role, bool current)
G_GNUC_INTERNAL void pcmk__order_promotable_instances(pcmk_resource_t *clone)
G_GNUC_INTERNAL void pcmk__create_instance_actions(pcmk_resource_t *rsc, GList *instances)
int pe__clone_max(const pcmk_resource_t *clone)
Definition: clone.c:56
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, uint32_t target)
void(* add_utilization)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
#define PCMK_META_INTERLEAVE
Definition: options.h:90
Promoted.
Definition: roles.h:39
uint64_t flags
Definition: scheduler.h:89
int pcmk__clone_apply_coloc_score(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
G_GNUC_INTERNAL void pcmk__create_promotable_actions(pcmk_resource_t *clone)
#define PCMK_META_CLONE_MAX
Definition: options.h:82
const pcmk__rsc_methods_t * fns
void(* add_actions_to_graph)(pcmk_resource_t *rsc)
void(* internal_constraints)(pcmk_resource_t *rsc)
const char * action
Definition: pcmk_fence.c:32
G_GNUC_INTERNAL bool pcmk__assign_resource(pcmk_resource_t *rsc, pcmk_node_t *node, bool force, bool stop_if_fail)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: xml_element.c:1015
#define pcmk__rsc_debug(rsc, fmt, args...)
pcmk__node_private_t * priv
Definition: nodes.h:85
void pcmk__clone_shutdown_lock(pcmk_resource_t *rsc)
#define PCMK__META_PROMOTED_NODE_MAX_LEGACY
#define PCMK_META_GLOBALLY_UNIQUE
Definition: options.h:89
G_GNUC_INTERNAL void pcmk__add_with_this_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
pcmk_scheduler_t * scheduler
Actions are ordered (optionally, if no other flags are set)
#define PCMK_META_CLONE_NODE_MAX
Definition: options.h:84
enum pcmk__rsc_variant variant
G_GNUC_INTERNAL void pcmk__set_instance_roles(pcmk_resource_t *rsc)
G_GNUC_INTERNAL int pcmk__update_promotable_dependent_priority(const pcmk_resource_t *primary, pcmk_resource_t *dependent, const pcmk__colocation_t *colocation)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:80
G_GNUC_INTERNAL void pcmk__add_promotion_scores(pcmk_resource_t *rsc)
void(* apply_location)(pcmk_resource_t *rsc, pcmk__location_t *location)
#define PCMK_ACTION_START
Definition: actions.h:63
pcmk__resource_private_t * priv
Definition: resources.h:61
G_GNUC_INTERNAL gint pcmk__cmp_instance(gconstpointer a, gconstpointer b)
Wrappers for and extensions to libxml2.
#define PCMK__META_PROMOTED_MAX_LEGACY
#define PCMK_ACTION_STOP
Definition: actions.h:66
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
void pcmk__clone_create_actions(pcmk_resource_t *rsc)
bool(* create_probe)(pcmk_resource_t *rsc, pcmk_node_t *node)
G_GNUC_INTERNAL void pcmk__assign_instances(pcmk_resource_t *collective, GList *instances, int max_total, int max_per_node)
G_GNUC_INTERNAL gint pcmk__cmp_instance_number(gconstpointer a, gconstpointer b)
int pcmk__add_scores(int score1, int score2)
Definition: scores.c:159
bool is_set_recursive(const pcmk_resource_t *rsc, long long flag, bool any)
Definition: clone.c:497
int pe__clone_promoted_node_max(const pcmk_resource_t *clone)
Definition: clone.c:107
int pe__clone_promoted_max(const pcmk_resource_t *clone)
Definition: clone.c:90
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
pcmk_resource_t * primary
#define pcmk__assert(expr)
G_GNUC_INTERNAL void pcmk__add_rsc_actions_to_graph(pcmk_resource_t *rsc)
pcmk_node_t * pcmk__clone_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
#define PCMK_META_NOTIFY
Definition: options.h:97
G_GNUC_INTERNAL void pcmk__update_dependent_with_promotable(const pcmk_resource_t *primary, pcmk_resource_t *dependent, const pcmk__colocation_t *colocation)
Update dependent for a colocation with a promotable clone.
uint32_t(* action_flags)(pcmk_action_t *action, const pcmk_node_t *node)
If &#39;then&#39; is required, &#39;first&#39; must be added to the transition graph.
void pe__create_clone_notifications(pcmk_resource_t *clone)
Definition: clone.c:1167
G_GNUC_INTERNAL GList * pcmk__with_this_colocations(const pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__add_dependent_scores(gpointer data, gpointer user_data)
void pcmk__clone_add_utilization(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
void pe__free_clone_notification_data(pcmk_resource_t *clone)
Definition: clone.c:1186
G_GNUC_INTERNAL void pcmk__add_this_with_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
void pcmk__clone_add_graph_meta(const pcmk_resource_t *rsc, xmlNode *xml)
#define PCMK_META_PROMOTED_NODE_MAX
Definition: options.h:103
If &#39;first&#39; is required and runnable, &#39;then&#39; must be in graph.
#define PCMK_ACTION_STOPPED
Definition: actions.h:67
G_GNUC_INTERNAL GList * pcmk__this_with_colocations(const pcmk_resource_t *rsc)
void pcmk__clone_add_actions_to_graph(pcmk_resource_t *rsc)
void pcmk__with_clone_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
#define PCMK_ACTION_PROMOTE
Definition: actions.h:57
pcmk_resource_t * dependent
gboolean crm_is_true(const char *s)
Definition: strings.c:490
#define pe__show_node_scores(level, rsc, text, nodes, scheduler)
Definition: internal.h:164
#define PCMK_META_PROMOTED_MAX
Definition: options.h:102
int pe__clone_node_max(const pcmk_resource_t *clone)
Definition: clone.c:73
unsigned long long flags
Definition: resources.h:69
Resource role is unknown.
Definition: roles.h:35
Location constraint object.
bool pe__clone_is_ordered(const pcmk_resource_t *clone)
Definition: clone.c:1041
#define PCMK_ACTION_RUNNING
Definition: actions.h:62
const char * parent
Definition: cib.c:27
unsigned int(* max_per_node)(const pcmk_resource_t *rsc)
#define PCMK_ACTION_DEMOTED
Definition: actions.h:41
int(* apply_coloc_score)(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
void pcmk__clone_apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
G_GNUC_INTERNAL void pcmk__colocation_intersect_nodes(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, const GList *primary_nodes, bool merge_scores)
const pcmk__assignment_methods_t * cmds
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:26
bool pcmk__clone_create_probe(pcmk_resource_t *rsc, pcmk_node_t *node)
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: xml_element.c:1070
void pcmk__clone_internal_constraints(pcmk_resource_t *rsc)
char * crm_meta_name(const char *field)
Get the environment variable equivalent of a meta-attribute name.
Definition: nvpair.c:407
struct pcmk__node_assignment * assign
Definition: nodes.h:79