pacemaker 2.1.5-a3f44794f94
Scalable High-Availability cluster resource manager
utils.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2022 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;
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 } else if (merge_scores) {
124 node->weight = pcmk__add_scores(node->weight, other_node->weight);
125 }
126 }
127
128 for (; gIter != NULL; gIter = gIter->next) {
129 pe_node_t *node = (pe_node_t *) gIter->data;
130
131 other_node = pe_hash_table_lookup(result, node->details->id);
132
133 if (other_node == NULL) {
134 pe_node_t *new_node = pe__copy_node(node);
135
136 new_node->weight = -INFINITY;
137 g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
138 }
139 }
140}
141
150GHashTable *
152{
153 GHashTable *result = NULL;
154
155 result = pcmk__strkey_table(NULL, free);
156 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
157 pe_node_t *new_node = pe__copy_node((pe_node_t *) gIter->data);
158
159 g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
160 }
161 return result;
162}
163
179gint
180pe__cmp_node_name(gconstpointer a, gconstpointer b)
181{
182 const pe_node_t *node1 = (const pe_node_t *) a;
183 const pe_node_t *node2 = (const pe_node_t *) b;
184
185 if ((node1 == NULL) && (node2 == NULL)) {
186 return 0;
187 }
188
189 if (node1 == NULL) {
190 return -1;
191 }
192
193 if (node2 == NULL) {
194 return 1;
195 }
196
199}
200
209static void
210pe__output_node_weights(pe_resource_t *rsc, const char *comment,
211 GHashTable *nodes, pe_working_set_t *data_set)
212{
214
215 // Sort the nodes so the output is consistent for regression tests
216 GList *list = g_list_sort(g_hash_table_get_values(nodes),
218
219 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
220 pe_node_t *node = (pe_node_t *) gIter->data;
221
222 out->message(out, "node-weight", rsc, comment, node->details->uname,
224 }
225 g_list_free(list);
226}
227
239static void
240pe__log_node_weights(const char *file, const char *function, int line,
241 pe_resource_t *rsc, const char *comment, GHashTable *nodes)
242{
243 GHashTableIter iter;
244 pe_node_t *node = NULL;
245
246 // Don't waste time if we're not tracing at this point
247 pcmk__log_else(LOG_TRACE, return);
248
249 g_hash_table_iter_init(&iter, nodes);
250 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
251 if (rsc) {
252 qb_log_from_external_source(function, file,
253 "%s: %s allocation score on %s: %s",
254 LOG_TRACE, line, 0,
255 comment, rsc->id,
256 pe__node_name(node),
257 pcmk_readable_score(node->weight));
258 } else {
259 qb_log_from_external_source(function, file, "%s: %s = %s",
260 LOG_TRACE, line, 0,
261 comment, pe__node_name(node),
262 pcmk_readable_score(node->weight));
263 }
264 }
265}
266
279void
280pe__show_node_weights_as(const char *file, const char *function, int line,
281 bool to_log, pe_resource_t *rsc, const char *comment,
282 GHashTable *nodes, pe_working_set_t *data_set)
283{
284 if (rsc != NULL && pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
285 // Don't show allocation scores for orphans
286 return;
287 }
288 if (nodes == NULL) {
289 // Nothing to show
290 return;
291 }
292
293 if (to_log) {
294 pe__log_node_weights(file, function, line, rsc, comment, nodes);
295 } else {
296 pe__output_node_weights(rsc, comment, nodes, data_set);
297 }
298
299 // If this resource has children, repeat recursively for each
300 if (rsc && rsc->children) {
301 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
302 pe_resource_t *child = (pe_resource_t *) gIter->data;
303
304 pe__show_node_weights_as(file, function, line, to_log, child,
305 comment, child->allowed_nodes, data_set);
306 }
307 }
308}
309
324gint
325pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
326{
327 const pe_resource_t *resource1 = (const pe_resource_t *)a;
328 const pe_resource_t *resource2 = (const pe_resource_t *)b;
329
330 if (a == NULL && b == NULL) {
331 return 0;
332 }
333 if (a == NULL) {
334 return 1;
335 }
336 if (b == NULL) {
337 return -1;
338 }
339
340 if (resource1->priority > resource2->priority) {
341 return -1;
342 }
343
344 if (resource1->priority < resource2->priority) {
345 return 1;
346 }
347
348 return 0;
349}
350
351static void
352resource_node_score(pe_resource_t * rsc, pe_node_t * node, int score, const char *tag)
353{
354 pe_node_t *match = NULL;
355
357 && pcmk__str_eq(tag, "symmetric_default", pcmk__str_casei)) {
358 /* This string comparision may be fragile, but exclusive resources and
359 * exclusive nodes should not have the symmetric_default constraint
360 * applied to them.
361 */
362 return;
363
364 } else if (rsc->children) {
365 GList *gIter = rsc->children;
366
367 for (; gIter != NULL; gIter = gIter->next) {
368 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
369
370 resource_node_score(child_rsc, node, score, tag);
371 }
372 }
373
374 pe_rsc_trace(rsc, "Setting %s for %s on %s: %d",
375 tag, rsc->id, pe__node_name(node), score);
376 match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
377 if (match == NULL) {
378 match = pe__copy_node(node);
379 g_hash_table_insert(rsc->allowed_nodes, (gpointer) match->details->id, match);
380 }
381 match->weight = pcmk__add_scores(match->weight, score);
382}
383
384void
385resource_location(pe_resource_t * rsc, pe_node_t * node, int score, const char *tag,
387{
388 if (node != NULL) {
389 resource_node_score(rsc, node, score, tag);
390
391 } else if (data_set != NULL) {
392 GList *gIter = data_set->nodes;
393
394 for (; gIter != NULL; gIter = gIter->next) {
395 pe_node_t *node_iter = (pe_node_t *) gIter->data;
396
397 resource_node_score(rsc, node_iter, score, tag);
398 }
399
400 } else {
401 GHashTableIter iter;
402 pe_node_t *node_iter = NULL;
403
404 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
405 while (g_hash_table_iter_next(&iter, NULL, (void **)&node_iter)) {
406 resource_node_score(rsc, node_iter, score, tag);
407 }
408 }
409
410 if (node == NULL && score == -INFINITY) {
411 if (rsc->allocated_to) {
412 crm_info("Deallocating %s from %s",
413 rsc->id, pe__node_name(rsc->allocated_to));
414 free(rsc->allocated_to);
415 rsc->allocated_to = NULL;
416 }
417 }
418}
419
420time_t
422{
423 if(data_set) {
424 if (data_set->now == NULL) {
425 crm_trace("Recording a new 'now'");
426 data_set->now = crm_time_new(NULL);
427 }
429 }
430
431 crm_trace("Defaulting to 'now'");
432 return time(NULL);
433}
434
435gboolean
437{
438 enum rsc_role_e local_role = RSC_ROLE_UNKNOWN;
439 const char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
440
441 CRM_CHECK(role != NULL, return FALSE);
442
443 if (pcmk__str_eq(value, "started", pcmk__str_null_matches | pcmk__str_casei)
444 || pcmk__str_eq("default", value, pcmk__str_casei)) {
445 return FALSE;
446 }
447
448 local_role = text2role(value);
449 if (local_role == RSC_ROLE_UNKNOWN) {
450 pcmk__config_err("Ignoring '" XML_RSC_ATTR_TARGET_ROLE "' for %s "
451 "because '%s' is not valid", rsc->id, value);
452 return FALSE;
453
454 } else if (local_role > RSC_ROLE_STARTED) {
456 if (local_role > RSC_ROLE_UNPROMOTED) {
457 /* This is what we'd do anyway, just leave the default to avoid messing up the placement algorithm */
458 return FALSE;
459 }
460
461 } else {
462 pcmk__config_err("Ignoring '" XML_RSC_ATTR_TARGET_ROLE "' for %s "
463 "because '%s' only makes sense for promotable "
464 "clones", rsc->id, value);
465 return FALSE;
466 }
467 }
468
469 *role = local_role;
470 return TRUE;
471}
472
473gboolean
474order_actions(pe_action_t * lh_action, pe_action_t * rh_action, enum pe_ordering order)
475{
476 GList *gIter = NULL;
477 pe_action_wrapper_t *wrapper = NULL;
478 GList *list = NULL;
479
480 if (order == pe_order_none) {
481 return FALSE;
482 }
483
484 if (lh_action == NULL || rh_action == NULL) {
485 return FALSE;
486 }
487
488 crm_trace("Creating action wrappers for ordering: %s then %s",
489 lh_action->uuid, rh_action->uuid);
490
491 /* Ensure we never create a dependency on ourselves... it's happened */
492 CRM_ASSERT(lh_action != rh_action);
493
494 /* Filter dups, otherwise update_action_states() has too much work to do */
495 gIter = lh_action->actions_after;
496 for (; gIter != NULL; gIter = gIter->next) {
497 pe_action_wrapper_t *after = (pe_action_wrapper_t *) gIter->data;
498
499 if (after->action == rh_action && (after->type & order)) {
500 return FALSE;
501 }
502 }
503
504 wrapper = calloc(1, sizeof(pe_action_wrapper_t));
505 wrapper->action = rh_action;
506 wrapper->type = order;
507 list = lh_action->actions_after;
508 list = g_list_prepend(list, wrapper);
509 lh_action->actions_after = list;
510
511 wrapper = calloc(1, sizeof(pe_action_wrapper_t));
512 wrapper->action = lh_action;
513 wrapper->type = order;
514 list = rh_action->actions_before;
515 list = g_list_prepend(list, wrapper);
516 rh_action->actions_before = list;
517 return TRUE;
518}
519
520void
522{
523 pe_ticket_t *ticket = data;
524
525 if (ticket->state) {
526 g_hash_table_destroy(ticket->state);
527 }
528 free(ticket->id);
529 free(ticket);
530}
531
533ticket_new(const char *ticket_id, pe_working_set_t * data_set)
534{
535 pe_ticket_t *ticket = NULL;
536
537 if (pcmk__str_empty(ticket_id)) {
538 return NULL;
539 }
540
541 if (data_set->tickets == NULL) {
543 }
544
545 ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
546 if (ticket == NULL) {
547
548 ticket = calloc(1, sizeof(pe_ticket_t));
549 if (ticket == NULL) {
550 crm_err("Cannot allocate ticket '%s'", ticket_id);
551 return NULL;
552 }
553
554 crm_trace("Creaing ticket entry for %s", ticket_id);
555
556 ticket->id = strdup(ticket_id);
557 ticket->granted = FALSE;
558 ticket->last_granted = -1;
559 ticket->standby = FALSE;
560 ticket->state = pcmk__strkey_table(free, free);
561
562 g_hash_table_insert(data_set->tickets, strdup(ticket->id), ticket);
563 }
564
565 return ticket;
566}
567
569{
570 if (!pcmk_is_set(rsc->flags, pe_rsc_unique)) {
571 return ID(rsc->xml);
572 }
573 return rsc->id;
574}
575
576void
578{
580 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
582 }
583}
584
585void
587{
588 for (GList *lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
589 pe_resource_t *r = (pe_resource_t *) lpc->data;
591 }
592}
593
594void
596{
598 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
600 }
601}
602
603void
605 pe_resource_t * rsc, pe_node_t *node, const char *reason, pe_action_t *dependency, pe_working_set_t * data_set)
606{
608 /* No resources require it */
609 return;
610
611 } else if ((rsc != NULL)
613 /* Wasn't a stonith device */
614 return;
615
616 } else if(node
617 && node->details->online
618 && node->details->unclean == FALSE
619 && node->details->shutdown == FALSE) {
620 pe_action_t *unfence = pe_fence_op(node, "on", FALSE, reason, FALSE, data_set);
621
622 if(dependency) {
623 order_actions(unfence, dependency, pe_order_optional);
624 }
625
626 } else if(rsc) {
627 GHashTableIter iter;
628
629 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
630 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
631 if(node->details->online && node->details->unclean == FALSE && node->details->shutdown == FALSE) {
632 trigger_unfencing(rsc, node, reason, dependency, data_set);
633 }
634 }
635 }
636}
637
638gboolean
639add_tag_ref(GHashTable * tags, const char * tag_name, const char * obj_ref)
640{
641 pe_tag_t *tag = NULL;
642 GList *gIter = NULL;
643 gboolean is_existing = FALSE;
644
645 CRM_CHECK(tags && tag_name && obj_ref, return FALSE);
646
647 tag = g_hash_table_lookup(tags, tag_name);
648 if (tag == NULL) {
649 tag = calloc(1, sizeof(pe_tag_t));
650 if (tag == NULL) {
651 return FALSE;
652 }
653 tag->id = strdup(tag_name);
654 tag->refs = NULL;
655 g_hash_table_insert(tags, strdup(tag_name), tag);
656 }
657
658 for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
659 const char *existing_ref = (const char *) gIter->data;
660
661 if (pcmk__str_eq(existing_ref, obj_ref, pcmk__str_none)){
662 is_existing = TRUE;
663 break;
664 }
665 }
666
667 if (is_existing == FALSE) {
668 tag->refs = g_list_append(tag->refs, strdup(obj_ref));
669 crm_trace("Added: tag=%s ref=%s", tag->id, obj_ref);
670 }
671
672 return TRUE;
673}
674
687bool
689{
690 const char *shutdown = pe_node_attribute_raw(node, XML_CIB_ATTR_SHUTDOWN);
691
692 return !pcmk__str_eq(shutdown, "0", pcmk__str_null_matches);
693}
694
702void
704{
705 if ((recheck > get_effective_time(data_set))
706 && ((data_set->recheck_by == 0)
707 || (data_set->recheck_by > recheck))) {
708 data_set->recheck_by = recheck;
709 }
710}
711
716void
717pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name,
718 pe_rule_eval_data_t *rule_data, GHashTable *hash,
719 const char *always_first, gboolean overwrite,
721{
722 crm_time_t *next_change = crm_time_new_undefined();
723
724 pe_eval_nvpairs(data_set->input, xml_obj, set_name, rule_data, hash,
725 always_first, overwrite, next_change);
726 if (crm_time_is_defined(next_change)) {
727 time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change);
728
730 }
731 crm_time_free(next_change);
732}
733
734bool
736{
737 const char *target_role = NULL;
738
739 CRM_CHECK(rsc != NULL, return false);
740 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
741 if (target_role) {
742 enum rsc_role_e target_role_e = text2role(target_role);
743
744 if ((target_role_e == RSC_ROLE_STOPPED)
745 || ((target_role_e == RSC_ROLE_UNPROMOTED)
747 return true;
748 }
749 }
750 return false;
751}
752
753bool
755{
756 for (GList *ele = rsc->running_on; ele; ele = ele->next) {
757 pe_node_t *node = (pe_node_t *) ele->data;
758 if (pcmk__str_in_list(node->details->uname, node_list,
760 return true;
761 }
762 }
763
764 return false;
765}
766
767bool
769{
770 return (rsc->fns->active(rsc, FALSE) && !pe__rsc_running_on_any(rsc, only_node));
771}
772
773GList *
774pe__filter_rsc_list(GList *rscs, GList *filter)
775{
776 GList *retval = NULL;
777
778 for (GList *gIter = rscs; gIter; gIter = gIter->next) {
779 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
780
781 /* I think the second condition is safe here for all callers of this
782 * function. If not, it needs to move into pe__node_text.
783 */
786 retval = g_list_prepend(retval, rsc);
787 }
788 }
789
790 return retval;
791}
792
793GList *
795 GList *nodes = NULL;
796
797 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
798 /* Nothing was given so return a list of all node names. Or, '*' was
799 * given. This would normally fall into the pe__unames_with_tag branch
800 * where it will return an empty list. Catch it here instead.
801 */
802 nodes = g_list_prepend(nodes, strdup("*"));
803 } else {
805
806 if (node) {
807 /* The given string was a valid uname for a node. Return a
808 * singleton list containing just that uname.
809 */
810 nodes = g_list_prepend(nodes, strdup(s));
811 } else {
812 /* The given string was not a valid uname. It's either a tag or
813 * it's a typo or something. In the first case, we'll return a
814 * list of all the unames of the nodes with the given tag. In the
815 * second case, we'll return a NULL pointer and nothing will
816 * get displayed.
817 */
818 nodes = pe__unames_with_tag(data_set, s);
819 }
820 }
821
822 return nodes;
823}
824
825GList *
827 GList *resources = NULL;
828
829 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
830 resources = g_list_prepend(resources, strdup("*"));
831 } else {
834
835 if (rsc) {
836 /* A colon in the name we were given means we're being asked to filter
837 * on a specific instance of a cloned resource. Put that exact string
838 * into the filter list. Otherwise, use the printable ID of whatever
839 * resource was found that matches what was asked for.
840 */
841 if (strstr(s, ":") != NULL) {
842 resources = g_list_prepend(resources, strdup(rsc->id));
843 } else {
844 resources = g_list_prepend(resources, strdup(rsc_printable_id(rsc)));
845 }
846 } else {
847 /* The given string was not a valid resource name. It's a tag or a
848 * typo or something. See pe__build_node_name_list() for more
849 * detail.
850 */
851 resources = pe__rscs_with_tag(data_set, s);
852 }
853 }
854
855 return resources;
856}
857
858xmlNode *
860{
862 const char *rsc_id = rsc->id;
863
864 if (rsc->variant == pe_clone) {
865 rsc_id = pe__clone_child_id(rsc);
866 } else if (parent->variant == pe_clone) {
867 rsc_id = pe__clone_child_id(parent);
868 }
869
870 for (xmlNode *xml_op = pcmk__xml_first_child(rsc->cluster->failed); xml_op != NULL;
871 xml_op = pcmk__xml_next(xml_op)) {
872 const char *value = NULL;
873 char *op_id = NULL;
874
875 /* This resource operation is not a failed probe. */
876 if (!pcmk_xe_mask_probe_failure(xml_op)) {
877 continue;
878 }
879
880 /* This resource operation was not run on the given node. Note that if name is
881 * NULL, this will always succeed.
882 */
883 value = crm_element_value(xml_op, XML_LRM_ATTR_TARGET);
884 if (value == NULL || !pcmk__str_eq(value, name, pcmk__str_casei|pcmk__str_null_matches)) {
885 continue;
886 }
887
888 /* This resource operation has no operation_key. */
890 if (!parse_op_key(value ? value : ID(xml_op), &op_id, NULL, NULL)) {
891 continue;
892 }
893
894 /* This resource operation's ID does not match the rsc_id we are looking for. */
895 if (!pcmk__str_eq(op_id, rsc_id, pcmk__str_none)) {
896 free(op_id);
897 continue;
898 }
899
900 free(op_id);
901 return xml_op;
902 }
903
904 return NULL;
905}
const char * parent
Definition: cib.c:25
const char * name
Definition: cib.c:24
uint64_t flags
Definition: remote.c:3
gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, guint *interval_ms)
Definition: operations.c:185
int pcmk__add_scores(int score1, int score2)
Definition: scores.c:113
bool pcmk_xe_mask_probe_failure(xmlNode *xml_op)
Definition: operations.c:562
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:483
pe_resource_t * uber_parent(pe_resource_t *rsc)
Definition: complex.c:912
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:352
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:140
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
Definition: iso8601.c:132
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:92
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
Definition: iso8601.c:116
struct crm_time_s crm_time_t
Definition: iso8601.h:32
#define crm_info(fmt, args...)
Definition: logging.h:362
#define crm_notice(fmt, args...)
Definition: logging.h:361
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:227
#define crm_err(fmt, args...)
Definition: logging.h:359
#define crm_trace(fmt, args...)
Definition: logging.h:365
#define LOG_TRACE
Definition: logging.h:37
#define pcmk__config_err(fmt...)
#define pcmk__log_else(level, else_action)
#define ID(x)
Definition: msg_xml.h:468
#define XML_RSC_ATTR_TARGET_ROLE
Definition: msg_xml.h:236
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:301
#define XML_CIB_ATTR_SHUTDOWN
Definition: msg_xml.h:286
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:302
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:517
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:66
#define pe_rsc_fence_device
Definition: pe_types.h:263
#define pe_flag_have_stonith_resource
Definition: pe_types.h:100
#define pe_flag_have_quorum
Definition: pe_types.h:95
pe_ordering
Definition: pe_types.h:479
@ pe_order_none
Definition: pe_types.h:480
@ pe_order_optional
Definition: pe_types.h:481
#define pe_flag_enable_unfencing
Definition: pe_types.h:101
#define pe_rsc_unique
Definition: pe_types.h:262
#define pe_rsc_orphan
Definition: pe_types.h:256
@ pe_discover_never
Definition: pe_types.h:474
@ pe_find_any
match base name of any clone instance
Definition: pe_types.h:90
@ pe_find_renamed
match resource ID or LRM history ID
Definition: pe_types.h:85
@ pe_clone
Definition: pe_types.h:40
#define pe_flag_stonith_enabled
Definition: pe_types.h:99
#define pe_rsc_promotable
Definition: pe_types.h:264
const char * pe_node_attribute_raw(const pe_node_t *node, const char *name)
Definition: common.c:562
GList * pe__unames_with_tag(pe_working_set_t *data_set, const char *tag_name)
Definition: tags.c:51
#define pe__clear_resource_flags(resource, flags_to_clear)
Definition: internal.h:80
GList * pe__rscs_with_tag(pe_working_set_t *data_set, const char *tag_name)
Definition: tags.c:20
const char * pe__clone_child_id(pe_resource_t *rsc)
Definition: clone.c:1200
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:47
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)
Definition: pe_actions.c:1081
#define pe__set_resource_flags(resource, flags_to_set)
Definition: internal.h:74
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:826
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:595
bool pe__rsc_running_on_any(pe_resource_t *rsc, GList *node_list)
Definition: utils.c:754
void destroy_ticket(gpointer data)
Definition: utils.c:521
GHashTable * pe__node_list2table(GList *list)
Definition: utils.c:151
void pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag)
Definition: utils.c:586
bool pcmk__rsc_filtered_by_node(pe_resource_t *rsc, GList *only_node)
Definition: utils.c:768
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:604
void pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name, pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, gboolean overwrite, pe_working_set_t *data_set)
Definition: utils.c:717
bool pe__resource_is_disabled(pe_resource_t *rsc)
Definition: utils.c:735
gint pe__cmp_rsc_priority(gconstpointer a, gconstpointer b)
Definition: utils.c:325
void pe__show_node_weights_as(const char *file, const char *function, int line, bool to_log, pe_resource_t *rsc, const char *comment, GHashTable *nodes, pe_working_set_t *data_set)
Definition: utils.c:280
gboolean get_target_role(pe_resource_t *rsc, enum rsc_role_e *role)
Definition: utils.c:436
GList * pe__build_node_name_list(pe_working_set_t *data_set, const char *s)
Definition: utils.c:794
GList * pe__filter_rsc_list(GList *rscs, GList *filter)
Definition: utils.c:774
gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data)
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
Definition: utils.c:180
gboolean order_actions(pe_action_t *lh_action, pe_action_t *rh_action, enum pe_ordering order)
Definition: utils.c:474
bool pe__shutdown_requested(pe_node_t *node)
Definition: utils.c:688
void resource_location(pe_resource_t *rsc, pe_node_t *node, int score, const char *tag, pe_working_set_t *data_set)
Definition: utils.c:385
time_t get_effective_time(pe_working_set_t *data_set)
Definition: utils.c:421
const char * rsc_printable_id(pe_resource_t *rsc)
Definition: utils.c:568
pe_ticket_t * ticket_new(const char *ticket_id, pe_working_set_t *data_set)
Definition: utils.c:533
xmlNode * pe__failed_probe_for_rsc(pe_resource_t *rsc, const char *name)
Definition: utils.c:859
bool pcmk__is_daemon
Definition: logging.c:47
void pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set)
Definition: utils.c:703
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:639
void pe__clear_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
Definition: utils.c:577
bool pe_can_fence(pe_working_set_t *data_set, pe_node_t *node)
Definition: utils.c:36
#define CRM_ASSERT(expr)
Definition: results.h:42
void pe_eval_nvpairs(xmlNode *top, const xmlNode *xml_obj, const char *set_name, pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, gboolean overwrite, crm_time_t *next_change)
Definition: rules.c:515
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(GList *node_list, const char *uname)
Definition: status.c:443
pe_node_t * pe_find_node_id(GList *node_list, const char *id)
Definition: status.c:427
int pcmk__numeric_strcasecmp(const char *s1, const char *s2)
Definition: strings.c:1018
gboolean pcmk__str_in_list(const gchar *s, const GList *lst, uint32_t flags)
Definition: strings.c:883
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:411
GList * actions_after
Definition: pe_types.h:444
GList * actions_before
Definition: pe_types.h:443
enum pe_ordering type
Definition: pe_types.h:528
pe_action_t * action
Definition: pe_types.h:530
int weight
Definition: pe_types.h:249
int rsc_discover_mode
Definition: pe_types.h:253
gboolean fixed
Definition: pe_types.h:250
struct pe_node_shared_s * details
Definition: pe_types.h:252
gboolean shutdown
Definition: pe_types.h:226
const char * id
Definition: pe_types.h:215
gboolean online
Definition: pe_types.h:220
const char * uname
Definition: pe_types.h:216
pe_resource_t * remote_rsc
Definition: pe_types.h:237
gboolean unclean
Definition: pe_types.h:224
GList * running_on
Definition: pe_types.h:373
enum pe_obj_types variant
Definition: pe_types.h:338
GHashTable * meta
Definition: pe_types.h:380
GList * children
Definition: pe_types.h:384
gboolean exclusive_discover
Definition: pe_types.h:359
pe_working_set_t * cluster
Definition: pe_types.h:335
pe_resource_t * container
Definition: pe_types.h:387
char * id
Definition: pe_types.h:329
xmlNode * xml
Definition: pe_types.h:331
GHashTable * allowed_nodes
Definition: pe_types.h:375
pe_node_t * allocated_to
Definition: pe_types.h:370
unsigned long long flags
Definition: pe_types.h:355
pe_resource_t * parent
Definition: pe_types.h:336
resource_object_functions_t * fns
Definition: pe_types.h:340
char * id
Definition: pe_types.h:461
GList * refs
Definition: pe_types.h:462
GHashTable * state
Definition: pe_types.h:457
char * id
Definition: pe_types.h:453
gboolean standby
Definition: pe_types.h:456
gboolean granted
Definition: pe_types.h:454
time_t last_granted
Definition: pe_types.h:455
xmlNode * input
Definition: pe_types.h:144
GList * resources
Definition: pe_types.h:165
xmlNode * failed
Definition: pe_types.h:172
unsigned long long flags
Definition: pe_types.h:153
enum pe_quorum_policy no_quorum_policy
Definition: pe_types.h:156
GHashTable * tickets
Definition: pe_types.h:159
GList * nodes
Definition: pe_types.h:164
time_t recheck_by
Definition: pe_types.h:194
crm_time_t * now
Definition: pe_types.h:145
gboolean(* active)(pe_resource_t *, gboolean)
Definition: pe_types.h:53