pacemaker  3.0.0-d8340737c4
Scalable High-Availability cluster resource manager
pcmk_sched_resource.c
Go to the documentation of this file.
1 /*
2  * Copyright 2014-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 <stdlib.h>
13 #include <string.h>
14 #include <crm/common/xml.h>
15 #include <pacemaker-internal.h>
16 
17 #include "libpacemaker_private.h"
18 
19 // Resource assignment methods by resource variant
20 static pcmk__assignment_methods_t assignment_methods[] = {
21  {
39  },
40  {
58  },
59  {
77  },
78  {
96  }
97 };
98 
110 bool
112  const xmlNode *rsc_entry, bool active_on_node)
113 {
114  bool changed = false;
115  const char *attr_list[] = {
116  PCMK_XA_TYPE,
119  };
120 
121  for (int i = 0; i < PCMK__NELEM(attr_list); i++) {
122  const char *value = crm_element_value(rsc->priv->xml, attr_list[i]);
123  const char *old_value = crm_element_value(rsc_entry, attr_list[i]);
124 
125  if (!pcmk__str_eq(value, old_value, pcmk__str_none)) {
126  changed = true;
127  trigger_unfencing(rsc, node, "Device definition changed", NULL,
128  rsc->priv->scheduler);
129  if (active_on_node) {
130  crm_notice("Forcing restart of %s on %s "
131  "because %s changed from '%s' to '%s'",
132  rsc->id, pcmk__node_name(node), attr_list[i],
133  pcmk__s(old_value, ""), pcmk__s(value, ""));
134  }
135  }
136  }
137  if (changed && active_on_node) {
138  // Make sure the resource is restarted
139  custom_action(rsc, stop_key(rsc), PCMK_ACTION_STOP, node, FALSE,
140  rsc->priv->scheduler);
142  }
143  return changed;
144 }
145 
156 static GList *
157 add_rsc_if_matching(GList *result, pcmk_resource_t *rsc, const char *id)
158 {
159  if (pcmk__str_eq(id, rsc->id, pcmk__str_none)
160  || pcmk__str_eq(id, rsc->priv->history_id, pcmk__str_none)) {
161  result = g_list_prepend(result, rsc);
162  }
163 
164  for (GList *iter = rsc->priv->children;
165  iter != NULL; iter = iter->next) {
166 
167  pcmk_resource_t *child = (pcmk_resource_t *) iter->data;
168 
169  result = add_rsc_if_matching(result, child, id);
170  }
171  return result;
172 }
173 
185 GList *
187 {
188  GList *result = NULL;
189 
190  CRM_CHECK((id != NULL) && (scheduler != NULL), return NULL);
191 
192  for (GList *iter = scheduler->priv->resources;
193  iter != NULL; iter = iter->next) {
194 
195  result = add_rsc_if_matching(result, (pcmk_resource_t *) iter->data,
196  id);
197  }
198  return result;
199 }
200 
208 static void
209 set_assignment_methods_for_rsc(gpointer data, gpointer user_data)
210 {
211  pcmk_resource_t *rsc = data;
212 
213  rsc->priv->cmds = &assignment_methods[rsc->priv->variant];
214  g_list_foreach(rsc->priv->children, set_assignment_methods_for_rsc,
215  NULL);
216 }
217 
224 void
226 {
227  g_list_foreach(scheduler->priv->resources, set_assignment_methods_for_rsc,
228  NULL);
229 }
230 
241 static inline void
242 add_colocated_resources(const pcmk_resource_t *rsc,
243  const pcmk_resource_t *orig_rsc, GList **list)
244 {
245  *list = rsc->priv->cmds->colocated_resources(rsc, orig_rsc, *list);
246 }
247 
248 // Shared implementation of pcmk__assignment_methods_t:colocated_resources()
249 GList *
251  const pcmk_resource_t *orig_rsc,
252  GList *colocated_rscs)
253 {
254  const GList *iter = NULL;
255  GList *colocations = NULL;
256 
257  if (orig_rsc == NULL) {
258  orig_rsc = rsc;
259  }
260 
261  if ((rsc == NULL) || (g_list_find(colocated_rscs, rsc) != NULL)) {
262  return colocated_rscs;
263  }
264 
265  pcmk__rsc_trace(orig_rsc, "%s is in colocation chain with %s",
266  rsc->id, orig_rsc->id);
267  colocated_rscs = g_list_prepend(colocated_rscs, (gpointer) rsc);
268 
269  // Follow colocations where this resource is the dependent resource
270  colocations = pcmk__this_with_colocations(rsc);
271  for (iter = colocations; iter != NULL; iter = iter->next) {
272  const pcmk__colocation_t *constraint = iter->data;
273  const pcmk_resource_t *primary = constraint->primary;
274 
275  if (primary == orig_rsc) {
276  continue; // Break colocation loop
277  }
278 
279  if ((constraint->score == PCMK_SCORE_INFINITY) &&
280  (pcmk__colocation_affects(rsc, primary, constraint,
281  true) == pcmk__coloc_affects_location)) {
282  add_colocated_resources(primary, orig_rsc, &colocated_rscs);
283  }
284  }
285  g_list_free(colocations);
286 
287  // Follow colocations where this resource is the primary resource
288  colocations = pcmk__with_this_colocations(rsc);
289  for (iter = colocations; iter != NULL; iter = iter->next) {
290  const pcmk__colocation_t *constraint = iter->data;
291  const pcmk_resource_t *dependent = constraint->dependent;
292 
293  if (dependent == orig_rsc) {
294  continue; // Break colocation loop
295  }
296 
297  if (pcmk__is_clone(rsc) && !pcmk__is_clone(dependent)) {
298  continue; // We can't be sure whether dependent will be colocated
299  }
300 
301  if ((constraint->score == PCMK_SCORE_INFINITY) &&
302  (pcmk__colocation_affects(dependent, rsc, constraint,
303  true) == pcmk__coloc_affects_location)) {
304  add_colocated_resources(dependent, orig_rsc, &colocated_rscs);
305  }
306  }
307  g_list_free(colocations);
308 
309  return colocated_rscs;
310 }
311 
312 // No-op function for variants that don't need to implement add_graph_meta()
313 void
315 {
316 }
317 
324 void
326 {
327  pcmk_node_t *next = NULL;
328  pcmk_node_t *current = NULL;
329  pcmk__output_t *out = NULL;
330 
331  pcmk__assert(rsc != NULL);
332 
333  out = rsc->priv->scheduler->priv->out;
334  if (rsc->priv->children != NULL) {
335 
336  for (GList *iter = rsc->priv->children;
337  iter != NULL; iter = iter->next) {
338 
339  pcmk_resource_t *child = (pcmk_resource_t *) iter->data;
340 
341  child->priv->cmds->output_actions(child);
342  }
343  return;
344  }
345 
346  next = rsc->priv->assigned_node;
347  if (rsc->priv->active_nodes != NULL) {
348  current = pcmk__current_node(rsc);
349  if (rsc->priv->orig_role == pcmk_role_stopped) {
350  /* This can occur when resources are being recovered because
351  * the current role can change in pcmk__primitive_create_actions()
352  */
354  }
355  }
356 
357  if ((current == NULL) && pcmk_is_set(rsc->flags, pcmk__rsc_removed)) {
358  /* Don't log stopped orphans */
359  return;
360  }
361 
362  out->message(out, "rsc-action", rsc, current, next);
363 }
364 
372 static inline void
373 add_assigned_resource(pcmk_node_t *node, pcmk_resource_t *rsc)
374 {
375  node->priv->assigned_resources =
376  g_list_prepend(node->priv->assigned_resources, rsc);
377 }
378 
414 bool
416  bool stop_if_fail)
417 {
418  bool changed = false;
419  pcmk_scheduler_t *scheduler = NULL;
420 
421  pcmk__assert(rsc != NULL);
422  scheduler = rsc->priv->scheduler;
423 
424  if (rsc->priv->children != NULL) {
425 
426  for (GList *iter = rsc->priv->children;
427  iter != NULL; iter = iter->next) {
428 
429  pcmk_resource_t *child_rsc = iter->data;
430 
431  changed |= pcmk__assign_resource(child_rsc, node, force,
432  stop_if_fail);
433  }
434  return changed;
435  }
436 
437  // Assigning a primitive
438 
439  if (!force && (node != NULL)
440  && ((node->assign->score < 0)
441  // Allow graph to assume that guest node connections will come up
442  || (!pcmk__node_available(node, true, false)
443  && !pcmk__is_guest_or_bundle_node(node)))) {
444 
445  pcmk__rsc_debug(rsc,
446  "All nodes for resource %s are unavailable, unclean or "
447  "shutting down (%s can%s run resources, with score %s)",
448  rsc->id, pcmk__node_name(node),
449  (pcmk__node_available(node, true, false)? "" : "not"),
451 
452  if (stop_if_fail) {
453  pe__set_next_role(rsc, pcmk_role_stopped, "node availability");
454  }
455  node = NULL;
456  }
457 
458  if (rsc->priv->assigned_node != NULL) {
459  changed = !pcmk__same_node(rsc->priv->assigned_node, node);
460  } else {
461  changed = (node != NULL);
462  }
465 
466  if (node == NULL) {
467  char *rc_stopped = NULL;
468 
469  pcmk__rsc_debug(rsc, "Could not assign %s to a node", rsc->id);
470 
471  if (!stop_if_fail) {
472  return changed;
473  }
474  pe__set_next_role(rsc, pcmk_role_stopped, "unable to assign");
475 
476  for (GList *iter = rsc->priv->actions;
477  iter != NULL; iter = iter->next) {
478 
479  pcmk_action_t *op = (pcmk_action_t *) iter->data;
480 
481  pcmk__rsc_debug(rsc, "Updating %s for %s assignment failure",
482  op->uuid, rsc->id);
483 
484  if (pcmk__str_eq(op->task, PCMK_ACTION_STOP, pcmk__str_none)) {
486 
487  } else if (pcmk__str_eq(op->task, PCMK_ACTION_START,
488  pcmk__str_none)) {
490 
491  } else {
492  // Cancel recurring actions, unless for stopped state
493  const char *interval_ms_s = NULL;
494  const char *target_rc_s = NULL;
495 
496  interval_ms_s = g_hash_table_lookup(op->meta,
498  target_rc_s = g_hash_table_lookup(op->meta,
500  if (rc_stopped == NULL) {
501  rc_stopped = pcmk__itoa(PCMK_OCF_NOT_RUNNING);
502  }
503 
504  if (!pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches)
505  && !pcmk__str_eq(rc_stopped, target_rc_s, pcmk__str_none)) {
506 
508  }
509  }
510  }
511  free(rc_stopped);
512  return changed;
513  }
514 
515  pcmk__rsc_debug(rsc, "Assigning %s to %s", rsc->id, pcmk__node_name(node));
516  rsc->priv->assigned_node = pe__copy_node(node);
517 
518  add_assigned_resource(node, rsc);
519  node->priv->num_resources++;
520  node->assign->count++;
522 
524  pcmk__output_t *out = scheduler->priv->out;
525 
526  out->message(out, "resource-util", rsc, node, __func__);
527  }
528  return changed;
529 }
530 
542 void
544 {
545  pcmk_node_t *old = rsc->priv->assigned_node;
546 
547  if (old == NULL) {
548  crm_info("Unassigning %s", rsc->id);
549  } else {
550  crm_info("Unassigning %s from %s", rsc->id, pcmk__node_name(old));
551  }
552 
554 
555  if (rsc->priv->children == NULL) {
556  if (old == NULL) {
557  return;
558  }
559  rsc->priv->assigned_node = NULL;
560 
561  /* We're going to free the pcmk_node_t copy, but its priv member is
562  * shared and will remain, so update that appropriately first.
563  */
564  old->priv->assigned_resources =
565  g_list_remove(old->priv->assigned_resources, rsc);
566  old->priv->num_resources--;
569  return;
570  }
571 
572  for (GList *iter = rsc->priv->children;
573  iter != NULL; iter = iter->next) {
574 
576  }
577 }
578 
590 bool
592  pcmk_resource_t **failed)
593 {
594  int fail_count, remaining_tries;
595  pcmk_resource_t *rsc_to_ban = rsc;
596 
597  // Migration threshold of 0 means never force away
598  if (rsc->priv->ban_after_failures == 0) {
599  return false;
600  }
601 
602  // If we're ignoring failures, also ignore the migration threshold
604  return false;
605  }
606 
607  // If there are no failures, there's no need to force away
608  fail_count = pe_get_failcount(node, rsc, NULL,
610  if (fail_count <= 0) {
611  return false;
612  }
613 
614  // If failed resource is anonymous clone instance, we'll force clone away
615  if (!pcmk_is_set(rsc->flags, pcmk__rsc_unique)) {
616  rsc_to_ban = uber_parent(rsc);
617  }
618 
619  // How many more times recovery will be tried on this node
620  remaining_tries = rsc->priv->ban_after_failures - fail_count;
621 
622  if (remaining_tries <= 0) {
624  "%s cannot run on %s due to reaching migration "
625  "threshold (clean up resource to allow again) "
626  QB_XS " failures=%d "
628  rsc_to_ban->id, pcmk__node_name(node), fail_count,
629  rsc->priv->ban_after_failures);
630  if (failed != NULL) {
631  *failed = rsc_to_ban;
632  }
633  return true;
634  }
635 
636  crm_info("%s can fail %d more time%s on "
637  "%s before reaching migration threshold (%d)",
638  rsc_to_ban->id, remaining_tries, pcmk__plural_s(remaining_tries),
639  pcmk__node_name(node), rsc->priv->ban_after_failures);
640  return false;
641 }
642 
652 static int
653 get_node_score(const pcmk_node_t *node, GHashTable *nodes)
654 {
655  pcmk_node_t *found_node = NULL;
656 
657  if ((node != NULL) && (nodes != NULL)) {
658  found_node = g_hash_table_lookup(nodes, node->priv->id);
659  }
660  if (found_node == NULL) {
661  return -PCMK_SCORE_INFINITY;
662  }
663  return found_node->assign->score;
664 }
665 
677 static gint
678 cmp_resources(gconstpointer a, gconstpointer b, gpointer data)
679 {
680  /* GLib insists that this function require gconstpointer arguments, but we
681  * make a small, temporary change to each argument (setting the
682  * pe_rsc_merging flag) during comparison
683  */
684  pcmk_resource_t *resource1 = (pcmk_resource_t *) a;
685  pcmk_resource_t *resource2 = (pcmk_resource_t *) b;
686  const GList *nodes = data;
687 
688  int rc = 0;
689  int r1_score = -PCMK_SCORE_INFINITY;
690  int r2_score = -PCMK_SCORE_INFINITY;
691  pcmk_node_t *r1_node = NULL;
692  pcmk_node_t *r2_node = NULL;
693  GHashTable *r1_nodes = NULL;
694  GHashTable *r2_nodes = NULL;
695  const char *reason = NULL;
696 
697  // Resources with highest priority should be assigned first
698  reason = "priority";
699  r1_score = resource1->priv->priority;
700  r2_score = resource2->priv->priority;
701  if (r1_score > r2_score) {
702  rc = -1;
703  goto done;
704  }
705  if (r1_score < r2_score) {
706  rc = 1;
707  goto done;
708  }
709 
710  // We need nodes to make any other useful comparisons
711  reason = "no node list";
712  if (nodes == NULL) {
713  goto done;
714  }
715 
716  // Calculate and log node scores
717  resource1->priv->cmds->add_colocated_node_scores(resource1, NULL,
718  resource1->id,
719  &r1_nodes, NULL, 1,
721  resource2->priv->cmds->add_colocated_node_scores(resource2, NULL,
722  resource2->id,
723  &r2_nodes, NULL, 1,
725  pe__show_node_scores(true, NULL, resource1->id, r1_nodes,
726  resource1->priv->scheduler);
727  pe__show_node_scores(true, NULL, resource2->id, r2_nodes,
728  resource2->priv->scheduler);
729 
730  // The resource with highest score on its current node goes first
731  reason = "current location";
732  if (resource1->priv->active_nodes != NULL) {
733  r1_node = pcmk__current_node(resource1);
734  }
735  if (resource2->priv->active_nodes != NULL) {
736  r2_node = pcmk__current_node(resource2);
737  }
738  r1_score = get_node_score(r1_node, r1_nodes);
739  r2_score = get_node_score(r2_node, r2_nodes);
740  if (r1_score > r2_score) {
741  rc = -1;
742  goto done;
743  }
744  if (r1_score < r2_score) {
745  rc = 1;
746  goto done;
747  }
748 
749  // Otherwise a higher score on any node will do
750  reason = "score";
751  for (const GList *iter = nodes; iter != NULL; iter = iter->next) {
752  const pcmk_node_t *node = (const pcmk_node_t *) iter->data;
753 
754  r1_score = get_node_score(node, r1_nodes);
755  r2_score = get_node_score(node, r2_nodes);
756  if (r1_score > r2_score) {
757  rc = -1;
758  goto done;
759  }
760  if (r1_score < r2_score) {
761  rc = 1;
762  goto done;
763  }
764  }
765 
766 done:
767  crm_trace("%s (%d)%s%s %c %s (%d)%s%s: %s",
768  resource1->id, r1_score,
769  ((r1_node == NULL)? "" : " on "),
770  ((r1_node == NULL)? "" : r1_node->priv->id),
771  ((rc < 0)? '>' : ((rc > 0)? '<' : '=')),
772  resource2->id, r2_score,
773  ((r2_node == NULL)? "" : " on "),
774  ((r2_node == NULL)? "" : r2_node->priv->id),
775  reason);
776  if (r1_nodes != NULL) {
777  g_hash_table_destroy(r1_nodes);
778  }
779  if (r2_nodes != NULL) {
780  g_hash_table_destroy(r2_nodes);
781  }
782  return rc;
783 }
784 
791 void
793 {
794  GList *nodes = g_list_copy(scheduler->nodes);
795 
796  nodes = pcmk__sort_nodes(nodes, NULL);
798  g_list_sort_with_data(scheduler->priv->resources, cmp_resources, nodes);
799  g_list_free(nodes);
800 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:213
G_GNUC_INTERNAL void pcmk__primitive_with_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
G_GNUC_INTERNAL pcmk_node_t * pcmk__primitive_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
Definition: utils.c:91
void trigger_unfencing(pcmk_resource_t *rsc, pcmk_node_t *node, const char *reason, pcmk_action_t *dependency, pcmk_scheduler_t *scheduler)
Definition: utils.c:610
#define crm_notice(fmt, args...)
Definition: logging.h:365
G_GNUC_INTERNAL void pcmk__apply_location(pcmk_resource_t *rsc, pcmk__location_t *constraint)
G_GNUC_INTERNAL void pcmk__group_shutdown_lock(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__primitive_create_actions(pcmk_resource_t *rsc)
char data[0]
Definition: cpg.c:58
G_GNUC_INTERNAL int pcmk__group_apply_coloc_score(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
#define PCMK_META_MIGRATION_THRESHOLD
Definition: options.h:95
G_GNUC_INTERNAL pcmk_node_t * pcmk__bundle_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
pcmk_resource_t * uber_parent(pcmk_resource_t *rsc)
Definition: complex.c:1017
Stopped.
Definition: roles.h:36
void pcmk__noop_add_graph_meta(const pcmk_resource_t *rsc, xmlNode *xml)
int(* message)(pcmk__output_t *out, const char *message_id,...)
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition: scores.c:102
G_GNUC_INTERNAL void pcmk__release_node_capacity(GHashTable *current_utilization, const pcmk_resource_t *rsc)
#define pcmk__rsc_trace(rsc, fmt, args...)
G_GNUC_INTERNAL void pcmk__bundle_add_utilization(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
#define PCMK__META_OP_TARGET_RC
#define pcmk__set_rsc_flags(resource, flags_to_set)
G_GNUC_INTERNAL GList * pcmk__group_colocated_resources(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *colocated_rscs)
Service safely stopped.
Definition: results.h:186
pcmk__scheduler_private_t * priv
Definition: scheduler.h:99
#define PCMK_XA_PROVIDER
Definition: xml_names.h:364
G_GNUC_INTERNAL void pcmk__with_bundle_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
uint64_t flags
Definition: scheduler.h:89
void pcmk__output_resource_actions(pcmk_resource_t *rsc)
G_GNUC_INTERNAL int pcmk__bundle_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__with_clone_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
G_GNUC_INTERNAL uint32_t pcmk__update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL void pcmk__clone_apply_location(pcmk_resource_t *rsc, pcmk__location_t *constraint)
bool pcmk__rsc_agent_changed(pcmk_resource_t *rsc, pcmk_node_t *node, const xmlNode *rsc_entry, bool active_on_node)
void pcmk__free_node_copy(void *data)
Definition: nodes.c:22
G_GNUC_INTERNAL void pcmk__bundle_shutdown_lock(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__group_with_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
#define PCMK_XA_TYPE
Definition: xml_names.h:430
void(* output_actions)(pcmk_resource_t *rsc)
int pe_get_failcount(const pcmk_node_t *node, pcmk_resource_t *rsc, time_t *last_failure, uint32_t flags, const xmlNode *xml_op)
Definition: failcounts.c:364
G_GNUC_INTERNAL bool pcmk__node_available(const pcmk_node_t *node, bool consider_score, bool consider_guest)
G_GNUC_INTERNAL void pcmk__clone_with_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
G_GNUC_INTERNAL bool pcmk__bundle_create_probe(pcmk_resource_t *rsc, pcmk_node_t *node)
G_GNUC_INTERNAL void pcmk__clone_internal_constraints(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__bundle_apply_location(pcmk_resource_t *rsc, pcmk__location_t *constraint)
G_GNUC_INTERNAL void pcmk__add_colocated_node_scores(pcmk_resource_t *source_rsc, const pcmk_resource_t *target_rsc, const char *log_id, GHashTable **nodes, const pcmk__colocation_t *colocation, float factor, uint32_t flags)
#define pcmk__rsc_debug(rsc, fmt, args...)
G_GNUC_INTERNAL void pcmk__bundle_with_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
pcmk__node_private_t * priv
Definition: nodes.h:85
G_GNUC_INTERNAL void pcmk__clone_add_actions_to_graph(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__consume_node_capacity(GHashTable *current_utilization, const pcmk_resource_t *rsc)
void pe__set_next_role(pcmk_resource_t *rsc, enum rsc_role_e role, const char *why)
Definition: complex.c:1265
bool pcmk__threshold_reached(pcmk_resource_t *rsc, const pcmk_node_t *node, pcmk_resource_t **failed)
G_GNUC_INTERNAL 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__primitive_add_graph_meta(const pcmk_resource_t *rsc, xmlNode *xml)
G_GNUC_INTERNAL void pcmk__bundle_internal_constraints(pcmk_resource_t *rsc)
pcmk_scheduler_t * scheduler
#define pcmk__clear_action_flags(action, flags_to_clear)
#define stop_key(rsc)
Definition: internal.h:196
void pcmk__set_assignment_methods(pcmk_scheduler_t *scheduler)
enum pcmk__rsc_variant variant
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: xml_element.c:1168
G_GNUC_INTERNAL uint32_t pcmk__group_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
#define crm_trace(fmt, args...)
Definition: logging.h:372
void(* add_colocated_node_scores)(pcmk_resource_t *source_rsc, const pcmk_resource_t *target_rsc, const char *log_id, GHashTable **nodes, const pcmk__colocation_t *colocation, float factor, uint32_t flags)
#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__clone_create_actions(pcmk_resource_t *rsc)
#define PCMK_ACTION_START
Definition: actions.h:63
pcmk__resource_private_t * priv
Definition: resources.h:61
GList * pcmk__rscs_matching_id(const char *id, const pcmk_scheduler_t *scheduler)
Wrappers for and extensions to libxml2.
#define PCMK__NELEM(a)
Definition: internal.h:49
#define PCMK_ACTION_STOP
Definition: actions.h:66
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
G_GNUC_INTERNAL pcmk_node_t * pcmk__clone_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
G_GNUC_INTERNAL void pcmk__with_primitive_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
GList * pcmk__colocated_resources(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *colocated_rscs)
G_GNUC_INTERNAL void pcmk__clone_add_graph_meta(const pcmk_resource_t *rsc, xmlNode *xml)
G_GNUC_INTERNAL void pcmk__primitive_add_utilization(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
pcmk_action_t * custom_action(pcmk_resource_t *rsc, char *key, const char *task, const pcmk_node_t *on_node, gboolean optional, pcmk_scheduler_t *scheduler)
Create or update an action object.
Definition: pe_actions.c:1093
G_GNUC_INTERNAL void pcmk__group_add_colocated_node_scores(pcmk_resource_t *source_rsc, const pcmk_resource_t *target_rsc, const char *log_id, GHashTable **nodes, const pcmk__colocation_t *colocation, float factor, uint32_t flags)
pcmk_resource_t * primary
#define pcmk__assert(expr)
#define pcmk__sched_warn(scheduler, fmt...)
G_GNUC_INTERNAL void pcmk__add_rsc_actions_to_graph(pcmk_resource_t *rsc)
void pcmk__sort_resources(pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL enum pcmk__coloc_affects pcmk__colocation_affects(const pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool preview)
#define PCMK_XA_CLASS
Definition: xml_names.h:246
G_GNUC_INTERNAL void pcmk__group_apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
#define PCMK_META_INTERVAL
Definition: options.h:91
GList * nodes
Definition: scheduler.h:97
G_GNUC_INTERNAL GList * pcmk__with_this_colocations(const pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__bundle_add_actions_to_graph(pcmk_resource_t *rsc)
pcmk__action_result_t result
Definition: pcmk_fence.c:37
G_GNUC_INTERNAL int pcmk__primitive_apply_coloc_score(pcmk_resource_t *dependent, const pcmk_resource_t *primary, const pcmk__colocation_t *colocation, bool for_dependent)
pcmk_scheduler_t * scheduler
G_GNUC_INTERNAL void pcmk__with_group_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
G_GNUC_INTERNAL void pcmk__output_bundle_actions(pcmk_resource_t *rsc)
G_GNUC_INTERNAL void pcmk__clone_shutdown_lock(pcmk_resource_t *rsc)
G_GNUC_INTERNAL GList * pcmk__this_with_colocations(const pcmk_resource_t *rsc)
Started.
Definition: roles.h:37
This structure contains everything that makes up a single output formatter.
G_GNUC_INTERNAL uint32_t pcmk__bundle_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
G_GNUC_INTERNAL void pcmk__clone_add_utilization(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
G_GNUC_INTERNAL void pcmk__group_create_actions(pcmk_resource_t *rsc)
G_GNUC_INTERNAL pcmk_node_t * pcmk__group_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
pcmk_resource_t * dependent
#define pe__show_node_scores(level, rsc, text, nodes, scheduler)
Definition: internal.h:164
#define pcmk__plural_s(i)
G_GNUC_INTERNAL void pcmk__primitive_shutdown_lock(pcmk_resource_t *rsc)
G_GNUC_INTERNAL uint32_t pcmk__group_update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL bool pcmk__probe_rsc_on_node(pcmk_resource_t *rsc, pcmk_node_t *node)
unsigned long long flags
Definition: resources.h:69
void pcmk__unassign_resource(pcmk_resource_t *rsc)
G_GNUC_INTERNAL GList * pcmk__sort_nodes(GList *nodes, pcmk_node_t *active_node)
G_GNUC_INTERNAL uint32_t pcmk__primitive_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
bool pcmk__assign_resource(pcmk_resource_t *rsc, pcmk_node_t *node, bool force, bool stop_if_fail)
GHashTable * meta
G_GNUC_INTERNAL uint32_t pcmk__clone_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
GList *(* colocated_resources)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *colocated_rscs)
G_GNUC_INTERNAL uint32_t pcmk__instance_update_ordered_actions(pcmk_action_t *first, pcmk_action_t *then, const pcmk_node_t *node, uint32_t flags, uint32_t filter, uint32_t type, pcmk_scheduler_t *scheduler)
#define crm_info(fmt, args...)
Definition: logging.h:367
G_GNUC_INTERNAL void pcmk__group_add_utilization(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
G_GNUC_INTERNAL void pcmk__bundle_create_actions(pcmk_resource_t *rsc)
G_GNUC_INTERNAL bool pcmk__clone_create_probe(pcmk_resource_t *rsc, pcmk_node_t *node)
const pcmk__assignment_methods_t * cmds
G_GNUC_INTERNAL void pcmk__primitive_internal_constraints(pcmk_resource_t *rsc)
GHashTable * utilization
G_GNUC_INTERNAL void pcmk__group_internal_constraints(pcmk_resource_t *rsc)
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:26
struct pcmk__node_assignment * assign
Definition: nodes.h:79