From 5e6a84a817af66562d59a851b130e1da71da13c3 Mon Sep 17 00:00:00 2001
From: "Gao,Yan" <ygao@suse.com>
Date: Wed, 6 May 2020 21:47:47 +0200
Subject: [PATCH 8/9] Fix: libstonithd: add `port` or `plug` parameter
 according to metadata on `validate` if no `pcmk_host_argument` specified

---
 include/crm/fencing/internal.h |  2 +-
 lib/fencing/st_client.c        |  8 +++-
 lib/fencing/st_rhcs.c          | 76 ++++++++++++++++++++++++++++++----
 3 files changed, 76 insertions(+), 10 deletions(-)

diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h
index 9b4cc71e3..63fcb09e7 100644
--- a/include/crm/fencing/internal.h
+++ b/include/crm/fencing/internal.h
@@ -160,7 +160,7 @@ int stonith__list_rhcs_agents(stonith_key_value_t **devices);
 int stonith__rhcs_metadata(const char *agent, int timeout, char **output);
 bool stonith__agent_is_rhcs(const char *agent);
 int stonith__rhcs_validate(stonith_t *st, int call_options, const char *target,
-                           const char *agent, GHashTable *params,
+                           const char *agent, GHashTable *params, const char *host_arg,
                            int timeout, char **output, char **error_output);
 
 #endif
diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c
index 3f7a83f15..c64541383 100644
--- a/lib/fencing/st_client.c
+++ b/lib/fencing/st_client.c
@@ -2143,11 +2143,15 @@ stonith_api_validate(stonith_t *st, int call_options, const char *rsc_id,
      * that is incorrect, we will need to allow the caller to pass the target).
      */
     const char *target = "node1";
+    const char *host_arg = NULL;
 
     GHashTable *params_table = crm_str_table_new();
 
     // Convert parameter list to a hash table
     for (; params; params = params->next) {
+        if (safe_str_eq(params->key, STONITH_ATTR_HOSTARG)) {
+            host_arg = params->value;
+        }
 
         // Strip out Pacemaker-implemented parameters
         if (!crm_starts_with(params->key, "pcmk_")
@@ -2176,8 +2180,8 @@ stonith_api_validate(stonith_t *st, int call_options, const char *rsc_id,
     switch (stonith_get_namespace(agent, namespace_s)) {
         case st_namespace_rhcs:
             rc = stonith__rhcs_validate(st, call_options, target, agent,
-                                        params_table, timeout, output,
-                                        error_output);
+                                        params_table, host_arg, timeout,
+                                        output, error_output);
             break;
 
 #if HAVE_STONITH_STONITH_H
diff --git a/lib/fencing/st_rhcs.c b/lib/fencing/st_rhcs.c
index 56ea08661..9d4ff1b08 100644
--- a/lib/fencing/st_rhcs.c
+++ b/lib/fencing/st_rhcs.c
@@ -91,12 +91,12 @@ stonith_rhcs_parameter_not_required(xmlNode *metadata, const char *parameter)
  *
  * \param[in]  agent    Agent to execute
  * \param[in]  timeout  Action timeout
- * \param[out] output   Where to store action output (or NULL to ignore)
+ * \param[out] metadata Where to store output xmlNode (or NULL to ignore)
  *
  * \todo timeout is currently ignored; shouldn't we use it?
  */
-int
-stonith__rhcs_metadata(const char *agent, int timeout, char **output)
+static int
+stonith__rhcs_get_metadata(const char *agent, int timeout, xmlNode **metadata)
 {
     char *buffer = NULL;
     xmlNode *xml = NULL;
@@ -161,6 +161,38 @@ stonith__rhcs_metadata(const char *agent, int timeout, char **output)
     stonith_rhcs_parameter_not_required(xml, "plug");
     stonith_rhcs_parameter_not_required(xml, "port");
 
+    if (metadata) {
+        *metadata = xml;
+
+    } else {
+        free_xml(xml);
+    }
+
+    return pcmk_ok;
+}
+
+/*!
+ * \brief Execute RHCS-compatible agent's meta-data action
+ *
+ * \param[in]  agent    Agent to execute
+ * \param[in]  timeout  Action timeout
+ * \param[out] output   Where to store action output (or NULL to ignore)
+ *
+ * \todo timeout is currently ignored; shouldn't we use it?
+ */
+int
+stonith__rhcs_metadata(const char *agent, int timeout, char **output)
+{
+    char *buffer = NULL;
+    xmlNode *xml = NULL;
+
+    int rc = stonith__rhcs_get_metadata(agent, timeout, &xml);
+
+    if (rc != pcmk_ok) {
+        free_xml(xml);
+        return rc;
+    }
+
     buffer = dump_xml_formatted_with_text(xml);
     free_xml(xml);
     if (buffer == NULL) {
@@ -187,13 +219,43 @@ stonith__agent_is_rhcs(const char *agent)
 
 int
 stonith__rhcs_validate(stonith_t *st, int call_options, const char *target,
-                       const char *agent, GHashTable *params, int timeout,
+                       const char *agent, GHashTable *params,
+                       const char * host_arg, int timeout,
                        char **output, char **error_output)
 {
     int rc = pcmk_ok;
-    stonith_action_t *action = stonith_action_create(agent, "validate-all",
-                                                     target, 0, timeout, params,
-                                                     NULL, NULL);
+    int remaining_timeout = timeout;
+    xmlNode *metadata = NULL;
+    stonith_action_t *action = NULL;
+
+    if (host_arg == NULL) {
+        time_t start_time = time(NULL);
+
+        rc = stonith__rhcs_get_metadata(agent, remaining_timeout, &metadata);
+
+        if (rc == pcmk_ok) {
+            long long device_flags = stonith__device_parameter_flags(metadata);
+
+            if (is_set(device_flags, st_device_supports_parameter_port)) {
+                host_arg = "port";
+
+            } else if (is_set(device_flags, st_device_supports_parameter_plug)) {
+                host_arg = "plug";
+            }
+        }
+
+        free_xml(metadata);
+
+        remaining_timeout -= time(NULL) - start_time;
+
+        if (rc == -ETIME || remaining_timeout <= 0 ) {
+            return -ETIME;
+        }
+    }
+
+    action = stonith_action_create(agent, "validate-all",
+                                   target, 0, remaining_timeout, params,
+                                   NULL, host_arg);
 
     rc = stonith__execute(action);
     if (rc == pcmk_ok) {
-- 
2.26.1

