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 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
46 crm_graph_functions_t default_fns = {
47 pseudo_action_dummy,
48 pseudo_action_dummy,
49 pseudo_action_dummy,
50 pseudo_action_dummy
51 };
52
53 void
54 set_default_graph_functions(void)
55 {
56 graph_fns = &default_fns;
57 }
58
59 void
60 set_graph_functions(crm_graph_functions_t * fns)
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);
69 CRM_ASSERT(graph_fns->stonith != NULL);
70 }
71
72 const char *
73 transition_status(enum transition_status state)
74 {
75 switch (state) {
76 case transition_active:
77 return "active";
78 case transition_pending:
79 return "pending";
80 case transition_complete:
81 return "complete";
82 case transition_stopped:
83 return "stopped";
84 case transition_terminated:
85 return "terminated";
86 case transition_action_failed:
87 return "failed (action)";
88 case transition_failed:
89 return "failed";
90 }
91 return "unknown";
92 }
93
94 const char *
95 actiontype2text(action_type_e type)
96 {
97 switch (type) {
98 case action_type_pseudo:
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
108 static crm_action_t *
109 find_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
132 static const char *
133 synapse_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
151 static char *
152 synapse_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
165
166 } else if (find_action(graph, input->id) != NULL) {
167
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
178 static void
179 log_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
196 static void
197 log_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);
201 const char *host = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
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
213 static void
214 print_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
231 void
232 print_action(int log_level, const char *prefix, crm_action_t * action)
233 {
234 print_synapse(log_level, NULL, action->synapse);
235 }
236
237 void
238 print_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
261 static const char *
262 abort2text(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
277 bool
278 update_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 }