pacemaker 2.1.1-77db578727
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_trans_graph.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2019 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
20update_synapse_ready(synapse_t * synapse, int action_id)
21{
22 GList *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
51static gboolean
52update_synapse_confirmed(synapse_t * synapse, int action_id)
53{
54 GList *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
90gboolean
92{
93 gboolean rc = FALSE;
94 gboolean updates = FALSE;
95 GList *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
119static gboolean
120should_fire_synapse(crm_graph_t * graph, synapse_t * synapse)
121{
122 GList *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 /* lookup prereqs */
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 /* None of the below applies to pseudo ops */
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
165static gboolean
166initiate_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
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
203static gboolean
204fire_synapse(crm_graph_t * graph, synapse_t * synapse)
205{
206 GList *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 /* allow some leeway */
218 gboolean passed = FALSE;
219
220 /* Invoke the action and start the timer */
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
235int
237{
238 GList *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) {
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 /* Pre-calculate the number of completed and in-flight operations */
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 /* Now check if there is work to do */
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 /* Already handled */
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}
A dumping ground.
#define INFINITY
Definition crm.h:99
#define CRM_OP_FENCE
Definition crm.h:145
#define do_crm_log(level, fmt, args...)
Log a message.
Definition logging.h:159
#define CRM_CHECK(expr, failure_action)
Definition logging.h:218
#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 ID(x)
Definition msg_xml.h:456
#define XML_LRM_ATTR_TASK
Definition msg_xml.h:297
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
int rc
Definition pcmk_fence.c:35
gboolean update_graph(crm_graph_t *graph, crm_action_t *action)
int run_graph(crm_graph_t *graph)
crm_graph_functions_t * graph_fns
@ transition_active
@ transition_complete
@ transition_terminated
@ transition_pending
void set_default_graph_functions(void)
@ action_type_rsc
@ action_type_pseudo
@ action_type_crm
@ pcmk__str_casei
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)
gboolean(* allowed)(crm_graph_t *graph, crm_action_t *action)
gboolean complete
gboolean executed
gboolean ready
gboolean confirmed
GList * actions
gboolean failed
Wrappers for and extensions to libxml2.