pacemaker  2.1.9-49aab99839
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 
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  pcmk__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  pcmk__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  pcmk__assert(!for_dependent && (colocation != NULL)
260  && pcmk__is_clone(primary) && pcmk__is_primitive(dependent));
261 
262  if (pcmk_is_set(primary->flags, pcmk_rsc_unassigned)) {
263  pcmk__rsc_trace(primary,
264  "Delaying processing colocation %s "
265  "because cloned primary %s is still provisional",
266  colocation->id, primary->id);
267  return 0;
268  }
269 
270  pcmk__rsc_trace(primary, "Processing colocation %s (%s with clone %s @%s)",
271  colocation->id, dependent->id, primary->id,
272  pcmk_readable_score(colocation->score));
273 
274  // Apply role-specific colocations
275  if (pcmk_is_set(primary->flags, pcmk_rsc_promotable)
276  && (colocation->primary_role != pcmk_role_unknown)) {
277 
278  if (pcmk_is_set(dependent->flags, pcmk_rsc_unassigned)) {
279  // We're assigning the dependent to a node
280  pcmk__update_dependent_with_promotable(primary, dependent,
281  colocation);
282  return 0;
283  }
284 
285  if (colocation->dependent_role == pcmk_role_promoted) {
286  // We're choosing a role for the dependent
288  dependent,
289  colocation);
290  }
291  }
292 
293  // Apply interleaved colocations
294  if (can_interleave(colocation)) {
295  const pcmk_resource_t *primary_instance = NULL;
296 
297  primary_instance = pcmk__find_compatible_instance(dependent, primary,
299  false);
300  if (primary_instance != NULL) {
301  pcmk__rsc_debug(primary, "Interleaving %s with %s",
302  dependent->id, primary_instance->id);
303 
304  return dependent->cmds->apply_coloc_score(dependent,
305  primary_instance,
306  colocation, true);
307  }
308 
309  if (colocation->score >= PCMK_SCORE_INFINITY) {
310  crm_notice("%s cannot run because it cannot interleave with "
311  "any instance of %s", dependent->id, primary->id);
312  pcmk__assign_resource(dependent, NULL, true, true);
313 
314  } else {
315  pcmk__rsc_debug(primary,
316  "%s will not colocate with %s "
317  "because no instance can interleave with it",
318  dependent->id, primary->id);
319  }
320 
321  return 0;
322  }
323 
324  // Apply mandatory colocations
325  if (colocation->score >= PCMK_SCORE_INFINITY) {
326  GList *primary_nodes = NULL;
327 
328  // Dependent can run only where primary will have unblocked instances
329  for (iter = primary->children; iter != NULL; iter = iter->next) {
330  const pcmk_resource_t *instance = iter->data;
331  pcmk_node_t *chosen = instance->fns->location(instance, NULL, 0);
332 
333  if ((chosen != NULL)
334  && !is_set_recursive(instance, pcmk_rsc_blocked, TRUE)) {
335  pcmk__rsc_trace(primary, "Allowing %s: %s %d",
336  colocation->id, pcmk__node_name(chosen),
337  chosen->weight);
338  primary_nodes = g_list_prepend(primary_nodes, chosen);
339  }
340  }
341  pcmk__colocation_intersect_nodes(dependent, primary, colocation,
342  primary_nodes, false);
343  g_list_free(primary_nodes);
344  return 0;
345  }
346 
347  // Apply optional colocations
348  for (iter = primary->children; iter != NULL; iter = iter->next) {
349  const pcmk_resource_t *instance = iter->data;
350  int instance_delta = instance->cmds->apply_coloc_score(dependent,
351  instance,
352  colocation,
353  false);
354 
355  priority_delta = pcmk__add_scores(priority_delta, instance_delta);
356  }
357  return priority_delta;
358 }
359 
360 // Clone implementation of pcmk_assignment_methods_t:with_this_colocations()
361 void
363  const pcmk_resource_t *orig_rsc, GList **list)
364 {
365  CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
366 
367  pcmk__add_with_this_list(list, rsc->rsc_cons_lhs, orig_rsc);
368 
369  if (rsc->parent != NULL) {
370  rsc->parent->cmds->with_this_colocations(rsc->parent, orig_rsc, list);
371  }
372 }
373 
374 // Clone implementation of pcmk_assignment_methods_t:this_with_colocations()
375 void
377  const pcmk_resource_t *orig_rsc, GList **list)
378 {
379  CRM_CHECK((rsc != NULL) && (orig_rsc != NULL) && (list != NULL), return);
380 
381  pcmk__add_this_with_list(list, rsc->rsc_cons, orig_rsc);
382 
383  if (rsc->parent != NULL) {
384  rsc->parent->cmds->this_with_colocations(rsc->parent, orig_rsc, list);
385  }
386 }
387 
397 uint32_t
399 {
400  pcmk__assert((action != NULL) && pcmk__is_clone(action->rsc));
401 
402  return pcmk__collective_action_flags(action, action->rsc->children, node);
403 }
404 
412 void
414 {
415  CRM_CHECK((location != NULL) && pcmk__is_clone(rsc), return);
416 
417  pcmk__apply_location(rsc, location);
418 
419  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
420  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
421 
422  instance->cmds->apply_location(instance, location);
423  }
424 }
425 
426 // GFunc wrapper for calling the action_flags() resource method
427 static void
428 call_action_flags(gpointer data, gpointer user_data)
429 {
430  pcmk_resource_t *rsc = user_data;
431 
432  rsc->cmds->action_flags((pcmk_action_t *) data, NULL);
433 }
434 
441 void
443 {
444  pcmk__assert(pcmk__is_clone(rsc));
445 
446  g_list_foreach(rsc->actions, call_action_flags, rsc);
448 
449  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
450  pcmk_resource_t *child_rsc = (pcmk_resource_t *) iter->data;
451 
452  child_rsc->cmds->add_actions_to_graph(child_rsc);
453  }
454 
457 }
458 
469 static bool
470 rsc_probed_on(const pcmk_resource_t *rsc, const pcmk_node_t *node)
471 {
472  if (rsc->children != NULL) {
473  for (GList *child_iter = rsc->children; child_iter != NULL;
474  child_iter = child_iter->next) {
475 
476  pcmk_resource_t *child = (pcmk_resource_t *) child_iter->data;
477 
478  if (rsc_probed_on(child, node)) {
479  return true;
480  }
481  }
482  return false;
483  }
484 
485  if (rsc->known_on != NULL) {
486  GHashTableIter iter;
487  pcmk_node_t *known_node = NULL;
488 
489  g_hash_table_iter_init(&iter, rsc->known_on);
490  while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &known_node)) {
491  if (pcmk__same_node(node, known_node)) {
492  return true;
493  }
494  }
495  }
496  return false;
497 }
498 
509 static pcmk_resource_t *
510 find_probed_instance_on(const pcmk_resource_t *clone, const pcmk_node_t *node)
511 {
512  for (GList *iter = clone->children; iter != NULL; iter = iter->next) {
513  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
514 
515  if (rsc_probed_on(instance, node)) {
516  return instance;
517  }
518  }
519  return NULL;
520 }
521 
529 static bool
530 probe_anonymous_clone(pcmk_resource_t *clone, pcmk_node_t *node)
531 {
532  // Check whether we already probed an instance on this node
533  pcmk_resource_t *child = find_probed_instance_on(clone, node);
534 
535  // Otherwise, check if we plan to start an instance on this node
536  for (GList *iter = clone->children; (iter != NULL) && (child == NULL);
537  iter = iter->next) {
538  pcmk_resource_t *instance = (pcmk_resource_t *) iter->data;
539  const pcmk_node_t *instance_node = NULL;
540 
541  instance_node = instance->fns->location(instance, NULL, 0);
542  if (pcmk__same_node(instance_node, node)) {
543  child = instance;
544  }
545  }
546 
547  // Otherwise, use the first clone instance
548  if (child == NULL) {
549  child = clone->children->data;
550  }
551 
552  // Anonymous clones only need to probe a single instance
553  return child->cmds->create_probe(child, node);
554 }
555 
565 bool
567 {
568  pcmk__assert((node != NULL) && pcmk__is_clone(rsc));
569 
570  if (rsc->exclusive_discover) {
571  /* The clone is configured to be probed only where a location constraint
572  * exists with PCMK_XA_RESOURCE_DISCOVERY set to exclusive.
573  *
574  * This check is not strictly necessary here since the instance's
575  * create_probe() method would also check, but doing it here is more
576  * efficient (especially for unique clones with a large number of
577  * instances), and affects the CRM_meta_notify_available_uname variable
578  * passed with notify actions.
579  */
580  pcmk_node_t *allowed = g_hash_table_lookup(rsc->allowed_nodes,
581  node->details->id);
582 
583  if ((allowed == NULL)
584  || (allowed->rsc_discover_mode != pcmk_probe_exclusive)) {
585  /* This node is not marked for resource discovery. Remove it from
586  * allowed_nodes so that notifications contain only nodes that the
587  * clone can possibly run on.
588  */
589  pcmk__rsc_trace(rsc,
590  "Skipping probe for %s on %s because resource has "
591  "exclusive discovery but is not allowed on node",
592  rsc->id, pcmk__node_name(node));
593  g_hash_table_remove(rsc->allowed_nodes, node->details->id);
594  return false;
595  }
596  }
597 
598  rsc->children = g_list_sort(rsc->children, pcmk__cmp_instance_number);
599  if (pcmk_is_set(rsc->flags, pcmk_rsc_unique)) {
600  return pcmk__probe_resource_list(rsc->children, node);
601  } else {
602  return probe_anonymous_clone(rsc, node);
603  }
604 }
605 
615 void
617 {
618  char *name = NULL;
619 
620  pcmk__assert(pcmk__is_clone(rsc) && (xml != NULL));
621 
623  crm_xml_add(xml, name, pcmk__flag_text(rsc->flags, pcmk_rsc_unique));
624  free(name);
625 
627  crm_xml_add(xml, name, pcmk__flag_text(rsc->flags, pcmk_rsc_notify));
628  free(name);
629 
631  crm_xml_add_int(xml, name, pe__clone_max(rsc));
632  free(name);
633 
636  free(name);
637 
639  int promoted_max = pe__clone_promoted_max(rsc);
640  int promoted_node_max = pe__clone_promoted_node_max(rsc);
641 
643  crm_xml_add_int(xml, name, promoted_max);
644  free(name);
645 
647  crm_xml_add_int(xml, name, promoted_node_max);
648  free(name);
649 
650  /* @COMPAT Maintain backward compatibility with resource agents that
651  * expect the old names (deprecated since 2.0.0).
652  */
654  crm_xml_add_int(xml, name, promoted_max);
655  free(name);
656 
658  crm_xml_add_int(xml, name, promoted_node_max);
659  free(name);
660  }
661 }
662 
663 // Clone implementation of pcmk_assignment_methods_t:add_utilization()
664 void
666  const pcmk_resource_t *orig_rsc, GList *all_rscs,
667  GHashTable *utilization)
668 {
669  bool existing = false;
670  pcmk_resource_t *child = NULL;
671 
672  pcmk__assert(pcmk__is_clone(rsc) && (orig_rsc != NULL)
673  && (utilization != NULL));
674 
675  if (!pcmk_is_set(rsc->flags, pcmk_rsc_unassigned)) {
676  return;
677  }
678 
679  // Look for any child already existing in the list
680  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
681  child = (pcmk_resource_t *) iter->data;
682  if (g_list_find(all_rscs, child)) {
683  existing = true; // Keep checking remaining children
684  } else {
685  // If this is a clone of a group, look for group's members
686  for (GList *member_iter = child->children; member_iter != NULL;
687  member_iter = member_iter->next) {
688 
689  pcmk_resource_t *member = (pcmk_resource_t *) member_iter->data;
690 
691  if (g_list_find(all_rscs, member) != NULL) {
692  // Add *child's* utilization, not group member's
693  child->cmds->add_utilization(child, orig_rsc, all_rscs,
694  utilization);
695  existing = true;
696  break;
697  }
698  }
699  }
700  }
701 
702  if (!existing && (rsc->children != NULL)) {
703  // If nothing was found, still add first child's utilization
704  child = (pcmk_resource_t *) rsc->children->data;
705 
706  child->cmds->add_utilization(child, orig_rsc, all_rscs, utilization);
707  }
708 }
709 
710 // Clone implementation of pcmk_assignment_methods_t:shutdown_lock()
711 void
713 {
714  pcmk__assert(pcmk__is_clone(rsc));
715  return; // Clones currently don't support shutdown locks
716 }
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:137
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:360
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:313
#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:163
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:94
G_GNUC_INTERNAL void pcmk__add_promotion_scores(pcmk_resource_t *rsc)
struct pe_node_shared_s * details
Definition: nodes.h:168
#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:167
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:171
const char * id
Definition: nodes.h:73
#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.
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 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:500
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:1043