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