commit c52267dfbe67a89136d962a137e0973852b08a77
Author: Gao,Yan <ygao@suse.com>
Date:   Wed Apr 13 12:57:44 2016 +0200

    Fix: fencing: Record the last known names of nodes to make sure fencing requested with nodeid works
    
    dlm_controld invokes dlm_stonith which calls stonith_api_kick_helper()
    to request fencing by nodeid. We need to translate the nodeid into
    the nodename when handling the fencing. Previously if the node had been
    lost, fencing would fail since the peer cache entry had been autoreaped.
    
    This commit fixes it by recording the last known names of the nodes in a
    dedicated hash table. This commit also switches the invocations of
    crm_get_peer() to crm_find_peer() to avoid recreating a node entry in the
    peer cache.

diff --git a/fencing/commands.c b/fencing/commands.c
index 2ea223d..bc6f9c0 100644
--- a/fencing/commands.c
+++ b/fencing/commands.c
@@ -2151,19 +2151,22 @@ stonith_fence(xmlNode * msg)
 
     } else {
         const char *host = crm_element_value(dev, F_STONITH_TARGET);
+        char *nodename = NULL;
 
         if (cmd->options & st_opt_cs_nodeid) {
             int nodeid = crm_atoi(host, NULL);
-            crm_node_t *node = crm_get_peer(nodeid, NULL);
 
-            if (node) {
-                host = node->uname;
+            nodename = stonith_get_peer_name(nodeid);
+            if (nodename) {
+                host = nodename;
             }
         }
 
         /* If we get to here, then self-fencing is implicitly allowed */
         get_capable_devices(host, cmd->action, cmd->default_timeout,
                             TRUE, cmd, stonith_fence_get_devices_cb);
+
+        free(nodename);
     }
 
     return -EINPROGRESS;
diff --git a/fencing/internal.h b/fencing/internal.h
index 5538a3a..c6d0060 100644
--- a/fencing/internal.h
+++ b/fencing/internal.h
@@ -235,8 +235,12 @@ schedule_internal_command(const char *origin,
                           void (*done_cb) (GPid pid, int rc, const char *output,
                                            gpointer user_data));
 
+char *stonith_get_peer_name(unsigned int nodeid);
+
 extern char *stonith_our_uname;
 extern gboolean stand_alone;
 extern GHashTable *device_list;
 extern GHashTable *topology;
 extern long stonith_watchdog_timeout_ms;
+
+extern GHashTable *known_peer_names;
diff --git a/fencing/main.c b/fencing/main.c
index 7610723..1d50355 100644
--- a/fencing/main.c
+++ b/fencing/main.c
@@ -62,6 +62,8 @@ gboolean stonith_shutdown_flag = FALSE;
 qb_ipcs_service_t *ipcs = NULL;
 xmlNode *local_cib = NULL;
 
+GHashTable *known_peer_names = NULL;
+
 static cib_t *cib_api = NULL;
 static void *cib_library = NULL;
 
@@ -1171,6 +1173,10 @@ stonith_cleanup(void)
     if (ipcs) {
         qb_ipcs_destroy(ipcs);
     }
+
+    g_hash_table_destroy(known_peer_names);
+    known_peer_names = NULL;
+
     crm_peer_destroy();
     crm_client_cleanup();
     free(stonith_our_uname);
@@ -1250,11 +1256,17 @@ static void
 st_peer_update_callback(enum crm_status_type type, crm_node_t * node, const void *data)
 {
     if ((type != crm_status_processes) && !is_set(node->flags, crm_remote_node)) {
+        xmlNode *query = NULL;
+
+        if (node->id && node->uname) {
+            g_hash_table_insert(known_peer_names, GUINT_TO_POINTER(node->id), strdup(node->uname));
+        }
+
         /*
          * This is a hack until we can send to a nodeid and/or we fix node name lookups
          * These messages are ignored in stonith_peer_callback()
          */
-        xmlNode *query = create_xml_node(NULL, "stonith_command");
+        query = create_xml_node(NULL, "stonith_command");
 
         crm_xml_add(query, F_XML_TAGNAME, "stonith_command");
         crm_xml_add(query, F_TYPE, T_STONITH_NG);
@@ -1434,6 +1446,7 @@ main(int argc, char **argv)
     mainloop_add_signal(SIGTERM, stonith_shutdown);
 
     crm_peer_init();
+    known_peer_names = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free);
 
     if (stand_alone == FALSE) {
 #if SUPPORT_HEARTBEAT
diff --git a/fencing/remote.c b/fencing/remote.c
index ec16160..2394590 100644
--- a/fencing/remote.c
+++ b/fencing/remote.c
@@ -918,6 +918,30 @@ stonith_manual_ack(xmlNode * msg, remote_fencing_op_t * op)
     return -EINPROGRESS;
 }
 
+char *
+stonith_get_peer_name(unsigned int nodeid)
+{
+    crm_node_t *node = crm_find_peer(nodeid, NULL);
+    char *nodename = NULL;
+
+    if (node && node->uname) {
+        return strdup(node->uname);
+
+    } else if ((nodename = get_node_name(nodeid))) {
+        return nodename;
+
+    } else {
+        const char *last_known_name = g_hash_table_lookup(known_peer_names, GUINT_TO_POINTER(nodeid));
+
+        if (last_known_name) {
+            crm_debug("Use the last known name %s for nodeid %u", last_known_name, nodeid);
+            return strdup(last_known_name);
+        }
+    }
+
+    return NULL;
+}
+
 /*!
  * \internal
  * \brief Create a new remote stonith op
@@ -999,16 +1023,17 @@ create_remote_stonith_op(const char *client, xmlNode * request, gboolean peer)
 
     if (op->call_options & st_opt_cs_nodeid) {
         int nodeid = crm_atoi(op->target, NULL);
-        crm_node_t *node = crm_get_peer(nodeid, NULL);
+        char *nodename = stonith_get_peer_name(nodeid);
 
         /* Ensure the conversion only happens once */
         op->call_options &= ~st_opt_cs_nodeid;
 
-        if (node && node->uname) {
+        if (nodename) {
             free(op->target);
-            op->target = strdup(node->uname);
+            op->target = nodename;
+
         } else {
-            crm_warn("Could not expand nodeid '%s' into a host name (%p)", op->target, node);
+            crm_warn("Could not expand nodeid '%s' into a host name", op->target);
         }
     }
 
@@ -1996,6 +2021,7 @@ stonith_fence_history(xmlNode * msg, xmlNode ** output)
     int rc = 0;
     const char *target = NULL;
     xmlNode *dev = get_xpath_object("//@" F_STONITH_TARGET, msg, LOG_TRACE);
+    char *nodename = NULL;
 
     if (dev) {
         int options = 0;
@@ -2004,10 +2030,10 @@ stonith_fence_history(xmlNode * msg, xmlNode ** output)
         crm_element_value_int(msg, F_STONITH_CALLOPTS, &options);
         if (target && (options & st_opt_cs_nodeid)) {
             int nodeid = crm_atoi(target, NULL);
-            crm_node_t *node = crm_get_peer(nodeid, NULL);
 
-            if (node) {
-                target = node->uname;
+            nodename = stonith_get_peer_name(nodeid);
+            if (nodename) {
+                target = nodename;
             }
         }
     }
@@ -2040,6 +2066,7 @@ stonith_fence_history(xmlNode * msg, xmlNode ** output)
         }
     }
 
+    free(nodename);
     return rc;
 }
 
