Blob Blame History Raw
commit 8af0d0c8aabe9ef6bb76c0e5032836d3c8bdc9d7
Author: Andrew Beekhof <andrew@beekhof.net>
Date:   Tue Aug 13 12:31:25 2013 +1000

    Feature: Fencing: Support agents that need the host to be unfenced at startup

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