pacemaker  2.1.9-49aab99839
Scalable High-Availability cluster resource manager
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 
32 static void
33 free_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 
54 static void
55 free_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 
70 void
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 
104 static void
105 update_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 
140 static void
141 update_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
162  && !pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
163  crm_trace("Confirmed synapse %d", synapse->id);
165  }
166 }
167 
175 void
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  */
204 static pcmk__graph_functions_t *graph_fns = NULL;
205 
212 void
214 {
215 
216  pcmk__assert((fns != NULL) && (fns->rsc != NULL) && (fns->cluster != NULL)
217  && (fns->pseudo != NULL) && (fns->fence != NULL));
218  crm_debug("Setting custom functions for executing transition graphs");
219  graph_fns = fns;
220 }
221 
231 static bool
232 should_fire_synapse(pcmk__graph_t *graph, pcmk__graph_synapse_t *synapse)
233 {
234  GList *lpc = NULL;
235 
237  for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
238  pcmk__graph_action_t *prereq = (pcmk__graph_action_t *) lpc->data;
239 
241  crm_trace("Input %d for synapse %d not yet confirmed",
242  prereq->id, synapse->id);
244  break;
245 
246  } else if (pcmk_is_set(prereq->flags, pcmk__graph_action_failed)
247  && !pcmk_is_set(prereq->flags,
249  crm_trace("Input %d for synapse %d confirmed but failed",
250  prereq->id, synapse->id);
252  break;
253  }
254  }
255  if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
256  crm_trace("Synapse %d is ready to execute", synapse->id);
257  } else {
258  return false;
259  }
260 
261  for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
262  pcmk__graph_action_t *a = (pcmk__graph_action_t *) lpc->data;
263 
264  if (a->type == pcmk__pseudo_graph_action) {
265  /* None of the below applies to pseudo ops */
266 
267  } else if (synapse->priority < graph->abort_priority) {
268  crm_trace("Skipping synapse %d: priority %d is less than "
269  "abort priority %d",
270  synapse->id, synapse->priority, graph->abort_priority);
271  graph->skipped++;
272  return false;
273 
274  } else if (graph_fns->allowed && !(graph_fns->allowed(graph, a))) {
275  crm_trace("Deferring synapse %d: not allowed", synapse->id);
276  return false;
277  }
278  }
279 
280  return true;
281 }
282 
292 static int
293 initiate_action(pcmk__graph_t *graph, pcmk__graph_action_t *action)
294 {
295  const char *id = pcmk__xe_id(action->xml);
296 
297  CRM_CHECK(id != NULL, return EINVAL);
299  return pcmk_rc_already);
300 
302  switch (action->type) {
304  crm_trace("Executing pseudo-action %d (%s)", action->id, id);
305  return graph_fns->pseudo(graph, action);
306 
308  crm_trace("Executing resource action %d (%s)", action->id, id);
309  return graph_fns->rsc(graph, action);
310 
312  if (pcmk__str_eq(crm_element_value(action->xml, PCMK_XA_OPERATION),
314  crm_trace("Executing fencing action %d (%s)",
315  action->id, id);
316  return graph_fns->fence(graph, action);
317  }
318  crm_trace("Executing cluster action %d (%s)", action->id, id);
319  return graph_fns->cluster(graph, action);
320 
321  default:
322  crm_err("Unsupported graph action type <%s " PCMK_XA_ID "='%s'> "
323  "(bug?)",
324  action->xml->name, id);
325  return EINVAL;
326  }
327 }
328 
338 static int
339 fire_synapse(pcmk__graph_t *graph, pcmk__graph_synapse_t *synapse)
340 {
342  for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
344  int rc = initiate_action(graph, action);
345 
346  if (rc != pcmk_rc_ok) {
347  crm_err("Failed initiating <%s " PCMK_XA_ID "=%d> in synapse %d: "
348  "%s",
349  action->xml->name, action->id, synapse->id,
350  pcmk_rc_str(rc));
355  return pcmk_rc_error;
356  }
357  }
358  return pcmk_rc_ok;
359 }
360 
372 static int
373 pseudo_action_dummy(pcmk__graph_t *graph, pcmk__graph_action_t *action)
374 {
375  static int fail = -1;
376 
377  if (fail < 0) {
378  long long fail_ll;
379 
380  if ((pcmk__scan_ll(getenv("PE_fail"), &fail_ll, 0LL) == pcmk_rc_ok)
381  && (fail_ll > 0LL) && (fail_ll <= INT_MAX)) {
382  fail = (int) fail_ll;
383  } else {
384  fail = 0;
385  }
386  }
387 
388  if (action->id == fail) {
389  crm_err("Dummy event handler: pretending action %d failed", action->id);
392  } else {
393  crm_trace("Dummy event handler: action %d initiated", action->id);
394  }
396  pcmk__update_graph(graph, action);
397  return pcmk_rc_ok;
398 }
399 
400 static pcmk__graph_functions_t default_fns = {
401  pseudo_action_dummy,
402  pseudo_action_dummy,
403  pseudo_action_dummy,
404  pseudo_action_dummy
405 };
406 
417 {
418  GList *lpc = NULL;
419  int log_level = LOG_DEBUG;
420  enum pcmk__graph_status pass_result = pcmk__graph_active;
421  const char *status = "In progress";
422 
423  if (graph_fns == NULL) {
424  graph_fns = &default_fns;
425  }
426  if (graph == NULL) {
427  return pcmk__graph_complete;
428  }
429 
430  graph->fired = 0;
431  graph->pending = 0;
432  graph->skipped = 0;
433  graph->completed = 0;
434  graph->incomplete = 0;
435 
436  // Count completed and in-flight synapses
437  for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
438  pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
439 
440  if (pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
441  graph->completed++;
442 
443  } else if (!pcmk_is_set(synapse->flags, pcmk__synapse_failed)
444  && pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
445  graph->pending++;
446  }
447  }
448  crm_trace("Executing graph %d (%d synapses already completed, %d pending)",
449  graph->id, graph->completed, graph->pending);
450 
451  // Execute any synapses that are ready
452  for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
453  pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
454 
455  if ((graph->batch_limit > 0)
456  && (graph->pending >= graph->batch_limit)) {
457 
458  crm_debug("Throttling graph execution: batch limit (%d) reached",
459  graph->batch_limit);
460  break;
461 
462  } else if (pcmk_is_set(synapse->flags, pcmk__synapse_failed)) {
463  graph->skipped++;
464  continue;
465 
466  } else if (pcmk_any_flags_set(synapse->flags,
469  continue; // Already handled
470 
471  } else if (should_fire_synapse(graph, synapse)) {
472  graph->fired++;
473  if (fire_synapse(graph, synapse) != pcmk_rc_ok) {
474  crm_err("Synapse %d failed to fire", synapse->id);
475  log_level = LOG_ERR;
477  graph->incomplete++;
478  graph->fired--;
479  }
480 
481  if (!(pcmk_is_set(synapse->flags, pcmk__synapse_confirmed))) {
482  graph->pending++;
483  }
484 
485  } else {
486  crm_trace("Synapse %d cannot fire", synapse->id);
487  graph->incomplete++;
488  }
489  }
490 
491  if ((graph->pending == 0) && (graph->fired == 0)) {
492  graph->complete = true;
493 
494  if ((graph->incomplete != 0) && (graph->abort_priority <= 0)) {
495  log_level = LOG_WARNING;
496  pass_result = pcmk__graph_terminated;
497  status = "Terminated";
498 
499  } else if (graph->skipped != 0) {
500  log_level = LOG_NOTICE;
501  pass_result = pcmk__graph_complete;
502  status = "Stopped";
503 
504  } else {
505  log_level = LOG_NOTICE;
506  pass_result = pcmk__graph_complete;
507  status = "Complete";
508  }
509 
510  } else if (graph->fired == 0) {
511  pass_result = pcmk__graph_pending;
512  }
513 
514  do_crm_log(log_level,
515  "Transition %d (Complete=%d, Pending=%d,"
516  " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s",
517  graph->id, graph->completed, graph->pending, graph->fired,
518  graph->skipped, graph->incomplete, graph->source, status);
519 
520  return pass_result;
521 }
522 
523 
524 /*
525  * Functions for unpacking transition graph XML into structs
526  */
527 
537 static pcmk__graph_action_t *
538 unpack_action(pcmk__graph_synapse_t *parent, xmlNode *xml_action)
539 {
540  enum pcmk__graph_action_type action_type;
542  const char *value = pcmk__xe_id(xml_action);
543 
544  if (value == NULL) {
545  crm_err("Ignoring transition graph action without " PCMK_XA_ID
546  " (bug?)");
547  crm_log_xml_trace(xml_action, "invalid");
548  return NULL;
549  }
550 
551  if (pcmk__xe_is(xml_action, PCMK__XE_RSC_OP)) {
552  action_type = pcmk__rsc_graph_action;
553 
554  } else if (pcmk__xe_is(xml_action, PCMK__XE_PSEUDO_EVENT)) {
555  action_type = pcmk__pseudo_graph_action;
556 
557  } else if (pcmk__xe_is(xml_action, PCMK__XE_CRM_EVENT)) {
558  action_type = pcmk__cluster_graph_action;
559 
560  } else {
561  crm_err("Ignoring transition graph action of unknown type '%s' (bug?)",
562  xml_action->name);
563  crm_log_xml_trace(xml_action, "invalid");
564  return NULL;
565  }
566 
567  action = calloc(1, sizeof(pcmk__graph_action_t));
568  if (action == NULL) {
569  crm_perror(LOG_CRIT, "Cannot unpack transition graph action");
570  crm_log_xml_trace(xml_action, "lost");
571  return NULL;
572  }
573 
574  pcmk__scan_min_int(value, &(action->id), -1);
576  action->xml = pcmk__xml_copy(NULL, xml_action);
577  action->synapse = parent;
578  action->type = action_type;
579  action->params = xml2list(action->xml);
580 
581  value = crm_meta_value(action->params, PCMK_META_TIMEOUT);
582  pcmk__scan_min_int(value, &(action->timeout), 0);
583 
584  /* Take PCMK_META_START_DELAY into account for the timeout of the action
585  * timer
586  */
587  value = crm_meta_value(action->params, PCMK_META_START_DELAY);
588  {
589  int start_delay;
590 
591  pcmk__scan_min_int(value, &start_delay, 0);
592  action->timeout += start_delay;
593  }
594 
596  0, &(action->interval_ms)) != pcmk_rc_ok) {
597  action->interval_ms = 0;
598  }
599 
600  value = crm_meta_value(action->params, PCMK__META_CAN_FAIL);
601  if (value != NULL) {
602  int can_fail = 0;
603 
604  if ((crm_str_to_boolean(value, &can_fail) > 0) && (can_fail > 0)) {
606  } else {
608  }
609 
611  crm_warn("Support for the " PCMK__META_CAN_FAIL " meta-attribute "
612  "is deprecated and will be removed in a future release");
613  }
614  }
615 
616  crm_trace("Action %d has timer set to %dms", action->id, action->timeout);
617 
618  return action;
619 }
620 
630 static pcmk__graph_synapse_t *
631 unpack_synapse(pcmk__graph_t *new_graph, const xmlNode *xml_synapse)
632 {
633  const char *value = NULL;
634  xmlNode *action_set = NULL;
635  pcmk__graph_synapse_t *new_synapse = NULL;
636 
637  crm_trace("Unpacking synapse %s", pcmk__xe_id(xml_synapse));
638 
639  new_synapse = calloc(1, sizeof(pcmk__graph_synapse_t));
640  if (new_synapse == NULL) {
641  return NULL;
642  }
643 
644  pcmk__scan_min_int(pcmk__xe_id(xml_synapse), &(new_synapse->id), 0);
645 
646  value = crm_element_value(xml_synapse, PCMK__XA_PRIORITY);
647  pcmk__scan_min_int(value, &(new_synapse->priority), 0);
648 
649  CRM_CHECK(new_synapse->id >= 0,
650  free_graph_synapse((gpointer) new_synapse); return NULL);
651 
652  new_graph->num_synapses++;
653 
654  crm_trace("Unpacking synapse %s action sets",
655  crm_element_value(xml_synapse, PCMK_XA_ID));
656 
657  for (action_set = pcmk__xe_first_child(xml_synapse, "action_set", NULL,
658  NULL);
659  action_set != NULL; action_set = pcmk__xe_next_same(action_set)) {
660 
661  for (xmlNode *action = pcmk__xe_first_child(action_set, NULL, NULL,
662  NULL);
663  action != NULL; action = pcmk__xe_next(action)) {
664 
665  pcmk__graph_action_t *new_action = unpack_action(new_synapse,
666  action);
667 
668  if (new_action == NULL) {
669  continue;
670  }
671 
672  crm_trace("Adding action %d to synapse %d",
673  new_action->id, new_synapse->id);
674  new_graph->num_actions++;
675  new_synapse->actions = g_list_append(new_synapse->actions,
676  new_action);
677  }
678  }
679 
680  crm_trace("Unpacking synapse %s inputs", pcmk__xe_id(xml_synapse));
681 
682  for (xmlNode *inputs = pcmk__xe_first_child(xml_synapse, "inputs", NULL,
683  NULL);
684  inputs != NULL; inputs = pcmk__xe_next_same(inputs)) {
685 
686  for (xmlNode *trigger = pcmk__xe_first_child(inputs, "trigger", NULL,
687  NULL);
688  trigger != NULL; trigger = pcmk__xe_next_same(trigger)) {
689 
690  for (xmlNode *input = pcmk__xe_first_child(trigger, NULL, NULL,
691  NULL);
692  input != NULL; input = pcmk__xe_next(input)) {
693 
694  pcmk__graph_action_t *new_input = unpack_action(new_synapse,
695  input);
696 
697  if (new_input == NULL) {
698  continue;
699  }
700 
701  crm_trace("Adding input %d to synapse %d",
702  new_input->id, new_synapse->id);
703 
704  new_synapse->inputs = g_list_append(new_synapse->inputs,
705  new_input);
706  }
707  }
708  }
709 
710  return new_synapse;
711 }
712 
739 pcmk__unpack_graph(const xmlNode *xml_graph, const char *reference)
740 {
741  pcmk__graph_t *new_graph = NULL;
742 
743  new_graph = calloc(1, sizeof(pcmk__graph_t));
744  if (new_graph == NULL) {
745  return NULL;
746  }
747 
748  new_graph->source = strdup(pcmk__s(reference, "unknown"));
749  if (new_graph->source == NULL) {
750  pcmk__free_graph(new_graph);
751  return NULL;
752  }
753 
754  new_graph->completion_action = pcmk__graph_done;
755 
756  // Parse top-level attributes from PCMK__XE_TRANSITION_GRAPH
757  if (xml_graph != NULL) {
758  const char *buf = crm_element_value(xml_graph, "transition_id");
759 
760  CRM_CHECK(buf != NULL,
761  pcmk__free_graph(new_graph); return NULL);
762  pcmk__scan_min_int(buf, &(new_graph->id), 1);
763 
764  buf = crm_element_value(xml_graph, PCMK_OPT_CLUSTER_DELAY);
765  CRM_CHECK(buf != NULL,
766  pcmk__free_graph(new_graph); return NULL);
767  pcmk_parse_interval_spec(buf, &(new_graph->network_delay));
768 
770  if (buf == NULL) {
771  new_graph->stonith_timeout = new_graph->network_delay;
772  } else {
773  pcmk_parse_interval_spec(buf, &(new_graph->stonith_timeout));
774  }
775 
776  // Use 0 (dynamic limit) as default/invalid, -1 (no limit) as minimum
777  buf = crm_element_value(xml_graph, PCMK_OPT_BATCH_LIMIT);
778  if ((buf == NULL)
779  || (pcmk__scan_min_int(buf, &(new_graph->batch_limit),
780  -1) != pcmk_rc_ok)) {
781  new_graph->batch_limit = 0;
782  }
783 
785  pcmk__scan_min_int(buf, &(new_graph->migration_limit), -1);
786 
787  new_graph->failed_stop_offset =
788  crm_element_value_copy(xml_graph, "failed-stop-offset");
789  new_graph->failed_start_offset =
790  crm_element_value_copy(xml_graph, "failed-start-offset");
791 
792  if (crm_element_value_epoch(xml_graph, "recheck-by",
793  &(new_graph->recheck_by)) != pcmk_ok) {
794  new_graph->recheck_by = 0;
795  }
796  }
797 
798  // Unpack each child <synapse> element
799  for (const xmlNode *synapse_xml = pcmk__xe_first_child(xml_graph,
800  "synapse", NULL,
801  NULL);
802  synapse_xml != NULL; synapse_xml = pcmk__xe_next_same(synapse_xml)) {
803 
804  pcmk__graph_synapse_t *new_synapse = unpack_synapse(new_graph,
805  synapse_xml);
806 
807  if (new_synapse != NULL) {
808  new_graph->synapses = g_list_append(new_graph->synapses,
809  new_synapse);
810  }
811  }
812 
813  crm_debug("Unpacked transition %d from %s: %d actions in %d synapses",
814  new_graph->id, new_graph->source, new_graph->num_actions,
815  new_graph->num_synapses);
816 
817  return new_graph;
818 }
819 
820 
821 /*
822  * Other transition graph utilities
823  */
824 
838 pcmk__event_from_graph_action(const xmlNode *resource,
840  int status, int rc, const char *exit_reason)
841 {
842  lrmd_event_data_t *op = NULL;
843  GHashTableIter iter;
844  const char *name = NULL;
845  const char *value = NULL;
846  xmlNode *action_resource = NULL;
847 
848  CRM_CHECK(action != NULL, return NULL);
849  CRM_CHECK(action->type == pcmk__rsc_graph_action, return NULL);
850 
851  action_resource = pcmk__xe_first_child(action->xml, PCMK_XE_PRIMITIVE, NULL,
852  NULL);
853  CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "invalid");
854  return NULL);
855 
856  op = lrmd_new_event(pcmk__xe_id(action_resource),
858  action->interval_ms);
859  lrmd__set_result(op, rc, status, exit_reason);
860  // coverity[store_truncates_time_t]
861  op->t_run = time(NULL);
862  op->t_rcchange = op->t_run;
863  op->params = pcmk__strkey_table(free, free);
864 
865  g_hash_table_iter_init(&iter, action->params);
866  while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
867  pcmk__insert_dup(op->params, name, value);
868  }
869 
870  for (xmlNode *xop = pcmk__xe_first_child(resource, NULL, NULL, NULL);
871  xop != NULL; xop = pcmk__xe_next(xop)) {
872 
873  int tmp = 0;
874 
876  crm_debug("Got call_id=%d for %s", tmp, pcmk__xe_id(resource));
877  if (tmp > op->call_id) {
878  op->call_id = tmp;
879  }
880  }
881 
882  op->call_id++;
883  return op;
884 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:245
#define PCMK__XA_PRIORITY
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition: xml.c:974
A dumping ground.
#define pcmk__set_synapse_flags(synapse, flags_to_set)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition: strings.c:126
const char * name
Definition: cib.c:26
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)
#define PCMK_XE_PRIMITIVE
Definition: xml_names.h:164
void pcmk__free_graph(pcmk__graph_t *graph)
char * failed_start_offset
Failcount after one failed start action.
pcmk__graph_action_type
#define PCMK__XE_PSEUDO_EVENT
unsigned int t_rcchange
Definition: lrmd_events.h:75
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:503
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:494
enum pcmk__graph_action_type type
int(* pseudo)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define PCMK_XA_OPERATION
Definition: xml_names.h:349
const char * action
Definition: pcmk_fence.c:30
int(* fence)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
void pcmk__update_graph(pcmk__graph_t *graph, const pcmk__graph_action_t *action)
char int pcmk_parse_interval_spec(const char *input, guint *result_ms)
Parse milliseconds from a Pacemaker interval specification.
Definition: strings.c:462
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:96
#define crm_warn(fmt, args...)
Definition: logging.h:394
GHashTable * xml2list(const xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:943
#define PCMK_OPT_BATCH_LIMIT
Definition: options.h:27
int pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val, guint *result)
Definition: strings.c:313
char * failed_stop_offset
Failcount after one failed stop action.
#define crm_debug(fmt, args...)
Definition: logging.h:402
enum pcmk__graph_next completion_action
pcmk__graph_status
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: nvpair.c:758
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:458
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:481
#define PCMK_META_START_DELAY
Definition: options.h:112
#define crm_trace(fmt, args...)
Definition: logging.h:404
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:181
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:94
time_t recheck_by
Time (from epoch) by which the controller should re-run the scheduler.
pcmk__graph_t * pcmk__unpack_graph(const xmlNode *xml_graph, const char *reference)
Wrappers for and extensions to libxml2.
enum pcmk__graph_status pcmk__execute_graph(pcmk__graph_t *graph)
#define crm_log_xml_warn(xml, text)
Definition: logging.h:408
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:651
#define PCMK_ACTION_STONITH
Definition: actions.h:74
#define PCMK_OPT_CLUSTER_DELAY
Definition: options.h:28
#define PCMK__XE_RSC_OP
#define PCMK_XA_ID
Definition: xml_names.h:301
#define pcmk__clear_graph_action_flags(action, flags_to_clear)
#define pcmk__clear_synapse_flags(synapse, flags_to_clear)
void free_xml(xmlNode *child)
Definition: xml.c:958
bool(* allowed)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
void pcmk__set_graph_functions(pcmk__graph_functions_t *fns)
#define PCMK_META_TIMEOUT
Definition: options.h:114
unsigned int t_run
Definition: lrmd_events.h:72
#define pcmk__assert(expr)
#define PCMK_OPT_STONITH_TIMEOUT
Definition: options.h:67
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:508
#define PCMK_META_INTERVAL
Definition: options.h:91
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:695
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:331
int(* rsc)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define PCMK__XE_CRM_EVENT
#define CRM_META
Definition: crm.h:81
#define crm_err(fmt, args...)
Definition: logging.h:391
#define pcmk__set_graph_action_flags(action, flags_to_set)
void lrmd__set_result(lrmd_event_data_t *event, enum ocf_exitcode rc, int op_status, const char *exit_reason)
Definition: lrmd_client.c:2667
xmlNode * input
#define PCMK_OPT_MIGRATION_LIMIT
Definition: options.h:45
#define pcmk_ok
Definition: results.h:65
#define PCMK__XA_CALL_ID
#define PCMK__META_CAN_FAIL
int(* cluster)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define crm_log_xml_trace(xml, text)
Definition: logging.h:412
const char * parent
Definition: cib.c:27
const char * crm_meta_value(GHashTable *hash, const char *field)
Get the value of a meta-attribute.
Definition: nvpair.c:1071
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.
Definition: lrmd_client.c:201
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition: xml.c:2130
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition: strings.c:713
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:24