Blame SOURCES/bz1078078-pcmk-execute_all_required_fencing_devices_regardless_of_what_topology_level_they_are_at.patch

7ebc05
commit 7aa42a14d8b06638f3e3e175fc59e16f730979a8
7ebc05
Author: David Vossel <dvossel@redhat.com>
7ebc05
Date:   Thu Apr 17 10:52:45 2014 -0500
7ebc05
7ebc05
    High: fencing: Execute all required fencing devices regardless of what topology level they are at
7ebc05
    
7ebc05
    (cherry picked from commit c922fd50f7c8deb337aad932cb0b8d1c26cbcd99)
7ebc05
7ebc05
diff --git a/fencing/commands.c b/fencing/commands.c
7ebc05
index 8efb156..b4cd862 100644
7ebc05
--- a/fencing/commands.c
7ebc05
+++ b/fencing/commands.c
7ebc05
@@ -1297,6 +1297,10 @@ stonith_query_capable_device_cb(GList * devices, void *user_data)
7ebc05
         crm_xml_add(dev, "namespace", device->namespace);
7ebc05
         crm_xml_add(dev, "agent", device->agent);
7ebc05
         crm_xml_add_int(dev, F_STONITH_DEVICE_VERIFIED, device->verified);
7ebc05
+        if (is_action_required(query->action, device)) {
7ebc05
+            crm_xml_add_int(dev, F_STONITH_DEVICE_REQUIRED, 1);
7ebc05
+        }
7ebc05
+        crm_xml_add_int(dev, F_STONITH_DEVICE_VERIFIED, device->verified);
7ebc05
         if (action_specific_timeout) {
7ebc05
             crm_xml_add_int(dev, F_STONITH_ACTION_TIMEOUT, action_specific_timeout);
7ebc05
         }
7ebc05
diff --git a/fencing/internal.h b/fencing/internal.h
7ebc05
index 971a32f..3fcad20 100644
7ebc05
--- a/fencing/internal.h
7ebc05
+++ b/fencing/internal.h
7ebc05
@@ -113,6 +113,10 @@ typedef struct remote_fencing_op_s {
7ebc05
 
7ebc05
     /*! The current topology level being executed */
7ebc05
     guint level;
7ebc05
+
7ebc05
+    /*! List of required devices the topology must execute regardless of what
7ebc05
+     * topology level they exist at. */
7ebc05
+    GListPtr required_list;
7ebc05
     /*! The device list of all the devices at the current executing topology level. */
7ebc05
     GListPtr devices_list;
7ebc05
     /*! Current entry in the topology device list */
7ebc05
diff --git a/fencing/remote.c b/fencing/remote.c
7ebc05
index fd25025..10447e7 100644
7ebc05
--- a/fencing/remote.c
7ebc05
+++ b/fencing/remote.c
7ebc05
@@ -68,6 +68,12 @@ static void report_timeout_period(remote_fencing_op_t * op, int op_timeout);
7ebc05
 static int get_op_total_timeout(remote_fencing_op_t * op, st_query_result_t * chosen_peer,
7ebc05
                                 int default_timeout);
7ebc05
 
7ebc05
+static gint
7ebc05
+sort_strings(gconstpointer a, gconstpointer b)
7ebc05
+{
7ebc05
+    return strcmp(a, b);
7ebc05
+}
7ebc05
+
7ebc05
 static void
7ebc05
 free_remote_query(gpointer data)
7ebc05
 {
7ebc05
@@ -128,6 +134,10 @@ free_remote_op(gpointer data)
7ebc05
         g_list_free_full(op->devices_list, free);
7ebc05
         op->devices_list = NULL;
7ebc05
     }
7ebc05
+    if (op->required_list) {
7ebc05
+        g_list_free_full(op->required_list, free);
7ebc05
+        op->required_list = NULL;
7ebc05
+    }
7ebc05
     free(op);
7ebc05
 }
7ebc05
 
7ebc05
@@ -400,6 +410,25 @@ topology_is_empty(stonith_topology_t *tp)
7ebc05
     return TRUE;
7ebc05
 }
7ebc05
 
7ebc05
+static void
7ebc05
+add_required_device(remote_fencing_op_t * op, const char *device)
7ebc05
+{
7ebc05
+    GListPtr match  = g_list_find_custom(op->required_list, device, sort_strings);
7ebc05
+    if (match) {
7ebc05
+        /* device already marked required */
7ebc05
+        return;
7ebc05
+    }
7ebc05
+    op->required_list = g_list_prepend(op->required_list, strdup(device));
7ebc05
+
7ebc05
+    /* make sure the required devices is in the current list of devices to be executed */
7ebc05
+    if (op->devices_list) {
7ebc05
+        GListPtr match  = g_list_find_custom(op->devices_list, device, sort_strings);
7ebc05
+        if (match == NULL) {
7ebc05
+           op->devices_list = g_list_append(op->devices_list, strdup(device));
7ebc05
+        }
7ebc05
+    }
7ebc05
+}
7ebc05
+
7ebc05
 /* deep copy the device list */
7ebc05
 static void
7ebc05
 set_op_device_list(remote_fencing_op_t * op, GListPtr devices)
