public inbox for cluster-cvs@sourceware.org
help / color / mirror / Atom feed
* cluster: STABLE3 - fence_tool, init.d/cman: fix wait/retry options
@ 2009-03-17 18:39 David Teigland
0 siblings, 0 replies; only message in thread
From: David Teigland @ 2009-03-17 18:39 UTC (permalink / raw)
To: cluster-cvs-relay
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=f77f286c34c8cd0ac904528341c07f5b4370470a
Commit: f77f286c34c8cd0ac904528341c07f5b4370470a
Parent: 0eec7f7ae4eb29877631ad6ca4d50b8eb8b03bca
Author: David Teigland <teigland@redhat.com>
AuthorDate: Mon Mar 16 16:37:42 2009 -0500
Committer: David Teigland <teigland@redhat.com>
CommitterDate: Tue Mar 17 13:34:36 2009 -0500
fence_tool, init.d/cman: fix wait/retry options
Bring some sanity to the fence_tool ad hoc wait/retry options, which
are used by init.d/cman. At a high level we want:
. fence_tool join to fail right away, with an error, if cman or
fenced fail or aren't running
. fence_tool join to exit with 0 if the join succeeds and
with 1 if it fails
. do these things properly even when fenced is slow starting up,
or in processing the join
Signed-off-by: David Teigland <teigland@redhat.com>
---
cman/init.d/cman.in | 20 +--
fence/fence_tool/fence_tool.c | 335 +++++++++++++++++++++++++----------------
2 files changed, 215 insertions(+), 140 deletions(-)
diff --git a/cman/init.d/cman.in b/cman/init.d/cman.in
index 288c267..bbaec7a 100644
--- a/cman/init.d/cman.in
+++ b/cman/init.d/cman.in
@@ -92,12 +92,11 @@ fi
# are found in @NOTIFYDDIR@
[ -z "$CMAN_NOTIFYD_START" ] && CMAN_NOTIFYD_START=conditional
-# FENCED_START_TIMEOUT -- amount of time to wait for starting fenced
-# before giving up. If FENCED_START_TIMEOUT is positive, then we will
-# wait FENCED_START_TIMEOUT seconds before giving up and failing when
-# fenced does not start. If FENCED_START_TIMEOUT is zero, then
-# wait indefinately for fenced to start.
-[ -z "$FENCED_START_TIMEOUT" ] && FENCED_START_TIMEOUT=300
+# FENCE_JOIN_TIMEOUT -- seconds to wait for fence domain join to
+# complete. If the join hasn't completed in this time, fence_tool join
+# exits with an error, and this script exits with an error. To wait
+# indefinitely set the value to -1.
+[ -z "$FENCE_JOIN_TIMEOUT" ] && FENCE_JOIN_TIMEOUT=20
# NET_RMEM_DEFAULT -- minimum value for rmem_default. If this is set
# higher elsewhere it will not be reduced here.
@@ -299,11 +298,11 @@ start_fence()
@SBINDIR@/cman_tool status | grep Flags | grep 2node > /dev/null 2>&1
if [ $? -ne 0 ]
then
- errmsg=$( @SBINDIR@/fence_tool -w -t $FENCED_START_TIMEOUT join \
+ errmsg=$( @SBINDIR@/fence_tool join -w $FENCE_JOIN_TIMEOUT \
> /dev/null 2>&1 ) || return 1
else
- errmsg=$( @SBINDIR@/fence_tool -w -t $FENCED_START_TIMEOUT \
- -m $FENCED_MEMBER_DELAY join \
+ errmsg=$( @SBINDIR@/fence_tool join -w $FENCE_JOIN_TIMEOUT \
+ -m $FENCED_MEMBER_DELAY join \
> /dev/null 2>&1 ) || return 1
fi
return 0
@@ -590,9 +589,8 @@ stop_fence()
{
if pidof fenced > /dev/null 2>&1
then
- @SBINDIR@/fence_tool -w leave > /dev/null 2>&1
+ @SBINDIR@/fence_tool leave -w 10 > /dev/null 2>&1
rtrn=$?
- sleep 1 # A bit of time for fenced to exit
return $rtrn
fi
return 0 # all ok
diff --git a/fence/fence_tool/fence_tool.c b/fence/fence_tool/fence_tool.c
index 6e37444..45d3ff2 100644
--- a/fence/fence_tool/fence_tool.c
+++ b/fence/fence_tool/fence_tool.c
@@ -26,23 +26,28 @@
#define OP_LIST 3
#define OP_DUMP 4
-#define DEFAULT_WAIT_TIMEOUT 300 /* five minutes */
-
#define MAX_NODES 128
int all_nodeids[MAX_NODES];
int all_nodeids_count;
+cman_handle_t ch;
cman_node_t cman_nodes[MAX_NODES];
int cman_nodes_count;
struct fenced_node nodes[MAX_NODES];
char *prog_name;
int operation;
-int ls_all_nodes = 0;
-int inquorate_fail = 0;
-int wait_join = 0; /* default: don't wait for join */
-int wait_leave = 0; /* default: don't wait for leave */
-int wait_members = 0; /* default: don't wait for members */
-int wait_timeout = DEFAULT_WAIT_TIMEOUT;
+
+#define DEFAULT_RETRY_CMAN 0 /* fail immediately if we can't connect to cman */
+#define DEFAULT_DELAY_QUORUM 0
+#define DEFAULT_DELAY_MEMBERS 0
+#define DEFAULT_WAIT_JOINLEAVE 0
+
+int opt_all_nodes = 0;
+int opt_retry_cman = DEFAULT_RETRY_CMAN;
+int opt_delay_quorum = DEFAULT_DELAY_QUORUM;
+int opt_delay_members = DEFAULT_DELAY_MEMBERS;
+int opt_wait_joinleave = DEFAULT_WAIT_JOINLEAVE;
+
#define die(fmt, args...) \
do { \
@@ -70,19 +75,30 @@ static int do_write(int fd, void *buf, size_t count)
return 0;
}
-static int get_int_arg(char argopt, char *arg)
+#define LOCKFILE_NAME "/var/run/fenced.pid"
+
+static void check_fenced_running(void)
{
- char *tmp;
- int val;
-
- val = strtol(arg, &tmp, 10);
- if (tmp == arg || tmp != arg + strlen(arg))
- die("argument to %c (%s) is not an integer", argopt, arg);
-
- if (val < 0)
- die("argument to %c cannot be negative", argopt);
-
- return val;
+ struct flock lock;
+ int fd, rv;
+
+ fd = open(LOCKFILE_NAME, O_RDONLY);
+ if (fd < 0)
+ die("fenced not running, no lockfile");
+
+ lock.l_type = F_RDLCK;
+ lock.l_start = 0;
+ lock.l_whence= SEEK_SET;
+ lock.l_len = 0;
+
+ rv = fcntl(fd, F_GETLK, &lock);
+ if (rv < 0)
+ die("fenced not running, get lockfile");
+
+ if (lock.l_type == F_UNLCK)
+ die("fenced not running, unlocked lockfile");
+
+ close(fd);
}
static int check_gfs(void)
@@ -102,7 +118,7 @@ static int check_gfs(void)
if (sscanf(line, "%s %s %s", device, path, type) != 3)
continue;
if (!strcmp(type, "gfs") || !strcmp(type, "gfs2")) {
- printf("found %s file system mounted from %s on %s\n",
+ fprintf(stderr, "found %s file system mounted from %s on %s\n",
type, device, path);
count++;
}
@@ -131,7 +147,7 @@ static int check_controlled_dir(char *path)
continue;
#endif
- printf("found dlm lockspace %s/%s\n", path, de->d_name);
+ fprintf(stderr, "found dlm lockspace %s/%s\n", path, de->d_name);
count++;
}
@@ -177,6 +193,9 @@ static void wait_domain(int joining)
int in, tries = 0;
while (1) {
+ if (joining)
+ check_fenced_running();
+
in = we_are_in_fence_domain();
if (joining && in)
@@ -185,19 +204,25 @@ static void wait_domain(int joining)
if (!joining && !in)
break;
- if (tries++ >= wait_timeout)
- goto fail;
+ tries++;
- if (!(tries % 5))
- printf("Waiting for fenced to %s the fence group.\n",
- joining ? "join" : "leave");
+ if (opt_wait_joinleave < 0)
+ goto retry_domain;
+
+ if (!opt_wait_joinleave || tries >= opt_wait_joinleave) {
+ fprintf(stderr, "%s: %s not complete\n",
+ prog_name, joining ? "join" : "leave");
+ break;
+ }
+ retry_domain:
+ if (!(tries % 10))
+ fprintf(stderr, "%s: waiting for fenced to %s the fence group.\n",
+ prog_name, joining ? "join" : "leave");
sleep(1);
}
return;
- fail:
- printf("Error %s the fence group.\n", joining ? "joining" : "leaving");
}
static void read_ccs_nodeids(int cd)
@@ -223,7 +248,7 @@ static void read_ccs_nodeids(int cd)
}
}
-static int all_nodeids_are_members(cman_handle_t ch)
+static int all_nodeids_are_members(void)
{
int i, j, rv, found;
@@ -231,10 +256,8 @@ static int all_nodeids_are_members(cman_handle_t ch)
cman_nodes_count = 0;
rv = cman_get_nodes(ch, MAX_NODES, &cman_nodes_count, cman_nodes);
- if (rv < 0) {
- printf("cman_get_nodes error %d %d\n", rv, errno);
- return 0;
- }
+ if (rv < 0)
+ return -1;
for (i = 0; i < all_nodeids_count; i++) {
found = 0;
@@ -253,30 +276,25 @@ static int all_nodeids_are_members(cman_handle_t ch)
return 1;
}
-static void wait_cman(void)
+static int connect_cman(void)
{
- cman_handle_t ch;
- int try_init = 0, try_active = 0, try_quorate = 0;
- int try_ccs = 0, try_members = 0;
- int rv, cd;
+ int rv, tries = 0;
while (1) {
ch = cman_init(NULL);
if (ch)
break;
- if (inquorate_fail)
- goto fail;
-
- if (try_init++ >= wait_timeout) {
- printf("%s: timed out waiting for cman init\n",
- prog_name);
- goto fail;
- }
+ tries++;
- if (!(try_init % 10))
- printf("%s: waiting for cman to start\n", prog_name);
+ if (opt_retry_cman < 0)
+ goto retry_init;
+ if (!opt_retry_cman || tries >= opt_retry_cman)
+ return -1;
+ retry_init:
+ if (!(tries % 10))
+ fprintf(stderr, "%s: retrying cman connection\n", prog_name);
sleep(1);
}
@@ -285,97 +303,140 @@ static void wait_cman(void)
if (rv)
break;
- if (inquorate_fail)
- goto fail;
+ tries++;
- if (try_active++ >= wait_timeout) {
- printf("%s: timed out waiting for cman active\n",
- prog_name);
- goto fail;
- }
+ if (opt_retry_cman < 0)
+ goto retry_active;
- if (!(try_active % 10))
- printf("%s: waiting for cman active\n", prog_name);
+ if (!opt_retry_cman || tries >= opt_retry_cman) {
+ cman_finish(ch);
+ return -1;
+ }
+ retry_active:
+ if (!(tries % 10))
+ fprintf(stderr, "%s: retrying cman active check\n", prog_name);
sleep(1);
}
+ return 0;
+}
+
+static void delay_quorum(void)
+{
+ int rv, tries = 0;
+
while (1) {
rv = cman_is_quorate(ch);
if (rv)
break;
- if (inquorate_fail)
- goto fail;
-
- if (try_quorate++ >= wait_timeout) {
- printf("%s: timed out waiting for cman quorum\n",
- prog_name);
- goto fail;
+ rv = cman_is_active(ch);
+ if (!rv) {
+ cman_finish(ch);
+ die("lost cman connection");
}
+
+ tries++;
+
+ if (opt_delay_quorum < 0)
+ goto retry_quorum;
- if (!(try_quorate % 10))
- printf("%s: waiting for cman quorum\n", prog_name);
+ if (!opt_delay_quorum || tries >= opt_delay_quorum) {
+ fprintf(stderr, "%s: continuing without quorum\n", prog_name);
+ break;
+ }
+ retry_quorum:
+ if (!(tries % 10))
+ fprintf(stderr, "%s: delaying for quorum\n", prog_name);
sleep(1);
}
- while (1) {
- cd = ccs_connect();
- if (cd > 0)
- break;
-
- if (try_ccs++ >= wait_timeout) {
- printf("%s: timed out waiting for ccs connect\n",
- prog_name);
- goto fail;
- }
+ return;
+}
- if (!(try_ccs % 10))
- printf("%s: waiting for ccs connect\n", prog_name);
+static void delay_members(void)
+{
+ int rv, tries = 0;
+ int cd;
- sleep(1);
+ cd = ccs_connect();
+ if (cd < 0) {
+ cman_finish(ch);
+ die("lost cman/ccs connection");
}
- if (!wait_members)
- goto out;
read_ccs_nodeids(cd);
while (1) {
- rv = all_nodeids_are_members(ch);
+ rv = all_nodeids_are_members();
+ if (rv < 0) {
+ ccs_disconnect(cd);
+ cman_finish(ch);
+ die("lost cman connection");
+ }
if (rv)
break;
- if (try_members++ >= wait_members)
+ tries++;
+
+ if (opt_delay_members < 0)
+ goto retry_members;
+
+ if (!opt_delay_members || tries > opt_delay_members) {
+ fprintf(stderr, "%s: continuing without all members\n", prog_name);
break;
+ }
+ retry_members:
+ if (!(tries % 10))
+ fprintf(stderr, "%s: delaying for members\n", prog_name);
- if (!(try_members % 10))
- printf("%s: waiting for all %d nodes to be members\n",
- prog_name, all_nodeids_count);
sleep(1);
}
- out:
ccs_disconnect(cd);
- cman_finish(ch);
return;
-
- fail:
- if (ch)
- cman_finish(ch);
- exit(EXIT_FAILURE);
}
static void do_join(int argc, char *argv[])
{
- int rv;
-
- wait_cman();
+ int rv, tries = 0;
- rv = fenced_join();
+ rv = connect_cman();
if (rv < 0)
- die("can't communicate with fenced");
+ die("can't connect to cman");
+
+ /* if delay_quorum() or delay_members() fail on any cman/ccs
+ connection or operation, they call cman_finish() and exit
+ with failure */
+
+ if (opt_delay_quorum)
+ delay_quorum();
+
+ if (opt_delay_members)
+ delay_members();
+
+ cman_finish(ch);
+
+ /* This loop deals with the case where fenced is slow enough starting
+ up that fenced_join fails. Do we also want to add a delay here to
+ deal with the case where fenced is so slow starting up that it hasn't
+ locked its lockfile yet, causing check_fenced_running to fail? */
- if (wait_join)
+ while (1) {
+ rv = fenced_join();
+ if (!rv)
+ break;
+
+ check_fenced_running();
+
+ tries++;
+ if (!(tries % 10))
+ fprintf(stderr, "%s: retrying join\n", prog_name);
+ sleep(1);
+ }
+
+ if (opt_wait_joinleave)
wait_domain(1);
exit(EXIT_SUCCESS);
@@ -389,9 +450,9 @@ static void do_leave(void)
rv = fenced_leave();
if (rv < 0)
- die("can't communicate with fenced");
+ die("leave: can't communicate with fenced");
- if (wait_leave)
+ if (opt_wait_joinleave)
wait_domain(0);
exit(EXIT_SUCCESS);
@@ -404,7 +465,7 @@ static void do_dump(void)
rv = fenced_dump_debug(buf);
if (rv < 0)
- die("can't communicate with fenced");
+ die("dump: can't communicate with fenced");
do_write(STDOUT_FILENO, buf, strlen(buf));
@@ -500,7 +561,7 @@ static int do_list(void)
}
printf("\n");
- if (!ls_all_nodes) {
+ if (!opt_all_nodes) {
printf("\n");
exit(EXIT_SUCCESS);
}
@@ -539,27 +600,40 @@ static void print_usage(void)
{
printf("Usage:\n");
printf("\n");
- printf("%s <join|leave|dump> [options]\n", prog_name);
+ printf("%s <ls|join|leave|dump> [options]\n", prog_name);
printf("\n");
printf("Actions:\n");
+ printf(" ls List nodes status\n");
printf(" join Join the default fence domain\n");
printf(" leave Leave default fence domain\n");
- printf(" ls List nodes status\n");
printf(" dump Dump debug buffer from fenced\n");
printf("\n");
printf("Options:\n");
printf(" -n Show all node information in ls\n");
+
+ printf(" -t <seconds> Retry cman connection for <seconds>.\n");
+ printf(" Default %d. 0 no retry, -1 indefinite retry.\n",
+ DEFAULT_RETRY_CMAN);
+
+ printf(" -q <seconds> Delay join up to <seconds> for the cluster to have quorum.\n");
+ printf(" Default %d. 0 no delay, -1 indefinite delay.\n",
+ DEFAULT_DELAY_QUORUM);
+
printf(" -m <seconds> Delay join up to <seconds> for all nodes in cluster.conf\n");
- printf(" to be cluster members\n");
- printf(" -w Wait for join or leave to complete\n");
- printf(" -t <seconds> Maximum time in seconds to wait (default %d)\n", DEFAULT_WAIT_TIMEOUT);
- printf(" -Q Fail if cluster is not quorate, don't wait\n");
+ printf(" to be cluster members.\n");
+ printf(" Default %d. 0 no delay, -1 indefinite delay\n",
+ DEFAULT_DELAY_MEMBERS);
+
+ printf(" -w <seconds> Wait up to <seconds> for join or leave result.\n");
+ printf(" Default %d. 0 no wait, -1 indefinite wait.\n",
+ DEFAULT_WAIT_JOINLEAVE);
+
printf(" -V Print program version information, then exit\n");
printf(" -h Print this help, then exit\n");
printf("\n");
}
-#define OPTION_STRING "Vht:wQm:n"
+#define OPTION_STRING "nt:q:m:w:Vh"
static void decode_arguments(int argc, char *argv[])
{
@@ -571,37 +645,36 @@ static void decode_arguments(int argc, char *argv[])
switch (optchar) {
- case 'V':
- printf("fence_tool %s (built %s %s)\n",
- RELEASE_VERSION, __DATE__, __TIME__);
- printf("%s\n", REDHAT_COPYRIGHT);
- exit(EXIT_SUCCESS);
+ case 'n':
+ opt_all_nodes = 1;
break;
- case 'n':
- ls_all_nodes = 1;
+ case 't':
+ opt_retry_cman = atoi(optarg);
break;
- case 'h':
- print_usage();
- exit(EXIT_SUCCESS);
+ case 'q':
+ opt_delay_quorum = atoi(optarg);
break;
- case 'Q':
- inquorate_fail = 1;
+ case 'm':
+ opt_delay_members = atoi(optarg);
break;
case 'w':
- wait_join = 1;
- wait_leave = 1;
+ opt_wait_joinleave = atoi(optarg);
break;
- case 'm':
- wait_members = atoi(optarg);
+ case 'V':
+ printf("fence_tool %s (built %s %s)\n",
+ RELEASE_VERSION, __DATE__, __TIME__);
+ printf("%s\n", REDHAT_COPYRIGHT);
+ exit(EXIT_SUCCESS);
break;
- case 't':
- wait_timeout = get_int_arg(optchar, optarg);
+ case 'h':
+ print_usage();
+ exit(EXIT_SUCCESS);
break;
case ':':
@@ -647,12 +720,16 @@ int main(int argc, char *argv[])
switch (operation) {
case OP_JOIN:
do_join(argc, argv);
+ break;
case OP_LEAVE:
do_leave();
+ break;
case OP_DUMP:
do_dump();
+ break;
case OP_LIST:
do_list();
+ break;
}
return EXIT_FAILURE;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2009-03-17 18:39 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-17 18:39 cluster: STABLE3 - fence_tool, init.d/cman: fix wait/retry options 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).