public inbox for cluster-cvs@sourceware.org
help / color / mirror / Atom feed
* cluster: STABLE3 - libfence/fence_node: unfencing
@ 2009-02-25 22:53 David Teigland
0 siblings, 0 replies; only message in thread
From: David Teigland @ 2009-02-25 22:53 UTC (permalink / raw)
To: cluster-cvs-relay
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=9ad630fd9402c1820d758ed12f41bceb8a12eeb6
Commit: 9ad630fd9402c1820d758ed12f41bceb8a12eeb6
Parent: a934a873dc5f2d28c4e0dd3e696177048aa8196a
Author: David Teigland <teigland@redhat.com>
AuthorDate: Wed Feb 25 16:43:42 2009 -0600
Committer: David Teigland <teigland@redhat.com>
CommitterDate: Wed Feb 25 16:43:42 2009 -0600
libfence/fence_node: unfencing
The new libfence unfence_node() function looks for per node <unfence>
sections. The <unfence> section contains no methods, only devices.
unfence_node() attempts all devices in the unfence section, regardless
of whether any fail. The function returns success only if all devices
were successful.
The <device> line within <unfence> would typically require action="on"
or similar, to tell the agent to do the reverse of normal fencing.
The arg string for agents are constructed in the same was as for fencing:
the combination of the per-node unfence/device args and the fencedevice
args.
The fence_node command has a new -U option that causes it to call
unfence_node() rather than fence_node().
Signed-off-by: David Teigland <teigland@redhat.com>
---
fence/fence_node/fence_node.c | 40 +++++---
fence/libfence/agent.c | 220 +++++++++++++++++++++++++++++++++++++++++
fence/libfence/libfence.h | 3 +
3 files changed, 248 insertions(+), 15 deletions(-)
diff --git a/fence/fence_node/fence_node.c b/fence/fence_node/fence_node.c
index 21a9ba2..6cb15e7 100644
--- a/fence/fence_node/fence_node.c
+++ b/fence/fence_node/fence_node.c
@@ -11,12 +11,14 @@
static char *prog_name;
static int verbose;
+static int unfence;
#define FL_SIZE 32
static struct fence_log log[FL_SIZE];
static int log_count;
+static char *action = "fence";
-#define OPTION_STRING "hvV"
+#define OPTION_STRING "UvhV"
#define die(fmt, args...) \
do \
@@ -35,6 +37,7 @@ static void print_usage(void)
printf("\n");
printf("Options:\n");
printf("\n");
+ printf(" -U Unfence the node\n");
printf(" -v Show fence agent results, -vv for agent args\n");
printf(" -h Print this help, then exit\n");
printf(" -V Print program version information, then exit\n");
@@ -72,7 +75,7 @@ static char *fe_str(int r)
int main(int argc, char *argv[])
{
char *victim = NULL, *p;
- int cont = 1, optchar, error, rv, i;
+ int cont = 1, optchar, error, rv, i, c;
prog_name = argv[0];
@@ -81,6 +84,11 @@ int main(int argc, char *argv[])
switch (optchar) {
+ case 'U':
+ unfence = 1;
+ action = "unfence";
+ break;
+
case 'v':
verbose++;
break;
@@ -126,7 +134,10 @@ int main(int argc, char *argv[])
memset(&log, 0, sizeof(log));
log_count = 0;
- error = fence_node(victim, log, FL_SIZE, &log_count);
+ if (unfence)
+ error = unfence_node(victim, log, FL_SIZE, &log_count);
+ else
+ error = fence_node(victim, log, FL_SIZE, &log_count);
logt_init("fence_node", LOG_MODE_OUTPUT_SYSLOG, SYSLOGFACILITY,
SYSLOGLEVEL, 0, NULL);
@@ -135,35 +146,34 @@ int main(int argc, char *argv[])
goto skip;
if (log_count > FL_SIZE) {
- fprintf(stderr, "fence_node log overflow %d", log_count);
+ fprintf(stderr, "%s_node log overflow %d", action, log_count);
log_count = FL_SIZE;
}
for (i = 0; i < log_count; i++) {
- fprintf(stderr, "fence %s dev %d.%d agent %s result: %s\n",
- victim, log[i].method_num, log[i].device_num,
+ fprintf(stderr, "%s %s dev %d.%d agent %s result: %s\n",
+ action, victim, log[i].method_num, log[i].device_num,
log[i].agent_name[0] ? log[i].agent_name : "none",
fe_str(log[i].error));
if (verbose < 2)
continue;
- p = strchr(log[i].agent_args, '\n');
- if (p)
- *p = '\0';
+ for (c = 0; c < strlen(log[i].agent_args); c++) {
+ if (log[i].agent_args[c] == '\n')
+ log[i].agent_args[c] = ' ';
+ }
fprintf(stderr, "agent args: %s\n", log[i].agent_args);
}
skip:
if (error) {
- fprintf(stderr, "Fence of \"%s\" was unsuccessful\n", victim);
- logt_print(LOG_ERR, "Fence of \"%s\" was unsuccessful\n",
- victim);
+ fprintf(stderr, "%s %s failed\n", action, victim);
+ logt_print(LOG_ERR, "%s %s failed\n", action, victim);
rv = EXIT_FAILURE;
} else {
- fprintf(stderr, "Fence of \"%s\" was successful\n", victim);
- logt_print(LOG_NOTICE, "Fence of \"%s\" was successful\n",
- victim);
+ fprintf(stderr, "%s %s success\n", action, victim);
+ logt_print(LOG_ERR, "%s %s success\n", action, victim);
rv = EXIT_SUCCESS;
/* Tell fenced what we've done so that it can avoid fencing
diff --git a/fence/libfence/agent.c b/fence/libfence/agent.c
index 51e9371..148be3c 100644
--- a/fence/libfence/agent.c
+++ b/fence/libfence/agent.c
@@ -396,3 +396,223 @@ int fence_node(char *victim, struct fence_log *log, int log_size,
*log_count = count;
return error;
}
+
+#define UN_DEVICE_NAME_PATH "/cluster/clusternodes/clusternode[@name=\"%s\"]/unfence/device[%d]/@name"
+#define UN_NODE_FENCE_ARGS_PATH "/cluster/clusternodes/clusternode[@name=\"%s\"]/unfence/device[%d]/@*"
+
+static int make_args_unfence(int cd, char *victim, int d,
+ char *device, char **args_out)
+{
+ char path[PATH_MAX], *args, *str;
+ int error, cnt = 0;
+
+ args = malloc(FENCE_AGENT_ARGS_MAX);
+ if (!args)
+ return -ENOMEM;
+ memset(args, 0, FENCE_AGENT_ARGS_MAX);
+
+ /* node-specific args for victim */
+
+ memset(path, 0, PATH_MAX);
+ sprintf(path, UN_NODE_FENCE_ARGS_PATH, victim, d+1);
+
+ for (;;) {
+ error = ccs_get_list(cd, path, &str);
+ if (error || !str)
+ break;
+ ++cnt;
+
+ if (!strncmp(str, "name=", 5)) {
+ free(str);
+ continue;
+ }
+
+ strcat(args, str);
+ strcat(args, "\n");
+ free(str);
+ }
+
+ /* device-specific args */
+
+ memset(path, 0, PATH_MAX);
+ sprintf(path, FENCE_DEVICE_ARGS_PATH, device);
+
+ for (;;) {
+ error = ccs_get_list(cd, path, &str);
+ if (error || !str)
+ break;
+ ++cnt;
+
+ if (!strncmp(str, "name=", 5)) {
+ free(str);
+ continue;
+ }
+
+ strcat(args, str);
+ strcat(args, "\n");
+ free(str);
+ }
+
+ if (cnt)
+ error = 0;
+ if (error) {
+ free(args);
+ args = NULL;
+ }
+
+ *args_out = args;
+ return error;
+}
+
+/* return name of d'th device under nodes/<victim>/unfence/ */
+
+static int get_device_unfence(int cd, char *victim, int d, char **device)
+{
+ char path[PATH_MAX], *str = NULL;
+ int error;
+
+ memset(path, 0, PATH_MAX);
+ sprintf(path, UN_DEVICE_NAME_PATH, victim, d+1);
+
+ error = ccs_get(cd, path, &str);
+ *device = str;
+ return error;
+}
+
+static int count_devices_unfence(int cd, char *victim)
+{
+ char path[PATH_MAX], *name;
+ int error, i;
+
+ for (i = 0; i < MAX_DEVICES; i++) {
+ memset(path, 0, PATH_MAX);
+ sprintf(path, UN_DEVICE_NAME_PATH, victim, i+1);
+
+ error = ccs_get(cd, path, &name);
+ if (error)
+ break;
+ free(name);
+ }
+ return i;
+}
+
+static int use_device_unfence(int cd, char *victim, int d,
+ char *device, struct fence_log *lp)
+{
+ char path[PATH_MAX], *agent, *args = NULL;
+ int error;
+
+ memset(path, 0, PATH_MAX);
+ sprintf(path, AGENT_NAME_PATH, device);
+
+ error = ccs_get(cd, path, &agent);
+ if (error) {
+ lp->error = FE_READ_AGENT;
+ goto out;
+ }
+
+ strncpy(lp->agent_name, agent, FENCE_AGENT_NAME_MAX);
+
+ error = make_args_unfence(cd, victim, d, device, &args);
+ if (error) {
+ lp->error = FE_READ_ARGS;
+ goto out_agent;
+ }
+
+ strncpy(lp->agent_args, args, FENCE_AGENT_ARGS_MAX);
+
+ error = run_agent(agent, args, &lp->error);
+
+ free(args);
+ out_agent:
+ free(agent);
+ out:
+ return error;
+}
+
+int unfence_node(char *victim, struct fence_log *log, int log_size,
+ int *log_count)
+{
+ struct fence_log stub;
+ struct fence_log *lp = log;
+ char *device = NULL;
+ char *victim_nodename = NULL;
+ int num_devices, d, cd, rv;
+ int left = log_size;
+ int error = -1;
+ int count = 0;
+
+ cd = ccs_connect();
+ if (cd < 0) {
+ if (lp && left) {
+ lp->error = FE_NO_CONFIG;
+ lp++;
+ left--;
+ }
+ count++;
+ error = -1;
+ goto ret;
+ }
+
+ if (ccs_lookup_nodename(cd, victim, &victim_nodename) == 0)
+ victim = victim_nodename;
+
+ num_devices = count_devices_unfence(cd, victim);
+ if (!num_devices) {
+ if (lp && left) {
+ lp->error = FE_NO_DEVICE;
+ lp++;
+ left--;
+ }
+ count++;
+ error = -1;
+ goto out;
+ }
+
+ /* try to unfence all devices even if some of them fail,
+ but the final return value is 0 only if all succeed */
+
+ for (d = 0; d < num_devices; d++) {
+ rv = get_device_unfence(cd, victim, d, &device);
+ if (rv) {
+ if (lp && left) {
+ lp->error = FE_READ_DEVICE;
+ lp->device_num = d;
+ lp++;
+ left--;
+ }
+ count++;
+ error = -1;
+ continue;
+ }
+
+ /* every call to use_device generates a log entry,
+ whether success or fail */
+
+ rv = use_device_unfence(cd, victim, d, device,
+ (lp && left) ? lp : &stub);
+ count++;
+ if (lp && left) {
+ /* error, name, args already set */
+ lp->device_num = d;
+ lp++;
+ left--;
+ }
+
+ if (rv)
+ error = -1;
+
+ free(device);
+ device = NULL;
+ }
+
+ if (victim_nodename)
+ free(victim_nodename);
+ out:
+ ccs_disconnect(cd);
+ ret:
+ if (log_count)
+ *log_count = count;
+ return error;
+}
+
diff --git a/fence/libfence/libfence.h b/fence/libfence/libfence.h
index 677041d..e3d2148 100644
--- a/fence/libfence/libfence.h
+++ b/fence/libfence/libfence.h
@@ -29,6 +29,9 @@ struct fence_log {
int fence_node(char *name, struct fence_log *log, int log_size, int *log_count);
+int unfence_node(char *name, struct fence_log *log, int log_size,
+ int *log_count);
+
#ifdef __cplusplus
}
#endif
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2009-02-25 22:53 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-25 22:53 cluster: STABLE3 - libfence/fence_node: unfencing David Teigland
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).