Blame SOURCES/pcmk-fencing_support_agents_that_need_the_host_to_be_unfenced_at_startup.patch

ed0026
commit 8af0d0c8aabe9ef6bb76c0e5032836d3c8bdc9d7
ed0026
Author: Andrew Beekhof <andrew@beekhof.net>
ed0026
Date:   Tue Aug 13 12:31:25 2013 +1000
ed0026
ed0026
    Feature: Fencing: Support agents that need the host to be unfenced at startup
ed0026
ed0026
diff --git a/fencing/commands.c b/fencing/commands.c
ed0026
index c7c1bf0..73a7fc1 100644
ed0026
--- a/fencing/commands.c
ed0026
+++ b/fencing/commands.c
ed0026
@@ -635,8 +635,9 @@ target_list_type(stonith_device_t * dev)
ed0026
     return check_type;
ed0026
 }
ed0026
 
ed0026
-static void
ed0026
-schedule_internal_command(stonith_device_t * device,
ed0026
+void
ed0026
+schedule_internal_command(const char *origin,
ed0026
+                          stonith_device_t * device,
ed0026
                           const char *action,
ed0026
                           const char *victim,
ed0026
                           int timeout,
ed0026
@@ -654,12 +655,12 @@ schedule_internal_command(stonith_device_t * device,
ed0026
     cmd->action = strdup(action);
ed0026
     cmd->victim = victim ? strdup(victim) : NULL;
ed0026
     cmd->device = strdup(device->id);
ed0026
-    cmd->origin = strdup("st_internal_cmd");
ed0026
-    cmd->client = strdup("st_internal_client");
ed0026
-    cmd->client_name = strdup("st_internal_client_name");
ed0026
+    cmd->origin = strdup(origin);
ed0026
+    cmd->client = strdup(crm_system_name);
ed0026
+    cmd->client_name = strdup(crm_system_name);
ed0026
 
ed0026
     cmd->internal_user_data = internal_user_data;
ed0026
-    cmd->done_cb = done_cb;
ed0026
+    cmd->done_cb = done_cb; /* cmd, not internal_user_data, is passed to 'done_cb' as the userdata */
ed0026
 
ed0026
     schedule_stonith_command(cmd, device);
ed0026
 }
ed0026
@@ -1093,9 +1094,7 @@ can_fence_host_with_device(stonith_device_t * dev, struct device_search_s *searc
ed0026
         time_t now = time(NULL);
ed0026
 
ed0026
         if (dev->targets == NULL || dev->targets_age + 60 < now) {
ed0026
-            schedule_internal_command(dev,
ed0026
-                                      "list",
ed0026
-                                      NULL,
ed0026
+            schedule_internal_command(__FUNCTION__, dev, "list", NULL,
ed0026
                                       search->per_device_timeout, search, dynamic_list_search_cb);
ed0026
 
ed0026
             /* we'll respond to this search request async in the cb */
ed0026
@@ -1107,9 +1106,7 @@ can_fence_host_with_device(stonith_device_t * dev, struct device_search_s *searc
ed0026
         }
ed0026
 
ed0026
     } else if (safe_str_eq(check_type, "status")) {
ed0026
-        schedule_internal_command(dev,
ed0026
-                                  "status",
ed0026
-                                  search->host,
ed0026
+        schedule_internal_command(__FUNCTION__, dev, "status", search->host,
ed0026
                                   search->per_device_timeout, search, status_search_cb);
ed0026
         /* we'll respond to this search request async in the cb */
ed0026
         return;
ed0026
@@ -1395,6 +1392,26 @@ stonith_send_async_reply(async_command_t * cmd, const char *output, int rc, GPid
ed0026
     free_xml(reply);
ed0026
 }
ed0026
 
ed0026
+void
ed0026
+unfence_cb(GPid pid, int rc, const char *output, gpointer user_data)
ed0026
+{
ed0026
+    async_command_t * cmd = user_data;
ed0026
+    stonith_device_t *dev = g_hash_table_lookup(device_list, cmd->device);
ed0026
+
ed0026
+    log_operation(cmd, rc, pid, NULL, output);
ed0026
+
ed0026
+    if(dev) {
ed0026
+        dev->active_pid = 0;
ed0026
+        mainloop_set_trigger(dev->work);
ed0026
+    } else {
ed0026
+        crm_trace("Device %s does not exist", cmd->device);
ed0026
+    }
ed0026
+
ed0026
+    if(rc != 0) {
ed0026
+        crm_exit(DAEMON_RESPAWN_STOP);
ed0026
+    }
ed0026
+}
ed0026
+
ed0026
 static void
ed0026
 cancel_stonith_command(async_command_t * cmd)
ed0026
 {
ed0026
diff --git a/fencing/internal.h b/fencing/internal.h
ed0026
index 737fc18..9a8b096 100644
ed0026
--- a/fencing/internal.h
ed0026
+++ b/fencing/internal.h
ed0026
@@ -162,6 +162,18 @@ bool fencing_peer_active(crm_node_t *peer);
ed0026
 
ed0026
 int stonith_manual_ack(xmlNode * msg, remote_fencing_op_t * op);
ed0026
 
ed0026
+void unfence_cb(GPid pid, int rc, const char *output, gpointer user_data);
ed0026
+
ed0026
+void
ed0026
+schedule_internal_command(const char *origin,
ed0026
+                          stonith_device_t * device,
ed0026
+                          const char *action,
ed0026
+                          const char *victim,
ed0026
+                          int timeout,
ed0026
+                          void *internal_user_data,
ed0026
+                          void (*done_cb) (GPid pid, int rc, const char *output,
ed0026
+                                           gpointer user_data));
ed0026
+
ed0026
 extern char *stonith_our_uname;
ed0026
 extern gboolean stand_alone;
ed0026
 extern GHashTable *device_list;
ed0026
diff --git a/fencing/main.c b/fencing/main.c
ed0026
index e002125..3fa7b5a 100644
ed0026
--- a/fencing/main.c
ed0026
+++ b/fencing/main.c
ed0026
@@ -573,6 +573,7 @@ fencing_topology_init(xmlNode * msg)
ed0026
 }
ed0026
 
ed0026
 #define rsc_name(x) x->clone_name?x->clone_name:x->id
ed0026
+static bool have_fence_scsi = FALSE;
ed0026
 
ed0026
 static void cib_device_update(resource_t *rsc, pe_working_set_t *data_set)
ed0026
 {
ed0026
@@ -661,6 +662,22 @@ static void cib_device_update(resource_t *rsc, pe_working_set_t *data_set)
ed0026
         data = create_device_registration_xml(rsc_name(rsc), provider, agent, params);
ed0026
         stonith_device_register(data, NULL, TRUE);
ed0026
 
ed0026
+        /* If required, unfence ourselves on cluster startup
ed0026
+         *
ed0026
+         * Make this generic/smarter if/when more than a single agent needs this
ed0026
+         */
ed0026
+        if(have_fence_scsi == FALSE && safe_str_eq(agent, "fence_scsi")) {
ed0026
+            stonith_device_t *device = g_hash_table_lookup(device_list, rsc->id);
ed0026
+
ed0026
+            if(device) {
ed0026
+                have_fence_scsi = TRUE;
ed0026
+                crm_notice("Unfencing ourselves with %s (%s)", agent, device->id);
ed0026
+                schedule_internal_command(__FUNCTION__, device, "on", stonith_our_uname, 0, NULL, unfence_cb);
ed0026
+            } else {
ed0026
+                crm_err("Device %s does not exist", rsc->id);
ed0026
+            }
ed0026
+        }
ed0026
+
ed0026
         stonith_key_value_freeall(params, 1, 1);
ed0026
         free_xml(data);
ed0026
     }