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