pacemaker  2.1.8-3980678f03
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  CRM_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 
65  pcmk__rsc_trace(rsc, "%s: Assigning colocation %s primary %s first",
66  rsc->id, constraint->id, constraint->primary->id);
67  constraint->primary->cmds->assign(constraint->primary, prefer,
68  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->allowed_nodes, rsc->cluster);
80 
81  rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance);
83  pe__clone_node_max(rsc));
84 
87  }
88 
90  pcmk__rsc_trace(rsc, "Assigned clone %s", rsc->id);
91  return NULL;
92 }
93 
100 void
102 {
103  CRM_ASSERT(pcmk__is_clone(rsc));
104 
105  pcmk__rsc_trace(rsc, "Creating actions for clone %s", rsc->id);
109  }
110 }
111 
118 void
120 {
121  bool ordered = false;
122 
123  CRM_ASSERT(pcmk__is_clone(rsc));
124 
125  pcmk__rsc_trace(rsc, "Creating internal constraints for clone %s", rsc->id);
126 
127  // Restart ordering: Stop -> stopped -> start -> started
129  rsc, PCMK_ACTION_START,
132  rsc, PCMK_ACTION_RUNNING,
135  rsc, PCMK_ACTION_STOPPED,
137 
138  // Demoted -> stop and started -> promote
141  rsc, PCMK_ACTION_STOP,
144  rsc, PCMK_ACTION_PROMOTE,
146  }
147 
148  ordered = pe__clone_is_ordered(rsc);
149  if (ordered) {
150  /* Ordered clone instances must start and stop by instance number. The
151  * instances might have been previously shuffled for assignment or
152  * promotion purposes, so re-sort them.
153  */
154  rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance_number);
155  }
156  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
157  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
158 
159  instance->cmds->internal_constraints(instance);
160 
161  // Start clone -> start instance -> clone started
165  rsc, PCMK_ACTION_RUNNING,
167 
168  // Stop clone -> stop instance -> clone stopped
171  rsc, PCMK_ACTION_STOPPED,
173 
174  /* Instances of ordered clones must be started and stopped by instance
175  * number. Since only some instances may be starting or stopping, order
176  * each instance relative to every later instance.
177  */
178  if (ordered) {
179  for (GList *later = iter->next;
180  later != NULL; later = later->next) {
181  pcmk__order_starts(instance, (pcmk_resource_t *) later->data,
183  pcmk__order_stops((pcmk_resource_t *) later->data, instance,
185  }
186  }
187  }
190  }
191 }
192 
201 static bool
202 can_interleave(const pcmk__colocation_t *colocation)
203 {
204  const pcmk_resource_t *dependent = colocation->dependent;
205 
206  // Only colocations between clone or bundle resources use interleaving
207  if (dependent->variant <= pcmk_rsc_variant_group) {
208  return false;
209  }
210 
211  // Only the dependent needs to be marked for interleaving
212  if (!crm_is_true(g_hash_table_lookup(dependent->meta,
214  return false;
215  }
216 
217  /* @TODO Do we actually care about multiple primary instances sharing a
218  * dependent instance?
219  */
220  if (dependent->fns->max_per_node(dependent)
221  != colocation->primary->fns->max_per_node(colocation->primary)) {
222  pcmk__config_err("Cannot interleave %s and %s because they do not "
223  "support the same number of instances per node",
224  dependent->id, colocation->primary->id);
225  return false;
226  }
227 
228  return true;
229 }
230 
246 int
248  const pcmk_resource_t *primary,
249  const pcmk__colocation_t *colocation,
250  bool for_dependent)
251 {
252  const GList *iter = NULL;
253  int priority_delta = 0;
254 
255  /* This should never be called for the clone itself as a dependent. Instead,
256  * we add its colocation constraints to its instances and call the
257  * apply_coloc_score() method for the instances as dependents.
258  */
259  CRM_ASSERT(!for_dependent);
260 
261  CRM_ASSERT((colocation != NULL) && pcmk__is_clone(primary)
262  && pcmk__is_primitive(dependent));
263 
264  if (pcmk_is_set(primary->flags, pcmk_rsc_unassigned)) {
265  pcmk__rsc_trace(primary,
266  "Delaying processing colocation %s "
267  "because cloned primary %s is still provisional",
268  colocation->id, primary->id);
269  return 0;
270  }
271 
272  pcmk__rsc_trace(primary, "Processing colocation %s (%s with clone %s @%s)",
273  colocation->id, dependent->id, primary->id,
274  pcmk_readable_score(colocation->score));
275 
276  // Apply role-specific colocations
277  if (pcmk_is_set(primary->flags, pcmk_rsc_promotable)
278  && (colocation->primary_role != pcmk_role_unknown)) {
279 
280  if (pcmk_is_set(dependent->flags, pcmk_rsc_unassigned)) {
281  // We're assigning the dependent to a node
282  pcmk__update_dependent_with_promotable(primary, dependent,
283  colocation);
284  return 0;
285  }
286 
287  if (colocation->dependent_role == pcmk_role_promoted) {
288  // We're choosing a role for the dependent
290  dependent,
291  colocation);
292  }
293  }
294 
295  // Apply interleaved colocations
296  if (can_interleave(colocation)) {
297  const pcmk_resource_t *primary_instance = NULL;
298 
299  primary_instance = pcmk__find_compatible_instance(dependent, primary,
301  false);
302  if (primary_instance != NULL) {
303  pcmk__rsc_debug(primary, "Interleaving %s with %s",
304  dependent->id, primary_instance->id);
305 
306  return dependent->cmds->apply_coloc_score(dependent,
307  primary_instance,
308  colocation, true);
309  }
310 
311  if (colocation->score >= PCMK_SCORE_INFINITY) {
312  crm_notice("%s cannot run because it cannot interleave with "
313  "any instance of %s", dependent->id, primary->id);
314  pcmk__assign_resource(dependent, NULL, true, true);
315 
316  } else {
317  pcmk__rsc_debug(primary,
318  "%s will not colocate with %s "
319  "because no instance can interleave with it",
320  dependent->id, primary->id);
321  }
322 
323  return 0;
324  }
325 
326  // Apply mandatory colocations
327  if (colocation->score >= PCMK_SCORE_INFINITY) {
328  GList *primary_nodes = NULL;
329 
330  // Dependent can run only where primary will have unblocked instances
331  for (iter = primary->children; iter != NULL; iter = iter->next) {
332  const pcmk_resource_t *instance = iter->data;
333  pcmk_node_t *chosen = instance->fns->location(instance, NULL, 0);
334 
335  if ((chosen != NULL)
336  && !is_set_recursive(instance, pcmk_rsc_blocked, TRUE)) {
337  pcmk__rsc_trace(primary, "Allowing %s: %s %d",
338  colocation->id, pcmk__node_name(chosen),
339  chosen->weight);
340  primary_nodes = g_list_prepend(primary_nodes, chosen);
341  }
342  }
343  pcmk__colocation_intersect_nodes(dependent, primary, colocation,
344  primary_nodes, false);
345  g_list_free(primary_nodes);
346  return 0;
347  }
348 
349  // Apply optional colocations
350  for (iter = primary->children; iter != NULL; iter = iter->next) {
351  const pcmk_resource_t *instance = iter->data;
352  int instance_delta = instance->cmds->apply_coloc_score(dependent,
353  instance,
354  colocation,
355  false);
356 
357  priority_delta = pcmk__add_scores(priority_delta, instance_delta);
358  }
359  return priority_delta;
360 }
361 
362 // Clone implementation of pcmk_assignment_methods_t:with_this_colocations()
363 void
365  const pcmk_resource_t *orig_rsc, GList **list)
366 {
367  CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
368 
369  pcmk__add_with_this_list(list, rsc->rsc_cons_lhs, orig_rsc);
370 
371  if (rsc->parent != NULL) {
372  rsc->parent->cmds->with_this_colocations(rsc->parent, orig_rsc, list);
373  }
374 }
375 
376 // Clone implementation of pcmk_assignment_methods_t:this_with_colocations()
377 void
379  const pcmk_resource_t *orig_rsc, GList **list)
380 {
381  CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
382 
383  pcmk__add_this_with_list(list, rsc->rsc_cons, orig_rsc);
384 
385  if (rsc->parent != NULL) {
386  rsc->parent->cmds->this_with_colocations(rsc->parent, orig_rsc, list);
387  }
388 }
389 
399 uint32_t
401 {
402  CRM_ASSERT((action != NULL) && pcmk__is_clone(action->rsc));
403 
404  return pcmk__collective_action_flags(action, action->rsc->children, node);
405 }
406 
414 void
416 {
417  CRM_CHECK((location != NULL) && pcmk__is_clone(rsc), return);
418 
419  pcmk__apply_location(rsc, location);
420 
421  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
422  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
423 
424  instance->cmds->apply_location(instance, location);
425  }
426 }
427 
428 // GFunc wrapper for calling the action_flags() resource method
429 static void
430 call_action_flags(gpointer data, gpointer user_data)
431 {
432  pcmk_resource_t *rsc = user_data;
433 
434  rsc->cmds->action_flags((pcmk_action_t *) data, NULL);
435 }
436 
443 void
445 {
446  CRM_ASSERT(pcmk__is_clone(rsc));
447 
448  g_list_foreach(rsc->actions, call_action_flags, rsc);
450 
451  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
452  pcmk_resource_t *child_rsc = (pcmk_resource_t *) iter->data;
453 
454  child_rsc->cmds->add_actions_to_graph(child_rsc);
455  }
456 
459 }
460 
471 static bool
472 rsc_probed_on(const pcmk_resource_t *rsc, const pcmk_node_t *node)
473 {
474  if (rsc->children != NULL) {
475  for (GList *child_iter = rsc->children; child_iter != NULL;
476  child_iter = child_iter->next) {
477 
478  pcmk_resource_t *child = (pcmk_resource_t *) child_iter->data;
479 
480  if (rsc_probed_on(child, node)) {
481  return true;
482  }
483  }
484  return false;
485  }
486 
487  if (rsc->known_on != NULL) {
488  GHashTableIter iter;
489  pcmk_node_t *known_node = NULL;
490 
491  g_hash_table_iter_init(&iter, rsc->known_on);
492  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &known_node)) {
493  if (pcmk__same_node(node, known_node)) {
494  return true;
495  }
496  }
497  }
498  return false;
499 }
500 
511 static pcmk_resource_t *
512 find_probed_instance_on(const pcmk_resource_t *clone, const pcmk_node_t *node)
513 {
514  for (GList *iter = clone->children; iter != NULL; iter = iter->next) {
515  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
516 
517  if (rsc_probed_on(instance, node)) {
518  return instance;
519  }
520  }
521  return NULL;
522 }
523 
531 static bool
532 probe_anonymous_clone(pcmk_resource_t *clone, pcmk_node_t *node)
533 {
534  // Check whether we already probed an instance on this node
535  pcmk_resource_t *child = find_probed_instance_on(clone, node);
536 
537  // Otherwise, check if we plan to start an instance on this node
538  for (GList *iter = clone->children; (iter != NULL) && (child == NULL);
539  iter = iter->next) {
540  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
541  const pcmk_node_t *instance_node = NULL;
542 
543  instance_node = instance->fns->location(instance, NULL, 0);
544  if (pcmk__same_node(instance_node, node)) {
545  child = instance;
546  }
547  }
548 
549  // Otherwise, use the first clone instance
550  if (child == NULL) {
551  child = clone->children->data;
552  }
553 
554  // Anonymous clones only need to probe a single instance
555  return child->cmds->create_probe(child, node);
556 }
557 
567 bool
569 {
570  CRM_ASSERT((node != NULL) && pcmk__is_clone(rsc));
571 
572  if (rsc->exclusive_discover) {
573  /* The clone is configured to be probed only where a location constraint
574  * exists with PCMK_XA_RESOURCE_DISCOVERY set to exclusive.
575  *
576  * This check is not strictly necessary here since the instance's
577  * create_probe() method would also check, but doing it here is more
578  * efficient (especially for unique clones with a large number of
579  * instances), and affects the CRM_meta_notify_available_uname variable
580  * passed with notify actions.
581  */
582  pcmk_node_t *allowed = g_hash_table_lookup(rsc->allowed_nodes,
583  node->details->id);
584 
585  if ((allowed == NULL)
586  || (allowed->rsc_discover_mode != pcmk_probe_exclusive)) {
587  /* This node is not marked for resource discovery. Remove it from
588  * allowed_nodes so that notifications contain only nodes that the
589  * clone can possibly run on.
590  */
591  pcmk__rsc_trace(rsc,
592  "Skipping probe for %s on %s because resource has "
593  "exclusive discovery but is not allowed on node",
594  rsc->id, pcmk__node_name(node));
595  g_hash_table_remove(rsc->allowed_nodes, node->details->id);
596  return false;
597  }
598  }
599 
600  rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance_number);
601  if (pcmk_is_set(rsc->flags, pcmk_rsc_unique)) {
602  return pcmk__probe_resource_list(rsc->children, node);
603  } else {
604  return probe_anonymous_clone(rsc, node);
605  }
606 }
607 
617 void
619 {
620  char *name = NULL;
621 
622  CRM_ASSERT(pcmk__is_clone(rsc) && (xml != NULL));
623 
625  crm_xml_add(xml, name, pcmk__flag_text(rsc->flags, pcmk_rsc_unique));
626  free(name);
627 
629  crm_xml_add(xml, name, pcmk__flag_text(rsc->flags, pcmk_rsc_notify));
630  free(name);
631 
633  crm_xml_add_int(xml, name, pe__clone_max(rsc));
634  free(name);
635 
638  free(name);
639 
641  int promoted_max = pe__clone_promoted_max(rsc);
642  int promoted_node_max = pe__clone_promoted_node_max(rsc);
643 
645  crm_xml_add_int(xml, name, promoted_max);
646  free(name);
647 
649  crm_xml_add_int(xml, name, promoted_node_max);
650  free(name);
651 
652  /* @COMPAT Maintain backward compatibility with resource agents that
653  * expect the old names (deprecated since 2.0.0).
654  */
656  crm_xml_add_int(xml, name, promoted_max);
657  free(name);
658 
660  crm_xml_add_int(xml, name, promoted_node_max);
661  free(name);
662  }
663 }
664 
665 // Clone implementation of pcmk_assignment_methods_t:add_utilization()
666 void
668  const pcmk_resource_t *orig_rsc, GList *all_rscs,
669  GHashTable *utilization)
670 {
671  bool existing = false;
672  pcmk_resource_t *child = NULL;
673 
674  CRM_ASSERT(pcmk__is_clone(rsc) && (orig_rsc != NULL)
675  && (utilization != NULL));
676 
677  if (!pcmk_is_set(rsc->flags, pcmk_rsc_unassigned)) {
678  return;
679  }
680 
681  // Look for any child already existing in the list
682  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
683  child = (pcmk_resource_t *) iter->data;
684  if (g_list_find(all_rscs, child)) {
685  existing = true; // Keep checking remaining children
686  } else {
687  // If this is a clone of a group, look for group's members
688  for (GList *member_iter = child->children; member_iter != NULL;
689  member_iter = member_iter->next) {
690 
691  pcmk_resource_t *member = (pcmk_resource_t *) member_iter->data;
692 
693  if (g_list_find(all_rscs, member) != NULL) {
694  // Add *child's* utilization, not group member's
695  child->cmds->add_utilization(child, orig_rsc, all_rscs,
696  utilization);
697  existing = true;
698  break;
699  }
700  }
701  }
702  }
703 
704  if (!existing && (rsc->children != NULL)) {
705  // If nothing was found, still add first child's utilization
706  child = (pcmk_resource_t *) rsc->children->data;
707 
708  child->cmds->add_utilization(child, orig_rsc, all_rscs, utilization);
709  }
710 }
711 
712 // Clone implementation of pcmk_assignment_methods_t:shutdown_lock()
713 void
715 {
716  CRM_ASSERT(pcmk__is_clone(rsc));
717  return; // Clones currently don't support shutdown locks
718 }
pcmk_assignment_methods_t * cmds
Definition: resources.h:413
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:245
#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:397
GHashTable * known_on
Definition: resources.h:459
&#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)
pcmk_scheduler_t * cluster
Definition: resources.h:408
char data[0]
Definition: cpg.c:58
GList * rsc_cons
Definition: resources.h:442
pcmk_node_t *(* location)(const pcmk_resource_t *rsc, GList **list, int current)
Definition: resources.h:328
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:86
uint32_t(* action_flags)(pcmk_action_t *action, const pcmk_node_t *node)
G_GNUC_INTERNAL bool pcmk__probe_resource_list(GList *rscs, pcmk_node_t *node)
GList * children
Definition: resources.h:471
#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)
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:348
gboolean exclusive_discover
Definition: resources.h:432
#define pcmk__config_err(fmt...)
GHashTable * meta
Definition: resources.h:467
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:63
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:301
#define PCMK_META_INTERLEAVE
Definition: options.h:90
Promoted.
Definition: roles.h:39
int pcmk__clone_apply_coloc_score(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
pcmk_node_t *(* assign)(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
G_GNUC_INTERNAL void pcmk__create_promotable_actions(pcmk_resource_t *clone)
GList * rsc_cons_lhs
Definition: resources.h:441
#define PCMK_META_CLONE_MAX
Definition: options.h:82
const char * action
Definition: pcmk_fence.c:30
G_GNUC_INTERNAL bool pcmk__assign_resource(pcmk_resource_t *rsc, pcmk_node_t *node, bool force, bool stop_if_fail)
void(* add_actions_to_graph)(pcmk_resource_t *rsc)
#define pcmk__rsc_debug(rsc, fmt, args...)
void(* with_this_colocations)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
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
int weight
Definition: nodes.h:162
pcmk_resource_t * parent
Definition: resources.h:409
G_GNUC_INTERNAL void pcmk__add_with_this_list(GList **list, GList *addition, const pcmk_resource_t *rsc)
unsigned int(* max_per_node)(const pcmk_resource_t *rsc)
Definition: resources.h:384
Actions are ordered (optionally, if no other flags are set)
#define PCMK_META_CLONE_NODE_MAX
Definition: options.h:84
void(* this_with_colocations)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
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:98
G_GNUC_INTERNAL void pcmk__add_promotion_scores(pcmk_resource_t *rsc)
struct pe_node_shared_s * details
Definition: nodes.h:167
#define PCMK_ACTION_START
Definition: actions.h:72
G_GNUC_INTERNAL gint pcmk__cmp_instance(gconstpointer a, gconstpointer b)
unsigned long long flags
Definition: resources.h:428
Wrappers for and extensions to libxml2.
#define PCMK__META_PROMOTED_MAX_LEGACY
void(* apply_location)(pcmk_resource_t *rsc, pcmk__location_t *location)
#define PCMK_ACTION_STOP
Definition: actions.h:75
GList * actions
Definition: resources.h:444
void pcmk__clone_create_actions(pcmk_resource_t *rsc)
#define pcmk__set_rsc_flags(resource, flags_to_set)
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:116
bool is_set_recursive(const pcmk_resource_t *rsc, long long flag, bool any)
Definition: clone.c:588
enum pe_obj_types variant
Definition: resources.h:410
bool(* create_probe)(pcmk_resource_t *rsc, pcmk_node_t *node)
int pe__clone_promoted_node_max(const pcmk_resource_t *clone)
Definition: clone.c:114
int pe__clone_promoted_max(const pcmk_resource_t *clone)
Definition: clone.c:97
int rsc_discover_mode
Definition: nodes.h:170
const char * id
Definition: nodes.h:72
#define pcmk__order_resource_actions(first_rsc, first_task, then_rsc, then_task, flags)
pcmk_resource_t * primary
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.
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:1470
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(* internal_constraints)(pcmk_resource_t *rsc)
pcmk_rsc_methods_t * fns
Definition: resources.h:412
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:1489
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 CRM_ASSERT(expr)
Definition: results.h:42
#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:76
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:66
pcmk_resource_t * dependent
#define pe__show_node_scores(level, rsc, text, nodes, scheduler)
Definition: internal.h:176
#define PCMK_META_PROMOTED_MAX
Definition: options.h:102
int pe__clone_node_max(const pcmk_resource_t *clone)
Definition: clone.c:80
gboolean crm_is_true(const char *s)
Definition: strings.c:488
Resource role is unknown.
Definition: roles.h:35
Location constraint object.
bool pe__clone_is_ordered(const pcmk_resource_t *clone)
Definition: clone.c:1344
#define PCMK_ACTION_RUNNING
Definition: actions.h:71
unsigned long long flags
Definition: scheduler.h:211
#define PCMK_ACTION_DEMOTED
Definition: actions.h:50
void pcmk__clone_apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
void(* add_utilization)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
int(* 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__colocation_intersect_nodes(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, const GList *primary_nodes, bool merge_scores)
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:24
bool pcmk__clone_create_probe(pcmk_resource_t *rsc, pcmk_node_t *node)
GHashTable * allowed_nodes
Definition: resources.h:462
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:959