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