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/msg_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->details->id, entry_b->node->details->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 = calloc(1, sizeof(notify_entry_t));
99
100 CRM_ASSERT(dup != NULL);
101 dup->rsc = entry->rsc;
102 dup->node = entry->node;
103 return dup;
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 static void
120 get_node_names(const GList *list, GString **all_node_names,
121 GString **host_node_names)
122 {
123 if (all_node_names != NULL) {
124 *all_node_names = NULL;
125 }
126 if (host_node_names != NULL) {
127 *host_node_names = NULL;
128 }
129
130 for (const GList *iter = list; iter != NULL; iter = iter->next) {
131 const pcmk_node_t *node = (const pcmk_node_t *) iter->data;
132
133 if (node->details->uname == NULL) {
134 continue;
135 }
136
137
138 if (all_node_names != NULL) {
139 pcmk__add_word(all_node_names, 1024, node->details->uname);
140 }
141
142
143 if (host_node_names != NULL) {
144 if (pe__is_guest_node(node)
145 && (node->details->remote_rsc->container->running_on != NULL)) {
146 node = pe__current_node(node->details->remote_rsc->container);
147 if (node->details->uname == NULL) {
148 continue;
149 }
150 }
151 pcmk__add_word(host_node_names, 1024, node->details->uname);
152 }
153 }
154
155 if ((all_node_names != NULL) && (*all_node_names == NULL)) {
156 *all_node_names = g_string_new(" ");
157 }
158 if ((host_node_names != NULL) && (*host_node_names == NULL)) {
159 *host_node_names = g_string_new(" ");
160 }
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, GString **rsc_names,
179 GString **node_names)
180 {
181 const char *last_rsc_id = NULL;
182
183
184 if (rsc_names != NULL) {
185 *rsc_names = NULL;
186 }
187 if (node_names != NULL) {
188 *node_names = NULL;
189 }
190
191
192 list = g_list_sort(list, compare_notify_entries);
193
194 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
195 notify_entry_t *entry = (notify_entry_t *) gIter->data;
196
197
198 CRM_LOG_ASSERT((entry != NULL) && (entry->rsc != NULL)
199 && (entry->rsc->id != NULL));
200 if ((entry == NULL) || (entry->rsc == NULL)
201 || (entry->rsc->id == NULL)) {
202 continue;
203 }
204
205
206 CRM_LOG_ASSERT((node_names == NULL) || (entry->node != NULL));
207 if ((node_names != NULL) && (entry->node == NULL)) {
208 continue;
209 }
210
211
212 if (pcmk__str_eq(entry->rsc->id, last_rsc_id, pcmk__str_none)) {
213 continue;
214 }
215 last_rsc_id = entry->rsc->id;
216
217 if (rsc_names != NULL) {
218 pcmk__add_word(rsc_names, 1024, entry->rsc->id);
219 }
220 if ((node_names != NULL) && (entry->node->details->uname != NULL)) {
221 pcmk__add_word(node_names, 1024, entry->node->details->uname);
222 }
223 }
224
225
226 if ((rsc_names != NULL) && (*rsc_names == NULL)) {
227 *rsc_names = g_string_new(" ");
228 }
229 if ((node_names != NULL) && (*node_names == NULL)) {
230 *node_names = g_string_new(" ");
231 }
232
233 return list;
234 }
235
236
237
238
239
240
241
242
243
244 static void
245 copy_meta_to_notify(gpointer key, gpointer value, gpointer user_data)
246 {
247 pcmk_action_t *notify = (pcmk_action_t *) user_data;
248
249
250
251
252 if (g_hash_table_lookup(notify->meta, (const char *) key) != NULL) {
253 return;
254 }
255
256 g_hash_table_insert(notify->meta, strdup((const char *) key),
257 strdup((const char *) value));
258 }
259
260 static void
261 add_notify_data_to_action_meta(const notify_data_t *n_data,
262 pcmk_action_t *action)
263 {
264 for (const GSList *item = n_data->keys; item; item = item->next) {
265 const pcmk_nvpair_t *nvpair = (const pcmk_nvpair_t *) item->data;
266
267 add_hash_param(action->meta, nvpair->name, nvpair->value);
268 }
269 }
270
271
272
273
274
275
276
277
278
279
280
281
282 static pcmk_action_t *
283 new_notify_pseudo_action(pcmk_resource_t *rsc, const pcmk_action_t *action,
284 const char *notif_action, const char *notif_type)
285 {
286 pcmk_action_t *notify = NULL;
287
288 notify = custom_action(rsc,
289 pcmk__notify_key(rsc->id, notif_type, action->task),
290 notif_action, NULL,
291 pcmk_is_set(action->flags, pcmk_action_optional),
292 rsc->cluster);
293 pe__set_action_flags(notify, pcmk_action_pseudo);
294 add_hash_param(notify->meta, "notify_key_type", notif_type);
295 add_hash_param(notify->meta, "notify_key_operation", action->task);
296 return notify;
297 }
298
299
300
301
302
303
304
305
306
307
308
309
310
311 static pcmk_action_t *
312 new_notify_action(pcmk_resource_t *rsc, const pcmk_node_t *node,
313 pcmk_action_t *op, pcmk_action_t *notify_done,
314 const notify_data_t *n_data)
315 {
316 char *key = NULL;
317 pcmk_action_t *notify_action = NULL;
318 const char *value = NULL;
319 const char *task = NULL;
320 const char *skip_reason = NULL;
321
322 CRM_CHECK((rsc != NULL) && (node != NULL), return NULL);
323
324
325 if (op == NULL) {
326 skip_reason = "no action";
327 } else if (notify_done == NULL) {
328 skip_reason = "no parent notification";
329 } else if (!node->details->online) {
330 skip_reason = "node offline";
331 } else if (!pcmk_is_set(op->flags, pcmk_action_runnable)) {
332 skip_reason = "original action not runnable";
333 }
334 if (skip_reason != NULL) {
335 pe_rsc_trace(rsc, "Skipping notify action for %s on %s: %s",
336 rsc->id, pe__node_name(node), skip_reason);
337 return NULL;
338 }
339
340 value = g_hash_table_lookup(op->meta, "notify_type");
341 task = g_hash_table_lookup(op->meta, "notify_operation");
342
343 pe_rsc_trace(rsc, "Creating notify action for %s on %s (%s-%s)",
344 rsc->id, pe__node_name(node), value, task);
345
346
347 key = pcmk__notify_key(rsc->id, value, task);
348 notify_action = custom_action(rsc, key, op->task, node,
349 pcmk_is_set(op->flags, pcmk_action_optional),
350 rsc->cluster);
351
352
353 g_hash_table_foreach(op->meta, copy_meta_to_notify, notify_action);
354 add_notify_data_to_action_meta(n_data, notify_action);
355
356
357 order_actions(op, notify_action, pcmk__ar_ordered);
358 order_actions(notify_action, notify_done, pcmk__ar_ordered);
359 return notify_action;
360 }
361
362
363
364
365
366
367
368
369
370 static void
371 new_post_notify_action(pcmk_resource_t *rsc, const pcmk_node_t *node,
372 notify_data_t *n_data)
373 {
374 pcmk_action_t *notify = NULL;
375
376 CRM_ASSERT(n_data != 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 pcmk_action_t *mon = (pcmk_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, PCMK_ACTION_CANCEL, pcmk__str_none)) {
397 continue;
398 }
399 order_actions(n_data->post_done, mon, pcmk__ar_ordered);
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 pe__action_notif_pseudo_ops(pcmk_resource_t *rsc, const char *task,
436 pcmk_action_t *action, pcmk_action_t *complete)
437 {
438 notify_data_t *n_data = NULL;
439
440 if (!pcmk_is_set(rsc->flags, pcmk_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, PCMK_ACTION_NOTIFY,
453 "pre");
454 pe__set_action_flags(n_data->pre, pcmk_action_runnable);
455 add_hash_param(n_data->pre->meta, "notify_type", "pre");
456 add_hash_param(n_data->pre->meta, "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 pe__set_action_flags(n_data->pre_done, pcmk_action_runnable);
463 add_hash_param(n_data->pre_done->meta, "notify_type", "pre");
464 add_hash_param(n_data->pre_done->meta,
465 "notify_operation", n_data->action);
466
467
468 order_actions(n_data->pre, n_data->pre_done, pcmk__ar_ordered);
469 order_actions(n_data->pre_done, action, pcmk__ar_ordered);
470 }
471
472 if (complete != NULL) {
473
474
475 n_data->post = new_notify_pseudo_action(rsc, complete,
476 PCMK_ACTION_NOTIFY, "post");
477 n_data->post->priority = INFINITY;
478 if (pcmk_is_set(complete->flags, pcmk_action_runnable)) {
479 pe__set_action_flags(n_data->post, pcmk_action_runnable);
480 } else {
481 pe__clear_action_flags(n_data->post, pcmk_action_runnable);
482 }
483 add_hash_param(n_data->post->meta, "notify_type", "post");
484 add_hash_param(n_data->post->meta, "notify_operation", n_data->action);
485
486
487 n_data->post_done = new_notify_pseudo_action(rsc, complete,
488 PCMK_ACTION_NOTIFIED,
489 "confirmed-post");
490 n_data->post_done->priority = INFINITY;
491 if (pcmk_is_set(complete->flags, pcmk_action_runnable)) {
492 pe__set_action_flags(n_data->post_done, pcmk_action_runnable);
493 } else {
494 pe__clear_action_flags(n_data->post_done, pcmk_action_runnable);
495 }
496 add_hash_param(n_data->post_done->meta, "notify_type", "post");
497 add_hash_param(n_data->post_done->meta,
498 "notify_operation", n_data->action);
499
500
501 order_actions(complete, n_data->post, pcmk__ar_first_implies_then);
502 order_actions(n_data->post, n_data->post_done,
503 pcmk__ar_first_implies_then);
504 }
505
506
507 if ((action != NULL) && (complete != NULL)) {
508 order_actions(n_data->pre_done, n_data->post, pcmk__ar_ordered);
509 }
510 return n_data;
511 }
512
513
514
515
516
517
518
519
520
521
522
523 static notify_entry_t *
524 new_notify_entry(const pcmk_resource_t *rsc, const pcmk_node_t *node)
525 {
526 notify_entry_t *entry = calloc(1, sizeof(notify_entry_t));
527
528 CRM_ASSERT(entry != NULL);
529 entry->rsc = rsc;
530 entry->node = node;
531 return entry;
532 }
533
534
535
536
537
538
539
540
541
542 static void
543 collect_resource_data(const pcmk_resource_t *rsc, bool activity,
544 notify_data_t *n_data)
545 {
546 const GList *iter = NULL;
547 notify_entry_t *entry = NULL;
548 const pcmk_node_t *node = NULL;
549
550 if (n_data == NULL) {
551 return;
552 }
553
554 if (n_data->allowed_nodes == NULL) {
555 n_data->allowed_nodes = rsc->allowed_nodes;
556 }
557
558
559 if (rsc->children != NULL) {
560 for (iter = rsc->children; iter != NULL; iter = iter->next) {
561 const pcmk_resource_t *child = (const pcmk_resource_t *) iter->data;
562
563 collect_resource_data(child, activity, n_data);
564 }
565 return;
566 }
567
568
569
570 if (rsc->running_on != NULL) {
571 node = rsc->running_on->data;
572 }
573 entry = new_notify_entry(rsc, node);
574
575
576 switch (rsc->role) {
577 case pcmk_role_stopped:
578 n_data->inactive = g_list_prepend(n_data->inactive, entry);
579 break;
580
581 case pcmk_role_started:
582 n_data->active = g_list_prepend(n_data->active, entry);
583 break;
584
585 case pcmk_role_unpromoted:
586 n_data->unpromoted = g_list_prepend(n_data->unpromoted, entry);
587 n_data->active = g_list_prepend(n_data->active,
588 dup_notify_entry(entry));
589 break;
590
591 case pcmk_role_promoted:
592 n_data->promoted = g_list_prepend(n_data->promoted, entry);
593 n_data->active = g_list_prepend(n_data->active,
594 dup_notify_entry(entry));
595 break;
596
597 default:
598 crm_err("Resource %s role on %s (%s) is not supported for "
599 "notifications (bug?)",
600 rsc->id, pe__node_name(node), role2text(rsc->role));
601 free(entry);
602 break;
603 }
604
605 if (!activity) {
606 return;
607 }
608
609
610 for (iter = rsc->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 action_tasks task = text2task(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->meta, XML_RSC_ATTR_TARGET);
757 if (pcmk__str_eq("host", source, pcmk__str_none)) {
758 get_node_names(rsc->cluster->nodes, &node_list, &metal_list);
759 add_notify_env_free_gs(n_data, "notify_all_hosts", metal_list);
760 } else {
761 get_node_names(rsc->cluster->nodes, &node_list, NULL);
762 }
763 add_notify_env_free_gs(n_data, "notify_all_uname", node_list);
764
765 if (required && (n_data->pre != NULL)) {
766 pe__clear_action_flags(n_data->pre, pcmk_action_optional);
767 pe__clear_action_flags(n_data->pre_done, pcmk_action_optional);
768 }
769
770 if (required && (n_data->post != NULL)) {
771 pe__clear_action_flags(n_data->post, pcmk_action_optional);
772 pe__clear_action_flags(n_data->post_done, pcmk_action_optional);
773 }
774 }
775
776
777
778
779
780
781
782
783
784 static pcmk_action_t *
785 find_remote_start(pcmk_action_t *action)
786 {
787 if ((action != NULL) && (action->node != NULL)) {
788 pcmk_resource_t *remote_rsc = action->node->details->remote_rsc;
789
790 if (remote_rsc != NULL) {
791 return find_first_action(remote_rsc->actions, NULL,
792 PCMK_ACTION_START,
793 NULL);
794 }
795 }
796 return NULL;
797 }
798
799
800
801
802
803
804
805
806 static void
807 create_notify_actions(pcmk_resource_t *rsc, notify_data_t *n_data)
808 {
809 GList *iter = NULL;
810 pcmk_action_t *stop = NULL;
811 pcmk_action_t *start = NULL;
812 enum action_tasks task = text2task(n_data->action);
813
814
815 if (rsc->children != NULL) {
816 g_list_foreach(rsc->children, (GFunc) create_notify_actions, n_data);
817 return;
818 }
819
820
821 for (iter = rsc->actions; iter != NULL; iter = iter->next) {
822 pcmk_action_t *op = (pcmk_action_t *) iter->data;
823
824 if (!pcmk_is_set(op->flags, pcmk_action_optional)
825 && (op->node != NULL)) {
826 switch (text2task(op->task)) {
827 case pcmk_action_start:
828 case pcmk_action_stop:
829 case pcmk_action_promote:
830 case pcmk_action_demote:
831 add_notify_data_to_action_meta(n_data, op);
832 break;
833 default:
834 break;
835 }
836 }
837 }
838
839
840 switch (task) {
841 case pcmk_action_start:
842 if (n_data->start == NULL) {
843 pe_rsc_trace(rsc, "No notify action needed for %s %s",
844 rsc->id, n_data->action);
845 return;
846 }
847 break;
848
849 case pcmk_action_promote:
850 if (n_data->promote == NULL) {
851 pe_rsc_trace(rsc, "No notify action needed for %s %s",
852 rsc->id, n_data->action);
853 return;
854 }
855 break;
856
857 case pcmk_action_demote:
858 if (n_data->demote == NULL) {
859 pe_rsc_trace(rsc, "No notify action needed for %s %s",
860 rsc->id, n_data->action);
861 return;
862 }
863 break;
864
865 default:
866
867 break;
868 }
869
870 pe_rsc_trace(rsc, "Creating notify actions for %s %s",
871 rsc->id, n_data->action);
872
873
874 if ((rsc->role != pcmk_role_stopped)
875 && ((task == pcmk_action_stop) || (task == pcmk_action_demote))) {
876
877 stop = find_first_action(rsc->actions, NULL, PCMK_ACTION_STOP, NULL);
878
879 for (iter = rsc->running_on; iter != NULL; iter = iter->next) {
880 pcmk_node_t *current_node = (pcmk_node_t *) iter->data;
881
882
883
884
885 if ((stop != NULL)
886 && pcmk_is_set(stop->flags, pcmk_action_pseudo)
887 && (current_node->details->unclean
888 || current_node->details->remote_requires_reset)) {
889 continue;
890 }
891
892 new_notify_action(rsc, current_node, n_data->pre,
893 n_data->pre_done, n_data);
894
895 if ((task == pcmk_action_demote) || (stop == NULL)
896 || pcmk_is_set(stop->flags, pcmk_action_optional)) {
897 new_post_notify_action(rsc, current_node, n_data);
898 }
899 }
900 }
901
902
903 if ((rsc->next_role != pcmk_role_stopped)
904 && ((task == pcmk_action_start) || (task == pcmk_action_promote))) {
905
906 start = find_first_action(rsc->actions, NULL, PCMK_ACTION_START, NULL);
907 if (start != NULL) {
908 pcmk_action_t *remote_start = find_remote_start(start);
909
910 if ((remote_start != NULL)
911 && !pcmk_is_set(remote_start->flags, pcmk_action_runnable)) {
912
913
914
915
916
917 return;
918 }
919 }
920 if (rsc->allocated_to == NULL) {
921 pe_proc_err("Next role '%s' but %s is not allocated",
922 role2text(rsc->next_role), rsc->id);
923 return;
924 }
925 if ((task != pcmk_action_start) || (start == NULL)
926 || pcmk_is_set(start->flags, pcmk_action_optional)) {
927
928 new_notify_action(rsc, rsc->allocated_to, n_data->pre,
929 n_data->pre_done, n_data);
930 }
931 new_post_notify_action(rsc, rsc->allocated_to, n_data);
932 }
933 }
934
935
936
937
938
939
940
941
942 void
943 pe__create_action_notifications(pcmk_resource_t *rsc, notify_data_t *n_data)
944 {
945 if ((rsc == NULL) || (n_data == NULL)) {
946 return;
947 }
948 collect_resource_data(rsc, true, n_data);
949 add_notif_keys(rsc, n_data);
950 create_notify_actions(rsc, n_data);
951 }
952
953
954
955
956
957
958
959 void
960 pe__free_action_notification_data(notify_data_t *n_data)
961 {
962 if (n_data == NULL) {
963 return;
964 }
965 g_list_free_full(n_data->stop, free);
966 g_list_free_full(n_data->start, free);
967 g_list_free_full(n_data->demote, free);
968 g_list_free_full(n_data->promote, free);
969 g_list_free_full(n_data->promoted, free);
970 g_list_free_full(n_data->unpromoted, free);
971 g_list_free_full(n_data->active, free);
972 g_list_free_full(n_data->inactive, free);
973 pcmk_free_nvpairs(n_data->keys);
974 free(n_data);
975 }
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991 void
992 pe__order_notifs_after_fencing(const pcmk_action_t *stop, pcmk_resource_t *rsc,
993 pcmk_action_t *stonith_op)
994 {
995 notify_data_t *n_data;
996
997 crm_info("Ordering notifications for implied %s after fencing", stop->uuid);
998 n_data = pe__action_notif_pseudo_ops(rsc, PCMK_ACTION_STOP, NULL,
999 stonith_op);
1000
1001 if (n_data != NULL) {
1002 collect_resource_data(rsc, false, n_data);
1003 add_notify_env(n_data, "notify_stop_resource", rsc->id);
1004 add_notify_env(n_data, "notify_stop_uname", stop->node->details->uname);
1005 create_notify_actions(uber_parent(rsc), n_data);
1006 pe__free_action_notification_data(n_data);
1007 }
1008 }