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