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
320 update_action_flags(n_data->pre, pe_action_pseudo, __func__, __LINE__);
321 update_action_flags(n_data->pre, pe_action_runnable, __func__,
322 __LINE__);
323
324 add_hash_param(n_data->pre->meta, "notify_type", "pre");
325 add_hash_param(n_data->pre->meta, "notify_operation", n_data->action);
326
327 add_hash_param(n_data->pre->meta, "notify_key_type", "pre");
328 add_hash_param(n_data->pre->meta, "notify_key_operation", start->task);
329
330
331 key = pcmk__notify_key(rsc->id, "confirmed-pre", start->task);
332 n_data->pre_done = custom_action(rsc, key, RSC_NOTIFIED, NULL,
333 pcmk_is_set(start->flags, pe_action_optional),
334 TRUE, data_set);
335
336 update_action_flags(n_data->pre_done, pe_action_pseudo, __func__,
337 __LINE__);
338 update_action_flags(n_data->pre_done, pe_action_runnable, __func__,
339 __LINE__);
340
341 add_hash_param(n_data->pre_done->meta, "notify_type", "pre");
342 add_hash_param(n_data->pre_done->meta, "notify_operation", n_data->action);
343
344 add_hash_param(n_data->pre_done->meta, "notify_key_type", "confirmed-pre");
345 add_hash_param(n_data->pre_done->meta, "notify_key_operation", start->task);
346
347 order_actions(n_data->pre_done, start, pe_order_optional);
348 order_actions(n_data->pre, n_data->pre_done, pe_order_optional);
349 }
350
351 if (end) {
352
353 key = pcmk__notify_key(rsc->id, "post", end->task);
354 n_data->post = custom_action(rsc, key, RSC_NOTIFY, NULL,
355 pcmk_is_set(end->flags, pe_action_optional),
356 TRUE, data_set);
357
358 n_data->post->priority = INFINITY;
359 update_action_flags(n_data->post, pe_action_pseudo, __func__,
360 __LINE__);
361 if (pcmk_is_set(end->flags, pe_action_runnable)) {
362 update_action_flags(n_data->post, pe_action_runnable, __func__,
363 __LINE__);
364 } else {
365 update_action_flags(n_data->post, pe_action_runnable | pe_action_clear,
366 __func__, __LINE__);
367 }
368
369 add_hash_param(n_data->post->meta, "notify_type", "post");
370 add_hash_param(n_data->post->meta, "notify_operation", n_data->action);
371
372 add_hash_param(n_data->post->meta, "notify_key_type", "post");
373 add_hash_param(n_data->post->meta, "notify_key_operation", end->task);
374
375
376 key = pcmk__notify_key(rsc->id, "confirmed-post", end->task);
377 n_data->post_done = custom_action(rsc, key, RSC_NOTIFIED, NULL,
378 pcmk_is_set(end->flags, pe_action_optional),
379 TRUE, data_set);
380
381 n_data->post_done->priority = INFINITY;
382 update_action_flags(n_data->post_done, pe_action_pseudo, __func__,
383 __LINE__);
384 if (pcmk_is_set(end->flags, pe_action_runnable)) {
385 update_action_flags(n_data->post_done, pe_action_runnable,
386 __func__, __LINE__);
387 } else {
388 update_action_flags(n_data->post_done, pe_action_runnable | pe_action_clear,
389 __func__, __LINE__);
390 }
391
392 add_hash_param(n_data->post_done->meta, "notify_type", "post");
393 add_hash_param(n_data->post_done->meta, "notify_operation", n_data->action);
394
395 add_hash_param(n_data->post_done->meta, "notify_key_type", "confirmed-post");
396 add_hash_param(n_data->post_done->meta, "notify_key_operation", end->task);
397
398 order_actions(end, n_data->post, pe_order_implies_then);
399 order_actions(n_data->post, n_data->post_done, pe_order_implies_then);
400 }
401
402 if (start && end) {
403 order_actions(n_data->pre_done, n_data->post, pe_order_optional);
404 }
405 return n_data;
406 }
407
408 void
409 collect_notification_data(pe_resource_t * rsc, gboolean state, gboolean activity,
410 notify_data_t * n_data)
411 {
412
413 if(n_data->allowed_nodes == NULL) {
414 n_data->allowed_nodes = rsc->allowed_nodes;
415 }
416
417 if (rsc->children) {
418 GList *gIter = rsc->children;
419
420 for (; gIter != NULL; gIter = gIter->next) {
421 pe_resource_t *child = (pe_resource_t *) gIter->data;
422
423 collect_notification_data(child, state, activity, n_data);
424 }
425 return;
426 }
427
428 if (state) {
429 notify_entry_t *entry = NULL;
430
431 entry = calloc(1, sizeof(notify_entry_t));
432 entry->rsc = rsc;
433 if (rsc->running_on) {
434
435 entry->node = rsc->running_on->data;
436 }
437
438 pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(rsc->role));
439
440 switch (rsc->role) {
441 case RSC_ROLE_STOPPED:
442 n_data->inactive = g_list_prepend(n_data->inactive, entry);
443 break;
444 case RSC_ROLE_STARTED:
445 n_data->active = g_list_prepend(n_data->active, entry);
446 break;
447 case RSC_ROLE_UNPROMOTED:
448 n_data->unpromoted = g_list_prepend(n_data->unpromoted, entry);
449 n_data->active = g_list_prepend(n_data->active,
450 dup_notify_entry(entry));
451 break;
452 case RSC_ROLE_PROMOTED:
453 n_data->promoted = g_list_prepend(n_data->promoted, entry);
454 n_data->active = g_list_prepend(n_data->active,
455 dup_notify_entry(entry));
456 break;
457 default:
458 crm_err("Unsupported notify role");
459 free(entry);
460 break;
461 }
462 }
463
464 if (activity) {
465 notify_entry_t *entry = NULL;
466 enum action_tasks task;
467
468 GList *gIter = rsc->actions;
469
470 for (; gIter != NULL; gIter = gIter->next) {
471 pe_action_t *op = (pe_action_t *) gIter->data;
472
473 if (!pcmk_is_set(op->flags, pe_action_optional)
474 && (op->node != NULL)) {
475
476 task = text2task(op->task);
477
478 if(task == stop_rsc && op->node->details->unclean) {
479
480 } else if (!pcmk_is_set(op->flags, pe_action_runnable)) {
481 continue;
482 }
483
484 entry = calloc(1, sizeof(notify_entry_t));
485 entry->node = op->node;
486 entry->rsc = rsc;
487
488 switch (task) {
489 case start_rsc:
490 n_data->start = g_list_prepend(n_data->start, entry);
491 break;
492 case stop_rsc:
493 n_data->stop = g_list_prepend(n_data->stop, entry);
494 break;
495 case action_promote:
496 n_data->promote = g_list_prepend(n_data->promote, entry);
497 break;
498 case action_demote:
499 n_data->demote = g_list_prepend(n_data->demote, entry);
500 break;
501 default:
502 free(entry);
503 break;
504 }
505 }
506 }
507 }
508 }
509
510 #define add_notify_env(n_data, key, value) do { \
511 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, value); \
512 } while (0)
513
514 #define add_notify_env_free(n_data, key, value) do { \
515 n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, value); \
516 free(value); value = NULL; \
517 } while (0)
518
519
520
521
522
523
524
525
526
527 void
528 pcmk__create_notification_keys(pe_resource_t *rsc,
529 notify_data_t *n_data,
530 pe_working_set_t *data_set)
531 {
532 bool required = false;
533 char *rsc_list = NULL;
534 char *node_list = NULL;
535 char *metal_list = NULL;
536 const char *source = NULL;
537 GList *nodes = NULL;
538
539 n_data->stop = expand_list(n_data->stop, &rsc_list, &node_list);
540 if (!pcmk__str_eq(" ", rsc_list, pcmk__str_null_matches)
541 && pcmk__str_eq(n_data->action, RSC_STOP, pcmk__str_casei)) {
542 required = true;
543 }
544 add_notify_env_free(n_data, "notify_stop_resource", rsc_list);
545 add_notify_env_free(n_data, "notify_stop_uname", node_list);
546
547 if ((n_data->start != NULL)
548 && pcmk__str_eq(n_data->action, RSC_START, pcmk__str_casei)) {
549 required = true;
550 }
551 n_data->start = expand_list(n_data->start, &rsc_list, &node_list);
552 add_notify_env_free(n_data, "notify_start_resource", rsc_list);
553 add_notify_env_free(n_data, "notify_start_uname", node_list);
554
555 if ((n_data->demote != NULL)
556 && pcmk__str_eq(n_data->action, RSC_DEMOTE, pcmk__str_casei)) {
557 required = true;
558 }
559 n_data->demote = expand_list(n_data->demote, &rsc_list, &node_list);
560 add_notify_env_free(n_data, "notify_demote_resource", rsc_list);
561 add_notify_env_free(n_data, "notify_demote_uname", node_list);
562
563 if ((n_data->promote != NULL)
564 && pcmk__str_eq(n_data->action, RSC_PROMOTE, pcmk__str_casei)) {
565 required = true;
566 }
567 n_data->promote = expand_list(n_data->promote, &rsc_list, &node_list);
568 add_notify_env_free(n_data, "notify_promote_resource", rsc_list);
569 add_notify_env_free(n_data, "notify_promote_uname", node_list);
570
571 n_data->active = expand_list(n_data->active, &rsc_list, &node_list);
572 add_notify_env_free(n_data, "notify_active_resource", rsc_list);
573 add_notify_env_free(n_data, "notify_active_uname", node_list);
574
575 n_data->unpromoted = expand_list(n_data->unpromoted, &rsc_list, &node_list);
576 add_notify_env(n_data, "notify_unpromoted_resource", rsc_list);
577 add_notify_env(n_data, "notify_unpromoted_uname", node_list);
578
579
580 add_notify_env_free(n_data, "notify_slave_resource", rsc_list);
581 add_notify_env_free(n_data, "notify_slave_uname", node_list);
582
583 n_data->promoted = expand_list(n_data->promoted, &rsc_list, &node_list);
584 add_notify_env(n_data, "notify_promoted_resource", rsc_list);
585 add_notify_env(n_data, "notify_promoted_uname", node_list);
586
587
588 add_notify_env_free(n_data, "notify_master_resource", rsc_list);
589 add_notify_env_free(n_data, "notify_master_uname", node_list);
590
591 n_data->inactive = expand_list(n_data->inactive, &rsc_list, NULL);
592 add_notify_env_free(n_data, "notify_inactive_resource", rsc_list);
593
594 nodes = g_hash_table_get_values(n_data->allowed_nodes);
595 if (!pcmk__is_daemon) {
596
597
598
599
600 nodes = g_list_sort(nodes, sort_node_uname);
601 }
602 expand_node_list(nodes, &node_list, NULL);
603 add_notify_env_free(n_data, "notify_available_uname", node_list);
604 g_list_free(nodes);
605
606 source = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET);
607 if (pcmk__str_eq("host", source, pcmk__str_casei)) {
608 expand_node_list(data_set->nodes, &node_list, &metal_list);
609 add_notify_env_free(n_data, "notify_all_hosts", metal_list);
610 } else {
611 expand_node_list(data_set->nodes, &node_list, NULL);
612 }
613 add_notify_env_free(n_data, "notify_all_uname", node_list);
614
615 if (required && n_data->pre) {
616 update_action_flags(n_data->pre, pe_action_optional | pe_action_clear,
617 __func__, __LINE__);
618 update_action_flags(n_data->pre_done, pe_action_optional | pe_action_clear,
619 __func__, __LINE__);
620 }
621
622 if (required && n_data->post) {
623 update_action_flags(n_data->post, pe_action_optional | pe_action_clear,
624 __func__, __LINE__);
625 update_action_flags(n_data->post_done, pe_action_optional | pe_action_clear,
626 __func__, __LINE__);
627 }
628 }
629
630
631
632
633
634
635
636
637
638 static pe_action_t *
639 find_remote_start(pe_action_t *action)
640 {
641 if (action && action->node) {
642 pe_resource_t *remote_rsc = action->node->details->remote_rsc;
643
644 if (remote_rsc) {
645 return find_first_action(remote_rsc->actions, NULL, RSC_START,
646 NULL);
647 }
648 }
649 return NULL;
650 }
651
652 void
653 create_notifications(pe_resource_t * rsc, notify_data_t * n_data, pe_working_set_t * data_set)
654 {
655 GList *gIter = NULL;
656 pe_action_t *stop = NULL;
657 pe_action_t *start = NULL;
658 enum action_tasks task = text2task(n_data->action);
659
660 if (rsc->children) {
661 gIter = rsc->children;
662 for (; gIter != NULL; gIter = gIter->next) {
663 pe_resource_t *child = (pe_resource_t *) gIter->data;
664
665 create_notifications(child, n_data, data_set);
666 }
667 return;
668 }
669
670
671
672 for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
673 pe_action_t *op = (pe_action_t *) gIter->data;
674
675 if (!pcmk_is_set(op->flags, pe_action_optional)
676 && (op->node != NULL)) {
677
678 enum action_tasks t = text2task(op->task);
679
680 switch (t) {
681 case start_rsc:
682 case stop_rsc:
683 case action_promote:
684 case action_demote:
685 add_notify_data_to_action_meta(n_data, op);
686 break;
687 default:
688 break;
689 }
690 }
691 }
692
693 switch (task) {
694 case start_rsc:
695 if (n_data->start == NULL) {
696 pe_rsc_trace(rsc, "Skipping empty notification for: %s.%s (%s->%s)",
697 n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
698 return;
699 }
700 break;
701 case action_promote:
702 if (n_data->promote == NULL) {
703 pe_rsc_trace(rsc, "Skipping empty notification for: %s.%s (%s->%s)",
704 n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
705 return;
706 }
707 break;
708 case action_demote:
709 if (n_data->demote == NULL) {
710 pe_rsc_trace(rsc, "Skipping empty notification for: %s.%s (%s->%s)",
711 n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
712 return;
713 }
714 break;
715 default:
716
717
718
719 break;
720 }
721
722 pe_rsc_trace(rsc, "Creating notifications for: %s.%s (%s->%s)",
723 n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
724
725 stop = find_first_action(rsc->actions, NULL, RSC_STOP, NULL);
726 start = find_first_action(rsc->actions, NULL, RSC_START, NULL);
727
728
729 if (rsc->role != RSC_ROLE_STOPPED) {
730 if (task == stop_rsc || task == action_demote) {
731 gIter = rsc->running_on;
732 for (; gIter != NULL; gIter = gIter->next) {
733 pe_node_t *current_node = (pe_node_t *) gIter->data;
734
735
736
737
738 if (stop && pcmk_is_set(stop->flags, pe_action_pseudo) &&
739 (current_node->details->unclean || current_node->details->remote_requires_reset) ) {
740
741 continue;
742 }
743
744 pe_notify(rsc, current_node, n_data->pre, n_data->pre_done, n_data, data_set);
745 if (task == action_demote || stop == NULL
746 || pcmk_is_set(stop->flags, pe_action_optional)) {
747 pe_post_notify(rsc, current_node, n_data, data_set);
748 }
749 }
750 }
751 }
752
753
754 if (rsc->next_role != RSC_ROLE_STOPPED) {
755 if (rsc->allocated_to == NULL) {
756 pe_proc_err("Next role '%s' but %s is not allocated", role2text(rsc->next_role),
757 rsc->id);
758
759 } else if (task == start_rsc || task == action_promote) {
760
761 if (start) {
762 pe_action_t *remote_start = find_remote_start(start);
763
764 if (remote_start
765 && !pcmk_is_set(remote_start->flags, pe_action_runnable)) {
766
767
768
769
770
771 return;
772 }
773 }
774 if ((task != start_rsc) || (start == NULL)
775 || pcmk_is_set(start->flags, pe_action_optional)) {
776
777 pe_notify(rsc, rsc->allocated_to, n_data->pre, n_data->pre_done, n_data, data_set);
778 }
779 pe_post_notify(rsc, rsc->allocated_to, n_data, data_set);
780 }
781 }
782 }
783
784 void
785 free_notification_data(notify_data_t * n_data)
786 {
787 if (n_data == NULL) {
788 return;
789 }
790
791 g_list_free_full(n_data->stop, free);
792 g_list_free_full(n_data->start, free);
793 g_list_free_full(n_data->demote, free);
794 g_list_free_full(n_data->promote, free);
795 g_list_free_full(n_data->promoted, free);
796 g_list_free_full(n_data->unpromoted, free);
797 g_list_free_full(n_data->active, free);
798 g_list_free_full(n_data->inactive, free);
799 pcmk_free_nvpairs(n_data->keys);
800 free(n_data);
801 }
802
803 void
804 create_secondary_notification(pe_action_t *action, pe_resource_t *rsc,
805 pe_action_t *stonith_op,
806 pe_working_set_t *data_set)
807 {
808 notify_data_t *n_data;
809
810 crm_info("Creating secondary notification for %s", action->uuid);
811 n_data = create_notification_boundaries(rsc, RSC_STOP, NULL, stonith_op,
812 data_set);
813 collect_notification_data(rsc, TRUE, FALSE, n_data);
814 add_notify_env(n_data, "notify_stop_resource", rsc->id);
815 add_notify_env(n_data, "notify_stop_uname", action->node->details->uname);
816 create_notifications(uber_parent(rsc), n_data, data_set);
817 free_notification_data(n_data);
818 }