This source file includes following definitions.
- compare_notify_entries
- dup_notify_entry
- get_node_names
- notify_entries_to_strings
- copy_meta_to_notify
- add_notify_data_to_action_meta
- new_notify_pseudo_action
- new_notify_action
- new_post_notify_action
- pcmk__clone_notif_pseudo_ops
- new_notify_entry
- collect_resource_data
- add_notif_keys
- find_remote_start
- create_notify_actions
- pcmk__create_notifications
- pcmk__free_notification_data
- pcmk__order_notifs_after_fencing
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/msg_xml.h>
12 #include <pacemaker-internal.h>
13 #include "libpacemaker_private.h"
14
15 typedef struct notify_entry_s {
16 pe_resource_t *rsc;
17 pe_node_t *node;
18 } notify_entry_t;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 static gint
34 compare_notify_entries(gconstpointer a, gconstpointer b)
35 {
36 int tmp;
37 const notify_entry_t *entry_a = a;
38 const notify_entry_t *entry_b = b;
39
40
41 if ((entry_a == NULL) && (entry_b == NULL)) {
42 return 0;
43 }
44 if (entry_a == NULL) {
45 return 1;
46 }
47 if (entry_b == NULL) {
48 return -1;
49 }
50
51
52 if ((entry_a->rsc == NULL) && (entry_b->rsc == NULL)) {
53 return 0;
54 }
55 if (entry_a->rsc == NULL) {
56 return 1;
57 }
58 if (entry_b->rsc == NULL) {
59 return -1;
60 }
61
62
63 tmp = strcmp(entry_a->rsc->id, entry_b->rsc->id);
64 if (tmp != 0) {
65 return tmp;
66 }
67
68
69 if ((entry_a->node == NULL) && (entry_b->node == NULL)) {
70 return 0;
71 }
72 if (entry_a->node == NULL) {
73 return 1;
74 }
75 if (entry_b->node == NULL) {
76 return -1;
77 }
78
79
80 return strcmp(entry_a->node->details->id, entry_b->node->details->id);
81 }
82
83
84
85
86
87
88
89
90
91
92 static notify_entry_t *
93 dup_notify_entry(notify_entry_t *entry)
94 {
95 notify_entry_t *dup = calloc(1, sizeof(notify_entry_t));
96
97 CRM_ASSERT(dup != NULL);
98 dup->rsc = entry->rsc;
99 dup->node = entry->node;
100 return dup;
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115 static void
116 get_node_names(GList *list, char **all_node_names, char **host_node_names)
117 {
118 size_t all_len = 0;
119 size_t host_len = 0;
120
121 if (all_node_names != NULL) {
122 *all_node_names = NULL;
123 }
124 if (host_node_names != NULL) {
125 *host_node_names = NULL;
126 }
127
128 for (GList *iter = list; iter != NULL; iter = iter->next) {
129 pe_node_t *node = (pe_node_t *) iter->data;
130
131 if (node->details->uname == NULL) {
132 continue;
133 }
134
135
136 if (all_node_names != NULL) {
137 pcmk__add_word(all_node_names, &all_len, node->details->uname);
138 }
139
140
141 if (host_node_names != NULL) {
142 if (pe__is_guest_node(node)
143 && (node->details->remote_rsc->container->running_on != NULL)) {
144 node = pe__current_node(node->details->remote_rsc->container);
145 if (node->details->uname == NULL) {
146 continue;
147 }
148 }
149 pcmk__add_word(host_node_names, &host_len,
150 node->details->uname);
151 }
152 }
153
154 if ((all_node_names != NULL) && (*all_node_names == NULL)) {
155 *all_node_names = strdup(" ");
156 CRM_ASSERT(*all_node_names != NULL);
157 }
158 if ((host_node_names != NULL) && (*host_node_names == NULL)) {
159 *host_node_names = strdup(" ");
160 CRM_ASSERT(*host_node_names != NULL);
161 }
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 static GList *
178 notify_entries_to_strings(GList *list, char **rsc_names, char **node_names)
179 {
180 const char *last_rsc_id = NULL;
181 size_t rsc_names_len = 0;
182 size_t node_names_len = 0;
183
184
185 if (rsc_names != NULL) {
186 *rsc_names = NULL;
187 }
188 if (node_names != NULL) {
189 *node_names = NULL;
190 }
191
192
193 list = g_list_sort(list, compare_notify_entries);
194
195 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
196 notify_entry_t *entry = (notify_entry_t *) gIter->data;
197
198
199 CRM_LOG_ASSERT((entry != NULL) && (entry->rsc != NULL)
200 && (entry->rsc->id != NULL));
201 if ((entry == NULL) || (entry->rsc == NULL)
202 || (entry->rsc->id == NULL)) {
203 continue;
204 }
205
206
207 CRM_LOG_ASSERT((node_names == NULL) || (entry->node != NULL));
208 if ((node_names != NULL) && (entry->node == NULL)) {
209 continue;
210 }
211
212
213 if (pcmk__str_eq(entry->rsc->id, last_rsc_id, pcmk__str_none)) {
214 continue;
215 }
216 last_rsc_id = entry->rsc->id;
217
218 if (rsc_names != NULL) {
219 pcmk__add_word(rsc_names, &rsc_names_len, entry->rsc->id);
220 }
221 if ((node_names != NULL) && (entry->node->details->uname != NULL)) {
222 pcmk__add_word(node_names, &node_names_len,
223 entry->node->details->uname);
224 }
225 }
226
227
228 if ((rsc_names != NULL) && (*rsc_names == NULL)) {
229 *rsc_names = strdup(" ");
230 CRM_ASSERT(*rsc_names != NULL);
231 }
232 if ((node_names != NULL) && (*node_names == NULL)) {
233 *node_names = strdup(" ");
234 CRM_ASSERT(*node_names != NULL);
235 }
236
237 return list;
238 }
239
240
241
242
243
244
245
246
247
248 static void
249 copy_meta_to_notify(gpointer key, gpointer value, gpointer user_data)
250 {
251 pe_action_t *notify = (pe_action_t *) user_data;
252
253
254
255
256 if (g_hash_table_lookup(notify->meta, (const char *) key) != NULL) {
257 return;
258 }
259
260 g_hash_table_insert(notify->meta, strdup((const char *) key),
261 strdup((const char *) value));
262 }
263
264 static void
265 add_notify_data_to_action_meta(notify_data_t *n_data, pe_action_t *action)
266 {
267 for (GSList *item = n_data->keys; item; item = item->next) {
268 pcmk_nvpair_t *nvpair = item->data;
269
270 add_hash_param(action->meta, nvpair->name, nvpair->value);
271 }
272 }
273
274
275
276
277
278
279
280
281
282
283
284
285 static pe_action_t *
286 new_notify_pseudo_action(pe_resource_t *rsc, const pe_action_t *action,
287 const char *notif_action, const char *notif_type)
288 {
289 pe_action_t *notify = NULL;
290
291 notify = custom_action(rsc,
292 pcmk__notify_key(rsc->id, notif_type, action->task),
293 notif_action, NULL,
294 pcmk_is_set(action->flags, pe_action_optional),
295 TRUE, rsc->cluster);
296 pe__set_action_flags(notify, pe_action_pseudo);
297 add_hash_param(notify->meta, "notify_key_type", notif_type);
298 add_hash_param(notify->meta, "notify_key_operation", action->task);
299 return notify;
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313
314 static pe_action_t *
315 new_notify_action(pe_resource_t *rsc, pe_node_t *node, pe_action_t *op,
316 pe_action_t *notify_done, notify_data_t *n_data)
317 {
318 char *key = NULL;
319 pe_action_t *notify_action = NULL;
320 const char *value = NULL;
321 const char *task = NULL;
322 const char *skip_reason = NULL;
323
324 CRM_CHECK((rsc != NULL) && (node != NULL), return NULL);
325
326
327 if (op == NULL) {
328 skip_reason = "no action";
329 } else if (notify_done == NULL) {
330 skip_reason = "no parent notification";
331 } else if (!node->details->online) {
332 skip_reason = "node offline";
333 } else if (!pcmk_is_set(op->flags, pe_action_runnable)) {
334 skip_reason = "original action not runnable";
335 }
336 if (skip_reason != NULL) {
337 pe_rsc_trace(rsc, "Skipping notify action for %s on %s: %s",
338 rsc->id, node->details->uname, skip_reason);
339 return NULL;
340 }
341
342 value = g_hash_table_lookup(op->meta, "notify_type");
343 task = g_hash_table_lookup(op->meta, "notify_operation");
344
345 pe_rsc_trace(rsc, "Creating notify action for %s on %s (%s-%s)",
346 rsc->id, node->details->uname, value, task);
347
348
349 key = pcmk__notify_key(rsc->id, value, task);
350 notify_action = custom_action(rsc, key, op->task, node,
351 pcmk_is_set(op->flags, pe_action_optional),
352 TRUE, rsc->cluster);
353
354
355 g_hash_table_foreach(op->meta, copy_meta_to_notify, notify_action);
356 add_notify_data_to_action_meta(n_data, notify_action);
357
358
359 order_actions(op, notify_action, pe_order_optional);
360 order_actions(notify_action, notify_done, pe_order_optional);
361 return notify_action;
362 }
363
364
365
366
367
368
369
370
371
372 static void
373 new_post_notify_action(pe_resource_t *rsc, pe_node_t *node,
374 notify_data_t *n_data)
375 {
376 pe_action_t *notify = NULL;
377
378
379 notify = new_notify_action(rsc, node, n_data->post, n_data->post_done,
380 n_data);
381 if (notify != NULL) {
382 notify->priority = INFINITY;
383 }
384
385
386 if (n_data->post_done == NULL) {
387 return;
388 }
389 for (GList *iter = rsc->actions; iter != NULL; iter = iter->next) {
390 pe_action_t *mon = (pe_action_t *) iter->data;
391 const char *interval_ms_s = NULL;
392
393 interval_ms_s = g_hash_table_lookup(mon->meta,
394 XML_LRM_ATTR_INTERVAL_MS);
395 if (pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches)
396 || pcmk__str_eq(mon->task, RSC_CANCEL, pcmk__str_none)) {
397 continue;
398 }
399 order_actions(n_data->post_done, mon, pe_order_optional);
400 }
401 }
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434 notify_data_t *
435 pcmk__clone_notif_pseudo_ops(pe_resource_t *rsc, const char *task,
436 pe_action_t *action, pe_action_t *complete)
437 {
438 notify_data_t *n_data = NULL;
439
440 if (!pcmk_is_set(rsc->flags, pe_rsc_notify)) {
441 return NULL;
442 }
443
444 n_data = calloc(1, sizeof(notify_data_t));
445 CRM_ASSERT(n_data != NULL);
446
447 n_data->action = task;
448
449 if (action != NULL) {
450
451
452 n_data->pre = new_notify_pseudo_action(rsc, action, RSC_NOTIFY, "pre");
453 pe__set_action_flags(n_data->pre, pe_action_runnable);
454 add_hash_param(n_data->pre->meta, "notify_type", "pre");
455 add_hash_param(n_data->pre->meta, "notify_operation", n_data->action);
456
457
458 n_data->pre_done = new_notify_pseudo_action(rsc, action, RSC_NOTIFIED,
459 "confirmed-pre");
460 pe__set_action_flags(n_data->pre_done, pe_action_runnable);
461 add_hash_param(n_data->pre_done->meta, "notify_type", "pre");
462 add_hash_param(n_data->pre_done->meta,
463 "notify_operation", n_data->action);
464
465
466 order_actions(n_data->pre, n_data->pre_done, pe_order_optional);
467 order_actions(n_data->pre_done, action, pe_order_optional);
468 }
469
470 if (complete != NULL) {
471
472
473 n_data->post = new_notify_pseudo_action(rsc, complete, RSC_NOTIFY,
474 "post");
475 n_data->post->priority = INFINITY;
476 if (pcmk_is_set(complete->flags, pe_action_runnable)) {
477 pe__set_action_flags(n_data->post, pe_action_runnable);
478 } else {
479 pe__clear_action_flags(n_data->post, pe_action_runnable);
480 }
481 add_hash_param(n_data->post->meta, "notify_type", "post");
482 add_hash_param(n_data->post->meta, "notify_operation", n_data->action);
483
484
485 n_data->post_done = new_notify_pseudo_action(rsc, complete,
486 RSC_NOTIFIED,
487 "confirmed-post");
488 n_data->post_done->priority = INFINITY;
489 if (pcmk_is_set(complete->flags, pe_action_runnable)) {
490 pe__set_action_flags(n_data->post_done, pe_action_runnable);
491 } else {
492 pe__clear_action_flags(n_data->post_done, pe_action_runnable);
493 }
494 add_hash_param(n_data->post_done->meta, "notify_type", "post");
495 add_hash_param(n_data->post_done->meta,
496 "notify_operation", n_data->action);
497
498
499 order_actions(complete, n_data->post, pe_order_implies_then);
500 order_actions(n_data->post, n_data->post_done, pe_order_implies_then);
501 }
502
503
504 if ((action != NULL) && (complete != NULL)) {
505 order_actions(n_data->pre_done, n_data->post, pe_order_optional);
506 }
507 return n_data;
508 }
509
510
511
512
513
514
515
516
517
518
519
520 static notify_entry_t *
521 new_notify_entry(pe_resource_t *rsc, pe_node_t *node)
522 {
523 notify_entry_t *entry = calloc(1, sizeof(notify_entry_t));
524
525 CRM_ASSERT(entry != NULL);
526 entry->rsc = rsc;
527 entry->node = node;
528 return entry;
529 }
530
531
532
533
534
535
536
537
538
539 static void
540 collect_resource_data(pe_resource_t *rsc, bool activity, notify_data_t *n_data)
541 {
542 GList *iter = NULL;
543 notify_entry_t *entry = NULL;
544 pe_node_t *node = NULL;
545
546 if (n_data->allowed_nodes == NULL) {
547 n_data->allowed_nodes = rsc->allowed_nodes;
548 }
549
550
551 if (rsc->children != NULL) {
552 for (iter = rsc->children; iter != NULL; iter = iter->next) {
553 pe_resource_t *child = (pe_resource_t *) iter->data;
554
555 collect_resource_data(child, activity, n_data);
556 }
557 return;
558 }
559
560
561
562 if (rsc->running_on != NULL) {
563 node = rsc->running_on->data;
564 }
565 entry = new_notify_entry(rsc, node);
566
567
568 switch (rsc->role) {
569 case RSC_ROLE_STOPPED:
570 n_data->inactive = g_list_prepend(n_data->inactive, entry);
571 break;
572
573 case RSC_ROLE_STARTED:
574 n_data->active = g_list_prepend(n_data->active, entry);
575 break;
576
577 case RSC_ROLE_UNPROMOTED:
578 n_data->unpromoted = g_list_prepend(n_data->unpromoted, entry);
579 n_data->active = g_list_prepend(n_data->active,
580 dup_notify_entry(entry));
581 break;
582
583 case RSC_ROLE_PROMOTED:
584 n_data->promoted = g_list_prepend(n_data->promoted, entry);
585 n_data->active = g_list_prepend(n_data->active,
586 dup_notify_entry(entry));
587 break;
588
589 default:
590 crm_err("Resource %s role on %s (%s) is not supported for "
591 "notifications (bug?)",
592 rsc->id, ((node == NULL)? "no node" : node->details->uname),
593 role2text(rsc->role));
594 free(entry);
595 break;
596 }
597
598 if (!activity) {
599 return;
600 }
601
602
603 for (iter = rsc->actions; iter != NULL; iter = iter->next) {
604 pe_action_t *op = (pe_action_t *) iter->data;
605
606 if (!pcmk_is_set(op->flags, pe_action_optional) && (op->node != NULL)) {
607 enum action_tasks task = text2task(op->task);
608
609 if ((task == stop_rsc) && op->node->details->unclean) {
610
611 } else if (!pcmk_is_set(op->flags, pe_action_runnable)) {
612 continue;
613 }
614
615 entry = new_notify_entry(rsc, op->node);
616
617 switch (task) {
618 case start_rsc:
619 n_data->start = g_list_prepend(n_data->start, entry);
620 break;
621 case stop_rsc:
622 n_data->stop = g_list_prepend(n_data->stop, entry);
623 break;
624 case action_promote:
625 n_data->promote = g_list_prepend(n_data->promote, entry);
626 break;
627 case action_demote:
628 n_data->demote = g_list_prepend(n_data->demote, entry);
629 break;
630 default:
631 free(entry);
632 break;
633 }
634 }
635 }
636 }
637
638 #define add_notify_env(n_data, key, value) do { \
639 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, value); \
640 } while (0)
641
642 #define add_notify_env_free(n_data, key, value) do { \
643 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, value); \
644 free(value); value = NULL; \
645 } while (0)
646
647
648
649
650
651
652
653
654 static void
655 add_notif_keys(pe_resource_t *rsc, notify_data_t *n_data)
656 {
657 bool required = false;
658 char *rsc_list = NULL;
659 char *node_list = NULL;
660 char *metal_list = NULL;
661 const char *source = NULL;
662 GList *nodes = NULL;
663
664 n_data->stop = notify_entries_to_strings(n_data->stop,
665 &rsc_list, &node_list);
666 if (!pcmk__str_eq(" ", rsc_list, pcmk__str_null_matches)
667 && pcmk__str_eq(n_data->action, RSC_STOP, pcmk__str_casei)) {
668 required = true;
669 }
670 add_notify_env_free(n_data, "notify_stop_resource", rsc_list);
671 add_notify_env_free(n_data, "notify_stop_uname", node_list);
672
673 if ((n_data->start != NULL)
674 && pcmk__str_eq(n_data->action, RSC_START, pcmk__str_none)) {
675 required = true;
676 }
677 n_data->start = notify_entries_to_strings(n_data->start,
678 &rsc_list, &node_list);
679 add_notify_env_free(n_data, "notify_start_resource", rsc_list);
680 add_notify_env_free(n_data, "notify_start_uname", node_list);
681
682 if ((n_data->demote != NULL)
683 && pcmk__str_eq(n_data->action, RSC_DEMOTE, pcmk__str_none)) {
684 required = true;
685 }
686 n_data->demote = notify_entries_to_strings(n_data->demote,
687 &rsc_list, &node_list);
688 add_notify_env_free(n_data, "notify_demote_resource", rsc_list);
689 add_notify_env_free(n_data, "notify_demote_uname", node_list);
690
691 if ((n_data->promote != NULL)
692 && pcmk__str_eq(n_data->action, RSC_PROMOTE, pcmk__str_none)) {
693 required = true;
694 }
695 n_data->promote = notify_entries_to_strings(n_data->promote,
696 &rsc_list, &node_list);
697 add_notify_env_free(n_data, "notify_promote_resource", rsc_list);
698 add_notify_env_free(n_data, "notify_promote_uname", node_list);
699
700 n_data->active = notify_entries_to_strings(n_data->active,
701 &rsc_list, &node_list);
702 add_notify_env_free(n_data, "notify_active_resource", rsc_list);
703 add_notify_env_free(n_data, "notify_active_uname", node_list);
704
705 n_data->unpromoted = notify_entries_to_strings(n_data->unpromoted,
706 &rsc_list, &node_list);
707 add_notify_env(n_data, "notify_unpromoted_resource", rsc_list);
708 add_notify_env(n_data, "notify_unpromoted_uname", node_list);
709
710
711 add_notify_env_free(n_data, "notify_slave_resource", rsc_list);
712 add_notify_env_free(n_data, "notify_slave_uname", node_list);
713
714 n_data->promoted = notify_entries_to_strings(n_data->promoted,
715 &rsc_list, &node_list);
716 add_notify_env(n_data, "notify_promoted_resource", rsc_list);
717 add_notify_env(n_data, "notify_promoted_uname", node_list);
718
719
720 add_notify_env_free(n_data, "notify_master_resource", rsc_list);
721 add_notify_env_free(n_data, "notify_master_uname", node_list);
722
723 n_data->inactive = notify_entries_to_strings(n_data->inactive,
724 &rsc_list, NULL);
725 add_notify_env_free(n_data, "notify_inactive_resource", rsc_list);
726
727 nodes = g_hash_table_get_values(n_data->allowed_nodes);
728 if (!pcmk__is_daemon) {
729
730
731
732
733 nodes = g_list_sort(nodes, sort_node_uname);
734 }
735 get_node_names(nodes, &node_list, NULL);
736 add_notify_env_free(n_data, "notify_available_uname", node_list);
737 g_list_free(nodes);
738
739 source = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET);
740 if (pcmk__str_eq("host", source, pcmk__str_none)) {
741 get_node_names(rsc->cluster->nodes, &node_list, &metal_list);
742 add_notify_env_free(n_data, "notify_all_hosts", metal_list);
743 } else {
744 get_node_names(rsc->cluster->nodes, &node_list, NULL);
745 }
746 add_notify_env_free(n_data, "notify_all_uname", node_list);
747
748 if (required && (n_data->pre != NULL)) {
749 pe__clear_action_flags(n_data->pre, pe_action_optional);
750 pe__clear_action_flags(n_data->pre_done, pe_action_optional);
751 }
752
753 if (required && (n_data->post != NULL)) {
754 pe__clear_action_flags(n_data->post, pe_action_optional);
755 pe__clear_action_flags(n_data->post_done, pe_action_optional);
756 }
757 }
758
759
760
761
762
763
764
765
766
767 static pe_action_t *
768 find_remote_start(pe_action_t *action)
769 {
770 if ((action != NULL) && (action->node != NULL)) {
771 pe_resource_t *remote_rsc = action->node->details->remote_rsc;
772
773 if (remote_rsc != NULL) {
774 return find_first_action(remote_rsc->actions, NULL, RSC_START,
775 NULL);
776 }
777 }
778 return NULL;
779 }
780
781
782
783
784
785
786
787
788 static void
789 create_notify_actions(pe_resource_t *rsc, notify_data_t *n_data)
790 {
791 GList *iter = NULL;
792 pe_action_t *stop = NULL;
793 pe_action_t *start = NULL;
794 enum action_tasks task = text2task(n_data->action);
795
796
797 if (rsc->children != NULL) {
798 g_list_foreach(rsc->children, (GFunc) create_notify_actions, n_data);
799 return;
800 }
801
802
803 for (iter = rsc->actions; iter != NULL; iter = iter->next) {
804 pe_action_t *op = (pe_action_t *) iter->data;
805
806 if (!pcmk_is_set(op->flags, pe_action_optional) && (op->node != NULL)) {
807 switch (text2task(op->task)) {
808 case start_rsc:
809 case stop_rsc:
810 case action_promote:
811 case action_demote:
812 add_notify_data_to_action_meta(n_data, op);
813 break;
814 default:
815 break;
816 }
817 }
818 }
819
820
821 switch (task) {
822 case start_rsc:
823 if (n_data->start == NULL) {
824 pe_rsc_trace(rsc, "No notify action needed for %s %s",
825 rsc->id, n_data->action);
826 return;
827 }
828 break;
829
830 case action_promote:
831 if (n_data->promote == NULL) {
832 pe_rsc_trace(rsc, "No notify action needed for %s %s",
833 rsc->id, n_data->action);
834 return;
835 }
836 break;
837
838 case action_demote:
839 if (n_data->demote == NULL) {
840 pe_rsc_trace(rsc, "No notify action needed for %s %s",
841 rsc->id, n_data->action);
842 return;
843 }
844 break;
845
846 default:
847
848 break;
849 }
850
851 pe_rsc_trace(rsc, "Creating notify actions for %s %s",
852 rsc->id, n_data->action);
853
854
855 if ((rsc->role != RSC_ROLE_STOPPED)
856 && ((task == stop_rsc) || (task == action_demote))) {
857
858 stop = find_first_action(rsc->actions, NULL, RSC_STOP, NULL);
859
860 for (iter = rsc->running_on; iter != NULL; iter = iter->next) {
861 pe_node_t *current_node = (pe_node_t *) iter->data;
862
863
864
865
866 if ((stop != NULL) && pcmk_is_set(stop->flags, pe_action_pseudo)
867 && (current_node->details->unclean
868 || current_node->details->remote_requires_reset)) {
869 continue;
870 }
871
872 new_notify_action(rsc, current_node, n_data->pre,
873 n_data->pre_done, n_data);
874
875 if ((task == action_demote) || (stop == NULL)
876 || pcmk_is_set(stop->flags, pe_action_optional)) {
877 new_post_notify_action(rsc, current_node, n_data);
878 }
879 }
880 }
881
882
883 if ((rsc->next_role != RSC_ROLE_STOPPED)
884 && ((task == start_rsc) || (task == action_promote))) {
885
886 start = find_first_action(rsc->actions, NULL, RSC_START, NULL);
887 if (start != NULL) {
888 pe_action_t *remote_start = find_remote_start(start);
889
890 if ((remote_start != NULL)
891 && !pcmk_is_set(remote_start->flags, pe_action_runnable)) {
892
893
894
895
896
897 return;
898 }
899 }
900 if (rsc->allocated_to == NULL) {
901 pe_proc_err("Next role '%s' but %s is not allocated",
902 role2text(rsc->next_role), rsc->id);
903 return;
904 }
905 if ((task != start_rsc) || (start == NULL)
906 || pcmk_is_set(start->flags, pe_action_optional)) {
907
908 new_notify_action(rsc, rsc->allocated_to, n_data->pre,
909 n_data->pre_done, n_data);
910 }
911 new_post_notify_action(rsc, rsc->allocated_to, n_data);
912 }
913 }
914
915
916
917
918
919
920
921
922 void
923 pcmk__create_notifications(pe_resource_t *rsc, notify_data_t *n_data)
924 {
925 if ((rsc == NULL) || (n_data == NULL)) {
926 return;
927 }
928 collect_resource_data(rsc, true, n_data);
929 add_notif_keys(rsc, n_data);
930 create_notify_actions(rsc, n_data);
931 }
932
933
934
935
936
937
938
939 void
940 pcmk__free_notification_data(notify_data_t *n_data)
941 {
942 if (n_data == NULL) {
943 return;
944 }
945 g_list_free_full(n_data->stop, free);
946 g_list_free_full(n_data->start, free);
947 g_list_free_full(n_data->demote, free);
948 g_list_free_full(n_data->promote, free);
949 g_list_free_full(n_data->promoted, free);
950 g_list_free_full(n_data->unpromoted, free);
951 g_list_free_full(n_data->active, free);
952 g_list_free_full(n_data->inactive, free);
953 pcmk_free_nvpairs(n_data->keys);
954 free(n_data);
955 }
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971 void
972 pcmk__order_notifs_after_fencing(pe_action_t *stop, pe_resource_t *rsc,
973 pe_action_t *stonith_op)
974 {
975 notify_data_t *n_data;
976
977 crm_info("Ordering notifications for implied %s after fencing", stop->uuid);
978 n_data = pcmk__clone_notif_pseudo_ops(rsc, RSC_STOP, NULL, stonith_op);
979 collect_resource_data(rsc, false, n_data);
980 add_notify_env(n_data, "notify_stop_resource", rsc->id);
981 add_notify_env(n_data, "notify_stop_uname", stop->node->details->uname);
982 create_notify_actions(uber_parent(rsc), n_data);
983 pcmk__free_notification_data(n_data);
984 }