pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_graph_consumer.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 <sys/param.h>
13#include <sys/stat.h>
14
15#include <crm/crm.h>
16#include <crm/common/xml.h>
18#include <crm/lrmd_internal.h>
19#include <pacemaker-internal.h>
20
21
22/*
23 * Functions for freeing transition graph objects
24 */
25
32static void
33free_graph_action(gpointer user_data)
34{
35 pcmk__graph_action_t *action = user_data;
36
37 if (action->timer != 0) {
38 crm_warn("Cancelling timer for graph action %d", action->id);
39 g_source_remove(action->timer);
40 }
41 if (action->params != NULL) {
42 g_hash_table_destroy(action->params);
43 }
44 free_xml(action->xml);
45 free(action);
46}
47
54static void
55free_graph_synapse(gpointer user_data)
56{
57 pcmk__graph_synapse_t *synapse = user_data;
58
59 g_list_free_full(synapse->actions, free_graph_action);
60 g_list_free_full(synapse->inputs, free_graph_action);
61 free(synapse);
62}
63
70void
72{
73 if (graph != NULL) {
74 g_list_free_full(graph->synapses, free_graph_synapse);
75 free(graph->source);
76 free(graph->failed_stop_offset);
77 free(graph->failed_start_offset);
78 free(graph);
79 }
80}
81
82
83/*
84 * Functions for updating graph
85 */
86
104static void
105update_synapse_ready(pcmk__graph_synapse_t *synapse, int action_id)
106{
107 if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
108 return; // All inputs have already been confirmed
109 }
110
111 // Presume ready until proven otherwise
113
114 for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
115 pcmk__graph_action_t *prereq = (pcmk__graph_action_t *) lpc->data;
116
117 if (prereq->id == action_id) {
118 crm_trace("Confirming input %d of synapse %d",
119 action_id, synapse->id);
121
122 } else if (!pcmk_is_set(prereq->flags, pcmk__graph_action_confirmed)) {
124 crm_trace("Synapse %d still not ready after action %d",
125 synapse->id, action_id);
126 }
127 }
128 if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
129 crm_trace("Synapse %d is now ready to execute", synapse->id);
130 }
131}
132
140static void
141update_synapse_confirmed(pcmk__graph_synapse_t *synapse, int action_id)
142{
143 bool all_confirmed = true;
144
145 for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
147
148 if (action->id == action_id) {
149 crm_trace("Confirmed action %d of synapse %d",
150 action_id, synapse->id);
152
153 } else if (all_confirmed &&
155 all_confirmed = false;
156 crm_trace("Synapse %d still not confirmed after action %d",
157 synapse->id, action_id);
158 }
159 }
160
161 if (all_confirmed
163 crm_trace("Confirmed synapse %d", synapse->id);
165 }
166}
167
175void
177{
178 for (GList *lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
179 pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
180
181 if (pcmk_any_flags_set(synapse->flags,
183 continue; // This synapse already completed
184
185 } else if (pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
186 update_synapse_confirmed(synapse, action->id);
187
188 } else if (!pcmk_is_set(action->flags, pcmk__graph_action_failed)
189 || (synapse->priority == PCMK_SCORE_INFINITY)) {
190 update_synapse_ready(synapse, action->id);
191 }
192 }
193}
194
195
196/*
197 * Functions for executing graph
198 */
199
200/* A transition graph consists of various types of actions. The library caller
201 * registers execution functions for each action type, which will be stored
202 * here.
203 */
204static pcmk__graph_functions_t *graph_fns = NULL;
205
212void
214{
215 crm_debug("Setting custom functions for executing transition graphs");
216 graph_fns = fns;
217
218 CRM_ASSERT(graph_fns != NULL);
219 CRM_ASSERT(graph_fns->rsc != NULL);
220 CRM_ASSERT(graph_fns->cluster != NULL);
221 CRM_ASSERT(graph_fns->pseudo != NULL);
222 CRM_ASSERT(graph_fns->fence != NULL);
223}
224
234static bool
235should_fire_synapse(pcmk__graph_t *graph, pcmk__graph_synapse_t *synapse)
236{
237 GList *lpc = NULL;
238
240 for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
241 pcmk__graph_action_t *prereq = (pcmk__graph_action_t *) lpc->data;
242
243 if (!(pcmk_is_set(prereq->flags, pcmk__graph_action_confirmed))) {
244 crm_trace("Input %d for synapse %d not yet confirmed",
245 prereq->id, synapse->id);
247 break;
248
249 } else if (pcmk_is_set(prereq->flags, pcmk__graph_action_failed)
250 && !pcmk_is_set(prereq->flags,
252 crm_trace("Input %d for synapse %d confirmed but failed",
253 prereq->id, synapse->id);
255 break;
256 }
257 }
258 if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
259 crm_trace("Synapse %d is ready to execute", synapse->id);
260 } else {
261 return false;
262 }
263
264 for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
266
267 if (a->type == pcmk__pseudo_graph_action) {
268 /* None of the below applies to pseudo ops */
269
270 } else if (synapse->priority < graph->abort_priority) {
271 crm_trace("Skipping synapse %d: priority %d is less than "
272 "abort priority %d",
273 synapse->id, synapse->priority, graph->abort_priority);
274 graph->skipped++;
275 return false;
276
277 } else if (graph_fns->allowed && !(graph_fns->allowed(graph, a))) {
278 crm_trace("Deferring synapse %d: not allowed", synapse->id);
279 return false;
280 }
281 }
282
283 return true;
284}
285
295static int
296initiate_action(pcmk__graph_t *graph, pcmk__graph_action_t *action)
297{
298 const char *id = pcmk__xe_id(action->xml);
299
300 CRM_CHECK(id != NULL, return EINVAL);
302 return pcmk_rc_already);
303
305 switch (action->type) {
307 crm_trace("Executing pseudo-action %d (%s)", action->id, id);
308 return graph_fns->pseudo(graph, action);
309
311 crm_trace("Executing resource action %d (%s)", action->id, id);
312 return graph_fns->rsc(graph, action);
313
315 if (pcmk__str_eq(crm_element_value(action->xml, PCMK_XA_OPERATION),
317 crm_trace("Executing fencing action %d (%s)",
318 action->id, id);
319 return graph_fns->fence(graph, action);
320 }
321 crm_trace("Executing cluster action %d (%s)", action->id, id);
322 return graph_fns->cluster(graph, action);
323
324 default:
325 crm_err("Unsupported graph action type <%s " PCMK_XA_ID "='%s'> "
326 "(bug?)",
327 action->xml->name, id);
328 return EINVAL;
329 }
330}
331
341static int
342fire_synapse(pcmk__graph_t *graph, pcmk__graph_synapse_t *synapse)
343{
345 for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
347 int rc = initiate_action(graph, action);
348
349 if (rc != pcmk_rc_ok) {
350 crm_err("Failed initiating <%s " PCMK_XA_ID "=%d> in synapse %d: "
351 "%s",
352 action->xml->name, action->id, synapse->id,
353 pcmk_rc_str(rc));
358 return pcmk_rc_error;
359 }
360 }
361 return pcmk_rc_ok;
362}
363
375static int
376pseudo_action_dummy(pcmk__graph_t *graph, pcmk__graph_action_t *action)
377{
378 static int fail = -1;
379
380 if (fail < 0) {
381 long long fail_ll;
382
383 if ((pcmk__scan_ll(getenv("PE_fail"), &fail_ll, 0LL) == pcmk_rc_ok)
384 && (fail_ll > 0LL) && (fail_ll <= INT_MAX)) {
385 fail = (int) fail_ll;
386 } else {
387 fail = 0;
388 }
389 }
390
391 if (action->id == fail) {
392 crm_err("Dummy event handler: pretending action %d failed", action->id);
395 } else {
396 crm_trace("Dummy event handler: action %d initiated", action->id);
397 }
400 return pcmk_rc_ok;
401}
402
403static pcmk__graph_functions_t default_fns = {
404 pseudo_action_dummy,
405 pseudo_action_dummy,
406 pseudo_action_dummy,
407 pseudo_action_dummy
408};
409
420{
421 GList *lpc = NULL;
422 int log_level = LOG_DEBUG;
423 enum pcmk__graph_status pass_result = pcmk__graph_active;
424 const char *status = "In progress";
425
426 if (graph_fns == NULL) {
427 graph_fns = &default_fns;
428 }
429 if (graph == NULL) {
431 }
432
433 graph->fired = 0;
434 graph->pending = 0;
435 graph->skipped = 0;
436 graph->completed = 0;
437 graph->incomplete = 0;
438
439 // Count completed and in-flight synapses
440 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
441 pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
442
444 graph->completed++;
445
446 } else if (!pcmk_is_set(synapse->flags, pcmk__synapse_failed)
448 graph->pending++;
449 }
450 }
451 crm_trace("Executing graph %d (%d synapses already completed, %d pending)",
452 graph->id, graph->completed, graph->pending);
453
454 // Execute any synapses that are ready
455 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
456 pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
457
458 if ((graph->batch_limit > 0)
459 && (graph->pending >= graph->batch_limit)) {
460
461 crm_debug("Throttling graph execution: batch limit (%d) reached",
462 graph->batch_limit);
463 break;
464
465 } else if (pcmk_is_set(synapse->flags, pcmk__synapse_failed)) {
466 graph->skipped++;
467 continue;
468
469 } else if (pcmk_any_flags_set(synapse->flags,
472 continue; // Already handled
473
474 } else if (should_fire_synapse(graph, synapse)) {
475 graph->fired++;
476 if (fire_synapse(graph, synapse) != pcmk_rc_ok) {
477 crm_err("Synapse %d failed to fire", synapse->id);
478 log_level = LOG_ERR;
480 graph->incomplete++;
481 graph->fired--;
482 }
483
484 if (!(pcmk_is_set(synapse->flags, pcmk__synapse_confirmed))) {
485 graph->pending++;
486 }
487
488 } else {
489 crm_trace("Synapse %d cannot fire", synapse->id);
490 graph->incomplete++;
491 }
492 }
493
494 if ((graph->pending == 0) && (graph->fired == 0)) {
495 graph->complete = true;
496
497 if ((graph->incomplete != 0) && (graph->abort_priority <= 0)) {
498 log_level = LOG_WARNING;
499 pass_result = pcmk__graph_terminated;
500 status = "Terminated";
501
502 } else if (graph->skipped != 0) {
503 log_level = LOG_NOTICE;
504 pass_result = pcmk__graph_complete;
505 status = "Stopped";
506
507 } else {
508 log_level = LOG_NOTICE;
509 pass_result = pcmk__graph_complete;
510 status = "Complete";
511 }
512
513 } else if (graph->fired == 0) {
514 pass_result = pcmk__graph_pending;
515 }
516
517 do_crm_log(log_level,
518 "Transition %d (Complete=%d, Pending=%d,"
519 " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s",
520 graph->id, graph->completed, graph->pending, graph->fired,
521 graph->skipped, graph->incomplete, graph->source, status);
522
523 return pass_result;
524}
525
526
527/*
528 * Functions for unpacking transition graph XML into structs
529 */
530
541unpack_action(pcmk__graph_synapse_t *parent, xmlNode *xml_action)
542{
543 enum pcmk__graph_action_type action_type;
545 const char *value = pcmk__xe_id(xml_action);
546
547 if (value == NULL) {
548 crm_err("Ignoring transition graph action without " PCMK_XA_ID
549 " (bug?)");
550 crm_log_xml_trace(xml_action, "invalid");
551 return NULL;
552 }
553
554 if (pcmk__xe_is(xml_action, PCMK__XE_RSC_OP)) {
555 action_type = pcmk__rsc_graph_action;
556
557 } else if (pcmk__xe_is(xml_action, PCMK__XE_PSEUDO_EVENT)) {
558 action_type = pcmk__pseudo_graph_action;
559
560 } else if (pcmk__xe_is(xml_action, PCMK__XE_CRM_EVENT)) {
561 action_type = pcmk__cluster_graph_action;
562
563 } else {
564 crm_err("Ignoring transition graph action of unknown type '%s' (bug?)",
565 xml_action->name);
566 crm_log_xml_trace(xml_action, "invalid");
567 return NULL;
568 }
569
570 action = calloc(1, sizeof(pcmk__graph_action_t));
571 if (action == NULL) {
572 crm_perror(LOG_CRIT, "Cannot unpack transition graph action");
573 crm_log_xml_trace(xml_action, "lost");
574 return NULL;
575 }
576
577 pcmk__scan_min_int(value, &(action->id), -1);
579 action->xml = pcmk__xml_copy(NULL, xml_action);
580 action->synapse = parent;
581 action->type = action_type;
582 action->params = xml2list(action->xml);
583
584 value = crm_meta_value(action->params, PCMK_META_TIMEOUT);
585 pcmk__scan_min_int(value, &(action->timeout), 0);
586
587 /* Take PCMK_META_START_DELAY into account for the timeout of the action
588 * timer
589 */
591 {
592 int start_delay;
593
594 pcmk__scan_min_int(value, &start_delay, 0);
595 action->timeout += start_delay;
596 }
597
599 0, &(action->interval_ms)) != pcmk_rc_ok) {
600 action->interval_ms = 0;
601 }
602
603 value = crm_meta_value(action->params, PCMK__META_CAN_FAIL);
604 if (value != NULL) {
605 int can_fail = 0;
606
607 if ((crm_str_to_boolean(value, &can_fail) > 0) && (can_fail > 0)) {
609 } else {
611 }
612
614 crm_warn("Support for the " PCMK__META_CAN_FAIL " meta-attribute "
615 "is deprecated and will be removed in a future release");
616 }
617 }
618
619 crm_trace("Action %d has timer set to %dms", action->id, action->timeout);
620
621 return action;
622}
623
634unpack_synapse(pcmk__graph_t *new_graph, const xmlNode *xml_synapse)
635{
636 const char *value = NULL;
637 xmlNode *action_set = NULL;
638 pcmk__graph_synapse_t *new_synapse = NULL;
639
640 crm_trace("Unpacking synapse %s", pcmk__xe_id(xml_synapse));
641
642 new_synapse = calloc(1, sizeof(pcmk__graph_synapse_t));
643 if (new_synapse == NULL) {
644 return NULL;
645 }
646
647 pcmk__scan_min_int(pcmk__xe_id(xml_synapse), &(new_synapse->id), 0);
648
649 value = crm_element_value(xml_synapse, PCMK__XA_PRIORITY);
650 pcmk__scan_min_int(value, &(new_synapse->priority), 0);
651
652 CRM_CHECK(new_synapse->id >= 0,
653 free_graph_synapse((gpointer) new_synapse); return NULL);
654
655 new_graph->num_synapses++;
656
657 crm_trace("Unpacking synapse %s action sets",
658 crm_element_value(xml_synapse, PCMK_XA_ID));
659
660 for (action_set = pcmk__xe_first_child(xml_synapse, "action_set", NULL,
661 NULL);
662 action_set != NULL; action_set = pcmk__xe_next_same(action_set)) {
663
664 for (xmlNode *action = pcmk__xe_first_child(action_set, NULL, NULL,
665 NULL);
666 action != NULL; action = pcmk__xe_next(action)) {
667
668 pcmk__graph_action_t *new_action = unpack_action(new_synapse,
669 action);
670
671 if (new_action == NULL) {
672 continue;
673 }
674
675 crm_trace("Adding action %d to synapse %d",
676 new_action->id, new_synapse->id);
677 new_graph->num_actions++;
678 new_synapse->actions = g_list_append(new_synapse->actions,
679 new_action);
680 }
681 }
682
683 crm_trace("Unpacking synapse %s inputs", pcmk__xe_id(xml_synapse));
684
685 for (xmlNode *inputs = pcmk__xe_first_child(xml_synapse, "inputs", NULL,
686 NULL);
687 inputs != NULL; inputs = pcmk__xe_next_same(inputs)) {
688
689 for (xmlNode *trigger = pcmk__xe_first_child(inputs, "trigger", NULL,
690 NULL);
691 trigger != NULL; trigger = pcmk__xe_next_same(trigger)) {
692
693 for (xmlNode *input = pcmk__xe_first_child(trigger, NULL, NULL,
694 NULL);
695 input != NULL; input = pcmk__xe_next(input)) {
696
697 pcmk__graph_action_t *new_input = unpack_action(new_synapse,
698 input);
699
700 if (new_input == NULL) {
701 continue;
702 }
703
704 crm_trace("Adding input %d to synapse %d",
705 new_input->id, new_synapse->id);
706
707 new_synapse->inputs = g_list_append(new_synapse->inputs,
708 new_input);
709 }
710 }
711 }
712
713 return new_synapse;
714}
715
742pcmk__unpack_graph(const xmlNode *xml_graph, const char *reference)
743{
744 pcmk__graph_t *new_graph = NULL;
745
746 new_graph = calloc(1, sizeof(pcmk__graph_t));
747 if (new_graph == NULL) {
748 return NULL;
749 }
750
751 new_graph->source = strdup(pcmk__s(reference, "unknown"));
752 if (new_graph->source == NULL) {
753 pcmk__free_graph(new_graph);
754 return NULL;
755 }
756
757 new_graph->id = -1;
758 new_graph->abort_priority = 0;
759 new_graph->network_delay = 0;
760 new_graph->stonith_timeout = 0;
762
763 // Parse top-level attributes from PCMK__XE_TRANSITION_GRAPH
764 if (xml_graph != NULL) {
765 const char *buf = crm_element_value(xml_graph, "transition_id");
766
767 CRM_CHECK(buf != NULL,
768 pcmk__free_graph(new_graph); return NULL);
769 pcmk__scan_min_int(buf, &(new_graph->id), -1);
770
772 CRM_CHECK(buf != NULL,
773 pcmk__free_graph(new_graph); return NULL);
774 pcmk_parse_interval_spec(buf, &(new_graph->network_delay));
775
777 if (buf == NULL) {
778 new_graph->stonith_timeout = new_graph->network_delay;
779 } else {
780 pcmk_parse_interval_spec(buf, &(new_graph->stonith_timeout));
781 }
782
783 // Use 0 (dynamic limit) as default/invalid, -1 (no limit) as minimum
784 buf = crm_element_value(xml_graph, PCMK_OPT_BATCH_LIMIT);
785 if ((buf == NULL)
786 || (pcmk__scan_min_int(buf, &(new_graph->batch_limit),
787 -1) != pcmk_rc_ok)) {
788 new_graph->batch_limit = 0;
789 }
790
792 pcmk__scan_min_int(buf, &(new_graph->migration_limit), -1);
793
794 new_graph->failed_stop_offset =
795 crm_element_value_copy(xml_graph, "failed-stop-offset");
796 new_graph->failed_start_offset =
797 crm_element_value_copy(xml_graph, "failed-start-offset");
798
799 if (crm_element_value_epoch(xml_graph, "recheck-by",
800 &(new_graph->recheck_by)) != pcmk_ok) {
801 new_graph->recheck_by = 0;
802 }
803 }
804
805 // Unpack each child <synapse> element
806 for (const xmlNode *synapse_xml = pcmk__xe_first_child(xml_graph,
807 "synapse", NULL,
808 NULL);
809 synapse_xml != NULL; synapse_xml = pcmk__xe_next_same(synapse_xml)) {
810
811 pcmk__graph_synapse_t *new_synapse = unpack_synapse(new_graph,
812 synapse_xml);
813
814 if (new_synapse != NULL) {
815 new_graph->synapses = g_list_append(new_graph->synapses,
816 new_synapse);
817 }
818 }
819
820 crm_debug("Unpacked transition %d from %s: %d actions in %d synapses",
821 new_graph->id, new_graph->source, new_graph->num_actions,
822 new_graph->num_synapses);
823
824 return new_graph;
825}
826
827
828/*
829 * Other transition graph utilities
830 */
831
845pcmk__event_from_graph_action(const xmlNode *resource,
847 int status, int rc, const char *exit_reason)
848{
849 lrmd_event_data_t *op = NULL;
850 GHashTableIter iter;
851 const char *name = NULL;
852 const char *value = NULL;
853 xmlNode *action_resource = NULL;
854
855 CRM_CHECK(action != NULL, return NULL);
856 CRM_CHECK(action->type == pcmk__rsc_graph_action, return NULL);
857
858 action_resource = pcmk__xe_first_child(action->xml, PCMK_XE_PRIMITIVE, NULL,
859 NULL);
860 CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "invalid");
861 return NULL);
862
863 op = lrmd_new_event(pcmk__xe_id(action_resource),
865 action->interval_ms);
866 lrmd__set_result(op, rc, status, exit_reason);
867 op->t_run = time(NULL);
868 op->t_rcchange = op->t_run;
869 op->params = pcmk__strkey_table(free, free);
870
871 g_hash_table_iter_init(&iter, action->params);
872 while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
873 pcmk__insert_dup(op->params, name, value);
874 }
875
876 for (xmlNode *xop = pcmk__xe_first_child(resource, NULL, NULL, NULL);
877 xop != NULL; xop = pcmk__xe_next(xop)) {
878
879 int tmp = 0;
880
882 crm_debug("Got call_id=%d for %s", tmp, pcmk__xe_id(resource));
883 if (tmp > op->call_id) {
884 op->call_id = tmp;
885 }
886 }
887
888 op->call_id++;
889 return op;
890}
#define PCMK_ACTION_STONITH
Definition actions.h:74
const char * parent
Definition cib.c:27
const char * name
Definition cib.c:26
char int pcmk_parse_interval_spec(const char *input, guint *result_ms)
Parse milliseconds from a Pacemaker interval specification.
Definition strings.c:451
int crm_str_to_boolean(const char *s, int *ret)
Definition strings.c:496
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:98
A dumping ground.
#define CRM_META
Definition crm.h:81
#define do_crm_log(level, fmt, args...)
Log a message.
Definition logging.h:181
#define crm_warn(fmt, args...)
Definition logging.h:392
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition logging.h:331
#define CRM_CHECK(expr, failure_action)
Definition logging.h:245
#define crm_debug(fmt, args...)
Definition logging.h:400
#define crm_err(fmt, args...)
Definition logging.h:389
#define crm_log_xml_trace(xml, text)
Definition logging.h:410
#define crm_log_xml_warn(xml, text)
Definition logging.h:406
#define crm_trace(fmt, args...)
Definition logging.h:402
lrmd_event_data_t * lrmd_new_event(const char *rsc_id, const char *task, guint interval_ms)
Create a new lrmd_event_data_t object.
void lrmd__set_result(lrmd_event_data_t *event, enum ocf_exitcode rc, int op_status, const char *exit_reason)
xmlNode * input
const char * crm_meta_value(GHashTable *hash, const char *field)
Get the value of a meta-attribute.
Definition nvpair.c:987
GHashTable * xml2list(const xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition nvpair.c:859
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:446
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition nvpair.c:482
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition nvpair.c:674
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
Definition nvpair.c:567
#define PCMK_META_INTERVAL
Definition options.h:91
#define PCMK_OPT_BATCH_LIMIT
Definition options.h:27
#define PCMK_OPT_CLUSTER_DELAY
Definition options.h:28
#define PCMK_META_START_DELAY
Definition options.h:112
#define PCMK_OPT_MIGRATION_LIMIT
Definition options.h:45
#define PCMK_META_TIMEOUT
Definition options.h:114
#define PCMK_OPT_STONITH_TIMEOUT
Definition options.h:67
#define PCMK__META_CAN_FAIL
const char * action
Definition pcmk_fence.c:30
void pcmk__free_graph(pcmk__graph_t *graph)
pcmk__graph_t * pcmk__unpack_graph(const xmlNode *xml_graph, const char *reference)
void pcmk__set_graph_functions(pcmk__graph_functions_t *fns)
enum pcmk__graph_status pcmk__execute_graph(pcmk__graph_t *graph)
lrmd_event_data_t * pcmk__event_from_graph_action(const xmlNode *resource, const pcmk__graph_action_t *action, int status, int rc, const char *exit_reason)
void pcmk__update_graph(pcmk__graph_t *graph, const pcmk__graph_action_t *action)
@ pcmk__graph_action_confirmed
@ pcmk__graph_action_can_fail
@ pcmk__graph_action_failed
@ pcmk__graph_action_executed
@ pcmk__graph_done
#define pcmk__clear_graph_action_flags(action, flags_to_clear)
@ pcmk__synapse_ready
@ pcmk__synapse_executed
@ pcmk__synapse_confirmed
@ pcmk__synapse_failed
#define pcmk__set_synapse_flags(synapse, flags_to_set)
#define pcmk__clear_synapse_flags(synapse, flags_to_clear)
pcmk__graph_status
@ pcmk__graph_pending
@ pcmk__graph_terminated
@ pcmk__graph_active
@ pcmk__graph_complete
pcmk__graph_action_type
@ pcmk__pseudo_graph_action
@ pcmk__cluster_graph_action
@ pcmk__rsc_graph_action
#define pcmk__set_graph_action_flags(action, flags_to_set)
#define CRM_ASSERT(expr)
Definition results.h:42
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition results.c:501
@ pcmk_rc_ok
Definition results.h:162
@ pcmk_rc_error
Definition results.h:157
@ pcmk_rc_already
Definition results.h:153
#define pcmk_ok
Definition results.h:69
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition scores.h:24
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition strings.c:701
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition strings.c:127
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:683
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition strings.c:97
@ pcmk__str_none
int pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val, guint *result)
Definition strings.c:311
unsigned int t_run
Definition lrmd_events.h:72
unsigned int t_rcchange
Definition lrmd_events.h:75
int(* fence)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
int(* rsc)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
int(* cluster)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
bool(* allowed)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
int(* pseudo)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
char * failed_stop_offset
Failcount after one failed stop action.
time_t recheck_by
Time (from epoch) by which the controller should re-run the scheduler.
enum pcmk__graph_next completion_action
char * failed_start_offset
Failcount after one failed start action.
Wrappers for and extensions to libxml2.
void free_xml(xmlNode *child)
Definition xml.c:867
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition xml.c:883
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition xml.c:440
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition xml.c:2108
#define PCMK_XA_OPERATION
Definition xml_names.h:344
#define PCMK_XA_ID
Definition xml_names.h:296
#define PCMK_XE_PRIMITIVE
Definition xml_names.h:160
#define PCMK__XA_PRIORITY
#define PCMK__XE_RSC_OP
#define PCMK__XE_CRM_EVENT
#define PCMK__XA_CALL_ID
#define PCMK__XE_PSEUDO_EVENT