This source file includes following definitions.
- sort_notify_entries
- dup_notify_entry
- expand_node_list
- expand_list
- dup_attr
- add_notify_data_to_action_meta
- pe_notify
- pe_post_notify
- create_notification_boundaries
- collect_notification_data
- pcmk__create_notification_keys
- find_remote_start
- create_notifications
- free_notification_data
- create_secondary_notification
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 extern bool pcmk__is_daemon;
15
16 typedef struct notify_entry_s {
17 pe_resource_t *rsc;
18 pe_node_t *node;
19 } notify_entry_t;
20
21 static gint
22 sort_notify_entries(gconstpointer a, gconstpointer b)
23 {
24 int tmp;
25 const notify_entry_t *entry_a = a;
26 const notify_entry_t *entry_b = b;
27
28 if (entry_a == NULL && entry_b == NULL) {
29 return 0;
30 }
31 if (entry_a == NULL) {
32 return 1;
33 }
34 if (entry_b == NULL) {
35 return -1;
36 }
37
38 if (entry_a->rsc == NULL && entry_b->rsc == NULL) {
39 return 0;
40 }
41 if (entry_a->rsc == NULL) {
42 return 1;
43 }
44 if (entry_b->rsc == NULL) {
45 return -1;
46 }
47
48 tmp = strcmp(entry_a->rsc->id, entry_b->rsc->id);
49 if (tmp != 0) {
50 return tmp;
51 }
52
53 if (entry_a->node == NULL && entry_b->node == NULL) {
54 return 0;
55 }
56 if (entry_a->node == NULL) {
57 return 1;
58 }
59 if (entry_b->node == NULL) {
60 return -1;
61 }
62
63 return strcmp(entry_a->node->details->id, entry_b->node->details->id);
64 }
65
66 static notify_entry_t *dup_notify_entry(notify_entry_t *entry)
67 {
68 notify_entry_t *dup = malloc(sizeof(notify_entry_t));
69
70 CRM_ASSERT(dup != NULL);
71 dup->rsc = entry->rsc;
72 dup->node = entry->node;
73 return dup;
74 }
75
76 static void
77 expand_node_list(GList *list, char **uname, char **metal)
78 {
79 GList *gIter = NULL;
80 char *node_list = NULL;
81 char *metal_list = NULL;
82 size_t node_list_len = 0;
83 size_t metal_list_len = 0;
84
85 CRM_ASSERT(uname != NULL);
86 if (list == NULL) {
87 *uname = strdup(" ");
88 if(metal) {
89 *metal = strdup(" ");
90 }
91 return;
92 }
93
94 for (gIter = list; gIter != NULL; gIter = gIter->next) {
95 pe_node_t *node = (pe_node_t *) gIter->data;
96
97 if (node->details->uname == NULL) {
98 continue;
99 }
100 pcmk__add_word(&node_list, &node_list_len, node->details->uname);
101 if(metal) {
102 if(node->details->remote_rsc
103 && node->details->remote_rsc->container
104 && node->details->remote_rsc->container->running_on) {
105 node = pe__current_node(node->details->remote_rsc->container);
106 }
107
108 if (node->details->uname == NULL) {
109 continue;
110 }
111 pcmk__add_word(&metal_list, &metal_list_len, node->details->uname);
112 }
113 }
114
115 *uname = node_list;
116 if(metal) {
117 *metal = metal_list;
118 }
119 }
120
121
122
123
124
125
126
127
128
129
130
131 static GList *
132 expand_list(GList *list, char **rsc_list, char **node_list)
133 {
134 const char *last_rsc_id = NULL;
135 size_t rsc_list_len = 0;
136 size_t node_list_len = 0;
137
138 CRM_CHECK(rsc_list != NULL, return list);
139
140
141 if (list == NULL) {
142 *rsc_list = strdup(" ");
143 if (node_list) {
144 *node_list = strdup(" ");
145 }
146 return list;
147 }
148
149
150 *rsc_list = NULL;
151 if (node_list) {
152 *node_list = NULL;
153 }
154
155
156 list = g_list_sort(list, sort_notify_entries);
157
158 for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
159 notify_entry_t *entry = (notify_entry_t *) gIter->data;
160
161
162 CRM_LOG_ASSERT((entry != NULL) && (entry->rsc != NULL)
163 && (entry->rsc->id != NULL));
164 if ((entry == NULL) || (entry->rsc == NULL)
165 || (entry->rsc->id == NULL)) {
166 continue;
167 }
168
169
170 CRM_LOG_ASSERT((node_list == NULL) || (entry->node != NULL));
171 if ((node_list != NULL) && (entry->node == NULL)) {
172 continue;
173 }
174
175
176 if (pcmk__str_eq(entry->rsc->id, last_rsc_id, pcmk__str_none)) {
177 continue;
178 }
179 last_rsc_id = entry->rsc->id;
180 pcmk__add_word(rsc_list, &rsc_list_len, entry->rsc->id);
181 if ((node_list != NULL) && (entry->node->details->uname != NULL)) {
182 pcmk__add_word(node_list, &node_list_len,
183 entry->node->details->uname);
184 }
185 }
186 return list;
187 }
188
189 static void
190 dup_attr(gpointer key, gpointer value, gpointer user_data)
191 {
192 add_hash_param(user_data, key, value);
193 }
194
195 static void
196 add_notify_data_to_action_meta(notify_data_t *n_data, pe_action_t *action)
197 {
198 for (GSList *item = n_data->keys; item; item = item->next) {
199 pcmk_nvpair_t *nvpair = item->data;
200
201 add_hash_param(action->meta, nvpair->name, nvpair->value);
202 }
203 }
204
205 static pe_action_t *
206 pe_notify(pe_resource_t * rsc, pe_node_t * node, pe_action_t * op, pe_action_t * confirm,
207 notify_data_t * n_data, pe_working_set_t * data_set)
208 {
209 char *key = NULL;
210 pe_action_t *trigger = NULL;
211 const char *value = NULL;
212 const char *task = NULL;
213
214 if (op == NULL || confirm == NULL) {
215 pe_rsc_trace(rsc, "Op=%p confirm=%p", op, confirm);
216 return NULL;
217 }
218
219 CRM_CHECK(rsc != NULL, return NULL);
220 CRM_CHECK(node != NULL, return NULL);
221
222 if (node->details->online == FALSE) {
223 pe_rsc_trace(rsc, "Skipping notification for %s: node offline", rsc->id);
224 return NULL;
225 } else if (!pcmk_is_set(op->flags, pe_action_runnable)) {
226 pe_rsc_trace(rsc, "Skipping notification for %s: not runnable", op->uuid);
227 return NULL;
228 }
229
230 value = g_hash_table_lookup(op->meta, "notify_type");
231 task = g_hash_table_lookup(op->meta, "notify_operation");
232
233 pe_rsc_trace(rsc, "Creating notify actions for %s: %s (%s-%s)", op->uuid, rsc->id, value, task);
234
235 key = pcmk__notify_key(rsc->id, value, task);
236 trigger = custom_action(rsc, key, op->task, node,
237 pcmk_is_set(op->flags, pe_action_optional),
238 TRUE, data_set);
239 g_hash_table_foreach(op->meta, dup_attr, trigger->meta);
240 add_notify_data_to_action_meta(n_data, trigger);
241
242
243 pe_rsc_trace(rsc, "Ordering %s before %s (%d->%d)", op->uuid, trigger->uuid, trigger->id,
244 op->id);
245
246 order_actions(op, trigger, pe_order_optional);
247 order_actions(trigger, confirm, pe_order_optional);
248 return trigger;
249 }
250
251 static void
252 pe_post_notify(pe_resource_t * rsc, pe_node_t * node, notify_data_t * n_data, pe_working_set_t * data_set)
253 {
254 pe_action_t *notify = NULL;
255
256 CRM_CHECK(rsc != NULL, return);
257
258 if (n_data->post == NULL) {
259 return;
260 }
261
262 notify = pe_notify(rsc, node, n_data->post, n_data->post_done, n_data, data_set);
263
264 if (notify != NULL) {
265 notify->priority = INFINITY;
266 }
267
268 if (n_data->post_done) {
269 GList *gIter = rsc->actions;
270
271 for (; gIter != NULL; gIter = gIter->next) {
272 pe_action_t *mon = (pe_action_t *) gIter->data;
273 const char *interval_ms_s = g_hash_table_lookup(mon->meta,
274 XML_LRM_ATTR_INTERVAL_MS);
275
276 if (pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches | pcmk__str_casei)) {
277 pe_rsc_trace(rsc, "Skipping %s: interval", mon->uuid);
278 continue;
279 } else if (pcmk__str_eq(mon->task, RSC_CANCEL, pcmk__str_casei)) {
280 pe_rsc_trace(rsc, "Skipping %s: cancel", mon->uuid);
281 continue;
282 }
283
284 order_actions(n_data->post_done, mon, pe_order_optional);
285 }
286 }
287 }
288
289 notify_data_t *
290 create_notification_boundaries(pe_resource_t * rsc, const char *action, pe_action_t * start,
291 pe_action_t * end, pe_working_set_t * data_set)
292 {
293
294
295
296
297
298
299
300
301
302 char *key = NULL;
303 notify_data_t *n_data = NULL;
304
305 if (!pcmk_is_set(rsc->flags, pe_rsc_notify)) {
306 return NULL;
307 }
308
309 n_data = calloc(1, sizeof(notify_data_t));
310 n_data->action = action;
311
312 if (start) {
313
314 key = pcmk__notify_key(rsc->id, "pre", start->task);
315 n_data->pre =
316 custom_action(rsc, key, RSC_NOTIFY, NULL,
317 pcmk_is_set(start->flags, pe_action_optional),
318 TRUE, data_set);
319 pe__set_action_flags(n_data->pre, pe_action_pseudo|pe_action_runnable);
320
321 add_hash_param(n_data->pre->meta, "notify_type", "pre");
322 add_hash_param(n_data->pre->meta, "notify_operation", n_data->action);
323
324 add_hash_param(n_data->pre->meta, "notify_key_type", "pre");
325 add_hash_param(n_data->pre->meta, "notify_key_operation", start->task);
326
327
328 key = pcmk__notify_key(rsc->id, "confirmed-pre", start->task);
329 n_data->pre_done = custom_action(rsc, key, RSC_NOTIFIED, NULL,
330 pcmk_is_set(start->flags, pe_action_optional),
331 TRUE, data_set);
332 pe__set_action_flags(n_data->pre_done,
333 pe_action_pseudo|pe_action_runnable);
334
335 add_hash_param(n_data->pre_done->meta, "notify_type", "pre");
336 add_hash_param(n_data->pre_done->meta, "notify_operation", n_data->action);
337
338 add_hash_param(n_data->pre_done->meta, "notify_key_type", "confirmed-pre");
339 add_hash_param(n_data->pre_done->meta, "notify_key_operation", start->task);
340
341 order_actions(n_data->pre_done, start, pe_order_optional);
342 order_actions(n_data->pre, n_data->pre_done, pe_order_optional);
343 }
344
345 if (end) {
346
347 key = pcmk__notify_key(rsc->id, "post", end->task);
348 n_data->post = custom_action(rsc, key, RSC_NOTIFY, NULL,
349 pcmk_is_set(end->flags, pe_action_optional),
350 TRUE, data_set);
351
352 n_data->post->priority = INFINITY;
353 pe__set_action_flags(n_data->post, pe_action_pseudo);
354 if (pcmk_is_set(end->flags, pe_action_runnable)) {
355 pe__set_action_flags(n_data->post, pe_action_runnable);
356 } else {
357 pe__clear_action_flags(n_data->post, pe_action_runnable);
358 }
359
360 add_hash_param(n_data->post->meta, "notify_type", "post");
361 add_hash_param(n_data->post->meta, "notify_operation", n_data->action);
362
363 add_hash_param(n_data->post->meta, "notify_key_type", "post");
364 add_hash_param(n_data->post->meta, "notify_key_operation", end->task);
365
366
367 key = pcmk__notify_key(rsc->id, "confirmed-post", end->task);
368 n_data->post_done = custom_action(rsc, key, RSC_NOTIFIED, NULL,
369 pcmk_is_set(end->flags, pe_action_optional),
370 TRUE, data_set);
371
372 n_data->post_done->priority = INFINITY;
373 pe__set_action_flags(n_data->post_done, pe_action_pseudo);
374 if (pcmk_is_set(end->flags, pe_action_runnable)) {
375 pe__set_action_flags(n_data->post_done, pe_action_runnable);
376 } else {
377 pe__clear_action_flags(n_data->post_done, pe_action_runnable);
378 }
379
380 add_hash_param(n_data->post_done->meta, "notify_type", "post");
381 add_hash_param(n_data->post_done->meta, "notify_operation", n_data->action);
382
383 add_hash_param(n_data->post_done->meta, "notify_key_type", "confirmed-post");
384 add_hash_param(n_data->post_done->meta, "notify_key_operation", end->task);
385
386 order_actions(end, n_data->post, pe_order_implies_then);
387 order_actions(n_data->post, n_data->post_done, pe_order_implies_then);
388 }
389
390 if (start && end) {
391 order_actions(n_data->pre_done, n_data->post, pe_order_optional);
392 }
393 return n_data;
394 }
395
396 void
397 collect_notification_data(pe_resource_t * rsc, gboolean state, gboolean activity,
398 notify_data_t * n_data)
399 {
400
401 if(n_data->allowed_nodes == NULL) {
402 n_data->allowed_nodes = rsc->allowed_nodes;
403 }
404
405 if (rsc->children) {
406 GList *gIter = rsc->children;
407
408 for (; gIter != NULL; gIter = gIter->next) {
409 pe_resource_t *child = (pe_resource_t *) gIter->data;
410
411 collect_notification_data(child, state, activity, n_data);
412 }
413 return;
414 }
415
416 if (state) {
417 notify_entry_t *entry = NULL;
418
419 entry = calloc(1, sizeof(notify_entry_t));
420 entry->rsc = rsc;
421 if (rsc->running_on) {
422
423 entry->node = rsc->running_on->data;
424 }
425
426 pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(rsc->role));
427
428 switch (rsc->role) {
429 case RSC_ROLE_STOPPED:
430 n_data->inactive = g_list_prepend(n_data->inactive, entry);
431 break;
432 case RSC_ROLE_STARTED:
433 n_data->active = g_list_prepend(n_data->active, entry);
434 break;
435 case RSC_ROLE_UNPROMOTED:
436 n_data->unpromoted = g_list_prepend(n_data->unpromoted, entry);
437 n_data->active = g_list_prepend(n_data->active,
438 dup_notify_entry(entry));
439 break;
440 case RSC_ROLE_PROMOTED:
441 n_data->promoted = g_list_prepend(n_data->promoted, entry);
442 n_data->active = g_list_prepend(n_data->active,
443 dup_notify_entry(entry));
444 break;
445 default:
446 crm_err("Unsupported notify role");
447 free(entry);
448 break;
449 }
450 }
451
452 if (activity) {
453 notify_entry_t *entry = NULL;
454 enum action_tasks task;
455
456 GList *gIter = rsc->actions;
457
458 for (; gIter != NULL; gIter = gIter->next) {
459 pe_action_t *op = (pe_action_t *) gIter->data;
460
461 if (!pcmk_is_set(op->flags, pe_action_optional)
462 && (op->node != NULL)) {
463
464 task = text2task(op->task);
465
466 if(task == stop_rsc && op->node->details->unclean) {
467
468 } else if (!pcmk_is_set(op->flags, pe_action_runnable)) {
469 continue;
470 }
471
472 entry = calloc(1, sizeof(notify_entry_t));
473 entry->node = op->node;
474 entry->rsc = rsc;
475
476 switch (task) {
477 case start_rsc:
478 n_data->start = g_list_prepend(n_data->start, entry);
479 break;
480 case stop_rsc:
481 n_data->stop = g_list_prepend(n_data->stop, entry);
482 break;
483 case action_promote:
484 n_data->promote = g_list_prepend(n_data->promote, entry);
485 break;
486 case action_demote:
487 n_data->demote = g_list_prepend(n_data->demote, entry);
488 break;
489 default:
490 free(entry);
491 break;
492 }
493 }
494 }
495 }
496 }
497
498 #define add_notify_env(n_data, key, value) do { \
499 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, value); \
500 } while (0)
501
502 #define add_notify_env_free(n_data, key, value) do { \
503 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, value); \
504 free(value); value = NULL; \
505 } while (0)
506
507
508
509
510
511
512
513
514
515 void
516 pcmk__create_notification_keys(pe_resource_t *rsc,
517 notify_data_t *n_data,
518 pe_working_set_t *data_set)
519 {
520 bool required = false;
521 char *rsc_list = NULL;
522 char *node_list = NULL;
523 char *metal_list = NULL;
524 const char *source = NULL;
525 GList *nodes = NULL;
526
527 n_data->stop = expand_list(n_data->stop, &rsc_list, &node_list);
528 if (!pcmk__str_eq(" ", rsc_list, pcmk__str_null_matches)
529 && pcmk__str_eq(n_data->action, RSC_STOP, pcmk__str_casei)) {
530 required = true;
531 }
532 add_notify_env_free(n_data, "notify_stop_resource", rsc_list);
533 add_notify_env_free(n_data, "notify_stop_uname", node_list);
534
535 if ((n_data->start != NULL)
536 && pcmk__str_eq(n_data->action, RSC_START, pcmk__str_casei)) {
537 required = true;
538 }
539 n_data->start = expand_list(n_data->start, &rsc_list, &node_list);
540 add_notify_env_free(n_data, "notify_start_resource", rsc_list);
541 add_notify_env_free(n_data, "notify_start_uname", node_list);
542
543 if ((n_data->demote != NULL)
544 && pcmk__str_eq(n_data->action, RSC_DEMOTE, pcmk__str_casei)) {
545 required = true;
546 }
547 n_data->demote = expand_list(n_data->demote, &rsc_list, &node_list);
548 add_notify_env_free(n_data, "notify_demote_resource", rsc_list);
549 add_notify_env_free(n_data, "notify_demote_uname", node_list);
550
551 if ((n_data->promote != NULL)
552 && pcmk__str_eq(n_data->action, RSC_PROMOTE, pcmk__str_casei)) {
553 required = true;
554 }
555 n_data->promote = expand_list(n_data->promote, &rsc_list, &node_list);
556 add_notify_env_free(n_data, "notify_promote_resource", rsc_list);
557 add_notify_env_free(n_data, "notify_promote_uname", node_list);
558
559 n_data->active = expand_list(n_data->active, &rsc_list, &node_list);
560 add_notify_env_free(n_data, "notify_active_resource", rsc_list);
561 add_notify_env_free(n_data, "notify_active_uname", node_list);
562
563 n_data->unpromoted = expand_list(n_data->unpromoted, &rsc_list, &node_list);
564 add_notify_env(n_data, "notify_unpromoted_resource", rsc_list);
565 add_notify_env(n_data, "notify_unpromoted_uname", node_list);
566
567
568 add_notify_env_free(n_data, "notify_slave_resource", rsc_list);
569 add_notify_env_free(n_data, "notify_slave_uname", node_list);
570
571 n_data->promoted = expand_list(n_data->promoted, &rsc_list, &node_list);
572 add_notify_env(n_data, "notify_promoted_resource", rsc_list);
573 add_notify_env(n_data, "notify_promoted_uname", node_list);
574
575
576 add_notify_env_free(n_data, "notify_master_resource", rsc_list);
577 add_notify_env_free(n_data, "notify_master_uname", node_list);
578
579 n_data->inactive = expand_list(n_data->inactive, &rsc_list, NULL);
580 add_notify_env_free(n_data, "notify_inactive_resource", rsc_list);
581
582 nodes = g_hash_table_get_values(n_data->allowed_nodes);
583 if (!pcmk__is_daemon) {
584
585
586
587
588 nodes = g_list_sort(nodes, sort_node_uname);
589 }
590 expand_node_list(nodes, &node_list, NULL);
591 add_notify_env_free(n_data, "notify_available_uname", node_list);
592 g_list_free(nodes);
593
594 source = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET);
595 if (pcmk__str_eq("host", source, pcmk__str_casei)) {
596 expand_node_list(data_set->nodes, &node_list, &metal_list);
597 add_notify_env_free(n_data, "notify_all_hosts", metal_list);
598 } else {
599 expand_node_list(data_set->nodes, &node_list, NULL);
600 }
601 add_notify_env_free(n_data, "notify_all_uname", node_list);
602
603 if (required && n_data->pre) {
604 pe__clear_action_flags(n_data->pre, pe_action_optional);
605 pe__clear_action_flags(n_data->pre_done, pe_action_optional);
606 }
607
608 if (required && n_data->post) {
609 pe__clear_action_flags(n_data->post, pe_action_optional);
610 pe__clear_action_flags(n_data->post_done, pe_action_optional);
611 }
612 }
613
614
615
616
617
618
619
620
621
622 static pe_action_t *
623 find_remote_start(pe_action_t *action)
624 {
625 if (action && action->node) {
626 pe_resource_t *remote_rsc = action->node->details->remote_rsc;
627
628 if (remote_rsc) {
629 return find_first_action(remote_rsc->actions, NULL, RSC_START,
630 NULL);
631 }
632 }
633 return NULL;
634 }
635
636 void
637 create_notifications(pe_resource_t * rsc, notify_data_t * n_data, pe_working_set_t * data_set)
638 {
639 GList *gIter = NULL;
640 pe_action_t *stop = NULL;
641 pe_action_t *start = NULL;
642 enum action_tasks task = text2task(n_data->action);
643
644 if (rsc->children) {
645 gIter = rsc->children;
646 for (; gIter != NULL; gIter = gIter->next) {
647 pe_resource_t *child = (pe_resource_t *) gIter->data;
648
649 create_notifications(child, n_data, data_set);
650 }
651 return;
652 }
653
654
655
656 for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
657 pe_action_t *op = (pe_action_t *) gIter->data;
658
659 if (!pcmk_is_set(op->flags, pe_action_optional)
660 && (op->node != NULL)) {
661
662 enum action_tasks t = text2task(op->task);
663
664 switch (t) {
665 case start_rsc:
666 case stop_rsc:
667 case action_promote:
668 case action_demote:
669 add_notify_data_to_action_meta(n_data, op);
670 break;
671 default:
672 break;
673 }
674 }
675 }
676
677 switch (task) {
678 case start_rsc:
679 if (n_data->start == NULL) {
680 pe_rsc_trace(rsc, "Skipping empty notification for: %s.%s (%s->%s)",
681 n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
682 return;
683 }
684 break;
685 case action_promote:
686 if (n_data->promote == NULL) {
687 pe_rsc_trace(rsc, "Skipping empty notification for: %s.%s (%s->%s)",
688 n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
689 return;
690 }
691 break;
692 case action_demote:
693 if (n_data->demote == NULL) {
694 pe_rsc_trace(rsc, "Skipping empty notification for: %s.%s (%s->%s)",
695 n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
696 return;
697 }
698 break;
699 default:
700
701
702
703 break;
704 }
705
706 pe_rsc_trace(rsc, "Creating notifications for: %s.%s (%s->%s)",
707 n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
708
709 stop = find_first_action(rsc->actions, NULL, RSC_STOP, NULL);
710 start = find_first_action(rsc->actions, NULL, RSC_START, NULL);
711
712
713 if (rsc->role != RSC_ROLE_STOPPED) {
714 if (task == stop_rsc || task == action_demote) {
715 gIter = rsc->running_on;
716 for (; gIter != NULL; gIter = gIter->next) {
717 pe_node_t *current_node = (pe_node_t *) gIter->data;
718
719
720
721
722 if (stop && pcmk_is_set(stop->flags, pe_action_pseudo) &&
723 (current_node->details->unclean || current_node->details->remote_requires_reset) ) {
724
725 continue;
726 }
727
728 pe_notify(rsc, current_node, n_data->pre, n_data->pre_done, n_data, data_set);
729 if (task == action_demote || stop == NULL
730 || pcmk_is_set(stop->flags, pe_action_optional)) {
731 pe_post_notify(rsc, current_node, n_data, data_set);
732 }
733 }
734 }
735 }
736
737
738 if (rsc->next_role != RSC_ROLE_STOPPED) {
739 if (rsc->allocated_to == NULL) {
740 pe_proc_err("Next role '%s' but %s is not allocated", role2text(rsc->next_role),
741 rsc->id);
742
743 } else if (task == start_rsc || task == action_promote) {
744
745 if (start) {
746 pe_action_t *remote_start = find_remote_start(start);
747
748 if (remote_start
749 && !pcmk_is_set(remote_start->flags, pe_action_runnable)) {
750
751
752
753
754
755 return;
756 }
757 }
758 if ((task != start_rsc) || (start == NULL)
759 || pcmk_is_set(start->flags, pe_action_optional)) {
760
761 pe_notify(rsc, rsc->allocated_to, n_data->pre, n_data->pre_done, n_data, data_set);
762 }
763 pe_post_notify(rsc, rsc->allocated_to, n_data, data_set);
764 }
765 }
766 }
767
768 void
769 free_notification_data(notify_data_t * n_data)
770 {
771 if (n_data == NULL) {
772 return;
773 }
774
775 g_list_free_full(n_data->stop, free);
776 g_list_free_full(n_data->start, free);
777 g_list_free_full(n_data->demote, free);
778 g_list_free_full(n_data->promote, free);
779 g_list_free_full(n_data->promoted, free);
780 g_list_free_full(n_data->unpromoted, free);
781 g_list_free_full(n_data->active, free);
782 g_list_free_full(n_data->inactive, free);
783 pcmk_free_nvpairs(n_data->keys);
784 free(n_data);
785 }
786
787 void
788 create_secondary_notification(pe_action_t *action, pe_resource_t *rsc,
789 pe_action_t *stonith_op,
790 pe_working_set_t *data_set)
791 {
792 notify_data_t *n_data;
793
794 crm_info("Creating secondary notification for %s", action->uuid);
795 n_data = create_notification_boundaries(rsc, RSC_STOP, NULL, stonith_op,
796 data_set);
797 collect_notification_data(rsc, TRUE, FALSE, n_data);
798 add_notify_env(n_data, "notify_stop_resource", rsc->id);
799 add_notify_env(n_data, "notify_stop_uname", action->node->details->uname);
800 create_notifications(uber_parent(rsc), n_data, data_set);
801 free_notification_data(n_data);
802 }