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