pacemaker  1.1.24-3850484742
Scalable High-Availability cluster resource manager
utils.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <crm_internal.h>
20 
21 #include <crm/crm.h>
22 #include <crm/msg_xml.h>
23 #include <crm/common/xml.h>
24 #include <crm/transition.h>
25 /* #include <sys/param.h> */
26 /* */
27 
29 
30 static gboolean
31 pseudo_action_dummy(crm_graph_t * graph, crm_action_t * action)
32 {
33  static int fail = -1;
34 
35  if (fail < 0) {
36  char *fail_s = getenv("PE_fail");
37 
38  if (fail_s) {
39  fail = crm_int_helper(fail_s, NULL);
40  } else {
41  fail = 0;
42  }
43  }
44 
45  crm_trace("Dummy event handler: action %d executed", action->id);
46  if (action->id == fail) {
47  crm_err("Dummy event handler: pretending action %d failed", action->id);
48  action->failed = TRUE;
49  graph->abort_priority = INFINITY;
50  }
51  action->confirmed = TRUE;
52  update_graph(graph, action);
53  return TRUE;
54 }
55 
57  pseudo_action_dummy,
58  pseudo_action_dummy,
59  pseudo_action_dummy,
60  pseudo_action_dummy
61 };
62 
63 void
65 {
66  graph_fns = &default_fns;
67 }
68 
69 void
71 {
72  crm_info("Setting custom graph functions");
73  graph_fns = fns;
74 
75  CRM_ASSERT(graph_fns != NULL);
76  CRM_ASSERT(graph_fns->rsc != NULL);
77  CRM_ASSERT(graph_fns->crmd != NULL);
78  CRM_ASSERT(graph_fns->pseudo != NULL);
79  CRM_ASSERT(graph_fns->stonith != NULL);
80 }
81 
82 const char *
84 {
85  switch (state) {
86  case transition_active:
87  return "active";
88  case transition_pending:
89  return "pending";
91  return "complete";
92  case transition_stopped:
93  return "stopped";
95  return "terminated";
97  return "failed (action)";
98  case transition_failed:
99  return "failed";
100  }
101  return "unknown";
102 }
103 
104 const char *
106 {
107  switch (type) {
108  case action_type_pseudo:
109  return "pseudo";
110  case action_type_rsc:
111  return "resource";
112  case action_type_crm:
113  return "cluster";
114  }
115  return "invalid";
116 }
117 
118 static crm_action_t *
119 find_action(crm_graph_t * graph, int id)
120 {
121  GListPtr sIter = NULL;
122 
123  if (graph == NULL) {
124  return NULL;
125  }
126 
127  for (sIter = graph->synapses; sIter != NULL; sIter = sIter->next) {
128  GListPtr aIter = NULL;
129  synapse_t *synapse = (synapse_t *) sIter->data;
130 
131  for (aIter = synapse->actions; aIter != NULL; aIter = aIter->next) {
132  crm_action_t *action = (crm_action_t *) aIter->data;
133 
134  if (action->id == id) {
135  return action;
136  }
137  }
138  }
139  return NULL;
140 }
141 
142 static const char *
143 synapse_state_str(synapse_t *synapse)
144 {
145  if (synapse->failed) {
146  return "Failed";
147 
148  } else if (synapse->confirmed) {
149  return "Completed";
150 
151  } else if (synapse->executed) {
152  return "In-flight";
153 
154  } else if (synapse->ready) {
155  return "Ready";
156  }
157  return "Pending";
158 }
159 
160 // List action IDs of inputs in graph that haven't completed successfully
161 static char *
162 synapse_pending_inputs(crm_graph_t *graph, synapse_t *synapse)
163 {
164  char *pending = NULL;
165 
166  for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
167  crm_action_t *input = (crm_action_t *) lpc->data;
168 
169  if (input->failed) {
170  pending = add_list_element(pending, ID(input->xml));
171 
172  } else if (input->confirmed) {
173  // Confirmed successful inputs are not pending
174 
175  } else if (find_action(graph, input->id) != NULL) {
176  // In-flight or pending
177  pending = add_list_element(pending, ID(input->xml));
178  }
179  }
180  if (pending == NULL) {
181  pending = strdup("none");
182  }
183  return pending;
184 }
185 
186 // Log synapse inputs that aren't in graph
187 static void
188 log_unresolved_inputs(unsigned int log_level, crm_graph_t *graph,
189  synapse_t *synapse)
190 {
191  for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
192  crm_action_t *input = (crm_action_t *) lpc->data;
193  const char *key = crm_element_value(input->xml, XML_LRM_ATTR_TASK_KEY);
194  const char *host = crm_element_value(input->xml, XML_LRM_ATTR_TARGET);
195 
196  if (find_action(graph, input->id) == NULL) {
197  do_crm_log(log_level,
198  " * [Input %2d]: Unresolved dependency %s op %s%s%s",
199  input->id, actiontype2text(input->type), key,
200  (host? " on " : ""), (host? host : ""));
201  }
202  }
203 }
204 
205 static void
206 log_synapse_action(unsigned int log_level, synapse_t *synapse,
207  crm_action_t *action, const char *pending_inputs)
208 {
209  const char *key = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
210  const char *host = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
211  char *desc = crm_strdup_printf("%s %s op %s",
212  synapse_state_str(synapse),
213  actiontype2text(action->type), key);
214 
215  do_crm_log(log_level,
216  "[Action %4d]: %-50s%s%s (priority: %d, waiting: %s)",
217  action->id, desc, (host? " on " : ""), (host? host : ""),
218  synapse->priority, pending_inputs);
219  free(desc);
220 }
221 
222 static void
223 print_synapse(unsigned int log_level, crm_graph_t * graph, synapse_t * synapse)
224 {
225  char *pending = NULL;
226 
227  if (!synapse->executed) {
228  pending = synapse_pending_inputs(graph, synapse);
229  }
230  for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
231  log_synapse_action(log_level, synapse, (crm_action_t *) lpc->data,
232  pending);
233  }
234  free(pending);
235  if (!synapse->executed) {
236  log_unresolved_inputs(log_level, graph, synapse);
237  }
238 }
239 
240 void
241 print_action(int log_level, const char *prefix, crm_action_t * action)
242 {
243  print_synapse(log_level, NULL, action->synapse);
244 }
245 
246 void
247 print_graph(unsigned int log_level, crm_graph_t * graph)
248 {
249  GListPtr lpc = NULL;
250 
251  if (graph == NULL || graph->num_actions == 0) {
252  if (log_level > LOG_DEBUG) {
253  crm_debug("Empty transition graph");
254  }
255  return;
256  }
257 
258  do_crm_log(log_level, "Graph %d with %d actions:"
259  " batch-limit=%d jobs, network-delay=%dms",
260  graph->id, graph->num_actions,
261  graph->batch_limit, graph->network_delay);
262 
263  for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
264  synapse_t *synapse = (synapse_t *) lpc->data;
265 
266  print_synapse(log_level, graph, synapse);
267  }
268 }
269 
270 static const char *
271 abort2text(enum transition_action abort_action)
272 {
273  switch (abort_action) {
274  case tg_done:
275  return "done";
276  case tg_stop:
277  return "stop";
278  case tg_restart:
279  return "restart";
280  case tg_shutdown:
281  return "shutdown";
282  }
283  return "unknown";
284 }
285 
286 bool
287 update_abort_priority(crm_graph_t * graph, int priority,
288  enum transition_action action, const char *abort_reason)
289 {
290  bool change = FALSE;
291 
292  if (graph == NULL) {
293  return change;
294  }
295 
296  if (graph->abort_priority < priority) {
297  crm_debug("Abort priority upgraded from %d to %d", graph->abort_priority, priority);
298  graph->abort_priority = priority;
299  if (graph->abort_reason != NULL) {
300  crm_debug("'%s' abort superseded by %s", graph->abort_reason, abort_reason);
301  }
302  graph->abort_reason = abort_reason;
303  change = TRUE;
304  }
305 
306  if (graph->completion_action < action) {
307  crm_debug("Abort action %s superseded by %s: %s",
308  abort2text(graph->completion_action), abort2text(action), abort_reason);
309  graph->completion_action = action;
310  change = TRUE;
311  }
312 
313  return change;
314 }
GListPtr actions
Definition: transition.h:43
gboolean confirmed
Definition: transition.h:41
A dumping ground.
action_type_e type
Definition: transition.h:52
#define INFINITY
Definition: crm.h:73
enum transition_action completion_action
Definition: transition.h:99
bool update_abort_priority(crm_graph_t *graph, int priority, enum transition_action action, const char *abort_reason)
Definition: utils.c:287
xmlNode * xml
Definition: transition.h:64
long long crm_int_helper(const char *text, char **end_text)
Definition: strings.c:81
gboolean(* stonith)(crm_graph_t *graph, crm_action_t *action)
Definition: transition.h:124
AIS_Host host
Definition: internal.h:80
transition_action
Definition: transition.h:85
gboolean ready
Definition: transition.h:38
#define XML_LRM_ATTR_TASK_KEY
Definition: msg_xml.h:289
int priority
Definition: transition.h:36
crm_graph_functions_t default_fns
Definition: utils.c:56
gboolean(* crmd)(crm_graph_t *graph, crm_action_t *action)
Definition: transition.h:123
#define crm_debug(fmt, args...)
Definition: logging.h:279
char * add_list_element(char *list, const char *value)
Definition: strings.c:426
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:393
const char * actiontype2text(action_type_e type)
Definition: utils.c:105
crm_graph_functions_t * graph_fns
Definition: graph.c:28
#define crm_trace(fmt, args...)
Definition: logging.h:280
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:129
Wrappers for and extensions to libxml2.
transition_status
Definition: transition.h:128
GListPtr synapses
Definition: transition.h:115
gboolean update_graph(crm_graph_t *graph, crm_action_t *action)
Definition: graph.c:102
void print_action(int log_level, const char *prefix, crm_action_t *action)
Definition: utils.c:241
gboolean(* rsc)(crm_graph_t *graph, crm_action_t *action)
Definition: transition.h:122
void print_graph(unsigned int log_level, crm_graph_t *graph)
Definition: utils.c:247
int batch_limit
Definition: transition.h:104
GListPtr inputs
Definition: transition.h:44
gboolean failed
Definition: transition.h:39
const char * transition_status(enum transition_status state)
Definition: utils.c:83
int network_delay
Definition: transition.h:105
int num_actions
Definition: transition.h:101
gboolean failed
Definition: transition.h:61
gboolean(* pseudo)(crm_graph_t *graph, crm_action_t *action)
Definition: transition.h:121
#define crm_err(fmt, args...)
Definition: logging.h:274
void set_graph_functions(crm_graph_functions_t *fns)
Definition: utils.c:70
int abort_priority
Definition: transition.h:95
#define CRM_ASSERT(expr)
Definition: error.h:20
void set_default_graph_functions(void)
Definition: utils.c:64
gboolean confirmed
Definition: transition.h:59
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:290
#define ID(x)
Definition: msg_xml.h:452
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
action_type_e
Definition: transition.h:25
gboolean executed
Definition: transition.h:40
GList * GListPtr
Definition: crm.h:210
#define crm_info(fmt, args...)
Definition: logging.h:277
synapse_t * synapse
Definition: transition.h:55
const char * abort_reason
Definition: transition.h:98
enum crm_ais_msg_types type
Definition: internal.h:79