pacemaker 2.1.8-2.1.8
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pe_notif.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2024 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU General Public License version 2
7 * or later (GPLv2+) WITHOUT ANY WARRANTY.
8 */
9
10#include <crm_internal.h>
11#include <crm/common/xml.h>
12
14#include <pacemaker-internal.h>
15
16#include "pe_status_private.h"
17
18typedef struct notify_entry_s {
19 const pcmk_resource_t *rsc;
20 const pcmk_node_t *node;
22
36static gint
37compare_notify_entries(gconstpointer a, gconstpointer b)
38{
39 int tmp;
40 const notify_entry_t *entry_a = a;
41 const notify_entry_t *entry_b = b;
42
43 // NULL a or b is not actually possible
44 if ((entry_a == NULL) && (entry_b == NULL)) {
45 return 0;
46 }
47 if (entry_a == NULL) {
48 return 1;
49 }
50 if (entry_b == NULL) {
51 return -1;
52 }
53
54 // NULL resources sort first
55 if ((entry_a->rsc == NULL) && (entry_b->rsc == NULL)) {
56 return 0;
57 }
58 if (entry_a->rsc == NULL) {
59 return 1;
60 }
61 if (entry_b->rsc == NULL) {
62 return -1;
63 }
64
65 // Compare resource names
66 tmp = strcmp(entry_a->rsc->id, entry_b->rsc->id);
67 if (tmp != 0) {
68 return tmp;
69 }
70
71 // Otherwise NULL nodes sort first
72 if ((entry_a->node == NULL) && (entry_b->node == NULL)) {
73 return 0;
74 }
75 if (entry_a->node == NULL) {
76 return 1;
77 }
78 if (entry_b->node == NULL) {
79 return -1;
80 }
81
82 // Finally, compare node names
83 return strcmp(entry_a->node->details->id, entry_b->node->details->id);
84}
85
95static notify_entry_t *
96dup_notify_entry(const notify_entry_t *entry)
97{
99
100 dup->rsc = entry->rsc;
101 dup->node = entry->node;
102 return dup;
103}
104
118static void
119get_node_names(const GList *list, GString **all_node_names,
120 GString **host_node_names)
121{
122 if (all_node_names != NULL) {
123 *all_node_names = NULL;
124 }
125 if (host_node_names != NULL) {
126 *host_node_names = NULL;
127 }
128
129 for (const GList *iter = list; iter != NULL; iter = iter->next) {
130 const pcmk_node_t *node = (const pcmk_node_t *) iter->data;
131
132 if (node->details->uname == NULL) {
133 continue;
134 }
135
136 // Always add to list of all node names
137 if (all_node_names != NULL) {
138 pcmk__add_word(all_node_names, 1024, node->details->uname);
139 }
140
141 // Add to host node name list if appropriate
142 if (host_node_names != NULL) {
143 if (pcmk__is_guest_or_bundle_node(node)
144 && (node->details->remote_rsc->container->running_on != NULL)) {
145 node = pcmk__current_node(node->details->remote_rsc->container);
146 if (node->details->uname == NULL) {
147 continue;
148 }
149 }
150 pcmk__add_word(host_node_names, 1024, node->details->uname);
151 }
152 }
153
154 if ((all_node_names != NULL) && (*all_node_names == NULL)) {
155 *all_node_names = g_string_new(" ");
156 }
157 if ((host_node_names != NULL) && (*host_node_names == NULL)) {
158 *host_node_names = g_string_new(" ");
159 }
160}
161
176static GList *
177notify_entries_to_strings(GList *list, GString **rsc_names,
178 GString **node_names)
179{
180 const char *last_rsc_id = NULL;
181
182 // Initialize output lists to NULL
183 if (rsc_names != NULL) {
184 *rsc_names = NULL;
185 }
186 if (node_names != NULL) {
187 *node_names = NULL;
188 }
189
190 // Sort input list for user-friendliness (and ease of filtering duplicates)
191 list = g_list_sort(list, compare_notify_entries);
192
193 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
194 notify_entry_t *entry = (notify_entry_t *) gIter->data;
195
196 // Entry must have a resource (with ID)
197 CRM_LOG_ASSERT((entry != NULL) && (entry->rsc != NULL)
198 && (entry->rsc->id != NULL));
199 if ((entry == NULL) || (entry->rsc == NULL)
200 || (entry->rsc->id == NULL)) {
201 continue;
202 }
203
204 // Entry must have a node unless listing inactive resources
205 CRM_LOG_ASSERT((node_names == NULL) || (entry->node != NULL));
206 if ((node_names != NULL) && (entry->node == NULL)) {
207 continue;
208 }
209
210 // Don't add duplicates of a particular clone instance
211 if (pcmk__str_eq(entry->rsc->id, last_rsc_id, pcmk__str_none)) {
212 continue;
213 }
214 last_rsc_id = entry->rsc->id;
215
216 if (rsc_names != NULL) {
217 pcmk__add_word(rsc_names, 1024, entry->rsc->id);
218 }
219 if ((node_names != NULL) && (entry->node->details->uname != NULL)) {
220 pcmk__add_word(node_names, 1024, entry->node->details->uname);
221 }
222 }
223
224 // If there are no entries, return "empty" lists
225 if ((rsc_names != NULL) && (*rsc_names == NULL)) {
226 *rsc_names = g_string_new(" ");
227 }
228 if ((node_names != NULL) && (*node_names == NULL)) {
229 *node_names = g_string_new(" ");
230 }
231
232 return list;
233}
234
243static void
244copy_meta_to_notify(gpointer key, gpointer value, gpointer user_data)
245{
246 pcmk_action_t *notify = (pcmk_action_t *) user_data;
247
248 /* Any existing meta-attributes (for example, the action timeout) are for
249 * the notify action itself, so don't override those.
250 */
251 if (g_hash_table_lookup(notify->meta, (const char *) key) != NULL) {
252 return;
253 }
254
255 pcmk__insert_dup(notify->meta, (const char *) key, (const char *) value);
256}
257
258static void
259add_notify_data_to_action_meta(const notify_data_t *n_data,
261{
262 for (const GSList *item = n_data->keys; item; item = item->next) {
263 const pcmk_nvpair_t *nvpair = (const pcmk_nvpair_t *) item->data;
264
265 pcmk__insert_meta(action, nvpair->name, nvpair->value);
266 }
267}
268
280static pcmk_action_t *
281new_notify_pseudo_action(pcmk_resource_t *rsc, const pcmk_action_t *action,
282 const char *notif_action, const char *notif_type)
283{
284 pcmk_action_t *notify = NULL;
285
286 notify = custom_action(rsc,
287 pcmk__notify_key(rsc->id, notif_type, action->task),
288 notif_action, NULL,
290 rsc->cluster);
292 pcmk__insert_meta(notify, "notify_key_type", notif_type);
293 pcmk__insert_meta(notify, "notify_key_operation", action->task);
294 return notify;
295}
296
309static pcmk_action_t *
310new_notify_action(pcmk_resource_t *rsc, const pcmk_node_t *node,
311 pcmk_action_t *op, pcmk_action_t *notify_done,
312 const notify_data_t *n_data)
313{
314 char *key = NULL;
315 pcmk_action_t *notify_action = NULL;
316 const char *value = NULL;
317 const char *task = NULL;
318 const char *skip_reason = NULL;
319
320 CRM_CHECK((rsc != NULL) && (node != NULL), return NULL);
321
322 // Ensure we have all the info we need
323 if (op == NULL) {
324 skip_reason = "no action";
325 } else if (notify_done == NULL) {
326 skip_reason = "no parent notification";
327 } else if (!node->details->online) {
328 skip_reason = "node offline";
329 } else if (!pcmk_is_set(op->flags, pcmk_action_runnable)) {
330 skip_reason = "original action not runnable";
331 }
332 if (skip_reason != NULL) {
333 pcmk__rsc_trace(rsc, "Skipping notify action for %s on %s: %s",
334 rsc->id, pcmk__node_name(node), skip_reason);
335 return NULL;
336 }
337
338 value = g_hash_table_lookup(op->meta, "notify_type"); // "pre" or "post"
339 task = g_hash_table_lookup(op->meta, "notify_operation"); // original action
340
341 pcmk__rsc_trace(rsc, "Creating notify action for %s on %s (%s-%s)",
342 rsc->id, pcmk__node_name(node), value, task);
343
344 // Create the notify action
345 key = pcmk__notify_key(rsc->id, value, task);
346 notify_action = custom_action(rsc, key, op->task, node,
348 rsc->cluster);
349
350 // Add meta-data to notify action
351 g_hash_table_foreach(op->meta, copy_meta_to_notify, notify_action);
352 add_notify_data_to_action_meta(n_data, notify_action);
353
354 // Order notify after original action and before parent notification
355 order_actions(op, notify_action, pcmk__ar_ordered);
356 order_actions(notify_action, notify_done, pcmk__ar_ordered);
357 return notify_action;
358}
359
368static void
369new_post_notify_action(pcmk_resource_t *rsc, const pcmk_node_t *node,
370 notify_data_t *n_data)
371{
372 pcmk_action_t *notify = NULL;
373
374 CRM_ASSERT(n_data != NULL);
375
376 // Create the "post-" notify action for specified instance
377 notify = new_notify_action(rsc, node, n_data->post, n_data->post_done,
378 n_data);
379 if (notify != NULL) {
381 }
382
383 // Order recurring monitors after all "post-" notifications complete
384 if (n_data->post_done == NULL) {
385 return;
386 }
387 for (GList *iter = rsc->actions; iter != NULL; iter = iter->next) {
388 pcmk_action_t *mon = (pcmk_action_t *) iter->data;
389 const char *interval_ms_s = NULL;
390
391 interval_ms_s = g_hash_table_lookup(mon->meta, PCMK_META_INTERVAL);
392 if (pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches)
393 || pcmk__str_eq(mon->task, PCMK_ACTION_CANCEL, pcmk__str_none)) {
394 continue; // Not a recurring monitor
395 }
397 }
398}
399
434{
435 notify_data_t *n_data = NULL;
436
437 if (!pcmk_is_set(rsc->flags, pcmk_rsc_notify)) {
438 return NULL;
439 }
440
441 n_data = pcmk__assert_alloc(1, sizeof(notify_data_t));
442
443 n_data->action = task;
444
445 if (action != NULL) { // Need "pre-" pseudo-actions
446
447 // Create "pre-" notify pseudo-action for clone
448 n_data->pre = new_notify_pseudo_action(rsc, action, PCMK_ACTION_NOTIFY,
449 "pre");
451 pcmk__insert_meta(n_data->pre, "notify_type", "pre");
452 pcmk__insert_meta(n_data->pre, "notify_operation", n_data->action);
453
454 // Create "pre-" notifications complete pseudo-action for clone
455 n_data->pre_done = new_notify_pseudo_action(rsc, action,
457 "confirmed-pre");
459 pcmk__insert_meta(n_data->pre_done, "notify_type", "pre");
460 pcmk__insert_meta(n_data->pre_done, "notify_operation", n_data->action);
461
462 // Order "pre-" -> "pre-" complete -> original action
463 order_actions(n_data->pre, n_data->pre_done, pcmk__ar_ordered);
465 }
466
467 if (complete != NULL) { // Need "post-" pseudo-actions
468
469 // Create "post-" notify pseudo-action for clone
470 n_data->post = new_notify_pseudo_action(rsc, complete,
471 PCMK_ACTION_NOTIFY, "post");
473 if (pcmk_is_set(complete->flags, pcmk_action_runnable)) {
475 } else {
477 }
478 pcmk__insert_meta(n_data->post, "notify_type", "post");
479 pcmk__insert_meta(n_data->post, "notify_operation", n_data->action);
480
481 // Create "post-" notifications complete pseudo-action for clone
482 n_data->post_done = new_notify_pseudo_action(rsc, complete,
484 "confirmed-post");
486 if (pcmk_is_set(complete->flags, pcmk_action_runnable)) {
488 } else {
490 }
491 pcmk__insert_meta(n_data->post_done, "notify_type", "post");
493 "notify_operation", n_data->action);
494
495 // Order original action complete -> "post-" -> "post-" complete
497 order_actions(n_data->post, n_data->post_done,
499 }
500
501 // If we created both, order "pre-" complete -> "post-"
502 if ((action != NULL) && (complete != NULL)) {
503 order_actions(n_data->pre_done, n_data->post, pcmk__ar_ordered);
504 }
505 return n_data;
506}
507
518static notify_entry_t *
519new_notify_entry(const pcmk_resource_t *rsc, const pcmk_node_t *node)
520{
522
523 entry->rsc = rsc;
524 entry->node = node;
525 return entry;
526}
527
536static void
537collect_resource_data(const pcmk_resource_t *rsc, bool activity,
538 notify_data_t *n_data)
539{
540 const GList *iter = NULL;
541 notify_entry_t *entry = NULL;
542 const pcmk_node_t *node = NULL;
543
544 if (n_data == NULL) {
545 return;
546 }
547
548 if (n_data->allowed_nodes == NULL) {
549 n_data->allowed_nodes = rsc->allowed_nodes;
550 }
551
552 // If this is a clone, call recursively for each instance
553 if (rsc->children != NULL) {
554 for (iter = rsc->children; iter != NULL; iter = iter->next) {
555 const pcmk_resource_t *child = (const pcmk_resource_t *) iter->data;
556
557 collect_resource_data(child, activity, n_data);
558 }
559 return;
560 }
561
562 // This is a notification for a single clone instance
563
564 if (rsc->running_on != NULL) {
565 node = rsc->running_on->data; // First is sufficient
566 }
567 entry = new_notify_entry(rsc, node);
568
569 // Add notification indicating the resource state
570 switch (rsc->role) {
572 n_data->inactive = g_list_prepend(n_data->inactive, entry);
573 break;
574
576 n_data->active = g_list_prepend(n_data->active, entry);
577 break;
578
580 n_data->unpromoted = g_list_prepend(n_data->unpromoted, entry);
581 n_data->active = g_list_prepend(n_data->active,
582 dup_notify_entry(entry));
583 break;
584
586 n_data->promoted = g_list_prepend(n_data->promoted, entry);
587 n_data->active = g_list_prepend(n_data->active,
588 dup_notify_entry(entry));
589 break;
590
591 default:
592 pcmk__sched_err("Resource %s role on %s (%s) is not supported for "
593 "notifications (bug?)",
594 rsc->id, pcmk__node_name(node),
595 pcmk_role_text(rsc->role));
596 free(entry);
597 break;
598 }
599
600 if (!activity) {
601 return;
602 }
603
604 // Add notification entries for each of the resource's actions
605 for (iter = rsc->actions; iter != NULL; iter = iter->next) {
606 const pcmk_action_t *op = (const pcmk_action_t *) iter->data;
607
609 && (op->node != NULL)) {
610 enum action_tasks task = pcmk_parse_action(op->task);
611
612 if ((task == pcmk_action_stop) && op->node->details->unclean) {
613 // Create anyway (additional noise if node can't be fenced)
614 } else if (!pcmk_is_set(op->flags, pcmk_action_runnable)) {
615 continue;
616 }
617
618 entry = new_notify_entry(rsc, op->node);
619
620 switch (task) {
622 n_data->start = g_list_prepend(n_data->start, entry);
623 break;
624 case pcmk_action_stop:
625 n_data->stop = g_list_prepend(n_data->stop, entry);
626 break;
628 n_data->promote = g_list_prepend(n_data->promote, entry);
629 break;
631 n_data->demote = g_list_prepend(n_data->demote, entry);
632 break;
633 default:
634 free(entry);
635 break;
636 }
637 }
638 }
639}
640
641// For (char *) value
642#define add_notify_env(n_data, key, value) do { \
643 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, value); \
644 } while (0)
645
646// For (GString *) value
647#define add_notify_env_gs(n_data, key, value) do { \
648 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, \
649 (const char *) value->str); \
650 } while (0)
651
652// For (GString *) value
653#define add_notify_env_free_gs(n_data, key, value) do { \
654 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, \
655 (const char *) value->str); \
656 g_string_free(value, TRUE); value = NULL; \
657 } while (0)
658
666static void
667add_notif_keys(const pcmk_resource_t *rsc, notify_data_t *n_data)
668{
669 bool required = false; // Whether to make notify actions required
670 GString *rsc_list = NULL;
671 GString *node_list = NULL;
672 GString *metal_list = NULL;
673 const char *source = NULL;
674 GList *nodes = NULL;
675
676 n_data->stop = notify_entries_to_strings(n_data->stop,
677 &rsc_list, &node_list);
678 if ((strcmp(" ", (const char *) rsc_list->str) != 0)
679 && pcmk__str_eq(n_data->action, PCMK_ACTION_STOP, pcmk__str_none)) {
680 required = true;
681 }
682 add_notify_env_free_gs(n_data, "notify_stop_resource", rsc_list);
683 add_notify_env_free_gs(n_data, "notify_stop_uname", node_list);
684
685 if ((n_data->start != NULL)
686 && pcmk__str_eq(n_data->action, PCMK_ACTION_START, pcmk__str_none)) {
687 required = true;
688 }
689 n_data->start = notify_entries_to_strings(n_data->start,
690 &rsc_list, &node_list);
691 add_notify_env_free_gs(n_data, "notify_start_resource", rsc_list);
692 add_notify_env_free_gs(n_data, "notify_start_uname", node_list);
693
694 if ((n_data->demote != NULL)
695 && pcmk__str_eq(n_data->action, PCMK_ACTION_DEMOTE, pcmk__str_none)) {
696 required = true;
697 }
698 n_data->demote = notify_entries_to_strings(n_data->demote,
699 &rsc_list, &node_list);
700 add_notify_env_free_gs(n_data, "notify_demote_resource", rsc_list);
701 add_notify_env_free_gs(n_data, "notify_demote_uname", node_list);
702
703 if ((n_data->promote != NULL)
704 && pcmk__str_eq(n_data->action, PCMK_ACTION_PROMOTE, pcmk__str_none)) {
705 required = true;
706 }
707 n_data->promote = notify_entries_to_strings(n_data->promote,
708 &rsc_list, &node_list);
709 add_notify_env_free_gs(n_data, "notify_promote_resource", rsc_list);
710 add_notify_env_free_gs(n_data, "notify_promote_uname", node_list);
711
712 n_data->active = notify_entries_to_strings(n_data->active,
713 &rsc_list, &node_list);
714 add_notify_env_free_gs(n_data, "notify_active_resource", rsc_list);
715 add_notify_env_free_gs(n_data, "notify_active_uname", node_list);
716
717 n_data->unpromoted = notify_entries_to_strings(n_data->unpromoted,
718 &rsc_list, &node_list);
719 add_notify_env_gs(n_data, "notify_unpromoted_resource", rsc_list);
720 add_notify_env_gs(n_data, "notify_unpromoted_uname", node_list);
721
722 // Deprecated: kept for backward compatibility with older resource agents
723 add_notify_env_free_gs(n_data, "notify_slave_resource", rsc_list);
724 add_notify_env_free_gs(n_data, "notify_slave_uname", node_list);
725
726 n_data->promoted = notify_entries_to_strings(n_data->promoted,
727 &rsc_list, &node_list);
728 add_notify_env_gs(n_data, "notify_promoted_resource", rsc_list);
729 add_notify_env_gs(n_data, "notify_promoted_uname", node_list);
730
731 // Deprecated: kept for backward compatibility with older resource agents
732 add_notify_env_free_gs(n_data, "notify_master_resource", rsc_list);
733 add_notify_env_free_gs(n_data, "notify_master_uname", node_list);
734
735 n_data->inactive = notify_entries_to_strings(n_data->inactive,
736 &rsc_list, NULL);
737 add_notify_env_free_gs(n_data, "notify_inactive_resource", rsc_list);
738
739 nodes = g_hash_table_get_values(n_data->allowed_nodes);
740 if (!pcmk__is_daemon) {
741 /* For display purposes, sort the node list, for consistent
742 * regression test output (while avoiding the performance hit
743 * for the live cluster).
744 */
745 nodes = g_list_sort(nodes, pe__cmp_node_name);
746 }
747 get_node_names(nodes, &node_list, NULL);
748 add_notify_env_free_gs(n_data, "notify_available_uname", node_list);
749 g_list_free(nodes);
750
751 source = g_hash_table_lookup(rsc->meta,
753 if (pcmk__str_eq(PCMK_VALUE_HOST, source, pcmk__str_none)) {
754 get_node_names(rsc->cluster->nodes, &node_list, &metal_list);
755 add_notify_env_free_gs(n_data, "notify_all_hosts", metal_list);
756 } else {
757 get_node_names(rsc->cluster->nodes, &node_list, NULL);
758 }
759 add_notify_env_free_gs(n_data, "notify_all_uname", node_list);
760
761 if (required && (n_data->pre != NULL)) {
764 }
765
766 if (required && (n_data->post != NULL)) {
769 }
770}
771
772/*
773 * \internal
774 * \brief Find any remote connection start relevant to an action
775 *
776 * \param[in] action Action to check
777 *
778 * \return If action is behind a remote connection, connection's start
779 */
780static pcmk_action_t *
781find_remote_start(pcmk_action_t *action)
782{
783 if ((action != NULL) && (action->node != NULL)) {
784 pcmk_resource_t *remote_rsc = action->node->details->remote_rsc;
785
786 if (remote_rsc != NULL) {
787 return find_first_action(remote_rsc->actions, NULL,
789 NULL);
790 }
791 }
792 return NULL;
793}
794
802static void
803create_notify_actions(pcmk_resource_t *rsc, notify_data_t *n_data)
804{
805 GList *iter = NULL;
806 pcmk_action_t *stop = NULL;
807 pcmk_action_t *start = NULL;
808 enum action_tasks task = pcmk_parse_action(n_data->action);
809
810 // If this is a clone, call recursively for each instance
811 if (rsc->children != NULL) {
812 g_list_foreach(rsc->children, (GFunc) create_notify_actions, n_data);
813 return;
814 }
815
816 // Add notification meta-attributes to original actions
817 for (iter = rsc->actions; iter != NULL; iter = iter->next) {
818 pcmk_action_t *op = (pcmk_action_t *) iter->data;
819
821 && (op->node != NULL)) {
822 switch (pcmk_parse_action(op->task)) {
824 case pcmk_action_stop:
827 add_notify_data_to_action_meta(n_data, op);
828 break;
829 default:
830 break;
831 }
832 }
833 }
834
835 // Skip notify action itself if original action was not needed
836 switch (task) {
838 if (n_data->start == NULL) {
839 pcmk__rsc_trace(rsc, "No notify action needed for %s %s",
840 rsc->id, n_data->action);
841 return;
842 }
843 break;
844
846 if (n_data->promote == NULL) {
847 pcmk__rsc_trace(rsc, "No notify action needed for %s %s",
848 rsc->id, n_data->action);
849 return;
850 }
851 break;
852
854 if (n_data->demote == NULL) {
855 pcmk__rsc_trace(rsc, "No notify action needed for %s %s",
856 rsc->id, n_data->action);
857 return;
858 }
859 break;
860
861 default:
862 // We cannot do same for stop because it might be implied by fencing
863 break;
864 }
865
866 pcmk__rsc_trace(rsc, "Creating notify actions for %s %s",
867 rsc->id, n_data->action);
868
869 // Create notify actions for stop or demote
870 if ((rsc->role != pcmk_role_stopped)
871 && ((task == pcmk_action_stop) || (task == pcmk_action_demote))) {
872
873 stop = find_first_action(rsc->actions, NULL, PCMK_ACTION_STOP, NULL);
874
875 for (iter = rsc->running_on; iter != NULL; iter = iter->next) {
876 pcmk_node_t *current_node = (pcmk_node_t *) iter->data;
877
878 /* If a stop is a pseudo-action implied by fencing, don't try to
879 * notify the node getting fenced.
880 */
881 if ((stop != NULL)
883 && (current_node->details->unclean
884 || current_node->details->remote_requires_reset)) {
885 continue;
886 }
887
888 new_notify_action(rsc, current_node, n_data->pre,
889 n_data->pre_done, n_data);
890
891 if ((task == pcmk_action_demote) || (stop == NULL)
893 new_post_notify_action(rsc, current_node, n_data);
894 }
895 }
896 }
897
898 // Create notify actions for start or promote
899 if ((rsc->next_role != pcmk_role_stopped)
900 && ((task == pcmk_action_start) || (task == pcmk_action_promote))) {
901
902 start = find_first_action(rsc->actions, NULL, PCMK_ACTION_START, NULL);
903 if (start != NULL) {
904 pcmk_action_t *remote_start = find_remote_start(start);
905
906 if ((remote_start != NULL)
907 && !pcmk_is_set(remote_start->flags, pcmk_action_runnable)) {
908 /* Start and promote actions for a clone instance behind
909 * a Pacemaker Remote connection happen after the
910 * connection starts. If the connection start is blocked, do
911 * not schedule notifications for these actions.
912 */
913 return;
914 }
915 }
916 if (rsc->allocated_to == NULL) {
917 pcmk__sched_err("Next role '%s' but %s is not allocated",
918 pcmk_role_text(rsc->next_role), rsc->id);
919 return;
920 }
921 if ((task != pcmk_action_start) || (start == NULL)
923
924 new_notify_action(rsc, rsc->allocated_to, n_data->pre,
925 n_data->pre_done, n_data);
926 }
927 new_post_notify_action(rsc, rsc->allocated_to, n_data);
928 }
929}
930
938void
940{
941 if ((rsc == NULL) || (n_data == NULL)) {
942 return;
943 }
944 collect_resource_data(rsc, true, n_data);
945 add_notif_keys(rsc, n_data);
946 create_notify_actions(rsc, n_data);
947}
948
955void
957{
958 if (n_data == NULL) {
959 return;
960 }
961 g_list_free_full(n_data->stop, free);
962 g_list_free_full(n_data->start, free);
963 g_list_free_full(n_data->demote, free);
964 g_list_free_full(n_data->promote, free);
965 g_list_free_full(n_data->promoted, free);
966 g_list_free_full(n_data->unpromoted, free);
967 g_list_free_full(n_data->active, free);
968 g_list_free_full(n_data->inactive, free);
969 pcmk_free_nvpairs(n_data->keys);
970 free(n_data);
971}
972
987void
989 pcmk_action_t *stonith_op)
990{
991 notify_data_t *n_data;
992
993 crm_info("Ordering notifications for implied %s after fencing", stop->uuid);
995 stonith_op);
996
997 if (n_data != NULL) {
998 collect_resource_data(rsc, false, n_data);
999 add_notify_env(n_data, "notify_stop_resource", rsc->id);
1000 add_notify_env(n_data, "notify_stop_uname", stop->node->details->uname);
1001 create_notify_actions(uber_parent(rsc), n_data);
1003 }
1004}
@ pcmk__ar_first_implies_then
@ pcmk__ar_ordered
Actions are ordered (optionally, if no other flags are set)
#define PCMK_ACTION_STOP
Definition actions.h:75
#define PCMK_ACTION_CANCEL
Definition actions.h:45
#define PCMK_ACTION_PROMOTE
Definition actions.h:66
#define PCMK_ACTION_START
Definition actions.h:72
#define PCMK_ACTION_NOTIFIED
Definition actions.h:61
@ pcmk_action_runnable
Definition actions.h:207
@ pcmk_action_pseudo
Definition actions.h:204
@ pcmk_action_optional
Definition actions.h:210
action_tasks
Definition actions.h:83
@ pcmk_action_start
Definition actions.h:92
@ pcmk_action_demote
Definition actions.h:101
@ pcmk_action_promote
Definition actions.h:98
@ pcmk_action_stop
Definition actions.h:89
enum action_tasks pcmk_parse_action(const char *action_name)
Parse an action type from an action name.
Definition actions.c:92
#define PCMK_ACTION_DEMOTE
Definition actions.h:49
#define PCMK_ACTION_NOTIFY
Definition actions.h:62
char * pcmk__notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
Definition actions.c:337
#define pcmk__set_action_flags(action, flags_to_set)
#define pcmk__clear_action_flags(action, flags_to_clear)
bool pcmk__is_daemon
Definition logging.c:47
#define pcmk__assert_alloc(nmemb, size)
Definition internal.h:297
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition util.h:98
pcmk_resource_t * uber_parent(pcmk_resource_t *rsc)
Definition complex.c:1007
#define crm_info(fmt, args...)
Definition logging.h:397
#define CRM_LOG_ASSERT(expr)
Definition logging.h:228
#define CRM_CHECK(expr, failure_action)
Definition logging.h:245
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
Definition nvpair.c:101
#define pcmk__insert_meta(obj, name, value)
#define PCMK_META_INTERVAL
Definition options.h:91
#define PCMK_META_CONTAINER_ATTRIBUTE_TARGET
Definition options.h:85
#define PCMK_VALUE_HOST
Definition options.h:160
const char * action
Definition pcmk_fence.c:30
#define add_notify_env(n_data, key, value)
Definition pe_notif.c:642
#define add_notify_env_free_gs(n_data, key, value)
Definition pe_notif.c:653
#define add_notify_env_gs(n_data, key, value)
Definition pe_notif.c:647
void pe__free_action_notification_data(notify_data_t *n_data)
Definition pe_notif.c:956
notify_data_t * pe__action_notif_pseudo_ops(pcmk_resource_t *rsc, const char *task, pcmk_action_t *action, pcmk_action_t *complete)
Definition pe_notif.c:432
void pe__order_notifs_after_fencing(const pcmk_action_t *stop, pcmk_resource_t *rsc, pcmk_action_t *stonith_op)
Definition pe_notif.c:988
struct notify_entry_s notify_entry_t
void pe__create_action_notifications(pcmk_resource_t *rsc, notify_data_t *n_data)
Definition pe_notif.c:939
gboolean order_actions(pcmk_action_t *lh_action, pcmk_action_t *rh_action, uint32_t flags)
Definition utils.c:457
gint pe__cmp_node_name(gconstpointer a, gconstpointer b)
Definition utils.c:145
pcmk_action_t * find_first_action(const GList *input, const char *uuid, const char *task, const pcmk_node_t *on_node)
pcmk_action_t * custom_action(pcmk_resource_t *rsc, char *key, const char *task, const pcmk_node_t *on_node, gboolean optional, pcmk_scheduler_t *scheduler)
Create or update an action object.
@ pcmk_rsc_notify
Definition resources.h:97
#define CRM_ASSERT(expr)
Definition results.h:42
const char * pcmk_role_text(enum rsc_role_e role)
Get readable description of a resource role.
Definition roles.c:23
@ pcmk_role_started
Started.
Definition roles.h:37
@ pcmk_role_unpromoted
Unpromoted.
Definition roles.h:38
@ pcmk_role_promoted
Promoted.
Definition roles.h:39
@ pcmk_role_stopped
Stopped.
Definition roles.h:36
#define pcmk__rsc_trace(rsc, fmt, args...)
#define pcmk__sched_err(fmt...)
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition scores.h:24
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition strings.c:701
@ pcmk__str_none
@ pcmk__str_null_matches
pcmk_action_t * pre
const char * action
GHashTable * allowed_nodes
pcmk_action_t * post
pcmk_action_t * pre_done
pcmk_action_t * post_done
pcmk_node_t * node
Definition actions.h:341
char * uuid
Definition actions.h:344
char * task
Definition actions.h:343
int priority
Definition actions.h:338
GHashTable * meta
Definition actions.h:354
enum pe_action_flags flags
Definition actions.h:349
struct pe_node_shared_s * details
Definition nodes.h:167
gboolean online
Definition nodes.h:80
const char * uname
Definition nodes.h:73
gboolean unclean
Definition nodes.h:91
GList * running_on
Definition resources.h:456
GList * actions
Definition resources.h:444
GHashTable * meta
Definition resources.h:467
GList * children
Definition resources.h:471
pcmk_scheduler_t * cluster
Definition resources.h:408
pcmk_node_t * allocated_to
Definition resources.h:447
GHashTable * allowed_nodes
Definition resources.h:462
unsigned long long flags
Definition resources.h:428
enum rsc_role_e next_role
Definition resources.h:465
enum rsc_role_e role
Definition resources.h:464
Wrappers for and extensions to libxml2.