This source file includes following definitions.
- pseudo_action_dummy
- set_default_graph_functions
- set_graph_functions
- transition_status
- actiontype2text
- find_action
- synapse_state_str
- synapse_pending_inputs
- log_unresolved_inputs
- log_synapse_action
- print_synapse
- print_action
- print_graph
- abort2text
- update_abort_priority
1
2
3
4
5
6
7
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
17 extern crm_graph_functions_t *graph_fns;
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
45 crm_graph_functions_t default_fns = {
46 pseudo_action_dummy,
47 pseudo_action_dummy,
48 pseudo_action_dummy,
49 pseudo_action_dummy
50 };
51
52 void
53 set_default_graph_functions(void)
54 {
55 graph_fns = &default_fns;
56 }
57
58 void
59 set_graph_functions(crm_graph_functions_t * fns)
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 *
72 transition_status(enum transition_status state)
73 {
74 switch (state) {
75 case transition_active:
76 return "active";
77 case transition_pending:
78 return "pending";
79 case transition_complete:
80 return "complete";
81 case transition_stopped:
82 return "stopped";
83 case transition_terminated:
84 return "terminated";
85 case transition_action_failed:
86 return "failed (action)";
87 case transition_failed:
88 return "failed";
89 }
90 return "unknown";
91 }
92
93 const char *
94 actiontype2text(action_type_e type)
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
150 static char *
151 synapse_pending_inputs(crm_graph_t *graph, synapse_t *synapse)
152 {
153 char *pending = NULL;
154 size_t pending_len = 0;
155
156 for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
157 crm_action_t *input = (crm_action_t *) lpc->data;
158
159 if (input->failed) {
160 pcmk__add_word(&pending, &pending_len, ID(input->xml));
161
162 } else if (input->confirmed) {
163
164
165 } else if (find_action(graph, input->id) != NULL) {
166
167 pcmk__add_word(&pending, &pending_len, ID(input->xml));
168 }
169 }
170 if (pending == NULL) {
171 pending = strdup("none");
172 }
173 return pending;
174 }
175
176
177 static void
178 log_unresolved_inputs(unsigned int log_level, crm_graph_t *graph,
179 synapse_t *synapse)
180 {
181 for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
182 crm_action_t *input = (crm_action_t *) lpc->data;
183 const char *key = crm_element_value(input->xml, XML_LRM_ATTR_TASK_KEY);
184 const char *host = crm_element_value(input->xml, XML_LRM_ATTR_TARGET);
185
186 if (find_action(graph, input->id) == NULL) {
187 do_crm_log(log_level,
188 " * [Input %2d]: Unresolved dependency %s op %s%s%s",
189 input->id, actiontype2text(input->type), key,
190 (host? " on " : ""), (host? host : ""));
191 }
192 }
193 }
194
195 static void
196 log_synapse_action(unsigned int log_level, synapse_t *synapse,
197 crm_action_t *action, const char *pending_inputs)
198 {
199 const char *key = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
200 const char *host = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
201 char *desc = crm_strdup_printf("%s %s op %s",
202 synapse_state_str(synapse),
203 actiontype2text(action->type), key);
204
205 do_crm_log(log_level,
206 "[Action %4d]: %-50s%s%s (priority: %d, waiting: %s)",
207 action->id, desc, (host? " on " : ""), (host? host : ""),
208 synapse->priority, pending_inputs);
209 free(desc);
210 }
211
212 static void
213 print_synapse(unsigned int log_level, crm_graph_t * graph, synapse_t * synapse)
214 {
215 char *pending = NULL;
216
217 if (!synapse->executed) {
218 pending = synapse_pending_inputs(graph, synapse);
219 }
220 for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
221 log_synapse_action(log_level, synapse, (crm_action_t *) lpc->data,
222 pending);
223 }
224 free(pending);
225 if (!synapse->executed) {
226 log_unresolved_inputs(log_level, graph, synapse);
227 }
228 }
229
230 void
231 print_action(int log_level, const char *prefix, crm_action_t * action)
232 {
233 print_synapse(log_level, NULL, action->synapse);
234 }
235
236 void
237 print_graph(unsigned int log_level, crm_graph_t * graph)
238 {
239 GListPtr lpc = NULL;
240
241 if (graph == NULL || graph->num_actions == 0) {
242 if (log_level == LOG_TRACE) {
243 crm_debug("Empty transition graph");
244 }
245 return;
246 }
247
248 do_crm_log(log_level, "Graph %d with %d actions:"
249 " batch-limit=%d jobs, network-delay=%ums",
250 graph->id, graph->num_actions,
251 graph->batch_limit, graph->network_delay);
252
253 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
254 synapse_t *synapse = (synapse_t *) lpc->data;
255
256 print_synapse(log_level, graph, synapse);
257 }
258 }
259
260 static const char *
261 abort2text(enum transition_action abort_action)
262 {
263 switch (abort_action) {
264 case tg_done:
265 return "done";
266 case tg_stop:
267 return "stop";
268 case tg_restart:
269 return "restart";
270 case tg_shutdown:
271 return "shutdown";
272 }
273 return "unknown";
274 }
275
276 bool
277 update_abort_priority(crm_graph_t * graph, int priority,
278 enum transition_action action, const char *abort_reason)
279 {
280 bool change = FALSE;
281
282 if (graph == NULL) {
283 return change;
284 }
285
286 if (graph->abort_priority < priority) {
287 crm_debug("Abort priority upgraded from %d to %d", graph->abort_priority, priority);
288 graph->abort_priority = priority;
289 if (graph->abort_reason != NULL) {
290 crm_debug("'%s' abort superseded by %s", graph->abort_reason, abort_reason);
291 }
292 graph->abort_reason = abort_reason;
293 change = TRUE;
294 }
295
296 if (graph->completion_action < action) {
297 crm_debug("Abort action %s superseded by %s: %s",
298 abort2text(graph->completion_action), abort2text(action), abort_reason);
299 graph->completion_action = action;
300 change = TRUE;
301 }
302
303 return change;
304 }