pacemaker  2.1.5-b7adf64e51
Scalable High-Availability cluster resource manager
pcmk_graph_consumer.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2022 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 id='%s'> (bug?)",
257  crm_element_name(action->xml), id);
258  return EINVAL;
259  }
260 }
261 
271 static int
272 fire_synapse(pcmk__graph_t *graph, pcmk__graph_synapse_t *synapse)
273 {
275  for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
277  int rc = initiate_action(graph, action);
278 
279  if (rc != pcmk_rc_ok) {
280  crm_err("Failed initiating <%s id=%d> in synapse %d: %s",
281  crm_element_name(action->xml), action->id, synapse->id,
282  pcmk_rc_str(rc));
287  return pcmk_rc_error;
288  }
289  }
290  return pcmk_rc_ok;
291 }
292 
304 static int
305 pseudo_action_dummy(pcmk__graph_t * graph, pcmk__graph_action_t *action)
306 {
307  static int fail = -1;
308 
309  if (fail < 0) {
310  long long fail_ll;
311 
312  if ((pcmk__scan_ll(getenv("PE_fail"), &fail_ll, 0LL) == pcmk_rc_ok)
313  && (fail_ll > 0LL) && (fail_ll <= INT_MAX)) {
314  fail = (int) fail_ll;
315  } else {
316  fail = 0;
317  }
318  }
319 
320  if (action->id == fail) {
321  crm_err("Dummy event handler: pretending action %d failed", action->id);
323  graph->abort_priority = INFINITY;
324  } else {
325  crm_trace("Dummy event handler: action %d initiated", action->id);
326  }
328  pcmk__update_graph(graph, action);
329  return pcmk_rc_ok;
330 }
331 
332 static pcmk__graph_functions_t default_fns = {
333  pseudo_action_dummy,
334  pseudo_action_dummy,
335  pseudo_action_dummy,
336  pseudo_action_dummy
337 };
338 
349 {
350  GList *lpc = NULL;
351  int log_level = LOG_DEBUG;
352  enum pcmk__graph_status pass_result = pcmk__graph_active;
353  const char *status = "In progress";
354 
355  if (graph_fns == NULL) {
356  graph_fns = &default_fns;
357  }
358  if (graph == NULL) {
359  return pcmk__graph_complete;
360  }
361 
362  graph->fired = 0;
363  graph->pending = 0;
364  graph->skipped = 0;
365  graph->completed = 0;
366  graph->incomplete = 0;
367 
368  // Count completed and in-flight synapses
369  for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
370  pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
371 
372  if (pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
373  graph->completed++;
374 
375  } else if (!(pcmk_is_set(synapse->flags, pcmk__synapse_failed)) && pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
376  graph->pending++;
377  }
378  }
379  crm_trace("Executing graph %d (%d synapses already completed, %d pending)",
380  graph->id, graph->completed, graph->pending);
381 
382  // Execute any synapses that are ready
383  for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
384  pcmk__graph_synapse_t *synapse = (pcmk__graph_synapse_t *) lpc->data;
385 
386  if ((graph->batch_limit > 0)
387  && (graph->pending >= graph->batch_limit)) {
388 
389  crm_debug("Throttling graph execution: batch limit (%d) reached",
390  graph->batch_limit);
391  break;
392 
393  } else if (pcmk_is_set(synapse->flags, pcmk__synapse_failed)) {
394  graph->skipped++;
395  continue;
396 
397  } else if (pcmk_any_flags_set(synapse->flags, pcmk__synapse_confirmed|pcmk__synapse_executed)) {
398  continue; // Already handled
399 
400  } else if (should_fire_synapse(graph, synapse)) {
401  graph->fired++;
402  if (fire_synapse(graph, synapse) != pcmk_rc_ok) {
403  crm_err("Synapse %d failed to fire", synapse->id);
404  log_level = LOG_ERR;
405  graph->abort_priority = INFINITY;
406  graph->incomplete++;
407  graph->fired--;
408  }
409 
410  if (!(pcmk_is_set(synapse->flags, pcmk__synapse_confirmed))) {
411  graph->pending++;
412  }
413 
414  } else {
415  crm_trace("Synapse %d cannot fire", synapse->id);
416  graph->incomplete++;
417  }
418  }
419 
420  if ((graph->pending == 0) && (graph->fired == 0)) {
421  graph->complete = true;
422 
423  if ((graph->incomplete != 0) && (graph->abort_priority <= 0)) {
424  log_level = LOG_WARNING;
425  pass_result = pcmk__graph_terminated;
426  status = "Terminated";
427 
428  } else if (graph->skipped != 0) {
429  log_level = LOG_NOTICE;
430  pass_result = pcmk__graph_complete;
431  status = "Stopped";
432 
433  } else {
434  log_level = LOG_NOTICE;
435  pass_result = pcmk__graph_complete;
436  status = "Complete";
437  }
438 
439  } else if (graph->fired == 0) {
440  pass_result = pcmk__graph_pending;
441  }
442 
443  do_crm_log(log_level,
444  "Transition %d (Complete=%d, Pending=%d,"
445  " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s",
446  graph->id, graph->completed, graph->pending, graph->fired,
447  graph->skipped, graph->incomplete, graph->source, status);
448 
449  return pass_result;
450 }
451 
452 
453 /*
454  * Functions for unpacking transition graph XML into structs
455  */
456 
466 static pcmk__graph_action_t *
467 unpack_action(pcmk__graph_synapse_t *parent, xmlNode *xml_action)
468 {
469  enum pcmk__graph_action_type action_type;
471  const char *element = TYPE(xml_action);
472  const char *value = ID(xml_action);
473 
474  if (value == NULL) {
475  crm_err("Ignoring transition graph action without id (bug?)");
476  crm_log_xml_trace(xml_action, "invalid");
477  return NULL;
478  }
479 
480  if (pcmk__str_eq(element, XML_GRAPH_TAG_RSC_OP, pcmk__str_casei)) {
481  action_type = pcmk__rsc_graph_action;
482 
483  } else if (pcmk__str_eq(element, XML_GRAPH_TAG_PSEUDO_EVENT,
484  pcmk__str_casei)) {
485  action_type = pcmk__pseudo_graph_action;
486 
487  } else if (pcmk__str_eq(element, XML_GRAPH_TAG_CRM_EVENT,
488  pcmk__str_casei)) {
489  action_type = pcmk__cluster_graph_action;
490 
491  } else {
492  crm_err("Ignoring transition graph action of unknown type '%s' (bug?)",
493  element);
494  crm_log_xml_trace(xml_action, "invalid");
495  return NULL;
496  }
497 
498  action = calloc(1, sizeof(pcmk__graph_action_t));
499  if (action == NULL) {
500  crm_perror(LOG_CRIT, "Cannot unpack transition graph action");
501  crm_log_xml_trace(xml_action, "lost");
502  return NULL;
503  }
504 
505  pcmk__scan_min_int(value, &(action->id), -1);
507  action->xml = copy_xml(xml_action);
508  action->synapse = parent;
509  action->type = action_type;
510  action->params = xml2list(action->xml);
511 
512  value = g_hash_table_lookup(action->params, "CRM_meta_timeout");
513  pcmk__scan_min_int(value, &(action->timeout), 0);
514 
515  /* Take start-delay into account for the timeout of the action timer */
516  value = g_hash_table_lookup(action->params, "CRM_meta_start_delay");
517  {
518  int start_delay;
519 
520  pcmk__scan_min_int(value, &start_delay, 0);
521  action->timeout += start_delay;
522  }
523 
524  if (pcmk__guint_from_hash(action->params,
526  &(action->interval_ms)) != pcmk_rc_ok) {
527  action->interval_ms = 0;
528  }
529 
530  value = g_hash_table_lookup(action->params, "CRM_meta_can_fail");
531  if (value != NULL) {
532 
533  gboolean can_fail = FALSE;
534  crm_str_to_boolean(value, &can_fail);
535  if (can_fail) {
537  } else {
539  }
540 
541 #ifndef PCMK__COMPAT_2_0
543  crm_warn("Support for the can_fail meta-attribute is deprecated"
544  " and will be removed in a future release");
545  }
546 #endif
547  }
548 
549  crm_trace("Action %d has timer set to %dms", action->id, action->timeout);
550 
551  return action;
552 }
553 
563 static pcmk__graph_synapse_t *
564 unpack_synapse(pcmk__graph_t *new_graph, xmlNode *xml_synapse)
565 {
566  const char *value = NULL;
567  xmlNode *action_set = NULL;
568  pcmk__graph_synapse_t *new_synapse = NULL;
569 
570  crm_trace("Unpacking synapse %s", ID(xml_synapse));
571 
572  new_synapse = calloc(1, sizeof(pcmk__graph_synapse_t));
573  if (new_synapse == NULL) {
574  return NULL;
575  }
576 
577  pcmk__scan_min_int(ID(xml_synapse), &(new_synapse->id), 0);
578 
579  value = crm_element_value(xml_synapse, XML_CIB_ATTR_PRIORITY);
580  pcmk__scan_min_int(value, &(new_synapse->priority), 0);
581 
582  CRM_CHECK(new_synapse->id >= 0, free(new_synapse);
583  return NULL);
584 
585  new_graph->num_synapses++;
586 
587  crm_trace("Unpacking synapse %s action sets",
588  crm_element_value(xml_synapse, XML_ATTR_ID));
589 
590  for (action_set = first_named_child(xml_synapse, "action_set");
591  action_set != NULL; action_set = crm_next_same_xml(action_set)) {
592 
593  for (xmlNode *action = pcmk__xml_first_child(action_set);
594  action != NULL; action = pcmk__xml_next(action)) {
595 
596  pcmk__graph_action_t *new_action = unpack_action(new_synapse,
597  action);
598 
599  if (new_action == NULL) {
600  continue;
601  }
602 
603  crm_trace("Adding action %d to synapse %d",
604  new_action->id, new_synapse->id);
605  new_graph->num_actions++;
606  new_synapse->actions = g_list_append(new_synapse->actions,
607  new_action);
608  }
609  }
610 
611  crm_trace("Unpacking synapse %s inputs", ID(xml_synapse));
612 
613  for (xmlNode *inputs = first_named_child(xml_synapse, "inputs");
614  inputs != NULL; inputs = crm_next_same_xml(inputs)) {
615 
616  for (xmlNode *trigger = first_named_child(inputs, "trigger");
617  trigger != NULL; trigger = crm_next_same_xml(trigger)) {
618 
619  for (xmlNode *input = pcmk__xml_first_child(trigger);
620  input != NULL; input = pcmk__xml_next(input)) {
621 
622  pcmk__graph_action_t *new_input = unpack_action(new_synapse,
623  input);
624 
625  if (new_input == NULL) {
626  continue;
627  }
628 
629  crm_trace("Adding input %d to synapse %d",
630  new_input->id, new_synapse->id);
631 
632  new_synapse->inputs = g_list_append(new_synapse->inputs,
633  new_input);
634  }
635  }
636  }
637 
638  return new_synapse;
639 }
640 
667 pcmk__unpack_graph(xmlNode *xml_graph, const char *reference)
668 {
669  pcmk__graph_t *new_graph = NULL;
670  const char *t_id = NULL;
671  const char *time = 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  t_id = crm_element_value(xml_graph, "transition_id");
693  CRM_CHECK(t_id != NULL, free(new_graph);
694  return NULL);
695  pcmk__scan_min_int(t_id, &(new_graph->id), -1);
696 
697  time = crm_element_value(xml_graph, "cluster-delay");
698  CRM_CHECK(time != NULL, free(new_graph);
699  return NULL);
700  new_graph->network_delay = crm_parse_interval_spec(time);
701 
702  time = crm_element_value(xml_graph, "stonith-timeout");
703  if (time == NULL) {
704  new_graph->stonith_timeout = new_graph->network_delay;
705  } else {
706  new_graph->stonith_timeout = crm_parse_interval_spec(time);
707  }
708 
709  // Use 0 (dynamic limit) as default/invalid, -1 (no limit) as minimum
710  t_id = crm_element_value(xml_graph, "batch-limit");
711  if ((t_id == NULL)
712  || (pcmk__scan_min_int(t_id, &(new_graph->batch_limit),
713  -1) != pcmk_rc_ok)) {
714  new_graph->batch_limit = 0;
715  }
716 
717  t_id = crm_element_value(xml_graph, "migration-limit");
718  pcmk__scan_min_int(t_id, &(new_graph->migration_limit), -1);
719  }
720 
721  // Unpack each child <synapse> element
722  for (xmlNode *synapse_xml = first_named_child(xml_graph, "synapse");
723  synapse_xml != NULL; synapse_xml = crm_next_same_xml(synapse_xml)) {
724 
725  pcmk__graph_synapse_t *new_synapse = unpack_synapse(new_graph,
726  synapse_xml);
727 
728  if (new_synapse != NULL) {
729  new_graph->synapses = g_list_append(new_graph->synapses,
730  new_synapse);
731  }
732  }
733 
734  crm_debug("Unpacked transition %d from %s: %d actions in %d synapses",
735  new_graph->id, new_graph->source, new_graph->num_actions,
736  new_graph->num_synapses);
737 
738  return new_graph;
739 }
740 
741 
742 /*
743  * Functions for freeing transition graph objects
744  */
745 
752 static void
753 free_graph_action(gpointer user_data)
754 {
755  pcmk__graph_action_t *action = user_data;
756 
757  if (action->timer != 0) {
758  crm_warn("Cancelling timer for graph action %d", action->id);
759  g_source_remove(action->timer);
760  }
761  if (action->params != NULL) {
762  g_hash_table_destroy(action->params);
763  }
764  free_xml(action->xml);
765  free(action);
766 }
767 
774 static void
775 free_graph_synapse(gpointer user_data)
776 {
777  pcmk__graph_synapse_t *synapse = user_data;
778 
779  g_list_free_full(synapse->actions, free_graph_action);
780  g_list_free_full(synapse->inputs, free_graph_action);
781  free(synapse);
782 }
783 
790 void
792 {
793  if (graph != NULL) {
794  g_list_free_full(graph->synapses, free_graph_synapse);
795  free(graph->source);
796  free(graph);
797  }
798 }
799 
800 
801 /*
802  * Other transition graph utilities
803  */
804 
818 pcmk__event_from_graph_action(const xmlNode *resource,
820  int status, int rc, const char *exit_reason)
821 {
822  lrmd_event_data_t *op = NULL;
823  GHashTableIter iter;
824  const char *name = NULL;
825  const char *value = NULL;
826  xmlNode *action_resource = NULL;
827 
828  CRM_CHECK(action != NULL, return NULL);
829  CRM_CHECK(action->type == pcmk__rsc_graph_action, return NULL);
830 
831  action_resource = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
832  CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "invalid");
833  return NULL);
834 
835  op = lrmd_new_event(ID(action_resource),
837  action->interval_ms);
838  lrmd__set_result(op, rc, status, exit_reason);
839  op->t_run = time(NULL);
840  op->t_rcchange = op->t_run;
841  op->params = pcmk__strkey_table(free, free);
842 
843  g_hash_table_iter_init(&iter, action->params);
844  while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
845  g_hash_table_insert(op->params, strdup(name), strdup(value));
846  }
847 
848  for (xmlNode *xop = pcmk__xml_first_child(resource); xop != NULL;
849  xop = pcmk__xml_next(xop)) {
850  int tmp = 0;
851 
853  crm_debug("Got call_id=%d for %s", tmp, ID(resource));
854  if (tmp > op->call_id) {
855  op->call_id = tmp;
856  }
857  }
858 
859  op->call_id++;
860  return op;
861 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:227
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)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2930
pcmk__graph_action_type
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:294
#define XML_GRAPH_TAG_RSC_OP
Definition: msg_xml.h:329
unsigned int t_rcchange
Definition: lrmd.h:247
#define XML_GRAPH_TAG_CRM_EVENT
Definition: msg_xml.h:331
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:476
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:553
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:469
void pcmk__update_graph(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define XML_GRAPH_TAG_PSEUDO_EVENT
Definition: msg_xml.h:330
int(* fence)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define XML_CIB_ATTR_PRIORITY
Definition: msg_xml.h:275
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:891
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:300
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:360
GHashTable * xml2list(const xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:896
int pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val, guint *result)
Definition: strings.c:311
#define crm_debug(fmt, args...)
Definition: logging.h:364
enum pcmk__graph_next completion_action
pcmk__graph_status
#define XML_ATTR_ID
Definition: msg_xml.h:134
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:517
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:217
#define crm_trace(fmt, args...)
Definition: logging.h:365
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:168
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:121
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:369
pcmk__graph_t * pcmk__unpack_graph(xmlNode *xml_graph, const char *reference)
#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:885
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)
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:310
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:359
#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:2472
xmlNode * input
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:312
int(* cluster)(pcmk__graph_t *graph, pcmk__graph_action_t *action)
#define crm_log_xml_trace(xml, text)
Definition: logging.h:373
#define ID(x)
Definition: msg_xml.h:468
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:2956