pacemaker  2.1.8-3980678f03
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  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 
234 static bool
235 should_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 
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) {
265  pcmk__graph_action_t *a = (pcmk__graph_action_t *) lpc->data;
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 
295 static int
296 initiate_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 
341 static int
342 fire_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 
375 static int
376 pseudo_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  }
399  pcmk__update_graph(graph, action);
400  return pcmk_rc_ok;
401 }
402 
403 static 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) {
430  return pcmk__graph_complete;
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 
443  if (pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
444  graph->completed++;
445 
446  } else if (!pcmk_is_set(synapse->flags, pcmk__synapse_failed)
447  && pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
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 
540 static pcmk__graph_action_t *
541 unpack_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  */
590  value = crm_meta_value(action->params, PCMK_META_START_DELAY);
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 
633 static pcmk__graph_synapse_t *
634 unpack_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 
742 pcmk__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;
761  new_graph->completion_action = pcmk__graph_done;
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 
771  buf = crm_element_value(xml_graph, PCMK_OPT_CLUSTER_DELAY);
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 
845 pcmk__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 CRM_CHECK(expr, failure_action)
Definition: logging.h:245
#define PCMK__XA_PRIORITY
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
Definition: xml.c:883
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:127
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:160
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:501
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
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:344
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:451
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
Definition: strings.c:97
#define crm_warn(fmt, args...)
Definition: logging.h:394
GHashTable * xml2list(const xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:859
#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:311
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:674
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:446
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:440
#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:98
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:567
#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:296
#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:867
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_OPT_STONITH_TIMEOUT
Definition: options.h:67
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:496
#define PCMK_META_INTERVAL
Definition: options.h:91
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:683
#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 CRM_ASSERT(expr)
Definition: results.h:42
#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:2562
xmlNode * input
#define PCMK_OPT_MIGRATION_LIMIT
Definition: options.h:45
#define pcmk_ok
Definition: results.h:69
#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:987
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:197
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition: xml.c:2108
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition: strings.c:701
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:24