This source file includes following definitions.
- rsc_is_known_on
- order_start_vs_fencing
- order_stop_vs_fencing
- rsc_stonith_ordering
- pcmk__order_vs_fence
- pcmk__order_vs_unfence
- pcmk__fence_guest
- pcmk__node_unfenced
- pcmk__order_restart_vs_unfence
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 rsc_is_known_on(const pcmk_resource_t *rsc, const pcmk_node_t *node)
30 {
31 const pcmk_resource_t *parent = rsc->priv->parent;
32
33 if (g_hash_table_lookup(rsc->priv->probed_nodes,
34 node->priv->id) != NULL) {
35 return TRUE;
36
37 } else if (pcmk__is_primitive(rsc) && pcmk__is_anonymous_clone(parent)
38 && (g_hash_table_lookup(parent->priv->probed_nodes,
39 node->priv->id) != NULL)) {
40
41
42
43
44 return TRUE;
45 }
46 return FALSE;
47 }
48
49
50
51
52
53
54
55
56 static void
57 order_start_vs_fencing(pcmk_resource_t *rsc, pcmk_action_t *stonith_op)
58 {
59 pcmk_node_t *target;
60
61 CRM_CHECK(stonith_op && stonith_op->node, return);
62 target = stonith_op->node;
63
64 for (GList *iter = rsc->priv->actions; iter != NULL; iter = iter->next) {
65 pcmk_action_t *action = iter->data;
66
67 switch (action->needs) {
68 case pcmk__requires_nothing:
69
70 break;
71
72 case pcmk__requires_fencing:
73 order_actions(stonith_op, action, pcmk__ar_ordered);
74 break;
75
76 case pcmk__requires_quorum:
77 if (pcmk__str_eq(action->task, PCMK_ACTION_START,
78 pcmk__str_none)
79 && (g_hash_table_lookup(rsc->priv->allowed_nodes,
80 target->priv->id) != NULL)
81 && !rsc_is_known_on(rsc, target)) {
82
83
84
85
86
87
88
89
90
91
92 pcmk__rsc_debug(rsc, "Ordering %s after %s recovery",
93 action->uuid, pcmk__node_name(target));
94 order_actions(stonith_op, action,
95 pcmk__ar_ordered
96 |pcmk__ar_unrunnable_first_blocks);
97 }
98 break;
99 }
100 }
101 }
102
103
104
105
106
107
108
109
110 static void
111 order_stop_vs_fencing(pcmk_resource_t *rsc, pcmk_action_t *stonith_op)
112 {
113 GList *iter = NULL;
114 GList *action_list = NULL;
115 bool order_implicit = false;
116
117 pcmk_resource_t *top = uber_parent(rsc);
118 pcmk_action_t *parent_stop = NULL;
119 pcmk_node_t *target;
120
121 CRM_CHECK(stonith_op && stonith_op->node, return);
122 target = stonith_op->node;
123
124
125 action_list = pe__resource_actions(rsc, target, PCMK_ACTION_STOP, FALSE);
126
127
128
129
130
131
132
133 if (pcmk_is_set(rsc->flags, pcmk__rsc_needs_fencing)
134 || pcmk__is_guest_or_bundle_node(target)) {
135
136 order_implicit = true;
137 }
138
139 if (action_list && order_implicit) {
140 parent_stop = find_first_action(top->priv->actions, NULL,
141 PCMK_ACTION_STOP, NULL);
142 }
143
144 for (iter = action_list; iter != NULL; iter = iter->next) {
145 pcmk_action_t *action = iter->data;
146
147
148 pcmk__set_action_flags(action,
149 pcmk__action_pseudo|pcmk__action_runnable);
150
151 if (order_implicit) {
152
153
154
155
156
157
158
159
160
161
162
163
164 if (!pcmk__is_bundled(rsc)) {
165 order_actions(stonith_op, action, pcmk__ar_guest_allowed);
166 }
167 order_actions(stonith_op, parent_stop, pcmk__ar_guest_allowed);
168 }
169
170 if (pcmk_is_set(rsc->flags, pcmk__rsc_failed)) {
171 crm_notice("Stop of failed resource %s is implicit %s %s is fenced",
172 rsc->id, (order_implicit? "after" : "because"),
173 pcmk__node_name(target));
174 } else {
175 crm_info("%s is implicit %s %s is fenced",
176 action->uuid, (order_implicit? "after" : "because"),
177 pcmk__node_name(target));
178 }
179
180 if (pcmk_is_set(rsc->flags, pcmk__rsc_notify)) {
181 pe__order_notifs_after_fencing(action, rsc, stonith_op);
182 }
183
184 #if 0
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 crm_info("Moving healthy resource %s off %s before fencing",
204 rsc->id, pcmk__node_name(node));
205 pcmk__new_ordering(rsc, stop_key(rsc), NULL, NULL,
206 strdup(PCMK_ACTION_STONITH), stonith_op,
207 pcmk__ar_ordered, rsc->private->scheduler);
208 #endif
209 }
210
211 g_list_free(action_list);
212
213
214 action_list = pe__resource_actions(rsc, target, PCMK_ACTION_DEMOTE, FALSE);
215
216 for (iter = action_list; iter != NULL; iter = iter->next) {
217 pcmk_action_t *action = iter->data;
218
219 if (!(action->node->details->online) || action->node->details->unclean
220 || pcmk_is_set(rsc->flags, pcmk__rsc_failed)) {
221
222 if (pcmk_is_set(rsc->flags, pcmk__rsc_failed)) {
223 pcmk__rsc_info(rsc,
224 "Demote of failed resource %s is implicit "
225 "after %s is fenced",
226 rsc->id, pcmk__node_name(target));
227 } else {
228 pcmk__rsc_info(rsc, "%s is implicit after %s is fenced",
229 action->uuid, pcmk__node_name(target));
230 }
231
232
233
234
235 pcmk__set_action_flags(action,
236 pcmk__action_pseudo|pcmk__action_runnable);
237
238 if (pcmk__is_bundled(rsc)) {
239
240
241 } else if (order_implicit) {
242 order_actions(stonith_op, action,
243 pcmk__ar_guest_allowed|pcmk__ar_ordered);
244 }
245 }
246 }
247
248 g_list_free(action_list);
249 }
250
251
252
253
254
255
256
257
258 static void
259 rsc_stonith_ordering(pcmk_resource_t *rsc, pcmk_action_t *stonith_op)
260 {
261 if (rsc->priv->children != NULL) {
262
263 for (GList *iter = rsc->priv->children;
264 iter != NULL; iter = iter->next) {
265
266 pcmk_resource_t *child_rsc = iter->data;
267
268 rsc_stonith_ordering(child_rsc, stonith_op);
269 }
270
271 } else if (!pcmk_is_set(rsc->flags, pcmk__rsc_managed)) {
272 pcmk__rsc_trace(rsc,
273 "Skipping fencing constraints for unmanaged resource: "
274 "%s", rsc->id);
275
276 } else {
277 order_start_vs_fencing(rsc, stonith_op);
278 order_stop_vs_fencing(rsc, stonith_op);
279 }
280 }
281
282
283
284
285
286
287
288
289
290
291
292
293 void
294 pcmk__order_vs_fence(pcmk_action_t *stonith_op, pcmk_scheduler_t *scheduler)
295 {
296 CRM_CHECK(stonith_op && scheduler, return);
297 for (GList *r = scheduler->priv->resources; r != NULL; r = r->next) {
298 rsc_stonith_ordering((pcmk_resource_t *) r->data, stonith_op);
299 }
300 }
301
302
303
304
305
306
307
308
309
310
311 void
312 pcmk__order_vs_unfence(const pcmk_resource_t *rsc, pcmk_node_t *node,
313 pcmk_action_t *action,
314 enum pcmk__action_relation_flags order)
315 {
316
317
318
319
320
321
322
323 if ((pcmk_is_set(rsc->flags, pcmk__rsc_fence_device)
324 && pcmk_is_set(rsc->priv->scheduler->flags,
325 pcmk__sched_enable_unfencing))
326 || pcmk_is_set(rsc->flags, pcmk__rsc_needs_unfencing)) {
327
328
329
330
331
332 pcmk_action_t *unfence = pe_fence_op(node, PCMK_ACTION_ON, TRUE, NULL,
333 FALSE, node->priv->scheduler);
334
335 order_actions(unfence, action, order);
336
337 if (!pcmk__node_unfenced(node)) {
338
339 char *reason = crm_strdup_printf("required by %s %s",
340 rsc->id, action->task);
341
342 trigger_unfencing(NULL, node, reason, NULL,
343 node->priv->scheduler);
344 free(reason);
345 }
346 }
347 }
348
349
350
351
352
353
354
355 void
356 pcmk__fence_guest(pcmk_node_t *node)
357 {
358 pcmk_resource_t *launcher = NULL;
359 pcmk_action_t *stop = NULL;
360 pcmk_action_t *stonith_op = NULL;
361
362
363
364
365
366
367
368 const char *fence_action = PCMK_ACTION_OFF;
369
370 pcmk__assert(node != NULL);
371
372
373
374
375 launcher = node->priv->remote->priv->launcher;
376 if (launcher != NULL) {
377 stop = find_first_action(launcher->priv->actions, NULL,
378 PCMK_ACTION_STOP, NULL);
379
380 if (find_first_action(launcher->priv->actions, NULL,
381 PCMK_ACTION_START, NULL)) {
382 fence_action = PCMK_ACTION_REBOOT;
383 }
384 }
385
386
387
388
389 stonith_op = pe_fence_op(node, fence_action, FALSE, "guest is unclean",
390 FALSE, node->priv->scheduler);
391 pcmk__set_action_flags(stonith_op,
392 pcmk__action_pseudo|pcmk__action_runnable);
393
394
395
396
397
398 if ((stop != NULL) && pcmk_is_set(stop->flags, pcmk__action_pseudo)) {
399 pcmk_action_t *parent_stonith_op = pe_fence_op(stop->node, NULL, FALSE,
400 NULL, FALSE,
401 node->priv->scheduler);
402
403 crm_info("Implying guest %s is down (action %d) after %s fencing",
404 pcmk__node_name(node), stonith_op->id,
405 pcmk__node_name(stop->node));
406 order_actions(parent_stonith_op, stonith_op,
407 pcmk__ar_unrunnable_first_blocks
408 |pcmk__ar_first_implies_then);
409
410 } else if (stop) {
411 order_actions(stop, stonith_op,
412 pcmk__ar_unrunnable_first_blocks
413 |pcmk__ar_first_implies_then);
414 crm_info("Implying guest %s is down (action %d) "
415 "after launcher %s is stopped (action %d)",
416 pcmk__node_name(node), stonith_op->id,
417 launcher->id, stop->id);
418 } else {
419
420
421
422
423
424
425
426 stop = find_first_action(node->priv->remote->priv->actions,
427 NULL, PCMK_ACTION_STOP, NULL);
428
429 if (stop) {
430 order_actions(stop, stonith_op, pcmk__ar_ordered);
431 crm_info("Implying guest %s is down (action %d) "
432 "after connection is stopped (action %d)",
433 pcmk__node_name(node), stonith_op->id, stop->id);
434 } else {
435
436
437
438 crm_info("Implying guest %s is down (action %d) ",
439 pcmk__node_name(node), stonith_op->id);
440 }
441 }
442
443
444 pcmk__order_vs_fence(stonith_op, node->priv->scheduler);
445 }
446
447
448
449
450
451
452
453
454
455
456 bool
457 pcmk__node_unfenced(const pcmk_node_t *node)
458 {
459 const char *unfenced = pcmk__node_attr(node, CRM_ATTR_UNFENCED, NULL,
460 pcmk__rsc_node_current);
461
462 return !pcmk__str_eq(unfenced, "0", pcmk__str_null_matches);
463 }
464
465
466
467
468
469
470
471
472 void
473 pcmk__order_restart_vs_unfence(gpointer data, gpointer user_data)
474 {
475 pcmk_node_t *node = (pcmk_node_t *) data;
476 pcmk_resource_t *rsc = (pcmk_resource_t *) user_data;
477
478 pcmk_action_t *unfence = pe_fence_op(node, PCMK_ACTION_ON, true, NULL,
479 false, rsc->priv->scheduler);
480
481 crm_debug("Ordering any stops of %s before %s, and any starts after",
482 rsc->id, unfence->uuid);
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499 pcmk__new_ordering(rsc, stop_key(rsc), NULL,
500 NULL, strdup(unfence->uuid), unfence,
501 pcmk__ar_ordered|pcmk__ar_if_on_same_node,
502 rsc->priv->scheduler);
503
504 pcmk__new_ordering(NULL, strdup(unfence->uuid), unfence,
505 rsc, start_key(rsc), NULL,
506 pcmk__ar_first_implies_same_node_then
507 |pcmk__ar_if_on_same_node,
508 rsc->priv->scheduler);
509 }