pacemaker  2.1.4-dc6eb4362
Scalable High-Availability cluster resource manager
pcmk_graph_consumer.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2021 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(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  crm_action_t *prereq = (crm_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(synapse_t *synapse, int action_id)
79 {
80  bool all_confirmed = true;
81 
82  for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
83  crm_action_t *action = (crm_action_t *) lpc->data;
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  synapse_t *synapse = (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 crm_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->crmd != NULL);
154  CRM_ASSERT(graph_fns->pseudo != NULL);
155  CRM_ASSERT(graph_fns->stonith != NULL);
156 }
157 
167 static bool
168 should_fire_synapse(crm_graph_t *graph, synapse_t *synapse)
169 {
170  GList *lpc = NULL;
171 
173  for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
174  crm_action_t *prereq = (crm_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  crm_action_t *a = (crm_action_t *) lpc->data;
197 
198  if (a->type == action_type_pseudo) {
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(crm_graph_t *graph, crm_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) {
237  case action_type_pseudo:
238  crm_trace("Executing pseudo-action %d (%s)", action->id, id);
239  return graph_fns->pseudo(graph, action)? pcmk_rc_ok : pcmk_rc_error;
240 
241  case action_type_rsc:
242  crm_trace("Executing resource action %d (%s)", action->id, id);
243  return graph_fns->rsc(graph, action)? pcmk_rc_ok : pcmk_rc_error;
244 
245  case action_type_crm:
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->stonith(graph, action)? pcmk_rc_ok : pcmk_rc_error;
251  }
252  crm_trace("Executing control action %d (%s)", action->id, id);
253  return graph_fns->crmd(graph, action)? pcmk_rc_ok : pcmk_rc_error;
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(crm_graph_t *graph, synapse_t *synapse)
273 {
275  for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
276  crm_action_t *action = (crm_action_t *) lpc->data;
277 
278  if (initiate_action(graph, action) != pcmk_rc_ok) {
279  crm_err("Failed initiating <%s id=%d> in synapse %d",
280  crm_element_name(action->xml), action->id, synapse->id);
283  return pcmk_rc_error;
284  }
285  }
286  return pcmk_rc_ok;
287 }
288 
300 static gboolean
301 pseudo_action_dummy(crm_graph_t * graph, crm_action_t * action)
302 {
303  static int fail = -1;
304 
305  if (fail < 0) {
306  long long fail_ll;
307 
308  if ((pcmk__scan_ll(getenv("PE_fail"), &fail_ll, 0LL) == pcmk_rc_ok)
309  && (fail_ll > 0LL) && (fail_ll <= INT_MAX)) {
310  fail = (int) fail_ll;
311  } else {
312  fail = 0;
313  }
314  }
315 
316  if (action->id == fail) {
317  crm_err("Dummy event handler: pretending action %d failed", action->id);
319  graph->abort_priority = INFINITY;
320  } else {
321  crm_trace("Dummy event handler: action %d initiated", action->id);
322  }
324  pcmk__update_graph(graph, action);
325  return TRUE;
326 }
327 
328 static crm_graph_functions_t default_fns = {
329  pseudo_action_dummy,
330  pseudo_action_dummy,
331  pseudo_action_dummy,
332  pseudo_action_dummy
333 };
334 
345 {
346  GList *lpc = NULL;
347  int log_level = LOG_DEBUG;
348  enum transition_status pass_result = transition_active;
349  const char *status = "In progress";
350 
351  if (graph_fns == NULL) {
352  graph_fns = &default_fns;
353  }
354  if (graph == NULL) {
355  return transition_complete;
356  }
357 
358  graph->fired = 0;
359  graph->pending = 0;
360  graph->skipped = 0;
361  graph->completed = 0;
362  graph->incomplete = 0;
363 
364  // Count completed and in-flight synapses
365  for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
366  synapse_t *synapse = (synapse_t *) lpc->data;
367 
368  if (pcmk_is_set(synapse->flags, pcmk__synapse_confirmed)) {
369  graph->completed++;
370 
371  } else if (!(pcmk_is_set(synapse->flags, pcmk__synapse_failed)) && pcmk_is_set(synapse->flags, pcmk__synapse_executed)) {
372  graph->pending++;
373  }
374  }
375  crm_trace("Executing graph %d (%d synapses already completed, %d pending)",
376  graph->id, graph->completed, graph->pending);
377 
378  // Execute any synapses that are ready
379  for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
380  synapse_t *synapse = (synapse_t *) lpc->data;
381 
382  if ((graph->batch_limit > 0)
383  && (graph->pending >= graph->batch_limit)) {
384 
385  crm_debug("Throttling graph execution: batch limit (%d) reached",
386  graph->batch_limit);
387  break;
388 
389  } else if (pcmk_is_set(synapse->flags, pcmk__synapse_failed)) {
390  graph->skipped++;
391  continue;
392 
393  } else if (pcmk_any_flags_set(synapse->flags, pcmk__synapse_confirmed|pcmk__synapse_executed)) {
394  continue; // Already handled
395 
396  } else if (should_fire_synapse(graph, synapse)) {
397  graph->fired++;
398  if (fire_synapse(graph, synapse) != pcmk_rc_ok) {
399  crm_err("Synapse %d failed to fire", synapse->id);
400  log_level = LOG_ERR;
401  graph->abort_priority = INFINITY;
402  graph->incomplete++;
403  graph->fired--;
404  }
405 
406  if (!(pcmk_is_set(synapse->flags, pcmk__synapse_confirmed))) {
407  graph->pending++;
408  }
409 
410  } else {
411  crm_trace("Synapse %d cannot fire", synapse->id);
412  graph->incomplete++;
413  }
414  }
415 
416  if ((graph->pending == 0) && (graph->fired == 0)) {
417  graph->complete = TRUE;
418 
419  if ((graph->incomplete != 0) && (graph->abort_priority <= 0)) {
420  log_level = LOG_WARNING;
421  pass_result = transition_terminated;
422  status = "Terminated";
423 
424  } else if (graph->skipped != 0) {
425  log_level = LOG_NOTICE;
426  pass_result = transition_complete;
427  status = "Stopped";
428 
429  } else {
430  log_level = LOG_NOTICE;
431  pass_result = transition_complete;
432  status = "Complete";
433  }
434 
435  } else if (graph->fired == 0) {
436  pass_result = transition_pending;
437  }
438 
439  do_crm_log(log_level,
440  "Transition %d (Complete=%d, Pending=%d,"
441  " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s",
442  graph->id, graph->completed, graph->pending, graph->fired,
443  graph->skipped, graph->incomplete, graph->source, status);
444 
445  return pass_result;
446 }
447 
448 
449 /*
450  * Functions for unpacking transition graph XML into structs
451  */
452 
462 static crm_action_t *
463 unpack_action(synapse_t *parent, xmlNode *xml_action)
464 {
465  action_type_e action_type;
466  crm_action_t *action = NULL;
467  const char *element = TYPE(xml_action);
468  const char *value = ID(xml_action);
469 
470  if (value == NULL) {
471  crm_err("Ignoring transition graph action without id (bug?)");
472  crm_log_xml_trace(xml_action, "invalid");
473  return NULL;
474  }
475 
476  if (pcmk__str_eq(element, XML_GRAPH_TAG_RSC_OP, pcmk__str_casei)) {
477  action_type = action_type_rsc;
478 
479  } else if (pcmk__str_eq(element, XML_GRAPH_TAG_PSEUDO_EVENT,
480  pcmk__str_casei)) {
481  action_type = action_type_pseudo;
482 
483  } else if (pcmk__str_eq(element, XML_GRAPH_TAG_CRM_EVENT,
484  pcmk__str_casei)) {
485  action_type = action_type_crm;
486 
487  } else {
488  crm_err("Ignoring transition graph action of unknown type '%s' (bug?)",
489  element);
490  crm_log_xml_trace(xml_action, "invalid");
491  return NULL;
492  }
493 
494  action = calloc(1, sizeof(crm_action_t));
495  if (action == NULL) {
496  crm_perror(LOG_CRIT, "Cannot unpack transition graph action");
497  crm_log_xml_trace(xml_action, "lost");
498  return NULL;
499  }
500 
501  pcmk__scan_min_int(value, &(action->id), -1);
502  action->type = action_type_rsc;
503  action->xml = copy_xml(xml_action);
504  action->synapse = parent;
505  action->type = action_type;
506  action->params = xml2list(action->xml);
507 
508  value = g_hash_table_lookup(action->params, "CRM_meta_timeout");
509  pcmk__scan_min_int(value, &(action->timeout), 0);
510 
511  /* Take start-delay into account for the timeout of the action timer */
512  value = g_hash_table_lookup(action->params, "CRM_meta_start_delay");
513  {
514  int start_delay;
515 
516  pcmk__scan_min_int(value, &start_delay, 0);
517  action->timeout += start_delay;
518  }
519 
520  if (pcmk__guint_from_hash(action->params,
522  &(action->interval_ms)) != pcmk_rc_ok) {
523  action->interval_ms = 0;
524  }
525 
526  value = g_hash_table_lookup(action->params, "CRM_meta_can_fail");
527  if (value != NULL) {
528 
529  gboolean can_fail = FALSE;
530  crm_str_to_boolean(value, &can_fail);
531  if (can_fail) {
533  } else {
535  }
536 
537 #ifndef PCMK__COMPAT_2_0
539  crm_warn("Support for the can_fail meta-attribute is deprecated"
540  " and will be removed in a future release");
541  }
542 #endif
543  }
544 
545  crm_trace("Action %d has timer set to %dms", action->id, action->timeout);
546 
547  return action;
548 }
549 
559 static synapse_t *
560 unpack_synapse(crm_graph_t *new_graph, xmlNode *xml_synapse)
561 {
562  const char *value = NULL;
563  xmlNode *action_set = NULL;
564  synapse_t *new_synapse = NULL;
565 
566  crm_trace("Unpacking synapse %s", ID(xml_synapse));
567 
568  new_synapse = calloc(1, sizeof(synapse_t));
569  if (new_synapse == NULL) {
570  return NULL;
571  }
572 
573  pcmk__scan_min_int(ID(xml_synapse), &(new_synapse->id), 0);
574 
575  value = crm_element_value(xml_synapse, XML_CIB_ATTR_PRIORITY);
576  pcmk__scan_min_int(value, &(new_synapse->priority), 0);
577 
578  CRM_CHECK(new_synapse->id >= 0, free(new_synapse);
579  return NULL);
580 
581  new_graph->num_synapses++;
582 
583  crm_trace("Unpacking synapse %s action sets",
584  crm_element_value(xml_synapse, XML_ATTR_ID));
585 
586  for (action_set = first_named_child(xml_synapse, "action_set");
587  action_set != NULL; action_set = crm_next_same_xml(action_set)) {
588 
589  for (xmlNode *action = pcmk__xml_first_child(action_set);
590  action != NULL; action = pcmk__xml_next(action)) {
591 
592  crm_action_t *new_action = unpack_action(new_synapse, action);
593 
594  if (new_action == NULL) {
595  continue;
596  }
597 
598  crm_trace("Adding action %d to synapse %d",
599  new_action->id, new_synapse->id);
600  new_graph->num_actions++;
601  new_synapse->actions = g_list_append(new_synapse->actions,
602  new_action);
603  }
604  }
605 
606  crm_trace("Unpacking synapse %s inputs", ID(xml_synapse));
607 
608  for (xmlNode *inputs = first_named_child(xml_synapse, "inputs");
609  inputs != NULL; inputs = crm_next_same_xml(inputs)) {
610 
611  for (xmlNode *trigger = first_named_child(inputs, "trigger");
612  trigger != NULL; trigger = crm_next_same_xml(trigger)) {
613 
614  for (xmlNode *input = pcmk__xml_first_child(trigger);
615  input != NULL; input = pcmk__xml_next(input)) {
616 
617  crm_action_t *new_input = unpack_action(new_synapse, input);
618 
619  if (new_input == NULL) {
620  continue;
621  }
622 
623  crm_trace("Adding input %d to synapse %d",
624  new_input->id, new_synapse->id);
625 
626  new_synapse->inputs = g_list_append(new_synapse->inputs,
627  new_input);
628  }
629  }
630  }
631 
632  return new_synapse;
633 }
634 
660 crm_graph_t *
661 pcmk__unpack_graph(xmlNode *xml_graph, const char *reference)
662 {
663  crm_graph_t *new_graph = NULL;
664  const char *t_id = NULL;
665  const char *time = NULL;
666 
667  new_graph = calloc(1, sizeof(crm_graph_t));
668  if (new_graph == NULL) {
669  return NULL;
670  }
671 
672  new_graph->source = strdup((reference == NULL)? "unknown" : reference);
673  if (new_graph->source == NULL) {
674  free(new_graph);
675  return NULL;
676  }
677 
678  new_graph->id = -1;
679  new_graph->abort_priority = 0;
680  new_graph->network_delay = 0;
681  new_graph->stonith_timeout = 0;
682  new_graph->completion_action = tg_done;
683 
684  // Parse top-level attributes from <transition_graph>
685  if (xml_graph != NULL) {
686  t_id = crm_element_value(xml_graph, "transition_id");
687  CRM_CHECK(t_id != NULL, free(new_graph);
688  return NULL);
689  pcmk__scan_min_int(t_id, &(new_graph->id), -1);
690 
691  time = crm_element_value(xml_graph, "cluster-delay");
692  CRM_CHECK(time != NULL, free(new_graph);
693  return NULL);
694  new_graph->network_delay = crm_parse_interval_spec(time);
695 
696  time = crm_element_value(xml_graph, "stonith-timeout");
697  if (time == NULL) {
698  new_graph->stonith_timeout = new_graph->network_delay;
699  } else {
700  new_graph->stonith_timeout = crm_parse_interval_spec(time);
701  }
702 
703  // Use 0 (dynamic limit) as default/invalid, -1 (no limit) as minimum
704  t_id = crm_element_value(xml_graph, "batch-limit");
705  if ((t_id == NULL)
706  || (pcmk__scan_min_int(t_id, &(new_graph->batch_limit),
707  -1) != pcmk_rc_ok)) {
708  new_graph->batch_limit = 0;
709  }
710 
711  t_id = crm_element_value(xml_graph, "migration-limit");
712  pcmk__scan_min_int(t_id, &(new_graph->migration_limit), -1);
713  }
714 
715  // Unpack each child <synapse> element
716  for (xmlNode *synapse_xml = first_named_child(xml_graph, "synapse");
717  synapse_xml != NULL; synapse_xml = crm_next_same_xml(synapse_xml)) {
718 
719  synapse_t *new_synapse = unpack_synapse(new_graph, synapse_xml);
720 
721  if (new_synapse != NULL) {
722  new_graph->synapses = g_list_append(new_graph->synapses,
723  new_synapse);
724  }
725  }
726 
727  crm_debug("Unpacked transition %d from %s: %d actions in %d synapses",
728  new_graph->id, new_graph->source, new_graph->num_actions,
729  new_graph->num_synapses);
730 
731  return new_graph;
732 }
733 
734 
735 /*
736  * Functions for freeing transition graph objects
737  */
738 
745 static void
746 free_graph_action(gpointer user_data)
747 {
748  crm_action_t *action = user_data;
749 
750  if ((action->timer != NULL) && (action->timer->source_id != 0)) {
751  crm_warn("Cancelling timer for graph action %d", action->id);
752  g_source_remove(action->timer->source_id);
753  }
754  if (action->params != NULL) {
755  g_hash_table_destroy(action->params);
756  }
757  free_xml(action->xml);
758  free(action->timer);
759  free(action);
760 }
761 
768 static void
769 free_graph_synapse(gpointer user_data)
770 {
771  synapse_t *synapse = user_data;
772 
773  g_list_free_full(synapse->actions, free_graph_action);
774  g_list_free_full(synapse->inputs, free_graph_action);
775  free(synapse);
776 }
777 
784 void
786 {
787  if (graph != NULL) {
788  g_list_free_full(graph->synapses, free_graph_synapse);
789  free(graph->source);
790  free(graph);
791  }
792 }
793 
794 
795 /*
796  * Other transition graph utilities
797  */
798 
813  int status, int rc, const char *exit_reason)
814 {
815  lrmd_event_data_t *op = NULL;
816  GHashTableIter iter;
817  const char *name = NULL;
818  const char *value = NULL;
819  xmlNode *action_resource = NULL;
820 
821  CRM_CHECK(action != NULL, return NULL);
822  CRM_CHECK(action->type == action_type_rsc, return NULL);
823 
824  action_resource = first_named_child(action->xml, XML_CIB_TAG_RESOURCE);
825  CRM_CHECK(action_resource != NULL, crm_log_xml_warn(action->xml, "invalid");
826  return NULL);
827 
828  op = lrmd_new_event(ID(action_resource),
830  action->interval_ms);
831  lrmd__set_result(op, rc, status, exit_reason);
832  op->t_run = time(NULL);
833  op->t_rcchange = op->t_run;
834  op->params = pcmk__strkey_table(free, free);
835 
836  g_hash_table_iter_init(&iter, action->params);
837  while (g_hash_table_iter_next(&iter, (void **)&name, (void **)&value)) {
838  g_hash_table_insert(op->params, strdup(name), strdup(value));
839  }
840 
841  for (xmlNode *xop = pcmk__xml_first_child(resource); xop != NULL;
842  xop = pcmk__xml_next(xop)) {
843  int tmp = 0;
844 
846  crm_debug("Got call_id=%d for %s", tmp, ID(resource));
847  if (tmp > op->call_id) {
848  op->call_id = tmp;
849  }
850  }
851 
852  op->call_id++;
853  return op;
854 }
enum transition_status pcmk__execute_graph(crm_graph_t *graph)
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:226
A dumping ground.
action_type_e type
#define pcmk__set_synapse_flags(synapse, flags_to_set)
#define INFINITY
Definition: crm.h:99
enum transition_action completion_action
#define CRM_OP_FENCE
Definition: crm.h:145
int pcmk__scan_min_int(const char *text, int *result, int minimum)
Definition: strings.c:127
const char * name
Definition: cib.c:24
void pcmk__set_graph_functions(crm_graph_functions_t *fns)
crm_graph_t * pcmk__unpack_graph(xmlNode *xml_graph, const char *reference)
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2794
transition_status
#define crm__clear_graph_action_flags(action, flags_to_clear)
#define XML_LRM_ATTR_INTERVAL
Definition: msg_xml.h:297
#define XML_GRAPH_TAG_RSC_OP
Definition: msg_xml.h:332
gboolean(* stonith)(crm_graph_t *graph, crm_action_t *action)
unsigned int t_rcchange
Definition: lrmd.h:231
#define XML_GRAPH_TAG_CRM_EVENT
Definition: msg_xml.h:334
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:565
const char * action
Definition: pcmk_fence.c:29
#define TYPE(x)
Definition: msg_xml.h:461
uint32_t flags
#define XML_GRAPH_TAG_PSEUDO_EVENT
Definition: msg_xml.h:333
#define XML_CIB_ATTR_PRIORITY
Definition: msg_xml.h:278
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:830
void pcmk__free_graph(crm_graph_t *graph)
#define XML_LRM_ATTR_TASK
Definition: msg_xml.h:303
gboolean(* crmd)(crm_graph_t *graph, crm_action_t *action)
void * params
Definition: lrmd.h:242
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:359
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:363
#define XML_ATTR_ID
Definition: msg_xml.h:135
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:529
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:220
#define crm_trace(fmt, args...)
Definition: logging.h:364
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:167
GList * inputs
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:122
GList * actions
Wrappers for and extensions to libxml2.
#define crm_log_xml_warn(xml, text)
Definition: logging.h:368
#define crm__set_graph_action_flags(action, flags_to_set)
gboolean complete
#define pcmk__clear_synapse_flags(synapse, flags_to_clear)
void free_xml(xmlNode *child)
Definition: xml.c:824
gboolean(* rsc)(crm_graph_t *graph, crm_action_t *action)
unsigned int t_run
Definition: lrmd.h:229
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
gboolean(* pseudo)(crm_graph_t *graph, crm_action_t *action)
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:309
#define CRM_META
Definition: crm.h:78
#define crm_err(fmt, args...)
Definition: logging.h:358
#define CRM_ASSERT(expr)
Definition: results.h:42
char guint crm_parse_interval_spec(const char *input)
Parse milliseconds from a Pacemaker interval specification.
Definition: utils.c:242
void lrmd__set_result(lrmd_event_data_t *event, enum ocf_exitcode rc, int op_status, const char *exit_reason)
Definition: lrmd_client.c:2356
xmlNode * input
#define XML_LRM_ATTR_CALLID
Definition: msg_xml.h:315
GHashTable * xml2list(xmlNode *parent)
Retrieve XML attributes as a hash table.
Definition: nvpair.c:908
void pcmk__update_graph(crm_graph_t *graph, crm_action_t *action)
#define crm_log_xml_trace(xml, text)
Definition: logging.h:372
action_type_e
#define ID(x)
Definition: msg_xml.h:460
const char * parent
Definition: cib.c:25
gboolean(* allowed)(crm_graph_t *graph, crm_action_t *action)
lrmd_event_data_t * pcmk__event_from_graph_action(xmlNode *resource, crm_action_t *action, int status, int rc, const char *exit_reason)
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:2820