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
- pe__action_notif_pseudo_ops
- new_notify_entry
- collect_resource_data
- add_notif_keys
- find_remote_start
- create_notify_actions
- pe__create_action_notifications
- pe__free_action_notification_data
- pe__order_notifs_after_fencing
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/common/xml.h>
12
13 #include <crm/pengine/internal.h>
14 #include <pacemaker-internal.h>
15
16 #include "pe_status_private.h"
17
18 typedef struct notify_entry_s {
19 const pcmk_resource_t *rsc;
20 const pcmk_node_t *node;
21 } notify_entry_t;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 static gint
37 compare_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
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
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
66 tmp = strcmp(entry_a->rsc->id, entry_b->rsc->id);
67 if (tmp != 0) {
68 return tmp;
69 }
70
71
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
83 return strcmp(entry_a->node->priv->id, entry_b->node->priv->id);
84 }
85
86
87
88
89
90
91
92
93
94
95 static notify_entry_t *
96 dup_notify_entry(const notify_entry_t *entry)
97 {
98 notify_entry_t *dup = pcmk__assert_alloc(1, sizeof(notify_entry_t));
99
100 dup->rsc = entry->rsc;
101 dup->node = entry->node;
102 return dup;
103 }
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 static void
119 get_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->priv->name == NULL) {
133 continue;
134 }
135
136
137 if (all_node_names != NULL) {
138 pcmk__add_word(all_node_names, 1024, node->priv->name);
139 }
140
141
142 if (host_node_names != NULL) {
143 if (pcmk__is_guest_or_bundle_node(node)) {
144 const pcmk_resource_t *launcher = NULL;
145
146 launcher = node->priv->remote->priv->launcher;
147 if (launcher->priv->active_nodes != NULL) {
148 node = pcmk__current_node(launcher);
149 if (node->priv->name == NULL) {
150 continue;
151 }
152 }
153 }
154 pcmk__add_word(host_node_names, 1024, node->priv->name);
155 }
156 }
157
158 if ((all_node_names != NULL) && (*all_node_names == NULL)) {
159 *all_node_names = g_string_new(" ");
160 }
161 if ((host_node_names != NULL) && (*host_node_names == NULL)) {
162 *host_node_names = g_string_new(" ");
163 }
164 }
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 static GList *
181 notify_entries_to_strings(GList *list, GString **rsc_names,
182 GString **node_names)
183 {
184 const char *last_rsc_id = NULL;
185
186
187 if (rsc_names != NULL) {
188 *rsc_names = NULL;
189 }
190 if (node_names != NULL) {
191 *node_names = NULL;
192 }
193
194
195 list = g_list_sort(list, compare_notify_entries);
196
197 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
198 notify_entry_t *entry = (notify_entry_t *) gIter->data;
199
200
201 CRM_LOG_ASSERT((entry != NULL) && (entry->rsc != NULL)
202 && (entry->rsc->id != NULL));
203 if ((entry == NULL) || (entry->rsc == NULL)
204 || (entry->rsc->id == NULL)) {
205 continue;
206 }
207
208
209 CRM_LOG_ASSERT((node_names == NULL) || (entry->node != NULL));
210 if ((node_names != NULL) && (entry->node == NULL)) {
211 continue;
212 }
213
214
215 if (pcmk__str_eq(entry->rsc->id, last_rsc_id, pcmk__str_none)) {
216 continue;
217 }
218 last_rsc_id = entry->rsc->id;
219
220 if (rsc_names != NULL) {
221 pcmk__add_word(rsc_names, 1024, entry->rsc->id);
222 }
223 if ((node_names != NULL) && (entry->node->priv->name != NULL)) {
224 pcmk__add_word(node_names, 1024, entry->node->priv->name);
225 }
226 }
227
228
229 if ((rsc_names != NULL) && (*rsc_names == NULL)) {
230 *rsc_names = g_string_new(" ");
231 }
232 if ((node_names != NULL) && (*node_names == NULL)) {
233 *node_names = g_string_new(" ");
234 }
235
236 return list;
237 }
238
239
240
241
242
243
244
245
246
247 static void
248 copy_meta_to_notify(gpointer key, gpointer value, gpointer user_data)
249 {
250 pcmk_action_t *notify = (pcmk_action_t *) user_data;
251
252
253
254
255 if (g_hash_table_lookup(notify->meta, (const char *) key) != NULL) {
256 return;
257 }
258
259 pcmk__insert_dup(notify->meta, (const char *) key, (const char *) value);
260 }
261
262 static void
263 add_notify_data_to_action_meta(const notify_data_t *n_data,
264 pcmk_action_t *action)
265 {
266 for (const GSList *item = n_data->keys; item; item = item->next) {
267 const pcmk_nvpair_t *nvpair = (const pcmk_nvpair_t *) item->data;
268
269 pcmk__insert_meta(action, nvpair->name, nvpair->value);
270 }
271 }
272
273
274
275
276
277
278
279
280
281
282
283
284 static pcmk_action_t *
285 new_notify_pseudo_action(pcmk_resource_t *rsc, const pcmk_action_t *action,
286 const char *notif_action, const char *notif_type)
287 {
288 pcmk_action_t *notify = NULL;
289
290 notify = custom_action(rsc,
291 pcmk__notify_key(rsc->id, notif_type, action->task),
292 notif_action, NULL,
293 pcmk_is_set(action->flags, pcmk__action_optional),
294 rsc->priv->scheduler);
295 pcmk__set_action_flags(notify, pcmk__action_pseudo);
296 pcmk__insert_meta(notify, "notify_key_type", notif_type);
297 pcmk__insert_meta(notify, "notify_key_operation", action->task);
298 return notify;
299 }
300
301
302
303
304
305
306
307
308
309
310
311
312
313 static pcmk_action_t *
314 new_notify_action(pcmk_resource_t *rsc, const pcmk_node_t *node,
315 pcmk_action_t *op, pcmk_action_t *notify_done,
316 const notify_data_t *n_data)
317 {
318 char *key = NULL;
319 pcmk_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, pcmk__action_runnable)) {
334 skip_reason = "original action not runnable";
335 }
336 if (skip_reason != NULL) {
337 pcmk__rsc_trace(rsc, "Skipping notify action for %s on %s: %s",
338 rsc->id, pcmk__node_name(node), 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 pcmk__rsc_trace(rsc, "Creating notify action for %s on %s (%s-%s)",
346 rsc->id, pcmk__node_name(node), 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, pcmk__action_optional),
352 rsc->priv->scheduler);
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, pcmk__ar_ordered);
360 order_actions(notify_action, notify_done, pcmk__ar_ordered);
361 return notify_action;
362 }
363
364
365
366
367
368
369
370
371
372 static void
373 new_post_notify_action(pcmk_resource_t *rsc, const pcmk_node_t *node,
374 notify_data_t *n_data)
375 {
376 pcmk_action_t *notify = NULL;
377
378 pcmk__assert(n_data != NULL);
379
380
381 notify = new_notify_action(rsc, node, n_data->post, n_data->post_done,
382 n_data);
383 if (notify != NULL) {
384 notify->priority = PCMK_SCORE_INFINITY;
385 }
386
387
388 if (n_data->post_done == NULL) {
389 return;
390 }
391 for (GList *iter = rsc->priv->actions; iter != NULL; iter = iter->next) {
392 pcmk_action_t *mon = (pcmk_action_t *) iter->data;
393 const char *interval_ms_s = NULL;
394
395 interval_ms_s = g_hash_table_lookup(mon->meta, PCMK_META_INTERVAL);
396 if (pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches)
397 || pcmk__str_eq(mon->task, PCMK_ACTION_CANCEL, pcmk__str_none)) {
398 continue;
399 }
400 order_actions(n_data->post_done, mon, pcmk__ar_ordered);
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
435 notify_data_t *
436 pe__action_notif_pseudo_ops(pcmk_resource_t *rsc, const char *task,
437 pcmk_action_t *action, pcmk_action_t *complete)
438 {
439 notify_data_t *n_data = NULL;
440
441 if (!pcmk_is_set(rsc->flags, pcmk__rsc_notify)) {
442 return NULL;
443 }
444
445 n_data = pcmk__assert_alloc(1, sizeof(notify_data_t));
446
447 n_data->action = task;
448
449 if (action != NULL) {
450
451
452 n_data->pre = new_notify_pseudo_action(rsc, action, PCMK_ACTION_NOTIFY,
453 "pre");
454 pcmk__set_action_flags(n_data->pre, pcmk__action_runnable);
455 pcmk__insert_meta(n_data->pre, "notify_type", "pre");
456 pcmk__insert_meta(n_data->pre, "notify_operation", n_data->action);
457
458
459 n_data->pre_done = new_notify_pseudo_action(rsc, action,
460 PCMK_ACTION_NOTIFIED,
461 "confirmed-pre");
462 pcmk__set_action_flags(n_data->pre_done, pcmk__action_runnable);
463 pcmk__insert_meta(n_data->pre_done, "notify_type", "pre");
464 pcmk__insert_meta(n_data->pre_done, "notify_operation", n_data->action);
465
466
467 order_actions(n_data->pre, n_data->pre_done, pcmk__ar_ordered);
468 order_actions(n_data->pre_done, action, pcmk__ar_ordered);
469 }
470
471 if (complete != NULL) {
472
473
474 n_data->post = new_notify_pseudo_action(rsc, complete,
475 PCMK_ACTION_NOTIFY, "post");
476 n_data->post->priority = PCMK_SCORE_INFINITY;
477 if (pcmk_is_set(complete->flags, pcmk__action_runnable)) {
478 pcmk__set_action_flags(n_data->post, pcmk__action_runnable);
479 } else {
480 pcmk__clear_action_flags(n_data->post, pcmk__action_runnable);
481 }
482 pcmk__insert_meta(n_data->post, "notify_type", "post");
483 pcmk__insert_meta(n_data->post, "notify_operation", n_data->action);
484
485
486 n_data->post_done = new_notify_pseudo_action(rsc, complete,
487 PCMK_ACTION_NOTIFIED,
488 "confirmed-post");
489 n_data->post_done->priority = PCMK_SCORE_INFINITY;
490 if (pcmk_is_set(complete->flags, pcmk__action_runnable)) {
491 pcmk__set_action_flags(n_data->post_done, pcmk__action_runnable);
492 } else {
493 pcmk__clear_action_flags(n_data->post_done, pcmk__action_runnable);
494 }
495 pcmk__insert_meta(n_data->post_done, "notify_type", "post");
496 pcmk__insert_meta(n_data->post_done,
497 "notify_operation", n_data->action);
498
499
500 order_actions(complete, n_data->post, pcmk__ar_first_implies_then);
501 order_actions(n_data->post, n_data->post_done,
502 pcmk__ar_first_implies_then);
503 }
504
505
506 if ((action != NULL) && (complete != NULL)) {
507 order_actions(n_data->pre_done, n_data->post, pcmk__ar_ordered);
508 }
509 return n_data;
510 }
511
512
513
514
515
516
517
518
519
520
521
522 static notify_entry_t *
523 new_notify_entry(const pcmk_resource_t *rsc, const pcmk_node_t *node)
524 {
525 notify_entry_t *entry = pcmk__assert_alloc(1, sizeof(notify_entry_t));
526
527 entry->rsc = rsc;
528 entry->node = node;
529 return entry;
530 }
531
532
533
534
535
536
537
538
539
540 static void
541 collect_resource_data(pcmk_resource_t *rsc, bool activity,
542 notify_data_t *n_data)
543 {
544 const GList *iter = NULL;
545 notify_entry_t *entry = NULL;
546 const pcmk_node_t *node = NULL;
547
548 if (n_data == NULL) {
549 return;
550 }
551
552 if (n_data->allowed_nodes == NULL) {
553 n_data->allowed_nodes = rsc->priv->allowed_nodes;
554 }
555
556
557 if (rsc->priv->children != NULL) {
558 for (iter = rsc->priv->children; iter != NULL; iter = iter->next) {
559 pcmk_resource_t *child = iter->data;
560
561 collect_resource_data(child, activity, n_data);
562 }
563 return;
564 }
565
566
567
568 if (rsc->priv->active_nodes != NULL) {
569 node = rsc->priv->active_nodes->data;
570 }
571 entry = new_notify_entry(rsc, node);
572
573
574 switch (rsc->priv->orig_role) {
575 case pcmk_role_stopped:
576 n_data->inactive = g_list_prepend(n_data->inactive, entry);
577 break;
578
579 case pcmk_role_started:
580 n_data->active = g_list_prepend(n_data->active, entry);
581 break;
582
583 case pcmk_role_unpromoted:
584 n_data->unpromoted = g_list_prepend(n_data->unpromoted, entry);
585 n_data->active = g_list_prepend(n_data->active,
586 dup_notify_entry(entry));
587 break;
588
589 case pcmk_role_promoted:
590 n_data->promoted = g_list_prepend(n_data->promoted, entry);
591 n_data->active = g_list_prepend(n_data->active,
592 dup_notify_entry(entry));
593 break;
594
595 default:
596 pcmk__sched_err(rsc->priv->scheduler,
597 "Resource %s role on %s (%s) is not supported for "
598 "notifications (bug?)",
599 rsc->id, pcmk__node_name(node),
600 pcmk_role_text(rsc->priv->orig_role));
601 free(entry);
602 break;
603 }
604
605 if (!activity) {
606 return;
607 }
608
609
610 for (iter = rsc->priv->actions; iter != NULL; iter = iter->next) {
611 const pcmk_action_t *op = (const pcmk_action_t *) iter->data;
612
613 if (!pcmk_is_set(op->flags, pcmk__action_optional)
614 && (op->node != NULL)) {
615 enum pcmk__action_type task = pcmk__parse_action(op->task);
616
617 if ((task == pcmk__action_stop) && op->node->details->unclean) {
618
619 } else if (!pcmk_is_set(op->flags, pcmk__action_runnable)) {
620 continue;
621 }
622
623 entry = new_notify_entry(rsc, op->node);
624
625 switch (task) {
626 case pcmk__action_start:
627 n_data->start = g_list_prepend(n_data->start, entry);
628 break;
629 case pcmk__action_stop:
630 n_data->stop = g_list_prepend(n_data->stop, entry);
631 break;
632 case pcmk__action_promote:
633 n_data->promote = g_list_prepend(n_data->promote, entry);
634 break;
635 case pcmk__action_demote:
636 n_data->demote = g_list_prepend(n_data->demote, entry);
637 break;
638 default:
639 free(entry);
640 break;
641 }
642 }
643 }
644 }
645
646
647 #define add_notify_env(n_data, key, value) do { \
648 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, value); \
649 } while (0)
650
651
652 #define add_notify_env_gs(n_data, key, value) do { \
653 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, \
654 (const char *) value->str); \
655 } while (0)
656
657
658 #define add_notify_env_free_gs(n_data, key, value) do { \
659 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, \
660 (const char *) value->str); \
661 g_string_free(value, TRUE); value = NULL; \
662 } while (0)
663
664
665
666
667
668
669
670
671 static void
672 add_notif_keys(const pcmk_resource_t *rsc, notify_data_t *n_data)
673 {
674 bool required = false;
675 GString *rsc_list = NULL;
676 GString *node_list = NULL;
677 GString *metal_list = NULL;
678 const char *source = NULL;
679 GList *nodes = NULL;
680
681 n_data->stop = notify_entries_to_strings(n_data->stop,
682 &rsc_list, &node_list);
683 if ((strcmp(" ", (const char *) rsc_list->str) != 0)
684 && pcmk__str_eq(n_data->action, PCMK_ACTION_STOP, pcmk__str_none)) {
685 required = true;
686 }
687 add_notify_env_free_gs(n_data, "notify_stop_resource", rsc_list);
688 add_notify_env_free_gs(n_data, "notify_stop_uname", node_list);
689
690 if ((n_data->start != NULL)
691 && pcmk__str_eq(n_data->action, PCMK_ACTION_START, pcmk__str_none)) {
692 required = true;
693 }
694 n_data->start = notify_entries_to_strings(n_data->start,
695 &rsc_list, &node_list);
696 add_notify_env_free_gs(n_data, "notify_start_resource", rsc_list);
697 add_notify_env_free_gs(n_data, "notify_start_uname", node_list);
698
699 if ((n_data->demote != NULL)
700 && pcmk__str_eq(n_data->action, PCMK_ACTION_DEMOTE, pcmk__str_none)) {
701 required = true;
702 }
703 n_data->demote = notify_entries_to_strings(n_data->demote,
704 &rsc_list, &node_list);
705 add_notify_env_free_gs(n_data, "notify_demote_resource", rsc_list);
706 add_notify_env_free_gs(n_data, "notify_demote_uname", node_list);
707
708 if ((n_data->promote != NULL)
709 && pcmk__str_eq(n_data->action, PCMK_ACTION_PROMOTE, pcmk__str_none)) {
710 required = true;
711 }
712 n_data->promote = notify_entries_to_strings(n_data->promote,
713 &rsc_list, &node_list);
714 add_notify_env_free_gs(n_data, "notify_promote_resource", rsc_list);
715 add_notify_env_free_gs(n_data, "notify_promote_uname", node_list);
716
717 n_data->active = notify_entries_to_strings(n_data->active,
718 &rsc_list, &node_list);
719 add_notify_env_free_gs(n_data, "notify_active_resource", rsc_list);
720 add_notify_env_free_gs(n_data, "notify_active_uname", node_list);
721
722 n_data->unpromoted = notify_entries_to_strings(n_data->unpromoted,
723 &rsc_list, &node_list);
724 add_notify_env_gs(n_data, "notify_unpromoted_resource", rsc_list);
725 add_notify_env_gs(n_data, "notify_unpromoted_uname", node_list);
726
727
728 add_notify_env_free_gs(n_data, "notify_slave_resource", rsc_list);
729 add_notify_env_free_gs(n_data, "notify_slave_uname", node_list);
730
731 n_data->promoted = notify_entries_to_strings(n_data->promoted,
732 &rsc_list, &node_list);
733 add_notify_env_gs(n_data, "notify_promoted_resource", rsc_list);
734 add_notify_env_gs(n_data, "notify_promoted_uname", node_list);
735
736
737 add_notify_env_free_gs(n_data, "notify_master_resource", rsc_list);
738 add_notify_env_free_gs(n_data, "notify_master_uname", node_list);
739
740 n_data->inactive = notify_entries_to_strings(n_data->inactive,
741 &rsc_list, NULL);
742 add_notify_env_free_gs(n_data, "notify_inactive_resource", rsc_list);
743
744 nodes = g_hash_table_get_values(n_data->allowed_nodes);
745 if (!pcmk__is_daemon) {
746
747
748
749
750 nodes = g_list_sort(nodes, pe__cmp_node_name);
751 }
752 get_node_names(nodes, &node_list, NULL);
753 add_notify_env_free_gs(n_data, "notify_available_uname", node_list);
754 g_list_free(nodes);
755
756 source = g_hash_table_lookup(rsc->priv->meta,
757 PCMK_META_CONTAINER_ATTRIBUTE_TARGET);
758 if (pcmk__str_eq(PCMK_VALUE_HOST, source, pcmk__str_none)) {
759 get_node_names(rsc->priv->scheduler->nodes, &node_list, &metal_list);
760 add_notify_env_free_gs(n_data, "notify_all_hosts", metal_list);
761 } else {
762 get_node_names(rsc->priv->scheduler->nodes, &node_list, NULL);
763 }
764 add_notify_env_free_gs(n_data, "notify_all_uname", node_list);
765
766 if (required && (n_data->pre != NULL)) {
767 pcmk__clear_action_flags(n_data->pre, pcmk__action_optional);
768 pcmk__clear_action_flags(n_data->pre_done, pcmk__action_optional);
769 }
770
771 if (required && (n_data->post != NULL)) {
772 pcmk__clear_action_flags(n_data->post, pcmk__action_optional);
773 pcmk__clear_action_flags(n_data->post_done, pcmk__action_optional);
774 }
775 }
776
777
778
779
780
781
782
783
784
785 static pcmk_action_t *
786 find_remote_start(pcmk_action_t *action)
787 {
788 if ((action != NULL) && (action->node != NULL)) {
789 pcmk_resource_t *remote_rsc = action->node->priv->remote;
790
791 if (remote_rsc != NULL) {
792 return find_first_action(remote_rsc->priv->actions, NULL,
793 PCMK_ACTION_START,
794 NULL);
795 }
796 }
797 return NULL;
798 }
799
800
801
802
803
804
805
806
807 static void
808 create_notify_actions(pcmk_resource_t *rsc, notify_data_t *n_data)
809 {
810 GList *iter = NULL;
811 pcmk_action_t *stop = NULL;
812 pcmk_action_t *start = NULL;
813 enum pcmk__action_type task = pcmk__parse_action(n_data->action);
814
815
816 if (rsc->priv->children != NULL) {
817 g_list_foreach(rsc->priv->children, (GFunc) create_notify_actions,
818 n_data);
819 return;
820 }
821
822
823 for (iter = rsc->priv->actions; iter != NULL; iter = iter->next) {
824 pcmk_action_t *op = (pcmk_action_t *) iter->data;
825
826 if (!pcmk_is_set(op->flags, pcmk__action_optional)
827 && (op->node != NULL)) {
828 switch (pcmk__parse_action(op->task)) {
829 case pcmk__action_start:
830 case pcmk__action_stop:
831 case pcmk__action_promote:
832 case pcmk__action_demote:
833 add_notify_data_to_action_meta(n_data, op);
834 break;
835 default:
836 break;
837 }
838 }
839 }
840
841
842 switch (task) {
843 case pcmk__action_start:
844 if (n_data->start == NULL) {
845 pcmk__rsc_trace(rsc, "No notify action needed for %s %s",
846 rsc->id, n_data->action);
847 return;
848 }
849 break;
850
851 case pcmk__action_promote:
852 if (n_data->promote == NULL) {
853 pcmk__rsc_trace(rsc, "No notify action needed for %s %s",
854 rsc->id, n_data->action);
855 return;
856 }
857 break;
858
859 case pcmk__action_demote:
860 if (n_data->demote == NULL) {
861 pcmk__rsc_trace(rsc, "No notify action needed for %s %s",
862 rsc->id, n_data->action);
863 return;
864 }
865 break;
866
867 default:
868
869 break;
870 }
871
872 pcmk__rsc_trace(rsc, "Creating notify actions for %s %s",
873 rsc->id, n_data->action);
874
875
876 if ((rsc->priv->orig_role != pcmk_role_stopped)
877 && ((task == pcmk__action_stop) || (task == pcmk__action_demote))) {
878
879 stop = find_first_action(rsc->priv->actions, NULL, PCMK_ACTION_STOP,
880 NULL);
881
882 for (iter = rsc->priv->active_nodes;
883 iter != NULL; iter = iter->next) {
884
885 pcmk_node_t *current_node = (pcmk_node_t *) iter->data;
886
887
888
889
890 if ((stop != NULL)
891 && pcmk_is_set(stop->flags, pcmk__action_pseudo)
892 && (current_node->details->unclean
893 || pcmk_is_set(current_node->priv->flags,
894 pcmk__node_remote_reset))) {
895 continue;
896 }
897
898 new_notify_action(rsc, current_node, n_data->pre,
899 n_data->pre_done, n_data);
900
901 if ((task == pcmk__action_demote) || (stop == NULL)
902 || pcmk_is_set(stop->flags, pcmk__action_optional)) {
903 new_post_notify_action(rsc, current_node, n_data);
904 }
905 }
906 }
907
908
909 if ((rsc->priv->next_role != pcmk_role_stopped)
910 && ((task == pcmk__action_start) || (task == pcmk__action_promote))) {
911
912 start = find_first_action(rsc->priv->actions, NULL,
913 PCMK_ACTION_START, NULL);
914 if (start != NULL) {
915 pcmk_action_t *remote_start = find_remote_start(start);
916
917 if ((remote_start != NULL)
918 && !pcmk_is_set(remote_start->flags, pcmk__action_runnable)) {
919
920
921
922
923
924 return;
925 }
926 }
927 if (rsc->priv->assigned_node == NULL) {
928 pcmk__sched_err(rsc->priv->scheduler,
929 "Next role '%s' but %s is not allocated",
930 pcmk_role_text(rsc->priv->next_role), rsc->id);
931 return;
932 }
933 if ((task != pcmk__action_start) || (start == NULL)
934 || pcmk_is_set(start->flags, pcmk__action_optional)) {
935
936 new_notify_action(rsc, rsc->priv->assigned_node, n_data->pre,
937 n_data->pre_done, n_data);
938 }
939 new_post_notify_action(rsc, rsc->priv->assigned_node, n_data);
940 }
941 }
942
943
944
945
946
947
948
949
950 void
951 pe__create_action_notifications(pcmk_resource_t *rsc, notify_data_t *n_data)
952 {
953 if ((rsc == NULL) || (n_data == NULL)) {
954 return;
955 }
956 collect_resource_data(rsc, true, n_data);
957 add_notif_keys(rsc, n_data);
958 create_notify_actions(rsc, n_data);
959 }
960
961
962
963
964
965
966
967 void
968 pe__free_action_notification_data(notify_data_t *n_data)
969 {
970 if (n_data == NULL) {
971 return;
972 }
973 g_list_free_full(n_data->stop, free);
974 g_list_free_full(n_data->start, free);
975 g_list_free_full(n_data->demote, free);
976 g_list_free_full(n_data->promote, free);
977 g_list_free_full(n_data->promoted, free);
978 g_list_free_full(n_data->unpromoted, free);
979 g_list_free_full(n_data->active, free);
980 g_list_free_full(n_data->inactive, free);
981 pcmk_free_nvpairs(n_data->keys);
982 free(n_data);
983 }
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999 void
1000 pe__order_notifs_after_fencing(const pcmk_action_t *stop, pcmk_resource_t *rsc,
1001 pcmk_action_t *stonith_op)
1002 {
1003 notify_data_t *n_data;
1004
1005 crm_info("Ordering notifications for implied %s after fencing", stop->uuid);
1006 n_data = pe__action_notif_pseudo_ops(rsc, PCMK_ACTION_STOP, NULL,
1007 stonith_op);
1008
1009 if (n_data != NULL) {
1010 collect_resource_data(rsc, false, n_data);
1011 add_notify_env(n_data, "notify_stop_resource", rsc->id);
1012 add_notify_env(n_data, "notify_stop_uname", stop->node->priv->name);
1013 create_notify_actions(uber_parent(rsc), n_data);
1014 pe__free_action_notification_data(n_data);
1015 }
1016 }