pacemaker  2.0.4-2deceaa
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pcmk_trans_utils.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 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 <crm/crm.h>
13 #include <crm/msg_xml.h>
14 #include <crm/common/xml.h>
15 #include <pacemaker-internal.h>
16 
18 
19 static gboolean
20 pseudo_action_dummy(crm_graph_t * graph, crm_action_t * action)
21 {
22  static int fail = -1;
23 
24  if (fail < 0) {
25  char *fail_s = getenv("PE_fail");
26 
27  if (fail_s) {
28  fail = (int) crm_parse_ll(fail_s, NULL);
29  } else {
30  fail = 0;
31  }
32  }
33 
34  crm_trace("Dummy event handler: action %d executed", action->id);
35  if (action->id == fail) {
36  crm_err("Dummy event handler: pretending action %d failed", action->id);
37  action->failed = TRUE;
38  graph->abort_priority = INFINITY;
39  }
40  action->confirmed = TRUE;
41  update_graph(graph, action);
42  return TRUE;
43 }
44 
46  pseudo_action_dummy,
47  pseudo_action_dummy,
48  pseudo_action_dummy,
49  pseudo_action_dummy
50 };
51 
52 void
54 {
55  graph_fns = &default_fns;
56 }
57 
58 void
60 {
61  crm_info("Setting custom graph functions");
62  graph_fns = fns;
63 
64  CRM_ASSERT(graph_fns != NULL);
65  CRM_ASSERT(graph_fns->rsc != NULL);
66  CRM_ASSERT(graph_fns->crmd != NULL);
67  CRM_ASSERT(graph_fns->pseudo != NULL);
68  CRM_ASSERT(graph_fns->stonith != NULL);
69 }
70 
71 const char *
73 {
74  switch (state) {
75  case transition_active:
76  return "active";
77  case transition_pending:
78  return "pending";
80  return "complete";
81  case transition_stopped:
82  return "stopped";
84  return "terminated";
86  return "failed (action)";
87  case transition_failed:
88  return "failed";
89  }
90  return "unknown";
91 }
92 
93 const char *
95 {
96  switch (type) {
97  case action_type_pseudo:
98  return "pseudo";
99  case action_type_rsc:
100  return "resource";
101  case action_type_crm:
102  return "cluster";
103  }
104  return "invalid";
105 }
106 
107 static crm_action_t *
108 find_action(crm_graph_t * graph, int id)
109 {
110  GListPtr sIter = NULL;
111 
112  if (graph == NULL) {
113  return NULL;
114  }
115 
116  for (sIter = graph->synapses; sIter != NULL; sIter = sIter->next) {
117  GListPtr aIter = NULL;
118  synapse_t *synapse = (synapse_t *) sIter->data;
119 
120  for (aIter = synapse->actions; aIter != NULL; aIter = aIter->next) {
121  crm_action_t *action = (crm_action_t *) aIter->data;
122 
123  if (action->id == id) {
124  return action;
125  }
126  }
127  }
128  return NULL;
129 }
130 
131 static const char *
132 synapse_state_str(synapse_t *synapse)
133 {
134  if (synapse->failed) {
135  return "Failed";
136 
137  } else if (synapse->confirmed) {
138  return "Completed";
139 
140  } else if (synapse->executed) {
141  return "In-flight";
142 
143  } else if (synapse->ready) {
144  return "Ready";
145  }
146  return "Pending";
147 }
148 
149 // List action IDs of inputs in graph that haven't completed successfully
150 static char *
151 synapse_pending_inputs(crm_graph_t *graph, synapse_t *synapse)
152 {
153  char *pending = NULL;
154 
155  for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
156  crm_action_t *input = (crm_action_t *) lpc->data;
157 
158  if (input->failed) {
159  pending = pcmk__add_word(pending, ID(input->xml));
160 
161  } else if (input->confirmed) {
162  // Confirmed successful inputs are not pending
163 
164  } else if (find_action(graph, input->id) != NULL) {
165  // In-flight or pending
166  pending = pcmk__add_word(pending, ID(input->xml));
167  }
168  }
169  if (pending == NULL) {
170  pending = strdup("none");
171  }
172  return pending;
173 }
174 
175 // Log synapse inputs that aren't in graph
176 static void
177 log_unresolved_inputs(unsigned int log_level, crm_graph_t *graph,
178  synapse_t *synapse)
179 {
180  for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
181  crm_action_t *input = (crm_action_t *) lpc->data;
182  const char *key = crm_element_value(input->xml, XML_LRM_ATTR_TASK_KEY);
183  const char *host = crm_element_value(input->xml, XML_LRM_ATTR_TARGET);
184 
185  if (find_action(graph, input->id) == NULL) {
186  do_crm_log(log_level,
187  " * [Input %2d]: Unresolved dependency %s op %s%s%s",
188  input->id, actiontype2text(input->type), key,
189  (host? " on " : ""), (host? host : ""));
190  }
191  }
192 }
193 
194 static void
195 log_synapse_action(unsigned int log_level, synapse_t *synapse,
196  crm_action_t *action, const char *pending_inputs)
197 {
198  const char *key = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
199  const char *host = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
200  char *desc = crm_strdup_printf("%s %s op %s",
201  synapse_state_str(synapse),
202  actiontype2text(action->type), key);
203 
204  do_crm_log(log_level,
205  "[Action %4d]: %-50s%s%s (priority: %d, waiting: %s)",
206  action->id, desc, (host? " on " : ""), (host? host : ""),
207  synapse->priority, pending_inputs);
208  free(desc);
209 }
210 
211 static void
212 print_synapse(unsigned int log_level, crm_graph_t * graph, synapse_t * synapse)
213 {
214  char *pending = NULL;
215 
216  if (!synapse->executed) {
217  pending = synapse_pending_inputs(graph, synapse);
218  }
219  for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
220  log_synapse_action(log_level, synapse, (crm_action_t *) lpc->data,
221  pending);
222  }
223  free(pending);
224  if (!synapse->executed) {
225  log_unresolved_inputs(log_level, graph, synapse);
226  }
227 }
228 
229 void
230 print_action(int log_level, const char *prefix, crm_action_t * action)
231 {
232  print_synapse(log_level, NULL, action->synapse);
233 }
234 
235 void
236 print_graph(unsigned int log_level, crm_graph_t * graph)
237 {
238  GListPtr lpc = NULL;
239 
240  if (graph == NULL || graph->num_actions == 0) {
241  if (log_level == LOG_TRACE) {
242  crm_debug("Empty transition graph");
243  }
244  return;
245  }
246 
247  do_crm_log(log_level, "Graph %d with %d actions:"
248  " batch-limit=%d jobs, network-delay=%ums",
249  graph->id, graph->num_actions,
250  graph->batch_limit, graph->network_delay);
251 
252  for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
253  synapse_t *synapse = (synapse_t *) lpc->data;
254 
255  print_synapse(log_level, graph, synapse);
256  }
257 }
258 
259 static const char *
260 abort2text(enum transition_action abort_action)
261 {
262  switch (abort_action) {
263  case tg_done:
264  return "done";
265  case tg_stop:
266  return "stop";
267  case tg_restart:
268  return "restart";
269  case tg_shutdown:
270  return "shutdown";
271  }
272  return "unknown";
273 }
274 
275 bool
276 update_abort_priority(crm_graph_t * graph, int priority,
277  enum transition_action action, const char *abort_reason)
278 {
279  bool change = FALSE;
280 
281  if (graph == NULL) {
282  return change;
283  }
284 
285  if (graph->abort_priority < priority) {
286  crm_debug("Abort priority upgraded from %d to %d", graph->abort_priority, priority);
287  graph->abort_priority = priority;
288  if (graph->abort_reason != NULL) {
289  crm_debug("'%s' abort superseded by %s", graph->abort_reason, abort_reason);
290  }
291  graph->abort_reason = abort_reason;
292  change = TRUE;
293  }
294 
295  if (graph->completion_action < action) {
296  crm_debug("Abort action %s superseded by %s: %s",
297  abort2text(graph->completion_action), abort2text(action), abort_reason);
298  graph->completion_action = action;
299  change = TRUE;
300  }
301 
302  return change;
303 }
#define LOG_TRACE
Definition: logging.h:36
gboolean(* pseudo)(crm_graph_t *graph, crm_action_t *action)
GListPtr actions
gboolean confirmed
A dumping ground.
bool update_abort_priority(crm_graph_t *graph, int priority, enum transition_action action, const char *abort_reason)
action_type_e type
#define INFINITY
Definition: crm.h:95
enum transition_action completion_action
void print_graph(unsigned int log_level, crm_graph_t *graph)
transition_status
gboolean(* rsc)(crm_graph_t *graph, crm_action_t *action)
AIS_Host host
Definition: internal.h:84
gboolean ready
const char * action
Definition: pcmk_fence.c:29
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:261
void print_action(int log_level, const char *prefix, crm_action_t *action)
#define crm_debug(fmt, args...)
Definition: logging.h:368
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:522
#define crm_trace(fmt, args...)
Definition: logging.h:369
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:150
void set_default_graph_functions(void)
Wrappers for and extensions to libxml2.
gboolean(* crmd)(crm_graph_t *graph, crm_action_t *action)
gboolean update_graph(crm_graph_t *graph, crm_action_t *action)
GListPtr synapses
const char * actiontype2text(action_type_e type)
GListPtr inputs
gboolean failed
long long crm_parse_ll(const char *text, const char *default_text)
Parse a long long integer value from a string.
Definition: strings.c:100
#define crm_err(fmt, args...)
Definition: logging.h:363
gboolean(* stonith)(crm_graph_t *graph, crm_action_t *action)
#define CRM_ASSERT(expr)
Definition: results.h:42
crm_graph_functions_t default_fns
transition_action
char * pcmk__add_word(char *list, const char *word)
Definition: strings.c:517
gboolean confirmed
action_type_e
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:262
#define ID(x)
Definition: msg_xml.h:418
void set_graph_functions(crm_graph_functions_t *fns)
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
gboolean executed
GList * GListPtr
Definition: crm.h:214
#define crm_info(fmt, args...)
Definition: logging.h:366
synapse_t * synapse
const char * abort_reason
crm_graph_functions_t * graph_fns
enum crm_ais_msg_types type
Definition: internal.h:83