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);
}