pacemaker  3.0.0-d8340737c4
Scalable High-Availability cluster resource manager
utils.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 Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <glib.h>
13 #include <stdbool.h>
14 
15 #include <crm/crm.h>
16 #include <crm/common/xml.h>
17 #include <crm/pengine/rules.h>
18 #include <crm/pengine/internal.h>
19 
20 #include "pe_status_private.h"
21 
22 extern bool pcmk__is_daemon;
23 
24 gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data);
25 
35 bool
37 {
38  if (pcmk__is_guest_or_bundle_node(node)) {
39  /* A guest or bundle node is fenced by stopping its launcher, which is
40  * possible if the launcher's host is either online or fenceable.
41  */
42  pcmk_resource_t *rsc = node->priv->remote->priv->launcher;
43 
44  for (GList *n = rsc->priv->active_nodes; n != NULL; n = n->next) {
45  pcmk_node_t *launcher_node = n->data;
46 
47  if (!launcher_node->details->online
48  && !pe_can_fence(scheduler, launcher_node)) {
49  return false;
50  }
51  }
52  return true;
53 
55  return false; /* Turned off */
56 
58  return false; /* No devices */
59 
61  return true;
62 
64  return true;
65 
66  } else if(node == NULL) {
67  return false;
68 
69  } else if(node->details->online) {
70  crm_notice("We can fence %s without quorum because they're in our membership",
71  pcmk__node_name(node));
72  return true;
73  }
74 
75  crm_trace("Cannot fence %s", pcmk__node_name(node));
76  return false;
77 }
78 
91 pe__copy_node(const pcmk_node_t *this_node)
92 {
93  pcmk_node_t *new_node = NULL;
94 
95  pcmk__assert(this_node != NULL);
96 
97  new_node = pcmk__assert_alloc(1, sizeof(pcmk_node_t));
98  new_node->assign = pcmk__assert_alloc(1,
99  sizeof(struct pcmk__node_assignment));
100 
101  new_node->assign->probe_mode = this_node->assign->probe_mode;
102  new_node->assign->score = this_node->assign->score;
103  new_node->assign->count = this_node->assign->count;
104  new_node->details = this_node->details;
105  new_node->priv = this_node->priv;
106 
107  return new_node;
108 }
109 
118 GHashTable *
119 pe__node_list2table(const GList *list)
120 {
121  GHashTable *result = NULL;
122 
124  for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
125  pcmk_node_t *new_node = NULL;
126 
127  new_node = pe__copy_node((const pcmk_node_t *) gIter->data);
128  g_hash_table_insert(result, (gpointer) new_node->priv->id, new_node);
129  }
130  return result;
131 }
132 
148 gint
149 pe__cmp_node_name(gconstpointer a, gconstpointer b)
150 {
151  const pcmk_node_t *node1 = (const pcmk_node_t *) a;
152  const pcmk_node_t *node2 = (const pcmk_node_t *) b;
153 
154  if ((node1 == NULL) && (node2 == NULL)) {
155  return 0;
156  }
157 
158  if (node1 == NULL) {
159  return -1;
160  }
161 
162  if (node2 == NULL) {
163  return 1;
164  }
165 
167 }
168 
178 static void
179 pe__output_node_weights(const pcmk_resource_t *rsc, const char *comment,
180  GHashTable *nodes, pcmk_scheduler_t *scheduler)
181 {
182  pcmk__output_t *out = scheduler->priv->out;
183 
184  // Sort the nodes so the output is consistent for regression tests
185  GList *list = g_list_sort(g_hash_table_get_values(nodes),
187 
188  for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
189  const pcmk_node_t *node = (const pcmk_node_t *) gIter->data;
190 
191  out->message(out, "node-weight", rsc, comment, node->priv->name,
193  }
194  g_list_free(list);
195 }
196 
208 static void
209 pe__log_node_weights(const char *file, const char *function, int line,
210  const pcmk_resource_t *rsc, const char *comment,
211  GHashTable *nodes)
212 {
213  GHashTableIter iter;
214  pcmk_node_t *node = NULL;
215 
216  // Don't waste time if we're not tracing at this point
217  pcmk__if_tracing({}, return);
218 
219  g_hash_table_iter_init(&iter, nodes);
220  while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
221  if (rsc) {
222  qb_log_from_external_source(function, file,
223  "%s: %s allocation score on %s: %s",
224  LOG_TRACE, line, 0,
225  comment, rsc->id,
226  pcmk__node_name(node),
227  pcmk_readable_score(node->assign->score));
228  } else {
229  qb_log_from_external_source(function, file, "%s: %s = %s",
230  LOG_TRACE, line, 0,
231  comment, pcmk__node_name(node),
232  pcmk_readable_score(node->assign->score));
233  }
234  }
235 }
236 
251 void
252 pe__show_node_scores_as(const char *file, const char *function, int line,
253  bool to_log, const pcmk_resource_t *rsc,
254  const char *comment, GHashTable *nodes,
256 {
257  if ((rsc != NULL) && pcmk_is_set(rsc->flags, pcmk__rsc_removed)) {
258  // Don't show allocation scores for orphans
259  return;
260  }
261  if (nodes == NULL) {
262  // Nothing to show
263  return;
264  }
265 
266  if (to_log) {
267  pe__log_node_weights(file, function, line, rsc, comment, nodes);
268  } else {
269  pe__output_node_weights(rsc, comment, nodes, scheduler);
270  }
271 
272  if (rsc == NULL) {
273  return;
274  }
275 
276  // If this resource has children, repeat recursively for each
277  for (GList *gIter = rsc->priv->children;
278  gIter != NULL; gIter = gIter->next) {
279 
280  pcmk_resource_t *child = (pcmk_resource_t *) gIter->data;
281 
282  pe__show_node_scores_as(file, function, line, to_log, child, comment,
283  child->priv->allowed_nodes, scheduler);
284  }
285 }
286 
298 gint
299 pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
300 {
301  const pcmk_resource_t *resource1 = (const pcmk_resource_t *)a;
302  const pcmk_resource_t *resource2 = (const pcmk_resource_t *)b;
303 
304  if (a == NULL && b == NULL) {
305  return 0;
306  }
307  if (a == NULL) {
308  return 1;
309  }
310  if (b == NULL) {
311  return -1;
312  }
313 
314  if (resource1->priv->priority > resource2->priv->priority) {
315  return -1;
316  }
317 
318  if (resource1->priv->priority < resource2->priv->priority) {
319  return 1;
320  }
321 
322  return 0;
323 }
324 
325 static void
326 resource_node_score(pcmk_resource_t *rsc, const pcmk_node_t *node, int score,
327  const char *tag)
328 {
329  pcmk_node_t *match = NULL;
330 
332  || (node->assign->probe_mode == pcmk__probe_never))
333  && pcmk__str_eq(tag, "symmetric_default", pcmk__str_casei)) {
334  /* This string comparision may be fragile, but exclusive resources and
335  * exclusive nodes should not have the symmetric_default constraint
336  * applied to them.
337  */
338  return;
339 
340  } else {
341  for (GList *gIter = rsc->priv->children;
342  gIter != NULL; gIter = gIter->next) {
343 
344  pcmk_resource_t *child_rsc = (pcmk_resource_t *) gIter->data;
345 
346  resource_node_score(child_rsc, node, score, tag);
347  }
348  }
349 
350  match = g_hash_table_lookup(rsc->priv->allowed_nodes, node->priv->id);
351  if (match == NULL) {
352  match = pe__copy_node(node);
353  g_hash_table_insert(rsc->priv->allowed_nodes,
354  (gpointer) match->priv->id, match);
355  }
356  match->assign->score = pcmk__add_scores(match->assign->score, score);
357  pcmk__rsc_trace(rsc,
358  "Enabling %s preference (%s) for %s on %s (now %s)",
359  tag, pcmk_readable_score(score), rsc->id,
360  pcmk__node_name(node),
361  pcmk_readable_score(match->assign->score));
362 }
363 
364 void
365 resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score,
366  const char *tag, pcmk_scheduler_t *scheduler)
367 {
368  if (node != NULL) {
369  resource_node_score(rsc, node, score, tag);
370 
371  } else if (scheduler != NULL) {
372  GList *gIter = scheduler->nodes;
373 
374  for (; gIter != NULL; gIter = gIter->next) {
375  pcmk_node_t *node_iter = (pcmk_node_t *) gIter->data;
376 
377  resource_node_score(rsc, node_iter, score, tag);
378  }
379 
380  } else {
381  GHashTableIter iter;
382  pcmk_node_t *node_iter = NULL;
383 
384  g_hash_table_iter_init(&iter, rsc->priv->allowed_nodes);
385  while (g_hash_table_iter_next(&iter, NULL, (void **)&node_iter)) {
386  resource_node_score(rsc, node_iter, score, tag);
387  }
388  }
389 
390  if ((node == NULL) && (score == -PCMK_SCORE_INFINITY)
391  && (rsc->priv->assigned_node != NULL)) {
392 
393  // @TODO Should this be more like pcmk__unassign_resource()?
394  crm_info("Unassigning %s from %s",
395  rsc->id, pcmk__node_name(rsc->priv->assigned_node));
397  rsc->priv->assigned_node = NULL;
398  }
399 }
400 
401 time_t
403 {
404  if(scheduler) {
405  if (scheduler->priv->now == NULL) {
406  crm_trace("Recording a new 'now'");
407  scheduler->priv->now = crm_time_new(NULL);
408  }
410  }
411 
412  crm_trace("Defaulting to 'now'");
413  return time(NULL);
414 }
415 
416 gboolean
418 {
419  enum rsc_role_e local_role = pcmk_role_unknown;
420  const char *value = g_hash_table_lookup(rsc->priv->meta,
422 
423  CRM_CHECK(role != NULL, return FALSE);
424 
425  if (pcmk__str_eq(value, PCMK_ROLE_STARTED,
427  return FALSE;
428  }
429  if (pcmk__str_eq(PCMK_VALUE_DEFAULT, value, pcmk__str_casei)) {
430  // @COMPAT Deprecated since 2.1.8
431  pcmk__config_warn("Support for setting " PCMK_META_TARGET_ROLE
432  " to the explicit value '" PCMK_VALUE_DEFAULT
433  "' is deprecated and will be removed in a "
434  "future release (just leave it unset)");
435  return FALSE;
436  }
437 
438  local_role = pcmk_parse_role(value);
439  if (local_role == pcmk_role_unknown) {
440  pcmk__config_err("Ignoring '" PCMK_META_TARGET_ROLE "' for %s "
441  "because '%s' is not valid", rsc->id, value);
442  return FALSE;
443 
444  } else if (local_role > pcmk_role_started) {
445  if (pcmk_is_set(pe__const_top_resource(rsc, false)->flags,
447  if (local_role > pcmk_role_unpromoted) {
448  /* This is what we'd do anyway, just leave the default to avoid messing up the placement algorithm */
449  return FALSE;
450  }
451 
452  } else {
453  pcmk__config_err("Ignoring '" PCMK_META_TARGET_ROLE "' for %s "
454  "because '%s' only makes sense for promotable "
455  "clones", rsc->id, value);
456  return FALSE;
457  }
458  }
459 
460  *role = local_role;
461  return TRUE;
462 }
463 
464 gboolean
466 {
467  GList *gIter = NULL;
468  pcmk__related_action_t *wrapper = NULL;
469  GList *list = NULL;
470 
471  if (flags == pcmk__ar_none) {
472  return FALSE;
473  }
474 
475  if ((first == NULL) || (then == NULL)) {
476  return FALSE;
477  }
478 
479  crm_trace("Creating action wrappers for ordering: %s then %s",
480  first->uuid, then->uuid);
481 
482  /* Ensure we never create a dependency on ourselves... it's happened */
483  pcmk__assert(first != then);
484 
485  /* Filter dups, otherwise update_action_states() has too much work to do */
486  gIter = first->actions_after;
487  for (; gIter != NULL; gIter = gIter->next) {
488  pcmk__related_action_t *after = gIter->data;
489 
490  if ((after->action == then)
491  && pcmk_any_flags_set(after->flags, flags)) {
492  return FALSE;
493  }
494  }
495 
496  wrapper = pcmk__assert_alloc(1, sizeof(pcmk__related_action_t));
497  wrapper->action = then;
498  wrapper->flags = flags;
499  list = first->actions_after;
500  list = g_list_prepend(list, wrapper);
501  first->actions_after = list;
502 
503  wrapper = pcmk__assert_alloc(1, sizeof(pcmk__related_action_t));
504  wrapper->action = first;
505  wrapper->flags = flags;
506  list = then->actions_before;
507  list = g_list_prepend(list, wrapper);
508  then->actions_before = list;
509  return TRUE;
510 }
511 
512 void
514 {
515  pcmk__ticket_t *ticket = data;
516 
517  if (ticket->state) {
518  g_hash_table_destroy(ticket->state);
519  }
520  free(ticket->id);
521  free(ticket);
522 }
523 
525 ticket_new(const char *ticket_id, pcmk_scheduler_t *scheduler)
526 {
527  pcmk__ticket_t *ticket = NULL;
528 
529  if (pcmk__str_empty(ticket_id)) {
530  return NULL;
531  }
532 
533  if (scheduler->priv->ticket_constraints == NULL) {
536  }
537 
538  ticket = g_hash_table_lookup(scheduler->priv->ticket_constraints,
539  ticket_id);
540  if (ticket == NULL) {
541 
542  ticket = calloc(1, sizeof(pcmk__ticket_t));
543  if (ticket == NULL) {
544  pcmk__sched_err(scheduler, "Cannot allocate ticket '%s'",
545  ticket_id);
546  return NULL;
547  }
548 
549  crm_trace("Creating ticket entry for %s", ticket_id);
550 
551  ticket->id = strdup(ticket_id);
552  ticket->last_granted = -1;
553  ticket->state = pcmk__strkey_table(free, free);
554 
555  g_hash_table_insert(scheduler->priv->ticket_constraints,
556  pcmk__str_copy(ticket->id), ticket);
557  }
558 
559  return ticket;
560 }
561 
562 const char *
564 {
565  if (pcmk_is_set(rsc->flags, pcmk__rsc_unique)) {
566  return rsc->id;
567  }
568  return pcmk__xe_id(rsc->priv->xml);
569 }
570 
571 void
573 {
575 
576  for (GList *gIter = rsc->priv->children;
577  gIter != NULL; gIter = gIter->next) {
578 
580  flags);
581  }
582 }
583 
584 void
586 {
587  for (GList *lpc = scheduler->priv->resources;
588  lpc != NULL; lpc = lpc->next) {
589 
590  pcmk_resource_t *r = (pcmk_resource_t *) lpc->data;
591 
593  }
594 }
595 
596 void
598 {
600 
601  for (GList *gIter = rsc->priv->children;
602  gIter != NULL; gIter = gIter->next) {
603 
605  flags);
606  }
607 }
608 
609 void
610 trigger_unfencing(pcmk_resource_t *rsc, pcmk_node_t *node, const char *reason,
612 {
614  /* No resources require it */
615  return;
616 
617  } else if ((rsc != NULL)
619  /* Wasn't a stonith device */
620  return;
621 
622  } else if(node
623  && node->details->online
624  && node->details->unclean == FALSE
625  && node->details->shutdown == FALSE) {
626  pcmk_action_t *unfence = pe_fence_op(node, PCMK_ACTION_ON, FALSE,
627  reason, FALSE, scheduler);
628 
629  if(dependency) {
630  order_actions(unfence, dependency, pcmk__ar_ordered);
631  }
632 
633  } else if(rsc) {
634  GHashTableIter iter;
635 
636  g_hash_table_iter_init(&iter, rsc->priv->allowed_nodes);
637  while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
638  if(node->details->online && node->details->unclean == FALSE && node->details->shutdown == FALSE) {
639  trigger_unfencing(rsc, node, reason, dependency, scheduler);
640  }
641  }
642  }
643 }
644 
657 bool
659 {
660  const char *shutdown = pcmk__node_attr(node, PCMK__NODE_ATTR_SHUTDOWN, NULL,
662 
663  return !pcmk__str_eq(shutdown, "0", pcmk__str_null_matches);
664 }
665 
674 void
676  const char *reason)
677 {
678  if ((recheck > get_effective_time(scheduler))
679  && ((scheduler->priv->recheck_by == 0)
680  || (scheduler->priv->recheck_by > recheck))) {
681  scheduler->priv->recheck_by = recheck;
682  crm_debug("Updated next scheduler recheck to %s for %s",
683  pcmk__trim(ctime(&recheck)), reason);
684  }
685 }
686 
700 void
701 pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name,
702  const pe_rule_eval_data_t *rule_data,
703  GHashTable *hash, const char *always_first,
705 {
706  crm_time_t *next_change = NULL;
707 
708  CRM_CHECK((set_name != NULL) && (rule_data != NULL) && (hash != NULL)
709  && (scheduler != NULL), return);
710 
711  // Node attribute expressions are not allowed for meta-attributes
712  CRM_CHECK((rule_data->node_hash == NULL)
713  || (strcmp(set_name, PCMK_XE_META_ATTRIBUTES) != 0), return);
714 
715  if (xml_obj == NULL) {
716  return;
717  }
718 
719  next_change = crm_time_new_undefined();
720  pe_eval_nvpairs(scheduler->input, xml_obj, set_name, rule_data, hash,
721  always_first, FALSE, next_change);
722  if (crm_time_is_defined(next_change)) {
723  time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change);
724 
725  pe__update_recheck_time(recheck, scheduler, "rule evaluation");
726  }
727  crm_time_free(next_change);
728 }
729 
730 bool
732 {
733  const char *target_role = NULL;
734 
735  CRM_CHECK(rsc != NULL, return false);
736  target_role = g_hash_table_lookup(rsc->priv->meta,
738  if (target_role) {
739  // If invalid, we've already logged an error when unpacking
740  enum rsc_role_e target_role_e = pcmk_parse_role(target_role);
741 
742  if ((target_role_e == pcmk_role_stopped)
743  || ((target_role_e == pcmk_role_unpromoted)
744  && pcmk_is_set(pe__const_top_resource(rsc, false)->flags,
746  return true;
747  }
748  }
749  return false;
750 }
751 
761 bool
763 {
764  return (rsc != NULL) && pcmk__list_of_1(rsc->priv->active_nodes)
765  && pcmk__same_node((const pcmk_node_t *)
766  rsc->priv->active_nodes->data, node);
767 }
768 
769 bool
771 {
772  if (rsc != NULL) {
773  for (GList *ele = rsc->priv->active_nodes; ele; ele = ele->next) {
774  pcmk_node_t *node = (pcmk_node_t *) ele->data;
775  if (pcmk__str_in_list(node->priv->name, node_list,
777  return true;
778  }
779  }
780  }
781  return false;
782 }
783 
784 bool
786 {
787  return rsc->priv->fns->active(rsc, FALSE)
788  && !pe__rsc_running_on_any(rsc, only_node);
789 }
790 
791 GList *
792 pe__filter_rsc_list(GList *rscs, GList *filter)
793 {
794  GList *retval = NULL;
795 
796  for (GList *gIter = rscs; gIter; gIter = gIter->next) {
797  pcmk_resource_t *rsc = (pcmk_resource_t *) gIter->data;
798 
799  /* I think the second condition is safe here for all callers of this
800  * function. If not, it needs to move into pe__node_text.
801  */
803  ((rsc->priv->parent != NULL)
805  filter, pcmk__str_star_matches))) {
806  retval = g_list_prepend(retval, rsc);
807  }
808  }
809 
810  return retval;
811 }
812 
813 GList *
815 {
816  GList *nodes = NULL;
817 
818  if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
819  /* Nothing was given so return a list of all node names. Or, '*' was
820  * given. This would normally fall into the pe__unames_with_tag branch
821  * where it will return an empty list. Catch it here instead.
822  */
823  nodes = g_list_prepend(nodes, strdup("*"));
824  } else {
826 
827  if (node) {
828  /* The given string was a valid uname for a node. Return a
829  * singleton list containing just that uname.
830  */
831  nodes = g_list_prepend(nodes, strdup(s));
832  } else {
833  /* The given string was not a valid uname. It's either a tag or
834  * it's a typo or something. In the first case, we'll return a
835  * list of all the unames of the nodes with the given tag. In the
836  * second case, we'll return a NULL pointer and nothing will
837  * get displayed.
838  */
839  nodes = pe__unames_with_tag(scheduler, s);
840  }
841  }
842 
843  return nodes;
844 }
845 
846 GList *
848 {
849  GList *resources = NULL;
850 
851  if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
852  resources = g_list_prepend(resources, strdup("*"));
853  } else {
855  pcmk_resource_t *rsc =
857 
858  if (rsc) {
859  /* A colon in the name we were given means we're being asked to filter
860  * on a specific instance of a cloned resource. Put that exact string
861  * into the filter list. Otherwise, use the printable ID of whatever
862  * resource was found that matches what was asked for.
863  */
864  if (strstr(s, ":") != NULL) {
865  resources = g_list_prepend(resources, strdup(rsc->id));
866  } else {
867  resources = g_list_prepend(resources, strdup(rsc_printable_id(rsc)));
868  }
869  } else {
870  /* The given string was not a valid resource name. It's a tag or a
871  * typo or something. See pe__build_node_name_list() for more
872  * detail.
873  */
874  resources = pe__rscs_with_tag(scheduler, s);
875  }
876  }
877 
878  return resources;
879 }
880 
881 xmlNode *
883 {
884  const pcmk_resource_t *parent = pe__const_top_resource(rsc, false);
885  const char *rsc_id = rsc->id;
886  const pcmk_scheduler_t *scheduler = rsc->priv->scheduler;
887 
888  if (pcmk__is_clone(parent)) {
889  rsc_id = pe__clone_child_id(parent);
890  }
891 
892  for (xmlNode *xml_op = pcmk__xe_first_child(scheduler->priv->failed,
893  NULL, NULL, NULL);
894  xml_op != NULL; xml_op = pcmk__xe_next(xml_op, NULL)) {
895 
896  const char *value = NULL;
897  char *op_id = NULL;
898 
899  /* This resource operation is not a failed probe. */
900  if (!pcmk_xe_mask_probe_failure(xml_op)) {
901  continue;
902  }
903 
904  /* This resource operation was not run on the given node. Note that if name is
905  * NULL, this will always succeed.
906  */
907  value = crm_element_value(xml_op, PCMK__META_ON_NODE);
908  if (value == NULL || !pcmk__str_eq(value, name, pcmk__str_casei|pcmk__str_null_matches)) {
909  continue;
910  }
911 
912  if (!parse_op_key(pcmk__xe_history_key(xml_op), &op_id, NULL, NULL)) {
913  continue; // This history entry is missing an operation key
914  }
915 
916  /* This resource operation's ID does not match the rsc_id we are looking for. */
917  if (!pcmk__str_eq(op_id, rsc_id, pcmk__str_none)) {
918  free(op_id);
919  continue;
920  }
921 
922  free(op_id);
923  return xml_op;
924  }
925 
926  return NULL;
927 }
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
Definition: iso8601.c:129
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
Definition: complex.c:1043
#define LOG_TRACE
Definition: logging.h:38
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:213
pcmk_node_t * pcmk_find_node(const pcmk_scheduler_t *scheduler, const char *node_name)
Find a node by name in scheduler data.
Definition: scheduler.c:100
enum pcmk__probe_mode probe_mode
A dumping ground.
void destroy_ticket(gpointer data)
Definition: utils.c:513
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml_element.c:42
#define crm_notice(fmt, args...)
Definition: logging.h:365
#define pcmk__sched_err(scheduler, fmt...)
#define PCMK__NODE_ATTR_SHUTDOWN
char data[0]
Definition: cpg.c:58
#define pcmk__if_tracing(if_action, else_action)
void pe__clear_resource_flags_on_all(pcmk_scheduler_t *scheduler, uint64_t flag)
Definition: utils.c:585
GHashTable * pe__node_list2table(const GList *list)
Definition: utils.c:119
gboolean(* active)(pcmk_resource_t *rsc, gboolean all)
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
Definition: iso8601.c:142
pcmk_resource_t * parent
Stopped.
Definition: roles.h:36
void pe__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, const char *reason)
Definition: utils.c:675
const char * name
Definition: cib.c:26
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
pcmk_resource_t * pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
Definition: status.c:459
struct crm_time_s crm_time_t
Definition: iso8601.h:32
#define pcmk__config_warn(fmt...)
#define pcmk__rsc_trace(rsc, fmt, args...)
void pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name, const pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, pcmk_scheduler_t *scheduler)
Definition: utils.c:701
#define PCMK_ACTION_ON
Definition: actions.h:55
#define pcmk__set_rsc_flags(resource, flags_to_set)
gboolean get_target_role(const pcmk_resource_t *rsc, enum rsc_role_e *role)
Definition: utils.c:417
#define pcmk__config_err(fmt...)
void pe__clear_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags)
Definition: utils.c:572
pcmk_action_t * pe_fence_op(pcmk_node_t *node, const char *op, bool optional, const char *reason, bool priority_delay, pcmk_scheduler_t *scheduler)
Definition: pe_actions.c:1245
pcmk__ticket_t * ticket_new(const char *ticket_id, pcmk_scheduler_t *scheduler)
Definition: utils.c:525
#define PCMK_VALUE_DEFAULT
Definition: options.h:143
pcmk__scheduler_private_t * priv
Definition: scheduler.h:99
uint64_t flags
Definition: scheduler.h:89
GList * pe__rscs_with_tag(pcmk_scheduler_t *scheduler, const char *tag_name)
Definition: tags.c:20
pcmk_node_t node2
gboolean shutdown
Definition: nodes.h:62
gboolean unclean
Definition: nodes.h:58
bool pe_can_fence(const pcmk_scheduler_t *scheduler, const pcmk_node_t *node)
Definition: utils.c:36
#define PCMK__META_ON_NODE
const pcmk__rsc_methods_t * fns
void pcmk__free_node_copy(void *data)
Definition: nodes.c:22
void pe__show_node_scores_as(const char *file, const char *function, int line, bool to_log, const pcmk_resource_t *rsc, const char *comment, GHashTable *nodes, pcmk_scheduler_t *scheduler)
Definition: utils.c:252
enum pe_quorum_policy no_quorum_policy
Definition: scheduler.h:93
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
Definition: roles.c:51
Also match clone instance ID from resource history.
Definition: resources.h:34
gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data)
GList * actions_after
void pe_eval_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name, const pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *next_change)
Extract nvpair blocks contained by an XML element into a hash table.
Definition: rules.c:185
pcmk__node_private_t * priv
Definition: nodes.h:85
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
Definition: utils.c:149
time_t get_effective_time(pcmk_scheduler_t *scheduler)
Definition: utils.c:402
#define crm_debug(fmt, args...)
Definition: logging.h:370
pcmk_scheduler_t * scheduler
Actions are ordered (optionally, if no other flags are set)
void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, const char *tag, pcmk_scheduler_t *scheduler)
Definition: utils.c:365
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: xml_element.c:1168
#define crm_trace(fmt, args...)
Definition: logging.h:372
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:80
GList * actions_before
pcmk__resource_private_t * priv
Definition: resources.h:61
GList * pe__unames_with_tag(pcmk_scheduler_t *scheduler, const char *tag_name)
Definition: tags.c:54
Unpromoted.
Definition: roles.h:38
Wrappers for and extensions to libxml2.
rsc_role_e
Definition: roles.h:34
#define PCMK_META_TARGET_ROLE
Definition: options.h:113
bool pe__resource_is_disabled(const pcmk_resource_t *rsc)
Definition: utils.c:731
Match clone instances (even unique) by base name as well as exact ID.
Definition: resources.h:46
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
Definition: utils.c:91
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
Act as if partition still holds quorum.
Definition: scheduler.h:41
int pcmk__add_scores(int score1, int score2)
Definition: scores.c:159
#define pcmk__str_copy(str)
long long crm_time_get_seconds_since_epoch(const crm_time_t *dt)
Definition: iso8601.c:374
bool pcmk_xe_mask_probe_failure(const xmlNode *xml_op)
Check whether an action history entry represents a maskable probe.
Definition: probes.c:70
#define PCMK_XE_META_ATTRIBUTES
Definition: xml_names.h:130
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
Definition: xml_element.c:106
#define pcmk__assert(expr)
bool pe__rsc_running_on_only(const pcmk_resource_t *rsc, const pcmk_node_t *node)
Definition: utils.c:762
GHashTable * state
GList * pe__build_node_name_list(pcmk_scheduler_t *scheduler, const char *s)
Definition: utils.c:814
GList * nodes
Definition: scheduler.h:97
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:685
pcmk__action_result_t result
Definition: pcmk_fence.c:37
#define PCMK_ROLE_STARTED
Definition: roles.h:26
pcmk_scheduler_t * scheduler
pcmk_resource_t * remote
GHashTable * node_hash
Definition: common.h:46
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:112
pcmk_resource_t * launcher
xmlNode * input
Definition: scheduler.h:81
const char * pcmk__node_attr(const pcmk_node_t *node, const char *name, const char *target, enum pcmk__rsc_node node_type)
Definition: attrs.c:114
gboolean order_actions(pcmk_action_t *first, pcmk_action_t *then, uint32_t flags)
Definition: utils.c:465
Started.
Definition: roles.h:37
This structure contains everything that makes up a single output formatter.
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition: actions.c:248
bool pe__rsc_running_on_any(pcmk_resource_t *rsc, GList *node_list)
Definition: utils.c:770
bool pe__shutdown_requested(const pcmk_node_t *node)
Definition: utils.c:658
xmlNode * pe__failed_probe_for_rsc(const pcmk_resource_t *rsc, const char *name)
Definition: utils.c:882
void pe__set_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags)
Definition: utils.c:597
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
Definition: strings.c:1079
const char * rsc_printable_id(const pcmk_resource_t *rsc)
Definition: utils.c:563
unsigned long long flags
Definition: resources.h:69
GList * pe__filter_rsc_list(GList *rscs, GList *filter)
Definition: utils.c:792
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
bool pcmk__is_daemon
Definition: logging.c:47
GList * pe__build_rsc_list(pcmk_scheduler_t *scheduler, const char *s)
Definition: utils.c:847
gboolean online
Definition: nodes.h:50
Resource role is unknown.
Definition: roles.h:35
char * pcmk__trim(char *str)
Definition: strings.c:530
const char * parent
Definition: cib.c:27
struct pcmk__node_details * details
Definition: nodes.h:82
pcmk_node_t node1
#define pcmk__assert_alloc(nmemb, size)
Definition: internal.h:257
bool pcmk__rsc_filtered_by_node(pcmk_resource_t *rsc, GList *only_node)
Definition: utils.c:785
const char * pe__clone_child_id(const pcmk_resource_t *rsc)
Definition: clone.c:1025
#define crm_info(fmt, args...)
Definition: logging.h:367
gint pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
Definition: utils.c:299
uint64_t flags
Definition: remote.c:211
No relation (compare with equality rather than bit set)
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:26
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)
Definition: strings.c:982
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:150
struct pcmk__node_assignment * assign
Definition: nodes.h:79