pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
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 
44 static void
45 update_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 
77 static void
78 update_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 
110 void
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  */
137 static pcmk__graph_functions_t *graph_fns = NULL;
138 
145 void
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 
167 static bool
168 should_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 
177  crm_trace("Input %d for synapse %d not yet confirmed",
178  prereq->id, synapse->id);
180  break;
181 
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) {
196  pcmk__graph_action_t *a = (pcmk__graph_action_t *) lpc->data;
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 
226 static int
227 initiate_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 
272 static int
273 fire_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 
306 static int
307 pseudo_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  }
330  pcmk__update_graph(graph, action);
331  return pcmk_rc_ok;
332 }
333 
334 static 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) {
361  return pcmk__graph_complete;
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 
374  if (pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
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 
468 static pcmk__graph_action_t *
469 unpack_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,
486  pcmk__str_casei)) {
487  action_type = pcmk__pseudo_graph_action;
488 
489  } else if (pcmk__str_eq(element, XML_GRAPH_TAG_CRM_EVENT,
490  pcmk__str_casei)) {
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 
565 static pcmk__graph_synapse_t *
566 unpack_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 
669 pcmk__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;
688  new_graph->completion_action = pcmk__graph_done;
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 {
707  new_graph->stonith_timeout = crm_parse_interval_spec(buf);
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 
721  pcmk__str_update(&(new_graph->failed_stop_offset),
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 
763 static void
764 free_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 
785 static void
786 free_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 
801 void
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 
831 pcmk__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 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:235
A dumping ground.
#define pcmk__set_synapse_flags(synapse, flags_to_set)
#define INFINITY
Definition: crm.h:99
#define CRM_OP_FENCE
Definition: crm.h:144
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition: strings.c:127
const char * name
Definition: cib.c:24
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__free_graph(pcmk__graph_t *graph)
char * failed_start_offset
Failcount after one failed start action.
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2521
pcmk__graph_action_type
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:309
#define XML_GRAPH_TAG_RSC_OP
Definition: msg_xml.h:344
unsigned int t_rcchange
Definition: lrmd.h:247
#define XML_GRAPH_TAG_CRM_EVENT
Definition: msg_xml.h:346
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:488
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
enum pcmk__graph_action_type type
int(* pseudo)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
const char * action
Definition: pcmk_fence.c:30
#define TYPE(x)
Definition: msg_xml.h:481
#define XML_GRAPH_TAG_PSEUDO_EVENT
Definition: msg_xml.h:345
int(* fence)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define XML_CIB_ATTR_PRIORITY
Definition: msg_xml.h:290
void pcmk__update_graph(pcmk__graph_t *graph, const pcmk__graph_action_t *action)
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:819
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:315
void * params
Definition: lrmd.h:258
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:378
GHashTable * xml2list(const xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:875
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:382
enum pcmk__graph_next completion_action
pcmk__graph_status
#define XML_ATTR_ID
Definition: msg_xml.h:147
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:496
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:230
#define crm_trace(fmt, args...)
Definition: logging.h:383
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:172
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:121
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)
void pcmk__str_update(char **str, const char *value)
Definition: strings.c:1193
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:387
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
#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:813
bool(* allowed)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
void pcmk__set_graph_functions(pcmk__graph_functions_t *fns)
unsigned int t_run
Definition: lrmd.h:245
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:427
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
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:611
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr.
Definition: logging.h:319
int(* rsc)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define CRM_META
Definition: crm.h:78
#define crm_err(fmt, args...)
Definition: logging.h:377
#define CRM_ASSERT(expr)
Definition: results.h:42
#define pcmk__set_graph_action_flags(action, flags_to_set)
char guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
Definition: utils.c:271
void lrmd__set_result(lrmd_event_data_t *event, enum ocf_exitcode rc, int op_status, const char *exit_reason)
Definition: lrmd_client.c:2481
xmlNode * input
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:327
#define pcmk_ok
Definition: results.h:68
int(* cluster)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define crm_log_xml_trace(xml, text)
Definition: logging.h:391
#define ID(x)
Definition: msg_xml.h:480
const char * parent
Definition: cib.c:25
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:2547