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