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