Blame SOURCES/029-stonith-action-param.patch

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