File bug-938545_pacemaker-fencing-concurrent-fencing.patch of Package pacemaker.3577
commit 7c63f4cb17ffe7cb1c806c3d855b5f2f3ce91cbb
Author: Gao,Yan <ygao@suse.com>
Date: Thu Sep 10 14:29:25 2015 +0200
Feature: fencing: Support concurrent fencing actions on each device
A "pcmk_action_limit" parameter can be configured for a fencing resource to
specify the maximum number of actions can be performed in parallel on
this device. It defaults to "1". "-1" is unlimited.
diff --git a/fencing/commands.c b/fencing/commands.c
index adf655b..6bafb83 100644
--- a/fencing/commands.c
+++ b/fencing/commands.c
@@ -252,6 +252,24 @@ create_async_command(xmlNode * msg)
return cmd;
}
+static int
+get_action_limit(stonith_device_t * device)
+{
+ const char *value = NULL;
+ int action_limit = 1;
+
+ value = g_hash_table_lookup(device->params, STONITH_ATTR_ACTION_LIMIT);
+ if (value) {
+ action_limit = crm_parse_int(value, "1");
+ if (action_limit == 0) {
+ /* pcmk_action_limit should not be 0. Enforce it to be 1. */
+ action_limit = 1;
+ }
+ }
+
+ return action_limit;
+}
+
static gboolean
stonith_device_execute(stonith_device_t * device)
{
@@ -259,11 +277,16 @@ stonith_device_execute(stonith_device_t * device)
const char *action_str = NULL;
async_command_t *cmd = NULL;
stonith_action_t *action = NULL;
+ guint active_pids = 0;
+ int action_limit = 0;
CRM_CHECK(device != NULL, return FALSE);
- if (device->active_pid) {
- crm_trace("%s is still active with pid %u", device->id, device->active_pid);
+ active_pids = g_list_length(device->active_pids);
+ action_limit = get_action_limit(device);
+ if (action_limit > -1 && active_pids >= action_limit) {
+ crm_trace("%s is over its action limit of %d (%u active pid%s)",
+ device->id, action_limit, active_pids, active_pids > 1 ? "s" : "");
return TRUE;
}
@@ -340,7 +363,7 @@ stonith_device_execute(stonith_device_t * device)
crm_debug("Operation %s%s%s on %s now running with pid=%d, timeout=%ds",
cmd->action, cmd->victim ? " for node " : "", cmd->victim ? cmd->victim : "",
device->id, exec_rc, cmd->timeout);
- device->active_pid = exec_rc;
+ device->active_pids = g_list_append(device->active_pids, GINT_TO_POINTER(exec_rc));
} else {
crm_warn("Operation %s%s%s on %s failed: %s (%d)",
@@ -431,6 +454,7 @@ free_device(gpointer data)
free_async_command(cmd);
}
g_list_free(device->pending_ops);
+ g_list_free(device->active_pids);
g_list_free_full(device->targets, free);
@@ -873,7 +897,7 @@ status_search_cb(GPid pid, int rc, const char *output, gpointer user_data)
return;
}
- dev->active_pid = 0;
+ dev->active_pids = g_list_remove(dev->active_pids, GINT_TO_POINTER(pid));
mainloop_set_trigger(dev->work);
if (rc == 1 /* unknown */ ) {
@@ -910,7 +934,7 @@ dynamic_list_search_cb(GPid pid, int rc, const char *output, gpointer user_data)
return;
}
- dev->active_pid = 0;
+ dev->active_pids = g_list_remove(dev->active_pids, GINT_TO_POINTER(pid));
mainloop_set_trigger(dev->work);
/* If we successfully got the targets earlier, don't disable. */
@@ -1771,7 +1795,7 @@ unfence_cb(GPid pid, int rc, const char *output, gpointer user_data)
log_operation(cmd, rc, pid, NULL, output);
if(dev) {
- dev->active_pid = 0;
+ dev->active_pids = g_list_remove(dev->active_pids, GINT_TO_POINTER(pid));
mainloop_set_trigger(dev->work);
} else {
crm_trace("Device %s does not exist", cmd->device);
@@ -1816,7 +1840,7 @@ st_child_done(GPid pid, int rc, const char *output, gpointer user_data)
/* The device is ready to do something else now */
device = g_hash_table_lookup(device_list, cmd->device);
if (device) {
- device->active_pid = 0;
+ device->active_pids = g_list_remove(device->active_pids, GINT_TO_POINTER(pid));
if (rc == pcmk_ok &&
(safe_str_eq(cmd->action, "list") ||
safe_str_eq(cmd->action, "monitor") || safe_str_eq(cmd->action, "status"))) {
diff --git a/fencing/internal.h b/fencing/internal.h
index 3fc75ec..d7140cb 100644
--- a/fencing/internal.h
+++ b/fencing/internal.h
@@ -34,7 +34,7 @@ typedef struct stonith_device_s {
/* whether the cluster should automatically unfence nodes with the device */
gboolean automatic_unfencing;
guint priority;
- guint active_pid;
+ GListPtr active_pids;
enum st_device_flags flags;
diff --git a/fencing/main.c b/fencing/main.c
index 43d2cb3..86a36ef 100644
--- a/fencing/main.c
+++ b/fencing/main.c
@@ -1405,6 +1405,16 @@ main(int argc, char **argv)
printf(" <content type=\"time\" default=\"0s\"/>\n");
printf(" </parameter>\n");
+ printf(" <parameter name=\"%s\" unique=\"0\">\n", STONITH_ATTR_ACTION_LIMIT);
+ printf
+ (" <shortdesc lang=\"en\">The maximum number of actions can be performed in parallel on this device</shortdesc>\n");
+ printf
+ (" <longdesc lang=\"en\">Pengine property concurrent-fencing=true needs to be configured first.\n"
+ "Then use this to specify the maximum number of actions can be performed in parallel on this device. -1 is unlimited.</longdesc>\n");
+ printf(" <content type=\"integer\" default=\"1\"/>\n");
+ printf(" </parameter>\n");
+
+
for (lpc = 0; lpc < DIMOF(actions); lpc++) {
printf(" <parameter name=\"pcmk_%s_action\" unique=\"0\">\n", actions[lpc]);
printf
diff --git a/include/crm/fencing/internal.h b/include/crm/fencing/internal.h
index a59151b..73169aa 100644
--- a/include/crm/fencing/internal.h
+++ b/include/crm/fencing/internal.h
@@ -110,6 +110,7 @@ xmlNode *create_device_registration_xml(const char *id, const char *namespace, c
# define STONITH_ATTR_HOSTLIST "pcmk_host_list"
# define STONITH_ATTR_HOSTCHECK "pcmk_host_check"
# define STONITH_ATTR_DELAY_MAX "pcmk_delay_max"
+# define STONITH_ATTR_ACTION_LIMIT "pcmk_action_limit"
# define STONITH_ATTR_ACTION_OP "action"