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->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 = 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->details->uname == NULL) {
133 continue;
134 }
135
136
137 if (all_node_names != NULL) {
138 pcmk__add_word(all_node_names, 1024, node->details->uname);
139 }
140
141
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176 static GList *
177 notify_entries_to_strings(GList *list, GString **rsc_names,
178 GString **node_names)
179 {
180 const char *last_rsc_id = NULL;
181
182
183 if (rsc_names != NULL) {
184 *rsc_names = NULL;
185 }
186 if (node_names != NULL) {
187 *node_names = NULL;
188 }
189
190
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
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
205 CRM_LOG_ASSERT((node_names == NULL) || (entry->node != NULL));
206 if ((node_names != NULL) && (entry->node == NULL)) {
207 continue;
208 }
209
210
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
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
235
236
237
238
239
240
241
242
243 static void
244 copy_meta_to_notify(gpointer key, gpointer value, gpointer user_data)
245 {
246 pcmk_action_t *notify = (pcmk_action_t *) user_data;
247
248
249
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
258 static void
259 add_notify_data_to_action_meta(const notify_data_t *n_data,
260 pcmk_action_t *action)
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
269
270
271
272
273
274
275
276
277
278
279
280 static pcmk_action_t *
281 new_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,
289 pcmk_is_set(action->flags, pcmk_action_optional),
290 rsc->cluster);
291 pcmk__set_action_flags(notify, pcmk_action_pseudo);
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
297
298
299
300
301
302
303
304
305
306
307
308
309 static pcmk_action_t *
310 new_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
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");
339 task = g_hash_table_lookup(op->meta, "notify_operation");
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
345 key = pcmk__notify_key(rsc->id, value, task);
346 notify_action = custom_action(rsc, key, op->task, node,
347 pcmk_is_set(op->flags, pcmk_action_optional),
348 rsc->cluster);
349
350
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
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
360
361
362
363
364
365
366
367
368 static void
369 new_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 pcmk__assert(n_data != NULL);
375
376
377 notify = new_notify_action(rsc, node, n_data->post, n_data->post_done,
378 n_data);
379 if (notify != NULL) {
380 notify->priority = PCMK_SCORE_INFINITY;
381 }
382
383
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;
395 }
396 order_actions(n_data->post_done, mon, pcmk__ar_ordered);
397 }
398 }
399
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 notify_data_t *
432 pe__action_notif_pseudo_ops(pcmk_resource_t *rsc, const char *task,
433 pcmk_action_t *action, pcmk_action_t *complete)
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) {
446
447
448 n_data->pre = new_notify_pseudo_action(rsc, action, PCMK_ACTION_NOTIFY,
449 "pre");
450 pcmk__set_action_flags(n_data->pre, pcmk_action_runnable);
451 pcmk__insert_meta(n_data->pre, "notify_type", "pre");
452 pcmk__insert_meta(n_data->pre, "notify_operation", n_data->action);
453
454
455 n_data->pre_done = new_notify_pseudo_action(rsc, action,
456 PCMK_ACTION_NOTIFIED,
457 "confirmed-pre");
458 pcmk__set_action_flags(n_data->pre_done, pcmk_action_runnable);
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
463 order_actions(n_data->pre, n_data->pre_done, pcmk__ar_ordered);
464 order_actions(n_data->pre_done, action, pcmk__ar_ordered);
465 }
466
467 if (complete != NULL) {
468
469
470 n_data->post = new_notify_pseudo_action(rsc, complete,
471 PCMK_ACTION_NOTIFY, "post");
472 n_data->post->priority = PCMK_SCORE_INFINITY;
473 if (pcmk_is_set(complete->flags, pcmk_action_runnable)) {
474 pcmk__set_action_flags(n_data->post, pcmk_action_runnable);
475 } else {
476 pcmk__clear_action_flags(n_data->post, pcmk_action_runnable);
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
482 n_data->post_done = new_notify_pseudo_action(rsc, complete,
483 PCMK_ACTION_NOTIFIED,
484 "confirmed-post");
485 n_data->post_done->priority = PCMK_SCORE_INFINITY;
486 if (pcmk_is_set(complete->flags, pcmk_action_runnable)) {
487 pcmk__set_action_flags(n_data->post_done, pcmk_action_runnable);
488 } else {
489 pcmk__clear_action_flags(n_data->post_done, pcmk_action_runnable);
490 }
491 pcmk__insert_meta(n_data->post_done, "notify_type", "post");
492 pcmk__insert_meta(n_data->post_done,
493 "notify_operation", n_data->action);
494
495
496 order_actions(complete, n_data->post, pcmk__ar_first_implies_then);
497 order_actions(n_data->post, n_data->post_done,
498 pcmk__ar_first_implies_then);
499 }
500
501
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
508
509
510
511
512
513
514
515
516
517
518 static notify_entry_t *
519 new_notify_entry(const pcmk_resource_t *rsc, const pcmk_node_t *node)
520 {
521 notify_entry_t *entry = pcmk__assert_alloc(1, sizeof(notify_entry_t));
522
523 entry->rsc = rsc;
524 entry->node = node;
525 return entry;
526 }
527
528
529
530
531
532
533
534
535
536 static void
537 collect_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
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
563
564 if (rsc->running_on != NULL) {
565 node = rsc->running_on->data;
566 }
567 entry = new_notify_entry(rsc, node);
568
569
570 switch (rsc->role) {
571 case pcmk_role_stopped:
572 n_data->inactive = g_list_prepend(n_data->inactive, entry);
573 break;
574
575 case pcmk_role_started:
576 n_data->active = g_list_prepend(n_data->active, entry);
577 break;
578
579 case pcmk_role_unpromoted:
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
585 case pcmk_role_promoted:
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
605 for (iter = rsc->actions; iter != NULL; iter = iter->next) {
606 const pcmk_action_t *op = (const pcmk_action_t *) iter->data;
607
608 if (!pcmk_is_set(op->flags, pcmk_action_optional)
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
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) {
621 case pcmk_action_start:
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;
627 case pcmk_action_promote:
628 n_data->promote = g_list_prepend(n_data->promote, entry);
629 break;
630 case pcmk_action_demote:
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
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
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
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
659
660
661
662
663
664
665
666 static void
667 add_notif_keys(const pcmk_resource_t *rsc, notify_data_t *n_data)
668 {
669 bool required = false;
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
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
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
742
743
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,
752 PCMK_META_CONTAINER_ATTRIBUTE_TARGET);
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)) {
762 pcmk__clear_action_flags(n_data->pre, pcmk_action_optional);
763 pcmk__clear_action_flags(n_data->pre_done, pcmk_action_optional);
764 }
765
766 if (required && (n_data->post != NULL)) {
767 pcmk__clear_action_flags(n_data->post, pcmk_action_optional);
768 pcmk__clear_action_flags(n_data->post_done, pcmk_action_optional);
769 }
770 }
771
772
773
774
775
776
777
778
779
780 static pcmk_action_t *
781 find_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,
788 PCMK_ACTION_START,
789 NULL);
790 }
791 }
792 return NULL;
793 }
794
795
796
797
798
799
800
801
802 static void
803 create_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
811 if (rsc->children != NULL) {
812 g_list_foreach(rsc->children, (GFunc) create_notify_actions, n_data);
813 return;
814 }
815
816
817 for (iter = rsc->actions; iter != NULL; iter = iter->next) {
818 pcmk_action_t *op = (pcmk_action_t *) iter->data;
819
820 if (!pcmk_is_set(op->flags, pcmk_action_optional)
821 && (op->node != NULL)) {
822 switch (pcmk_parse_action(op->task)) {
823 case pcmk_action_start:
824 case pcmk_action_stop:
825 case pcmk_action_promote:
826 case pcmk_action_demote:
827 add_notify_data_to_action_meta(n_data, op);
828 break;
829 default:
830 break;
831 }
832 }
833 }
834
835
836 switch (task) {
837 case pcmk_action_start:
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
845 case pcmk_action_promote:
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
853 case pcmk_action_demote:
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
863 break;
864 }
865
866 pcmk__rsc_trace(rsc, "Creating notify actions for %s %s",
867 rsc->id, n_data->action);
868
869
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
879
880
881 if ((stop != NULL)
882 && pcmk_is_set(stop->flags, pcmk_action_pseudo)
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)
892 || pcmk_is_set(stop->flags, pcmk_action_optional)) {
893 new_post_notify_action(rsc, current_node, n_data);
894 }
895 }
896 }
897
898
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
909
910
911
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)
922 || pcmk_is_set(start->flags, pcmk_action_optional)) {
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
931
932
933
934
935
936
937
938 void
939 pe__create_action_notifications(pcmk_resource_t *rsc, notify_data_t *n_data)
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
949
950
951
952
953
954
955 void
956 pe__free_action_notification_data(notify_data_t *n_data)
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
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987 void
988 pe__order_notifs_after_fencing(const pcmk_action_t *stop, pcmk_resource_t *rsc,
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);
994 n_data = pe__action_notif_pseudo_ops(rsc, PCMK_ACTION_STOP, NULL,
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);
1002 pe__free_action_notification_data(n_data);
1003 }
1004 }