This source file includes following definitions.
- probe_needed_before_action
- add_probe_orderings_for_stops
- add_restart_orderings_for_probe
- clear_actions_tracking_flag
- add_restart_orderings_for_rsc
- order_then_probes
- pcmk__order_probes
- pcmk__schedule_probes
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <glib.h>
13
14 #include <crm/crm.h>
15 #include <crm/pengine/status.h>
16 #include <pacemaker-internal.h>
17 #include "libpacemaker_private.h"
18
19
20
21
22
23
24
25
26
27
28 static bool
29 probe_needed_before_action(pe_action_t *probe, pe_action_t *then)
30 {
31
32 if (pcmk__str_eq(then->task, CRM_OP_FENCE, pcmk__str_casei)
33 && (probe->node != NULL) && (then->node != NULL)
34 && (probe->node->details == then->node->details)) {
35 const char *op = g_hash_table_lookup(then->meta, "stonith_action");
36
37 if (pcmk__str_eq(op, "on", pcmk__str_casei)) {
38 return false;
39 }
40 }
41
42
43 if (pcmk__str_eq(then->task, CRM_OP_SHUTDOWN, pcmk__str_none)
44 && (probe->node != NULL) && (then->node != NULL)
45 && (probe->node->details != then->node->details)) {
46 return false;
47 }
48
49
50 return true;
51 }
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 static void
67 add_probe_orderings_for_stops(pe_working_set_t *data_set)
68 {
69 for (GList *iter = data_set->ordering_constraints; iter != NULL;
70 iter = iter->next) {
71
72 pe__ordering_t *order = iter->data;
73 enum pe_ordering order_type = pe_order_optional;
74 GList *probes = NULL;
75 GList *then_actions = NULL;
76
77
78 if (order->type == pe_order_none) {
79 continue;
80 }
81
82
83 if ((order->lh_rsc == NULL) || (order->lh_rsc == order->rh_rsc)) {
84 continue;
85 }
86
87
88 if (((order->lh_action == NULL) && (order->lh_action_task == NULL)) ||
89 ((order->rh_action == NULL) && (order->rh_action_task == NULL))) {
90 continue;
91 }
92
93
94 if ((order->lh_action != NULL)
95 && !pcmk__str_eq(order->lh_action->task, RSC_STOP, pcmk__str_none)) {
96 continue;
97 } else if ((order->lh_action == NULL)
98 && !pcmk__ends_with(order->lh_action_task, "_" RSC_STOP "_0")) {
99 continue;
100 }
101
102
103
104
105
106 if ((order->rh_rsc != NULL)
107 && (order->lh_rsc->container == order->rh_rsc)) {
108
109 if ((order->rh_action != NULL)
110 && pcmk__str_eq(order->rh_action->task, RSC_STOP,
111 pcmk__str_none)) {
112 continue;
113 } else if ((order->rh_action == NULL)
114 && pcmk__ends_with(order->rh_action_task,
115 "_" RSC_STOP "_0")) {
116 continue;
117 }
118 }
119
120
121 if (pcmk_is_set(order->type, pe_order_apply_first_non_migratable)) {
122 pe__set_order_flags(order_type,
123 pe_order_apply_first_non_migratable);
124 }
125 if (pcmk_is_set(order->type, pe_order_same_node)) {
126 pe__set_order_flags(order_type, pe_order_same_node);
127 }
128
129
130 if ((order->type == pe_order_anti_colocation)
131 || (order->type == pe_order_load)) {
132 order_type = order->type;
133 }
134
135
136 probes = pe__resource_actions(order->lh_rsc, NULL, RSC_STATUS, FALSE);
137 if (probes == NULL) {
138 continue;
139 }
140
141
142 if (order->rh_action != NULL) {
143 then_actions = g_list_prepend(NULL, order->rh_action);
144
145 } else if (order->rh_rsc != NULL) {
146 then_actions = find_actions(order->rh_rsc->actions,
147 order->rh_action_task, NULL);
148 if (then_actions == NULL) {
149 g_list_free(probes);
150 continue;
151 }
152 }
153
154 crm_trace("Implying 'probe then' orderings for '%s then %s' "
155 "(id=%d, type=%.6x)",
156 order->lh_action? order->lh_action->uuid : order->lh_action_task,
157 order->rh_action? order->rh_action->uuid : order->rh_action_task,
158 order->id, order->type);
159
160 for (GList *probe_iter = probes; probe_iter != NULL;
161 probe_iter = probe_iter->next) {
162
163 pe_action_t *probe = (pe_action_t *) probe_iter->data;
164
165 for (GList *then_iter = then_actions; then_iter != NULL;
166 then_iter = then_iter->next) {
167
168 pe_action_t *then = (pe_action_t *) then_iter->data;
169
170 if (probe_needed_before_action(probe, then)) {
171 order_actions(probe, then, order_type);
172 }
173 }
174 }
175
176 g_list_free(then_actions);
177 g_list_free(probes);
178 }
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 static void
195 add_restart_orderings_for_probe(pe_action_t *probe, pe_action_t *after,
196 pe_working_set_t *data_set)
197 {
198 GList *iter = NULL;
199 bool interleave = false;
200 pe_resource_t *compatible_rsc = NULL;
201
202
203 if ((after == NULL) || (probe == NULL) || (probe->rsc == NULL)
204 || (probe->rsc->variant != pe_native)
205 || !pcmk__str_eq(probe->task, RSC_STATUS, pcmk__str_casei)) {
206 return;
207 }
208
209
210 if (pcmk_is_set(after->flags, pe_action_tracking)) {
211 return;
212 }
213 pe__set_action_flags(after, pe_action_tracking);
214
215 crm_trace("Adding probe restart orderings for '%s@%s then %s@%s'",
216 probe->uuid,
217 ((probe->node == NULL)? "" : probe->node->details->uname),
218 after->uuid,
219 ((after->node == NULL)? "" : after->node->details->uname));
220
221
222
223
224 if ((after->rsc != NULL) && (after->rsc->variant == pe_native)
225 && (probe->rsc != after->rsc)) {
226
227 GList *then_actions = NULL;
228
229 if (pcmk__str_eq(after->task, RSC_START, pcmk__str_casei)) {
230 then_actions = pe__resource_actions(after->rsc, NULL, RSC_STOP,
231 FALSE);
232
233 } else if (pcmk__str_eq(after->task, RSC_PROMOTE, pcmk__str_casei)) {
234 then_actions = pe__resource_actions(after->rsc, NULL,
235 RSC_DEMOTE, FALSE);
236 }
237
238 for (iter = then_actions; iter != NULL; iter = iter->next) {
239 pe_action_t *then = (pe_action_t *) iter->data;
240
241
242 if (!pcmk_is_set(then->flags, pe_action_pseudo)) {
243 order_actions(probe, then, pe_order_optional);
244 }
245 }
246 g_list_free(then_actions);
247 }
248
249
250
251
252 if ((after->rsc != NULL)
253 && (after->rsc->variant > pe_group)) {
254 const char *interleave_s = g_hash_table_lookup(after->rsc->meta,
255 XML_RSC_ATTR_INTERLEAVE);
256
257 interleave = crm_is_true(interleave_s);
258 if (interleave) {
259 compatible_rsc = find_compatible_child(probe->rsc,
260 after->rsc,
261 RSC_ROLE_UNKNOWN,
262 FALSE, data_set);
263 }
264 }
265
266
267
268
269
270 for (iter = after->actions_after; iter != NULL; iter = iter->next) {
271 pe_action_wrapper_t *after_wrapper = (pe_action_wrapper_t *) iter->data;
272
273
274
275
276
277
278
279
280
281 if (!pcmk_is_set(after_wrapper->type, pe_order_implies_then)) {
282
283
284
285
286
287
288
289 if ((after->rsc == NULL)
290 || (after->rsc->variant < pe_group)
291 || (probe->rsc->parent == after->rsc)
292 || (after_wrapper->action->rsc == NULL)
293 || (after_wrapper->action->rsc->variant > pe_group)
294 || (after->rsc != after_wrapper->action->rsc->parent)) {
295 continue;
296 }
297
298
299
300
301 if ((after->rsc->variant > pe_group) && interleave
302 && ((compatible_rsc == NULL)
303 || (compatible_rsc != after_wrapper->action->rsc))) {
304 continue;
305 }
306 }
307
308 crm_trace("Recursively adding probe restart orderings for "
309 "'%s@%s then %s@%s' (type=%#.6x)",
310 after->uuid,
311 ((after->node == NULL)? "" : after->node->details->uname),
312 after_wrapper->action->uuid,
313 ((after_wrapper->action->node == NULL)? "" : after_wrapper->action->node->details->uname),
314 after_wrapper->type);
315
316 add_restart_orderings_for_probe(probe, after_wrapper->action, data_set);
317 }
318 }
319
320
321
322
323
324
325
326 static void
327 clear_actions_tracking_flag(pe_working_set_t *data_set)
328 {
329 GList *gIter = NULL;
330
331 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
332 pe_action_t *action = (pe_action_t *) gIter->data;
333
334 pe__clear_action_flags(action, pe_action_tracking);
335 }
336 }
337
338
339
340
341
342
343
344
345 static void
346 add_restart_orderings_for_rsc(pe_resource_t *rsc, pe_working_set_t *data_set)
347 {
348 GList *probes = NULL;
349
350
351 if (rsc->variant != pe_native) {
352 g_list_foreach(rsc->children, (GFunc) add_restart_orderings_for_rsc,
353 data_set);
354 return;
355 }
356
357
358 probes = pe__resource_actions(rsc, NULL, RSC_STATUS, FALSE);
359
360
361 for (GList *iter = probes; iter != NULL; iter = iter->next) {
362 pe_action_t *probe = (pe_action_t *) iter->data;
363
364 for (GList *then_iter = probe->actions_after; then_iter != NULL;
365 then_iter = then_iter->next) {
366
367 pe_action_wrapper_t *then = (pe_action_wrapper_t *) then_iter->data;
368
369 add_restart_orderings_for_probe(probe, then->action, data_set);
370 clear_actions_tracking_flag(data_set);
371 }
372 }
373
374 g_list_free(probes);
375 }
376
377
378
379
380
381
382
383
384
385 static void
386 order_then_probes(pe_working_set_t *data_set)
387 {
388 #if 0
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418 for (GList *iter = data_set->resources; iter != NULL; iter = iter->next) {
419 pe_resource_t *rsc = (pe_resource_t *) iter->data;
420
421 pe_action_t *start = NULL;
422 GList *actions = NULL;
423 GList *probes = NULL;
424
425 actions = pe__resource_actions(rsc, NULL, RSC_START, FALSE);
426
427 if (actions) {
428 start = actions->data;
429 g_list_free(actions);
430 }
431
432 if (start == NULL) {
433 crm_err("No start action for %s", rsc->id);
434 continue;
435 }
436
437 probes = pe__resource_actions(rsc, NULL, RSC_STATUS, FALSE);
438
439 for (actions = start->actions_before; actions != NULL;
440 actions = actions->next) {
441
442 pe_action_wrapper_t *before = (pe_action_wrapper_t *) actions->data;
443
444 pe_action_t *first = before->action;
445 pe_resource_t *first_rsc = first->rsc;
446
447 if (first->required_runnable_before) {
448 for (GList *clone_actions = first->actions_before;
449 clone_actions != NULL;
450 clone_actions = clone_actions->next) {
451
452 before = (pe_action_wrapper_t *) clone_actions->data;
453
454 crm_trace("Testing '%s then %s' for %s",
455 first->uuid, before->action->uuid, start->uuid);
456
457 CRM_ASSERT(before->action->rsc != NULL);
458 first_rsc = before->action->rsc;
459 break;
460 }
461
462 } else if (!pcmk__str_eq(first->task, RSC_START, pcmk__str_none)) {
463 crm_trace("Not a start op %s for %s", first->uuid, start->uuid);
464 }
465
466 if (first_rsc == NULL) {
467 continue;
468
469 } else if (uber_parent(first_rsc) == uber_parent(start->rsc)) {
470 crm_trace("Same parent %s for %s", first_rsc->id, start->uuid);
471 continue;
472
473 } else if (!pe_rsc_is_clone(uber_parent(first_rsc))) {
474 crm_trace("Not a clone %s for %s", first_rsc->id, start->uuid);
475 continue;
476 }
477
478 crm_err("Applying %s before %s %d", first->uuid, start->uuid,
479 uber_parent(first_rsc)->variant);
480
481 for (GList *probe_iter = probes; probe_iter != NULL;
482 probe_iter = probe_iter->next) {
483
484 pe_action_t *probe = (pe_action_t *) probe_iter->data;
485
486 crm_err("Ordering %s before %s", first->uuid, probe->uuid);
487 order_actions(first, probe, pe_order_optional);
488 }
489 }
490 }
491 #endif
492 }
493
494 void
495 pcmk__order_probes(pe_working_set_t *data_set)
496 {
497
498 g_list_foreach(data_set->resources, (GFunc) add_restart_orderings_for_rsc,
499 data_set);
500 add_probe_orderings_for_stops(data_set);
501
502 order_then_probes(data_set);
503 }
504
505
506
507
508
509
510
511
512
513 void
514 pcmk__schedule_probes(pe_working_set_t *data_set)
515 {
516
517 for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
518 pe_node_t *node = (pe_node_t *) iter->data;
519 const char *probed = NULL;
520
521 if (!node->details->online) {
522 if (pcmk__is_failed_remote_node(node)) {
523 pe_fence_node(data_set, node,
524 "the connection is unrecoverable", FALSE);
525 }
526 continue;
527
528 } else if (node->details->unclean) {
529 continue;
530
531 } else if (!node->details->rsc_discovery_enabled) {
532
533 continue;
534 }
535
536
537
538
539
540
541 probed = pe_node_attribute_raw(node, CRM_OP_PROBED);
542 if (probed != NULL && crm_is_true(probed) == FALSE) {
543 pe_action_t *probe_op = NULL;
544
545 probe_op = custom_action(NULL,
546 crm_strdup_printf("%s-%s", CRM_OP_REPROBE,
547 node->details->uname),
548 CRM_OP_REPROBE, node, FALSE, TRUE,
549 data_set);
550 add_hash_param(probe_op->meta, XML_ATTR_TE_NOWAIT,
551 XML_BOOLEAN_TRUE);
552 continue;
553 }
554
555
556 for (GList *rsc_iter = data_set->resources; rsc_iter != NULL;
557 rsc_iter = rsc_iter->next) {
558 pe_resource_t *rsc = (pe_resource_t *) rsc_iter->data;
559
560 rsc->cmds->create_probe(rsc, node, NULL, FALSE, data_set);
561 }
562 }
563 }