pacemaker 2.1.6-6fdc9deea29
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-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 <sys/param.h>
13#include <sys/stat.h>
14
15#include <crm/crm.h>
16#include <crm/msg_xml.h>
17#include <crm/common/xml.h>
19#include <crm/lrmd_internal.h>
20#include <pacemaker-internal.h>
21
22
23/*
24 * Functions for updating graph
25 */
26
44static void
45update_synapse_ready(pcmk__graph_synapse_t *synapse, int action_id)
46{
47 if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
48 return; // All inputs have already been confirmed
49 }
50 pcmk__set_synapse_flags(synapse, pcmk__synapse_ready); // Presume ready until proven otherwise
51 for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
52 pcmk__graph_action_t *prereq = (pcmk__graph_action_t *) lpc->data;
53
54 if (prereq->id == action_id) {
55 crm_trace("Confirming input %d of synapse %d",
56 action_id, synapse->id);
58
59 } else if (!(pcmk_is_set(prereq->flags, pcmk__graph_action_confirmed))) {
61 crm_trace("Synapse %d still not ready after action %d",
62 synapse->id, action_id);
63 }
64 }
65 if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
66 crm_trace("Synapse %d is now ready to execute", synapse->id);
67 }
68}
69
77static void
78update_synapse_confirmed(pcmk__graph_synapse_t *synapse, int action_id)
79{
80 bool all_confirmed = true;
81
82 for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
84
85 if (action->id == action_id) {
86 crm_trace("Confirmed action %d of synapse %d",
87 action_id, synapse->id);
89
90 } else if (all_confirmed && !(pcmk_is_set(action->flags, pcmk__graph_action_confirmed))) {
91 all_confirmed = false;
92 crm_trace("Synapse %d still not confirmed after action %d",
93 synapse->id, action_id);
94 }
95 }
96
97 if (all_confirmed && !(pcmk_is_set(synapse->flags, pcmk__synapse_confirmed))) {
98 crm_trace("Confirmed synapse %d", synapse->id);
100 }
101}
102
110void
112{
113 for (GList *lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
114 pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
115
116 if (pcmk_any_flags_set(synapse->flags, pcmk__synapse_confirmed|pcmk__synapse_failed)) {
117 continue; // This synapse already completed
118
119 } else if (pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
120 update_synapse_confirmed(synapse, action->id);
121
122 } else if (!(pcmk_is_set(action->flags, pcmk__graph_action_failed)) || (synapse->priority == INFINITY)) {
123 update_synapse_ready(synapse, action->id);
124 }
125 }
126}
127
128
129/*
130 * Functions for executing graph
131 */
132
133/* A transition graph consists of various types of actions. The library caller
134 * registers execution functions for each action type, which will be stored
135 * here.
136 */
137static pcmk__graph_functions_t *graph_fns = NULL;
138
145void
147{
148 crm_debug("Setting custom functions for executing transition graphs");
149 graph_fns = fns;
150
151 CRM_ASSERT(graph_fns != NULL);
152 CRM_ASSERT(graph_fns->rsc != NULL);
153 CRM_ASSERT(graph_fns->cluster != NULL);
154 CRM_ASSERT(graph_fns->pseudo != NULL);
155 CRM_ASSERT(graph_fns->fence != NULL);
156}
157
167static bool
168should_fire_synapse(pcmk__graph_t *graph, pcmk__graph_synapse_t *synapse)
169{
170 GList *lpc = NULL;
171
173 for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
174 pcmk__graph_action_t *prereq = (pcmk__graph_action_t *) lpc->data;
175
176 if (!(pcmk_is_set(prereq->flags, pcmk__graph_action_confirmed))) {
177 crm_trace("Input %d for synapse %d not yet confirmed",
178 prereq->id, synapse->id);
180 break;
181
182 } else if (pcmk_is_set(prereq->flags, pcmk__graph_action_failed) && !(pcmk_is_set(prereq->flags, pcmk__graph_action_can_fail))) {
183 crm_trace("Input %d for synapse %d confirmed but failed",
184 prereq->id, synapse->id);
186 break;
187 }
188 }
189 if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
190 crm_trace("Synapse %d is ready to execute", synapse->id);
191 } else {
192 return false;
193 }
194
195 for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
197
198 if (a->type == pcmk__pseudo_graph_action) {
199 /* None of the below applies to pseudo ops */
200
201 } else if (synapse->priority < graph->abort_priority) {
202 crm_trace("Skipping synapse %d: priority %d is less than "
203 "abort priority %d",
204 synapse->id, synapse->priority, graph->abort_priority);
205 graph->skipped++;
206 return false;
207
208 } else if (graph_fns->allowed && !(graph_fns->allowed(graph, a))) {
209 crm_trace("Deferring synapse %d: not allowed", synapse->id);
210 return false;
211 }
212 }
213
214 return true;
215}
216
226static int
227initiate_action(pcmk__graph_t *graph, pcmk__graph_action_t *action)
228{
229 const char *id = ID(action->xml);
230
231 CRM_CHECK(id != NULL, return EINVAL);
233 return pcmk_rc_already);
234
236 switch (action->type) {
238 crm_trace("Executing pseudo-action %d (%s)", action->id, id);
239 return graph_fns->pseudo(graph, action);
240
242 crm_trace("Executing resource action %d (%s)", action->id, id);
243 return graph_fns->rsc(graph, action);
244
246 if (pcmk__str_eq(crm_element_value(action->xml, XML_LRM_ATTR_TASK),
248 crm_trace("Executing fencing action %d (%s)",
249 action->id, id);
250 return graph_fns->fence(graph, action);
251 }
252 crm_trace("Executing cluster action %d (%s)", action->id, id);
253 return graph_fns->cluster(graph, action);
254
255 default:
256 crm_err("Unsupported graph action type <%s " XML_ATTR_ID "='%s'> "
257 "(bug?)",
258 crm_element_name(action->xml), id);
259 return EINVAL;
260 }
261}
262
272static int
273fire_synapse(pcmk__graph_t *graph, pcmk__graph_synapse_t *synapse)
274{
276 for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
278 int rc = initiate_action(graph, action);
279
280 if (rc != pcmk_rc_ok) {
281 crm_err("Failed initiating <%s " XML_ATTR_ID "=%d> in synapse %d: "
282 "%s",
283 crm_element_name(action->xml), action->id, synapse->id,
284 pcmk_rc_str(rc));
289 return pcmk_rc_error;
290 }
291 }
292 return pcmk_rc_ok;
293}
294
306static int
307pseudo_action_dummy(pcmk__graph_t *graph, pcmk__graph_action_t *action)
308{
309 static int fail = -1;
310
311 if (fail < 0) {
312 long long fail_ll;
313
314 if ((pcmk__scan_ll(getenv("PE_fail"), &fail_ll, 0LL) == pcmk_rc_ok)
315 && (fail_ll > 0LL) && (fail_ll <= INT_MAX)) {
316 fail = (int) fail_ll;
317 } else {
318 fail = 0;
319 }
320 }
321
322 if (action->id == fail) {
323 crm_err("Dummy event handler: pretending action %d failed", action->id);
325 graph->abort_priority = INFINITY;
326 } else {
327 crm_trace("Dummy event handler: action %d initiated", action->id);
328 }
331 return pcmk_rc_ok;
332}
333
334static pcmk__graph_functions_t default_fns = {
335 pseudo_action_dummy,
336 pseudo_action_dummy,
337 pseudo_action_dummy,
338 pseudo_action_dummy
339};
340
351{
352 GList *lpc = NULL;
353 int log_level = LOG_DEBUG;
354 enum pcmk__graph_status pass_result = pcmk__graph_active;
355 const char *status = "In progress";
356
357 if (graph_fns == NULL) {
358 graph_fns = &default_fns;
359 }
360 if (graph == NULL) {
362 }
363
364 graph->fired = 0;
365 graph->pending = 0;
366 graph->skipped = 0;
367 graph->completed = 0;
368 graph->incomplete = 0;
369
370 // Count completed and in-flight synapses
371 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
372 pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
373
375 graph->completed++;
376
377 } else if (!(pcmk_is_set(synapse->flags, pcmk__synapse_failed)) && pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
378 graph->pending++;
379 }
380 }
381 crm_trace("Executing graph %d (%d synapses already completed, %d pending)",
382 graph->id, graph->completed, graph->pending);
383
384 // Execute any synapses that are ready
385 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
386 pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
387
388 if ((graph->batch_limit > 0)
389 && (graph->pending >= graph->batch_limit)) {
390
391 crm_debug("Throttling graph execution: batch limit (%d) reached",
392 graph->batch_limit);
393 break;
394
395 } else if (pcmk_is_set(synapse->flags, pcmk__synapse_failed)) {
396 graph->skipped++;
397 continue;
398
399 } else if (pcmk_any_flags_set(synapse->flags, pcmk__synapse_confirmed|pcmk__synapse_executed)) {
400 continue; // Already handled
401
402 } else if (should_fire_synapse(graph, synapse)) {
403 graph->fired++;
404 if (fire_synapse(graph, synapse) != pcmk_rc_ok) {
405 crm_err("Synapse %d failed to fire", synapse->id);
406 log_level = LOG_ERR;
407 graph->abort_priority = INFINITY;
408 graph->incomplete++;
409 graph->fired--;
410 }
411
412 if (!(pcmk_is_set(synapse->flags, pcmk__synapse_confirmed))) {
413 graph->pending++;
414 }
415
416 } else {
417 crm_trace("Synapse %d cannot fire", synapse->id);
418 graph->incomplete++;
419 }
420 }
421
422 if ((graph->pending == 0) && (graph->fired == 0)) {
423 graph->complete = true;
424
425 if ((graph->incomplete != 0) && (graph->abort_priority <= 0)) {
426 log_level = LOG_WARNING;
427 pass_result = pcmk__graph_terminated;
428 status = "Terminated";
429
430 } else if (graph->skipped != 0) {
431 log_level = LOG_NOTICE;
432 pass_result = pcmk__graph_complete;
433 status = "Stopped";
434
435 } else {
436 log_level = LOG_NOTICE;
437 pass_result = pcmk__graph_complete;
438 status = "Complete";
439 }
440
441 } else if (graph->fired == 0) {
442 pass_result = pcmk__graph_pending;
443 }
444
445 do_crm_log(log_level,
446 "Transition %d (Complete=%d, Pending=%d,"
447 " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s",
448 graph->id, graph->completed, graph->pending, graph->fired,
449 graph->skipped, graph->incomplete, graph->source, status);
450
451 return pass_result;
452}
453
454
455/*
456 * Functions for unpacking transition graph XML into structs
457 */
458
469unpack_action(pcmk__graph_synapse_t *parent, xmlNode *xml_action)
470{
471 enum pcmk__graph_action_type action_type;
473 const char *element = TYPE(xml_action);
474 const char *value = ID(xml_action);
475
476 if (value == NULL) {
477 crm_err("Ignoring transition graph action without id (bug?)");
478 crm_log_xml_trace(xml_action, "invalid");
479 return NULL;
480 }
481
482 if (pcmk__str_eq(element, XML_GRAPH_TAG_RSC_OP, pcmk__str_casei)) {
483 action_type = pcmk__rsc_graph_action;
484
485 } else if (pcmk__str_eq(element, XML_GRAPH_TAG_PSEUDO_EVENT,
487 action_type = pcmk__pseudo_graph_action;
488
489 } else if (pcmk__str_eq(element, XML_GRAPH_TAG_CRM_EVENT,
491 action_type = pcmk__cluster_graph_action;
492
493 } else {
494 crm_err("Ignoring transition graph action of unknown type '%s' (bug?)",
495 element);
496 crm_log_xml_trace(xml_action, "invalid");
497 return NULL;
498 }
499
500 action = calloc(1, sizeof(pcmk__graph_action_t));
501 if (action == NULL) {
502 crm_perror(LOG_CRIT, "Cannot unpack transition graph action");
503 crm_log_xml_trace(xml_action, "lost");
504 return NULL;
505 }
506
507 pcmk__scan_min_int(value, &(action->id), -1);
509 action->xml = copy_xml(xml_action);
510 action->synapse = parent;
511 action->type = action_type;
512 action->params = xml2list(action->xml);
513
514 value = g_hash_table_lookup(action->params, "CRM_meta_timeout");
515 pcmk__scan_min_int(value, &(action->timeout), 0);
516
517 /* Take start-delay into account for the timeout of the action timer */
518 value = g_hash_table_lookup(action->params, "CRM_meta_start_delay");
519 {
520 int start_delay;
521
522 pcmk__scan_min_int(value, &start_delay, 0);
523 action->timeout += start_delay;
524 }
525
526 if (pcmk__guint_from_hash(action->params,
528 &(action->interval_ms)) != pcmk_rc_ok) {
529 action->interval_ms = 0;
530 }
531
532 value = g_hash_table_lookup(action->params, "CRM_meta_can_fail");
533 if (value != NULL) {
534
535 gboolean can_fail = FALSE;
536 crm_str_to_boolean(value, &can_fail);
537 if (can_fail) {
539 } else {
541 }
542
543#ifndef PCMK__COMPAT_2_0
545 crm_warn("Support for the can_fail meta-attribute is deprecated"
546 " and will be removed in a future release");
547 }
548#endif
549 }
550
551 crm_trace("Action %d has timer set to %dms", action->id, action->timeout);
552
553 return action;
554}
555
566unpack_synapse(pcmk__graph_t *new_graph, const xmlNode *xml_synapse)
567{
568 const char *value = NULL;
569 xmlNode *action_set = NULL;
570 pcmk__graph_synapse_t *new_synapse = NULL;
571
572 crm_trace("Unpacking synapse %s", ID(xml_synapse));
573
574 new_synapse = calloc(1, sizeof(pcmk__graph_synapse_t));
575 if (new_synapse == NULL) {
576 return NULL;
577 }
578
579 pcmk__scan_min_int(ID(xml_synapse), &(new_synapse->id), 0);
580
581 value = crm_element_value(xml_synapse, XML_CIB_ATTR_PRIORITY);
582 pcmk__scan_min_int(value, &(new_synapse->priority), 0);
583
584 CRM_CHECK(new_synapse->id >= 0, free(new_synapse);
585 return NULL);
586
587 new_graph->num_synapses++;
588
589 crm_trace("Unpacking synapse %s action sets",
590 crm_element_value(xml_synapse, XML_ATTR_ID));
591
592 for (action_set = first_named_child(xml_synapse, "action_set");
593 action_set != NULL; action_set = crm_next_same_xml(action_set)) {
594
595 for (xmlNode *action = pcmk__xml_first_child(action_set);
596 action != NULL; action = pcmk__xml_next(action)) {
597
598 pcmk__graph_action_t *new_action = unpack_action(new_synapse,
599 action);
600
601 if (new_action == NULL) {
602 continue;
603 }
604
605 crm_trace("Adding action %d to synapse %d",
606 new_action->id, new_synapse->id);
607 new_graph->num_actions++;
608 new_synapse->actions = g_list_append(new_synapse->actions,
609 new_action);
610 }
611 }
612
613 crm_trace("Unpacking synapse %s inputs", ID(xml_synapse));
614
615 for (xmlNode *inputs = first_named_child(xml_synapse, "inputs");
616 inputs != NULL; inputs = crm_next_same_xml(inputs)) {
617
618 for (xmlNode *trigger = first_named_child(inputs, "trigger");
619 trigger != NULL; trigger = crm_next_same_xml(trigger)) {
620
621 for (xmlNode *input = pcmk__xml_first_child(trigger);
622 input != NULL; input = pcmk__xml_next(input)) {
623
624 pcmk__graph_action_t *new_input = unpack_action(new_synapse,
625 input);
626
627 if (new_input == NULL) {
628 continue;
629 }
630
631 crm_trace("Adding input %d to synapse %d",
632 new_input->id, new_synapse->id);
633
634 new_synapse->inputs = g_list_append(new_synapse->inputs,
635 new_input);
636 }
637 }
638 }
639
640 return new_synapse;
641}
642
669pcmk__unpack_graph(const xmlNode *xml_graph, const char *reference)
670{
671 pcmk__graph_t *new_graph = NULL;
672
673 new_graph = calloc(1, sizeof(pcmk__graph_t));
674 if (new_graph == NULL) {
675 return NULL;
676 }
677
678 new_graph->source = strdup((reference == NULL)? "unknown" : reference);
679 if (new_graph->source == NULL) {
680 free(new_graph);
681 return NULL;
682 }
683
684 new_graph->id = -1;
685 new_graph->abort_priority = 0;
686 new_graph->network_delay = 0;
687 new_graph->stonith_timeout = 0;
689
690 // Parse top-level attributes from <transition_graph>
691 if (xml_graph != NULL) {
692 const char *buf = crm_element_value(xml_graph, "transition_id");
693
694 CRM_CHECK(buf != NULL, free(new_graph);
695 return NULL);
696 pcmk__scan_min_int(buf, &(new_graph->id), -1);
697
698 buf = crm_element_value(xml_graph, "cluster-delay");
699 CRM_CHECK(buf != NULL, free(new_graph);
700 return NULL);
701 new_graph->network_delay = crm_parse_interval_spec(buf);
702
703 buf = crm_element_value(xml_graph, "stonith-timeout");
704 if (buf == NULL) {
705 new_graph->stonith_timeout = new_graph->network_delay;
706 } else {
708 }
709
710 // Use 0 (dynamic limit) as default/invalid, -1 (no limit) as minimum
711 buf = crm_element_value(xml_graph, "batch-limit");
712 if ((buf == NULL)
713 || (pcmk__scan_min_int(buf, &(new_graph->batch_limit),
714 -1) != pcmk_rc_ok)) {
715 new_graph->batch_limit = 0;
716 }
717
718 buf = crm_element_value(xml_graph, "migration-limit");
719 pcmk__scan_min_int(buf, &(new_graph->migration_limit), -1);
720
722 crm_element_value(xml_graph, "failed-stop-offset"));
724 crm_element_value(xml_graph, "failed-start-offset"));
725
726 if (crm_element_value_epoch(xml_graph, "recheck-by",
727 &(new_graph->recheck_by)) != pcmk_ok) {
728 new_graph->recheck_by = 0;
729 }
730 }
731
732 // Unpack each child <synapse> element
733 for (const xmlNode *synapse_xml = first_named_child(xml_graph, "synapse");
734 synapse_xml != NULL; synapse_xml = crm_next_same_xml(synapse_xml)) {
735
736 pcmk__graph_synapse_t *new_synapse = unpack_synapse(new_graph,
737 synapse_xml);
738
739 if (new_synapse != NULL) {
740 new_graph->synapses = g_list_append(new_graph->synapses,
741 new_synapse);
742 }
743 }
744
745 crm_debug("Unpacked transition %d from %s: %d actions in %d synapses",
746 new_graph->id, new_graph->source, new_graph->num_actions,
747 new_graph->num_synapses);
748
749 return new_graph;
750}
751
752
753/*
754 * Functions for freeing transition graph objects
755 */
756
763static void
764free_graph_action(gpointer user_data)
765{
766 pcmk__graph_action_t *action = user_data;
767
768 if (action->timer != 0) {
769 crm_warn("Cancelling timer for graph action %d", action->id);
770 g_source_remove(action->timer);
771 }
772 if (action->params != NULL) {
773 g_hash_table_destroy(action->params);
774 }
775 free_xml(action->xml);
776 free(action);
777}
778
785static void
786free_graph_synapse(gpointer user_data)
787{
788 pcmk__graph_synapse_t *synapse = user_data;
789
790 g_list_free_full(synapse->actions, free_graph_action);
791 g_list_free_full(synapse->inputs, free_graph_action);
792 free(synapse);
793}
794
801void
803{
804 if (graph != NULL) {
805 g_list_free_full(graph->synapses, free_graph_synapse);
806 free(graph->source);
807 free(graph->failed_stop_offset);
808 free(graph->failed_start_offset);
809 free(graph);
810 }
811}
812
813
814/*
815 * Other transition graph utilities
816 */
817
831pcmk__event_from_graph_action(const xmlNode *resource,
833 int status, int rc, const char *exit_reason)
834{
835 lrmd_event_data_t *op = NULL;
836 GHashTableIter iter;
837 const char *name = NULL;
838 const char *value = NULL;
839 xmlNode *action_resource = NULL;
840
841 CRM_CHECK(action != NULL, return NULL);
842 CRM_CHECK(action->type == pcmk__rsc_graph_action, return NULL);
843
844 action_resource = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
845 CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "invalid");
846 return NULL);
847
848 op = lrmd_new_event(ID(action_resource),
850 action->interval_ms);
851 lrmd__set_result(op, rc, status, exit_reason);
852 op->t_run = time(NULL);
853 op->t_rcchange = op->t_run;
854 op->params = pcmk__strkey_table(free, free);
855
856 g_hash_table_iter_init(&iter, action->params);
857 while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
858 g_hash_table_insert(op->params, strdup(name), strdup(value));
859 }
860
861 for (xmlNode *xop = pcmk__xml_first_child(resource); xop != NULL;
862 xop = pcmk__xml_next(xop)) {
863 int tmp = 0;
864
866 crm_debug("Got call_id=%d for %s", tmp, ID(resource));
867 if (tmp > op->call_id) {
868 op->call_id = tmp;
869 }
870 }
871
872 op->call_id++;
873 return op;
874}
const char * parent
Definition cib.c:25
const char * name
Definition cib.c:24
char guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
Definition utils.c:271
int crm_str_to_boolean(const char *s, int *ret)
Definition strings.c:427
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:121
A dumping ground.
#define CRM_META
Definition crm.h:78
#define INFINITY
Definition crm.h:99
#define CRM_OP_FENCE
Definition crm.h:144
#define do_crm_log(level, fmt, args...)
Log a message.
Definition logging.h:172
#define crm_warn(fmt, args...)
Definition logging.h:376
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition logging.h:319
#define CRM_CHECK(expr, failure_action)
Definition logging.h:235
#define crm_debug(fmt, args...)
Definition logging.h:380
#define crm_err(fmt, args...)
Definition logging.h:375
#define crm_log_xml_trace(xml, text)
Definition logging.h:389
#define crm_log_xml_warn(xml, text)
Definition logging.h:385
#define crm_trace(fmt, args...)
Definition logging.h:381
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)
#define ID(x)
Definition msg_xml.h:480
#define TYPE(x)
Definition msg_xml.h:481
#define XML_CIB_ATTR_PRIORITY
Definition msg_xml.h:290
#define XML_ATTR_ID
Definition msg_xml.h:147
#define XML_LRM_ATTR_INTERVAL
Definition msg_xml.h:309
#define XML_GRAPH_TAG_CRM_EVENT
Definition msg_xml.h:346
#define XML_LRM_ATTR_TASK
Definition msg_xml.h:315
#define XML_GRAPH_TAG_PSEUDO_EVENT
Definition msg_xml.h:345
#define XML_GRAPH_TAG_RSC_OP
Definition msg_xml.h:344
#define XML_LRM_ATTR_CALLID
Definition msg_xml.h:327
#define XML_CIB_TAG_RESOURCE
Definition msg_xml.h:230
xmlNode * input
GHashTable * xml2list(const xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition nvpair.c:875
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:496
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition nvpair.c:532
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:617
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:488
@ pcmk_rc_ok
Definition results.h:151
@ pcmk_rc_error
Definition results.h:147
@ pcmk_rc_already
Definition results.h:143
#define pcmk_ok
Definition results.h:68
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:611
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition strings.c:97
void pcmk__str_update(char **str, const char *value)
Definition strings.c:1193
@ pcmk__str_casei
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.h:245
unsigned int t_rcchange
Definition lrmd.h:247
void * params
Definition lrmd.h:258
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.
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition xml.c:2521
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition xml.c:2547
void free_xml(xmlNode *child)
Definition xml.c:813
xmlNode * copy_xml(xmlNode *src_node)
Definition xml.c:819