pacemaker 2.1.6-6fdc9deea29
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
utils.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2023 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/msg_xml.h>
17#include <crm/pengine/rules.h>
19
20#include "pe_status_private.h"
21
22extern bool pcmk__is_daemon;
23
24gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data);
25
35bool
37{
38 if (pe__is_guest_node(node)) {
39 /* Guest nodes are fenced by stopping their container resource. We can
40 * do that if the container's host is either online or fenceable.
41 */
43
44 for (GList *n = rsc->running_on; n != NULL; n = n->next) {
45 pe_node_t *container_node = n->data;
46
47 if (!container_node->details->online
48 && !pe_can_fence(data_set, container_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 pe__node_name(node));
72 return true;
73 }
74
75 crm_trace("Cannot fence %s", pe__node_name(node));
76 return false;
77}
78
89pe__copy_node(const pe_node_t *this_node)
90{
91 pe_node_t *new_node = NULL;
92
93 CRM_ASSERT(this_node != NULL);
94
95 new_node = calloc(1, sizeof(pe_node_t));
96 CRM_ASSERT(new_node != NULL);
97
98 new_node->rsc_discover_mode = this_node->rsc_discover_mode;
99 new_node->weight = this_node->weight;
100 new_node->fixed = this_node->fixed; // @COMPAT deprecated and unused
101 new_node->details = this_node->details;
102
103 return new_node;
104}
105
106/* any node in list1 or list2 and not in the other gets a score of -INFINITY */
107void
108node_list_exclude(GHashTable * hash, GList *list, gboolean merge_scores)
109{
110 GHashTable *result = hash;
111 pe_node_t *other_node = NULL;
112 GList *gIter = list;
113
114 GHashTableIter iter;
115 pe_node_t *node = NULL;
116
117 g_hash_table_iter_init(&iter, hash);
118 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
119
120 other_node = pe_find_node_id(list, node->details->id);
121 if (other_node == NULL) {
122 node->weight = -INFINITY;
123 crm_trace("Banning dependent from %s (no primary instance)",
124 pe__node_name(node));
125 } else if (merge_scores) {
126 node->weight = pcmk__add_scores(node->weight, other_node->weight);
127 crm_trace("Added primary's score %s to dependent's score for %s "
128 "(now %s)", pcmk_readable_score(other_node->weight),
129 pe__node_name(node), pcmk_readable_score(node->weight));
130 }
131 }
132
133 for (; gIter != NULL; gIter = gIter->next) {
134 pe_node_t *node = (pe_node_t *) gIter->data;
135
136 other_node = pe_hash_table_lookup(result, node->details->id);
137
138 if (other_node == NULL) {
139 pe_node_t *new_node = pe__copy_node(node);
140
141 new_node->weight = -INFINITY;
142 g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
143 }
144 }
145}
146
155GHashTable *
156pe__node_list2table(const GList *list)
157{
158 GHashTable *result = NULL;
159
160 result = pcmk__strkey_table(NULL, free);
161 for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
162 pe_node_t *new_node = pe__copy_node((const pe_node_t *) gIter->data);
163
164 g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
165 }
166 return result;
167}
168
184gint
185pe__cmp_node_name(gconstpointer a, gconstpointer b)
186{
187 const pe_node_t *node1 = (const pe_node_t *) a;
188 const pe_node_t *node2 = (const pe_node_t *) b;
189
190 if ((node1 == NULL) && (node2 == NULL)) {
191 return 0;
192 }
193
194 if (node1 == NULL) {
195 return -1;
196 }
197
198 if (node2 == NULL) {
199 return 1;
200 }
201
204}
205
215static void
216pe__output_node_weights(const pe_resource_t *rsc, const char *comment,
217 GHashTable *nodes, pe_working_set_t *data_set)
218{
220
221 // Sort the nodes so the output is consistent for regression tests
222 GList *list = g_list_sort(g_hash_table_get_values(nodes),
224
225 for (const GList *gIter = list; gIter != NULL; gIter = gIter->next) {
226 const pe_node_t *node = (const pe_node_t *) gIter->data;
227
228 out->message(out, "node-weight", rsc, comment, node->details->uname,
229 pcmk_readable_score(node->weight));
230 }
231 g_list_free(list);
232}
233
245static void
246pe__log_node_weights(const char *file, const char *function, int line,
247 const pe_resource_t *rsc, const char *comment,
248 GHashTable *nodes)
249{
250 GHashTableIter iter;
251 pe_node_t *node = NULL;
252
253 // Don't waste time if we're not tracing at this point
254 pcmk__if_tracing({}, return);
255
256 g_hash_table_iter_init(&iter, nodes);
257 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
258 if (rsc) {
259 qb_log_from_external_source(function, file,
260 "%s: %s allocation score on %s: %s",
261 LOG_TRACE, line, 0,
262 comment, rsc->id,
263 pe__node_name(node),
264 pcmk_readable_score(node->weight));
265 } else {
266 qb_log_from_external_source(function, file, "%s: %s = %s",
267 LOG_TRACE, line, 0,
268 comment, pe__node_name(node),
269 pcmk_readable_score(node->weight));
270 }
271 }
272}
273
288void
289pe__show_node_weights_as(const char *file, const char *function, int line,
290 bool to_log, const pe_resource_t *rsc,
291 const char *comment, GHashTable *nodes,
293{
294 if (rsc != NULL && pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
295 // Don't show allocation scores for orphans
296 return;
297 }
298 if (nodes == NULL) {
299 // Nothing to show
300 return;
301 }
302
303 if (to_log) {
304 pe__log_node_weights(file, function, line, rsc, comment, nodes);
305 } else {
306 pe__output_node_weights(rsc, comment, nodes, data_set);
307 }
308
309 // If this resource has children, repeat recursively for each
310 if (rsc && rsc->children) {
311 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
312 pe_resource_t *child = (pe_resource_t *) gIter->data;
313
314 pe__show_node_weights_as(file, function, line, to_log, child,
315 comment, child->allowed_nodes, data_set);
316 }
317 }
318}
319
334gint
335pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
336{
337 const pe_resource_t *resource1 = (const pe_resource_t *)a;
338 const pe_resource_t *resource2 = (const pe_resource_t *)b;
339
340 if (a == NULL && b == NULL) {
341 return 0;
342 }
343 if (a == NULL) {
344 return 1;
345 }
346 if (b == NULL) {
347 return -1;
348 }
349
350 if (resource1->priority > resource2->priority) {
351 return -1;
352 }
353
354 if (resource1->priority < resource2->priority) {
355 return 1;
356 }
357
358 return 0;
359}
360
361static void
362resource_node_score(pe_resource_t *rsc, const pe_node_t *node, int score,
363 const char *tag)
364{
365 pe_node_t *match = NULL;
366
368 && pcmk__str_eq(tag, "symmetric_default", pcmk__str_casei)) {
369 /* This string comparision may be fragile, but exclusive resources and
370 * exclusive nodes should not have the symmetric_default constraint
371 * applied to them.
372 */
373 return;
374
375 } else if (rsc->children) {
376 GList *gIter = rsc->children;
377
378 for (; gIter != NULL; gIter = gIter->next) {
379 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
380
381 resource_node_score(child_rsc, node, score, tag);
382 }
383 }
384
385 match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
386 if (match == NULL) {
387 match = pe__copy_node(node);
388 g_hash_table_insert(rsc->allowed_nodes, (gpointer) match->details->id, match);
389 }
390 match->weight = pcmk__add_scores(match->weight, score);
391 pe_rsc_trace(rsc,
392 "Enabling %s preference (%s) for %s on %s (now %s)",
393 tag, pcmk_readable_score(score), rsc->id, pe__node_name(node),
395}
396
397void
398resource_location(pe_resource_t *rsc, const pe_node_t *node, int score,
399 const char *tag, pe_working_set_t *data_set)
400{
401 if (node != NULL) {
402 resource_node_score(rsc, node, score, tag);
403
404 } else if (data_set != NULL) {
405 GList *gIter = data_set->nodes;
406
407 for (; gIter != NULL; gIter = gIter->next) {
408 pe_node_t *node_iter = (pe_node_t *) gIter->data;
409
410 resource_node_score(rsc, node_iter, score, tag);
411 }
412
413 } else {
414 GHashTableIter iter;
415 pe_node_t *node_iter = NULL;
416
417 g_hash_table_iter_init(&iter, rsc->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 == -INFINITY) {
424 if (rsc->allocated_to) {
425 crm_info("Deallocating %s from %s",
426 rsc->id, pe__node_name(rsc->allocated_to));
427 free(rsc->allocated_to);
428 rsc->allocated_to = NULL;
429 }
430 }
431}
432
433time_t
435{
436 if(data_set) {
437 if (data_set->now == NULL) {
438 crm_trace("Recording a new 'now'");
439 data_set->now = crm_time_new(NULL);
440 }
442 }
443
444 crm_trace("Defaulting to 'now'");
445 return time(NULL);
446}
447
448gboolean
450{
451 enum rsc_role_e local_role = RSC_ROLE_UNKNOWN;
452 const char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
453
454 CRM_CHECK(role != NULL, return FALSE);
455
456 if (pcmk__str_eq(value, "started", pcmk__str_null_matches | pcmk__str_casei)
457 || pcmk__str_eq("default", value, pcmk__str_casei)) {
458 return FALSE;
459 }
460
461 local_role = text2role(value);
462 if (local_role == RSC_ROLE_UNKNOWN) {
463 pcmk__config_err("Ignoring '" XML_RSC_ATTR_TARGET_ROLE "' for %s "
464 "because '%s' is not valid", rsc->id, value);
465 return FALSE;
466
467 } else if (local_role > RSC_ROLE_STARTED) {
470 if (local_role > RSC_ROLE_UNPROMOTED) {
471 /* This is what we'd do anyway, just leave the default to avoid messing up the placement algorithm */
472 return FALSE;
473 }
474
475 } else {
476 pcmk__config_err("Ignoring '" XML_RSC_ATTR_TARGET_ROLE "' for %s "
477 "because '%s' only makes sense for promotable "
478 "clones", rsc->id, value);
479 return FALSE;
480 }
481 }
482
483 *role = local_role;
484 return TRUE;
485}
486
487gboolean
488order_actions(pe_action_t * lh_action, pe_action_t * rh_action, enum pe_ordering order)
489{
490 GList *gIter = NULL;
491 pe_action_wrapper_t *wrapper = NULL;
492 GList *list = NULL;
493
494 if (order == pe_order_none) {
495 return FALSE;
496 }
497
498 if (lh_action == NULL || rh_action == NULL) {
499 return FALSE;
500 }
501
502 crm_trace("Creating action wrappers for ordering: %s then %s",
503 lh_action->uuid, rh_action->uuid);
504
505 /* Ensure we never create a dependency on ourselves... it's happened */
506 CRM_ASSERT(lh_action != rh_action);
507
508 /* Filter dups, otherwise update_action_states() has too much work to do */
509 gIter = lh_action->actions_after;
510 for (; gIter != NULL; gIter = gIter->next) {
511 pe_action_wrapper_t *after = (pe_action_wrapper_t *) gIter->data;
512
513 if (after->action == rh_action && (after->type & order)) {
514 return FALSE;
515 }
516 }
517
518 wrapper = calloc(1, sizeof(pe_action_wrapper_t));
519 wrapper->action = rh_action;
520 wrapper->type = order;
521 list = lh_action->actions_after;
522 list = g_list_prepend(list, wrapper);
523 lh_action->actions_after = list;
524
525 wrapper = calloc(1, sizeof(pe_action_wrapper_t));
526 wrapper->action = lh_action;
527 wrapper->type = order;
528 list = rh_action->actions_before;
529 list = g_list_prepend(list, wrapper);
530 rh_action->actions_before = list;
531 return TRUE;
532}
533
534void
536{
537 pe_ticket_t *ticket = data;
538
539 if (ticket->state) {
540 g_hash_table_destroy(ticket->state);
541 }
542 free(ticket->id);
543 free(ticket);
544}
545
547ticket_new(const char *ticket_id, pe_working_set_t * data_set)
548{
549 pe_ticket_t *ticket = NULL;
550
551 if (pcmk__str_empty(ticket_id)) {
552 return NULL;
553 }
554
555 if (data_set->tickets == NULL) {
557 }
558
559 ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
560 if (ticket == NULL) {
561
562 ticket = calloc(1, sizeof(pe_ticket_t));
563 if (ticket == NULL) {
564 crm_err("Cannot allocate ticket '%s'", ticket_id);
565 return NULL;
566 }
567
568 crm_trace("Creaing ticket entry for %s", ticket_id);
569
570 ticket->id = strdup(ticket_id);
571 ticket->granted = FALSE;
572 ticket->last_granted = -1;
573 ticket->standby = FALSE;
574 ticket->state = pcmk__strkey_table(free, free);
575
576 g_hash_table_insert(data_set->tickets, strdup(ticket->id), ticket);
577 }
578
579 return ticket;
580}
581
582const char *
584{
585 return pcmk_is_set(rsc->flags, pe_rsc_unique)? rsc->id : ID(rsc->xml);
586}
587
588void
590{
592 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
594 }
595}
596
597void
599{
600 for (GList *lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
601 pe_resource_t *r = (pe_resource_t *) lpc->data;
603 }
604}
605
606void
608{
610 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
612 }
613}
614
615void
616trigger_unfencing(pe_resource_t *rsc, pe_node_t *node, const char *reason,
618{
620 /* No resources require it */
621 return;
622
623 } else if ((rsc != NULL)
625 /* Wasn't a stonith device */
626 return;
627
628 } else if(node
629 && node->details->online
630 && node->details->unclean == FALSE
631 && node->details->shutdown == FALSE) {
632 pe_action_t *unfence = pe_fence_op(node, "on", FALSE, reason, FALSE, data_set);
633
634 if(dependency) {
635 order_actions(unfence, dependency, pe_order_optional);
636 }
637
638 } else if(rsc) {
639 GHashTableIter iter;
640
641 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
642 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
643 if(node->details->online && node->details->unclean == FALSE && node->details->shutdown == FALSE) {
644 trigger_unfencing(rsc, node, reason, dependency, data_set);
645 }
646 }
647 }
648}
649
650gboolean
651add_tag_ref(GHashTable * tags, const char * tag_name, const char * obj_ref)
652{
653 pe_tag_t *tag = NULL;
654 GList *gIter = NULL;
655 gboolean is_existing = FALSE;
656
657 CRM_CHECK(tags && tag_name && obj_ref, return FALSE);
658
659 tag = g_hash_table_lookup(tags, tag_name);
660 if (tag == NULL) {
661 tag = calloc(1, sizeof(pe_tag_t));
662 if (tag == NULL) {
663 return FALSE;
664 }
665 tag->id = strdup(tag_name);
666 tag->refs = NULL;
667 g_hash_table_insert(tags, strdup(tag_name), tag);
668 }
669
670 for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
671 const char *existing_ref = (const char *) gIter->data;
672
673 if (pcmk__str_eq(existing_ref, obj_ref, pcmk__str_none)){
674 is_existing = TRUE;
675 break;
676 }
677 }
678
679 if (is_existing == FALSE) {
680 tag->refs = g_list_append(tag->refs, strdup(obj_ref));
681 crm_trace("Added: tag=%s ref=%s", tag->id, obj_ref);
682 }
683
684 return TRUE;
685}
686
699bool
701{
702 const char *shutdown = pe_node_attribute_raw(node, XML_CIB_ATTR_SHUTDOWN);
703
704 return !pcmk__str_eq(shutdown, "0", pcmk__str_null_matches);
705}
706
714void
716{
717 if ((recheck > get_effective_time(data_set))
718 && ((data_set->recheck_by == 0)
719 || (data_set->recheck_by > recheck))) {
720 data_set->recheck_by = recheck;
721 }
722}
723
736void
737pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name,
738 const pe_rule_eval_data_t *rule_data,
739 GHashTable *hash, const char *always_first,
740 gboolean overwrite, pe_working_set_t *data_set)
741{
742 crm_time_t *next_change = crm_time_new_undefined();
743
744 pe_eval_nvpairs(data_set->input, xml_obj, set_name, rule_data, hash,
745 always_first, overwrite, next_change);
746 if (crm_time_is_defined(next_change)) {
747 time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change);
748
750 }
751 crm_time_free(next_change);
752}
753
754bool
756{
757 const char *target_role = NULL;
758
759 CRM_CHECK(rsc != NULL, return false);
760 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
761 if (target_role) {
762 enum rsc_role_e target_role_e = text2role(target_role);
763
764 if ((target_role_e == RSC_ROLE_STOPPED)
765 || ((target_role_e == RSC_ROLE_UNPROMOTED)
768 return true;
769 }
770 }
771 return false;
772}
773
783bool
785{
786 return (rsc != NULL) && pcmk__list_of_1(rsc->running_on)
787 && pe__same_node((const pe_node_t *) rsc->running_on->data, node);
788}
789
790bool
792{
793 for (GList *ele = rsc->running_on; ele; ele = ele->next) {
794 pe_node_t *node = (pe_node_t *) ele->data;
795 if (pcmk__str_in_list(node->details->uname, node_list,
797 return true;
798 }
799 }
800
801 return false;
802}
803
804bool
806{
807 return (rsc->fns->active(rsc, FALSE) && !pe__rsc_running_on_any(rsc, only_node));
808}
809
810GList *
811pe__filter_rsc_list(GList *rscs, GList *filter)
812{
813 GList *retval = NULL;
814
815 for (GList *gIter = rscs; gIter; gIter = gIter->next) {
816 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
817
818 /* I think the second condition is safe here for all callers of this
819 * function. If not, it needs to move into pe__node_text.
820 */
823 retval = g_list_prepend(retval, rsc);
824 }
825 }
826
827 return retval;
828}
829
830GList *
832 GList *nodes = NULL;
833
834 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
835 /* Nothing was given so return a list of all node names. Or, '*' was
836 * given. This would normally fall into the pe__unames_with_tag branch
837 * where it will return an empty list. Catch it here instead.
838 */
839 nodes = g_list_prepend(nodes, strdup("*"));
840 } else {
842
843 if (node) {
844 /* The given string was a valid uname for a node. Return a
845 * singleton list containing just that uname.
846 */
847 nodes = g_list_prepend(nodes, strdup(s));
848 } else {
849 /* The given string was not a valid uname. It's either a tag or
850 * it's a typo or something. In the first case, we'll return a
851 * list of all the unames of the nodes with the given tag. In the
852 * second case, we'll return a NULL pointer and nothing will
853 * get displayed.
854 */
855 nodes = pe__unames_with_tag(data_set, s);
856 }
857 }
858
859 return nodes;
860}
861
862GList *
864 GList *resources = NULL;
865
866 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
867 resources = g_list_prepend(resources, strdup("*"));
868 } else {
871
872 if (rsc) {
873 /* A colon in the name we were given means we're being asked to filter
874 * on a specific instance of a cloned resource. Put that exact string
875 * into the filter list. Otherwise, use the printable ID of whatever
876 * resource was found that matches what was asked for.
877 */
878 if (strstr(s, ":") != NULL) {
879 resources = g_list_prepend(resources, strdup(rsc->id));
880 } else {
881 resources = g_list_prepend(resources, strdup(rsc_printable_id(rsc)));
882 }
883 } else {
884 /* The given string was not a valid resource name. It's a tag or a
885 * typo or something. See pe__build_node_name_list() for more
886 * detail.
887 */
888 resources = pe__rscs_with_tag(data_set, s);
889 }
890 }
891
892 return resources;
893}
894
895xmlNode *
897{
898 const pe_resource_t *parent = pe__const_top_resource(rsc, false);
899 const char *rsc_id = rsc->id;
900
901 if (parent->variant == pe_clone) {
902 rsc_id = pe__clone_child_id(parent);
903 }
904
905 for (xmlNode *xml_op = pcmk__xml_first_child(rsc->cluster->failed); xml_op != NULL;
906 xml_op = pcmk__xml_next(xml_op)) {
907 const char *value = NULL;
908 char *op_id = NULL;
909
910 /* This resource operation is not a failed probe. */
911 if (!pcmk_xe_mask_probe_failure(xml_op)) {
912 continue;
913 }
914
915 /* This resource operation was not run on the given node. Note that if name is
916 * NULL, this will always succeed.
917 */
918 value = crm_element_value(xml_op, XML_LRM_ATTR_TARGET);
919 if (value == NULL || !pcmk__str_eq(value, name, pcmk__str_casei|pcmk__str_null_matches)) {
920 continue;
921 }
922
923 if (!parse_op_key(pe__xe_history_key(xml_op), &op_id, NULL, NULL)) {
924 continue; // This history entry is missing an operation key
925 }
926
927 /* This resource operation's ID does not match the rsc_id we are looking for. */
928 if (!pcmk__str_eq(op_id, rsc_id, pcmk__str_none)) {
929 free(op_id);
930 continue;
931 }
932
933 free(op_id);
934 return xml_op;
935 }
936
937 return NULL;
938}
const char * parent
Definition cib.c:25
const char * name
Definition cib.c:24
bool pcmk__is_daemon
Definition logging.c:47
uint64_t flags
Definition remote.c:3
bool pcmk_xe_mask_probe_failure(const xmlNode *xml_op)
Definition operations.c:516
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition operations.c:96
int pcmk__add_scores(int score1, int score2)
Definition scores.c:116
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition scores.c:86
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:121
rsc_role_e
Possible roles that a resource can be in.
Definition common.h:92
@ RSC_ROLE_STARTED
Definition common.h:95
@ RSC_ROLE_STOPPED
Definition common.h:94
@ RSC_ROLE_UNKNOWN
Definition common.h:93
@ RSC_ROLE_UNPROMOTED
Definition common.h:96
enum rsc_role_e text2role(const char *role)
Definition common.c:479
char data[0]
Definition cpg.c:10
A dumping ground.
#define INFINITY
Definition crm.h:99
long long crm_time_get_seconds_since_epoch(const crm_time_t *dt)
Definition iso8601.c:359
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(const char *string)
Definition iso8601.c:109
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
Definition iso8601.c:126
struct crm_time_s crm_time_t
Definition iso8601.h:32
#define crm_info(fmt, args...)
Definition logging.h:378
#define crm_notice(fmt, args...)
Definition logging.h:377
#define CRM_CHECK(expr, failure_action)
Definition logging.h:235
#define crm_err(fmt, args...)
Definition logging.h:375
#define crm_trace(fmt, args...)
Definition logging.h:381
#define LOG_TRACE
Definition logging.h:37
#define pcmk__config_err(fmt...)
#define pcmk__if_tracing(if_action, else_action)
#define ID(x)
Definition msg_xml.h:480
#define XML_RSC_ATTR_TARGET_ROLE
Definition msg_xml.h:249
#define XML_CIB_ATTR_SHUTDOWN
Definition msg_xml.h:301
#define XML_LRM_ATTR_TARGET
Definition msg_xml.h:317
pe_working_set_t * data_set
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:496
pcmk__action_result_t result
Definition pcmk_fence.c:35
pe_node_t node1
pe_node_t node2
@ no_quorum_ignore
Definition pe_types.h:82
#define pe_rsc_fence_device
Definition pe_types.h:279
#define pe_flag_have_stonith_resource
Definition pe_types.h:116
#define pe_flag_have_quorum
Definition pe_types.h:111
pe_ordering
Definition pe_types.h:506
@ pe_order_none
Definition pe_types.h:507
@ pe_order_optional
Definition pe_types.h:508
#define pe_flag_enable_unfencing
Definition pe_types.h:117
#define pe_rsc_unique
Definition pe_types.h:278
#define pe_rsc_orphan
Definition pe_types.h:272
@ pe_discover_never
Definition pe_types.h:501
@ pe_find_any
match base name of any clone instance
Definition pe_types.h:106
@ pe_find_renamed
match resource ID or LRM history ID
Definition pe_types.h:101
@ pe_clone
Definition pe_types.h:40
#define pe_flag_stonith_enabled
Definition pe_types.h:115
#define pe_rsc_promotable
Definition pe_types.h:280
const char * pe_node_attribute_raw(const pe_node_t *node, const char *name)
Definition common.c:558
GList * pe__unames_with_tag(pe_working_set_t *data_set, const char *tag_name)
Definition tags.c:51
const char * pe__clone_child_id(const pe_resource_t *rsc)
Definition clone.c:1273
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition internal.h:83
GList * pe__rscs_with_tag(pe_working_set_t *data_set, const char *tag_name)
Definition tags.c:20
#define pe_rsc_trace(rsc, fmt, args...)
Definition internal.h:50
pe_action_t * pe_fence_op(pe_node_t *node, const char *op, bool optional, const char *reason, bool priority_delay, pe_working_set_t *data_set)
#define pe__set_resource_flags(resource, flags_to_set)
Definition internal.h:77
const pe_resource_t * pe__const_top_resource(const pe_resource_t *rsc, bool include_bundle)
Definition complex.c:947
bool pe__is_guest_node(const pe_node_t *node)
Definition remote.c:33
GList * pe__build_rsc_list(pe_working_set_t *data_set, const char *s)
Definition utils.c:863
bool pe__resource_is_disabled(const pe_resource_t *rsc)
Definition utils.c:755
GHashTable * pe__node_list2table(const GList *list)
Definition utils.c:156
void node_list_exclude(GHashTable *hash, GList *list, gboolean merge_scores)
Definition utils.c:108
void pe__set_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
Definition utils.c:607
bool pe__rsc_running_on_any(pe_resource_t *rsc, GList *node_list)
Definition utils.c:791
void destroy_ticket(gpointer data)
Definition utils.c:535
const char * rsc_printable_id(const pe_resource_t *rsc)
Definition utils.c:583
void pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag)
Definition utils.c:598
bool pcmk__rsc_filtered_by_node(pe_resource_t *rsc, GList *only_node)
Definition utils.c:805
void trigger_unfencing(pe_resource_t *rsc, pe_node_t *node, const char *reason, pe_action_t *dependency, pe_working_set_t *data_set)
Definition utils.c:616
xmlNode * pe__failed_probe_for_rsc(const pe_resource_t *rsc, const char *name)
Definition utils.c:896
gint pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
Definition utils.c:335
void pe__show_node_weights_as(const char *file, const char *function, int line, bool to_log, const pe_resource_t *rsc, const char *comment, GHashTable *nodes, pe_working_set_t *data_set)
Definition utils.c:289
GList * pe__build_node_name_list(pe_working_set_t *data_set, const char *s)
Definition utils.c:831
GList * pe__filter_rsc_list(GList *rscs, GList *filter)
Definition utils.c:811
gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data)
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
Definition utils.c:185
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition utils.c:488
gboolean get_target_role(const pe_resource_t *rsc, enum rsc_role_e *role)
Definition utils.c:449
void resource_location(pe_resource_t *rsc, const pe_node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition utils.c:398
time_t get_effective_time(pe_working_set_t *data_set)
Definition utils.c:434
pe_ticket_t * ticket_new(const char *ticket_id, pe_working_set_t *data_set)
Definition utils.c:547
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, gboolean overwrite, pe_working_set_t *data_set)
Definition utils.c:737
bool pe__shutdown_requested(const pe_node_t *node)
Definition utils.c:700
void pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set)
Definition utils.c:715
bool pe_can_fence(const pe_working_set_t *data_set, const pe_node_t *node)
Definition utils.c:36
pe_node_t * pe__copy_node(const pe_node_t *this_node)
Definition utils.c:89
gboolean add_tag_ref(GHashTable *tags, const char *tag_name, const char *obj_ref)
Definition utils.c:651
void pe__clear_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
Definition utils.c:589
bool pe__rsc_running_on_only(const pe_resource_t *rsc, const pe_node_t *node)
Definition utils.c:784
#define CRM_ASSERT(expr)
Definition results.h:42
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:497
pe_node_t * pe_find_node(const GList *node_list, const char *node_name)
Find a node by name in a list of nodes.
Definition status.c:473
pe_resource_t * pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags)
Definition status.c:397
pe_node_t * pe_find_node_id(const GList *node_list, const char *id)
Find a node by ID in a list of nodes.
Definition status.c:448
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
Definition strings.c:1023
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)
Definition strings.c:888
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:611
@ pcmk__str_none
@ pcmk__str_null_matches
@ pcmk__str_star_matches
@ pcmk__str_casei
This structure contains everything that makes up a single output formatter.
int(* message)(pcmk__output_t *out, const char *message_id,...)
char * uuid
Definition pe_types.h:438
GList * actions_after
Definition pe_types.h:471
GList * actions_before
Definition pe_types.h:470
enum pe_ordering type
Definition pe_types.h:555
pe_action_t * action
Definition pe_types.h:557
int weight
Definition pe_types.h:265
int rsc_discover_mode
Definition pe_types.h:269
gboolean fixed
Definition pe_types.h:266
struct pe_node_shared_s * details
Definition pe_types.h:268
gboolean shutdown
Definition pe_types.h:242
const char * id
Definition pe_types.h:231
gboolean online
Definition pe_types.h:236
const char * uname
Definition pe_types.h:232
pe_resource_t * remote_rsc
Definition pe_types.h:253
gboolean unclean
Definition pe_types.h:240
GList * running_on
Definition pe_types.h:398
GHashTable * meta
Definition pe_types.h:405
GList * children
Definition pe_types.h:409
gboolean exclusive_discover
Definition pe_types.h:377
pe_working_set_t * cluster
Definition pe_types.h:353
pe_resource_t * container
Definition pe_types.h:412
xmlNode * xml
Definition pe_types.h:349
GHashTable * allowed_nodes
Definition pe_types.h:400
pe_node_t * allocated_to
Definition pe_types.h:395
unsigned long long flags
Definition pe_types.h:373
pe_resource_t * parent
Definition pe_types.h:354
resource_object_functions_t * fns
Definition pe_types.h:358
char * id
Definition pe_types.h:488
GList * refs
Definition pe_types.h:489
GHashTable * state
Definition pe_types.h:484
char * id
Definition pe_types.h:480
gboolean standby
Definition pe_types.h:483
gboolean granted
Definition pe_types.h:481
time_t last_granted
Definition pe_types.h:482
xmlNode * input
Definition pe_types.h:160
GList * resources
Definition pe_types.h:181
xmlNode * failed
Definition pe_types.h:188
unsigned long long flags
Definition pe_types.h:169
enum pe_quorum_policy no_quorum_policy
Definition pe_types.h:172
GHashTable * tickets
Definition pe_types.h:175
time_t recheck_by
Definition pe_types.h:210
crm_time_t * now
Definition pe_types.h:161
gboolean(* active)(pe_resource_t *, gboolean)
Definition pe_types.h:53