|
|
60de42 |
From 9c0c3d60b4df3076ff27dd176af9b8d131254337 Mon Sep 17 00:00:00 2001
|
|
|
60de42 |
From: Ken Gaillot <kgaillot@redhat.com>
|
|
|
60de42 |
Date: Thu, 2 Mar 2017 13:52:47 -0600
|
|
|
60de42 |
Subject: [PATCH] Fix: libfencing,fencing: properly remap "action" in
|
|
|
60de42 |
configuration
|
|
|
60de42 |
|
|
|
60de42 |
"action" should never be specified in fence device configuration.
|
|
|
60de42 |
|
|
|
60de42 |
Previously, this was handled by re-inserting the proper action when creating a
|
|
|
60de42 |
fence command, if the proper action were on a "safe" list (list, monitor,
|
|
|
60de42 |
status, or meta-data).
|
|
|
60de42 |
|
|
|
60de42 |
However, that was insufficient, partly because "on" should have been on the
|
|
|
60de42 |
list, but also because action="reboot" would interfere with reboots that were
|
|
|
60de42 |
remapped to off or off+on.
|
|
|
60de42 |
|
|
|
60de42 |
Now, stonithd intelligently maps any action parameter to pcmk_off_action and/or
|
|
|
60de42 |
pcmk_reboot_action as appropriate when the device configuration is registered,
|
|
|
60de42 |
and libfencing ignores any action parameter that makes it that far.
|
|
|
60de42 |
---
|
|
|
60de42 |
fencing/commands.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
|
60de42 |
lib/fencing/st_client.c | 52 ++++++++++++++------------------------
|
|
|
60de42 |
2 files changed, 83 insertions(+), 35 deletions(-)
|
|
|
60de42 |
|
|
|
60de42 |
diff --git a/fencing/commands.c b/fencing/commands.c
|
|
|
60de42 |
index e7fce78..b4e6eb5 100644
|
|
|
60de42 |
--- a/fencing/commands.c
|
|
|
60de42 |
+++ b/fencing/commands.c
|
|
|
60de42 |
@@ -783,6 +783,70 @@ read_action_metadata(stonith_device_t *device)
|
|
|
60de42 |
freeXpathObject(xpath);
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
+/*!
|
|
|
60de42 |
+ * \internal
|
|
|
60de42 |
+ * \brief Set a pcmk_*_action parameter if not already set
|
|
|
60de42 |
+ *
|
|
|
60de42 |
+ * \param[in,out] params Device parameters
|
|
|
60de42 |
+ * \param[in] action Name of action
|
|
|
60de42 |
+ * \param[in] value Value to use if action is not already set
|
|
|
60de42 |
+ */
|
|
|
60de42 |
+static void
|
|
|
60de42 |
+map_action(GHashTable *params, const char *action, const char *value)
|
|
|
60de42 |
+{
|
|
|
60de42 |
+ char *key = crm_strdup_printf("pcmk_%s_action", action);
|
|
|
60de42 |
+
|
|
|
60de42 |
+ if (g_hash_table_lookup(params, key)) {
|
|
|
60de42 |
+ crm_warn("Ignoring %s='%s', see %s instead",
|
|
|
60de42 |
+ STONITH_ATTR_ACTION_OP, value, key);
|
|
|
60de42 |
+ free(key);
|
|
|
60de42 |
+ } else {
|
|
|
60de42 |
+ crm_warn("Mapping %s='%s' to %s='%s'",
|
|
|
60de42 |
+ STONITH_ATTR_ACTION_OP, value, key, value);
|
|
|
60de42 |
+ g_hash_table_insert(params, key, strdup(value));
|
|
|
60de42 |
+ }
|
|
|
60de42 |
+}
|
|
|
60de42 |
+
|
|
|
60de42 |
+/*!
|
|
|
60de42 |
+ * \internal
|
|
|
60de42 |
+ * \brief Create device parameter table from XML
|
|
|
60de42 |
+ *
|
|
|
60de42 |
+ * \param[in] name Device name (used for logging only)
|
|
|
60de42 |
+ * \param[in,out] params Device parameters
|
|
|
60de42 |
+ */
|
|
|
60de42 |
+static GHashTable *
|
|
|
60de42 |
+xml2device_params(const char *name, xmlNode *dev)
|
|
|
60de42 |
+{
|
|
|
60de42 |
+ GHashTable *params = xml2list(dev);
|
|
|
60de42 |
+ const char *value;
|
|
|
60de42 |
+
|
|
|
60de42 |
+ /* Action should never be specified in the device configuration,
|
|
|
60de42 |
+ * but we support it for users who are familiar with other software
|
|
|
60de42 |
+ * that worked that way.
|
|
|
60de42 |
+ */
|
|
|
60de42 |
+ value = g_hash_table_lookup(params, STONITH_ATTR_ACTION_OP);
|
|
|
60de42 |
+ if (value != NULL) {
|
|
|
60de42 |
+ crm_warn("%s has '%s' parameter, which should never be specified in configuration",
|
|
|
60de42 |
+ name, STONITH_ATTR_ACTION_OP);
|
|
|
60de42 |
+
|
|
|
60de42 |
+ if (strcmp(value, "reboot") == 0) {
|
|
|
60de42 |
+ crm_warn("Ignoring %s='reboot' (see stonith-action cluster property instead)",
|
|
|
60de42 |
+ STONITH_ATTR_ACTION_OP);
|
|
|
60de42 |
+
|
|
|
60de42 |
+ } else if (strcmp(value, "off") == 0) {
|
|
|
60de42 |
+ map_action(params, "reboot", value);
|
|
|
60de42 |
+
|
|
|
60de42 |
+ } else {
|
|
|
60de42 |
+ map_action(params, "off", value);
|
|
|
60de42 |
+ map_action(params, "reboot", value);
|
|
|
60de42 |
+ }
|
|
|
60de42 |
+
|
|
|
60de42 |
+ g_hash_table_remove(params, STONITH_ATTR_ACTION_OP);
|
|
|
60de42 |
+ }
|
|
|
60de42 |
+
|
|
|
60de42 |
+ return params;
|
|
|
60de42 |
+}
|
|
|
60de42 |
+
|
|
|
60de42 |
static stonith_device_t *
|
|
|
60de42 |
build_device_from_xml(xmlNode * msg)
|
|
|
60de42 |
{
|
|
|
60de42 |
@@ -794,7 +858,7 @@ build_device_from_xml(xmlNode * msg)
|
|
|
60de42 |
device->id = crm_element_value_copy(dev, XML_ATTR_ID);
|
|
|
60de42 |
device->agent = crm_element_value_copy(dev, "agent");
|
|
|
60de42 |
device->namespace = crm_element_value_copy(dev, "namespace");
|
|
|
60de42 |
- device->params = xml2list(dev);
|
|
|
60de42 |
+ device->params = xml2device_params(device->id, dev);
|
|
|
60de42 |
|
|
|
60de42 |
value = g_hash_table_lookup(device->params, STONITH_ATTR_HOSTLIST);
|
|
|
60de42 |
if (value) {
|
|
|
60de42 |
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
|
|
|
60de42 |
index c7f4079..34bba88 100644
|
|
|
60de42 |
--- a/lib/fencing/st_client.c
|
|
|
60de42 |
+++ b/lib/fencing/st_client.c
|
|
|
60de42 |
@@ -394,11 +394,10 @@ stonith_api_register_level(stonith_t * st, int options, const char *node, int le
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
static void
|
|
|
60de42 |
-append_arg(gpointer key, gpointer value, gpointer user_data)
|
|
|
60de42 |
+append_arg(const char *key, const char *value, char **args)
|
|
|
60de42 |
{
|
|
|
60de42 |
int len = 3; /* =, \n, \0 */
|
|
|
60de42 |
int last = 0;
|
|
|
60de42 |
- char **args = user_data;
|
|
|
60de42 |
|
|
|
60de42 |
CRM_CHECK(key != NULL, return);
|
|
|
60de42 |
CRM_CHECK(value != NULL, return);
|
|
|
60de42 |
@@ -418,22 +417,20 @@ append_arg(gpointer key, gpointer value, gpointer user_data)
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
*args = realloc_safe(*args, last + len);
|
|
|
60de42 |
- crm_trace("Appending: %s=%s", (char *)key, (char *)value);
|
|
|
60de42 |
- sprintf((*args) + last, "%s=%s\n", (char *)key, (char *)value);
|
|
|
60de42 |
+ crm_trace("Appending: %s=%s", key, value);
|
|
|
60de42 |
+ sprintf((*args) + last, "%s=%s\n", key, value);
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
static void
|
|
|
60de42 |
-append_const_arg(const char *key, const char *value, char **arg_list)
|
|
|
60de42 |
+append_config_arg(gpointer key, gpointer value, gpointer user_data)
|
|
|
60de42 |
{
|
|
|
60de42 |
- CRM_LOG_ASSERT(key && value);
|
|
|
60de42 |
- if(key && value) {
|
|
|
60de42 |
- char *glib_sucks_key = strdup(key);
|
|
|
60de42 |
- char *glib_sucks_value = strdup(value);
|
|
|
60de42 |
-
|
|
|
60de42 |
- append_arg(glib_sucks_key, glib_sucks_value, arg_list);
|
|
|
60de42 |
-
|
|
|
60de42 |
- free(glib_sucks_value);
|
|
|
60de42 |
- free(glib_sucks_key);
|
|
|
60de42 |
+ /* stonithd will filter action out when it registers the device,
|
|
|
60de42 |
+ * but ignore it here just in case any other library callers
|
|
|
60de42 |
+ * fail to do so.
|
|
|
60de42 |
+ */
|
|
|
60de42 |
+ if (safe_str_neq(key, STONITH_ATTR_ACTION_OP)) {
|
|
|
60de42 |
+ append_arg(key, value, user_data);
|
|
|
60de42 |
+ return;
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
@@ -446,7 +443,7 @@ append_host_specific_args(const char *victim, const char *map, GHashTable * para
|
|
|
60de42 |
if (map == NULL) {
|
|
|
60de42 |
/* The best default there is for now... */
|
|
|
60de42 |
crm_debug("Using default arg map: port=uname");
|
|
|
60de42 |
- append_const_arg("port", victim, arg_list);
|
|
|
60de42 |
+ append_arg("port", victim, arg_list);
|
|
|
60de42 |
return;
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
@@ -489,7 +486,7 @@ append_host_specific_args(const char *victim, const char *map, GHashTable * para
|
|
|
60de42 |
|
|
|
60de42 |
if (value) {
|
|
|
60de42 |
crm_debug("Setting '%s'='%s' (%s) for %s", name, value, param, victim);
|
|
|
60de42 |
- append_const_arg(name, value, arg_list);
|
|
|
60de42 |
+ append_arg(name, value, arg_list);
|
|
|
60de42 |
|
|
|
60de42 |
} else {
|
|
|
60de42 |
crm_err("No node attribute '%s' for '%s'", name, victim);
|
|
|
60de42 |
@@ -516,7 +513,6 @@ make_args(const char *agent, const char *action, const char *victim, uint32_t vi
|
|
|
60de42 |
char buffer[512];
|
|
|
60de42 |
char *arg_list = NULL;
|
|
|
60de42 |
const char *value = NULL;
|
|
|
60de42 |
- const char *_action = action;
|
|
|
60de42 |
|
|
|
60de42 |
CRM_CHECK(action != NULL, return NULL);
|
|
|
60de42 |
|
|
|
60de42 |
@@ -542,7 +538,7 @@ make_args(const char *agent, const char *action, const char *victim, uint32_t vi
|
|
|
60de42 |
action = value;
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
- append_const_arg(STONITH_ATTR_ACTION_OP, action, &arg_list);
|
|
|
60de42 |
+ append_arg(STONITH_ATTR_ACTION_OP, action, &arg_list);
|
|
|
60de42 |
if (victim && device_args) {
|
|
|
60de42 |
const char *alias = victim;
|
|
|
60de42 |
const char *param = g_hash_table_lookup(device_args, STONITH_ATTR_HOSTARG);
|
|
|
60de42 |
@@ -554,13 +550,13 @@ make_args(const char *agent, const char *action, const char *victim, uint32_t vi
|
|
|
60de42 |
/* Always supply the node's name too:
|
|
|
60de42 |
* https://fedorahosted.org/cluster/wiki/FenceAgentAPI
|
|
|
60de42 |
*/
|
|
|
60de42 |
- append_const_arg("nodename", victim, &arg_list);
|
|
|
60de42 |
+ append_arg("nodename", victim, &arg_list);
|
|
|
60de42 |
if (victim_nodeid) {
|
|
|
60de42 |
char nodeid_str[33] = { 0, };
|
|
|
60de42 |
if (snprintf(nodeid_str, 33, "%u", (unsigned int)victim_nodeid)) {
|
|
|
60de42 |
crm_info("For stonith action (%s) for victim %s, adding nodeid (%s) to parameters",
|
|
|
60de42 |
action, victim, nodeid_str);
|
|
|
60de42 |
- append_const_arg("nodeid", nodeid_str, &arg_list);
|
|
|
60de42 |
+ append_arg("nodeid", nodeid_str, &arg_list);
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
@@ -592,24 +588,12 @@ make_args(const char *agent, const char *action, const char *victim, uint32_t vi
|
|
|
60de42 |
if (value == NULL || safe_str_eq(value, "dynamic")) {
|
|
|
60de42 |
crm_debug("Performing %s action for node '%s' as '%s=%s'", action, victim, param,
|
|
|
60de42 |
alias);
|
|
|
60de42 |
- append_const_arg(param, alias, &arg_list);
|
|
|
60de42 |
+ append_arg(param, alias, &arg_list);
|
|
|
60de42 |
}
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
if (device_args) {
|
|
|
60de42 |
- g_hash_table_foreach(device_args, append_arg, &arg_list);
|
|
|
60de42 |
- }
|
|
|
60de42 |
-
|
|
|
60de42 |
- if(device_args && g_hash_table_lookup(device_args, STONITH_ATTR_ACTION_OP)) {
|
|
|
60de42 |
- if(safe_str_eq(_action,"list")
|
|
|
60de42 |
- || safe_str_eq(_action,"status")
|
|
|
60de42 |
- || safe_str_eq(_action,"monitor")
|
|
|
60de42 |
- || safe_str_eq(_action,"metadata")) {
|
|
|
60de42 |
- /* Force use of the calculated command for support ops
|
|
|
60de42 |
- * We don't want list or monitor ops initiating fencing, regardless of what the admin configured
|
|
|
60de42 |
- */
|
|
|
60de42 |
- append_const_arg(STONITH_ATTR_ACTION_OP, action, &arg_list);
|
|
|
60de42 |
- }
|
|
|
60de42 |
+ g_hash_table_foreach(device_args, append_config_arg, &arg_list);
|
|
|
60de42 |
}
|
|
|
60de42 |
|
|
|
60de42 |
return arg_list;
|
|
|
60de42 |
--
|
|
|
60de42 |
1.8.3.1
|
|
|
60de42 |
|