This source file includes following definitions.
- update_synapse_ready
- update_synapse_confirmed
- update_graph
- should_fire_synapse
- initiate_action
- fire_synapse
- run_graph
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 crm_graph_functions_t *graph_fns = NULL;
18
19 static gboolean
20 update_synapse_ready(synapse_t * synapse, int action_id)
21 {
22 GListPtr lpc = NULL;
23 gboolean updates = FALSE;
24
25 CRM_CHECK(synapse->executed == FALSE, return FALSE);
26 CRM_CHECK(synapse->confirmed == FALSE, return FALSE);
27
28 synapse->ready = TRUE;
29 for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
30 crm_action_t *prereq = (crm_action_t *) lpc->data;
31
32 crm_trace("Processing input %d", prereq->id);
33
34 if (prereq->id == action_id) {
35 crm_trace("Marking input %d of synapse %d confirmed", action_id, synapse->id);
36 prereq->confirmed = TRUE;
37 updates = TRUE;
38
39 } else if (prereq->confirmed == FALSE) {
40 synapse->ready = FALSE;
41 }
42
43 }
44
45 if (updates) {
46 crm_trace("Updated synapse %d", synapse->id);
47 }
48 return updates;
49 }
50
51 static gboolean
52 update_synapse_confirmed(synapse_t * synapse, int action_id)
53 {
54 GListPtr lpc = NULL;
55 gboolean updates = FALSE;
56 gboolean is_confirmed = TRUE;
57
58 CRM_CHECK(synapse->executed, return FALSE);
59 CRM_CHECK(synapse->confirmed == FALSE, return TRUE);
60
61 is_confirmed = TRUE;
62 for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
63 crm_action_t *action = (crm_action_t *) lpc->data;
64
65 crm_trace("Processing action %d", action->id);
66
67 if (action->id == action_id) {
68 crm_trace("Confirmed: Action %d of Synapse %d", action_id, synapse->id);
69 action->confirmed = TRUE;
70 updates = TRUE;
71
72 } else if (action->confirmed == FALSE) {
73 is_confirmed = FALSE;
74 crm_trace("Synapse %d still not confirmed after action %d", synapse->id, action_id);
75 }
76 }
77
78 if (is_confirmed && synapse->confirmed == FALSE) {
79 crm_trace("Confirmed: Synapse %d", synapse->id);
80 synapse->confirmed = TRUE;
81 updates = TRUE;
82 }
83
84 if (updates) {
85 crm_trace("Updated synapse %d", synapse->id);
86 }
87 return updates;
88 }
89
90 gboolean
91 update_graph(crm_graph_t * graph, crm_action_t * action)
92 {
93 gboolean rc = FALSE;
94 gboolean updates = FALSE;
95 GListPtr lpc = NULL;
96
97 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
98 synapse_t *synapse = (synapse_t *) lpc->data;
99
100 if (synapse->confirmed || synapse->failed) {
101 crm_trace("Synapse complete");
102
103 } else if (synapse->executed) {
104 crm_trace("Synapse executed");
105 rc = update_synapse_confirmed(synapse, action->id);
106
107 } else if (action->failed == FALSE || synapse->priority == INFINITY) {
108 rc = update_synapse_ready(synapse, action->id);
109 }
110 updates = updates || rc;
111 }
112
113 if (updates) {
114 crm_trace("Updated graph with completed action %d", action->id);
115 }
116 return updates;
117 }
118
119 static gboolean
120 should_fire_synapse(crm_graph_t * graph, synapse_t * synapse)
121 {
122 GListPtr lpc = NULL;
123
124 CRM_CHECK(synapse->executed == FALSE, return FALSE);
125 CRM_CHECK(synapse->confirmed == FALSE, return FALSE);
126
127 crm_trace("Checking pre-reqs for synapse %d", synapse->id);
128
129 synapse->ready = TRUE;
130 for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
131 crm_action_t *prereq = (crm_action_t *) lpc->data;
132
133 crm_trace("Processing input %d", prereq->id);
134 if (prereq->confirmed == FALSE) {
135 crm_trace("Input %d for synapse %d not satisfied: not confirmed", prereq->id, synapse->id);
136 synapse->ready = FALSE;
137 break;
138 } else if(prereq->failed && prereq->can_fail == FALSE) {
139 crm_trace("Input %d for synapse %d not satisfied: failed", prereq->id, synapse->id);
140 synapse->ready = FALSE;
141 break;
142 }
143 }
144
145 for (lpc = synapse->actions; synapse->ready && lpc != NULL; lpc = lpc->next) {
146 crm_action_t *a = (crm_action_t *) lpc->data;
147
148 if (a->type == action_type_pseudo) {
149
150
151 } else if (synapse->priority < graph->abort_priority) {
152 crm_trace("Skipping synapse %d: abort level %d", synapse->id, graph->abort_priority);
153 graph->skipped++;
154 return FALSE;
155
156 } else if(graph_fns->allowed && graph_fns->allowed(graph, a) == FALSE) {
157 crm_trace("Deferring synapse %d: allowed", synapse->id);
158 return FALSE;
159 }
160 }
161
162 return synapse->ready;
163 }
164
165 static gboolean
166 initiate_action(crm_graph_t * graph, crm_action_t * action)
167 {
168 const char *id = NULL;
169
170 CRM_CHECK(action->executed == FALSE, return FALSE);
171
172 id = ID(action->xml);
173 CRM_CHECK(id != NULL, return FALSE);
174
175 action->executed = TRUE;
176 if (action->type == action_type_pseudo) {
177 crm_trace("Executing pseudo-event: %s (%d)", id, action->id);
178 return graph_fns->pseudo(graph, action);
179
180 } else if (action->type == action_type_rsc) {
181 crm_trace("Executing rsc-event: %s (%d)", id, action->id);
182 return graph_fns->rsc(graph, action);
183
184 } else if (action->type == action_type_crm) {
185 const char *task = NULL;
186
187 task = crm_element_value(action->xml, XML_LRM_ATTR_TASK);
188 CRM_CHECK(task != NULL, return FALSE);
189
190 if (pcmk__str_eq(task, CRM_OP_FENCE, pcmk__str_casei)) {
191 crm_trace("Executing STONITH-event: %s (%d)", id, action->id);
192 return graph_fns->stonith(graph, action);
193 }
194
195 crm_trace("Executing crm-event: %s (%d)", id, action->id);
196 return graph_fns->crmd(graph, action);
197 }
198
199 crm_err("Failed on unsupported command type: %s (id=%s)", crm_element_name(action->xml), id);
200 return FALSE;
201 }
202
203 static gboolean
204 fire_synapse(crm_graph_t * graph, synapse_t * synapse)
205 {
206 GListPtr lpc = NULL;
207
208 CRM_CHECK(synapse != NULL, return FALSE);
209 CRM_CHECK(synapse->ready, return FALSE);
210 CRM_CHECK(synapse->confirmed == FALSE, return TRUE);
211
212 crm_trace("Synapse %d fired", synapse->id);
213 synapse->executed = TRUE;
214 for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
215 crm_action_t *action = (crm_action_t *) lpc->data;
216
217
218 gboolean passed = FALSE;
219
220
221 passed = initiate_action(graph, action);
222 if (passed == FALSE) {
223 crm_err("Failed initiating <%s id=%d> in synapse %d",
224 crm_element_name(action->xml), action->id, synapse->id);
225 synapse->confirmed = TRUE;
226 action->confirmed = TRUE;
227 action->failed = TRUE;
228 return FALSE;
229 }
230 }
231
232 return TRUE;
233 }
234
235 int
236 run_graph(crm_graph_t * graph)
237 {
238 GListPtr lpc = NULL;
239 int stat_log_level = LOG_DEBUG;
240 int pass_result = transition_active;
241
242 const char *status = "In-progress";
243
244 if (graph_fns == NULL) {
245 set_default_graph_functions();
246 }
247 if (graph == NULL) {
248 return transition_complete;
249 }
250
251 graph->fired = 0;
252 graph->pending = 0;
253 graph->skipped = 0;
254 graph->completed = 0;
255 graph->incomplete = 0;
256 crm_trace("Entering graph %d callback", graph->id);
257
258
259 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
260 synapse_t *synapse = (synapse_t *) lpc->data;
261
262 if (synapse->confirmed) {
263 crm_trace("Synapse %d complete", synapse->id);
264 graph->completed++;
265
266 } else if (synapse->failed == FALSE && synapse->executed) {
267 crm_trace("Synapse %d: confirmation pending", synapse->id);
268 graph->pending++;
269 }
270 }
271
272
273 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
274 synapse_t *synapse = (synapse_t *) lpc->data;
275
276 if (graph->batch_limit > 0 && graph->pending >= graph->batch_limit) {
277 crm_debug("Throttling output: batch limit (%d) reached", graph->batch_limit);
278 break;
279 } else if (synapse->failed) {
280 graph->skipped++;
281 continue;
282
283 } else if (synapse->confirmed || synapse->executed) {
284
285 continue;
286 }
287
288 if (should_fire_synapse(graph, synapse)) {
289 crm_trace("Synapse %d fired", synapse->id);
290 graph->fired++;
291 if(fire_synapse(graph, synapse) == FALSE) {
292 crm_err("Synapse %d failed to fire", synapse->id);
293 stat_log_level = LOG_ERR;
294 graph->abort_priority = INFINITY;
295 graph->incomplete++;
296 graph->fired--;
297 }
298
299 if (synapse->confirmed == FALSE) {
300 graph->pending++;
301 }
302
303 } else {
304 crm_trace("Synapse %d cannot fire", synapse->id);
305 graph->incomplete++;
306 }
307 }
308
309 if (graph->pending == 0 && graph->fired == 0) {
310 graph->complete = TRUE;
311 stat_log_level = LOG_NOTICE;
312 pass_result = transition_complete;
313 status = "Complete";
314
315 if (graph->incomplete != 0 && graph->abort_priority <= 0) {
316 stat_log_level = LOG_WARNING;
317 pass_result = transition_terminated;
318 status = "Terminated";
319
320 } else if (graph->skipped != 0) {
321 status = "Stopped";
322 }
323
324 } else if (graph->fired == 0) {
325 pass_result = transition_pending;
326 }
327
328 do_crm_log(stat_log_level,
329 "Transition %d (Complete=%d, Pending=%d,"
330 " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s",
331 graph->id, graph->completed, graph->pending, graph->fired,
332 graph->skipped, graph->incomplete, graph->source, status);
333
334 return pass_result;
335 }