From 30c04b0f6d717ad27601477eb4b4c47402f46b57 Mon Sep 17 00:00:00 2001
From: Kazunori INOUE <kazunori_inoue@newson.co.jp>
Date: Fri, 29 Jan 2021 11:28:20 +0900
Subject: [PATCH] Fix: fencing: remove any devices that are not installed

---
 daemons/fenced/fenced_commands.c  |  2 ++
 daemons/fenced/pacemaker-fenced.c | 37 ++++++++++++++++++-------------
 daemons/fenced/pacemaker-fenced.h |  1 +
 3 files changed, 25 insertions(+), 15 deletions(-)

Index: pacemaker-2.0.1+20190417.13d370ca9/daemons/fenced/fenced_commands.c
===================================================================
--- pacemaker-2.0.1+20190417.13d370ca9.orig/daemons/fenced/fenced_commands.c
+++ pacemaker-2.0.1+20190417.13d370ca9/daemons/fenced/fenced_commands.c
@@ -1224,6 +1224,8 @@ stonith_device_register(xmlNode * msg, c
                    g_hash_table_size(device_list));
         free_device(device);
         device = dup;
+        dup = g_hash_table_lookup(device_list, device->id);
+        dup->dirty = FALSE;
 
     } else {
         stonith_device_t *old = g_hash_table_lookup(device_list, device->id);
Index: pacemaker-2.0.1+20190417.13d370ca9/daemons/fenced/pacemaker-fenced.c
===================================================================
--- pacemaker-2.0.1+20190417.13d370ca9.orig/daemons/fenced/pacemaker-fenced.c
+++ pacemaker-2.0.1+20190417.13d370ca9/daemons/fenced/pacemaker-fenced.c
@@ -580,11 +580,8 @@ static void cib_device_update(resource_t
     const char *value = NULL;
     const char *rclass = NULL;
     node_t *parent = NULL;
-    gboolean remove = TRUE;
 
-    /* If this is a complex resource, check children rather than this resource itself.
-     * TODO: Mark each installed device and remove if untouched when this process finishes.
-     */
+    /* If this is a complex resource, check children rather than this resource itself. */
     if(rsc->children) {
         GListPtr gIter = NULL;
         for (gIter = rsc->children; gIter != NULL; gIter = gIter->next) {
@@ -603,11 +600,11 @@ static void cib_device_update(resource_t
         return;
     }
 
-    /* If this STONITH resource is disabled, just remove it. */
+    /* If this STONITH resource is disabled, remove it. */
     value = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET_ROLE);
     if (safe_str_eq(value, RSC_STOPPED)) {
         crm_info("Device %s has been disabled", rsc->id);
-        goto update_done;
+        return;
     }
 
     /* Check whether our node is allowed for this resource (and its parent if in a group) */
@@ -626,7 +623,7 @@ static void cib_device_update(resource_t
             crm_trace("Available: %s = %d", node->details->uname, node->weight);
         }
 
-        goto update_done;
+        return;
 
     } else if(node->weight < 0 || (parent && parent->weight < 0)) {
         /* Our node (or its group) is disallowed by score, so remove the device */
@@ -635,7 +632,7 @@ static void cib_device_update(resource_t
         crm_info("Device %s has been disabled on %s: score=%s", rsc->id, stonith_our_uname, score);
         free(score);
 
-        goto update_done;
+        return;
 
     } else {
         /* Our node is allowed, so update the device information */
@@ -663,7 +660,6 @@ static void cib_device_update(resource_t
             crm_trace(" %s=%s", name, value);
         }
 
-        remove = FALSE;
         data = create_device_registration_xml(rsc_name(rsc), st_namespace_any,
                                               agent, params, rsc_provides);
         stonith_key_value_freeall(params, 1, 1);
@@ -671,12 +667,6 @@ static void cib_device_update(resource_t
         CRM_ASSERT(rc == pcmk_ok);
         free_xml(data);
     }
-
-update_done:
-
-    if(remove && g_hash_table_lookup(device_list, rsc_name(rsc))) {
-        stonith_device_remove(rsc_name(rsc), TRUE);
-    }
 }
 
 /*!
@@ -687,6 +677,8 @@ static void
 cib_devices_update(void)
 {
     GListPtr gIter = NULL;
+    GHashTableIter iter;
+    stonith_device_t *device = NULL;
 
     crm_info("Updating devices to version %s.%s.%s",
              crm_element_value(local_cib, XML_ATTR_GENERATION_ADMIN),
@@ -702,9 +694,24 @@ cib_devices_update(void)
     cluster_status(fenced_data_set);
     pcmk__schedule_actions(fenced_data_set, NULL, NULL);
 
+    g_hash_table_iter_init(&iter, device_list);
+    while (g_hash_table_iter_next(&iter, NULL, (void **)&device)) {
+        if (device->cib_registered) {
+            device->dirty = TRUE;
+        }
+    }
+
     for (gIter = fenced_data_set->resources; gIter != NULL; gIter = gIter->next) {
         cib_device_update(gIter->data, fenced_data_set);
     }
+
+    g_hash_table_iter_init(&iter, device_list);
+    while (g_hash_table_iter_next(&iter, NULL, (void **)&device)) {
+        if (device->dirty) {
+            g_hash_table_iter_remove(&iter);
+        }
+    }
+
     fenced_data_set->input = NULL; // Wasn't a copy, so don't let API free it
     pe_reset_working_set(fenced_data_set);
 }
Index: pacemaker-2.0.1+20190417.13d370ca9/daemons/fenced/pacemaker-fenced.h
===================================================================
--- pacemaker-2.0.1+20190417.13d370ca9.orig/daemons/fenced/pacemaker-fenced.h
+++ pacemaker-2.0.1+20190417.13d370ca9/daemons/fenced/pacemaker-fenced.h
@@ -49,6 +49,7 @@ typedef struct stonith_device_s {
 
     gboolean cib_registered;
     gboolean api_registered;
+    gboolean dirty;
 } stonith_device_t;
 
 /* These values are used to index certain arrays by "phase". Usually an
