pacemaker  3.0.0-d8340737c4
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  pcmk__xml_free(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  crm_trace("Input %d for synapse %d confirmed but failed",
248  prereq->id, synapse->id);
250  break;
251  }
252  }
253  if (pcmk_is_set(synapse->flags, pcmk__synapse_ready)) {
254  crm_trace("Synapse %d is ready to execute", synapse->id);
255  } else {
256  return false;
257  }
258 
259  for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
260  pcmk__graph_action_t *a = (pcmk__graph_action_t *) lpc->data;
261 
262  if (a->type == pcmk__pseudo_graph_action) {
263  /* None of the below applies to pseudo ops */
264 
265  } else if (synapse->priority < graph->abort_priority) {
266  crm_trace("Skipping synapse %d: priority %d is less than "
267  "abort priority %d",
268  synapse->id, synapse->priority, graph->abort_priority);
269  graph->skipped++;
270  return false;
271 
272  } else if (graph_fns->allowed && !(graph_fns->allowed(graph, a))) {
273  crm_trace("Deferring synapse %d: not allowed", synapse->id);
274  return false;
275  }
276  }
277 
278  return true;
279 }
280 
290 static int
291 initiate_action(pcmk__graph_t *graph, pcmk__graph_action_t *action)
292 {
293  const char *id = pcmk__xe_id(action->xml);
294 
295  CRM_CHECK(id != NULL, return EINVAL);
297  return pcmk_rc_already);
298 
300  switch (action->type) {
302  crm_trace("Executing pseudo-action %d (%s)", action->id, id);
303  return graph_fns->pseudo(graph, action);
304 
306  crm_trace("Executing resource action %d (%s)", action->id, id);
307  return graph_fns->rsc(graph, action);
308 
310  if (pcmk__str_eq(crm_element_value(action->xml, PCMK_XA_OPERATION),
312  crm_trace("Executing fencing action %d (%s)",
313  action->id, id);
314  return graph_fns->fence(graph, action);
315  }
316  crm_trace("Executing cluster action %d (%s)", action->id, id);
317  return graph_fns->cluster(graph, action);
318 
319  default:
320  crm_err("Unsupported graph action type <%s " PCMK_XA_ID "='%s'> "
321  "(bug?)",
322  action->xml->name, id);
323  return EINVAL;
324  }
325 }
326 
336 static int
337 fire_synapse(pcmk__graph_t *graph, pcmk__graph_synapse_t *synapse)
338 {
340  for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
342  int rc = initiate_action(graph, action);
343 
344  if (rc != pcmk_rc_ok) {
345  crm_err("Failed initiating <%s " PCMK_XA_ID "=%d> in synapse %d: "
346  "%s",
347  action->xml->name, action->id, synapse->id,
348  pcmk_rc_str(rc));
353  return pcmk_rc_error;
354  }
355  }
356  return pcmk_rc_ok;
357 }
358 
370 static int
371 pseudo_action_dummy(pcmk__graph_t *graph, pcmk__graph_action_t *action)
372 {
373  static int fail = -1;
374 
375  if (fail < 0) {
376  long long fail_ll;
377 
378  if ((pcmk__scan_ll(getenv("PE_fail"), &fail_ll, 0LL) == pcmk_rc_ok)
379  && (fail_ll > 0LL) && (fail_ll <= INT_MAX)) {
380  fail = (int) fail_ll;
381  } else {
382  fail = 0;
383  }
384  }
385 
386  if (action->id == fail) {
387  crm_err("Dummy event handler: pretending action %d failed", action->id);
390  } else {
391  crm_trace("Dummy event handler: action %d initiated", action->id);
392  }
394  pcmk__update_graph(graph, action);
395  return pcmk_rc_ok;
396 }
397 
398 static pcmk__graph_functions_t default_fns = {
399  pseudo_action_dummy,
400  pseudo_action_dummy,
401  pseudo_action_dummy,
402  pseudo_action_dummy
403 };
404 
415 {
416  GList *lpc = NULL;
417  int log_level = LOG_DEBUG;
418  enum pcmk__graph_status pass_result = pcmk__graph_active;
419  const char *status = "In progress";
420 
421  if (graph_fns == NULL) {
422  graph_fns = &default_fns;
423  }
424  if (graph == NULL) {
425  return pcmk__graph_complete;
426  }
427 
428  graph->fired = 0;
429  graph->pending = 0;
430  graph->skipped = 0;
431  graph->completed = 0;
432  graph->incomplete = 0;
433 
434  // Count completed and in-flight synapses
435  for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
436  pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
437 
438  if (pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
439  graph->completed++;
440 
441  } else if (!pcmk_is_set(synapse->flags, pcmk__synapse_failed)
442  && pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
443  graph->pending++;
444  }
445  }
446  crm_trace("Executing graph %d (%d synapses already completed, %d pending)",
447  graph->id, graph->completed, graph->pending);
448 
449  // Execute any synapses that are ready
450  for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
451  pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
452 
453  if ((graph->batch_limit > 0)
454  && (graph->pending >= graph->batch_limit)) {
455 
456  crm_debug("Throttling graph execution: batch limit (%d) reached",
457  graph->batch_limit);
458  break;
459 
460  } else if (pcmk_is_set(synapse->flags, pcmk__synapse_failed)) {
461  graph->skipped++;
462  continue;
463 
464  } else if (pcmk_any_flags_set(synapse->flags,
467  continue; // Already handled
468 
469  } else if (should_fire_synapse(graph, synapse)) {
470  graph->fired++;
471  if (fire_synapse(graph, synapse) != pcmk_rc_ok) {
472  crm_err("Synapse %d failed to fire", synapse->id);
473  log_level = LOG_ERR;
475  graph->incomplete++;
476  graph->fired--;
477  }
478 
479  if (!(pcmk_is_set(synapse->flags, pcmk__synapse_confirmed))) {
480  graph->pending++;
481  }
482 
483  } else {
484  crm_trace("Synapse %d cannot fire", synapse->id);
485  graph->incomplete++;
486  }
487  }
488 
489  if ((graph->pending == 0) && (graph->fired == 0)) {
490  graph->complete = true;
491 
492  if ((graph->incomplete != 0) && (graph->abort_priority <= 0)) {
493  log_level = LOG_WARNING;
494  pass_result = pcmk__graph_terminated;
495  status = "Terminated";
496 
497  } else if (graph->skipped != 0) {
498  log_level = LOG_NOTICE;
499  pass_result = pcmk__graph_complete;
500  status = "Stopped";
501 
502  } else {
503  log_level = LOG_NOTICE;
504  pass_result = pcmk__graph_complete;
505  status = "Complete";
506  }
507 
508  } else if (graph->fired == 0) {
509  pass_result = pcmk__graph_pending;
510  }
511 
512  do_crm_log(log_level,
513  "Transition %d (Complete=%d, Pending=%d,"
514  " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s",
515  graph->id, graph->completed, graph->pending, graph->fired,
516  graph->skipped, graph->incomplete, graph->source, status);
517 
518  return pass_result;
519 }
520 
521 
522 /*
523  * Functions for unpacking transition graph XML into structs
524  */
525 
535 static pcmk__graph_action_t *
536 unpack_action(pcmk__graph_synapse_t *parent, xmlNode *xml_action)
537 {
538  enum pcmk__graph_action_type action_type;
540  const char *value = pcmk__xe_id(xml_action);
541 
542  if (value == NULL) {
543  crm_err("Ignoring transition graph action without " PCMK_XA_ID
544  " (bug?)");
545  crm_log_xml_trace(xml_action, "invalid");
546  return NULL;
547  }
548 
549  if (pcmk__xe_is(xml_action, PCMK__XE_RSC_OP)) {
550  action_type = pcmk__rsc_graph_action;
551 
552  } else if (pcmk__xe_is(xml_action, PCMK__XE_PSEUDO_EVENT)) {
553  action_type = pcmk__pseudo_graph_action;
554 
555  } else if (pcmk__xe_is(xml_action, PCMK__XE_CRM_EVENT)) {
556  action_type = pcmk__cluster_graph_action;
557 
558  } else {
559  crm_err("Ignoring transition graph action of unknown type '%s' (bug?)",
560  xml_action->name);
561  crm_log_xml_trace(xml_action, "invalid");
562  return NULL;
563  }
564 
565  action = calloc(1, sizeof(pcmk__graph_action_t));
566  if (action == NULL) {
567  crm_perror(LOG_CRIT, "Cannot unpack transition graph action");
568  crm_log_xml_trace(xml_action, "lost");
569  return NULL;
570  }
571 
572  pcmk__scan_min_int(value, &(action->id), -1);
574  action->xml = pcmk__xml_copy(NULL, xml_action);
575  action->synapse = parent;
576  action->type = action_type;
577  action->params = xml2list(action->xml);
578 
579  value = crm_meta_value(action->params, PCMK_META_TIMEOUT);
580  pcmk__scan_min_int(value, &(action->timeout), 0);
581 
582  /* Take PCMK_META_START_DELAY into account for the timeout of the action
583  * timer
584  */
585  value = crm_meta_value(action->params, PCMK_META_START_DELAY);
586  {
587  int start_delay;
588 
589  pcmk__scan_min_int(value, &start_delay, 0);
590  action->timeout += start_delay;
591  }
592 
594  0, &(action->interval_ms)) != pcmk_rc_ok) {
595  action->interval_ms = 0;
596  }
597 
598  crm_trace("Action %d has timer set to %dms", action->id, action->timeout);
599 
600  return action;
601 }
602 
612 static pcmk__graph_synapse_t *
613 unpack_synapse(pcmk__graph_t *new_graph, const xmlNode *xml_synapse)
614 {
615  const char *value = NULL;
616  xmlNode *action_set = NULL;
617  pcmk__graph_synapse_t *new_synapse = NULL;
618 
619  crm_trace("Unpacking synapse %s", pcmk__xe_id(xml_synapse));
620 
621  new_synapse = calloc(1, sizeof(pcmk__graph_synapse_t));
622  if (new_synapse == NULL) {
623  return NULL;
624  }
625 
626  pcmk__scan_min_int(pcmk__xe_id(xml_synapse), &(new_synapse->id), 0);
627 
628  value = crm_element_value(xml_synapse, PCMK__XA_PRIORITY);
629  pcmk__scan_min_int(value, &(new_synapse->priority), 0);
630 
631  CRM_CHECK(new_synapse->id >= 0,
632  free_graph_synapse((gpointer) new_synapse); return NULL);
633 
634  new_graph->num_synapses++;
635 
636  crm_trace("Unpacking synapse %s action sets",
637  crm_element_value(xml_synapse, PCMK_XA_ID));
638 
639  for (action_set = pcmk__xe_first_child(xml_synapse, PCMK__XE_ACTION_SET,
640  NULL, NULL);
641  action_set != NULL;
642  action_set = pcmk__xe_next(action_set, PCMK__XE_ACTION_SET)) {
643 
644  for (xmlNode *action = pcmk__xe_first_child(action_set, NULL, NULL,
645  NULL);
646  action != NULL; action = pcmk__xe_next(action, NULL)) {
647 
648  pcmk__graph_action_t *new_action = unpack_action(new_synapse,
649  action);
650 
651  if (new_action == NULL) {
652  continue;
653  }
654 
655  crm_trace("Adding action %d to synapse %d",
656  new_action->id, new_synapse->id);
657  new_graph->num_actions++;
658  new_synapse->actions = g_list_append(new_synapse->actions,
659  new_action);
660  }
661  }
662 
663  crm_trace("Unpacking synapse %s inputs", pcmk__xe_id(xml_synapse));
664 
665  for (xmlNode *inputs = pcmk__xe_first_child(xml_synapse, PCMK__XE_INPUTS,
666  NULL, NULL);
667  inputs != NULL; inputs = pcmk__xe_next(inputs, PCMK__XE_INPUTS)) {
668 
669  for (xmlNode *trigger = pcmk__xe_first_child(inputs, PCMK__XE_TRIGGER,
670  NULL, NULL);
671  trigger != NULL;
672  trigger = pcmk__xe_next(trigger, PCMK__XE_TRIGGER)) {
673 
674  for (xmlNode *input = pcmk__xe_first_child(trigger, NULL, NULL,
675  NULL);
676  input != NULL; input = pcmk__xe_next(input, NULL)) {
677 
678  pcmk__graph_action_t *new_input = unpack_action(new_synapse,
679  input);
680 
681  if (new_input == NULL) {
682  continue;
683  }
684 
685  crm_trace("Adding input %d to synapse %d",
686  new_input->id, new_synapse->id);
687 
688  new_synapse->inputs = g_list_append(new_synapse->inputs,
689  new_input);
690  }
691  }
692  }
693 
694  return new_synapse;
695 }
696 
723 pcmk__unpack_graph(const xmlNode *xml_graph, const char *reference)
724 {
725  pcmk__graph_t *new_graph = NULL;
726 
727  new_graph = calloc(1, sizeof(pcmk__graph_t));
728  if (new_graph == NULL) {
729  return NULL;
730  }
731 
732  new_graph->source = strdup(pcmk__s(reference, "unknown"));
733  if (new_graph->source == NULL) {
734  pcmk__free_graph(new_graph);
735  return NULL;
736  }
737 
738  new_graph->completion_action = pcmk__graph_done;
739 
740  // Parse top-level attributes from PCMK__XE_TRANSITION_GRAPH
741  if (xml_graph != NULL) {
742  const char *buf = crm_element_value(xml_graph, "transition_id");
743 
744  CRM_CHECK(buf != NULL,
745  pcmk__free_graph(new_graph); return NULL);
746  pcmk__scan_min_int(buf, &(new_graph->id), 1);
747 
748  buf = crm_element_value(xml_graph, PCMK_OPT_CLUSTER_DELAY);
749  CRM_CHECK(buf != NULL,
750  pcmk__free_graph(new_graph); return NULL);
751  pcmk_parse_interval_spec(buf, &(new_graph->network_delay));
752 
754  if (buf == NULL) {
755  new_graph->stonith_timeout = new_graph->network_delay;
756  } else {
757  pcmk_parse_interval_spec(buf, &(new_graph->stonith_timeout));
758  }
759 
760  // Use 0 (dynamic limit) as default/invalid, -1 (no limit) as minimum
761  buf = crm_element_value(xml_graph, PCMK_OPT_BATCH_LIMIT);
762  if ((buf == NULL)
763  || (pcmk__scan_min_int(buf, &(new_graph->batch_limit),
764  -1) != pcmk_rc_ok)) {
765  new_graph->batch_limit = 0;
766  }
767 
769  pcmk__scan_min_int(buf, &(new_graph->migration_limit), -1);
770 
771  new_graph->failed_stop_offset =
773  new_graph->failed_start_offset =
775 
776  if (crm_element_value_epoch(xml_graph, "recheck-by",
777  &(new_graph->recheck_by)) != pcmk_ok) {
778  new_graph->recheck_by = 0;
779  }
780  }
781 
782  // Unpack each child <synapse> element
783  for (const xmlNode *synapse_xml = pcmk__xe_first_child(xml_graph,
785  NULL, NULL);
786  synapse_xml != NULL;
787  synapse_xml = pcmk__xe_next(synapse_xml, PCMK__XE_SYNAPSE)) {
788 
789  pcmk__graph_synapse_t *new_synapse = unpack_synapse(new_graph,
790  synapse_xml);
791 
792  if (new_synapse != NULL) {
793  new_graph->synapses = g_list_append(new_graph->synapses,
794  new_synapse);
795  }
796  }
797 
798  crm_debug("Unpacked transition %d from %s: %d actions in %d synapses",
799  new_graph->id, new_graph->source, new_graph->num_actions,
800  new_graph->num_synapses);
801 
802  return new_graph;
803 }
804 
805 
806 /*
807  * Other transition graph utilities
808  */
809 
823 pcmk__event_from_graph_action(const xmlNode *resource,
825  int status, int rc, const char *exit_reason)
826 {
827  lrmd_event_data_t *op = NULL;
828  GHashTableIter iter;
829  const char *name = NULL;
830  const char *value = NULL;
831  xmlNode *action_resource = NULL;
832 
833  CRM_CHECK(action != NULL, return NULL);
834  CRM_CHECK(action->type == pcmk__rsc_graph_action, return NULL);
835 
836  action_resource = pcmk__xe_first_child(action->xml, PCMK_XE_PRIMITIVE, NULL,
837  NULL);
838  CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "invalid");
839  return NULL);
840 
841  op = lrmd_new_event(pcmk__xe_id(action_resource),
843  action->interval_ms);
844  lrmd__set_result(op, rc, status, exit_reason);
845  op->t_run = time(NULL);
846  op->t_rcchange = op->t_run;
847  op->params = pcmk__strkey_table(free, free);
848 
849  g_hash_table_iter_init(&iter, action->params);
850  while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
851  pcmk__insert_dup(op->params, name, value);
852  }
853 
854  for (xmlNode *xop = pcmk__xe_first_child(resource, NULL, NULL, NULL);
855  xop != NULL; xop = pcmk__xe_next(xop, NULL)) {
856 
857  int tmp = 0;
858 
860  crm_debug("Got call_id=%d for %s", tmp, pcmk__xe_id(resource));
861  if (tmp > op->call_id) {
862  op->call_id = tmp;
863  }
864  }
865 
866  op->call_id++;
867  return op;
868 }
#define PCMK__XE_ACTION_SET
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:213
#define PCMK__XA_PRIORITY
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition: xml.c:805
A dumping ground.
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml_element.c:42
#define pcmk__set_synapse_flags(synapse, flags_to_set)
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition: strings.c:116
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)
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: xml_element.c:1359
char * failed_start_offset
Failcount after one failed start action.
pcmk__graph_action_type
#define PCMK__XE_PSEUDO_EVENT
#define PCMK__XE_SYNAPSE
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:609
enum pcmk__graph_action_type type
#define PCMK__XE_TRIGGER
int(* pseudo)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define PCMK_XA_OPERATION
Definition: xml_names.h:349
#define PCMK__XA_FAILED_STOP_OFFSET
const char * action
Definition: pcmk_fence.c:32
#define PCMK__XE_INPUTS
int(* fence)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
void pcmk__xml_free(xmlNode *xml)
Definition: xml.c:789
void pcmk__update_graph(pcmk__graph_t *graph, const pcmk__graph_action_t *action)
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:92
#define crm_warn(fmt, args...)
Definition: logging.h:362
GHashTable * xml2list(const xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:350
#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:303
char * failed_stop_offset
Failcount after one failed stop action.
#define crm_debug(fmt, args...)
Definition: logging.h:370
enum pcmk__graph_next completion_action
pcmk__graph_status
int pcmk_parse_interval_spec(const char *input, guint *result_ms)
Parse milliseconds from a Pacemaker interval specification.
Definition: strings.c:452
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
Definition: xml_element.c:1466
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: xml_element.c:1168
#define PCMK_META_START_DELAY
Definition: options.h:112
#define crm_trace(fmt, args...)
Definition: logging.h:372
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:149
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:80
#define PCMK__XA_FAILED_START_OFFSET
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:376
#define PCMK_ACTION_STONITH
Definition: actions.h:65
#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_synapse_flags(synapse, flags_to_clear)
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
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
Definition: xml_element.c:106
#define pcmk__assert(expr)
#define PCMK_OPT_STONITH_TIMEOUT
Definition: options.h:67
#define PCMK_META_INTERVAL
Definition: options.h:91
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:685
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:299
int(* rsc)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define PCMK__XE_CRM_EVENT
#define CRM_META
Definition: crm.h:75
#define crm_err(fmt, args...)
Definition: logging.h:359
#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:2617
xmlNode * input
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: xml_element.c:1201
#define PCMK_OPT_MIGRATION_LIMIT
Definition: options.h:45
#define pcmk_ok
Definition: results.h:65
#define PCMK__XA_CALL_ID
int(* cluster)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define crm_log_xml_trace(xml, text)
Definition: logging.h:380
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:435
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:195
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition: strings.c:703
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:26