This source file includes following definitions.
- pe_rsc_action_details
- pe_free_rsc_action_details
- pe_can_fence
- pe__copy_node
- node_list_exclude
- pe__node_list2table
- sort_node_uname
- pe__output_node_weights
- pe__log_node_weights
- pe__show_node_weights_as
- sort_rsc_index
- sort_rsc_priority
- effective_quorum_policy
- add_singleton
- lookup_singleton
- find_existing_action
- new_action
- unpack_action_node_attributes
- update_action_optional
- update_resource_action_runnable
- update_resource_flags_for_action
- custom_action
- valid_stop_on_fail
- unpack_operation_on_fail
- find_min_interval_mon
- unpack_start_delay
- unpack_interval_origin
- unpack_timeout
- pe_get_configured_timeout
- unpack_versioned_meta
- unpack_operation
- find_rsc_op_entry_helper
- find_rsc_op_entry
- print_str_str
- pe_free_action
- find_recurring_actions
- get_complex_task
- find_first_action
- find_actions
- find_actions_exact
- pe__resource_actions
- resource_node_score
- resource_location
- sort_op_by_callid
- get_effective_time
- get_target_role
- order_actions
- get_pseudo_op
- destroy_ticket
- ticket_new
- rsc_printable_id
- pe__clear_resource_flags_recursive
- pe__clear_resource_flags_on_all
- pe__set_resource_flags_recursive
- find_unfencing_devices
- node_priority_fencing_delay
- pe_fence_op
- trigger_unfencing
- add_tag_ref
- pe__action2reason
- pe_action_set_reason
- pe__shutdown_requested
- pe__update_recheck_time
- pe__unpack_dataset_nvpairs
- pe__resource_is_disabled
- pe__clear_resource_history
- pe__rsc_running_on_any
- pcmk__rsc_filtered_by_node
- pe__filter_rsc_list
- pe__build_node_name_list
- pe__build_rsc_list
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/crm.h>
12 #include <crm/msg_xml.h>
13 #include <crm/common/xml.h>
14 #include <crm/common/xml_internal.h>
15 #include <crm/common/util.h>
16
17 #include <glib.h>
18 #include <stdbool.h>
19
20 #include <crm/pengine/rules.h>
21 #include <crm/pengine/internal.h>
22 #include "pe_status_private.h"
23
24 extern bool pcmk__is_daemon;
25
26 extern xmlNode *get_object_root(const char *object_type, xmlNode * the_root);
27 void print_str_str(gpointer key, gpointer value, gpointer user_data);
28 gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data);
29 static void unpack_operation(pe_action_t * action, xmlNode * xml_obj, pe_resource_t * container,
30 pe_working_set_t * data_set, guint interval_ms);
31 static xmlNode *find_rsc_op_entry_helper(pe_resource_t * rsc, const char *key,
32 gboolean include_disabled);
33
34 #if ENABLE_VERSIONED_ATTRS
35 pe_rsc_action_details_t *
36 pe_rsc_action_details(pe_action_t *action)
37 {
38 pe_rsc_action_details_t *details;
39
40 CRM_CHECK(action != NULL, return NULL);
41
42 if (action->action_details == NULL) {
43 action->action_details = calloc(1, sizeof(pe_rsc_action_details_t));
44 CRM_CHECK(action->action_details != NULL, return NULL);
45 }
46
47 details = (pe_rsc_action_details_t *) action->action_details;
48 if (details->versioned_parameters == NULL) {
49 details->versioned_parameters = create_xml_node(NULL,
50 XML_TAG_OP_VER_ATTRS);
51 }
52 if (details->versioned_meta == NULL) {
53 details->versioned_meta = create_xml_node(NULL, XML_TAG_OP_VER_META);
54 }
55 return details;
56 }
57
58 static void
59 pe_free_rsc_action_details(pe_action_t *action)
60 {
61 pe_rsc_action_details_t *details;
62
63 if ((action == NULL) || (action->action_details == NULL)) {
64 return;
65 }
66
67 details = (pe_rsc_action_details_t *) action->action_details;
68
69 if (details->versioned_parameters) {
70 free_xml(details->versioned_parameters);
71 }
72 if (details->versioned_meta) {
73 free_xml(details->versioned_meta);
74 }
75
76 action->action_details = NULL;
77 }
78 #endif
79
80
81
82
83
84
85
86
87
88
89 bool
90 pe_can_fence(pe_working_set_t *data_set, pe_node_t *node)
91 {
92 if (pe__is_guest_node(node)) {
93
94
95
96 pe_resource_t *rsc = node->details->remote_rsc->container;
97
98 for (GList *n = rsc->running_on; n != NULL; n = n->next) {
99 pe_node_t *container_node = n->data;
100
101 if (!container_node->details->online
102 && !pe_can_fence(data_set, container_node)) {
103 return false;
104 }
105 }
106 return true;
107
108 } else if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
109 return false;
110
111 } else if (!pcmk_is_set(data_set->flags, pe_flag_have_stonith_resource)) {
112 return false;
113
114 } else if (pcmk_is_set(data_set->flags, pe_flag_have_quorum)) {
115 return true;
116
117 } else if (data_set->no_quorum_policy == no_quorum_ignore) {
118 return true;
119
120 } else if(node == NULL) {
121 return false;
122
123 } else if(node->details->online) {
124 crm_notice("We can fence %s without quorum because they're in our membership", node->details->uname);
125 return true;
126 }
127
128 crm_trace("Cannot fence %s", node->details->uname);
129 return false;
130 }
131
132
133
134
135
136
137
138
139
140
141 pe_node_t *
142 pe__copy_node(const pe_node_t *this_node)
143 {
144 pe_node_t *new_node = NULL;
145
146 CRM_ASSERT(this_node != NULL);
147
148 new_node = calloc(1, sizeof(pe_node_t));
149 CRM_ASSERT(new_node != NULL);
150
151 new_node->rsc_discover_mode = this_node->rsc_discover_mode;
152 new_node->weight = this_node->weight;
153 new_node->fixed = this_node->fixed;
154 new_node->details = this_node->details;
155
156 return new_node;
157 }
158
159
160 void
161 node_list_exclude(GHashTable * hash, GList *list, gboolean merge_scores)
162 {
163 GHashTable *result = hash;
164 pe_node_t *other_node = NULL;
165 GList *gIter = list;
166
167 GHashTableIter iter;
168 pe_node_t *node = NULL;
169
170 g_hash_table_iter_init(&iter, hash);
171 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
172
173 other_node = pe_find_node_id(list, node->details->id);
174 if (other_node == NULL) {
175 node->weight = -INFINITY;
176 } else if (merge_scores) {
177 node->weight = pe__add_scores(node->weight, other_node->weight);
178 }
179 }
180
181 for (; gIter != NULL; gIter = gIter->next) {
182 pe_node_t *node = (pe_node_t *) gIter->data;
183
184 other_node = pe_hash_table_lookup(result, node->details->id);
185
186 if (other_node == NULL) {
187 pe_node_t *new_node = pe__copy_node(node);
188
189 new_node->weight = -INFINITY;
190 g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
191 }
192 }
193 }
194
195
196
197
198
199
200
201
202
203 GHashTable *
204 pe__node_list2table(GList *list)
205 {
206 GHashTable *result = NULL;
207
208 result = pcmk__strkey_table(NULL, free);
209 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
210 pe_node_t *new_node = pe__copy_node((pe_node_t *) gIter->data);
211
212 g_hash_table_insert(result, (gpointer) new_node->details->id, new_node);
213 }
214 return result;
215 }
216
217 gint
218 sort_node_uname(gconstpointer a, gconstpointer b)
219 {
220 return pcmk__numeric_strcasecmp(((const pe_node_t *) a)->details->uname,
221 ((const pe_node_t *) b)->details->uname);
222 }
223
224
225
226
227
228
229
230
231
232 static void
233 pe__output_node_weights(pe_resource_t *rsc, const char *comment,
234 GHashTable *nodes, pe_working_set_t *data_set)
235 {
236 pcmk__output_t *out = data_set->priv;
237 char score[128];
238
239
240 GList *list = g_list_sort(g_hash_table_get_values(nodes), sort_node_uname);
241
242 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
243 pe_node_t *node = (pe_node_t *) gIter->data;
244
245 score2char_stack(node->weight, score, sizeof(score));
246 out->message(out, "node-weight", rsc, comment, node->details->uname, score);
247 }
248 g_list_free(list);
249 }
250
251
252
253
254
255
256
257
258
259
260
261
262 static void
263 pe__log_node_weights(const char *file, const char *function, int line,
264 pe_resource_t *rsc, const char *comment, GHashTable *nodes)
265 {
266 GHashTableIter iter;
267 pe_node_t *node = NULL;
268 char score[128];
269
270
271 pcmk__log_else(LOG_TRACE, return);
272
273 g_hash_table_iter_init(&iter, nodes);
274 while (g_hash_table_iter_next(&iter, NULL, (void **) &node)) {
275 score2char_stack(node->weight, score, sizeof(score));
276 if (rsc) {
277 qb_log_from_external_source(function, file,
278 "%s: %s allocation score on %s: %s",
279 LOG_TRACE, line, 0,
280 comment, rsc->id,
281 node->details->uname, score);
282 } else {
283 qb_log_from_external_source(function, file, "%s: %s = %s",
284 LOG_TRACE, line, 0,
285 comment, node->details->uname,
286 score);
287 }
288 }
289 }
290
291
292
293
294
295
296
297
298
299
300
301
302
303 void
304 pe__show_node_weights_as(const char *file, const char *function, int line,
305 bool to_log, pe_resource_t *rsc, const char *comment,
306 GHashTable *nodes, pe_working_set_t *data_set)
307 {
308 if (rsc != NULL && pcmk_is_set(rsc->flags, pe_rsc_orphan)) {
309
310 return;
311 }
312 if (nodes == NULL) {
313
314 return;
315 }
316
317 if (to_log) {
318 pe__log_node_weights(file, function, line, rsc, comment, nodes);
319 } else {
320 pe__output_node_weights(rsc, comment, nodes, data_set);
321 }
322
323
324 if (rsc && rsc->children) {
325 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
326 pe_resource_t *child = (pe_resource_t *) gIter->data;
327
328 pe__show_node_weights_as(file, function, line, to_log, child,
329 comment, child->allowed_nodes, data_set);
330 }
331 }
332 }
333
334 gint
335 sort_rsc_index(gconstpointer a, gconstpointer b)
336 {
337 const pe_resource_t *resource1 = (const pe_resource_t *)a;
338 const pe_resource_t *resource2 = (const pe_resource_t *)b;
339
340 if (a == NULL && b == NULL) {
341 return 0;
342 }
343 if (a == NULL) {
344 return 1;
345 }
346 if (b == NULL) {
347 return -1;
348 }
349
350 if (resource1->sort_index > resource2->sort_index) {
351 return -1;
352 }
353
354 if (resource1->sort_index < resource2->sort_index) {
355 return 1;
356 }
357
358 return 0;
359 }
360
361 gint
362 sort_rsc_priority(gconstpointer a, gconstpointer b)
363 {
364 const pe_resource_t *resource1 = (const pe_resource_t *)a;
365 const pe_resource_t *resource2 = (const pe_resource_t *)b;
366
367 if (a == NULL && b == NULL) {
368 return 0;
369 }
370 if (a == NULL) {
371 return 1;
372 }
373 if (b == NULL) {
374 return -1;
375 }
376
377 if (resource1->priority > resource2->priority) {
378 return -1;
379 }
380
381 if (resource1->priority < resource2->priority) {
382 return 1;
383 }
384
385 return 0;
386 }
387
388 static enum pe_quorum_policy
389 effective_quorum_policy(pe_resource_t *rsc, pe_working_set_t *data_set)
390 {
391 enum pe_quorum_policy policy = data_set->no_quorum_policy;
392
393 if (pcmk_is_set(data_set->flags, pe_flag_have_quorum)) {
394 policy = no_quorum_ignore;
395
396 } else if (data_set->no_quorum_policy == no_quorum_demote) {
397 switch (rsc->role) {
398 case RSC_ROLE_PROMOTED:
399 case RSC_ROLE_UNPROMOTED:
400 if (rsc->next_role > RSC_ROLE_UNPROMOTED) {
401 pe__set_next_role(rsc, RSC_ROLE_UNPROMOTED,
402 "no-quorum-policy=demote");
403 }
404 policy = no_quorum_ignore;
405 break;
406 default:
407 policy = no_quorum_stop;
408 break;
409 }
410 }
411 return policy;
412 }
413
414 static void
415 add_singleton(pe_working_set_t *data_set, pe_action_t *action)
416 {
417 if (data_set->singletons == NULL) {
418 data_set->singletons = pcmk__strkey_table(NULL, NULL);
419 }
420 g_hash_table_insert(data_set->singletons, action->uuid, action);
421 }
422
423 static pe_action_t *
424 lookup_singleton(pe_working_set_t *data_set, const char *action_uuid)
425 {
426 if (data_set->singletons == NULL) {
427 return NULL;
428 }
429 return g_hash_table_lookup(data_set->singletons, action_uuid);
430 }
431
432
433
434
435
436
437
438
439
440
441
442
443 static pe_action_t *
444 find_existing_action(const char *key, pe_resource_t *rsc, pe_node_t *node,
445 pe_working_set_t *data_set)
446 {
447 GList *matches = NULL;
448 pe_action_t *action = NULL;
449
450
451
452
453 matches = find_actions(((rsc == NULL)? data_set->actions : rsc->actions),
454 key, node);
455 if (matches == NULL) {
456 return NULL;
457 }
458 CRM_LOG_ASSERT(!pcmk__list_of_multiple(matches));
459
460 action = matches->data;
461 g_list_free(matches);
462 return action;
463 }
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481 static pe_action_t *
482 new_action(char *key, const char *task, pe_resource_t *rsc, pe_node_t *node,
483 bool optional, bool for_graph, pe_working_set_t *data_set)
484 {
485 pe_action_t *action = calloc(1, sizeof(pe_action_t));
486
487 CRM_ASSERT(action != NULL);
488
489 action->rsc = rsc;
490 action->task = strdup(task); CRM_ASSERT(action->task != NULL);
491 action->uuid = key;
492 action->extra = pcmk__strkey_table(free, free);
493 action->meta = pcmk__strkey_table(free, free);
494
495 if (node) {
496 action->node = pe__copy_node(node);
497 }
498
499 if (pcmk__str_eq(task, CRM_OP_LRM_DELETE, pcmk__str_casei)) {
500
501 pe__set_action_flags(action, pe_action_dc);
502 }
503
504 pe__set_action_flags(action, pe_action_runnable);
505 if (optional) {
506 pe__set_action_flags(action, pe_action_optional);
507 } else {
508 pe__clear_action_flags(action, pe_action_optional);
509 }
510
511 if (rsc != NULL) {
512 guint interval_ms = 0;
513
514 action->op_entry = find_rsc_op_entry_helper(rsc, key, TRUE);
515 parse_op_key(key, NULL, NULL, &interval_ms);
516 unpack_operation(action, action->op_entry, rsc->container, data_set,
517 interval_ms);
518 }
519
520 if (for_graph) {
521 pe_rsc_trace(rsc, "Created %s action %d (%s): %s for %s on %s",
522 (optional? "optional" : "required"),
523 data_set->action_id, key, task,
524 ((rsc == NULL)? "no resource" : rsc->id),
525 ((node == NULL)? "no node" : node->details->uname));
526 action->id = data_set->action_id++;
527
528 data_set->actions = g_list_prepend(data_set->actions, action);
529 if (rsc == NULL) {
530 add_singleton(data_set, action);
531 } else {
532 rsc->actions = g_list_prepend(rsc->actions, action);
533 }
534 }
535 return action;
536 }
537
538
539
540
541
542
543
544
545 static void
546 unpack_action_node_attributes(pe_action_t *action, pe_working_set_t *data_set)
547 {
548 if (!pcmk_is_set(action->flags, pe_action_have_node_attrs)
549 && (action->op_entry != NULL)) {
550
551 pe_rule_eval_data_t rule_data = {
552 .node_hash = action->node->details->attrs,
553 .role = RSC_ROLE_UNKNOWN,
554 .now = data_set->now,
555 .match_data = NULL,
556 .rsc_data = NULL,
557 .op_data = NULL
558 };
559
560 pe__set_action_flags(action, pe_action_have_node_attrs);
561 pe__unpack_dataset_nvpairs(action->op_entry, XML_TAG_ATTR_SETS,
562 &rule_data, action->extra, NULL,
563 FALSE, data_set);
564 }
565 }
566
567
568
569
570
571
572
573
574 static void
575 update_action_optional(pe_action_t *action, gboolean optional)
576 {
577
578 if ((action->rsc != NULL) && (action->node != NULL)
579 && !pcmk_is_set(action->flags, pe_action_pseudo)
580 && !pcmk_is_set(action->rsc->flags, pe_rsc_managed)
581 && (g_hash_table_lookup(action->meta,
582 XML_LRM_ATTR_INTERVAL_MS) == NULL)) {
583 pe_rsc_debug(action->rsc, "%s on %s is optional (%s is unmanaged)",
584 action->uuid, action->node->details->uname,
585 action->rsc->id);
586 pe__set_action_flags(action, pe_action_optional);
587
588
589
590 } else if (!optional) {
591 pe__clear_action_flags(action, pe_action_optional);
592 }
593 }
594
595
596
597
598
599
600
601
602
603
604
605 static void
606 update_resource_action_runnable(pe_action_t *action, bool for_graph,
607 pe_working_set_t *data_set)
608 {
609 if (pcmk_is_set(action->flags, pe_action_pseudo)) {
610 return;
611 }
612
613 if (action->node == NULL) {
614 pe_rsc_trace(action->rsc, "%s is unrunnable (unallocated)",
615 action->uuid);
616 pe__clear_action_flags(action, pe_action_runnable);
617
618 } else if (!pcmk_is_set(action->flags, pe_action_dc)
619 && !(action->node->details->online)
620 && (!pe__is_guest_node(action->node)
621 || action->node->details->remote_requires_reset)) {
622 pe__clear_action_flags(action, pe_action_runnable);
623 do_crm_log((for_graph? LOG_WARNING: LOG_TRACE),
624 "%s on %s is unrunnable (node is offline)",
625 action->uuid, action->node->details->uname);
626 if (pcmk_is_set(action->rsc->flags, pe_rsc_managed)
627 && for_graph
628 && pcmk__str_eq(action->task, CRMD_ACTION_STOP, pcmk__str_casei)
629 && !(action->node->details->unclean)) {
630 pe_fence_node(data_set, action->node, "stop is unrunnable", false);
631 }
632
633 } else if (!pcmk_is_set(action->flags, pe_action_dc)
634 && action->node->details->pending) {
635 pe__clear_action_flags(action, pe_action_runnable);
636 do_crm_log((for_graph? LOG_WARNING: LOG_TRACE),
637 "Action %s on %s is unrunnable (node is pending)",
638 action->uuid, action->node->details->uname);
639
640 } else if (action->needs == rsc_req_nothing) {
641 pe_action_set_reason(action, NULL, TRUE);
642 if (pe__is_guest_node(action->node)
643 && !pe_can_fence(data_set, action->node)) {
644
645
646
647
648
649 pe_rsc_debug(action->rsc, "%s on %s is unrunnable "
650 "(node's host cannot be fenced)",
651 action->uuid, action->node->details->uname);
652 pe__clear_action_flags(action, pe_action_runnable);
653 } else {
654 pe_rsc_trace(action->rsc,
655 "%s on %s does not require fencing or quorum",
656 action->uuid, action->node->details->uname);
657 pe__set_action_flags(action, pe_action_runnable);
658 }
659
660 } else {
661 switch (effective_quorum_policy(action->rsc, data_set)) {
662 case no_quorum_stop:
663 pe_rsc_debug(action->rsc, "%s on %s is unrunnable (no quorum)",
664 action->uuid, action->node->details->uname);
665 pe__clear_action_flags(action, pe_action_runnable);
666 pe_action_set_reason(action, "no quorum", true);
667 break;
668
669 case no_quorum_freeze:
670 if (!action->rsc->fns->active(action->rsc, TRUE)
671 || (action->rsc->next_role > action->rsc->role)) {
672 pe_rsc_debug(action->rsc,
673 "%s on %s is unrunnable (no quorum)",
674 action->uuid, action->node->details->uname);
675 pe__clear_action_flags(action, pe_action_runnable);
676 pe_action_set_reason(action, "quorum freeze", true);
677 }
678 break;
679
680 default:
681
682 pe__set_action_flags(action, pe_action_runnable);
683 break;
684 }
685 }
686 }
687
688
689
690
691
692
693
694
695 static void
696 update_resource_flags_for_action(pe_resource_t *rsc, pe_action_t *action)
697 {
698
699
700
701 if (pcmk__str_eq(action->task, CRMD_ACTION_STOP, pcmk__str_casei)) {
702 pe__set_resource_flags(rsc, pe_rsc_stopping);
703
704 } else if (pcmk__str_eq(action->task, CRMD_ACTION_START, pcmk__str_casei)) {
705 if (pcmk_is_set(action->flags, pe_action_runnable)) {
706 pe__set_resource_flags(rsc, pe_rsc_starting);
707 } else {
708 pe__clear_resource_flags(rsc, pe_rsc_starting);
709 }
710 }
711 }
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730 pe_action_t *
731 custom_action(pe_resource_t *rsc, char *key, const char *task,
732 pe_node_t *on_node, gboolean optional, gboolean save_action,
733 pe_working_set_t *data_set)
734 {
735 pe_action_t *action = NULL;
736
737 CRM_ASSERT((key != NULL) && (task != NULL) && (data_set != NULL));
738
739 if (save_action) {
740 action = find_existing_action(key, rsc, on_node, data_set);
741 }
742
743 if (action == NULL) {
744 action = new_action(key, task, rsc, on_node, optional, save_action,
745 data_set);
746 } else {
747 free(key);
748 }
749
750 update_action_optional(action, optional);
751
752 if (rsc != NULL) {
753 if (action->node != NULL) {
754 unpack_action_node_attributes(action, data_set);
755 }
756
757 update_resource_action_runnable(action, save_action, data_set);
758
759 if (save_action) {
760 update_resource_flags_for_action(rsc, action);
761 }
762 }
763
764 return action;
765 }
766
767 static bool
768 valid_stop_on_fail(const char *value)
769 {
770 return !pcmk__strcase_any_of(value, "standby", "demote", "stop", NULL);
771 }
772
773 static const char *
774 unpack_operation_on_fail(pe_action_t * action)
775 {
776
777 const char *name = NULL;
778 const char *role = NULL;
779 const char *on_fail = NULL;
780 const char *interval_spec = NULL;
781 const char *enabled = NULL;
782 const char *value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ON_FAIL);
783
784 if (pcmk__str_eq(action->task, CRMD_ACTION_STOP, pcmk__str_casei)
785 && !valid_stop_on_fail(value)) {
786
787 pcmk__config_err("Resetting '" XML_OP_ATTR_ON_FAIL "' for %s stop "
788 "action to default value because '%s' is not "
789 "allowed for stop", action->rsc->id, value);
790 return NULL;
791
792 } else if (pcmk__str_eq(action->task, CRMD_ACTION_DEMOTE, pcmk__str_casei) && !value) {
793
794 xmlNode *operation = NULL;
795
796 CRM_CHECK(action->rsc != NULL, return NULL);
797
798 for (operation = pcmk__xe_first_child(action->rsc->ops_xml);
799 (operation != NULL) && (value == NULL);
800 operation = pcmk__xe_next(operation)) {
801
802 if (!pcmk__str_eq((const char *)operation->name, "op", pcmk__str_none)) {
803 continue;
804 }
805 name = crm_element_value(operation, "name");
806 role = crm_element_value(operation, "role");
807 on_fail = crm_element_value(operation, XML_OP_ATTR_ON_FAIL);
808 enabled = crm_element_value(operation, "enabled");
809 interval_spec = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
810 if (!on_fail) {
811 continue;
812 } else if (enabled && !crm_is_true(enabled)) {
813 continue;
814 } else if (!pcmk__str_eq(name, "monitor", pcmk__str_casei)
815 || !pcmk__strcase_any_of(role, RSC_ROLE_PROMOTED_S,
816 RSC_ROLE_PROMOTED_LEGACY_S,
817 NULL)) {
818 continue;
819 } else if (crm_parse_interval_spec(interval_spec) == 0) {
820 continue;
821 } else if (pcmk__str_eq(on_fail, "demote", pcmk__str_casei)) {
822 continue;
823 }
824
825 value = on_fail;
826 }
827 } else if (pcmk__str_eq(action->task, CRM_OP_LRM_DELETE, pcmk__str_casei)) {
828 value = "ignore";
829
830 } else if (pcmk__str_eq(value, "demote", pcmk__str_casei)) {
831 name = crm_element_value(action->op_entry, "name");
832 role = crm_element_value(action->op_entry, "role");
833 interval_spec = crm_element_value(action->op_entry,
834 XML_LRM_ATTR_INTERVAL);
835
836 if (!pcmk__str_eq(name, CRMD_ACTION_PROMOTE, pcmk__str_casei)
837 && (!pcmk__str_eq(name, CRMD_ACTION_STATUS, pcmk__str_casei)
838 || !pcmk__strcase_any_of(role, RSC_ROLE_PROMOTED_S,
839 RSC_ROLE_PROMOTED_LEGACY_S, NULL)
840 || (crm_parse_interval_spec(interval_spec) == 0))) {
841 pcmk__config_err("Resetting '" XML_OP_ATTR_ON_FAIL "' for %s %s "
842 "action to default value because 'demote' is not "
843 "allowed for it", action->rsc->id, name);
844 return NULL;
845 }
846 }
847
848 return value;
849 }
850
851 static xmlNode *
852 find_min_interval_mon(pe_resource_t * rsc, gboolean include_disabled)
853 {
854 guint interval_ms = 0;
855 guint min_interval_ms = G_MAXUINT;
856 const char *name = NULL;
857 const char *value = NULL;
858 const char *interval_spec = NULL;
859 xmlNode *op = NULL;
860 xmlNode *operation = NULL;
861
862 for (operation = pcmk__xe_first_child(rsc->ops_xml);
863 operation != NULL;
864 operation = pcmk__xe_next(operation)) {
865
866 if (pcmk__str_eq((const char *)operation->name, "op", pcmk__str_none)) {
867 name = crm_element_value(operation, "name");
868 interval_spec = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
869 value = crm_element_value(operation, "enabled");
870 if (!include_disabled && value && crm_is_true(value) == FALSE) {
871 continue;
872 }
873
874 if (!pcmk__str_eq(name, RSC_STATUS, pcmk__str_casei)) {
875 continue;
876 }
877
878 interval_ms = crm_parse_interval_spec(interval_spec);
879
880 if (interval_ms && (interval_ms < min_interval_ms)) {
881 min_interval_ms = interval_ms;
882 op = operation;
883 }
884 }
885 }
886
887 return op;
888 }
889
890 static int
891 unpack_start_delay(const char *value, GHashTable *meta)
892 {
893 int start_delay = 0;
894
895 if (value != NULL) {
896 start_delay = crm_get_msec(value);
897
898 if (start_delay < 0) {
899 start_delay = 0;
900 }
901
902 if (meta) {
903 g_hash_table_replace(meta, strdup(XML_OP_ATTR_START_DELAY),
904 pcmk__itoa(start_delay));
905 }
906 }
907
908 return start_delay;
909 }
910
911
912 static bool
913 unpack_interval_origin(const char *value, xmlNode *xml_obj, guint interval_ms,
914 crm_time_t *now, long long *start_delay)
915 {
916 long long result = 0;
917 guint interval_sec = interval_ms / 1000;
918 crm_time_t *origin = NULL;
919
920
921 if ((value == NULL) || (interval_ms == 0) || (now == NULL)) {
922 return false;
923 }
924
925
926 origin = crm_time_new(value);
927 if (origin == NULL) {
928 pcmk__config_err("Ignoring '" XML_OP_ATTR_ORIGIN "' for operation "
929 "'%s' because '%s' is not valid",
930 (ID(xml_obj)? ID(xml_obj) : "(missing ID)"), value);
931 return false;
932 }
933
934
935 result = crm_time_get_seconds(now) - crm_time_get_seconds(origin);
936 crm_time_free(origin);
937
938
939 result = result % interval_sec;
940
941
942 result = ((result <= 0)? 0 : interval_sec) - result;
943 crm_info("Calculated a start delay of %llds for operation '%s'",
944 result,
945 (ID(xml_obj)? ID(xml_obj) : "(unspecified)"));
946
947 if (start_delay != NULL) {
948 *start_delay = result * 1000;
949 }
950 return true;
951 }
952
953 static int
954 unpack_timeout(const char *value)
955 {
956 int timeout_ms = crm_get_msec(value);
957
958 if (timeout_ms < 0) {
959 timeout_ms = crm_get_msec(CRM_DEFAULT_OP_TIMEOUT_S);
960 }
961 return timeout_ms;
962 }
963
964 int
965 pe_get_configured_timeout(pe_resource_t *rsc, const char *action, pe_working_set_t *data_set)
966 {
967 xmlNode *child = NULL;
968 GHashTable *action_meta = NULL;
969 const char *timeout_spec = NULL;
970 int timeout_ms = 0;
971
972 pe_rule_eval_data_t rule_data = {
973 .node_hash = NULL,
974 .role = RSC_ROLE_UNKNOWN,
975 .now = data_set->now,
976 .match_data = NULL,
977 .rsc_data = NULL,
978 .op_data = NULL
979 };
980
981 for (child = first_named_child(rsc->ops_xml, XML_ATTR_OP);
982 child != NULL; child = crm_next_same_xml(child)) {
983 if (pcmk__str_eq(action, crm_element_value(child, XML_NVPAIR_ATTR_NAME),
984 pcmk__str_casei)) {
985 timeout_spec = crm_element_value(child, XML_ATTR_TIMEOUT);
986 break;
987 }
988 }
989
990 if (timeout_spec == NULL && data_set->op_defaults) {
991 action_meta = pcmk__strkey_table(free, free);
992 pe__unpack_dataset_nvpairs(data_set->op_defaults, XML_TAG_META_SETS,
993 &rule_data, action_meta, NULL, FALSE, data_set);
994 timeout_spec = g_hash_table_lookup(action_meta, XML_ATTR_TIMEOUT);
995 }
996
997
998
999
1000 timeout_ms = crm_get_msec(timeout_spec);
1001 if (timeout_ms < 0) {
1002 timeout_ms = crm_get_msec(CRM_DEFAULT_OP_TIMEOUT_S);
1003 }
1004
1005 if (action_meta != NULL) {
1006 g_hash_table_destroy(action_meta);
1007 }
1008 return timeout_ms;
1009 }
1010
1011 #if ENABLE_VERSIONED_ATTRS
1012 static void
1013 unpack_versioned_meta(xmlNode *versioned_meta, xmlNode *xml_obj,
1014 guint interval_ms, crm_time_t *now)
1015 {
1016 xmlNode *attrs = NULL;
1017 xmlNode *attr = NULL;
1018
1019 for (attrs = pcmk__xe_first_child(versioned_meta); attrs != NULL;
1020 attrs = pcmk__xe_next(attrs)) {
1021
1022 for (attr = pcmk__xe_first_child(attrs); attr != NULL;
1023 attr = pcmk__xe_next(attr)) {
1024
1025 const char *name = crm_element_value(attr, XML_NVPAIR_ATTR_NAME);
1026 const char *value = crm_element_value(attr, XML_NVPAIR_ATTR_VALUE);
1027
1028 if (pcmk__str_eq(name, XML_OP_ATTR_START_DELAY, pcmk__str_casei)) {
1029 int start_delay = unpack_start_delay(value, NULL);
1030
1031 crm_xml_add_int(attr, XML_NVPAIR_ATTR_VALUE, start_delay);
1032 } else if (pcmk__str_eq(name, XML_OP_ATTR_ORIGIN, pcmk__str_casei)) {
1033 long long start_delay = 0;
1034
1035 if (unpack_interval_origin(value, xml_obj, interval_ms, now,
1036 &start_delay)) {
1037 crm_xml_add(attr, XML_NVPAIR_ATTR_NAME,
1038 XML_OP_ATTR_START_DELAY);
1039 crm_xml_add_ll(attr, XML_NVPAIR_ATTR_VALUE, start_delay);
1040 }
1041 } else if (pcmk__str_eq(name, XML_ATTR_TIMEOUT, pcmk__str_casei)) {
1042 int timeout_ms = unpack_timeout(value);
1043
1044 crm_xml_add_int(attr, XML_NVPAIR_ATTR_VALUE, timeout_ms);
1045 }
1046 }
1047 }
1048 }
1049 #endif
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064 static void
1065 unpack_operation(pe_action_t * action, xmlNode * xml_obj, pe_resource_t * container,
1066 pe_working_set_t * data_set, guint interval_ms)
1067 {
1068 int timeout_ms = 0;
1069 const char *value = NULL;
1070 bool is_probe = pcmk__str_eq(action->task, RSC_STATUS, pcmk__str_casei)
1071 && (interval_ms == 0);
1072 #if ENABLE_VERSIONED_ATTRS
1073 pe_rsc_action_details_t *rsc_details = NULL;
1074 #endif
1075
1076 pe_rsc_eval_data_t rsc_rule_data = {
1077 .standard = crm_element_value(action->rsc->xml, XML_AGENT_ATTR_CLASS),
1078 .provider = crm_element_value(action->rsc->xml, XML_AGENT_ATTR_PROVIDER),
1079 .agent = crm_element_value(action->rsc->xml, XML_EXPR_ATTR_TYPE)
1080 };
1081
1082 pe_op_eval_data_t op_rule_data = {
1083 .op_name = action->task,
1084 .interval = interval_ms
1085 };
1086
1087 pe_rule_eval_data_t rule_data = {
1088 .node_hash = NULL,
1089 .role = RSC_ROLE_UNKNOWN,
1090 .now = data_set->now,
1091 .match_data = NULL,
1092 .rsc_data = &rsc_rule_data,
1093 .op_data = &op_rule_data
1094 };
1095
1096 CRM_CHECK(action && action->rsc, return);
1097
1098
1099 pe__unpack_dataset_nvpairs(data_set->op_defaults, XML_TAG_META_SETS, &rule_data,
1100 action->meta, NULL, FALSE, data_set);
1101
1102
1103 if (is_probe) {
1104 xmlNode *min_interval_mon = find_min_interval_mon(action->rsc, FALSE);
1105
1106 if (min_interval_mon) {
1107 value = crm_element_value(min_interval_mon, XML_ATTR_TIMEOUT);
1108 if (value) {
1109 crm_trace("\t%s: Setting default timeout to minimum-interval "
1110 "monitor's timeout '%s'", action->uuid, value);
1111 g_hash_table_replace(action->meta, strdup(XML_ATTR_TIMEOUT),
1112 strdup(value));
1113 }
1114 }
1115 }
1116
1117 if (xml_obj) {
1118 xmlAttrPtr xIter = NULL;
1119
1120
1121 pe__unpack_dataset_nvpairs(xml_obj, XML_TAG_META_SETS, &rule_data,
1122 action->meta, NULL, TRUE, data_set);
1123
1124 #if ENABLE_VERSIONED_ATTRS
1125 rsc_details = pe_rsc_action_details(action);
1126
1127 pe_eval_versioned_attributes(data_set->input, xml_obj,
1128 XML_TAG_ATTR_SETS, &rule_data,
1129 rsc_details->versioned_parameters,
1130 NULL);
1131 pe_eval_versioned_attributes(data_set->input, xml_obj,
1132 XML_TAG_META_SETS, &rule_data,
1133 rsc_details->versioned_meta,
1134 NULL);
1135 #endif
1136
1137
1138
1139
1140 for (xIter = xml_obj->properties; xIter; xIter = xIter->next) {
1141 const char *prop_name = (const char *)xIter->name;
1142 const char *prop_value = crm_element_value(xml_obj, prop_name);
1143
1144 g_hash_table_replace(action->meta, strdup(prop_name), strdup(prop_value));
1145 }
1146 }
1147
1148 g_hash_table_remove(action->meta, "id");
1149
1150
1151 if (interval_ms > 0) {
1152 g_hash_table_replace(action->meta, strdup(XML_LRM_ATTR_INTERVAL),
1153 crm_strdup_printf("%u", interval_ms));
1154 } else {
1155 g_hash_table_remove(action->meta, XML_LRM_ATTR_INTERVAL);
1156 }
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172 if (pcmk_is_set(pcmk_get_ra_caps(rsc_rule_data.standard),
1173 pcmk_ra_cap_fence_params)
1174 && (pcmk__str_eq(action->task, RSC_START, pcmk__str_casei)
1175 || is_probe)) {
1176
1177 GHashTable *params = pe_rsc_params(action->rsc, action->node, data_set);
1178
1179 value = g_hash_table_lookup(params, "pcmk_monitor_timeout");
1180
1181 if (value) {
1182 crm_trace("\t%s: Setting timeout to pcmk_monitor_timeout '%s', "
1183 "overriding default", action->uuid, value);
1184 g_hash_table_replace(action->meta, strdup(XML_ATTR_TIMEOUT),
1185 strdup(value));
1186 }
1187 }
1188
1189
1190 value = g_hash_table_lookup(action->meta, XML_ATTR_TIMEOUT);
1191 timeout_ms = unpack_timeout(value);
1192 g_hash_table_replace(action->meta, strdup(XML_ATTR_TIMEOUT),
1193 pcmk__itoa(timeout_ms));
1194
1195 if (!pcmk__strcase_any_of(action->task, RSC_START, RSC_PROMOTE, NULL)) {
1196 action->needs = rsc_req_nothing;
1197 value = "nothing (not start or promote)";
1198
1199 } else if (pcmk_is_set(action->rsc->flags, pe_rsc_needs_fencing)) {
1200 action->needs = rsc_req_stonith;
1201 value = "fencing";
1202
1203 } else if (pcmk_is_set(action->rsc->flags, pe_rsc_needs_quorum)) {
1204 action->needs = rsc_req_quorum;
1205 value = "quorum";
1206
1207 } else {
1208 action->needs = rsc_req_nothing;
1209 value = "nothing";
1210 }
1211 pe_rsc_trace(action->rsc, "%s requires %s", action->uuid, value);
1212
1213 value = unpack_operation_on_fail(action);
1214
1215 if (value == NULL) {
1216
1217 } else if (pcmk__str_eq(value, "block", pcmk__str_casei)) {
1218 action->on_fail = action_fail_block;
1219 g_hash_table_insert(action->meta, strdup(XML_OP_ATTR_ON_FAIL), strdup("block"));
1220 value = "block";
1221
1222 } else if (pcmk__str_eq(value, "fence", pcmk__str_casei)) {
1223 action->on_fail = action_fail_fence;
1224 value = "node fencing";
1225
1226 if (!pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
1227 pcmk__config_err("Resetting '" XML_OP_ATTR_ON_FAIL "' for "
1228 "operation '%s' to 'stop' because 'fence' is not "
1229 "valid when fencing is disabled", action->uuid);
1230 action->on_fail = action_fail_stop;
1231 action->fail_role = RSC_ROLE_STOPPED;
1232 value = "stop resource";
1233 }
1234
1235 } else if (pcmk__str_eq(value, "standby", pcmk__str_casei)) {
1236 action->on_fail = action_fail_standby;
1237 value = "node standby";
1238
1239 } else if (pcmk__strcase_any_of(value, "ignore", "nothing", NULL)) {
1240 action->on_fail = action_fail_ignore;
1241 value = "ignore";
1242
1243 } else if (pcmk__str_eq(value, "migrate", pcmk__str_casei)) {
1244 action->on_fail = action_fail_migrate;
1245 value = "force migration";
1246
1247 } else if (pcmk__str_eq(value, "stop", pcmk__str_casei)) {
1248 action->on_fail = action_fail_stop;
1249 action->fail_role = RSC_ROLE_STOPPED;
1250 value = "stop resource";
1251
1252 } else if (pcmk__str_eq(value, "restart", pcmk__str_casei)) {
1253 action->on_fail = action_fail_recover;
1254 value = "restart (and possibly migrate)";
1255
1256 } else if (pcmk__str_eq(value, "restart-container", pcmk__str_casei)) {
1257 if (container) {
1258 action->on_fail = action_fail_restart_container;
1259 value = "restart container (and possibly migrate)";
1260
1261 } else {
1262 value = NULL;
1263 }
1264
1265 } else if (pcmk__str_eq(value, "demote", pcmk__str_casei)) {
1266 action->on_fail = action_fail_demote;
1267 value = "demote instance";
1268
1269 } else {
1270 pe_err("Resource %s: Unknown failure type (%s)", action->rsc->id, value);
1271 value = NULL;
1272 }
1273
1274
1275 if (value == NULL && container) {
1276 action->on_fail = action_fail_restart_container;
1277 value = "restart container (and possibly migrate) (default)";
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287 } else if (((value == NULL) || !pcmk_is_set(action->rsc->flags, pe_rsc_managed))
1288 && pe__resource_is_remote_conn(action->rsc, data_set)
1289 && !(pcmk__str_eq(action->task, CRMD_ACTION_STATUS, pcmk__str_casei)
1290 && (interval_ms == 0))
1291 && !pcmk__str_eq(action->task, CRMD_ACTION_START, pcmk__str_casei)) {
1292
1293 if (!pcmk_is_set(action->rsc->flags, pe_rsc_managed)) {
1294 action->on_fail = action_fail_stop;
1295 action->fail_role = RSC_ROLE_STOPPED;
1296 value = "stop unmanaged remote node (enforcing default)";
1297
1298 } else {
1299 if (pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
1300 value = "fence remote node (default)";
1301 } else {
1302 value = "recover remote node connection (default)";
1303 }
1304
1305 if (action->rsc->remote_reconnect_ms) {
1306 action->fail_role = RSC_ROLE_STOPPED;
1307 }
1308 action->on_fail = action_fail_reset_remote;
1309 }
1310
1311 } else if (value == NULL && pcmk__str_eq(action->task, CRMD_ACTION_STOP, pcmk__str_casei)) {
1312 if (pcmk_is_set(data_set->flags, pe_flag_stonith_enabled)) {
1313 action->on_fail = action_fail_fence;
1314 value = "resource fence (default)";
1315
1316 } else {
1317 action->on_fail = action_fail_block;
1318 value = "resource block (default)";
1319 }
1320
1321 } else if (value == NULL) {
1322 action->on_fail = action_fail_recover;
1323 value = "restart (and possibly migrate) (default)";
1324 }
1325
1326 pe_rsc_trace(action->rsc, "%s failure handling: %s",
1327 action->uuid, value);
1328
1329 value = NULL;
1330 if (xml_obj != NULL) {
1331 value = g_hash_table_lookup(action->meta, "role_after_failure");
1332 if (value) {
1333 pe_warn_once(pe_wo_role_after,
1334 "Support for role_after_failure is deprecated and will be removed in a future release");
1335 }
1336 }
1337 if (value != NULL && action->fail_role == RSC_ROLE_UNKNOWN) {
1338 action->fail_role = text2role(value);
1339 }
1340
1341 if (action->fail_role == RSC_ROLE_UNKNOWN) {
1342 if (pcmk__str_eq(action->task, CRMD_ACTION_PROMOTE, pcmk__str_casei)) {
1343 action->fail_role = RSC_ROLE_UNPROMOTED;
1344 } else {
1345 action->fail_role = RSC_ROLE_STARTED;
1346 }
1347 }
1348 pe_rsc_trace(action->rsc, "%s failure results in: %s",
1349 action->uuid, role2text(action->fail_role));
1350
1351 value = g_hash_table_lookup(action->meta, XML_OP_ATTR_START_DELAY);
1352 if (value) {
1353 unpack_start_delay(value, action->meta);
1354 } else {
1355 long long start_delay = 0;
1356
1357 value = g_hash_table_lookup(action->meta, XML_OP_ATTR_ORIGIN);
1358 if (unpack_interval_origin(value, xml_obj, interval_ms, data_set->now,
1359 &start_delay)) {
1360 g_hash_table_replace(action->meta, strdup(XML_OP_ATTR_START_DELAY),
1361 crm_strdup_printf("%lld", start_delay));
1362 }
1363 }
1364
1365 #if ENABLE_VERSIONED_ATTRS
1366 unpack_versioned_meta(rsc_details->versioned_meta, xml_obj, interval_ms,
1367 data_set->now);
1368 #endif
1369 }
1370
1371 static xmlNode *
1372 find_rsc_op_entry_helper(pe_resource_t * rsc, const char *key, gboolean include_disabled)
1373 {
1374 guint interval_ms = 0;
1375 gboolean do_retry = TRUE;
1376 char *local_key = NULL;
1377 const char *name = NULL;
1378 const char *value = NULL;
1379 const char *interval_spec = NULL;
1380 char *match_key = NULL;
1381 xmlNode *op = NULL;
1382 xmlNode *operation = NULL;
1383
1384 retry:
1385 for (operation = pcmk__xe_first_child(rsc->ops_xml); operation != NULL;
1386 operation = pcmk__xe_next(operation)) {
1387
1388 if (pcmk__str_eq((const char *)operation->name, "op", pcmk__str_none)) {
1389 name = crm_element_value(operation, "name");
1390 interval_spec = crm_element_value(operation, XML_LRM_ATTR_INTERVAL);
1391 value = crm_element_value(operation, "enabled");
1392 if (!include_disabled && value && crm_is_true(value) == FALSE) {
1393 continue;
1394 }
1395
1396 interval_ms = crm_parse_interval_spec(interval_spec);
1397 match_key = pcmk__op_key(rsc->id, name, interval_ms);
1398 if (pcmk__str_eq(key, match_key, pcmk__str_casei)) {
1399 op = operation;
1400 }
1401 free(match_key);
1402
1403 if (rsc->clone_name) {
1404 match_key = pcmk__op_key(rsc->clone_name, name, interval_ms);
1405 if (pcmk__str_eq(key, match_key, pcmk__str_casei)) {
1406 op = operation;
1407 }
1408 free(match_key);
1409 }
1410
1411 if (op != NULL) {
1412 free(local_key);
1413 return op;
1414 }
1415 }
1416 }
1417
1418 free(local_key);
1419 if (do_retry == FALSE) {
1420 return NULL;
1421 }
1422
1423 do_retry = FALSE;
1424 if (strstr(key, CRMD_ACTION_MIGRATE) || strstr(key, CRMD_ACTION_MIGRATED)) {
1425 local_key = pcmk__op_key(rsc->id, "migrate", 0);
1426 key = local_key;
1427 goto retry;
1428
1429 } else if (strstr(key, "_notify_")) {
1430 local_key = pcmk__op_key(rsc->id, "notify", 0);
1431 key = local_key;
1432 goto retry;
1433 }
1434
1435 return NULL;
1436 }
1437
1438 xmlNode *
1439 find_rsc_op_entry(pe_resource_t * rsc, const char *key)
1440 {
1441 return find_rsc_op_entry_helper(rsc, key, FALSE);
1442 }
1443
1444
1445
1446
1447 void
1448 print_str_str(gpointer key, gpointer value, gpointer user_data)
1449 {
1450 crm_trace("%s%s %s ==> %s",
1451 user_data == NULL ? "" : (char *)user_data,
1452 user_data == NULL ? "" : ": ", (char *)key, (char *)value);
1453 }
1454
1455 void
1456 pe_free_action(pe_action_t * action)
1457 {
1458 if (action == NULL) {
1459 return;
1460 }
1461 g_list_free_full(action->actions_before, free);
1462 g_list_free_full(action->actions_after, free);
1463 if (action->extra) {
1464 g_hash_table_destroy(action->extra);
1465 }
1466 if (action->meta) {
1467 g_hash_table_destroy(action->meta);
1468 }
1469 #if ENABLE_VERSIONED_ATTRS
1470 if (action->rsc) {
1471 pe_free_rsc_action_details(action);
1472 }
1473 #endif
1474 free(action->cancel_task);
1475 free(action->reason);
1476 free(action->task);
1477 free(action->uuid);
1478 free(action->node);
1479 free(action);
1480 }
1481
1482 GList *
1483 find_recurring_actions(GList *input, pe_node_t * not_on_node)
1484 {
1485 const char *value = NULL;
1486 GList *result = NULL;
1487 GList *gIter = input;
1488
1489 CRM_CHECK(input != NULL, return NULL);
1490
1491 for (; gIter != NULL; gIter = gIter->next) {
1492 pe_action_t *action = (pe_action_t *) gIter->data;
1493
1494 value = g_hash_table_lookup(action->meta, XML_LRM_ATTR_INTERVAL_MS);
1495 if (value == NULL) {
1496
1497 } else if (pcmk__str_eq(value, "0", pcmk__str_casei)) {
1498
1499 } else if (pcmk__str_eq(CRMD_ACTION_CANCEL, action->task, pcmk__str_casei)) {
1500
1501 } else if (not_on_node == NULL) {
1502 crm_trace("(null) Found: %s", action->uuid);
1503 result = g_list_prepend(result, action);
1504
1505 } else if (action->node == NULL) {
1506
1507 } else if (action->node->details != not_on_node->details) {
1508 crm_trace("Found: %s", action->uuid);
1509 result = g_list_prepend(result, action);
1510 }
1511 }
1512
1513 return result;
1514 }
1515
1516 enum action_tasks
1517 get_complex_task(pe_resource_t * rsc, const char *name, gboolean allow_non_atomic)
1518 {
1519 enum action_tasks task = text2task(name);
1520
1521 if (rsc == NULL) {
1522 return task;
1523
1524 } else if (allow_non_atomic == FALSE || rsc->variant == pe_native) {
1525 switch (task) {
1526 case stopped_rsc:
1527 case started_rsc:
1528 case action_demoted:
1529 case action_promoted:
1530 crm_trace("Folding %s back into its atomic counterpart for %s", name, rsc->id);
1531 return task - 1;
1532 default:
1533 break;
1534 }
1535 }
1536 return task;
1537 }
1538
1539 pe_action_t *
1540 find_first_action(GList *input, const char *uuid, const char *task, pe_node_t * on_node)
1541 {
1542 GList *gIter = NULL;
1543
1544 CRM_CHECK(uuid || task, return NULL);
1545
1546 for (gIter = input; gIter != NULL; gIter = gIter->next) {
1547 pe_action_t *action = (pe_action_t *) gIter->data;
1548
1549 if (uuid != NULL && !pcmk__str_eq(uuid, action->uuid, pcmk__str_casei)) {
1550 continue;
1551
1552 } else if (task != NULL && !pcmk__str_eq(task, action->task, pcmk__str_casei)) {
1553 continue;
1554
1555 } else if (on_node == NULL) {
1556 return action;
1557
1558 } else if (action->node == NULL) {
1559 continue;
1560
1561 } else if (on_node->details == action->node->details) {
1562 return action;
1563 }
1564 }
1565
1566 return NULL;
1567 }
1568
1569 GList *
1570 find_actions(GList *input, const char *key, const pe_node_t *on_node)
1571 {
1572 GList *gIter = input;
1573 GList *result = NULL;
1574
1575 CRM_CHECK(key != NULL, return NULL);
1576
1577 for (; gIter != NULL; gIter = gIter->next) {
1578 pe_action_t *action = (pe_action_t *) gIter->data;
1579
1580 if (!pcmk__str_eq(key, action->uuid, pcmk__str_casei)) {
1581 continue;
1582
1583 } else if (on_node == NULL) {
1584 crm_trace("Action %s matches (ignoring node)", key);
1585 result = g_list_prepend(result, action);
1586
1587 } else if (action->node == NULL) {
1588 crm_trace("Action %s matches (unallocated, assigning to %s)",
1589 key, on_node->details->uname);
1590
1591 action->node = pe__copy_node(on_node);
1592 result = g_list_prepend(result, action);
1593
1594 } else if (on_node->details == action->node->details) {
1595 crm_trace("Action %s on %s matches", key, on_node->details->uname);
1596 result = g_list_prepend(result, action);
1597 }
1598 }
1599
1600 return result;
1601 }
1602
1603 GList *
1604 find_actions_exact(GList *input, const char *key, const pe_node_t *on_node)
1605 {
1606 GList *result = NULL;
1607
1608 CRM_CHECK(key != NULL, return NULL);
1609
1610 if (on_node == NULL) {
1611 return NULL;
1612 }
1613
1614 for (GList *gIter = input; gIter != NULL; gIter = gIter->next) {
1615 pe_action_t *action = (pe_action_t *) gIter->data;
1616
1617 if ((action->node != NULL)
1618 && pcmk__str_eq(key, action->uuid, pcmk__str_casei)
1619 && pcmk__str_eq(on_node->details->id, action->node->details->id,
1620 pcmk__str_casei)) {
1621
1622 crm_trace("Action %s on %s matches", key, on_node->details->uname);
1623 result = g_list_prepend(result, action);
1624 }
1625 }
1626
1627 return result;
1628 }
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642 GList *
1643 pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node,
1644 const char *task, bool require_node)
1645 {
1646 GList *result = NULL;
1647 char *key = pcmk__op_key(rsc->id, task, 0);
1648
1649 if (require_node) {
1650 result = find_actions_exact(rsc->actions, key, node);
1651 } else {
1652 result = find_actions(rsc->actions, key, node);
1653 }
1654 free(key);
1655 return result;
1656 }
1657
1658 static void
1659 resource_node_score(pe_resource_t * rsc, pe_node_t * node, int score, const char *tag)
1660 {
1661 pe_node_t *match = NULL;
1662
1663 if ((rsc->exclusive_discover || (node->rsc_discover_mode == pe_discover_never))
1664 && pcmk__str_eq(tag, "symmetric_default", pcmk__str_casei)) {
1665
1666
1667
1668
1669 return;
1670
1671 } else if (rsc->children) {
1672 GList *gIter = rsc->children;
1673
1674 for (; gIter != NULL; gIter = gIter->next) {
1675 pe_resource_t *child_rsc = (pe_resource_t *) gIter->data;
1676
1677 resource_node_score(child_rsc, node, score, tag);
1678 }
1679 }
1680
1681 pe_rsc_trace(rsc, "Setting %s for %s on %s: %d", tag, rsc->id, node->details->uname, score);
1682 match = pe_hash_table_lookup(rsc->allowed_nodes, node->details->id);
1683 if (match == NULL) {
1684 match = pe__copy_node(node);
1685 g_hash_table_insert(rsc->allowed_nodes, (gpointer) match->details->id, match);
1686 }
1687 match->weight = pe__add_scores(match->weight, score);
1688 }
1689
1690 void
1691 resource_location(pe_resource_t * rsc, pe_node_t * node, int score, const char *tag,
1692 pe_working_set_t * data_set)
1693 {
1694 if (node != NULL) {
1695 resource_node_score(rsc, node, score, tag);
1696
1697 } else if (data_set != NULL) {
1698 GList *gIter = data_set->nodes;
1699
1700 for (; gIter != NULL; gIter = gIter->next) {
1701 pe_node_t *node_iter = (pe_node_t *) gIter->data;
1702
1703 resource_node_score(rsc, node_iter, score, tag);
1704 }
1705
1706 } else {
1707 GHashTableIter iter;
1708 pe_node_t *node_iter = NULL;
1709
1710 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
1711 while (g_hash_table_iter_next(&iter, NULL, (void **)&node_iter)) {
1712 resource_node_score(rsc, node_iter, score, tag);
1713 }
1714 }
1715
1716 if (node == NULL && score == -INFINITY) {
1717 if (rsc->allocated_to) {
1718 crm_info("Deallocating %s from %s", rsc->id, rsc->allocated_to->details->uname);
1719 free(rsc->allocated_to);
1720 rsc->allocated_to = NULL;
1721 }
1722 }
1723 }
1724
1725 #define sort_return(an_int, why) do { \
1726 free(a_uuid); \
1727 free(b_uuid); \
1728 crm_trace("%s (%d) %c %s (%d) : %s", \
1729 a_xml_id, a_call_id, an_int>0?'>':an_int<0?'<':'=', \
1730 b_xml_id, b_call_id, why); \
1731 return an_int; \
1732 } while(0)
1733
1734 gint
1735 sort_op_by_callid(gconstpointer a, gconstpointer b)
1736 {
1737 int a_call_id = -1;
1738 int b_call_id = -1;
1739
1740 char *a_uuid = NULL;
1741 char *b_uuid = NULL;
1742
1743 const xmlNode *xml_a = a;
1744 const xmlNode *xml_b = b;
1745
1746 const char *a_xml_id = crm_element_value(xml_a, XML_ATTR_ID);
1747 const char *b_xml_id = crm_element_value(xml_b, XML_ATTR_ID);
1748
1749 if (pcmk__str_eq(a_xml_id, b_xml_id, pcmk__str_casei)) {
1750
1751
1752
1753
1754
1755 pe_err("Duplicate lrm_rsc_op entries named %s", a_xml_id);
1756 sort_return(0, "duplicate");
1757 }
1758
1759 crm_element_value_int(xml_a, XML_LRM_ATTR_CALLID, &a_call_id);
1760 crm_element_value_int(xml_b, XML_LRM_ATTR_CALLID, &b_call_id);
1761
1762 if (a_call_id == -1 && b_call_id == -1) {
1763
1764
1765
1766 sort_return(0, "pending");
1767
1768 } else if (a_call_id >= 0 && a_call_id < b_call_id) {
1769 sort_return(-1, "call id");
1770
1771 } else if (b_call_id >= 0 && a_call_id > b_call_id) {
1772 sort_return(1, "call id");
1773
1774 } else if (b_call_id >= 0 && a_call_id == b_call_id) {
1775
1776
1777
1778
1779 time_t last_a = -1;
1780 time_t last_b = -1;
1781
1782 crm_element_value_epoch(xml_a, XML_RSC_OP_LAST_CHANGE, &last_a);
1783 crm_element_value_epoch(xml_b, XML_RSC_OP_LAST_CHANGE, &last_b);
1784
1785 crm_trace("rc-change: %lld vs %lld",
1786 (long long) last_a, (long long) last_b);
1787 if (last_a >= 0 && last_a < last_b) {
1788 sort_return(-1, "rc-change");
1789
1790 } else if (last_b >= 0 && last_a > last_b) {
1791 sort_return(1, "rc-change");
1792 }
1793 sort_return(0, "rc-change");
1794
1795 } else {
1796
1797
1798
1799
1800 int a_id = -1;
1801 int b_id = -1;
1802
1803 const char *a_magic = crm_element_value(xml_a, XML_ATTR_TRANSITION_MAGIC);
1804 const char *b_magic = crm_element_value(xml_b, XML_ATTR_TRANSITION_MAGIC);
1805
1806 CRM_CHECK(a_magic != NULL && b_magic != NULL, sort_return(0, "No magic"));
1807 if (!decode_transition_magic(a_magic, &a_uuid, &a_id, NULL, NULL, NULL,
1808 NULL)) {
1809 sort_return(0, "bad magic a");
1810 }
1811 if (!decode_transition_magic(b_magic, &b_uuid, &b_id, NULL, NULL, NULL,
1812 NULL)) {
1813 sort_return(0, "bad magic b");
1814 }
1815
1816
1817
1818
1819
1820
1821 if (!pcmk__str_eq(a_uuid, b_uuid, pcmk__str_casei) || a_id == b_id) {
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831 if (b_call_id == -1) {
1832 sort_return(-1, "transition + call");
1833
1834 } else if (a_call_id == -1) {
1835 sort_return(1, "transition + call");
1836 }
1837
1838 } else if ((a_id >= 0 && a_id < b_id) || b_id == -1) {
1839 sort_return(-1, "transition");
1840
1841 } else if ((b_id >= 0 && a_id > b_id) || a_id == -1) {
1842 sort_return(1, "transition");
1843 }
1844 }
1845
1846
1847 CRM_CHECK(FALSE, sort_return(0, "default"));
1848
1849 }
1850
1851 time_t
1852 get_effective_time(pe_working_set_t * data_set)
1853 {
1854 if(data_set) {
1855 if (data_set->now == NULL) {
1856 crm_trace("Recording a new 'now'");
1857 data_set->now = crm_time_new(NULL);
1858 }
1859 return crm_time_get_seconds_since_epoch(data_set->now);
1860 }
1861
1862 crm_trace("Defaulting to 'now'");
1863 return time(NULL);
1864 }
1865
1866 gboolean
1867 get_target_role(pe_resource_t * rsc, enum rsc_role_e * role)
1868 {
1869 enum rsc_role_e local_role = RSC_ROLE_UNKNOWN;
1870 const char *value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
1871
1872 CRM_CHECK(role != NULL, return FALSE);
1873
1874 if (pcmk__str_eq(value, "started", pcmk__str_null_matches | pcmk__str_casei)
1875 || pcmk__str_eq("default", value, pcmk__str_casei)) {
1876 return FALSE;
1877 }
1878
1879 local_role = text2role(value);
1880 if (local_role == RSC_ROLE_UNKNOWN) {
1881 pcmk__config_err("Ignoring '" XML_RSC_ATTR_TARGET_ROLE "' for %s "
1882 "because '%s' is not valid", rsc->id, value);
1883 return FALSE;
1884
1885 } else if (local_role > RSC_ROLE_STARTED) {
1886 if (pcmk_is_set(uber_parent(rsc)->flags, pe_rsc_promotable)) {
1887 if (local_role > RSC_ROLE_UNPROMOTED) {
1888
1889 return FALSE;
1890 }
1891
1892 } else {
1893 pcmk__config_err("Ignoring '" XML_RSC_ATTR_TARGET_ROLE "' for %s "
1894 "because '%s' only makes sense for promotable "
1895 "clones", rsc->id, value);
1896 return FALSE;
1897 }
1898 }
1899
1900 *role = local_role;
1901 return TRUE;
1902 }
1903
1904 gboolean
1905 order_actions(pe_action_t * lh_action, pe_action_t * rh_action, enum pe_ordering order)
1906 {
1907 GList *gIter = NULL;
1908 pe_action_wrapper_t *wrapper = NULL;
1909 GList *list = NULL;
1910
1911 if (order == pe_order_none) {
1912 return FALSE;
1913 }
1914
1915 if (lh_action == NULL || rh_action == NULL) {
1916 return FALSE;
1917 }
1918
1919 crm_trace("Creating action wrappers for ordering: %s then %s",
1920 lh_action->uuid, rh_action->uuid);
1921
1922
1923 CRM_ASSERT(lh_action != rh_action);
1924
1925
1926 gIter = lh_action->actions_after;
1927 for (; gIter != NULL; gIter = gIter->next) {
1928 pe_action_wrapper_t *after = (pe_action_wrapper_t *) gIter->data;
1929
1930 if (after->action == rh_action && (after->type & order)) {
1931 return FALSE;
1932 }
1933 }
1934
1935 wrapper = calloc(1, sizeof(pe_action_wrapper_t));
1936 wrapper->action = rh_action;
1937 wrapper->type = order;
1938 list = lh_action->actions_after;
1939 list = g_list_prepend(list, wrapper);
1940 lh_action->actions_after = list;
1941
1942 wrapper = calloc(1, sizeof(pe_action_wrapper_t));
1943 wrapper->action = lh_action;
1944 wrapper->type = order;
1945 list = rh_action->actions_before;
1946 list = g_list_prepend(list, wrapper);
1947 rh_action->actions_before = list;
1948 return TRUE;
1949 }
1950
1951 pe_action_t *
1952 get_pseudo_op(const char *name, pe_working_set_t * data_set)
1953 {
1954 pe_action_t *op = lookup_singleton(data_set, name);
1955
1956 if (op == NULL) {
1957 op = custom_action(NULL, strdup(name), name, NULL, TRUE, TRUE, data_set);
1958 pe__set_action_flags(op, pe_action_pseudo|pe_action_runnable);
1959 }
1960 return op;
1961 }
1962
1963 void
1964 destroy_ticket(gpointer data)
1965 {
1966 pe_ticket_t *ticket = data;
1967
1968 if (ticket->state) {
1969 g_hash_table_destroy(ticket->state);
1970 }
1971 free(ticket->id);
1972 free(ticket);
1973 }
1974
1975 pe_ticket_t *
1976 ticket_new(const char *ticket_id, pe_working_set_t * data_set)
1977 {
1978 pe_ticket_t *ticket = NULL;
1979
1980 if (pcmk__str_empty(ticket_id)) {
1981 return NULL;
1982 }
1983
1984 if (data_set->tickets == NULL) {
1985 data_set->tickets = pcmk__strkey_table(free, destroy_ticket);
1986 }
1987
1988 ticket = g_hash_table_lookup(data_set->tickets, ticket_id);
1989 if (ticket == NULL) {
1990
1991 ticket = calloc(1, sizeof(pe_ticket_t));
1992 if (ticket == NULL) {
1993 crm_err("Cannot allocate ticket '%s'", ticket_id);
1994 return NULL;
1995 }
1996
1997 crm_trace("Creaing ticket entry for %s", ticket_id);
1998
1999 ticket->id = strdup(ticket_id);
2000 ticket->granted = FALSE;
2001 ticket->last_granted = -1;
2002 ticket->standby = FALSE;
2003 ticket->state = pcmk__strkey_table(free, free);
2004
2005 g_hash_table_insert(data_set->tickets, strdup(ticket->id), ticket);
2006 }
2007
2008 return ticket;
2009 }
2010
2011 const char *rsc_printable_id(pe_resource_t *rsc)
2012 {
2013 if (!pcmk_is_set(rsc->flags, pe_rsc_unique)) {
2014 return ID(rsc->xml);
2015 }
2016 return rsc->id;
2017 }
2018
2019 void
2020 pe__clear_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
2021 {
2022 pe__clear_resource_flags(rsc, flags);
2023 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
2024 pe__clear_resource_flags_recursive((pe_resource_t *) gIter->data, flags);
2025 }
2026 }
2027
2028 void
2029 pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag)
2030 {
2031 for (GList *lpc = data_set->resources; lpc != NULL; lpc = lpc->next) {
2032 pe_resource_t *r = (pe_resource_t *) lpc->data;
2033 pe__clear_resource_flags_recursive(r, flag);
2034 }
2035 }
2036
2037 void
2038 pe__set_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags)
2039 {
2040 pe__set_resource_flags(rsc, flags);
2041 for (GList *gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
2042 pe__set_resource_flags_recursive((pe_resource_t *) gIter->data, flags);
2043 }
2044 }
2045
2046 static GList *
2047 find_unfencing_devices(GList *candidates, GList *matches)
2048 {
2049 for (GList *gIter = candidates; gIter != NULL; gIter = gIter->next) {
2050 pe_resource_t *candidate = gIter->data;
2051 const char *provides = g_hash_table_lookup(candidate->meta,
2052 PCMK_STONITH_PROVIDES);
2053 const char *requires = g_hash_table_lookup(candidate->meta, XML_RSC_ATTR_REQUIRES);
2054
2055 if(candidate->children) {
2056 matches = find_unfencing_devices(candidate->children, matches);
2057 } else if (!pcmk_is_set(candidate->flags, pe_rsc_fence_device)) {
2058 continue;
2059
2060 } else if (pcmk__str_eq(provides, "unfencing", pcmk__str_casei) || pcmk__str_eq(requires, "unfencing", pcmk__str_casei)) {
2061 matches = g_list_prepend(matches, candidate);
2062 }
2063 }
2064 return matches;
2065 }
2066
2067 static int
2068 node_priority_fencing_delay(pe_node_t * node, pe_working_set_t * data_set)
2069 {
2070 int member_count = 0;
2071 int online_count = 0;
2072 int top_priority = 0;
2073 int lowest_priority = 0;
2074 GList *gIter = NULL;
2075
2076
2077 if (data_set->priority_fencing_delay <= 0) {
2078 return 0;
2079 }
2080
2081
2082
2083 if (node->details->type != node_member) {
2084 return 0;
2085 }
2086
2087
2088 if (node->details->online) {
2089 return 0;
2090 }
2091
2092 for (gIter = data_set->nodes; gIter != NULL; gIter = gIter->next) {
2093 pe_node_t *n = gIter->data;
2094
2095 if (n->details->type != node_member) {
2096 continue;
2097 }
2098
2099 member_count ++;
2100
2101 if (n->details->online) {
2102 online_count++;
2103 }
2104
2105 if (member_count == 1
2106 || n->details->priority > top_priority) {
2107 top_priority = n->details->priority;
2108 }
2109
2110 if (member_count == 1
2111 || n->details->priority < lowest_priority) {
2112 lowest_priority = n->details->priority;
2113 }
2114 }
2115
2116
2117 if (online_count > member_count / 2) {
2118 return 0;
2119 }
2120
2121
2122
2123 if (lowest_priority == top_priority) {
2124 return 0;
2125 }
2126
2127 if (node->details->priority < top_priority) {
2128 return 0;
2129 }
2130
2131 return data_set->priority_fencing_delay;
2132 }
2133
2134 pe_action_t *
2135 pe_fence_op(pe_node_t * node, const char *op, bool optional, const char *reason,
2136 bool priority_delay, pe_working_set_t * data_set)
2137 {
2138 char *op_key = NULL;
2139 pe_action_t *stonith_op = NULL;
2140
2141 if(op == NULL) {
2142 op = data_set->stonith_action;
2143 }
2144
2145 op_key = crm_strdup_printf("%s-%s-%s", CRM_OP_FENCE, node->details->uname, op);
2146
2147 stonith_op = lookup_singleton(data_set, op_key);
2148 if(stonith_op == NULL) {
2149 stonith_op = custom_action(NULL, op_key, CRM_OP_FENCE, node, TRUE, TRUE, data_set);
2150
2151 add_hash_param(stonith_op->meta, XML_LRM_ATTR_TARGET, node->details->uname);
2152 add_hash_param(stonith_op->meta, XML_LRM_ATTR_TARGET_UUID, node->details->id);
2153 add_hash_param(stonith_op->meta, "stonith_action", op);
2154
2155 if (pe__is_guest_or_remote_node(node)
2156 && pcmk_is_set(data_set->flags, pe_flag_enable_unfencing)) {
2157
2158
2159
2160
2161
2162 long max = 1024;
2163 long digests_all_offset = 0;
2164 long digests_secure_offset = 0;
2165
2166 char *digests_all = calloc(max, sizeof(char));
2167 char *digests_secure = calloc(max, sizeof(char));
2168 GList *matches = find_unfencing_devices(data_set->resources, NULL);
2169
2170 for (GList *gIter = matches; gIter != NULL; gIter = gIter->next) {
2171 pe_resource_t *match = gIter->data;
2172 const char *agent = g_hash_table_lookup(match->meta,
2173 XML_ATTR_TYPE);
2174 op_digest_cache_t *data = NULL;
2175
2176 data = pe__compare_fencing_digest(match, agent, node, data_set);
2177 if(data->rc == RSC_DIGEST_ALL) {
2178 optional = FALSE;
2179 crm_notice("Unfencing %s (remote): because the definition of %s changed", node->details->uname, match->id);
2180 if (!pcmk__is_daemon && data_set->priv != NULL) {
2181 pcmk__output_t *out = data_set->priv;
2182 out->info(out, "notice: Unfencing %s (remote): because the definition of %s changed",
2183 node->details->uname, match->id);
2184 }
2185 }
2186
2187 digests_all_offset += snprintf(
2188 digests_all+digests_all_offset, max-digests_all_offset,
2189 "%s:%s:%s,", match->id, agent, data->digest_all_calc);
2190
2191 digests_secure_offset += snprintf(
2192 digests_secure+digests_secure_offset, max-digests_secure_offset,
2193 "%s:%s:%s,", match->id, agent, data->digest_secure_calc);
2194 }
2195 g_hash_table_insert(stonith_op->meta,
2196 strdup(XML_OP_ATTR_DIGESTS_ALL),
2197 digests_all);
2198 g_hash_table_insert(stonith_op->meta,
2199 strdup(XML_OP_ATTR_DIGESTS_SECURE),
2200 digests_secure);
2201 }
2202
2203 } else {
2204 free(op_key);
2205 }
2206
2207 if (data_set->priority_fencing_delay > 0
2208
2209
2210
2211 && (priority_delay
2212
2213
2214
2215
2216 || g_hash_table_lookup(stonith_op->meta,
2217 XML_CONFIG_ATTR_PRIORITY_FENCING_DELAY) != NULL)) {
2218
2219
2220
2221
2222
2223 char *delay_s = pcmk__itoa(node_priority_fencing_delay(node, data_set));
2224
2225 g_hash_table_insert(stonith_op->meta,
2226 strdup(XML_CONFIG_ATTR_PRIORITY_FENCING_DELAY),
2227 delay_s);
2228 }
2229
2230 if(optional == FALSE && pe_can_fence(data_set, node)) {
2231 pe__clear_action_flags(stonith_op, pe_action_optional);
2232 pe_action_set_reason(stonith_op, reason, false);
2233
2234 } else if(reason && stonith_op->reason == NULL) {
2235 stonith_op->reason = strdup(reason);
2236 }
2237
2238 return stonith_op;
2239 }
2240
2241 void
2242 trigger_unfencing(
2243 pe_resource_t * rsc, pe_node_t *node, const char *reason, pe_action_t *dependency, pe_working_set_t * data_set)
2244 {
2245 if (!pcmk_is_set(data_set->flags, pe_flag_enable_unfencing)) {
2246
2247 return;
2248
2249 } else if ((rsc != NULL)
2250 && !pcmk_is_set(rsc->flags, pe_rsc_fence_device)) {
2251
2252 return;
2253
2254 } else if(node
2255 && node->details->online
2256 && node->details->unclean == FALSE
2257 && node->details->shutdown == FALSE) {
2258 pe_action_t *unfence = pe_fence_op(node, "on", FALSE, reason, FALSE, data_set);
2259
2260 if(dependency) {
2261 order_actions(unfence, dependency, pe_order_optional);
2262 }
2263
2264 } else if(rsc) {
2265 GHashTableIter iter;
2266
2267 g_hash_table_iter_init(&iter, rsc->allowed_nodes);
2268 while (g_hash_table_iter_next(&iter, NULL, (void **)&node)) {
2269 if(node->details->online && node->details->unclean == FALSE && node->details->shutdown == FALSE) {
2270 trigger_unfencing(rsc, node, reason, dependency, data_set);
2271 }
2272 }
2273 }
2274 }
2275
2276 gboolean
2277 add_tag_ref(GHashTable * tags, const char * tag_name, const char * obj_ref)
2278 {
2279 pe_tag_t *tag = NULL;
2280 GList *gIter = NULL;
2281 gboolean is_existing = FALSE;
2282
2283 CRM_CHECK(tags && tag_name && obj_ref, return FALSE);
2284
2285 tag = g_hash_table_lookup(tags, tag_name);
2286 if (tag == NULL) {
2287 tag = calloc(1, sizeof(pe_tag_t));
2288 if (tag == NULL) {
2289 return FALSE;
2290 }
2291 tag->id = strdup(tag_name);
2292 tag->refs = NULL;
2293 g_hash_table_insert(tags, strdup(tag_name), tag);
2294 }
2295
2296 for (gIter = tag->refs; gIter != NULL; gIter = gIter->next) {
2297 const char *existing_ref = (const char *) gIter->data;
2298
2299 if (pcmk__str_eq(existing_ref, obj_ref, pcmk__str_none)){
2300 is_existing = TRUE;
2301 break;
2302 }
2303 }
2304
2305 if (is_existing == FALSE) {
2306 tag->refs = g_list_append(tag->refs, strdup(obj_ref));
2307 crm_trace("Added: tag=%s ref=%s", tag->id, obj_ref);
2308 }
2309
2310 return TRUE;
2311 }
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323 char *
2324 pe__action2reason(pe_action_t *action, enum pe_action_flags flag)
2325 {
2326 const char *change = NULL;
2327
2328 switch (flag) {
2329 case pe_action_runnable:
2330 case pe_action_migrate_runnable:
2331 change = "unrunnable";
2332 break;
2333 case pe_action_optional:
2334 change = "required";
2335 break;
2336 default:
2337
2338 CRM_CHECK(change != NULL, change = "");
2339 break;
2340 }
2341 return crm_strdup_printf("%s%s%s %s", change,
2342 (action->rsc == NULL)? "" : " ",
2343 (action->rsc == NULL)? "" : action->rsc->id,
2344 action->task);
2345 }
2346
2347 void pe_action_set_reason(pe_action_t *action, const char *reason, bool overwrite)
2348 {
2349 if (action->reason != NULL && overwrite) {
2350 pe_rsc_trace(action->rsc, "Changing %s reason from '%s' to '%s'",
2351 action->uuid, action->reason, crm_str(reason));
2352 free(action->reason);
2353 } else if (action->reason == NULL) {
2354 pe_rsc_trace(action->rsc, "Set %s reason to '%s'",
2355 action->uuid, crm_str(reason));
2356 } else {
2357
2358 return;
2359 }
2360
2361 if (reason != NULL) {
2362 action->reason = strdup(reason);
2363 } else {
2364 action->reason = NULL;
2365 }
2366 }
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380 bool
2381 pe__shutdown_requested(pe_node_t *node)
2382 {
2383 const char *shutdown = pe_node_attribute_raw(node, XML_CIB_ATTR_SHUTDOWN);
2384
2385 return !pcmk__str_eq(shutdown, "0", pcmk__str_null_matches);
2386 }
2387
2388
2389
2390
2391
2392
2393
2394
2395 void
2396 pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set)
2397 {
2398 if ((recheck > get_effective_time(data_set))
2399 && ((data_set->recheck_by == 0)
2400 || (data_set->recheck_by > recheck))) {
2401 data_set->recheck_by = recheck;
2402 }
2403 }
2404
2405
2406
2407
2408
2409 void
2410 pe__unpack_dataset_nvpairs(xmlNode *xml_obj, const char *set_name,
2411 pe_rule_eval_data_t *rule_data, GHashTable *hash,
2412 const char *always_first, gboolean overwrite,
2413 pe_working_set_t *data_set)
2414 {
2415 crm_time_t *next_change = crm_time_new_undefined();
2416
2417 pe_eval_nvpairs(data_set->input, xml_obj, set_name, rule_data, hash,
2418 always_first, overwrite, next_change);
2419 if (crm_time_is_defined(next_change)) {
2420 time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change);
2421
2422 pe__update_recheck_time(recheck, data_set);
2423 }
2424 crm_time_free(next_change);
2425 }
2426
2427 bool
2428 pe__resource_is_disabled(pe_resource_t *rsc)
2429 {
2430 const char *target_role = NULL;
2431
2432 CRM_CHECK(rsc != NULL, return false);
2433 target_role = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
2434 if (target_role) {
2435 enum rsc_role_e target_role_e = text2role(target_role);
2436
2437 if ((target_role_e == RSC_ROLE_STOPPED)
2438 || ((target_role_e == RSC_ROLE_UNPROMOTED)
2439 && pcmk_is_set(uber_parent(rsc)->flags, pe_rsc_promotable))) {
2440 return true;
2441 }
2442 }
2443 return false;
2444 }
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455 pe_action_t *
2456 pe__clear_resource_history(pe_resource_t *rsc, pe_node_t *node,
2457 pe_working_set_t *data_set)
2458 {
2459 char *key = NULL;
2460
2461 CRM_ASSERT(rsc && node);
2462 key = pcmk__op_key(rsc->id, CRM_OP_LRM_DELETE, 0);
2463 return custom_action(rsc, key, CRM_OP_LRM_DELETE, node, FALSE, TRUE,
2464 data_set);
2465 }
2466
2467 bool
2468 pe__rsc_running_on_any(pe_resource_t *rsc, GList *node_list)
2469 {
2470 for (GList *ele = rsc->running_on; ele; ele = ele->next) {
2471 pe_node_t *node = (pe_node_t *) ele->data;
2472 if (pcmk__str_in_list(node->details->uname, node_list,
2473 pcmk__str_star_matches|pcmk__str_casei)) {
2474 return true;
2475 }
2476 }
2477
2478 return false;
2479 }
2480
2481 bool
2482 pcmk__rsc_filtered_by_node(pe_resource_t *rsc, GList *only_node)
2483 {
2484 return (rsc->fns->active(rsc, FALSE) && !pe__rsc_running_on_any(rsc, only_node));
2485 }
2486
2487 GList *
2488 pe__filter_rsc_list(GList *rscs, GList *filter)
2489 {
2490 GList *retval = NULL;
2491
2492 for (GList *gIter = rscs; gIter; gIter = gIter->next) {
2493 pe_resource_t *rsc = (pe_resource_t *) gIter->data;
2494
2495
2496
2497
2498 if (pcmk__str_in_list(rsc_printable_id(rsc), filter, pcmk__str_star_matches) ||
2499 (rsc->parent && pcmk__str_in_list(rsc_printable_id(rsc->parent), filter, pcmk__str_star_matches))) {
2500 retval = g_list_prepend(retval, rsc);
2501 }
2502 }
2503
2504 return retval;
2505 }
2506
2507 GList *
2508 pe__build_node_name_list(pe_working_set_t *data_set, const char *s) {
2509 GList *nodes = NULL;
2510
2511 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
2512
2513
2514
2515
2516 nodes = g_list_prepend(nodes, strdup("*"));
2517 } else {
2518 pe_node_t *node = pe_find_node(data_set->nodes, s);
2519
2520 if (node) {
2521
2522
2523
2524 nodes = g_list_prepend(nodes, strdup(s));
2525 } else {
2526
2527
2528
2529
2530
2531
2532 nodes = pe__unames_with_tag(data_set, s);
2533 }
2534 }
2535
2536 return nodes;
2537 }
2538
2539 GList *
2540 pe__build_rsc_list(pe_working_set_t *data_set, const char *s) {
2541 GList *resources = NULL;
2542
2543 if (pcmk__str_eq(s, "*", pcmk__str_null_matches)) {
2544 resources = g_list_prepend(resources, strdup("*"));
2545 } else {
2546 pe_resource_t *rsc = pe_find_resource_with_flags(data_set->resources, s,
2547 pe_find_renamed|pe_find_any);
2548
2549 if (rsc) {
2550
2551
2552
2553
2554
2555 if (strstr(s, ":") != NULL) {
2556 resources = g_list_prepend(resources, strdup(rsc->id));
2557 } else {
2558 resources = g_list_prepend(resources, strdup(rsc_printable_id(rsc)));
2559 }
2560 } else {
2561
2562
2563
2564
2565 resources = pe__rscs_with_tag(data_set, s);
2566 }
2567 }
2568
2569 return resources;
2570 }