pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
utils.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2025 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>
18
19#include "pe_status_private.h"
20
21extern bool pcmk__is_daemon;
22
23gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data);
24
34bool
36{
37 if (pcmk__is_guest_or_bundle_node(node)) {
38 /* A guest or bundle node is fenced by stopping its launcher, which is
39 * possible if the launcher's host is either online or fenceable.
40 */
41 pcmk_resource_t *rsc = node->priv->remote->priv->launcher;
42
43 for (GList *n = rsc->priv->active_nodes; n != NULL; n = n->next) {
44 pcmk_node_t *launcher_node = n->data;
45
46 if (!launcher_node->details->online
47 && !pe_can_fence(scheduler, launcher_node)) {
48 return false;
49 }
50 }
51 return true;
52
54 return false; /* Turned off */
55
57 return false; /* No devices */
58
60 return true;
61
63 return true;
64
65 } else if (node == NULL) {
66 return false;
67
68 } else if (node->details->online) {
69 /* Remote nodes are marked online when we assign their resource to a
70 * node, not when they are actually started (see remote_connection_assigned)
71 * so the above test by itself isn't good enough.
72 */
73 if (pcmk__is_pacemaker_remote_node(node)
75 /* If we're on a system without quorum, it's entirely possible that
76 * the remote resource was automatically moved to a node on the
77 * partition with quorum. We can't tell that from this node - the
78 * best we can do is check if it's possible for the resource to run
79 * on another node in the partition with quorum. If so, it has
80 * likely been moved and we shouldn't fence it.
81 *
82 * NOTE: This condition appears to only come up in very limited
83 * circumstances. It at least requires some very lengthy fencing
84 * timeouts set, some way for fencing to still take place (a second
85 * NIC is how I've reproduced it in testing, but fence_scsi or
86 * sbd could work too), and a resource that runs on the remote node.
87 */
88 pcmk_resource_t *rsc = node->priv->remote;
89 pcmk_node_t *n = NULL;
90 GHashTableIter iter;
91
92 g_hash_table_iter_init(&iter, rsc->priv->allowed_nodes);
93 while (g_hash_table_iter_next(&iter, NULL, (void **) &n)) {
94 /* A node that's not online according to this non-quorum node
95 * is a node that's in another partition.
96 */
97 if (!n->details->online) {
98 return false;
99 }
100 }
101 }
102
103 crm_notice("We can fence %s without quorum because they're in our membership",
104 pcmk__node_name(node));
105 return true;
106 }
107
108 crm_trace("Cannot fence %s", pcmk__node_name(node));
109 return false;
110}
111
124pe__copy_node(const pcmk_node_t *this_node)
125{
126 pcmk_node_t *new_node = NULL;
127
128 pcmk__assert(this_node != NULL);
129
130 new_node = pcmk__assert_alloc(1, sizeof(pcmk_node_t));
131 new_node->assign = pcmk__assert_alloc(1,
132 sizeof(struct pcmk__node_assignment));
133
134 new_node->assign->probe_mode = this_node->assign->probe_mode;
135 new_node->assign->score = this_node->assign->score;
136 new_node->assign->count = this_node->assign->count;
137 new_node->details = this_node->details;
138 new_node->priv = this_node->priv;
139
140 return new_node;
141}
142
151GHashTable *
152pe__node_list2table(const GList *list)
153{
154 GHashTable *result = NULL;
155
157 for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
158 pcmk_node_t *new_node = NULL;
159
160 new_node = pe__copy_node((const pcmk_node_t *) gIter->data);
161 g_hash_table_insert(result, (gpointer) new_node->priv->id, new_node);
162 }
163 return result;
164}
165
181gint
182pe__cmp_node_name(gconstpointer a, gconstpointer b)
183{
184 const pcmk_node_t *node1 = (const pcmk_node_t *) a;
185 const pcmk_node_t *node2 = (const pcmk_node_t *) b;
186
187 if ((node1 == NULL) && (node2 == NULL)) {
188 return 0;
189 }
190
191 if (node1 == NULL) {
192 return -1;
193 }
194
195 if (node2 == NULL) {
196 return 1;
197 }
198
200}
201
211static void
212pe__output_node_weights(const pcmk_resource_t *rsc, const char *comment,
213 GHashTable *nodes, pcmk_scheduler_t *scheduler)
214{
216
217 // Sort the nodes so the output is consistent for regression tests
218 GList *list = g_list_sort(g_hash_table_get_values(nodes),
220
221 for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
222 const pcmk_node_t *node = (const pcmk_node_t *) gIter->data;
223
224 out->message(out, "node-weight", rsc, comment, node->priv->name,
225 pcmk_readable_score(node->assign->score));
226 }
227 g_list_free(list);
228}
229
241static void
242pe__log_node_weights(const char *file, const char *function, int line,
243 const pcmk_resource_t *rsc, const char *comment,
244 GHashTable *nodes)
245{
246 GHashTableIter iter;
247 pcmk_node_t *node = NULL;
248
249 // Don't waste time if we're not tracing at this point
250 pcmk__if_tracing({}, return);
251
252 g_hash_table_iter_init(&iter, nodes);
253 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
254 if (rsc) {
255 qb_log_from_external_source(function, file,
256 "%s: %s allocation score on %s: %s",
257 LOG_TRACE, line, 0,
258 comment, rsc->id,
259 pcmk__node_name(node),
260 pcmk_readable_score(node->assign->score));
261 } else {
262 qb_log_from_external_source(function, file, "%s: %s = %s",
263 LOG_TRACE, line, 0,
264 comment, pcmk__node_name(node),
265 pcmk_readable_score(node->assign->score));
266 }
267 }
268}
269
284void
285pe__show_node_scores_as(const char *file, const char *function, int line,
286 bool to_log, const pcmk_resource_t *rsc,
287 const char *comment, GHashTable *nodes,
289{
290 if ((rsc != NULL) && pcmk_is_set(rsc->flags, pcmk__rsc_removed)) {
291 // Don't show allocation scores for orphans
292 return;
293 }
294 if (nodes == NULL) {
295 // Nothing to show
296 return;
297 }
298
299 if (to_log) {
300 pe__log_node_weights(file, function, line, rsc, comment, nodes);
301 } else {
302 pe__output_node_weights(rsc, comment, nodes, scheduler);
303 }
304
305 if (rsc == NULL) {
306 return;
307 }
308
309 // If this resource has children, repeat recursively for each
310 for (GList *gIter = rsc->priv->children;
311 gIter != NULL; gIter = gIter->next) {
312
313 pcmk_resource_t *child = (pcmk_resource_t *) gIter->data;
314
315 pe__show_node_scores_as(file, function, line, to_log, child, comment,
316 child->priv->allowed_nodes, scheduler);
317 }
318}
319
331gint
332pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
333{
334 const pcmk_resource_t *resource1 = (const pcmk_resource_t *)a;
335 const pcmk_resource_t *resource2 = (const pcmk_resource_t *)b;
336
337 if (a == NULL && b == NULL) {
338 return 0;
339 }
340 if (a == NULL) {
341 return 1;
342 }
343 if (b == NULL) {
344 return -1;
345 }
346
347 if (resource1->priv->priority > resource2->priv->priority) {
348 return -1;
349 }
350
351 if (resource1->priv->priority < resource2->priv->priority) {
352 return 1;
353 }
354
355 return 0;
356}
357
358static void
359resource_node_score(pcmk_resource_t *rsc, const pcmk_node_t *node, int score,
360 const char *tag)
361{
362 pcmk_node_t *match = NULL;
363
365 || (node->assign->probe_mode == pcmk__probe_never))
366 && pcmk__str_eq(tag, "symmetric_default", pcmk__str_casei)) {
367 /* This string comparision may be fragile, but exclusive resources and
368 * exclusive nodes should not have the symmetric_default constraint
369 * applied to them.
370 */
371 return;
372
373 } else {
374 for (GList *gIter = rsc->priv->children;
375 gIter != NULL; gIter = gIter->next) {
376
377 pcmk_resource_t *child_rsc = (pcmk_resource_t *) gIter->data;
378
379 resource_node_score(child_rsc, node, score, tag);
380 }
381 }
382
383 match = g_hash_table_lookup(rsc->priv->allowed_nodes, node->priv->id);
384 if (match == NULL) {
385 match = pe__copy_node(node);
386 g_hash_table_insert(rsc->priv->allowed_nodes,
387 (gpointer) match->priv->id, match);
388 }
389 match->assign->score = pcmk__add_scores(match->assign->score, score);
390 pcmk__rsc_trace(rsc,
391 "Enabling %s preference (%s) for %s on %s (now %s)",
392 tag, pcmk_readable_score(score), rsc->id,
393 pcmk__node_name(node),
395}
396
397void
398resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score,
399 const char *tag, pcmk_scheduler_t *scheduler)
400{
401 if (node != NULL) {
402 resource_node_score(rsc, node, score, tag);
403
404 } else if (scheduler != NULL) {
405 GList *gIter = scheduler->nodes;
406
407 for (; gIter != NULL; gIter = gIter->next) {
408 pcmk_node_t *node_iter = (pcmk_node_t *) gIter->data;
409
410 resource_node_score(rsc, node_iter, score, tag);
411 }
412
413 } else {
414 GHashTableIter iter;
415 pcmk_node_t *node_iter = NULL;
416
417 g_hash_table_iter_init(&iter, rsc->priv->allowed_nodes);
418 while (g_hash_table_iter_next(&iter, NULL, (void **)&node_iter)) {
419 resource_node_score(rsc, node_iter, score, tag);
420 }
421 }
422
423 if ((node == NULL) && (score == -PCMK_SCORE_INFINITY)
424 && (rsc->priv->assigned_node != NULL)) {
425
426 // @TODO Should this be more like pcmk__unassign_resource()?
427 crm_info("Unassigning %s from %s",
428 rsc->id, pcmk__node_name(rsc->priv->assigned_node));
430 rsc->priv->assigned_node = NULL;
431 }
432}
433
434gboolean
436{
437 enum rsc_role_e local_role = pcmk_role_unknown;
438 const char *value = g_hash_table_lookup(rsc->priv->meta,
440
441 CRM_CHECK(role != NULL, return FALSE);
442
443 if (pcmk__str_eq(value, PCMK_ROLE_STARTED,
445 return FALSE;
446 }
447 if (pcmk__str_eq(PCMK_VALUE_DEFAULT, value, pcmk__str_casei)) {
448 // @COMPAT Deprecated since 2.1.8
449 pcmk__config_warn("Support for setting " PCMK_META_TARGET_ROLE
450 " to the explicit value '" PCMK_VALUE_DEFAULT
451 "' is deprecated and will be removed in a "
452 "future release (just leave it unset)");
453 return FALSE;
454 }
455
456 local_role = pcmk_parse_role(value);
457 if (local_role == pcmk_role_unknown) {
458 pcmk__config_err("Ignoring '" PCMK_META_TARGET_ROLE "' for %s "
459 "because '%s' is not valid", rsc->id, value);
460 return FALSE;
461
462 } else if (local_role > pcmk_role_started) {
465 if (local_role > pcmk_role_unpromoted) {
466 /* This is what we'd do anyway, just leave the default to avoid messing up the placement algorithm */
467 return FALSE;
468 }
469
470 } else {
471 pcmk__config_err("Ignoring '" PCMK_META_TARGET_ROLE "' for %s "
472 "because '%s' only makes sense for promotable "
473 "clones", rsc->id, value);
474 return FALSE;
475 }
476 }
477
478 *role = local_role;
479 return TRUE;
480}
481
482gboolean
484{
485 GList *gIter = NULL;
486 pcmk__related_action_t *wrapper = NULL;
487 GList *list = NULL;
488
489 if (flags == pcmk__ar_none) {
490 return FALSE;
491 }
492
493 if ((first == NULL) || (then == NULL)) {
494 return FALSE;
495 }
496
497 crm_trace("Creating action wrappers for ordering: %s then %s",
498 first->uuid, then->uuid);
499
500 /* Ensure we never create a dependency on ourselves... it's happened */
501 pcmk__assert(first != then);
502
503 /* Filter dups, otherwise update_action_states() has too much work to do */
504 gIter = first->actions_after;
505 for (; gIter != NULL; gIter = gIter->next) {
506 pcmk__related_action_t *after = gIter->data;
507
508 if ((after->action == then)
509 && pcmk_any_flags_set(after->flags, flags)) {
510 return FALSE;
511 }
512 }
513
514 wrapper = pcmk__assert_alloc(1, sizeof(pcmk__related_action_t));
515 wrapper->action = then;
516 wrapper->flags = flags;
517 list = first->actions_after;
518 list = g_list_prepend(list, wrapper);
519 first->actions_after = list;
520
521 wrapper = pcmk__assert_alloc(1, sizeof(pcmk__related_action_t));
522 wrapper->action = first;
523 wrapper->flags = flags;
524 list = then->actions_before;
525 list = g_list_prepend(list, wrapper);
526 then->actions_before = list;
527 return TRUE;
528}
529
530void
532{
533 pcmk__ticket_t *ticket = data;
534
535 if (ticket->state) {
536 g_hash_table_destroy(ticket->state);
537 }
538 free(ticket->id);
539 free(ticket);
540}
541
543ticket_new(const char *ticket_id, pcmk_scheduler_t *scheduler)
544{
545 pcmk__ticket_t *ticket = NULL;
546
547 if (pcmk__str_empty(ticket_id)) {
548 return NULL;
549 }
550
551 if (scheduler->priv->ticket_constraints == NULL) {
554 }
555
556 ticket = g_hash_table_lookup(scheduler->priv->ticket_constraints,
557 ticket_id);
558 if (ticket == NULL) {
559
560 ticket = calloc(1, sizeof(pcmk__ticket_t));
561 if (ticket == NULL) {
562 pcmk__sched_err(scheduler, "Cannot allocate ticket '%s'",
563 ticket_id);
564 return NULL;
565 }
566
567 crm_trace("Creating ticket entry for %s", ticket_id);
568
569 ticket->id = strdup(ticket_id);
570 ticket->last_granted = -1;
571 ticket->state = pcmk__strkey_table(free, free);
572
573 g_hash_table_insert(scheduler->priv->ticket_constraints,
574 pcmk__str_copy(ticket->id), ticket);
575 }
576
577 return ticket;
578}
579
580const char *
582{
584 return rsc->id;
585 }
586 return pcmk__xe_id(rsc->priv->xml);
587}
588
589void
591{
593
594 for (GList *gIter = rsc->priv->children;
595 gIter != NULL; gIter = gIter->next) {
596
598 flags);
599 }
600}
601
602void
604{
605 for (GList *lpc = scheduler->priv->resources;
606 lpc != NULL; lpc = lpc->next) {
607
608 pcmk_resource_t *r = (pcmk_resource_t *) lpc->data;
609
611 }
612}
613
614void
616{
618
619 for (GList *gIter = rsc->priv->children;
620 gIter != NULL; gIter = gIter->next) {
621
623 flags);
624 }
625}
626
627void
628trigger_unfencing(pcmk_resource_t *rsc, pcmk_node_t *node, const char *reason,
630{
632 /* No resources require it */
633 return;
634
635 } else if ((rsc != NULL)
637 /* Wasn't a stonith device */
638 return;
639
640 } else if(node
641 && node->details->online
642 && node->details->unclean == FALSE
643 && node->details->shutdown == FALSE) {
644 pcmk_action_t *unfence = pe_fence_op(node, PCMK_ACTION_ON, FALSE,
645 reason, FALSE, scheduler);
646
647 if(dependency) {
648 order_actions(unfence, dependency, pcmk__ar_ordered);
649 }
650
651 } else if(rsc) {
652 GHashTableIter iter;
653
654 g_hash_table_iter_init(&iter, rsc->priv->allowed_nodes);
655 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
656 if(node->details->online && node->details->unclean == FALSE && node->details->shutdown == FALSE) {
657 trigger_unfencing(rsc, node, reason, dependency, scheduler);
658 }
659 }
660 }
661}
662
675bool
677{
678 const char *shutdown = pcmk__node_attr(node, PCMK__NODE_ATTR_SHUTDOWN, NULL,
680
681 return !pcmk__str_eq(shutdown, "0", pcmk__str_null_matches);
682}
683
697void
698pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name,
699 const pcmk_rule_input_t *rule_input,
700 GHashTable *hash, const char *always_first,
702{
703 crm_time_t *next_change = NULL;
704
705 CRM_CHECK((set_name != NULL) && (rule_input != NULL) && (hash != NULL)
706 && (scheduler != NULL), return);
707
708 // Node attribute expressions are not allowed for meta-attributes
709 CRM_CHECK((rule_input->node_attrs == NULL)
710 || (strcmp(set_name, PCMK_XE_META_ATTRIBUTES) != 0), return);
711
712 if (xml_obj == NULL) {
713 return;
714 }
715
716 next_change = crm_time_new_undefined();
717 pcmk_unpack_nvpair_blocks(xml_obj, set_name, always_first, rule_input, hash,
718 next_change);
719 if (crm_time_is_defined(next_change)) {
720 time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change);
721
722 pcmk__update_recheck_time(recheck, scheduler, "rule evaluation");
723 }
724 crm_time_free(next_change);
725}
726
727bool
729{
730 const char *target_role = NULL;
731
732 CRM_CHECK(rsc != NULL, return false);
733 target_role = g_hash_table_lookup(rsc->priv->meta,
735 if (target_role) {
736 // If invalid, we've already logged an error when unpacking
737 enum rsc_role_e target_role_e = pcmk_parse_role(target_role);
738
739 if ((target_role_e == pcmk_role_stopped)
740 || ((target_role_e == pcmk_role_unpromoted)
743 return true;
744 }
745 }
746 return false;
747}
748
758bool
760{
761 return (rsc != NULL) && pcmk__list_of_1(rsc->priv->active_nodes)
762 && pcmk__same_node((const pcmk_node_t *)
763 rsc->priv->active_nodes->data, node);
764}
765
766bool
768{
769 if (rsc != NULL) {
770 for (GList *ele = rsc->priv->active_nodes; ele; ele = ele->next) {
771 pcmk_node_t *node = (pcmk_node_t *) ele->data;
772 if (pcmk__str_in_list(node->priv->name, node_list,
774 return true;
775 }
776 }
777 }
778 return false;
779}
780
781bool
783{
784 return rsc->priv->fns->active(rsc, false)
785 && !pe__rsc_running_on_any(rsc, only_node);
786}
787
788GList *
789pe__filter_rsc_list(GList *rscs, GList *filter)
790{
791 GList *retval = NULL;
792
793 for (GList *gIter = rscs; gIter; gIter = gIter->next) {
794 pcmk_resource_t *rsc = (pcmk_resource_t *) gIter->data;
795
796 /* I think the second condition is safe here for all callers of this
797 * function. If not, it needs to move into pe__node_text.
798 */
800 ((rsc->priv->parent != NULL)
802 filter, pcmk__str_star_matches))) {
803 retval = g_list_prepend(retval, rsc);
804 }
805 }
806
807 return retval;
808}
809
810GList *
812{
813 GList *nodes = NULL;
814
815 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
816 /* Nothing was given so return a list of all node names. Or, '*' was
817 * given. This would normally fall into the pe__unames_with_tag branch
818 * where it will return an empty list. Catch it here instead.
819 */
820 nodes = g_list_prepend(nodes, strdup("*"));
821 } else {
823
824 if (node) {
825 /* The given string was a valid uname for a node. Return a
826 * singleton list containing just that uname.
827 */
828 nodes = g_list_prepend(nodes, strdup(s));
829 } else {
830 /* The given string was not a valid uname. It's either a tag or
831 * it's a typo or something. In the first case, we'll return a
832 * list of all the unames of the nodes with the given tag. In the
833 * second case, we'll return a NULL pointer and nothing will
834 * get displayed.
835 */
836 nodes = pe__unames_with_tag(scheduler, s);
837 }
838 }
839
840 return nodes;
841}
842
843GList *
845{
846 GList *resources = NULL;
847
848 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
849 resources = g_list_prepend(resources, strdup("*"));
850 } else {
852 pcmk_resource_t *rsc =
854
855 if (rsc) {
856 /* A colon in the name we were given means we're being asked to filter
857 * on a specific instance of a cloned resource. Put that exact string
858 * into the filter list. Otherwise, use the printable ID of whatever
859 * resource was found that matches what was asked for.
860 */
861 if (strstr(s, ":") != NULL) {
862 resources = g_list_prepend(resources, strdup(rsc->id));
863 } else {
864 resources = g_list_prepend(resources, strdup(rsc_printable_id(rsc)));
865 }
866 } else {
867 /* The given string was not a valid resource name. It's a tag or a
868 * typo or something. See pe__build_node_name_list() for more
869 * detail.
870 */
871 resources = pe__rscs_with_tag(scheduler, s);
872 }
873 }
874
875 return resources;
876}
877
878xmlNode *
880{
881 const pcmk_resource_t *parent = pe__const_top_resource(rsc, false);
882 const char *rsc_id = rsc->id;
884
885 if (pcmk__is_clone(parent)) {
886 rsc_id = pe__clone_child_id(parent);
887 }
888
889 for (xmlNode *xml_op = pcmk__xe_first_child(scheduler->priv->failed,
890 NULL, NULL, NULL);
891 xml_op != NULL; xml_op = pcmk__xe_next(xml_op, NULL)) {
892
893 const char *value = NULL;
894 char *op_id = NULL;
895
896 /* This resource operation is not a failed probe. */
897 if (!pcmk_xe_mask_probe_failure(xml_op)) {
898 continue;
899 }
900
901 /* This resource operation was not run on the given node. Note that if name is
902 * NULL, this will always succeed.
903 */
904 value = crm_element_value(xml_op, PCMK__META_ON_NODE);
905 if (value == NULL || !pcmk__str_eq(value, name, pcmk__str_casei|pcmk__str_null_matches)) {
906 continue;
907 }
908
909 if (!parse_op_key(pcmk__xe_history_key(xml_op), &op_id, NULL, NULL)) {
910 continue; // This history entry is missing an operation key
911 }
912
913 /* This resource operation's ID does not match the rsc_id we are looking for. */
914 if (!pcmk__str_eq(op_id, rsc_id, pcmk__str_none)) {
915 free(op_id);
916 continue;
917 }
918
919 free(op_id);
920 return xml_op;
921 }
922
923 return NULL;
924}
@ pcmk__ar_none
No relation (compare with equality rather than bit set)
@ pcmk__ar_ordered
Actions are ordered (optionally, if no other flags are set)
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition actions.c:278
#define PCMK_ACTION_ON
Definition actions.h:55
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
const char * parent
Definition cib.c:27
const char * name
Definition cib.c:26
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:246
uint64_t flags
Definition remote.c:3
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:80
char data[0]
Definition cpg.c:10
A dumping ground.
long long crm_time_get_seconds_since_epoch(const crm_time_t *dt)
Definition iso8601.c:374
void crm_time_free(crm_time_t *dt)
Definition iso8601.c:150
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
Definition iso8601.c:142
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
Definition iso8601.c:129
struct crm_time_s crm_time_t
Definition iso8601.h:32
#define crm_info(fmt, args...)
Definition logging.h:365
#define crm_notice(fmt, args...)
Definition logging.h:363
#define CRM_CHECK(expr, failure_action)
Definition logging.h:213
#define crm_trace(fmt, args...)
Definition logging.h:370
#define LOG_TRACE
Definition logging.h:38
#define pcmk__config_warn(fmt...)
#define pcmk__config_err(fmt...)
#define pcmk__if_tracing(if_action, else_action)
pcmk_scheduler_t * scheduler
#define PCMK__NODE_ATTR_SHUTDOWN
void pcmk__free_node_copy(void *data)
Definition nodes.c:64
@ pcmk__probe_never
void pcmk_unpack_nvpair_blocks(const xmlNode *xml, const char *element_name, const char *first_id, const pcmk_rule_input_t *rule_input, GHashTable *values, crm_time_t *next_change)
Unpack nvpair blocks contained by an XML element into a hash table, evaluated for any rules.
Definition nvpair.c:483
#define PCMK_META_TARGET_ROLE
Definition options.h:114
#define PCMK_VALUE_DEFAULT
Definition options.h:144
#define PCMK__META_ON_NODE
pcmk__action_result_t result
Definition pcmk_fence.c:37
pcmk_node_t node2
pcmk_node_t node1
const pcmk_resource_t * pe__const_top_resource(const pcmk_resource_t *rsc, bool include_bundle)
Definition complex.c:1025
GList * pe__rscs_with_tag(pcmk_scheduler_t *scheduler, const char *tag_name)
Definition tags.c:20
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)
GList * pe__unames_with_tag(pcmk_scheduler_t *scheduler, const char *tag_name)
Definition tags.c:54
const char * pe__clone_child_id(const pcmk_resource_t *rsc)
Definition clone.c:1027
bool pe_can_fence(const pcmk_scheduler_t *scheduler, const pcmk_node_t *node)
Definition utils.c:35
pcmk_node_t * pe__copy_node(const pcmk_node_t *this_node)
Definition utils.c:124
GHashTable * pe__node_list2table(const GList *list)
Definition utils.c:152
gboolean get_target_role(const pcmk_resource_t *rsc, enum rsc_role_e *role)
Definition utils.c:435
GList * pe__build_rsc_list(pcmk_scheduler_t *scheduler, const char *s)
Definition utils.c:844
void destroy_ticket(gpointer data)
Definition utils.c:531
bool pe__rsc_running_on_any(pcmk_resource_t *rsc, GList *node_list)
Definition utils.c:767
void pe__set_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags)
Definition utils.c:615
void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, const char *tag, pcmk_scheduler_t *scheduler)
Definition utils.c:398
gint pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
Definition utils.c:332
gboolean order_actions(pcmk_action_t *first, pcmk_action_t *then, uint32_t flags)
Definition utils.c:483
void pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name, const pcmk_rule_input_t *rule_input, GHashTable *hash, const char *always_first, pcmk_scheduler_t *scheduler)
Definition utils.c:698
bool pe__rsc_running_on_only(const pcmk_resource_t *rsc, const pcmk_node_t *node)
Definition utils.c:759
pcmk__ticket_t * ticket_new(const char *ticket_id, pcmk_scheduler_t *scheduler)
Definition utils.c:543
GList * pe__filter_rsc_list(GList *rscs, GList *filter)
Definition utils.c:789
gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data)
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
Definition utils.c:182
void pe__clear_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags)
Definition utils.c:590
xmlNode * pe__failed_probe_for_rsc(const pcmk_resource_t *rsc, const char *name)
Definition utils.c:879
GList * pe__build_node_name_list(pcmk_scheduler_t *scheduler, const char *s)
Definition utils.c:811
void pe__clear_resource_flags_on_all(pcmk_scheduler_t *scheduler, uint64_t flag)
Definition utils.c:603
bool pcmk__is_daemon
Definition logging.c:47
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:285
bool pe__resource_is_disabled(const pcmk_resource_t *rsc)
Definition utils.c:728
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:628
bool pcmk__rsc_filtered_by_node(pcmk_resource_t *rsc, GList *only_node)
Definition utils.c:782
bool pe__shutdown_requested(const pcmk_node_t *node)
Definition utils.c:676
const char * rsc_printable_id(const pcmk_resource_t *rsc)
Definition utils.c:581
bool pcmk_xe_mask_probe_failure(const xmlNode *xml_op)
Check whether an action history entry represents a maskable probe.
Definition probes.c:70
@ pcmk_rsc_match_basename
Match clone instances (even unique) by base name as well as exact ID.
Definition resources.h:46
@ pcmk_rsc_match_history
Also match clone instance ID from resource history.
Definition resources.h:34
@ pcmk__rsc_unique
@ pcmk__rsc_removed
@ pcmk__rsc_promotable
@ pcmk__rsc_fence_device
@ pcmk__rsc_exclusive_probes
#define pcmk__set_rsc_flags(resource, flags_to_set)
@ pcmk__rsc_node_current
#define pcmk__clear_rsc_flags(resource, flags_to_clear)
#define pcmk__assert(expr)
#define PCMK_ROLE_STARTED
Definition roles.h:26
enum rsc_role_e pcmk_parse_role(const char *role)
Parse a resource role from a string role specification.
Definition roles.c:51
rsc_role_e
Definition roles.h:34
@ pcmk_role_started
Started.
Definition roles.h:37
@ pcmk_role_unknown
Resource role is unknown.
Definition roles.h:35
@ pcmk_role_unpromoted
Unpromoted.
Definition roles.h:38
@ pcmk_role_stopped
Stopped.
Definition roles.h:36
@ pcmk_no_quorum_ignore
Act as if partition still holds quorum.
Definition scheduler.h:41
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:282
#define pcmk__sched_err(scheduler, fmt...)
#define pcmk__rsc_trace(rsc, fmt, args...)
void pcmk__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, const char *reason)
Definition scheduler.c:321
@ pcmk__sched_enable_unfencing
@ pcmk__sched_quorate
@ pcmk__sched_fencing_enabled
@ pcmk__sched_fence_remote_no_quorum
@ pcmk__sched_have_fencing
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition scores.c:102
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition scores.h:26
int pcmk__add_scores(int score1, int score2)
Definition scores.c:159
pcmk_resource_t * pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
Definition status.c:197
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
Definition strings.c:1081
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)
Definition strings.c:984
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:685
@ pcmk__str_none
@ pcmk__str_null_matches
@ pcmk__str_star_matches
@ pcmk__str_casei
#define pcmk__str_copy(str)
enum pcmk__probe_mode probe_mode
gboolean shutdown
Definition nodes.h:62
gboolean online
Definition nodes.h:50
gboolean unclean
Definition nodes.h:58
pcmk_resource_t * remote
This structure contains everything that makes up a single output formatter.
int(* message)(pcmk__output_t *out, const char *message_id,...)
pcmk_scheduler_t * scheduler
const pcmk__rsc_methods_t * fns
unsigned long long flags
Definition resources.h:69
pcmk__resource_private_t * priv
Definition resources.h:61
bool(* active)(const pcmk_resource_t *rsc, bool all)
pcmk__scheduler_private_t * priv
Definition scheduler.h:99
enum pe_quorum_policy no_quorum_policy
Definition scheduler.h:93
GList * nodes
Definition scheduler.h:97
uint64_t flags
Definition scheduler.h:89
pcmk__node_private_t * priv
Definition nodes.h:85
struct pcmk__node_details * details
Definition nodes.h:82
struct pcmk__node_assignment * assign
Definition nodes.h:79
GHashTable * state
Data used to evaluate a rule (any NULL items are ignored)
Definition rules.h:57
GHashTable * node_attrs
Definition rules.h:77
Wrappers for and extensions to libxml2.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition xml_element.c:43
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
#define PCMK_XE_META_ATTRIBUTES
Definition xml_names.h:130