This source file includes following definitions.
- pseudo_action_dummy
- set_default_graph_functions
- set_graph_functions
- transition_status
- actiontype2text
- find_action
- print_synapse
- print_action
- print_graph
- abort2text
- update_abort_priority
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
26
27
28 extern crm_graph_functions_t *graph_fns;
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
56 crm_graph_functions_t default_fns = {
57 pseudo_action_dummy,
58 pseudo_action_dummy,
59 pseudo_action_dummy,
60 pseudo_action_dummy
61 };
62
63 void
64 set_default_graph_functions(void)
65 {
66 graph_fns = &default_fns;
67 }
68
69 void
70 set_graph_functions(crm_graph_functions_t * fns)
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 *
83 transition_status(enum transition_status state)
84 {
85 switch (state) {
86 case transition_active:
87 return "active";
88 case transition_pending:
89 return "pending";
90 case transition_complete:
91 return "complete";
92 case transition_stopped:
93 return "stopped";
94 case transition_terminated:
95 return "terminated";
96 case transition_action_failed:
97 return "failed (action)";
98 case transition_failed:
99 return "failed";
100 }
101 return "unknown";
102 }
103
104 const char *
105 actiontype2text(action_type_e type)
106 {
107 switch (type) {
108 case action_type_pseudo:
109 return "pseudo";
110 case action_type_rsc:
111 return "rsc";
112 case action_type_crm:
113 return "crm";
114
115 }
116 return "<unknown>";
117 }
118
119 static crm_action_t *
120 find_action(crm_graph_t * graph, int id)
121 {
122 GListPtr sIter = NULL;
123
124 if (graph == NULL) {
125 return NULL;
126 }
127
128 for (sIter = graph->synapses; sIter != NULL; sIter = sIter->next) {
129 GListPtr aIter = NULL;
130 synapse_t *synapse = (synapse_t *) sIter->data;
131
132 for (aIter = synapse->actions; aIter != NULL; aIter = aIter->next) {
133 crm_action_t *action = (crm_action_t *) aIter->data;
134
135 if (action->id == id) {
136 return action;
137 }
138 }
139 }
140 return NULL;
141 }
142
143 static void
144 print_synapse(unsigned int log_level, crm_graph_t * graph, synapse_t * synapse)
145 {
146 GListPtr lpc = NULL;
147 char *pending = NULL;
148 const char *state = "Pending";
149
150 if (synapse->failed) {
151 state = "Failed";
152
153 } else if (synapse->confirmed) {
154 state = "Completed";
155
156 } else if (synapse->executed) {
157 state = "In-flight";
158
159 } else if (synapse->ready) {
160 state = "Ready";
161 }
162
163 if (synapse->executed == FALSE) {
164 for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
165 crm_action_t *input = (crm_action_t *) lpc->data;
166 const char *id_string = crm_element_value(input->xml, XML_ATTR_ID);
167
168 if (input->failed) {
169 pending = add_list_element(pending, id_string);
170
171 } else if (input->confirmed) {
172
173
174 } else if (find_action(graph, input->id)) {
175
176 pending = add_list_element(pending, id_string);
177 }
178 }
179 }
180
181 for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
182 crm_action_t *action = (crm_action_t *) lpc->data;
183 const char *key = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
184 const char *host = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
185 char *desc = crm_strdup_printf("%s %s op %s", state, actiontype2text(action->type), key);
186
187 do_crm_log(log_level,
188 "[Action %4d]: %-50s on %s (priority: %d, waiting: %s)",
189 action->id, desc, host ? host : "N/A",
190 synapse->priority, pending ? pending : "none");
191
192 free(desc);
193 }
194
195 if (synapse->executed == FALSE) {
196 for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
197 crm_action_t *input = (crm_action_t *) lpc->data;
198 const char *key = crm_element_value(input->xml, XML_LRM_ATTR_TASK_KEY);
199 const char *host = crm_element_value(input->xml, XML_LRM_ATTR_TARGET);
200
201 if (find_action(graph, input->id) == NULL) {
202 if (host == NULL) {
203 do_crm_log(log_level, " * [Input %2d]: Unresolved dependency %s op %s",
204 input->id, actiontype2text(input->type), key);
205 } else {
206 do_crm_log(log_level, " * [Input %2d]: Unresolved dependency %s op %s on %s",
207 input->id, actiontype2text(input->type), key, host);
208 }
209 }
210 }
211 }
212
213 free(pending);
214 }
215
216 void
217 print_action(int log_level, const char *prefix, crm_action_t * action)
218 {
219 print_synapse(log_level, NULL, action->synapse);
220 }
221
222 void
223 print_graph(unsigned int log_level, crm_graph_t * graph)
224 {
225 GListPtr lpc = NULL;
226
227 if (graph == NULL || graph->num_actions == 0) {
228 if (log_level > LOG_DEBUG) {
229 crm_debug("Empty transition graph");
230 }
231 return;
232 }
233
234 do_crm_log(log_level, "Graph %d with %d actions:"
235 " batch-limit=%d jobs, network-delay=%dms",
236 graph->id, graph->num_actions,
237 graph->batch_limit, graph->network_delay);
238
239 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
240 synapse_t *synapse = (synapse_t *) lpc->data;
241
242 print_synapse(log_level, graph, synapse);
243 }
244 }
245
246 static const char *
247 abort2text(enum transition_action abort_action)
248 {
249 switch (abort_action) {
250 case tg_done:
251 return "done";
252 case tg_stop:
253 return "stop";
254 case tg_restart:
255 return "restart";
256 case tg_shutdown:
257 return "shutdown";
258 }
259 return "unknown";
260 }
261
262 bool
263 update_abort_priority(crm_graph_t * graph, int priority,
264 enum transition_action action, const char *abort_reason)
265 {
266 bool change = FALSE;
267
268 if (graph == NULL) {
269 return change;
270 }
271
272 if (graph->abort_priority < priority) {
273 crm_debug("Abort priority upgraded from %d to %d", graph->abort_priority, priority);
274 graph->abort_priority = priority;
275 if (graph->abort_reason != NULL) {
276 crm_debug("'%s' abort superseded by %s", graph->abort_reason, abort_reason);
277 }
278 graph->abort_reason = abort_reason;
279 change = TRUE;
280 }
281
282 if (graph->completion_action < action) {
283 crm_debug("Abort action %s superseded by %s: %s",
284 abort2text(graph->completion_action), abort2text(action), abort_reason);
285 graph->completion_action = action;
286 change = TRUE;
287 }
288
289 return change;
290 }