Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F1842080
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
28 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/pacemaker/pcmk_sched_notif.c b/lib/pacemaker/pcmk_sched_notif.c
index 588f516d3f..eb582c789d 100644
--- a/lib/pacemaker/pcmk_sched_notif.c
+++ b/lib/pacemaker/pcmk_sched_notif.c
@@ -1,808 +1,808 @@
/*
* Copyright 2004-2020 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU General Public License version 2
* or later (GPLv2+) WITHOUT ANY WARRANTY.
*/
#include <crm_internal.h>
#include <crm/msg_xml.h>
#include <pacemaker-internal.h>
typedef struct notify_entry_s {
pe_resource_t *rsc;
pe_node_t *node;
} notify_entry_t;
static gint
sort_notify_entries(gconstpointer a, gconstpointer b)
{
int tmp;
const notify_entry_t *entry_a = a;
const notify_entry_t *entry_b = b;
if (entry_a == NULL && entry_b == NULL) {
return 0;
}
if (entry_a == NULL) {
return 1;
}
if (entry_b == NULL) {
return -1;
}
if (entry_a->rsc == NULL && entry_b->rsc == NULL) {
return 0;
}
if (entry_a->rsc == NULL) {
return 1;
}
if (entry_b->rsc == NULL) {
return -1;
}
tmp = strcmp(entry_a->rsc->id, entry_b->rsc->id);
if (tmp != 0) {
return tmp;
}
if (entry_a->node == NULL && entry_b->node == NULL) {
return 0;
}
if (entry_a->node == NULL) {
return 1;
}
if (entry_b->node == NULL) {
return -1;
}
return strcmp(entry_a->node->details->id, entry_b->node->details->id);
}
static notify_entry_t *dup_notify_entry(notify_entry_t *entry)
{
notify_entry_t *dup = malloc(sizeof(notify_entry_t));
CRM_ASSERT(dup != NULL);
dup->rsc = entry->rsc;
dup->node = entry->node;
return dup;
}
static void
expand_node_list(GListPtr list, char **uname, char **metal)
{
GListPtr gIter = NULL;
char *node_list = NULL;
char *metal_list = NULL;
size_t node_list_len = 0;
size_t metal_list_len = 0;
CRM_ASSERT(uname != NULL);
if (list == NULL) {
*uname = strdup(" ");
if(metal) {
*metal = strdup(" ");
}
return;
}
for (gIter = list; gIter != NULL; gIter = gIter->next) {
pe_node_t *node = (pe_node_t *) gIter->data;
if (node->details->uname == NULL) {
continue;
}
pcmk__add_word(&node_list, &node_list_len, node->details->uname);
if(metal) {
if(node->details->remote_rsc
&& node->details->remote_rsc->container
&& node->details->remote_rsc->container->running_on) {
node = pe__current_node(node->details->remote_rsc->container);
}
if (node->details->uname == NULL) {
continue;
}
pcmk__add_word(&metal_list, &metal_list_len, node->details->uname);
}
}
*uname = node_list;
if(metal) {
*metal = metal_list;
}
}
/*!
* \internal
* \brief Separate a list of notification entries into resource and node strings
*
* \param[in,out] list List of notify_entry_t* (will be sorted here)
* \param[out] rsc_list String list of clone instances from \p list
* \param[out] node_list String list of nodes from \p list
*
* \return (Possibly new head of) sorted \p list
*/
static GList *
expand_list(GList *list, char **rsc_list, char **node_list)
{
const char *last_rsc_id = NULL;
size_t rsc_list_len = 0;
size_t node_list_len = 0;
CRM_CHECK(rsc_list != NULL, return list);
// If there are no entries, return "empty" lists
if (list == NULL) {
*rsc_list = strdup(" ");
if (node_list) {
*node_list = strdup(" ");
}
return list;
}
// Initialize output lists to NULL
*rsc_list = NULL;
if (node_list) {
*node_list = NULL;
}
// Sort input list for user-friendliness (and ease of filtering duplicates)
list = g_list_sort(list, sort_notify_entries);
for (GList *gIter = list; gIter != NULL; gIter = gIter->next) {
notify_entry_t *entry = (notify_entry_t *) gIter->data;
// Entry must have a resource (with ID)
CRM_LOG_ASSERT((entry != NULL) && (entry->rsc != NULL)
&& (entry->rsc->id != NULL));
if ((entry == NULL) || (entry->rsc == NULL)
|| (entry->rsc->id == NULL)) {
continue;
}
// Entry must have a node unless listing inactive resources
CRM_LOG_ASSERT((node_list == NULL) || (entry->node != NULL));
if ((node_list != NULL) && (entry->node == NULL)) {
continue;
}
// Don't add duplicates of a particular clone instance
if (pcmk__str_eq(entry->rsc->id, last_rsc_id, pcmk__str_none)) {
continue;
}
last_rsc_id = entry->rsc->id;
pcmk__add_word(rsc_list, &rsc_list_len, entry->rsc->id);
if ((node_list != NULL) && (entry->node->details->uname != NULL)) {
pcmk__add_word(node_list, &node_list_len,
entry->node->details->uname);
}
}
return list;
}
static void
dup_attr(gpointer key, gpointer value, gpointer user_data)
{
add_hash_param(user_data, key, value);
}
static void
add_notify_data_to_action_meta(notify_data_t *n_data, pe_action_t *action)
{
for (GSList *item = n_data->keys; item; item = item->next) {
pcmk_nvpair_t *nvpair = item->data;
add_hash_param(action->meta, nvpair->name, nvpair->value);
}
}
static pe_action_t *
pe_notify(pe_resource_t * rsc, pe_node_t * node, pe_action_t * op, pe_action_t * confirm,
notify_data_t * n_data, pe_working_set_t * data_set)
{
char *key = NULL;
pe_action_t *trigger = NULL;
const char *value = NULL;
const char *task = NULL;
if (op == NULL || confirm == NULL) {
pe_rsc_trace(rsc, "Op=%p confirm=%p", op, confirm);
return NULL;
}
CRM_CHECK(rsc != NULL, return NULL);
CRM_CHECK(node != NULL, return NULL);
if (node->details->online == FALSE) {
pe_rsc_trace(rsc, "Skipping notification for %s: node offline", rsc->id);
return NULL;
} else if (!pcmk_is_set(op->flags, pe_action_runnable)) {
pe_rsc_trace(rsc, "Skipping notification for %s: not runnable", op->uuid);
return NULL;
}
value = g_hash_table_lookup(op->meta, "notify_type");
task = g_hash_table_lookup(op->meta, "notify_operation");
pe_rsc_trace(rsc, "Creating notify actions for %s: %s (%s-%s)", op->uuid, rsc->id, value, task);
key = pcmk__notify_key(rsc->id, value, task);
trigger = custom_action(rsc, key, op->task, node,
pcmk_is_set(op->flags, pe_action_optional),
TRUE, data_set);
g_hash_table_foreach(op->meta, dup_attr, trigger->meta);
add_notify_data_to_action_meta(n_data, trigger);
/* pseudo_notify before notify */
pe_rsc_trace(rsc, "Ordering %s before %s (%d->%d)", op->uuid, trigger->uuid, trigger->id,
op->id);
order_actions(op, trigger, pe_order_optional);
order_actions(trigger, confirm, pe_order_optional);
return trigger;
}
static void
pe_post_notify(pe_resource_t * rsc, pe_node_t * node, notify_data_t * n_data, pe_working_set_t * data_set)
{
pe_action_t *notify = NULL;
CRM_CHECK(rsc != NULL, return);
if (n_data->post == NULL) {
return; /* Nothing to do */
}
notify = pe_notify(rsc, node, n_data->post, n_data->post_done, n_data, data_set);
if (notify != NULL) {
notify->priority = INFINITY;
}
if (n_data->post_done) {
GListPtr gIter = rsc->actions;
for (; gIter != NULL; gIter = gIter->next) {
pe_action_t *mon = (pe_action_t *) gIter->data;
const char *interval_ms_s = g_hash_table_lookup(mon->meta,
XML_LRM_ATTR_INTERVAL_MS);
if (pcmk__str_eq(interval_ms_s, "0", pcmk__str_null_matches | pcmk__str_casei)) {
pe_rsc_trace(rsc, "Skipping %s: interval", mon->uuid);
continue;
} else if (pcmk__str_eq(mon->task, RSC_CANCEL, pcmk__str_casei)) {
pe_rsc_trace(rsc, "Skipping %s: cancel", mon->uuid);
continue;
}
order_actions(n_data->post_done, mon, pe_order_optional);
}
}
}
notify_data_t *
create_notification_boundaries(pe_resource_t * rsc, const char *action, pe_action_t * start,
pe_action_t * end, pe_working_set_t * data_set)
{
/* Create the pseudo ops that precede and follow the actual notifications */
/*
* Creates two sequences (conditional on start and end being supplied):
* pre_notify -> pre_notify_complete -> start, and
* end -> post_notify -> post_notify_complete
*
* 'start' and 'end' may be the same event or ${X} and ${X}ed as per clones
*/
char *key = NULL;
notify_data_t *n_data = NULL;
if (!pcmk_is_set(rsc->flags, pe_rsc_notify)) {
return NULL;
}
n_data = calloc(1, sizeof(notify_data_t));
n_data->action = action;
if (start) {
/* create pre-event notification wrappers */
key = pcmk__notify_key(rsc->id, "pre", start->task);
n_data->pre =
custom_action(rsc, key, RSC_NOTIFY, NULL,
pcmk_is_set(start->flags, pe_action_optional),
TRUE, data_set);
update_action_flags(n_data->pre, pe_action_pseudo, __func__, __LINE__);
update_action_flags(n_data->pre, pe_action_runnable, __func__,
__LINE__);
add_hash_param(n_data->pre->meta, "notify_type", "pre");
add_hash_param(n_data->pre->meta, "notify_operation", n_data->action);
add_hash_param(n_data->pre->meta, "notify_key_type", "pre");
add_hash_param(n_data->pre->meta, "notify_key_operation", start->task);
/* create pre_notify_complete */
key = pcmk__notify_key(rsc->id, "confirmed-pre", start->task);
n_data->pre_done = custom_action(rsc, key, RSC_NOTIFIED, NULL,
pcmk_is_set(start->flags, pe_action_optional),
TRUE, data_set);
update_action_flags(n_data->pre_done, pe_action_pseudo, __func__,
__LINE__);
update_action_flags(n_data->pre_done, pe_action_runnable, __func__,
__LINE__);
add_hash_param(n_data->pre_done->meta, "notify_type", "pre");
add_hash_param(n_data->pre_done->meta, "notify_operation", n_data->action);
add_hash_param(n_data->pre_done->meta, "notify_key_type", "confirmed-pre");
add_hash_param(n_data->pre_done->meta, "notify_key_operation", start->task);
order_actions(n_data->pre_done, start, pe_order_optional);
order_actions(n_data->pre, n_data->pre_done, pe_order_optional);
}
if (end) {
/* create post-event notification wrappers */
key = pcmk__notify_key(rsc->id, "post", end->task);
n_data->post = custom_action(rsc, key, RSC_NOTIFY, NULL,
pcmk_is_set(end->flags, pe_action_optional),
TRUE, data_set);
n_data->post->priority = INFINITY;
update_action_flags(n_data->post, pe_action_pseudo, __func__,
__LINE__);
if (pcmk_is_set(end->flags, pe_action_runnable)) {
update_action_flags(n_data->post, pe_action_runnable, __func__,
__LINE__);
} else {
update_action_flags(n_data->post, pe_action_runnable | pe_action_clear,
__func__, __LINE__);
}
add_hash_param(n_data->post->meta, "notify_type", "post");
add_hash_param(n_data->post->meta, "notify_operation", n_data->action);
add_hash_param(n_data->post->meta, "notify_key_type", "post");
add_hash_param(n_data->post->meta, "notify_key_operation", end->task);
/* create post_notify_complete */
key = pcmk__notify_key(rsc->id, "confirmed-post", end->task);
n_data->post_done = custom_action(rsc, key, RSC_NOTIFIED, NULL,
pcmk_is_set(end->flags, pe_action_optional),
TRUE, data_set);
n_data->post_done->priority = INFINITY;
update_action_flags(n_data->post_done, pe_action_pseudo, __func__,
__LINE__);
if (pcmk_is_set(end->flags, pe_action_runnable)) {
update_action_flags(n_data->post_done, pe_action_runnable,
__func__, __LINE__);
} else {
update_action_flags(n_data->post_done, pe_action_runnable | pe_action_clear,
__func__, __LINE__);
}
add_hash_param(n_data->post_done->meta, "notify_type", "post");
add_hash_param(n_data->post_done->meta, "notify_operation", n_data->action);
add_hash_param(n_data->post_done->meta, "notify_key_type", "confirmed-post");
add_hash_param(n_data->post_done->meta, "notify_key_operation", end->task);
order_actions(end, n_data->post, pe_order_implies_then);
order_actions(n_data->post, n_data->post_done, pe_order_implies_then);
}
if (start && end) {
order_actions(n_data->pre_done, n_data->post, pe_order_optional);
}
return n_data;
}
void
collect_notification_data(pe_resource_t * rsc, gboolean state, gboolean activity,
notify_data_t * n_data)
{
if(n_data->allowed_nodes == NULL) {
n_data->allowed_nodes = rsc->allowed_nodes;
}
if (rsc->children) {
GListPtr gIter = rsc->children;
for (; gIter != NULL; gIter = gIter->next) {
pe_resource_t *child = (pe_resource_t *) gIter->data;
collect_notification_data(child, state, activity, n_data);
}
return;
}
if (state) {
notify_entry_t *entry = NULL;
entry = calloc(1, sizeof(notify_entry_t));
entry->rsc = rsc;
if (rsc->running_on) {
/* we only take the first one */
entry->node = rsc->running_on->data;
}
pe_rsc_trace(rsc, "%s state: %s", rsc->id, role2text(rsc->role));
switch (rsc->role) {
case RSC_ROLE_STOPPED:
n_data->inactive = g_list_prepend(n_data->inactive, entry);
break;
case RSC_ROLE_STARTED:
n_data->active = g_list_prepend(n_data->active, entry);
break;
case RSC_ROLE_SLAVE:
n_data->slave = g_list_prepend(n_data->slave, entry);
n_data->active = g_list_prepend(n_data->active,
dup_notify_entry(entry));
break;
case RSC_ROLE_MASTER:
n_data->master = g_list_prepend(n_data->master, entry);
n_data->active = g_list_prepend(n_data->active,
dup_notify_entry(entry));
break;
default:
crm_err("Unsupported notify role");
free(entry);
break;
}
}
if (activity) {
notify_entry_t *entry = NULL;
enum action_tasks task;
GListPtr gIter = rsc->actions;
for (; gIter != NULL; gIter = gIter->next) {
pe_action_t *op = (pe_action_t *) gIter->data;
if (!pcmk_is_set(op->flags, pe_action_optional)
&& (op->node != NULL)) {
task = text2task(op->task);
if(task == stop_rsc && op->node->details->unclean) {
// Create anyway (additional noise if node can't be fenced)
} else if (!pcmk_is_set(op->flags, pe_action_runnable)) {
continue;
}
entry = calloc(1, sizeof(notify_entry_t));
entry->node = op->node;
entry->rsc = rsc;
switch (task) {
case start_rsc:
n_data->start = g_list_prepend(n_data->start, entry);
break;
case stop_rsc:
n_data->stop = g_list_prepend(n_data->stop, entry);
break;
case action_promote:
n_data->promote = g_list_prepend(n_data->promote, entry);
break;
case action_demote:
n_data->demote = g_list_prepend(n_data->demote, entry);
break;
default:
free(entry);
break;
}
}
}
}
}
#define add_notify_env(n_data, key, value) do { \
n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, value); \
} while (0)
#define add_notify_env_free(n_data, key, value) do { \
n_data->keys = pcmk_prepend_nvpair(n_data->keys, key, value); \
free(value); value = NULL; \
} while (0)
/*!
* \internal
* \brief Create notification name/value pairs from raw data
*
* \param[in] rsc Resource that notification is for
* \param[in,out] n_data Notification data
* \param[in] data_set Cluster working set
*/
void
pcmk__create_notification_keys(pe_resource_t *rsc,
notify_data_t *n_data,
pe_working_set_t *data_set)
{
bool required = false; // Whether to make notify actions required
char *rsc_list = NULL;
char *node_list = NULL;
char *metal_list = NULL;
const char *source = NULL;
GListPtr nodes = NULL;
n_data->stop = expand_list(n_data->stop, &rsc_list, &node_list);
if (!pcmk__str_eq(" ", rsc_list, pcmk__str_null_matches)
&& pcmk__str_eq(n_data->action, RSC_STOP, pcmk__str_casei)) {
required = true;
}
add_notify_env_free(n_data, "notify_stop_resource", rsc_list);
add_notify_env_free(n_data, "notify_stop_uname", node_list);
- if ((n_data->start != NULL) && (rsc_list != NULL)
+ if ((n_data->start != NULL)
&& pcmk__str_eq(n_data->action, RSC_START, pcmk__str_casei)) {
required = true;
}
n_data->start = expand_list(n_data->start, &rsc_list, &node_list);
add_notify_env_free(n_data, "notify_start_resource", rsc_list);
add_notify_env_free(n_data, "notify_start_uname", node_list);
if ((n_data->demote != NULL)
&& pcmk__str_eq(n_data->action, RSC_DEMOTE, pcmk__str_casei)) {
required = true;
}
n_data->demote = expand_list(n_data->demote, &rsc_list, &node_list);
add_notify_env_free(n_data, "notify_demote_resource", rsc_list);
add_notify_env_free(n_data, "notify_demote_uname", node_list);
if ((n_data->promote != NULL)
&& pcmk__str_eq(n_data->action, RSC_PROMOTE, pcmk__str_casei)) {
required = true;
}
n_data->promote = expand_list(n_data->promote, &rsc_list, &node_list);
add_notify_env_free(n_data, "notify_promote_resource", rsc_list);
add_notify_env_free(n_data, "notify_promote_uname", node_list);
n_data->active = expand_list(n_data->active, &rsc_list, &node_list);
add_notify_env_free(n_data, "notify_active_resource", rsc_list);
add_notify_env_free(n_data, "notify_active_uname", node_list);
n_data->slave = expand_list(n_data->slave, &rsc_list, &node_list);
add_notify_env_free(n_data, "notify_slave_resource", rsc_list);
add_notify_env_free(n_data, "notify_slave_uname", node_list);
n_data->master = expand_list(n_data->master, &rsc_list, &node_list);
add_notify_env_free(n_data, "notify_master_resource", rsc_list);
add_notify_env_free(n_data, "notify_master_uname", node_list);
n_data->inactive = expand_list(n_data->inactive, &rsc_list, NULL);
add_notify_env_free(n_data, "notify_inactive_resource", rsc_list);
nodes = g_hash_table_get_values(n_data->allowed_nodes);
if (pcmk_is_set(data_set->flags, pe_flag_stdout)) {
/* If printing to stdout, sort the node list, for consistent
* regression test output (while avoiding the performance hit
* for the live cluster).
*/
nodes = g_list_sort(nodes, sort_node_uname);
}
expand_node_list(nodes, &node_list, NULL);
add_notify_env_free(n_data, "notify_available_uname", node_list);
g_list_free(nodes);
source = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET);
if (pcmk__str_eq("host", source, pcmk__str_casei)) {
expand_node_list(data_set->nodes, &node_list, &metal_list);
add_notify_env_free(n_data, "notify_all_hosts", metal_list);
} else {
expand_node_list(data_set->nodes, &node_list, NULL);
}
add_notify_env_free(n_data, "notify_all_uname", node_list);
if (required && n_data->pre) {
update_action_flags(n_data->pre, pe_action_optional | pe_action_clear,
__func__, __LINE__);
update_action_flags(n_data->pre_done, pe_action_optional | pe_action_clear,
__func__, __LINE__);
}
if (required && n_data->post) {
update_action_flags(n_data->post, pe_action_optional | pe_action_clear,
__func__, __LINE__);
update_action_flags(n_data->post_done, pe_action_optional | pe_action_clear,
__func__, __LINE__);
}
}
/*
* \internal
* \brief Find any remote connection start relevant to an action
*
* \param[in] action Action to chek
*
* \return If action is behind a remote connection, connection's start
*/
static pe_action_t *
find_remote_start(pe_action_t *action)
{
if (action && action->node) {
pe_resource_t *remote_rsc = action->node->details->remote_rsc;
if (remote_rsc) {
return find_first_action(remote_rsc->actions, NULL, RSC_START,
NULL);
}
}
return NULL;
}
void
create_notifications(pe_resource_t * rsc, notify_data_t * n_data, pe_working_set_t * data_set)
{
GListPtr gIter = NULL;
pe_action_t *stop = NULL;
pe_action_t *start = NULL;
enum action_tasks task = text2task(n_data->action);
if (rsc->children) {
gIter = rsc->children;
for (; gIter != NULL; gIter = gIter->next) {
pe_resource_t *child = (pe_resource_t *) gIter->data;
create_notifications(child, n_data, data_set);
}
return;
}
/* Copy notification details into standard ops */
for (gIter = rsc->actions; gIter != NULL; gIter = gIter->next) {
pe_action_t *op = (pe_action_t *) gIter->data;
if (!pcmk_is_set(op->flags, pe_action_optional)
&& (op->node != NULL)) {
enum action_tasks t = text2task(op->task);
switch (t) {
case start_rsc:
case stop_rsc:
case action_promote:
case action_demote:
add_notify_data_to_action_meta(n_data, op);
break;
default:
break;
}
}
}
switch (task) {
case start_rsc:
if (n_data->start == NULL) {
pe_rsc_trace(rsc, "Skipping empty notification for: %s.%s (%s->%s)",
n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
return;
}
break;
case action_promote:
if (n_data->promote == NULL) {
pe_rsc_trace(rsc, "Skipping empty notification for: %s.%s (%s->%s)",
n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
return;
}
break;
case action_demote:
if (n_data->demote == NULL) {
pe_rsc_trace(rsc, "Skipping empty notification for: %s.%s (%s->%s)",
n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
return;
}
break;
default:
/* We cannot do the same for stop_rsc/n_data->stop at it
* might be implied by fencing
*/
break;
}
pe_rsc_trace(rsc, "Creating notifications for: %s.%s (%s->%s)",
n_data->action, rsc->id, role2text(rsc->role), role2text(rsc->next_role));
stop = find_first_action(rsc->actions, NULL, RSC_STOP, NULL);
start = find_first_action(rsc->actions, NULL, RSC_START, NULL);
/* stop / demote */
if (rsc->role != RSC_ROLE_STOPPED) {
if (task == stop_rsc || task == action_demote) {
gIter = rsc->running_on;
for (; gIter != NULL; gIter = gIter->next) {
pe_node_t *current_node = (pe_node_t *) gIter->data;
/* if this stop action is a pseudo action as a result of the current
* node being fenced, this stop action is implied by the fencing
* action. There's no reason to send the fenced node a stop notification */
if (stop && pcmk_is_set(stop->flags, pe_action_pseudo) &&
(current_node->details->unclean || current_node->details->remote_requires_reset) ) {
continue;
}
pe_notify(rsc, current_node, n_data->pre, n_data->pre_done, n_data, data_set);
if (task == action_demote || stop == NULL
|| pcmk_is_set(stop->flags, pe_action_optional)) {
pe_post_notify(rsc, current_node, n_data, data_set);
}
}
}
}
/* start / promote */
if (rsc->next_role != RSC_ROLE_STOPPED) {
if (rsc->allocated_to == NULL) {
pe_proc_err("Next role '%s' but %s is not allocated", role2text(rsc->next_role),
rsc->id);
} else if (task == start_rsc || task == action_promote) {
if (start) {
pe_action_t *remote_start = find_remote_start(start);
if (remote_start
&& !pcmk_is_set(remote_start->flags, pe_action_runnable)) {
/* Start and promote actions for a clone instance behind
* a Pacemaker Remote connection happen after the
* connection starts. If the connection start is blocked, do
* not schedule notifications for these actions.
*/
return;
}
}
if ((task != start_rsc) || (start == NULL)
|| pcmk_is_set(start->flags, pe_action_optional)) {
pe_notify(rsc, rsc->allocated_to, n_data->pre, n_data->pre_done, n_data, data_set);
}
pe_post_notify(rsc, rsc->allocated_to, n_data, data_set);
}
}
}
void
free_notification_data(notify_data_t * n_data)
{
if (n_data == NULL) {
return;
}
g_list_free_full(n_data->stop, free);
g_list_free_full(n_data->start, free);
g_list_free_full(n_data->demote, free);
g_list_free_full(n_data->promote, free);
g_list_free_full(n_data->master, free);
g_list_free_full(n_data->slave, free);
g_list_free_full(n_data->active, free);
g_list_free_full(n_data->inactive, free);
pcmk_free_nvpairs(n_data->keys);
free(n_data);
}
void
create_secondary_notification(pe_action_t *action, pe_resource_t *rsc,
pe_action_t *stonith_op,
pe_working_set_t *data_set)
{
notify_data_t *n_data;
crm_info("Creating secondary notification for %s", action->uuid);
n_data = create_notification_boundaries(rsc, RSC_STOP, NULL, stonith_op,
data_set);
collect_notification_data(rsc, TRUE, FALSE, n_data);
add_notify_env(n_data, "notify_stop_resource", rsc->id);
add_notify_env(n_data, "notify_stop_uname", action->node->details->uname);
create_notifications(uber_parent(rsc), n_data, data_set);
free_notification_data(n_data);
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 23, 11:45 AM (22 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1018689
Default Alt Text
(28 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment