pacemaker  2.1.8-3980678f03
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->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->cluster);
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->cluster);
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 ((strcmp(rsc->id, id) == 0)
160  || ((rsc->clone_name != NULL) && (strcmp(rsc->clone_name, id) == 0))) {
161  result = g_list_prepend(result, rsc);
162  }
163  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
164  pcmk_resource_t *child = (pcmk_resource_t *) iter->data;
165 
166  result = add_rsc_if_matching(result, child, id);
167  }
168  return result;
169 }
170 
182 GList *
184 {
185  GList *result = NULL;
186 
187  CRM_CHECK((id != NULL) && (scheduler != NULL), return NULL);
188  for (GList *iter = scheduler->resources; iter != NULL; iter = iter->next) {
189  result = add_rsc_if_matching(result, (pcmk_resource_t *) iter->data,
190  id);
191  }
192  return result;
193 }
194 
202 static void
203 set_assignment_methods_for_rsc(gpointer data, gpointer user_data)
204 {
205  pcmk_resource_t *rsc = data;
206 
207  rsc->cmds = &assignment_methods[rsc->variant];
208  g_list_foreach(rsc->children, set_assignment_methods_for_rsc, NULL);
209 }
210 
217 void
219 {
220  g_list_foreach(scheduler->resources, set_assignment_methods_for_rsc, NULL);
221 }
222 
233 static inline void
234 add_colocated_resources(const pcmk_resource_t *rsc,
235  const pcmk_resource_t *orig_rsc, GList **list)
236 {
237  *list = rsc->cmds->colocated_resources(rsc, orig_rsc, *list);
238 }
239 
240 // Shared implementation of pcmk_assignment_methods_t:colocated_resources()
241 GList *
243  const pcmk_resource_t *orig_rsc,
244  GList *colocated_rscs)
245 {
246  const GList *iter = NULL;
247  GList *colocations = NULL;
248 
249  if (orig_rsc == NULL) {
250  orig_rsc = rsc;
251  }
252 
253  if ((rsc == NULL) || (g_list_find(colocated_rscs, rsc) != NULL)) {
254  return colocated_rscs;
255  }
256 
257  pcmk__rsc_trace(orig_rsc, "%s is in colocation chain with %s",
258  rsc->id, orig_rsc->id);
259  colocated_rscs = g_list_prepend(colocated_rscs, (gpointer) rsc);
260 
261  // Follow colocations where this resource is the dependent resource
262  colocations = pcmk__this_with_colocations(rsc);
263  for (iter = colocations; iter != NULL; iter = iter->next) {
264  const pcmk__colocation_t *constraint = iter->data;
265  const pcmk_resource_t *primary = constraint->primary;
266 
267  if (primary == orig_rsc) {
268  continue; // Break colocation loop
269  }
270 
271  if ((constraint->score == PCMK_SCORE_INFINITY) &&
272  (pcmk__colocation_affects(rsc, primary, constraint,
273  true) == pcmk__coloc_affects_location)) {
274  add_colocated_resources(primary, orig_rsc, &colocated_rscs);
275  }
276  }
277  g_list_free(colocations);
278 
279  // Follow colocations where this resource is the primary resource
280  colocations = pcmk__with_this_colocations(rsc);
281  for (iter = colocations; iter != NULL; iter = iter->next) {
282  const pcmk__colocation_t *constraint = iter->data;
283  const pcmk_resource_t *dependent = constraint->dependent;
284 
285  if (dependent == orig_rsc) {
286  continue; // Break colocation loop
287  }
288 
289  if (pcmk__is_clone(rsc) && !pcmk__is_clone(dependent)) {
290  continue; // We can't be sure whether dependent will be colocated
291  }
292 
293  if ((constraint->score == PCMK_SCORE_INFINITY) &&
294  (pcmk__colocation_affects(dependent, rsc, constraint,
295  true) == pcmk__coloc_affects_location)) {
296  add_colocated_resources(dependent, orig_rsc, &colocated_rscs);
297  }
298  }
299  g_list_free(colocations);
300 
301  return colocated_rscs;
302 }
303 
304 // No-op function for variants that don't need to implement add_graph_meta()
305 void
307 {
308 }
309 
316 void
318 {
319  pcmk_node_t *next = NULL;
320  pcmk_node_t *current = NULL;
321  pcmk__output_t *out = NULL;
322 
323  CRM_ASSERT(rsc != NULL);
324 
325  out = rsc->cluster->priv;
326  if (rsc->children != NULL) {
327  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
328  pcmk_resource_t *child = (pcmk_resource_t *) iter->data;
329 
330  child->cmds->output_actions(child);
331  }
332  return;
333  }
334 
335  next = rsc->allocated_to;
336  if (rsc->running_on) {
337  current = pcmk__current_node(rsc);
338  if (rsc->role == pcmk_role_stopped) {
339  /* This can occur when resources are being recovered because
340  * the current role can change in pcmk__primitive_create_actions()
341  */
342  rsc->role = pcmk_role_started;
343  }
344  }
345 
346  if ((current == NULL) && pcmk_is_set(rsc->flags, pcmk_rsc_removed)) {
347  /* Don't log stopped orphans */
348  return;
349  }
350 
351  out->message(out, "rsc-action", rsc, current, next);
352 }
353 
361 static inline void
362 add_assigned_resource(pcmk_node_t *node, pcmk_resource_t *rsc)
363 {
364  node->details->allocated_rsc = g_list_prepend(node->details->allocated_rsc,
365  rsc);
366 }
367 
403 bool
405  bool stop_if_fail)
406 {
407  bool changed = false;
408 
409  CRM_ASSERT(rsc != NULL);
410 
411  if (rsc->children != NULL) {
412  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
413  pcmk_resource_t *child_rsc = iter->data;
414 
415  changed |= pcmk__assign_resource(child_rsc, node, force,
416  stop_if_fail);
417  }
418  return changed;
419  }
420 
421  // Assigning a primitive
422 
423  if (!force && (node != NULL)
424  && ((node->weight < 0)
425  // Allow graph to assume that guest node connections will come up
426  || (!pcmk__node_available(node, true, false)
427  && !pcmk__is_guest_or_bundle_node(node)))) {
428 
429  pcmk__rsc_debug(rsc,
430  "All nodes for resource %s are unavailable, unclean or "
431  "shutting down (%s can%s run resources, with score %s)",
432  rsc->id, pcmk__node_name(node),
433  (pcmk__node_available(node, true, false)? "" : "not"),
434  pcmk_readable_score(node->weight));
435 
436  if (stop_if_fail) {
437  pe__set_next_role(rsc, pcmk_role_stopped, "node availability");
438  }
439  node = NULL;
440  }
441 
442  if (rsc->allocated_to != NULL) {
443  changed = !pcmk__same_node(rsc->allocated_to, node);
444  } else {
445  changed = (node != NULL);
446  }
449 
450  if (node == NULL) {
451  char *rc_stopped = NULL;
452 
453  pcmk__rsc_debug(rsc, "Could not assign %s to a node", rsc->id);
454 
455  if (!stop_if_fail) {
456  return changed;
457  }
458  pe__set_next_role(rsc, pcmk_role_stopped, "unable to assign");
459 
460  for (GList *iter = rsc->actions; iter != NULL; iter = iter->next) {
461  pcmk_action_t *op = (pcmk_action_t *) iter->data;
462 
463  pcmk__rsc_debug(rsc, "Updating %s for %s assignment failure",
464  op->uuid, rsc->id);
465 
466  if (pcmk__str_eq(op->task, PCMK_ACTION_STOP, pcmk__str_none)) {
468 
469  } else if (pcmk__str_eq(op->task, PCMK_ACTION_START,
470  pcmk__str_none)) {
472 
473  } else {
474  // Cancel recurring actions, unless for stopped state
475  const char *interval_ms_s = NULL;
476  const char *target_rc_s = NULL;
477 
478  interval_ms_s = g_hash_table_lookup(op->meta,
480  target_rc_s = g_hash_table_lookup(op->meta,
482  if (rc_stopped == NULL) {
483  rc_stopped = pcmk__itoa(PCMK_OCF_NOT_RUNNING);
484  }
485 
486  if (!pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches)
487  && !pcmk__str_eq(rc_stopped, target_rc_s, pcmk__str_none)) {
488 
490  }
491  }
492  }
493  free(rc_stopped);
494  return changed;
495  }
496 
497  pcmk__rsc_debug(rsc, "Assigning %s to %s", rsc->id, pcmk__node_name(node));
498  rsc->allocated_to = pe__copy_node(node);
499 
500  add_assigned_resource(node, rsc);
501  node->details->num_resources++;
502  node->count++;
504 
506  pcmk__output_t *out = rsc->cluster->priv;
507 
508  out->message(out, "resource-util", rsc, node, __func__);
509  }
510  return changed;
511 }
512 
524 void
526 {
527  pcmk_node_t *old = rsc->allocated_to;
528 
529  if (old == NULL) {
530  crm_info("Unassigning %s", rsc->id);
531  } else {
532  crm_info("Unassigning %s from %s", rsc->id, pcmk__node_name(old));
533  }
534 
536 
537  if (rsc->children == NULL) {
538  if (old == NULL) {
539  return;
540  }
541  rsc->allocated_to = NULL;
542 
543  /* We're going to free the pcmk_node_t, but its details member is shared
544  * and will remain, so update that appropriately first.
545  */
546  old->details->allocated_rsc = g_list_remove(old->details->allocated_rsc,
547  rsc);
548  old->details->num_resources--;
550  free(old);
551  return;
552  }
553 
554  for (GList *iter = rsc->children; iter != NULL; iter = iter->next) {
556  }
557 }
558 
570 bool
572  pcmk_resource_t **failed)
573 {
574  int fail_count, remaining_tries;
575  pcmk_resource_t *rsc_to_ban = rsc;
576 
577  // Migration threshold of 0 means never force away
578  if (rsc->migration_threshold == 0) {
579  return false;
580  }
581 
582  // If we're ignoring failures, also ignore the migration threshold
584  return false;
585  }
586 
587  // If there are no failures, there's no need to force away
588  fail_count = pe_get_failcount(node, rsc, NULL,
590  if (fail_count <= 0) {
591  return false;
592  }
593 
594  // If failed resource is anonymous clone instance, we'll force clone away
595  if (!pcmk_is_set(rsc->flags, pcmk_rsc_unique)) {
596  rsc_to_ban = uber_parent(rsc);
597  }
598 
599  // How many more times recovery will be tried on this node
600  remaining_tries = rsc->migration_threshold - fail_count;
601 
602  if (remaining_tries <= 0) {
603  pcmk__sched_warn("%s cannot run on %s due to reaching migration "
604  "threshold (clean up resource to allow again)"
605  CRM_XS " failures=%d "
607  rsc_to_ban->id, pcmk__node_name(node), fail_count,
608  rsc->migration_threshold);
609  if (failed != NULL) {
610  *failed = rsc_to_ban;
611  }
612  return true;
613  }
614 
615  crm_info("%s can fail %d more time%s on "
616  "%s before reaching migration threshold (%d)",
617  rsc_to_ban->id, remaining_tries, pcmk__plural_s(remaining_tries),
618  pcmk__node_name(node), rsc->migration_threshold);
619  return false;
620 }
621 
631 static int
632 get_node_score(const pcmk_node_t *node, GHashTable *nodes)
633 {
634  pcmk_node_t *found_node = NULL;
635 
636  if ((node != NULL) && (nodes != NULL)) {
637  found_node = g_hash_table_lookup(nodes, node->details->id);
638  }
639  return (found_node == NULL)? -PCMK_SCORE_INFINITY : found_node->weight;
640 }
641 
653 static gint
654 cmp_resources(gconstpointer a, gconstpointer b, gpointer data)
655 {
656  /* GLib insists that this function require gconstpointer arguments, but we
657  * make a small, temporary change to each argument (setting the
658  * pe_rsc_merging flag) during comparison
659  */
660  pcmk_resource_t *resource1 = (pcmk_resource_t *) a;
661  pcmk_resource_t *resource2 = (pcmk_resource_t *) b;
662  const GList *nodes = data;
663 
664  int rc = 0;
665  int r1_score = -PCMK_SCORE_INFINITY;
666  int r2_score = -PCMK_SCORE_INFINITY;
667  pcmk_node_t *r1_node = NULL;
668  pcmk_node_t *r2_node = NULL;
669  GHashTable *r1_nodes = NULL;
670  GHashTable *r2_nodes = NULL;
671  const char *reason = NULL;
672 
673  // Resources with highest priority should be assigned first
674  reason = "priority";
675  r1_score = resource1->priority;
676  r2_score = resource2->priority;
677  if (r1_score > r2_score) {
678  rc = -1;
679  goto done;
680  }
681  if (r1_score < r2_score) {
682  rc = 1;
683  goto done;
684  }
685 
686  // We need nodes to make any other useful comparisons
687  reason = "no node list";
688  if (nodes == NULL) {
689  goto done;
690  }
691 
692  // Calculate and log node scores
693  resource1->cmds->add_colocated_node_scores(resource1, NULL, resource1->id,
694  &r1_nodes, NULL, 1,
696  resource2->cmds->add_colocated_node_scores(resource2, NULL, resource2->id,
697  &r2_nodes, NULL, 1,
699  pe__show_node_scores(true, NULL, resource1->id, r1_nodes,
700  resource1->cluster);
701  pe__show_node_scores(true, NULL, resource2->id, r2_nodes,
702  resource2->cluster);
703 
704  // The resource with highest score on its current node goes first
705  reason = "current location";
706  if (resource1->running_on != NULL) {
707  r1_node = pcmk__current_node(resource1);
708  }
709  if (resource2->running_on != NULL) {
710  r2_node = pcmk__current_node(resource2);
711  }
712  r1_score = get_node_score(r1_node, r1_nodes);
713  r2_score = get_node_score(r2_node, r2_nodes);
714  if (r1_score > r2_score) {
715  rc = -1;
716  goto done;
717  }
718  if (r1_score < r2_score) {
719  rc = 1;
720  goto done;
721  }
722 
723  // Otherwise a higher score on any node will do
724  reason = "score";
725  for (const GList *iter = nodes; iter != NULL; iter = iter->next) {
726  const pcmk_node_t *node = (const pcmk_node_t *) iter->data;
727 
728  r1_score = get_node_score(node, r1_nodes);
729  r2_score = get_node_score(node, r2_nodes);
730  if (r1_score > r2_score) {
731  rc = -1;
732  goto done;
733  }
734  if (r1_score < r2_score) {
735  rc = 1;
736  goto done;
737  }
738  }
739 
740 done:
741  crm_trace("%s (%d)%s%s %c %s (%d)%s%s: %s",
742  resource1->id, r1_score,
743  ((r1_node == NULL)? "" : " on "),
744  ((r1_node == NULL)? "" : r1_node->details->id),
745  ((rc < 0)? '>' : ((rc > 0)? '<' : '=')),
746  resource2->id, r2_score,
747  ((r2_node == NULL)? "" : " on "),
748  ((r2_node == NULL)? "" : r2_node->details->id),
749  reason);
750  if (r1_nodes != NULL) {
751  g_hash_table_destroy(r1_nodes);
752  }
753  if (r2_nodes != NULL) {
754  g_hash_table_destroy(r2_nodes);
755  }
756  return rc;
757 }
758 
765 void
767 {
768  GList *nodes = g_list_copy(scheduler->nodes);
769 
770  nodes = pcmk__sort_nodes(nodes, NULL);
771  scheduler->resources = g_list_sort_with_data(scheduler->resources,
772  cmp_resources, nodes);
773  g_list_free(nodes);
774 }
pcmk_assignment_methods_t * cmds
Definition: resources.h:413
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:245
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:89
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:591
#define crm_notice(fmt, args...)
Definition: logging.h:397
G_GNUC_INTERNAL void pcmk__apply_location(pcmk_resource_t *rsc, pcmk__location_t *constraint)
pcmk_scheduler_t * cluster
Definition: resources.h:408
void(* output_actions)(pcmk_resource_t *rsc)
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:1007
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:86
G_GNUC_INTERNAL void pcmk__release_node_capacity(GHashTable *current_utilization, const pcmk_resource_t *rsc)
enum rsc_role_e role
Definition: resources.h:464
GList * children
Definition: resources.h:471
#define pcmk__rsc_trace(rsc, fmt, args...)
int count
Definition: nodes.h:164
G_GNUC_INTERNAL void pcmk__bundle_add_utilization(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *all_rscs, GHashTable *utilization)
xmlNode * xml
Definition: resources.h:400
#define PCMK__META_OP_TARGET_RC
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:190
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_XA_PROVIDER
Definition: xml_names.h:359
G_GNUC_INTERNAL void pcmk__with_bundle_colocations(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList **list)
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)
int migration_threshold
Definition: resources.h:422
bool pcmk__rsc_agent_changed(pcmk_resource_t *rsc, pcmk_node_t *node, const xmlNode *rsc_entry, bool active_on_node)
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:425
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:361
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)
GList * resources
Definition: scheduler.h:231
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)
int weight
Definition: nodes.h:162
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:1253
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)
#define pcmk__clear_action_flags(action, flags_to_clear)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:446
#define stop_key(rsc)
Definition: internal.h:213
void pcmk__set_assignment_methods(pcmk_scheduler_t *scheduler)
char * task
Definition: actions.h:343
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:404
int num_resources
Definition: nodes.h:132
GHashTable * meta
Definition: actions.h:354
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:98
struct pe_node_shared_s * details
Definition: nodes.h:167
G_GNUC_INTERNAL void pcmk__clone_create_actions(pcmk_resource_t *rsc)
#define PCMK_ACTION_START
Definition: actions.h:72
GList * pcmk__rscs_matching_id(const char *id, const pcmk_scheduler_t *scheduler)
unsigned long long flags
Definition: resources.h:428
Wrappers for and extensions to libxml2.
char * clone_name
Definition: resources.h:397
#define PCMK__NELEM(a)
Definition: internal.h:48
#define PCMK_ACTION_STOP
Definition: actions.h:75
GList * actions
Definition: resources.h:444
GList *(* colocated_resources)(const pcmk_resource_t *rsc, const pcmk_resource_t *orig_rsc, GList *colocated_rscs)
#define pcmk__set_rsc_flags(resource, flags_to_set)
char * uuid
Definition: actions.h:344
G_GNUC_INTERNAL pcmk_node_t * pcmk__clone_assign(pcmk_resource_t *rsc, const pcmk_node_t *prefer, bool stop_if_fail)
enum pe_obj_types variant
Definition: resources.h:410
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)
const char * id
Definition: nodes.h:72
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:1129
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
G_GNUC_INTERNAL void pcmk__add_rsc_actions_to_graph(pcmk_resource_t *rsc)
#define CRM_XS
Definition: logging.h:56
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:241
G_GNUC_INTERNAL void pcmk__group_apply_location(pcmk_resource_t *rsc, pcmk__location_t *location)
#define PCMK_META_INTERVAL
Definition: options.h:91
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:35
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
#define CRM_ASSERT(expr)
Definition: results.h:42
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)
#define pcmk__sched_warn(fmt...)
Started.
Definition: roles.h:37
This structure contains everything that makes up a single output formatter.
pcmk_node_t * allocated_to
Definition: resources.h:447
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)
GHashTable * utilization
Definition: nodes.h:143
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:176
#define pcmk__plural_s(i)
G_GNUC_INTERNAL void pcmk__primitive_shutdown_lock(pcmk_resource_t *rsc)
GList * running_on
Definition: resources.h:456
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)
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)
G_GNUC_INTERNAL uint32_t pcmk__clone_action_flags(pcmk_action_t *action, const pcmk_node_t *node)
unsigned long long flags
Definition: scheduler.h:211
GList * allocated_rsc
Definition: nodes.h:141
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:399
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
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)
G_GNUC_INTERNAL void pcmk__primitive_internal_constraints(pcmk_resource_t *rsc)
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:24