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