This source file includes following definitions.
- state2text
- update_action_flags
- check_rsc_parameters
- CancelXmlOp
- check_action_definition
- check_params
- check_actions_for
- find_rsc_list
- check_actions
- apply_placement_constraints
- failcount_clear_action_exists
- check_migration_threshold
- common_apply_stickiness
- complex_set_cmds
- set_alloc_actions
- calculate_system_health
- apply_system_health
- stage0
- probe_resources
- rsc_discover_filter
- shutdown_time
- apply_shutdown_lock
- stage2
- stage3
- stage4
- convert_const_pointer
- sort_rsc_process_order
- allocate_resources
- order_start_then_action
- order_action_then_stop
- cleanup_orphans
- stage5
- is_managed
- any_managed_resources
- fence_guest
- stage6
- find_actions_by_task
- rsc_order_then
- rsc_order_first
- is_recurring_action
- apply_container_ordering
- get_remote_node_state
- apply_remote_ordering
- apply_remote_node_ordering
- order_first_probe_unneeded
- order_first_probes_imply_stops
- order_first_probe_then_restart_repromote
- clear_actions_tracking_flag
- order_first_rsc_probes
- order_first_probes
- order_then_probes
- order_probes
- stage7
- pcmk__log_transition_summary
- stage8
- LogNodeActions
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13
14 #include <crm/crm.h>
15 #include <crm/cib.h>
16 #include <crm/msg_xml.h>
17 #include <crm/common/xml.h>
18 #include <crm/common/xml_internal.h>
19
20 #include <glib.h>
21
22 #include <crm/pengine/status.h>
23 #include <pacemaker-internal.h>
24
25 CRM_TRACE_INIT_DATA(pacemaker);
26
27 void set_alloc_actions(pe_working_set_t * data_set);
28 extern void ReloadRsc(pe_resource_t * rsc, pe_node_t *node, pe_working_set_t * data_set);
29 extern gboolean DeleteRsc(pe_resource_t * rsc, pe_node_t * node, gboolean optional, pe_working_set_t * data_set);
30 static void apply_remote_node_ordering(pe_working_set_t *data_set);
31 static enum remote_connection_state get_remote_node_state(pe_node_t *node);
32
33 enum remote_connection_state {
34 remote_state_unknown = 0,
35 remote_state_alive = 1,
36 remote_state_resting = 2,
37 remote_state_failed = 3,
38 remote_state_stopped = 4
39 };
40
41 static const char *
42 state2text(enum remote_connection_state state)
43 {
44 switch (state) {
45 case remote_state_unknown:
46 return "unknown";
47 case remote_state_alive:
48 return "alive";
49 case remote_state_resting:
50 return "resting";
51 case remote_state_failed:
52 return "failed";
53 case remote_state_stopped:
54 return "stopped";
55 }
56
57 return "impossible";
58 }
59
60 resource_alloc_functions_t resource_class_alloc_functions[] = {
61 {
62 pcmk__native_merge_weights,
63 pcmk__native_allocate,
64 native_create_actions,
65 native_create_probe,
66 native_internal_constraints,
67 native_rsc_colocation_lh,
68 native_rsc_colocation_rh,
69 native_rsc_location,
70 native_action_flags,
71 native_update_actions,
72 native_expand,
73 native_append_meta,
74 },
75 {
76 pcmk__group_merge_weights,
77 pcmk__group_allocate,
78 group_create_actions,
79 native_create_probe,
80 group_internal_constraints,
81 group_rsc_colocation_lh,
82 group_rsc_colocation_rh,
83 group_rsc_location,
84 group_action_flags,
85 group_update_actions,
86 group_expand,
87 group_append_meta,
88 },
89 {
90 pcmk__native_merge_weights,
91 pcmk__clone_allocate,
92 clone_create_actions,
93 clone_create_probe,
94 clone_internal_constraints,
95 clone_rsc_colocation_lh,
96 clone_rsc_colocation_rh,
97 clone_rsc_location,
98 clone_action_flags,
99 pcmk__multi_update_actions,
100 clone_expand,
101 clone_append_meta,
102 },
103 {
104 pcmk__native_merge_weights,
105 pcmk__bundle_allocate,
106 pcmk__bundle_create_actions,
107 pcmk__bundle_create_probe,
108 pcmk__bundle_internal_constraints,
109 pcmk__bundle_rsc_colocation_lh,
110 pcmk__bundle_rsc_colocation_rh,
111 pcmk__bundle_rsc_location,
112 pcmk__bundle_action_flags,
113 pcmk__multi_update_actions,
114 pcmk__bundle_expand,
115 pcmk__bundle_append_meta,
116 }
117 };
118
119 gboolean
120 update_action_flags(pe_action_t * action, enum pe_action_flags flags, const char *source, int line)
121 {
122 static unsigned long calls = 0;
123 gboolean changed = FALSE;
124 gboolean clear = pcmk_is_set(flags, pe_action_clear);
125 enum pe_action_flags last = action->flags;
126
127 if (clear) {
128 pe__clear_action_flags_as(source, line, action, flags);
129 } else {
130 pe__set_action_flags_as(source, line, action, flags);
131 }
132
133 if (last != action->flags) {
134 calls++;
135 changed = TRUE;
136
137
138 pe__clear_raw_action_flags(flags, "action update", pe_action_clear);
139 crm_trace("%s on %s: %sset flags 0x%.6x (was 0x%.6x, now 0x%.6x, %lu, %s)",
140 action->uuid, action->node ? action->node->details->uname : "[none]",
141 clear ? "un-" : "", flags, last, action->flags, calls, source);
142 }
143
144 return changed;
145 }
146
147 static gboolean
148 check_rsc_parameters(pe_resource_t * rsc, pe_node_t * node, xmlNode * rsc_entry,
149 gboolean active_here, pe_working_set_t * data_set)
150 {
151 int attr_lpc = 0;
152 gboolean force_restart = FALSE;
153 gboolean delete_resource = FALSE;
154 gboolean changed = FALSE;
155
156 const char *value = NULL;
157 const char *old_value = NULL;
158
159 const char *attr_list[] = {
160 XML_ATTR_TYPE,
161 XML_AGENT_ATTR_CLASS,
162 XML_AGENT_ATTR_PROVIDER
163 };
164
165 for (; attr_lpc < DIMOF(attr_list); attr_lpc++) {
166 value = crm_element_value(rsc->xml, attr_list[attr_lpc]);
167 old_value = crm_element_value(rsc_entry, attr_list[attr_lpc]);
168 if (value == old_value
169 || pcmk__str_eq(value, old_value, pcmk__str_none)) {
170 continue;
171 }
172
173 changed = TRUE;
174 trigger_unfencing(rsc, node, "Device definition changed", NULL, data_set);
175 if (active_here) {
176 force_restart = TRUE;
177 crm_notice("Forcing restart of %s on %s, %s changed: %s -> %s",
178 rsc->id, node->details->uname, attr_list[attr_lpc],
179 crm_str(old_value), crm_str(value));
180 }
181 }
182 if (force_restart) {
183
184 stop_action(rsc, node, FALSE);
185 pe__set_resource_flags(rsc, pe_rsc_start_pending);
186 delete_resource = TRUE;
187
188 } else if (changed) {
189 delete_resource = TRUE;
190 }
191 return delete_resource;
192 }
193
194 static void
195 CancelXmlOp(pe_resource_t * rsc, xmlNode * xml_op, pe_node_t * active_node,
196 const char *reason, pe_working_set_t * data_set)
197 {
198 guint interval_ms = 0;
199 pe_action_t *cancel = NULL;
200
201 const char *task = NULL;
202 const char *call_id = NULL;
203
204 CRM_CHECK(xml_op != NULL, return);
205 CRM_CHECK(active_node != NULL, return);
206
207 task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
208 call_id = crm_element_value(xml_op, XML_LRM_ATTR_CALLID);
209 crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
210
211 crm_info("Action " PCMK__OP_FMT " on %s will be stopped: %s",
212 rsc->id, task, interval_ms,
213 active_node->details->uname, (reason? reason : "unknown"));
214
215 cancel = pe_cancel_op(rsc, task, interval_ms, active_node, data_set);
216 add_hash_param(cancel->meta, XML_LRM_ATTR_CALLID, call_id);
217 custom_action_order(rsc, stop_key(rsc), NULL, rsc, NULL, cancel, pe_order_optional, data_set);
218 }
219
220 static gboolean
221 check_action_definition(pe_resource_t * rsc, pe_node_t * active_node, xmlNode * xml_op,
222 pe_working_set_t * data_set)
223 {
224 char *key = NULL;
225 guint interval_ms = 0;
226 const op_digest_cache_t *digest_data = NULL;
227 gboolean did_change = FALSE;
228
229 const char *task = crm_element_value(xml_op, XML_LRM_ATTR_TASK);
230 const char *digest_secure = NULL;
231
232 CRM_CHECK(active_node != NULL, return FALSE);
233
234 crm_element_value_ms(xml_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
235 if (interval_ms > 0) {
236 xmlNode *op_match = NULL;
237
238
239 key = pcmk__op_key(rsc->id, task, interval_ms);
240
241 pe_rsc_trace(rsc, "Checking parameters for %s", key);
242 op_match = find_rsc_op_entry(rsc, key);
243
244 if ((op_match == NULL)
245 && pcmk_is_set(data_set->flags, pe_flag_stop_action_orphans)) {
246 CancelXmlOp(rsc, xml_op, active_node, "orphan", data_set);
247 free(key);
248 return TRUE;
249
250 } else if (op_match == NULL) {
251 pe_rsc_debug(rsc, "Orphan action detected: %s on %s", key, active_node->details->uname);
252 free(key);
253 return TRUE;
254 }
255 free(key);
256 key = NULL;
257 }
258
259 crm_trace("Testing " PCMK__OP_FMT " on %s",
260 rsc->id, task, interval_ms, active_node->details->uname);
261 if ((interval_ms == 0) && pcmk__str_eq(task, RSC_STATUS, pcmk__str_casei)) {
262
263 task = RSC_START;
264
265 } else if ((interval_ms == 0) && pcmk__str_eq(task, RSC_MIGRATED, pcmk__str_casei)) {
266
267 task = RSC_START;
268 } else if ((interval_ms == 0) && pcmk__str_eq(task, RSC_PROMOTE, pcmk__str_casei)) {
269
270 task = RSC_START;
271 }
272
273 digest_data = rsc_action_digest_cmp(rsc, xml_op, active_node, data_set);
274
275 if (pcmk_is_set(data_set->flags, pe_flag_sanitized)) {
276 digest_secure = crm_element_value(xml_op, XML_LRM_ATTR_SECURE_DIGEST);
277 }
278
279 if(digest_data->rc != RSC_DIGEST_MATCH
280 && digest_secure
281 && digest_data->digest_secure_calc
282 && strcmp(digest_data->digest_secure_calc, digest_secure) == 0) {
283 if (pcmk_is_set(data_set->flags, pe_flag_stdout)) {
284 printf("Only 'private' parameters to " PCMK__OP_FMT
285 " on %s changed: %s\n",
286 rsc->id, task, interval_ms, active_node->details->uname,
287 crm_element_value(xml_op, XML_ATTR_TRANSITION_MAGIC));
288 }
289
290 } else if (digest_data->rc == RSC_DIGEST_RESTART) {
291
292 pe_action_t *required = NULL;
293
294 did_change = TRUE;
295 key = pcmk__op_key(rsc->id, task, interval_ms);
296 crm_log_xml_info(digest_data->params_restart, "params:restart");
297 required = custom_action(rsc, key, task, NULL, TRUE, TRUE, data_set);
298 pe_action_set_flag_reason(__func__, __LINE__, required, NULL,
299 "resource definition change", pe_action_optional, TRUE);
300
301 trigger_unfencing(rsc, active_node, "Device parameters changed", NULL, data_set);
302
303 } else if ((digest_data->rc == RSC_DIGEST_ALL) || (digest_data->rc == RSC_DIGEST_UNKNOWN)) {
304
305 const char *digest_restart = crm_element_value(xml_op, XML_LRM_ATTR_RESTART_DIGEST);
306
307 did_change = TRUE;
308 trigger_unfencing(rsc, active_node, "Device parameters changed (reload)", NULL, data_set);
309 crm_log_xml_info(digest_data->params_all, "params:reload");
310 key = pcmk__op_key(rsc->id, task, interval_ms);
311
312 if (interval_ms > 0) {
313 pe_action_t *op = NULL;
314
315 #if 0
316
317 ReloadRsc(rsc, active_node, data_set);
318 #else
319
320 op = custom_action(rsc, key, task, active_node, TRUE, TRUE, data_set);
321 pe__set_action_flags(op, pe_action_reschedule);
322 #endif
323
324 } else if (digest_restart) {
325 pe_rsc_trace(rsc, "Reloading '%s' action for resource %s", task, rsc->id);
326
327
328 ReloadRsc(rsc, active_node, data_set);
329 free(key);
330
331 } else {
332 pe_action_t *required = NULL;
333 pe_rsc_trace(rsc, "Resource %s doesn't know how to reload", rsc->id);
334
335
336
337
338 required = custom_action(rsc, key, task, NULL, TRUE, TRUE, data_set);
339 pe_action_set_flag_reason(__func__, __LINE__, required, NULL,
340 "resource definition change", pe_action_optional, TRUE);
341 }
342 }
343
344 return did_change;
345 }
346
347
348
349
350
351
352
353 static void
354 check_params(pe_resource_t *rsc, pe_node_t *node, xmlNode *rsc_op,
355 enum pe_check_parameters check, pe_working_set_t *data_set)
356 {
357 const char *reason = NULL;
358 op_digest_cache_t *digest_data = NULL;
359
360 switch (check) {
361 case pe_check_active:
362 if (check_action_definition(rsc, node, rsc_op, data_set)
363 && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
364 data_set)) {
365
366 reason = "action definition changed";
367 }
368 break;
369
370 case pe_check_last_failure:
371 digest_data = rsc_action_digest_cmp(rsc, rsc_op, node, data_set);
372 switch (digest_data->rc) {
373 case RSC_DIGEST_UNKNOWN:
374 crm_trace("Resource %s history entry %s on %s has no digest to compare",
375 rsc->id, ID(rsc_op), node->details->id);
376 break;
377 case RSC_DIGEST_MATCH:
378 break;
379 default:
380 reason = "resource parameters have changed";
381 break;
382 }
383 break;
384 }
385
386 if (reason) {
387 pe__clear_failcount(rsc, node, reason, data_set);
388 }
389 }
390
391 static void
392 check_actions_for(xmlNode * rsc_entry, pe_resource_t * rsc, pe_node_t * node, pe_working_set_t * data_set)
393 {
394 GListPtr gIter = NULL;
395 int offset = -1;
396 int stop_index = 0;
397 int start_index = 0;
398
399 const char *task = NULL;
400
401 xmlNode *rsc_op = NULL;
402 GListPtr op_list = NULL;
403 GListPtr sorted_op_list = NULL;
404
405 CRM_CHECK(node != NULL, return);
406
407 if (pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
408 pe_resource_t *parent = uber_parent(rsc);
409 if(parent == NULL
410 || pe_rsc_is_clone(parent) == FALSE
411 || pcmk_is_set(parent->flags, pe_rsc_unique)) {
412 pe_rsc_trace(rsc, "Skipping param check for %s and deleting: orphan", rsc->id);
413 DeleteRsc(rsc, node, FALSE, data_set);
414 } else {
415 pe_rsc_trace(rsc, "Skipping param check for %s (orphan clone)", rsc->id);
416 }
417 return;
418
419 } else if (pe_find_node_id(rsc->running_on, node->details->id) == NULL) {
420 if (check_rsc_parameters(rsc, node, rsc_entry, FALSE, data_set)) {
421 DeleteRsc(rsc, node, FALSE, data_set);
422 }
423 pe_rsc_trace(rsc, "Skipping param check for %s: no longer active on %s",
424 rsc->id, node->details->uname);
425 return;
426 }
427
428 pe_rsc_trace(rsc, "Processing %s on %s", rsc->id, node->details->uname);
429
430 if (check_rsc_parameters(rsc, node, rsc_entry, TRUE, data_set)) {
431 DeleteRsc(rsc, node, FALSE, data_set);
432 }
433
434 for (rsc_op = pcmk__xe_first_child(rsc_entry); rsc_op != NULL;
435 rsc_op = pcmk__xe_next(rsc_op)) {
436
437 if (pcmk__str_eq((const char *)rsc_op->name, XML_LRM_TAG_RSC_OP, pcmk__str_none)) {
438 op_list = g_list_prepend(op_list, rsc_op);
439 }
440 }
441
442 sorted_op_list = g_list_sort(op_list, sort_op_by_callid);
443 calculate_active_ops(sorted_op_list, &start_index, &stop_index);
444
445 for (gIter = sorted_op_list; gIter != NULL; gIter = gIter->next) {
446 xmlNode *rsc_op = (xmlNode *) gIter->data;
447 guint interval_ms = 0;
448
449 offset++;
450
451 if (start_index < stop_index) {
452
453 continue;
454 } else if (offset < start_index) {
455
456 continue;
457 }
458
459 task = crm_element_value(rsc_op, XML_LRM_ATTR_TASK);
460 crm_element_value_ms(rsc_op, XML_LRM_ATTR_INTERVAL_MS, &interval_ms);
461
462 if ((interval_ms > 0) &&
463 (pcmk_is_set(rsc->flags, pe_rsc_maintenance) || node->details->maintenance)) {
464
465 CancelXmlOp(rsc, rsc_op, node, "maintenance mode", data_set);
466
467 } else if ((interval_ms > 0) || pcmk__strcase_any_of(task, RSC_STATUS, RSC_START,
468 RSC_PROMOTE, RSC_MIGRATED, NULL)) {
469
470
471
472
473 if (pe__bundle_needs_remote_name(rsc)) {
474
475
476
477
478
479
480
481 pe__add_param_check(rsc_op, rsc, node, pe_check_active,
482 data_set);
483
484 } else if (check_action_definition(rsc, node, rsc_op, data_set)
485 && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
486 data_set)) {
487 pe__clear_failcount(rsc, node, "action definition changed",
488 data_set);
489 }
490 }
491 }
492 g_list_free(sorted_op_list);
493 }
494
495 static GListPtr
496 find_rsc_list(GListPtr result, pe_resource_t * rsc, const char *id, gboolean renamed_clones,
497 gboolean partial, pe_working_set_t * data_set)
498 {
499 GListPtr gIter = NULL;
500 gboolean match = FALSE;
501
502 if (id == NULL) {
503 return NULL;
504 }
505
506 if (rsc == NULL) {
507 if (data_set == NULL) {
508 return NULL;
509 }
510 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
511 pe_resource_t *child = (pe_resource_t *) gIter->data;
512
513 result = find_rsc_list(result, child, id, renamed_clones, partial,
514 NULL);
515 }
516 return result;
517 }
518
519 if (partial) {
520 if (strstr(rsc->id, id)) {
521 match = TRUE;
522
523 } else if (renamed_clones && rsc->clone_name && strstr(rsc->clone_name, id)) {
524 match = TRUE;
525 }
526
527 } else {
528 if (strcmp(rsc->id, id) == 0) {
529 match = TRUE;
530
531 } else if (renamed_clones && rsc->clone_name && strcmp(rsc->clone_name, id) == 0) {
532 match = TRUE;
533 }
534 }
535
536 if (match) {
537 result = g_list_prepend(result, rsc);
538 }
539
540 if (rsc->children) {
541 gIter = rsc->children;
542 for (; gIter != NULL; gIter = gIter->next) {
543 pe_resource_t *child = (pe_resource_t *) gIter->data;
544
545 result = find_rsc_list(result, child, id, renamed_clones, partial, NULL);
546 }
547 }
548
549 return result;
550 }
551
552 static void
553 check_actions(pe_working_set_t * data_set)
554 {
555 const char *id = NULL;
556 pe_node_t *node = NULL;
557 xmlNode *lrm_rscs = NULL;
558 xmlNode *status = get_object_root(XML_CIB_TAG_STATUS, data_set->input);
559
560 xmlNode *node_state = NULL;
561
562 for (node_state = pcmk__xe_first_child(status); node_state != NULL;
563 node_state = pcmk__xe_next(node_state)) {
564
565 if (pcmk__str_eq((const char *)node_state->name, XML_CIB_TAG_STATE,
566 pcmk__str_none)) {
567 id = crm_element_value(node_state, XML_ATTR_ID);
568 lrm_rscs = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
569 lrm_rscs = find_xml_node(lrm_rscs, XML_LRM_TAG_RESOURCES, FALSE);
570
571 node = pe_find_node_id(data_set->nodes, id);
572
573 if (node == NULL) {
574 continue;
575
576
577 } else if (can_run_resources(node) == FALSE && node->details->maintenance == FALSE) {
578 crm_trace("Skipping param check for %s: can't run resources",
579 node->details->uname);
580 continue;
581 }
582
583 crm_trace("Processing node %s", node->details->uname);
584 if (node->details->online
585 || pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
586 xmlNode *rsc_entry = NULL;
587
588 for (rsc_entry = pcmk__xe_first_child(lrm_rscs);
589 rsc_entry != NULL;
590 rsc_entry = pcmk__xe_next(rsc_entry)) {
591
592 if (pcmk__str_eq((const char *)rsc_entry->name, XML_LRM_TAG_RESOURCE, pcmk__str_none)) {
593
594 if (xml_has_children(rsc_entry)) {
595 GListPtr gIter = NULL;
596 GListPtr result = NULL;
597 const char *rsc_id = ID(rsc_entry);
598
599 CRM_CHECK(rsc_id != NULL, return);
600
601 result = find_rsc_list(NULL, NULL, rsc_id, TRUE, FALSE, data_set);
602 for (gIter = result; gIter != NULL; gIter = gIter->next) {
603 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
604
605 if (rsc->variant != pe_native) {
606 continue;
607 }
608 check_actions_for(rsc_entry, rsc, node, data_set);
609 }
610 g_list_free(result);
611 }
612 }
613 }
614 }
615 }
616 }
617 }
618
619 static void
620 apply_placement_constraints(pe_working_set_t * data_set)
621 {
622 for (GList *gIter = data_set->placement_constraints;
623 gIter != NULL; gIter = gIter->next) {
624 pe__location_t *cons = gIter->data;
625
626 cons->rsc_lh->cmds->rsc_location(cons->rsc_lh, cons);
627 }
628 }
629
630 static gboolean
631 failcount_clear_action_exists(pe_node_t * node, pe_resource_t * rsc)
632 {
633 gboolean rc = FALSE;
634 GList *list = pe__resource_actions(rsc, node, CRM_OP_CLEAR_FAILCOUNT, TRUE);
635
636 if (list) {
637 rc = TRUE;
638 }
639 g_list_free(list);
640 return rc;
641 }
642
643
644
645
646
647
648
649
650
651 static void
652 check_migration_threshold(pe_resource_t *rsc, pe_node_t *node,
653 pe_working_set_t *data_set)
654 {
655 int fail_count, countdown;
656 pe_resource_t *failed;
657
658
659 if (rsc->migration_threshold == 0) {
660 return;
661 }
662
663
664 if (pcmk_is_set(rsc->flags, pe_rsc_failure_ignored)) {
665 return;
666 }
667
668
669 fail_count = pe_get_failcount(node, rsc, NULL,
670 pe_fc_effective|pe_fc_fillers, NULL,
671 data_set);
672 if (fail_count <= 0) {
673 return;
674 }
675
676
677 countdown = QB_MAX(rsc->migration_threshold - fail_count, 0);
678
679
680 failed = rsc;
681 if (!pcmk_is_set(rsc->flags, pe_rsc_unique)) {
682 failed = uber_parent(rsc);
683 }
684
685 if (countdown == 0) {
686 resource_location(failed, node, -INFINITY, "__fail_limit__", data_set);
687 crm_warn("Forcing %s away from %s after %d failures (max=%d)",
688 failed->id, node->details->uname, fail_count,
689 rsc->migration_threshold);
690 } else {
691 crm_info("%s can fail %d more times on %s before being forced off",
692 failed->id, countdown, node->details->uname);
693 }
694 }
695
696 static void
697 common_apply_stickiness(pe_resource_t * rsc, pe_node_t * node, pe_working_set_t * data_set)
698 {
699 if (rsc->children) {
700 GListPtr gIter = rsc->children;
701
702 for (; gIter != NULL; gIter = gIter->next) {
703 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
704
705 common_apply_stickiness(child_rsc, node, data_set);
706 }
707 return;
708 }
709
710 if (pcmk_is_set(rsc->flags, pe_rsc_managed)
711 && rsc->stickiness != 0 && pcmk__list_of_1(rsc->running_on)) {
712 pe_node_t *current = pe_find_node_id(rsc->running_on, node->details->id);
713 pe_node_t *match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
714
715 if (current == NULL) {
716
717 } else if ((match != NULL)
718 || pcmk_is_set(data_set->flags, pe_flag_symmetric_cluster)) {
719 pe_resource_t *sticky_rsc = rsc;
720
721 resource_location(sticky_rsc, node, rsc->stickiness, "stickiness", data_set);
722 pe_rsc_debug(sticky_rsc, "Resource %s: preferring current location"
723 " (node=%s, weight=%d)", sticky_rsc->id,
724 node->details->uname, rsc->stickiness);
725 } else {
726 GHashTableIter iter;
727 pe_node_t *nIter = NULL;
728
729 pe_rsc_debug(rsc, "Ignoring stickiness for %s: the cluster is asymmetric"
730 " and node %s is not explicitly allowed", rsc->id, node->details->uname);
731 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
732 while (g_hash_table_iter_next(&iter, NULL, (void **)&nIter)) {
733 crm_err("%s[%s] = %d", rsc->id, nIter->details->uname, nIter->weight);
734 }
735 }
736 }
737
738
739
740
741
742
743
744
745
746
747
748
749 if (failcount_clear_action_exists(node, rsc) == FALSE) {
750 check_migration_threshold(rsc, node, data_set);
751 }
752 }
753
754 void
755 complex_set_cmds(pe_resource_t * rsc)
756 {
757 GListPtr gIter = rsc->children;
758
759 rsc->cmds = &resource_class_alloc_functions[rsc->variant];
760
761 for (; gIter != NULL; gIter = gIter->next) {
762 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
763
764 complex_set_cmds(child_rsc);
765 }
766 }
767
768 void
769 set_alloc_actions(pe_working_set_t * data_set)
770 {
771
772 GListPtr gIter = data_set->resources;
773
774 for (; gIter != NULL; gIter = gIter->next) {
775 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
776
777 complex_set_cmds(rsc);
778 }
779 }
780
781 static void
782 calculate_system_health(gpointer gKey, gpointer gValue, gpointer user_data)
783 {
784 const char *key = (const char *)gKey;
785 const char *value = (const char *)gValue;
786 int *system_health = (int *)user_data;
787
788 if (!gKey || !gValue || !user_data) {
789 return;
790 }
791
792 if (pcmk__starts_with(key, "#health")) {
793 int score;
794
795
796 score = char2score(value);
797
798
799 *system_health = pe__add_scores(score, *system_health);
800 }
801 }
802
803 static gboolean
804 apply_system_health(pe_working_set_t * data_set)
805 {
806 GListPtr gIter = NULL;
807 const char *health_strategy = pe_pref(data_set->config_hash, "node-health-strategy");
808 int base_health = 0;
809
810 if (pcmk__str_eq(health_strategy, "none", pcmk__str_null_matches | pcmk__str_casei)) {
811
812 pcmk__score_red = 0;
813 pcmk__score_yellow = 0;
814 pcmk__score_green = 0;
815 return TRUE;
816
817 } else if (pcmk__str_eq(health_strategy, "migrate-on-red", pcmk__str_casei)) {
818
819
820
821
822 pcmk__score_red = -INFINITY;
823 pcmk__score_yellow = 0;
824 pcmk__score_green = 0;
825
826 } else if (pcmk__str_eq(health_strategy, "only-green", pcmk__str_casei)) {
827
828
829
830
831 pcmk__score_red = -INFINITY;
832 pcmk__score_yellow = -INFINITY;
833 pcmk__score_green = 0;
834
835 } else if (pcmk__str_eq(health_strategy, "progressive", pcmk__str_casei)) {
836
837
838
839
840 base_health = crm_parse_int(pe_pref(data_set->config_hash, "node-health-base"), "0");
841
842 } else if (pcmk__str_eq(health_strategy, "custom", pcmk__str_casei)) {
843
844
845
846
847
848 return TRUE;
849
850 } else {
851 crm_err("Unknown node health strategy: %s", health_strategy);
852 return FALSE;
853 }
854
855 crm_info("Applying automated node health strategy: %s", health_strategy);
856
857 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
858 int system_health = base_health;
859 pe_node_t *node = (pe_node_t *) gIter->data;
860
861
862 g_hash_table_foreach(node->details->attrs, calculate_system_health, &system_health);
863
864 crm_info(" Node %s has an combined system health of %d",
865 node->details->uname, system_health);
866
867
868
869
870 if (system_health != 0) {
871
872 GListPtr gIter2 = data_set->resources;
873
874 for (; gIter2 != NULL; gIter2 = gIter2->next) {
875 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
876
877 rsc2node_new(health_strategy, rsc, system_health, NULL, node, data_set);
878 }
879 }
880 }
881
882 return TRUE;
883 }
884
885 gboolean
886 stage0(pe_working_set_t * data_set)
887 {
888 xmlNode *cib_constraints = get_object_root(XML_CIB_TAG_CONSTRAINTS, data_set->input);
889
890 if (data_set->input == NULL) {
891 return FALSE;
892 }
893
894 if (!pcmk_is_set(data_set->flags, pe_flag_have_status)) {
895 crm_trace("Calculating status");
896 cluster_status(data_set);
897 }
898
899 set_alloc_actions(data_set);
900 apply_system_health(data_set);
901 unpack_constraints(cib_constraints, data_set);
902
903 return TRUE;
904 }
905
906
907
908
909 gboolean
910 probe_resources(pe_working_set_t * data_set)
911 {
912 pe_action_t *probe_node_complete = NULL;
913
914 for (GListPtr gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
915 pe_node_t *node = (pe_node_t *) gIter->data;
916 const char *probed = pe_node_attribute_raw(node, CRM_OP_PROBED);
917
918 if (node->details->online == FALSE) {
919
920 if (pe__is_remote_node(node) && node->details->remote_rsc
921 && (get_remote_node_state(node) == remote_state_failed)) {
922
923 pe_fence_node(data_set, node, "the connection is unrecoverable", FALSE);
924 }
925 continue;
926
927 } else if (node->details->unclean) {
928 continue;
929
930 } else if (node->details->rsc_discovery_enabled == FALSE) {
931
932 continue;
933 }
934
935 if (probed != NULL && crm_is_true(probed) == FALSE) {
936 pe_action_t *probe_op = custom_action(NULL, crm_strdup_printf("%s-%s", CRM_OP_REPROBE, node->details->uname),
937 CRM_OP_REPROBE, node, FALSE, TRUE, data_set);
938
939 add_hash_param(probe_op->meta, XML_ATTR_TE_NOWAIT, XML_BOOLEAN_TRUE);
940 continue;
941 }
942
943 for (GListPtr gIter2 = data_set->resources; gIter2 != NULL; gIter2 = gIter2->next) {
944 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
945
946 rsc->cmds->create_probe(rsc, node, probe_node_complete, FALSE, data_set);
947 }
948 }
949 return TRUE;
950 }
951
952 static void
953 rsc_discover_filter(pe_resource_t *rsc, pe_node_t *node)
954 {
955 GListPtr gIter = rsc->children;
956 pe_resource_t *top = uber_parent(rsc);
957 pe_node_t *match;
958
959 if (rsc->exclusive_discover == FALSE && top->exclusive_discover == FALSE) {
960 return;
961 }
962
963 for (; gIter != NULL; gIter = gIter->next) {
964 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
965 rsc_discover_filter(child_rsc, node);
966 }
967
968 match = g_hash_table_lookup(rsc->allowed_nodes, node->details->id);
969 if (match && match->rsc_discover_mode != pe_discover_exclusive) {
970 match->weight = -INFINITY;
971 }
972 }
973
974 static time_t
975 shutdown_time(pe_node_t *node, pe_working_set_t *data_set)
976 {
977 const char *shutdown = pe_node_attribute_raw(node, XML_CIB_ATTR_SHUTDOWN);
978 time_t result = 0;
979
980 if (shutdown) {
981 errno = 0;
982 result = (time_t) crm_parse_ll(shutdown, NULL);
983 if (errno != 0) {
984 result = 0;
985 }
986 }
987 return result? result : get_effective_time(data_set);
988 }
989
990 static void
991 apply_shutdown_lock(pe_resource_t *rsc, pe_working_set_t *data_set)
992 {
993 const char *class;
994
995
996 if (rsc->variant == pe_group) {
997 for (GList *item = rsc->children; item != NULL;
998 item = item->next) {
999 apply_shutdown_lock((pe_resource_t *) item->data, data_set);
1000 }
1001 } else if (rsc->variant != pe_native) {
1002 return;
1003 }
1004
1005
1006 class = crm_element_value(rsc->xml, XML_AGENT_ATTR_CLASS);
1007 if (pcmk__str_eq(class, PCMK_RESOURCE_CLASS_STONITH, pcmk__str_null_matches)
1008 || pe__resource_is_remote_conn(rsc, data_set)) {
1009 return;
1010 }
1011
1012 if (rsc->lock_node != NULL) {
1013
1014
1015 if (rsc->running_on != NULL) {
1016
1017
1018
1019
1020 pe_rsc_info(rsc,
1021 "Cancelling shutdown lock because %s is already active",
1022 rsc->id);
1023 pe__clear_resource_history(rsc, rsc->lock_node, data_set);
1024 rsc->lock_node = NULL;
1025 rsc->lock_time = 0;
1026 }
1027
1028
1029 } else if (pcmk__list_of_1(rsc->running_on)) {
1030 pe_node_t *node = rsc->running_on->data;
1031
1032 if (node->details->shutdown) {
1033 if (node->details->unclean) {
1034 pe_rsc_debug(rsc, "Not locking %s to unclean %s for shutdown",
1035 rsc->id, node->details->uname);
1036 } else {
1037 rsc->lock_node = node;
1038 rsc->lock_time = shutdown_time(node, data_set);
1039 }
1040 }
1041 }
1042
1043 if (rsc->lock_node == NULL) {
1044
1045 return;
1046 }
1047
1048 if (data_set->shutdown_lock > 0) {
1049 time_t lock_expiration = rsc->lock_time + data_set->shutdown_lock;
1050
1051 pe_rsc_info(rsc, "Locking %s to %s due to shutdown (expires @%lld)",
1052 rsc->id, rsc->lock_node->details->uname,
1053 (long long) lock_expiration);
1054 pe__update_recheck_time(++lock_expiration, data_set);
1055 } else {
1056 pe_rsc_info(rsc, "Locking %s to %s due to shutdown",
1057 rsc->id, rsc->lock_node->details->uname);
1058 }
1059
1060
1061 for (GList *item = data_set->nodes; item != NULL; item = item->next) {
1062 pe_node_t *node = item->data;
1063
1064 if (strcmp(node->details->uname, rsc->lock_node->details->uname)) {
1065 resource_location(rsc, node, -CRM_SCORE_INFINITY,
1066 XML_CONFIG_ATTR_SHUTDOWN_LOCK, data_set);
1067 }
1068 }
1069 }
1070
1071
1072
1073
1074
1075
1076
1077
1078 gboolean
1079 stage2(pe_working_set_t * data_set)
1080 {
1081 GListPtr gIter = NULL;
1082
1083 if (pcmk_is_set(data_set->flags, pe_flag_shutdown_lock)) {
1084 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1085 apply_shutdown_lock((pe_resource_t *) gIter->data, data_set);
1086 }
1087 }
1088
1089 if (!pcmk_is_set(data_set->flags, pe_flag_no_compat)) {
1090
1091 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1092 pe_node_t *node = (pe_node_t *) gIter->data;
1093
1094 if (node && (node->weight >= 0) && node->details->online
1095 && (node->details->type != node_ping)) {
1096 data_set->max_valid_nodes++;
1097 }
1098 }
1099 }
1100
1101 apply_placement_constraints(data_set);
1102
1103 gIter = data_set->nodes;
1104 for (; gIter != NULL; gIter = gIter->next) {
1105 GListPtr gIter2 = NULL;
1106 pe_node_t *node = (pe_node_t *) gIter->data;
1107
1108 gIter2 = data_set->resources;
1109 for (; gIter2 != NULL; gIter2 = gIter2->next) {
1110 pe_resource_t *rsc = (pe_resource_t *) gIter2->data;
1111
1112 common_apply_stickiness(rsc, node, data_set);
1113 rsc_discover_filter(rsc, node);
1114 }
1115 }
1116
1117 return TRUE;
1118 }
1119
1120
1121
1122
1123 gboolean
1124 stage3(pe_working_set_t * data_set)
1125 {
1126
1127 GListPtr gIter = data_set->resources;
1128
1129 for (; gIter != NULL; gIter = gIter->next) {
1130 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1131
1132 rsc->cmds->internal_constraints(rsc, data_set);
1133 }
1134
1135 return TRUE;
1136 }
1137
1138
1139
1140
1141 gboolean
1142 stage4(pe_working_set_t * data_set)
1143 {
1144 check_actions(data_set);
1145 return TRUE;
1146 }
1147
1148 static void *
1149 convert_const_pointer(const void *ptr)
1150 {
1151
1152 return (void *)ptr;
1153 }
1154
1155 static gint
1156 sort_rsc_process_order(gconstpointer a, gconstpointer b, gpointer data)
1157 {
1158 int rc = 0;
1159 int r1_weight = -INFINITY;
1160 int r2_weight = -INFINITY;
1161
1162 const char *reason = "existence";
1163
1164 const GListPtr nodes = (GListPtr) data;
1165 const pe_resource_t *resource1 = a;
1166 const pe_resource_t *resource2 = b;
1167
1168 pe_node_t *r1_node = NULL;
1169 pe_node_t *r2_node = NULL;
1170 GListPtr gIter = NULL;
1171 GHashTable *r1_nodes = NULL;
1172 GHashTable *r2_nodes = NULL;
1173
1174 reason = "priority";
1175 r1_weight = resource1->priority;
1176 r2_weight = resource2->priority;
1177
1178 if (r1_weight > r2_weight) {
1179 rc = -1;
1180 goto done;
1181 }
1182
1183 if (r1_weight < r2_weight) {
1184 rc = 1;
1185 goto done;
1186 }
1187
1188 reason = "no node list";
1189 if (nodes == NULL) {
1190 goto done;
1191 }
1192
1193 r1_nodes = pcmk__native_merge_weights(convert_const_pointer(resource1),
1194 resource1->id, NULL, NULL, 1,
1195 pe_weights_forward | pe_weights_init);
1196 pe__show_node_weights(true, NULL, resource1->id, r1_nodes);
1197
1198 r2_nodes = pcmk__native_merge_weights(convert_const_pointer(resource2),
1199 resource2->id, NULL, NULL, 1,
1200 pe_weights_forward | pe_weights_init);
1201 pe__show_node_weights(true, NULL, resource2->id, r2_nodes);
1202
1203
1204 reason = "current location";
1205 r1_weight = -INFINITY;
1206 r2_weight = -INFINITY;
1207
1208 if (resource1->running_on) {
1209 r1_node = pe__current_node(resource1);
1210 r1_node = g_hash_table_lookup(r1_nodes, r1_node->details->id);
1211 if (r1_node != NULL) {
1212 r1_weight = r1_node->weight;
1213 }
1214 }
1215 if (resource2->running_on) {
1216 r2_node = pe__current_node(resource2);
1217 r2_node = g_hash_table_lookup(r2_nodes, r2_node->details->id);
1218 if (r2_node != NULL) {
1219 r2_weight = r2_node->weight;
1220 }
1221 }
1222
1223 if (r1_weight > r2_weight) {
1224 rc = -1;
1225 goto done;
1226 }
1227
1228 if (r1_weight < r2_weight) {
1229 rc = 1;
1230 goto done;
1231 }
1232
1233 reason = "score";
1234 for (gIter = nodes; gIter != NULL; gIter = gIter->next) {
1235 pe_node_t *node = (pe_node_t *) gIter->data;
1236
1237 r1_node = NULL;
1238 r2_node = NULL;
1239
1240 r1_weight = -INFINITY;
1241 if (r1_nodes) {
1242 r1_node = g_hash_table_lookup(r1_nodes, node->details->id);
1243 }
1244 if (r1_node) {
1245 r1_weight = r1_node->weight;
1246 }
1247
1248 r2_weight = -INFINITY;
1249 if (r2_nodes) {
1250 r2_node = g_hash_table_lookup(r2_nodes, node->details->id);
1251 }
1252 if (r2_node) {
1253 r2_weight = r2_node->weight;
1254 }
1255
1256 if (r1_weight > r2_weight) {
1257 rc = -1;
1258 goto done;
1259 }
1260
1261 if (r1_weight < r2_weight) {
1262 rc = 1;
1263 goto done;
1264 }
1265 }
1266
1267 done:
1268 crm_trace("%s (%d) on %s %c %s (%d) on %s: %s",
1269 resource1->id, r1_weight, r1_node ? r1_node->details->id : "n/a",
1270 rc < 0 ? '>' : rc > 0 ? '<' : '=',
1271 resource2->id, r2_weight, r2_node ? r2_node->details->id : "n/a", reason);
1272
1273 if (r1_nodes) {
1274 g_hash_table_destroy(r1_nodes);
1275 }
1276 if (r2_nodes) {
1277 g_hash_table_destroy(r2_nodes);
1278 }
1279
1280 return rc;
1281 }
1282
1283 static void
1284 allocate_resources(pe_working_set_t * data_set)
1285 {
1286 GListPtr gIter = NULL;
1287
1288 if (pcmk_is_set(data_set->flags, pe_flag_have_remote_nodes)) {
1289
1290
1291
1292
1293 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1294 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1295 if (rsc->is_remote_node == FALSE) {
1296 continue;
1297 }
1298 pe_rsc_trace(rsc, "Allocating remote connection resource '%s'",
1299 rsc->id);
1300 rsc->cmds->allocate(rsc, rsc->partial_migration_target, data_set);
1301 }
1302 }
1303
1304
1305 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1306 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1307 if (rsc->is_remote_node == TRUE) {
1308 continue;
1309 }
1310 pe_rsc_trace(rsc, "Allocating %s resource '%s'",
1311 crm_element_name(rsc->xml), rsc->id);
1312 rsc->cmds->allocate(rsc, NULL, data_set);
1313 }
1314 }
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324 static inline void
1325 order_start_then_action(pe_resource_t *lh_rsc, pe_action_t *rh_action,
1326 enum pe_ordering extra, pe_working_set_t *data_set)
1327 {
1328 if (lh_rsc && rh_action && data_set) {
1329 custom_action_order(lh_rsc, start_key(lh_rsc), NULL,
1330 rh_action->rsc, NULL, rh_action,
1331 pe_order_preserve | pe_order_runnable_left | extra,
1332 data_set);
1333 }
1334 }
1335
1336 static inline void
1337 order_action_then_stop(pe_action_t *lh_action, pe_resource_t *rh_rsc,
1338 enum pe_ordering extra, pe_working_set_t *data_set)
1339 {
1340 if (lh_action && rh_rsc && data_set) {
1341 custom_action_order(lh_action->rsc, NULL, lh_action,
1342 rh_rsc, stop_key(rh_rsc), NULL,
1343 pe_order_preserve | extra, data_set);
1344 }
1345 }
1346
1347
1348 static void
1349 cleanup_orphans(pe_resource_t * rsc, pe_working_set_t * data_set)
1350 {
1351 GListPtr gIter = NULL;
1352
1353 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1354 pe_node_t *node = (pe_node_t *) gIter->data;
1355
1356 if (node->details->online
1357 && pe_get_failcount(node, rsc, NULL, pe_fc_effective, NULL,
1358 data_set)) {
1359
1360 pe_action_t *clear_op = NULL;
1361
1362 clear_op = pe__clear_failcount(rsc, node, "it is orphaned",
1363 data_set);
1364
1365
1366
1367
1368 custom_action_order(clear_op->rsc, NULL, clear_op,
1369 rsc, stop_key(rsc), NULL,
1370 pe_order_optional, data_set);
1371 }
1372 }
1373 }
1374
1375 gboolean
1376 stage5(pe_working_set_t * data_set)
1377 {
1378 GListPtr gIter = NULL;
1379 int log_prio = show_utilization? LOG_STDOUT : LOG_TRACE;
1380
1381 if (!pcmk__str_eq(data_set->placement_strategy, "default", pcmk__str_casei)) {
1382 GListPtr nodes = g_list_copy(data_set->nodes);
1383
1384 nodes = sort_nodes_by_weight(nodes, NULL, data_set);
1385 data_set->resources =
1386 g_list_sort_with_data(data_set->resources, sort_rsc_process_order, nodes);
1387
1388 g_list_free(nodes);
1389 }
1390
1391 gIter = data_set->nodes;
1392 for (; gIter != NULL; gIter = gIter->next) {
1393 pe_node_t *node = (pe_node_t *) gIter->data;
1394
1395 dump_node_capacity(log_prio, "Original", node);
1396 }
1397
1398 crm_trace("Allocating services");
1399
1400
1401 allocate_resources(data_set);
1402
1403 gIter = data_set->nodes;
1404 for (; gIter != NULL; gIter = gIter->next) {
1405 pe_node_t *node = (pe_node_t *) gIter->data;
1406
1407 dump_node_capacity(log_prio, "Remaining", node);
1408 }
1409
1410
1411 pe__foreach_param_check(data_set, check_params);
1412 pe__free_param_checks(data_set);
1413
1414 if (pcmk_is_set(data_set->flags, pe_flag_startup_probes)) {
1415 crm_trace("Calculating needed probes");
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450 probe_resources(data_set);
1451 }
1452
1453 crm_trace("Handle orphans");
1454 if (pcmk_is_set(data_set->flags, pe_flag_stop_rsc_orphans)) {
1455 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1456 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1457
1458
1459
1460
1461 if (pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
1462 cleanup_orphans(rsc, data_set);
1463 }
1464 }
1465 }
1466
1467 crm_trace("Creating actions");
1468
1469 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
1470 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1471
1472 rsc->cmds->create_actions(rsc, data_set);
1473 }
1474
1475 crm_trace("Creating done");
1476 return TRUE;
1477 }
1478
1479 static gboolean
1480 is_managed(const pe_resource_t * rsc)
1481 {
1482 GListPtr gIter = rsc->children;
1483
1484 if (pcmk_is_set(rsc->flags, pe_rsc_managed)) {
1485 return TRUE;
1486 }
1487
1488 for (; gIter != NULL; gIter = gIter->next) {
1489 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
1490
1491 if (is_managed(child_rsc)) {
1492 return TRUE;
1493 }
1494 }
1495
1496 return FALSE;
1497 }
1498
1499 static gboolean
1500 any_managed_resources(pe_working_set_t * data_set)
1501 {
1502
1503 GListPtr gIter = data_set->resources;
1504
1505 for (; gIter != NULL; gIter = gIter->next) {
1506 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
1507
1508 if (is_managed(rsc)) {
1509 return TRUE;
1510 }
1511 }
1512 return FALSE;
1513 }
1514
1515
1516
1517
1518
1519
1520
1521
1522 static void
1523 fence_guest(pe_node_t *node, pe_working_set_t *data_set)
1524 {
1525 pe_resource_t *container = node->details->remote_rsc->container;
1526 pe_action_t *stop = NULL;
1527 pe_action_t *stonith_op = NULL;
1528
1529
1530
1531
1532
1533
1534
1535 const char *fence_action = "off";
1536
1537
1538
1539
1540 if (container) {
1541 stop = find_first_action(container->actions, NULL, CRMD_ACTION_STOP, NULL);
1542
1543 if (find_first_action(container->actions, NULL, CRMD_ACTION_START, NULL)) {
1544 fence_action = "reboot";
1545 }
1546 }
1547
1548
1549
1550
1551 stonith_op = pe_fence_op(node, fence_action, FALSE, "guest is unclean", FALSE, data_set);
1552 update_action_flags(stonith_op, pe_action_pseudo | pe_action_runnable,
1553 __func__, __LINE__);
1554
1555
1556
1557
1558
1559 if ((stop != NULL) && pcmk_is_set(stop->flags, pe_action_pseudo)) {
1560 pe_action_t *parent_stonith_op = pe_fence_op(stop->node, NULL, FALSE, NULL, FALSE, data_set);
1561 crm_info("Implying guest node %s is down (action %d) after %s fencing",
1562 node->details->uname, stonith_op->id, stop->node->details->uname);
1563 order_actions(parent_stonith_op, stonith_op,
1564 pe_order_runnable_left|pe_order_implies_then);
1565
1566 } else if (stop) {
1567 order_actions(stop, stonith_op,
1568 pe_order_runnable_left|pe_order_implies_then);
1569 crm_info("Implying guest node %s is down (action %d) "
1570 "after container %s is stopped (action %d)",
1571 node->details->uname, stonith_op->id,
1572 container->id, stop->id);
1573 } else {
1574
1575
1576
1577
1578
1579
1580
1581 stop = find_first_action(node->details->remote_rsc->actions, NULL,
1582 RSC_STOP, NULL);
1583
1584 if (stop) {
1585 order_actions(stop, stonith_op, pe_order_optional);
1586 crm_info("Implying guest node %s is down (action %d) "
1587 "after connection is stopped (action %d)",
1588 node->details->uname, stonith_op->id, stop->id);
1589 } else {
1590
1591
1592
1593 crm_info("Implying guest node %s is down (action %d) ",
1594 node->details->uname, stonith_op->id);
1595 }
1596 }
1597
1598
1599 pcmk__order_vs_fence(stonith_op, data_set);
1600 }
1601
1602
1603
1604
1605 gboolean
1606 stage6(pe_working_set_t * data_set)
1607 {
1608 pe_action_t *dc_down = NULL;
1609 pe_action_t *stonith_op = NULL;
1610 gboolean integrity_lost = FALSE;
1611 gboolean need_stonith = TRUE;
1612 GListPtr gIter;
1613 GListPtr stonith_ops = NULL;
1614 GList *shutdown_ops = NULL;
1615
1616
1617
1618
1619
1620
1621
1622 crm_trace("Creating remote ordering constraints");
1623 apply_remote_node_ordering(data_set);
1624
1625 crm_trace("Processing fencing and shutdown cases");
1626 if (any_managed_resources(data_set) == FALSE) {
1627 crm_notice("Delaying fencing operations until there are resources to manage");
1628 need_stonith = FALSE;
1629 }
1630
1631
1632 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
1633 pe_node_t *node = (pe_node_t *) gIter->data;
1634
1635
1636
1637
1638 if (pe__is_guest_node(node)) {
1639 if (node->details->remote_requires_reset && need_stonith
1640 && pe_can_fence(data_set, node)) {
1641 fence_guest(node, data_set);
1642 }
1643 continue;
1644 }
1645
1646 stonith_op = NULL;
1647
1648 if (node->details->unclean
1649 && need_stonith && pe_can_fence(data_set, node)) {
1650
1651 stonith_op = pe_fence_op(node, NULL, FALSE, "node is unclean", FALSE, data_set);
1652 pe_warn("Scheduling Node %s for STONITH", node->details->uname);
1653
1654 pcmk__order_vs_fence(stonith_op, data_set);
1655
1656 if (node->details->is_dc) {
1657
1658 dc_down = stonith_op;
1659
1660 } else {
1661
1662 if (!pcmk_is_set(data_set->flags, pe_flag_concurrent_fencing)
1663 && (stonith_ops != NULL)) {
1664
1665
1666
1667
1668
1669 order_actions((pe_action_t *) stonith_ops->data,
1670 stonith_op, pe_order_optional);
1671 }
1672
1673
1674 stonith_ops = g_list_prepend(stonith_ops, stonith_op);
1675 }
1676
1677 } else if (node->details->online && node->details->shutdown &&
1678
1679
1680
1681 pe__is_guest_or_remote_node(node) == FALSE) {
1682
1683 pe_action_t *down_op = sched_shutdown_op(node, data_set);
1684
1685 if (node->details->is_dc) {
1686
1687 dc_down = down_op;
1688 } else {
1689
1690 shutdown_ops = g_list_prepend(shutdown_ops, down_op);
1691 }
1692 }
1693
1694 if (node->details->unclean && stonith_op == NULL) {
1695 integrity_lost = TRUE;
1696 pe_warn("Node %s is unclean!", node->details->uname);
1697 }
1698 }
1699
1700 if (integrity_lost) {
1701 if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
1702 pe_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED");
1703 pe_err("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE");
1704
1705 } else if (!pcmk_is_set(data_set->flags, pe_flag_have_quorum)) {
1706 crm_notice("Cannot fence unclean nodes until quorum is"
1707 " attained (or no-quorum-policy is set to ignore)");
1708 }
1709 }
1710
1711 if (dc_down != NULL) {
1712
1713
1714
1715
1716
1717
1718
1719 if (pcmk__str_eq(dc_down->task, CRM_OP_SHUTDOWN, pcmk__str_casei)) {
1720 for (gIter = shutdown_ops; gIter != NULL; gIter = gIter->next) {
1721 pe_action_t *node_stop = (pe_action_t *) gIter->data;
1722
1723 crm_debug("Ordering shutdown on %s before %s on DC %s",
1724 node_stop->node->details->uname,
1725 dc_down->task, dc_down->node->details->uname);
1726
1727 order_actions(node_stop, dc_down, pe_order_optional);
1728 }
1729 }
1730
1731
1732
1733 if (pcmk_is_set(data_set->flags, pe_flag_concurrent_fencing)) {
1734
1735
1736
1737 for (gIter = stonith_ops; gIter != NULL; gIter = gIter->next) {
1738 order_actions((pe_action_t *) gIter->data, dc_down,
1739 pe_order_optional);
1740 }
1741 } else if (stonith_ops) {
1742
1743
1744
1745
1746
1747 order_actions((pe_action_t *) stonith_ops->data, dc_down,
1748 pe_order_optional);
1749 }
1750 }
1751 g_list_free(stonith_ops);
1752 g_list_free(shutdown_ops);
1753 return TRUE;
1754 }
1755
1756
1757
1758
1759
1760
1761
1762
1763 static GListPtr
1764 find_actions_by_task(GListPtr actions, pe_resource_t * rsc, const char *original_key)
1765 {
1766 GListPtr list = NULL;
1767
1768 list = find_actions(actions, original_key, NULL);
1769 if (list == NULL) {
1770
1771 char *key = NULL;
1772 char *task = NULL;
1773 guint interval_ms = 0;
1774
1775 if (parse_op_key(original_key, NULL, &task, &interval_ms)) {
1776 key = pcmk__op_key(rsc->id, task, interval_ms);
1777 list = find_actions(actions, key, NULL);
1778
1779 } else {
1780 crm_err("search key: %s", original_key);
1781 }
1782
1783 free(key);
1784 free(task);
1785 }
1786
1787 return list;
1788 }
1789
1790 static void
1791 rsc_order_then(pe_action_t *lh_action, pe_resource_t *rsc,
1792 pe__ordering_t *order)
1793 {
1794 GListPtr gIter = NULL;
1795 GListPtr rh_actions = NULL;
1796 pe_action_t *rh_action = NULL;
1797 enum pe_ordering type;
1798
1799 CRM_CHECK(rsc != NULL, return);
1800 CRM_CHECK(order != NULL, return);
1801
1802 type = order->type;
1803 rh_action = order->rh_action;
1804 crm_trace("Processing RH of ordering constraint %d", order->id);
1805
1806 if (rh_action != NULL) {
1807 rh_actions = g_list_prepend(NULL, rh_action);
1808
1809 } else if (rsc != NULL) {
1810 rh_actions = find_actions_by_task(rsc->actions, rsc, order->rh_action_task);
1811 }
1812
1813 if (rh_actions == NULL) {
1814 pe_rsc_trace(rsc, "No RH-Side (%s/%s) found for constraint..."
1815 " ignoring", rsc->id, order->rh_action_task);
1816 if (lh_action) {
1817 pe_rsc_trace(rsc, "LH-Side was: %s", lh_action->uuid);
1818 }
1819 return;
1820 }
1821
1822 if ((lh_action != NULL) && (lh_action->rsc == rsc)
1823 && pcmk_is_set(lh_action->flags, pe_action_dangle)) {
1824
1825 pe_rsc_trace(rsc, "Detected dangling operation %s -> %s", lh_action->uuid,
1826 order->rh_action_task);
1827 pe__clear_order_flags(type, pe_order_implies_then);
1828 }
1829
1830 gIter = rh_actions;
1831 for (; gIter != NULL; gIter = gIter->next) {
1832 pe_action_t *rh_action_iter = (pe_action_t *) gIter->data;
1833
1834 if (lh_action) {
1835 order_actions(lh_action, rh_action_iter, type);
1836
1837 } else if (type & pe_order_implies_then) {
1838 update_action_flags(rh_action_iter, pe_action_runnable | pe_action_clear,
1839 __func__, __LINE__);
1840 crm_warn("Unrunnable %s 0x%.6x", rh_action_iter->uuid, type);
1841 } else {
1842 crm_warn("neither %s 0x%.6x", rh_action_iter->uuid, type);
1843 }
1844 }
1845
1846 g_list_free(rh_actions);
1847 }
1848
1849 static void
1850 rsc_order_first(pe_resource_t *lh_rsc, pe__ordering_t *order,
1851 pe_working_set_t *data_set)
1852 {
1853 GListPtr gIter = NULL;
1854 GListPtr lh_actions = NULL;
1855 pe_action_t *lh_action = order->lh_action;
1856 pe_resource_t *rh_rsc = order->rh_rsc;
1857
1858 crm_trace("Processing LH of ordering constraint %d", order->id);
1859 CRM_ASSERT(lh_rsc != NULL);
1860
1861 if (lh_action != NULL) {
1862 lh_actions = g_list_prepend(NULL, lh_action);
1863
1864 } else {
1865 lh_actions = find_actions_by_task(lh_rsc->actions, lh_rsc, order->lh_action_task);
1866 }
1867
1868 if (lh_actions == NULL && lh_rsc != rh_rsc) {
1869 char *key = NULL;
1870 char *op_type = NULL;
1871 guint interval_ms = 0;
1872
1873 parse_op_key(order->lh_action_task, NULL, &op_type, &interval_ms);
1874 key = pcmk__op_key(lh_rsc->id, op_type, interval_ms);
1875
1876 if (lh_rsc->fns->state(lh_rsc, TRUE) == RSC_ROLE_STOPPED && pcmk__str_eq(op_type, RSC_STOP, pcmk__str_casei)) {
1877 free(key);
1878 pe_rsc_trace(lh_rsc, "No LH-Side (%s/%s) found for constraint %d with %s - ignoring",
1879 lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task);
1880
1881 } else if (lh_rsc->fns->state(lh_rsc, TRUE) == RSC_ROLE_SLAVE && pcmk__str_eq(op_type, RSC_DEMOTE, pcmk__str_casei)) {
1882 free(key);
1883 pe_rsc_trace(lh_rsc, "No LH-Side (%s/%s) found for constraint %d with %s - ignoring",
1884 lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task);
1885
1886 } else {
1887 pe_rsc_trace(lh_rsc, "No LH-Side (%s/%s) found for constraint %d with %s - creating",
1888 lh_rsc->id, order->lh_action_task, order->id, order->rh_action_task);
1889 lh_action = custom_action(lh_rsc, key, op_type, NULL, TRUE, TRUE, data_set);
1890 lh_actions = g_list_prepend(NULL, lh_action);
1891 }
1892
1893 free(op_type);
1894 }
1895
1896 gIter = lh_actions;
1897 for (; gIter != NULL; gIter = gIter->next) {
1898 pe_action_t *lh_action_iter = (pe_action_t *) gIter->data;
1899
1900 if (rh_rsc == NULL && order->rh_action) {
1901 rh_rsc = order->rh_action->rsc;
1902 }
1903 if (rh_rsc) {
1904 rsc_order_then(lh_action_iter, rh_rsc, order);
1905
1906 } else if (order->rh_action) {
1907 order_actions(lh_action_iter, order->rh_action, order->type);
1908 }
1909 }
1910
1911 g_list_free(lh_actions);
1912 }
1913
1914 extern void update_colo_start_chain(pe_action_t *action,
1915 pe_working_set_t *data_set);
1916
1917 static int
1918 is_recurring_action(pe_action_t *action)
1919 {
1920 guint interval_ms;
1921
1922 if (pcmk__guint_from_hash(action->meta,
1923 XML_LRM_ATTR_INTERVAL_MS, 0,
1924 &interval_ms) != pcmk_rc_ok) {
1925 return 0;
1926 }
1927 return (interval_ms > 0);
1928 }
1929
1930 static void
1931 apply_container_ordering(pe_action_t *action, pe_working_set_t *data_set)
1932 {
1933
1934
1935
1936
1937
1938
1939
1940 pe_resource_t *remote_rsc = NULL;
1941 pe_resource_t *container = NULL;
1942 enum action_tasks task = text2task(action->task);
1943
1944 CRM_ASSERT(action->rsc);
1945 CRM_ASSERT(action->node);
1946 CRM_ASSERT(pe__is_guest_or_remote_node(action->node));
1947
1948 remote_rsc = action->node->details->remote_rsc;
1949 CRM_ASSERT(remote_rsc);
1950
1951 container = remote_rsc->container;
1952 CRM_ASSERT(container);
1953
1954 if (pcmk_is_set(container->flags, pe_rsc_failed)) {
1955 pe_fence_node(data_set, action->node, "container failed", FALSE);
1956 }
1957
1958 crm_trace("Order %s action %s relative to %s%s for %s%s",
1959 action->task, action->uuid,
1960 pcmk_is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
1961 remote_rsc->id,
1962 pcmk_is_set(container->flags, pe_rsc_failed)? "failed " : "",
1963 container->id);
1964
1965 if (pcmk__strcase_any_of(action->task, CRMD_ACTION_MIGRATE, CRMD_ACTION_MIGRATED, NULL)) {
1966
1967
1968
1969 task = stop_rsc;
1970 }
1971
1972 switch (task) {
1973 case start_rsc:
1974 case action_promote:
1975
1976 order_start_then_action(container, action, pe_order_implies_then,
1977 data_set);
1978
1979
1980 order_start_then_action(remote_rsc, action, pe_order_none,
1981 data_set);
1982 break;
1983
1984 case stop_rsc:
1985 case action_demote:
1986 if (pcmk_is_set(container->flags, pe_rsc_failed)) {
1987
1988
1989
1990
1991
1992
1993 } else {
1994
1995
1996
1997
1998
1999
2000
2001
2002 order_action_then_stop(action, remote_rsc, pe_order_none,
2003 data_set);
2004 }
2005 break;
2006
2007 default:
2008
2009 if (is_recurring_action(action)) {
2010
2011
2012
2013
2014 if(task != no_action) {
2015 order_start_then_action(remote_rsc, action,
2016 pe_order_implies_then, data_set);
2017 }
2018 } else {
2019 order_start_then_action(remote_rsc, action, pe_order_none,
2020 data_set);
2021 }
2022 break;
2023 }
2024 }
2025
2026 static enum remote_connection_state
2027 get_remote_node_state(pe_node_t *node)
2028 {
2029 pe_resource_t *remote_rsc = NULL;
2030 pe_node_t *cluster_node = NULL;
2031
2032 CRM_ASSERT(node);
2033
2034 remote_rsc = node->details->remote_rsc;
2035 CRM_ASSERT(remote_rsc);
2036
2037 cluster_node = pe__current_node(remote_rsc);
2038
2039
2040
2041
2042
2043 if(remote_rsc->next_role == RSC_ROLE_STOPPED || remote_rsc->allocated_to == NULL) {
2044
2045
2046 if (cluster_node && cluster_node->details->unclean) {
2047
2048
2049
2050 return remote_state_failed;
2051 }
2052
2053 if (!pcmk_is_set(remote_rsc->flags, pe_rsc_failed)) {
2054
2055 return remote_state_stopped;
2056 }
2057
2058
2059
2060 if ((remote_rsc->next_role == RSC_ROLE_STOPPED)
2061 && remote_rsc->remote_reconnect_ms
2062 && node->details->remote_was_fenced
2063 && !pe__shutdown_requested(node)) {
2064
2065
2066
2067
2068 return remote_state_unknown;
2069 }
2070
2071
2072
2073
2074
2075 return remote_state_failed;
2076
2077 } else if (cluster_node == NULL) {
2078
2079 return remote_state_unknown;
2080
2081 } else if(cluster_node->details->unclean == TRUE
2082 || cluster_node->details->online == FALSE) {
2083
2084 return remote_state_resting;
2085
2086 } else if (pcmk__list_of_multiple(remote_rsc->running_on)
2087 && remote_rsc->partial_migration_source
2088 && remote_rsc->partial_migration_target) {
2089
2090
2091
2092
2093 return remote_state_resting;
2094
2095 }
2096 return remote_state_alive;
2097 }
2098
2099
2100
2101
2102
2103 static void
2104 apply_remote_ordering(pe_action_t *action, pe_working_set_t *data_set)
2105 {
2106 pe_resource_t *remote_rsc = NULL;
2107 enum action_tasks task = text2task(action->task);
2108 enum remote_connection_state state = get_remote_node_state(action->node);
2109
2110 enum pe_ordering order_opts = pe_order_none;
2111
2112 if (action->rsc == NULL) {
2113 return;
2114 }
2115
2116 CRM_ASSERT(action->node);
2117 CRM_ASSERT(pe__is_guest_or_remote_node(action->node));
2118
2119 remote_rsc = action->node->details->remote_rsc;
2120 CRM_ASSERT(remote_rsc);
2121
2122 crm_trace("Order %s action %s relative to %s%s (state: %s)",
2123 action->task, action->uuid,
2124 pcmk_is_set(remote_rsc->flags, pe_rsc_failed)? "failed " : "",
2125 remote_rsc->id, state2text(state));
2126
2127 if (pcmk__strcase_any_of(action->task, CRMD_ACTION_MIGRATE, CRMD_ACTION_MIGRATED, NULL)) {
2128
2129
2130
2131 task = stop_rsc;
2132 }
2133
2134 switch (task) {
2135 case start_rsc:
2136 case action_promote:
2137 order_opts = pe_order_none;
2138
2139 if (state == remote_state_failed) {
2140
2141 pe__set_order_flags(order_opts, pe_order_implies_then);
2142 }
2143
2144
2145 order_start_then_action(remote_rsc, action, order_opts, data_set);
2146 break;
2147
2148 case stop_rsc:
2149 if(state == remote_state_alive) {
2150 order_action_then_stop(action, remote_rsc,
2151 pe_order_implies_first, data_set);
2152
2153 } else if(state == remote_state_failed) {
2154
2155
2156
2157
2158
2159
2160 pe_fence_node(data_set, action->node, "resources are active and the connection is unrecoverable", FALSE);
2161
2162 } else if(remote_rsc->next_role == RSC_ROLE_STOPPED) {
2163
2164
2165
2166
2167 order_action_then_stop(action, remote_rsc,
2168 pe_order_implies_first, data_set);
2169
2170 } else {
2171
2172
2173
2174 order_start_then_action(remote_rsc, action, pe_order_none, data_set);
2175 }
2176 break;
2177
2178 case action_demote:
2179
2180
2181
2182
2183 if(state == remote_state_resting || state == remote_state_unknown) {
2184 order_start_then_action(remote_rsc, action, pe_order_none,
2185 data_set);
2186 }
2187 break;
2188
2189 default:
2190
2191 if (is_recurring_action(action)) {
2192
2193
2194
2195
2196 order_start_then_action(remote_rsc, action,
2197 pe_order_implies_then, data_set);
2198
2199 } else {
2200 pe_node_t *cluster_node = pe__current_node(remote_rsc);
2201
2202 if(task == monitor_rsc && state == remote_state_failed) {
2203
2204
2205
2206
2207
2208 pe_fence_node(data_set, action->node, "resources are in an unknown state and the connection is unrecoverable", FALSE);
2209 }
2210
2211 if(cluster_node && state == remote_state_stopped) {
2212
2213
2214
2215
2216
2217
2218
2219 order_action_then_stop(action, remote_rsc,
2220 pe_order_runnable_left, data_set);
2221
2222 } else {
2223 order_start_then_action(remote_rsc, action, pe_order_none,
2224 data_set);
2225 }
2226 }
2227 break;
2228 }
2229 }
2230
2231 static void
2232 apply_remote_node_ordering(pe_working_set_t *data_set)
2233 {
2234 if (!pcmk_is_set(data_set->flags, pe_flag_have_remote_nodes)) {
2235 return;
2236 }
2237
2238 for (GListPtr gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2239 pe_action_t *action = (pe_action_t *) gIter->data;
2240 pe_resource_t *remote = NULL;
2241
2242
2243 if (action->rsc == NULL) {
2244 continue;
2245 }
2246
2247
2248
2249
2250
2251 if (action->rsc->is_remote_node &&
2252 pcmk__str_eq(action->task, CRM_OP_CLEAR_FAILCOUNT, pcmk__str_casei)) {
2253
2254 custom_action_order(action->rsc,
2255 NULL,
2256 action,
2257 action->rsc,
2258 pcmk__op_key(action->rsc->id, RSC_START, 0),
2259 NULL,
2260 pe_order_optional,
2261 data_set);
2262
2263 continue;
2264 }
2265
2266
2267 if (action->node == NULL) {
2268 continue;
2269 }
2270
2271 if (!pe__is_guest_or_remote_node(action->node)) {
2272 continue;
2273 }
2274
2275
2276
2277
2278
2279
2280
2281 if (pcmk_is_set(action->flags, pe_action_pseudo)) {
2282 continue;
2283 }
2284
2285 remote = action->node->details->remote_rsc;
2286 if (remote == NULL) {
2287
2288 continue;
2289 }
2290
2291
2292
2293
2294
2295
2296 if (pcmk__str_eq(action->task, RSC_START, pcmk__str_casei)) {
2297 for (GList *item = action->rsc->actions; item != NULL;
2298 item = item->next) {
2299 pe_action_t *rsc_action = item->data;
2300
2301 if ((rsc_action->node->details != action->node->details)
2302 && pcmk__str_eq(rsc_action->task, RSC_STOP, pcmk__str_casei)) {
2303 custom_action_order(remote, start_key(remote), NULL,
2304 action->rsc, NULL, rsc_action,
2305 pe_order_optional, data_set);
2306 }
2307 }
2308 }
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319 if (remote->container) {
2320 crm_trace("Container ordering for %s", action->uuid);
2321 apply_container_ordering(action, data_set);
2322
2323 } else {
2324 crm_trace("Remote ordering for %s", action->uuid);
2325 apply_remote_ordering(action, data_set);
2326 }
2327 }
2328 }
2329
2330 static gboolean
2331 order_first_probe_unneeded(pe_action_t * probe, pe_action_t * rh_action)
2332 {
2333
2334
2335
2336
2337
2338 if (pcmk__str_eq(rh_action->task, CRM_OP_FENCE, pcmk__str_casei)
2339 && probe->node && rh_action->node
2340 && probe->node->details == rh_action->node->details) {
2341 const char *op = g_hash_table_lookup(rh_action->meta, "stonith_action");
2342
2343 if (pcmk__str_eq(op, "on", pcmk__str_casei)) {
2344 return TRUE;
2345 }
2346 }
2347
2348
2349 if ((pcmk__str_eq(rh_action->task, CRM_OP_SHUTDOWN, pcmk__str_casei))
2350 && probe->node && rh_action->node
2351 && probe->node->details != rh_action->node->details) {
2352 return TRUE;
2353 }
2354 return FALSE;
2355 }
2356
2357 static void
2358 order_first_probes_imply_stops(pe_working_set_t * data_set)
2359 {
2360 GListPtr gIter = NULL;
2361
2362 for (gIter = data_set->ordering_constraints; gIter != NULL; gIter = gIter->next) {
2363 pe__ordering_t *order = gIter->data;
2364 enum pe_ordering order_type = pe_order_optional;
2365
2366 pe_resource_t *lh_rsc = order->lh_rsc;
2367 pe_resource_t *rh_rsc = order->rh_rsc;
2368 pe_action_t *lh_action = order->lh_action;
2369 pe_action_t *rh_action = order->rh_action;
2370 const char *lh_action_task = order->lh_action_task;
2371 const char *rh_action_task = order->rh_action_task;
2372
2373 GListPtr probes = NULL;
2374 GListPtr rh_actions = NULL;
2375
2376 GListPtr pIter = NULL;
2377
2378 if (lh_rsc == NULL) {
2379 continue;
2380
2381 } else if (rh_rsc && lh_rsc == rh_rsc) {
2382 continue;
2383 }
2384
2385 if (lh_action == NULL && lh_action_task == NULL) {
2386 continue;
2387 }
2388
2389 if (rh_action == NULL && rh_action_task == NULL) {
2390 continue;
2391 }
2392
2393
2394
2395
2396
2397 if (lh_action && !pcmk__str_eq(lh_action->task, RSC_STOP, pcmk__str_casei)) {
2398 continue;
2399
2400 } else if (lh_action == NULL
2401 && lh_action_task
2402 && !pcmk__ends_with(lh_action_task, "_" RSC_STOP "_0")) {
2403 continue;
2404 }
2405
2406
2407
2408
2409
2410 if (rh_rsc && lh_rsc->container == rh_rsc) {
2411 if (rh_action && pcmk__str_eq(rh_action->task, RSC_STOP, pcmk__str_casei)) {
2412 continue;
2413
2414 } else if (rh_action == NULL && rh_action_task
2415 && pcmk__ends_with(rh_action_task,"_" RSC_STOP "_0")) {
2416 continue;
2417 }
2418 }
2419
2420 if (order->type == pe_order_none) {
2421 continue;
2422 }
2423
2424
2425 if (pcmk_is_set(order->type, pe_order_apply_first_non_migratable)) {
2426 pe__set_order_flags(order_type,
2427 pe_order_apply_first_non_migratable);
2428 }
2429
2430 if (pcmk_is_set(order->type, pe_order_same_node)) {
2431 pe__set_order_flags(order_type, pe_order_same_node);
2432 }
2433
2434
2435 if (order->type == pe_order_anti_colocation
2436 || order->type == pe_order_load) {
2437 order_type = order->type;
2438 }
2439
2440 probes = pe__resource_actions(lh_rsc, NULL, RSC_STATUS, FALSE);
2441 if (probes == NULL) {
2442 continue;
2443 }
2444
2445 if (rh_action) {
2446 rh_actions = g_list_prepend(rh_actions, rh_action);
2447
2448 } else if (rh_rsc && rh_action_task) {
2449 rh_actions = find_actions(rh_rsc->actions, rh_action_task, NULL);
2450 }
2451
2452 if (rh_actions == NULL) {
2453 g_list_free(probes);
2454 continue;
2455 }
2456
2457 crm_trace("Processing for LH probe based on ordering constraint %s -> %s"
2458 " (id=%d, type=%.6x)",
2459 lh_action ? lh_action->uuid : lh_action_task,
2460 rh_action ? rh_action->uuid : rh_action_task,
2461 order->id, order->type);
2462
2463 for (pIter = probes; pIter != NULL; pIter = pIter->next) {
2464 pe_action_t *probe = (pe_action_t *) pIter->data;
2465 GListPtr rIter = NULL;
2466
2467 for (rIter = rh_actions; rIter != NULL; rIter = rIter->next) {
2468 pe_action_t *rh_action_iter = (pe_action_t *) rIter->data;
2469
2470 if (order_first_probe_unneeded(probe, rh_action_iter)) {
2471 continue;
2472 }
2473 order_actions(probe, rh_action_iter, order_type);
2474 }
2475 }
2476
2477 g_list_free(rh_actions);
2478 g_list_free(probes);
2479 }
2480 }
2481
2482 static void
2483 order_first_probe_then_restart_repromote(pe_action_t * probe,
2484 pe_action_t * after,
2485 pe_working_set_t * data_set)
2486 {
2487 GListPtr gIter = NULL;
2488 bool interleave = FALSE;
2489 pe_resource_t *compatible_rsc = NULL;
2490
2491 if (probe == NULL
2492 || probe->rsc == NULL
2493 || probe->rsc->variant != pe_native) {
2494 return;
2495 }
2496
2497 if (after == NULL
2498
2499 || pcmk_is_set(after->flags, pe_action_tracking)) {
2500 return;
2501 }
2502
2503 if (!pcmk__str_eq(probe->task, RSC_STATUS, pcmk__str_casei)) {
2504 return;
2505 }
2506
2507 pe__set_action_flags(after, pe_action_tracking);
2508
2509 crm_trace("Processing based on %s %s -> %s %s",
2510 probe->uuid,
2511 probe->node ? probe->node->details->uname: "",
2512 after->uuid,
2513 after->node ? after->node->details->uname : "");
2514
2515 if (after->rsc
2516
2517
2518
2519
2520 && after->rsc->variant == pe_native
2521 && probe->rsc != after->rsc) {
2522
2523 GListPtr then_actions = NULL;
2524 enum pe_ordering probe_order_type = pe_order_optional;
2525
2526 if (pcmk__str_eq(after->task, RSC_START, pcmk__str_casei)) {
2527 then_actions = pe__resource_actions(after->rsc, NULL, RSC_STOP, FALSE);
2528
2529 } else if (pcmk__str_eq(after->task, RSC_PROMOTE, pcmk__str_casei)) {
2530 then_actions = pe__resource_actions(after->rsc, NULL, RSC_DEMOTE, FALSE);
2531 }
2532
2533 for (gIter = then_actions; gIter != NULL; gIter = gIter->next) {
2534 pe_action_t *then = (pe_action_t *) gIter->data;
2535
2536
2537 if (pcmk_is_set(then->flags, pe_action_pseudo)) {
2538 continue;
2539 }
2540
2541 order_actions(probe, then, probe_order_type);
2542 }
2543 g_list_free(then_actions);
2544 }
2545
2546 if (after->rsc
2547 && after->rsc->variant > pe_group) {
2548 const char *interleave_s = g_hash_table_lookup(after->rsc->meta,
2549 XML_RSC_ATTR_INTERLEAVE);
2550
2551 interleave = crm_is_true(interleave_s);
2552
2553 if (interleave) {
2554
2555
2556
2557 compatible_rsc = find_compatible_child(probe->rsc,
2558 after->rsc,
2559 RSC_ROLE_UNKNOWN,
2560 FALSE, data_set);
2561 }
2562 }
2563
2564 for (gIter = after->actions_after; gIter != NULL; gIter = gIter->next) {
2565 pe_action_wrapper_t *after_wrapper = (pe_action_wrapper_t *) gIter->data;
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575 if (!pcmk_is_set(after_wrapper->type, pe_order_implies_then)) {
2576
2577
2578
2579
2580
2581
2582
2583 if (after->rsc == NULL
2584 || after->rsc->variant < pe_group
2585 || probe->rsc->parent == after->rsc
2586 || after_wrapper->action->rsc == NULL
2587 || after_wrapper->action->rsc->variant > pe_group
2588 || after->rsc != after_wrapper->action->rsc->parent) {
2589 continue;
2590 }
2591
2592
2593
2594
2595 if (after->rsc->variant > pe_group
2596 && interleave == TRUE
2597 && (compatible_rsc == NULL
2598 || compatible_rsc != after_wrapper->action->rsc)) {
2599 continue;
2600 }
2601 }
2602
2603 crm_trace("Proceeding through %s %s -> %s %s (type=0x%.6x)",
2604 after->uuid,
2605 after->node ? after->node->details->uname: "",
2606 after_wrapper->action->uuid,
2607 after_wrapper->action->node ? after_wrapper->action->node->details->uname : "",
2608 after_wrapper->type);
2609
2610 order_first_probe_then_restart_repromote(probe, after_wrapper->action, data_set);
2611 }
2612 }
2613
2614 static void clear_actions_tracking_flag(pe_working_set_t * data_set)
2615 {
2616 GListPtr gIter = NULL;
2617
2618 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2619 pe_action_t *action = (pe_action_t *) gIter->data;
2620
2621 if (pcmk_is_set(action->flags, pe_action_tracking)) {
2622 pe__clear_action_flags(action, pe_action_tracking);
2623 }
2624 }
2625 }
2626
2627 static void
2628 order_first_rsc_probes(pe_resource_t * rsc, pe_working_set_t * data_set)
2629 {
2630 GListPtr gIter = NULL;
2631 GListPtr probes = NULL;
2632
2633 for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
2634 pe_resource_t * child = (pe_resource_t *) gIter->data;
2635
2636 order_first_rsc_probes(child, data_set);
2637 }
2638
2639 if (rsc->variant != pe_native) {
2640 return;
2641 }
2642
2643 probes = pe__resource_actions(rsc, NULL, RSC_STATUS, FALSE);
2644
2645 for (gIter = probes; gIter != NULL; gIter= gIter->next) {
2646 pe_action_t *probe = (pe_action_t *) gIter->data;
2647 GListPtr aIter = NULL;
2648
2649 for (aIter = probe->actions_after; aIter != NULL; aIter = aIter->next) {
2650 pe_action_wrapper_t *after_wrapper = (pe_action_wrapper_t *) aIter->data;
2651
2652 order_first_probe_then_restart_repromote(probe, after_wrapper->action, data_set);
2653 clear_actions_tracking_flag(data_set);
2654 }
2655 }
2656
2657 g_list_free(probes);
2658 }
2659
2660 static void
2661 order_first_probes(pe_working_set_t * data_set)
2662 {
2663 GListPtr gIter = NULL;
2664
2665 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
2666 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2667
2668 order_first_rsc_probes(rsc, data_set);
2669 }
2670
2671 order_first_probes_imply_stops(data_set);
2672 }
2673
2674 static void
2675 order_then_probes(pe_working_set_t * data_set)
2676 {
2677 #if 0
2678 GListPtr gIter = NULL;
2679
2680 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
2681 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725 pe_action_t *start = NULL;
2726 GListPtr actions = NULL;
2727 GListPtr probes = NULL;
2728
2729 actions = pe__resource_actions(rsc, NULL, RSC_START, FALSE);
2730
2731 if (actions) {
2732 start = actions->data;
2733 g_list_free(actions);
2734 }
2735
2736 if(start == NULL) {
2737 crm_err("No start action for %s", rsc->id);
2738 continue;
2739 }
2740
2741 probes = pe__resource_actions(rsc, NULL, RSC_STATUS, FALSE);
2742
2743 for (actions = start->actions_before; actions != NULL; actions = actions->next) {
2744 pe_action_wrapper_t *before = (pe_action_wrapper_t *) actions->data;
2745
2746 GListPtr pIter = NULL;
2747 pe_action_t *first = before->action;
2748 pe_resource_t *first_rsc = first->rsc;
2749
2750 if(first->required_runnable_before) {
2751 GListPtr clone_actions = NULL;
2752 for (clone_actions = first->actions_before; clone_actions != NULL; clone_actions = clone_actions->next) {
2753 before = (pe_action_wrapper_t *) clone_actions->data;
2754
2755 crm_trace("Testing %s -> %s (%p) for %s", first->uuid, before->action->uuid, before->action->rsc, start->uuid);
2756
2757 CRM_ASSERT(before->action->rsc);
2758 first_rsc = before->action->rsc;
2759 break;
2760 }
2761
2762 } else if(!pcmk__str_eq(first->task, RSC_START, pcmk__str_casei)) {
2763 crm_trace("Not a start op %s for %s", first->uuid, start->uuid);
2764 }
2765
2766 if(first_rsc == NULL) {
2767 continue;
2768
2769 } else if(uber_parent(first_rsc) == uber_parent(start->rsc)) {
2770 crm_trace("Same parent %s for %s", first_rsc->id, start->uuid);
2771 continue;
2772
2773 } else if(FALSE && pe_rsc_is_clone(uber_parent(first_rsc)) == FALSE) {
2774 crm_trace("Not a clone %s for %s", first_rsc->id, start->uuid);
2775 continue;
2776 }
2777
2778 crm_err("Applying %s before %s %d", first->uuid, start->uuid, uber_parent(first_rsc)->variant);
2779
2780 for (pIter = probes; pIter != NULL; pIter = pIter->next) {
2781 pe_action_t *probe = (pe_action_t *) pIter->data;
2782
2783 crm_err("Ordering %s before %s", first->uuid, probe->uuid);
2784 order_actions(first, probe, pe_order_optional);
2785 }
2786 }
2787 }
2788 #endif
2789 }
2790
2791 static void
2792 order_probes(pe_working_set_t * data_set)
2793 {
2794 order_first_probes(data_set);
2795 order_then_probes(data_set);
2796 }
2797
2798 gboolean
2799 stage7(pe_working_set_t * data_set)
2800 {
2801 GList *gIter = NULL;
2802
2803 crm_trace("Applying ordering constraints");
2804
2805
2806
2807
2808
2809
2810
2811 data_set->ordering_constraints = g_list_reverse(data_set->ordering_constraints);
2812
2813 for (gIter = data_set->ordering_constraints; gIter != NULL; gIter = gIter->next) {
2814 pe__ordering_t *order = gIter->data;
2815 pe_resource_t *rsc = order->lh_rsc;
2816
2817 crm_trace("Applying ordering constraint: %d", order->id);
2818
2819 if (rsc != NULL) {
2820 crm_trace("rsc_action-to-*");
2821 rsc_order_first(rsc, order, data_set);
2822 continue;
2823 }
2824
2825 rsc = order->rh_rsc;
2826 if (rsc != NULL) {
2827 crm_trace("action-to-rsc_action");
2828 rsc_order_then(order->lh_action, rsc, order);
2829
2830 } else {
2831 crm_trace("action-to-action");
2832 order_actions(order->lh_action, order->rh_action, order->type);
2833 }
2834 }
2835
2836 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2837 pe_action_t *action = (pe_action_t *) gIter->data;
2838
2839 update_colo_start_chain(action, data_set);
2840 }
2841
2842 crm_trace("Ordering probes");
2843 order_probes(data_set);
2844
2845 crm_trace("Updating %d actions", g_list_length(data_set->actions));
2846 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2847 pe_action_t *action = (pe_action_t *) gIter->data;
2848
2849 update_action(action, data_set);
2850 }
2851
2852
2853 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
2854 pe_action_t *action = (pe_action_t *) gIter->data;
2855 pe_action_wrapper_t *input = NULL;
2856
2857 for (GList *input_iter = action->actions_before;
2858 input_iter != NULL; input_iter = input_iter->next) {
2859
2860 input = (pe_action_wrapper_t *) input_iter->data;
2861 if (pcmk__ordering_is_invalid(action, input)) {
2862 input->type = pe_order_none;
2863 }
2864 }
2865 }
2866
2867 LogNodeActions(data_set, FALSE);
2868 for (gIter = data_set->resources; gIter != NULL; gIter = gIter->next) {
2869 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2870
2871 LogActions(rsc, data_set, FALSE);
2872 }
2873 return TRUE;
2874 }
2875
2876 static int transition_id = -1;
2877
2878
2879
2880
2881
2882
2883
2884 void
2885 pcmk__log_transition_summary(const char *filename)
2886 {
2887 if (was_processing_error) {
2888 crm_err("Calculated transition %d (with errors), saving inputs in %s",
2889 transition_id, filename);
2890
2891 } else if (was_processing_warning) {
2892 crm_warn("Calculated transition %d (with warnings), saving inputs in %s",
2893 transition_id, filename);
2894
2895 } else {
2896 crm_notice("Calculated transition %d, saving inputs in %s",
2897 transition_id, filename);
2898 }
2899 if (pcmk__config_error) {
2900 crm_notice("Configuration errors found during scheduler processing,"
2901 " please run \"crm_verify -L\" to identify issues");
2902 }
2903 }
2904
2905
2906
2907
2908 gboolean
2909 stage8(pe_working_set_t * data_set)
2910 {
2911 GListPtr gIter = NULL;
2912 const char *value = NULL;
2913
2914 transition_id++;
2915 crm_trace("Creating transition graph %d.", transition_id);
2916
2917 data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH);
2918
2919 value = pe_pref(data_set->config_hash, "cluster-delay");
2920 crm_xml_add(data_set->graph, "cluster-delay", value);
2921
2922 value = pe_pref(data_set->config_hash, "stonith-timeout");
2923 crm_xml_add(data_set->graph, "stonith-timeout", value);
2924
2925 crm_xml_add(data_set->graph, "failed-stop-offset", "INFINITY");
2926
2927 if (pcmk_is_set(data_set->flags, pe_flag_start_failure_fatal)) {
2928 crm_xml_add(data_set->graph, "failed-start-offset", "INFINITY");
2929 } else {
2930 crm_xml_add(data_set->graph, "failed-start-offset", "1");
2931 }
2932
2933 value = pe_pref(data_set->config_hash, "batch-limit");
2934 crm_xml_add(data_set->graph, "batch-limit", value);
2935
2936 crm_xml_add_int(data_set->graph, "transition_id", transition_id);
2937
2938 value = pe_pref(data_set->config_hash, "migration-limit");
2939 if (crm_parse_ll(value, NULL) > 0) {
2940 crm_xml_add(data_set->graph, "migration-limit", value);
2941 }
2942
2943 if (data_set->recheck_by > 0) {
2944 char *recheck_epoch = NULL;
2945
2946 recheck_epoch = crm_strdup_printf("%llu",
2947 (long long) data_set->recheck_by);
2948 crm_xml_add(data_set->graph, "recheck-by", recheck_epoch);
2949 free(recheck_epoch);
2950 }
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965 gIter = data_set->resources;
2966 for (; gIter != NULL; gIter = gIter->next) {
2967 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2968
2969 pe_rsc_trace(rsc, "processing actions for rsc=%s", rsc->id);
2970 rsc->cmds->expand(rsc, data_set);
2971 }
2972
2973 crm_log_xml_trace(data_set->graph, "created resource-driven action list");
2974
2975
2976 add_maintenance_update(data_set);
2977
2978
2979 crm_trace("processing non-resource actions");
2980
2981 gIter = data_set->actions;
2982 for (; gIter != NULL; gIter = gIter->next) {
2983 pe_action_t *action = (pe_action_t *) gIter->data;
2984
2985 if (action->rsc
2986 && action->node
2987 && action->node->details->shutdown
2988 && !pcmk_is_set(action->rsc->flags, pe_rsc_maintenance)
2989 && !pcmk_any_flags_set(action->flags,
2990 pe_action_optional|pe_action_runnable)
2991 && pcmk__str_eq(action->task, RSC_STOP, pcmk__str_none)
2992 ) {
2993
2994
2995
2996
2997 if (pcmk_is_set(data_set->flags, pe_flag_have_quorum)
2998 || data_set->no_quorum_policy == no_quorum_ignore) {
2999 crm_crit("Cannot %s node '%s' because of %s:%s%s (%s)",
3000 action->node->details->unclean ? "fence" : "shut down",
3001 action->node->details->uname, action->rsc->id,
3002 pcmk_is_set(action->rsc->flags, pe_rsc_managed)? " blocked" : " unmanaged",
3003 pcmk_is_set(action->rsc->flags, pe_rsc_failed)? " failed" : "",
3004 action->uuid);
3005 }
3006 }
3007
3008 graph_element_from_action(action, data_set);
3009 }
3010
3011 crm_log_xml_trace(data_set->graph, "created generic action list");
3012 crm_trace("Created transition graph %d.", transition_id);
3013
3014 return TRUE;
3015 }
3016
3017 void
3018 LogNodeActions(pe_working_set_t * data_set, gboolean terminal)
3019 {
3020 GListPtr gIter = NULL;
3021
3022 for (gIter = data_set->actions; gIter != NULL; gIter = gIter->next) {
3023 char *node_name = NULL;
3024 char *task = NULL;
3025 pe_action_t *action = (pe_action_t *) gIter->data;
3026
3027 if (action->rsc != NULL) {
3028 continue;
3029 } else if (pcmk_is_set(action->flags, pe_action_optional)) {
3030 continue;
3031 }
3032
3033 if (pe__is_guest_node(action->node)) {
3034 node_name = crm_strdup_printf("%s (resource: %s)", action->node->details->uname, action->node->details->remote_rsc->container->id);
3035 } else if(action->node) {
3036 node_name = crm_strdup_printf("%s", action->node->details->uname);
3037 }
3038
3039
3040 if (pcmk__str_eq(action->task, CRM_OP_SHUTDOWN, pcmk__str_casei)) {
3041 task = strdup("Shutdown");
3042 } else if (pcmk__str_eq(action->task, CRM_OP_FENCE, pcmk__str_casei)) {
3043 const char *op = g_hash_table_lookup(action->meta, "stonith_action");
3044 task = crm_strdup_printf("Fence (%s)", op);
3045 }
3046
3047 if(task == NULL) {
3048
3049 } else if(terminal && action->reason) {
3050 printf(" * %s %s '%s'\n", task, node_name, action->reason);
3051 } else if(terminal) {
3052 printf(" * %s %s\n", task, node_name);
3053 } else if(action->reason) {
3054 crm_notice(" * %s %s '%s'\n", task, node_name, action->reason);
3055 } else {
3056 crm_notice(" * %s %s\n", task, node_name);
3057 }
3058
3059 free(node_name);
3060 free(task);
3061 }
3062 }