7ebc05
@@ -413,6 +442,18 @@ set_op_device_list(remote_fencing_op_t * op, GListPtr devices)
7ebc05
     for (lpc = devices; lpc != NULL; lpc = lpc->next) {
7ebc05
         op->devices_list = g_list_append(op->devices_list, strdup(lpc->data));
7ebc05
     }
7ebc05
+
7ebc05
+    /* tack on whatever required devices have not been executed
7ebc05
+     * to the end of the current devices list. This ensures that
7ebc05
+     * the required devices will get executed regardless of what topology
7ebc05
+     * level they exist at. */
7ebc05
+    for (lpc = op->required_list; lpc != NULL; lpc = lpc->next) {
7ebc05
+        GListPtr match  = g_list_find_custom(op->devices_list, lpc->data, sort_strings);
7ebc05
+        if (match == NULL) {
7ebc05
+           op->devices_list = g_list_append(op->devices_list, strdup(lpc->data));
7ebc05
+        }
7ebc05
+    }
7ebc05
+
7ebc05
     op->devices = op->devices_list;
7ebc05
 }
7ebc05
 
7ebc05
@@ -714,12 +755,6 @@ initiate_remote_stonith_op(crm_client_t * client, xmlNode * request, gboolean ma
7ebc05
     return op;
7ebc05
 }
7ebc05
 
7ebc05
-static gint
7ebc05
-sort_strings(gconstpointer a, gconstpointer b)
7ebc05
-{
7ebc05
-    return strcmp(a, b);
7ebc05
-}
7ebc05
-
7ebc05
 enum find_best_peer_options {
7ebc05
     /*! Skip checking the target peer for capable fencing devices */
7ebc05
     FIND_PEER_SKIP_TARGET = 0x0001,
7ebc05
@@ -1165,11 +1200,13 @@ process_remote_stonith_query(xmlNode * msg)
7ebc05
         const char *device = ID(child);
7ebc05
         int action_timeout = 0;
7ebc05
         int verified = 0;
7ebc05
+        int required = 0;
7ebc05
 
7ebc05
         if (device) {
7ebc05
             result->device_list = g_list_prepend(result->device_list, strdup(device));
7ebc05
             crm_element_value_int(child, F_STONITH_ACTION_TIMEOUT, &action_timeout);
7ebc05
             crm_element_value_int(child, F_STONITH_DEVICE_VERIFIED, &verified);
7ebc05
+            crm_element_value_int(child, F_STONITH_DEVICE_REQUIRED, &required);
7ebc05
             if (action_timeout) {
7ebc05
                 crm_trace("Peer %s with device %s returned action timeout %d",
7ebc05
                           result->host, device, action_timeout);
7ebc05
@@ -1181,6 +1218,13 @@ process_remote_stonith_query(xmlNode * msg)
7ebc05
                 g_hash_table_insert(result->verified_devices,
7ebc05
                                     strdup(device), GINT_TO_POINTER(verified));
7ebc05
             }
7ebc05
+            if (required) {
7ebc05
+                crm_trace("Peer %s requires device %s to execute for action %s",
7ebc05
+                          result->host, device, op->action);
7ebc05
+                /* This matters when executing a topology. Required devices will get 
7ebc05
+                 * executed regardless of their topology level. We use this for unfencing. */
7ebc05
+                add_required_device(op, device);
7ebc05
+            }
7ebc05
         }
7ebc05
     }
7ebc05
 
7ebc05
@@ -1312,10 +1356,14 @@ process_remote_stonith_exec(xmlNode * msg)
7ebc05
          * Continue the topology if more devices exist at the current level, otherwise
7ebc05
          * mark as done. */
7ebc05
         if (rc == pcmk_ok) {
7ebc05
+            GListPtr required_match = g_list_find_custom(op->required_list, device, sort_strings);
7ebc05
             if (op->devices) {
7ebc05
                 /* Success, are there any more? */
7ebc05
                 op->devices = op->devices->next;
7ebc05
             }
7ebc05
+            if (required_match) {
7ebc05
+                op->required_list = g_list_remove(op->required_list, required_match->data);
7ebc05
+            }
7ebc05
             /* if no more devices at this fencing level, we are done,
7ebc05
              * else we need to contine with executing the next device in the list */
7ebc05
             if (op->devices == NULL) {
7ebc05
diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h
7ebc05
index 2822e9a..3625cf9 100644
7ebc05
--- a/include/crm/fencing/internal.h
7ebc05
+++ b/include/crm/fencing/internal.h
7ebc05
@@ -66,6 +66,8 @@ xmlNode *create_device_registration_xml(const char *id, const char *namespace, c
7ebc05
 /*! Has this device been verified using a monitor type
7ebc05
  *  operation (monitor, list, status) */
7ebc05
 #  define F_STONITH_DEVICE_VERIFIED   "st_monitor_verified"
7ebc05
+/*! device is required for this action */
7ebc05
+#  define F_STONITH_DEVICE_REQUIRED   "st_required"
7ebc05
 #  define F_STONITH_CALLBACK_TOKEN    "st_async_id"
7ebc05
 #  define F_STONITH_CLIENTNAME        "st_clientname"
7ebc05
 #  define F_STONITH_CLIENTNODE        "st_clientnode"