Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=8d…
Commit: 8d94f0871db6236ac3caa366560578976477d0eb
Parent: 1837d87a8548f2244db2634897ad831d90217a44
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Mon Dec 6 15:01:55 2010 -0500
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Fri Apr 8 09:31:15 2011 -0400
cman: Don't increment on LEAVING->MEMBER transition
If a node left the cluster prior using 'cman_tool leave', its
internal state is set to NODESTATE_LEAVING.
Ordinarily, during the transition from NODESTATE_LEAVING to
NODESTATE_DEAD, the member count is decremented. However, it
is possible to rejoin the cluster membership from the
NODESTATE_LEAVING state.
If this occurs, the cluster member count is incremented, but
since the node never transitioned from LEAVING->DEAD, it was
not previously decremented, causing an ever-increasing node
count in 'cman_tool status'.
This patch resolves the issue by not incrementing the member
count during a LEAVING->MEMBER transition.
Resolves: rhbz#649533
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
Reviewed-by: Fabio M. Di Nitto <fdinitto(a)redhat.com>
Reviewed-by: Christine Caulfield <ccaulfie(a)redhat.com>
---
cman/daemon/commands.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/cman/daemon/commands.c b/cman/daemon/commands.c
index 6ffe9e5..6c91d7a 100644
--- a/cman/daemon/commands.c
+++ b/cman/daemon/commands.c
@@ -1994,9 +1994,12 @@ void add_ais_node(int nodeid, uint64_t incarnation, int total_members)
if (node->state == NODESTATE_DEAD || node->state == NODESTATE_LEAVING) {
gettimeofday(&node->join_time, NULL);
+ /* If a node rejoins before it completes a leave,
+ * we should not increment cluster_members */
+ if (node->state != NODESTATE_LEAVING)
+ cluster_members++;
node->incarnation = incarnation;
node->state = NODESTATE_MEMBER;
- cluster_members++;
recalculate_quorum(0, 0);
}
}
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=18…
Commit: 1837d87a8548f2244db2634897ad831d90217a44
Parent: 8a36ef759c422205d282e2f5543e8a76b00eb847
Author: Shane Bradley <sbradley(a)redhat.com>
AuthorDate: Thu Apr 7 09:59:51 2011 -0400
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Fri Apr 8 09:31:15 2011 -0400
cman: Clarify 'expected' option
Resolves: rhbz#688701
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
Reviewed-by: Fabio M. Di Nitto <fdinitto(a)redhat.com>
---
cman/man/cman_tool.8 | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/cman/man/cman_tool.8 b/cman/man/cman_tool.8
index 554a316..71e1841 100644
--- a/cman/man/cman_tool.8
+++ b/cman/man/cman_tool.8
@@ -58,6 +58,12 @@ version of "leave force" so only use if if you really know what you are doing.
Tells CMAN a new value of expected votes and instructs it to recalculate
quorum based on this value.
.br
+The recalculation takes into account the number of currently
+active nodes, so this option should not be used in an attempt to
+artificially lower the quorum value in advance of a planned shutdown of
+cluster nodes. Instead, the 'cman_tool leave remove' command should be
+used (see the 'leave' subcommand above).
+.br
Use this option if your cluster has lost quorum due to nodes failing and
you need to get it running again in a hurry.
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=07…
Commit: 079f56ecb56b0d53b44b1871fa8937c22981fc1e
Parent: 1d56164f2dea0772188696a8578a4144c8379885
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Thu Apr 7 16:01:58 2011 -0400
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Thu Apr 7 16:51:00 2011 -0400
rgmanager: Pause during exit if we stopped services
A difference between rgmanager 1.9.x and later versions is that
they rely on openais/corosync for messaging. This messaging is
quite reliable and has proved useful.
However, one drawback is that if you very quickly stop rgmanager
and corosync/cman, the other nodes in the cluster can not restart
services because message traffic is interrupted for the duration
of the token timeout.
There is no simple solution to this problem. Rgmanager could
(in theory) find new placements for services prior to stopping,
but this is a large amount of design work; it was never designed
to run policies in the exit path.
A far simpler idea is to simply give the other nodes time to
restart services.
NOTE: This solution does not and can not work with central
processing mode.
Resolves: rhbz#619468
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
rgmanager/include/event.h | 1 +
rgmanager/include/groups.h | 2 +-
rgmanager/src/daemons/groups.c | 12 +++++++++++-
rgmanager/src/daemons/main.c | 15 ++++++++++++---
rgmanager/src/daemons/rg_event.c | 7 +++++++
5 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/rgmanager/include/event.h b/rgmanager/include/event.h
index ad3fe39..9fc9521 100644
--- a/rgmanager/include/event.h
+++ b/rgmanager/include/event.h
@@ -119,6 +119,7 @@ int slang_process_event(event_table_t *event_table, event_t *ev);
/* For distributed events. */
void set_transition_throttling(int nsecs);
+int get_transition_throttling(void);
/* Simplified service start. */
int service_op_start(char *svcName, int *target_list, int target_list_len,
diff --git a/rgmanager/include/groups.h b/rgmanager/include/groups.h
index f776a31..f02f0e2 100644
--- a/rgmanager/include/groups.h
+++ b/rgmanager/include/groups.h
@@ -25,7 +25,7 @@ void kill_resource_groups(void);
/* do this op on all resource groups. The handler for the request
will sort out whether or not it's a valid request given the state */
-void rg_doall(int request, int block, const char *debugfmt);
+int rg_doall(int request, int block, const char *debugfmt);
void do_status_checks(void); /* Queue status checks for locally running
services */
diff --git a/rgmanager/src/daemons/groups.c b/rgmanager/src/daemons/groups.c
index ec8ab63..e9413cd 100644
--- a/rgmanager/src/daemons/groups.c
+++ b/rgmanager/src/daemons/groups.c
@@ -1276,13 +1276,21 @@ svc_exists(const char *svcname)
}
-void
+/*
+ * Perform an operation on all resources groups.
+ *
+ * Returns the number of requests queued. This value is
+ * only used during shutdown, where we queue RG_STOP_EXITING
+ * only for services we have running locally as an optimization.
+ */
+int
rg_doall(int request, int block,
const char __attribute__ ((unused)) *debugfmt)
{
resource_node_t *curr;
rg_state_t svcblk;
char rg[64];
+ int queued = 0;
pthread_rwlock_rdlock(&resource_lock);
list_do(&_tree, curr) {
@@ -1307,6 +1315,7 @@ rg_doall(int request, int block,
rt_enqueue_request(rg, request, NULL, 0,
0, 0, 0);
+ ++queued;
} while (!list_done(&_tree, curr));
pthread_rwlock_unlock(&resource_lock);
@@ -1316,6 +1325,7 @@ rg_doall(int request, int block,
other rgmanagers to complete. */
if (block)
rg_wait_threads();
+ return queued;
}
diff --git a/rgmanager/src/daemons/main.c b/rgmanager/src/daemons/main.c
index 02cd2dc..a3ab7c4 100644
--- a/rgmanager/src/daemons/main.c
+++ b/rgmanager/src/daemons/main.c
@@ -29,7 +29,6 @@
void dump_thread_states(FILE *);
#endif
static int configure_rgmanager(int ccsfd, int debug, int *cluster_timeout);
-void set_transition_throttling(int);
void flag_shutdown(int sig);
@@ -43,6 +42,7 @@ static int signalled = 0;
static uint8_t ALIGNED port = RG_PORT;
static char *rgmanager_lsname = (char *)"rgmanager"; /* XXX default */
static int status_poll_interval = DEFAULT_CHECK_INTERVAL;
+static int stops_queued = 0;
static void
segfault(int __attribute__ ((unused)) sig)
@@ -930,7 +930,7 @@ static void *
shutdown_thread(void __attribute__ ((unused)) *arg)
{
rg_lockall(L_SYS|L_SHUTDOWN);
- rg_doall(RG_STOP_EXITING, 1, NULL);
+ stops_queued = rg_doall(RG_STOP_EXITING, 1, NULL);
running = 0;
pthread_exit(NULL);
@@ -1119,8 +1119,17 @@ out_ls:
out:
rgm_dbus_release();
- logt_print(LOG_NOTICE, "Shutdown complete, exiting\n");
+ logt_print(LOG_DEBUG, "Stopped %d services\n", stops_queued);
+ logt_print(LOG_NOTICE, "Disconnecting from CMAN\n");
cman_finish(clu);
+
+ if (stops_queued && !central_events_enabled()) {
+ logt_print(LOG_DEBUG, "Pausing to allow services to "
+ "start on other node(s)\n");
+ sleep(get_transition_throttling() * 3);
+ }
+
+ logt_print(LOG_NOTICE, "Exiting\n");
close_logging();
/*malloc_stats();*/
diff --git a/rgmanager/src/daemons/rg_event.c b/rgmanager/src/daemons/rg_event.c
index d03f4e3..7048bc6 100644
--- a/rgmanager/src/daemons/rg_event.c
+++ b/rgmanager/src/daemons/rg_event.c
@@ -56,6 +56,13 @@ set_transition_throttling(int nsecs)
}
+int
+get_transition_throttling(void)
+{
+ return transition_throttling;
+}
+
+
void
set_central_events(int flag)
{
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=1d…
Commit: 1d56164f2dea0772188696a8578a4144c8379885
Parent: 00c3dbbbde98f51ddd99994f88c7a1e339ff6130
Author: Shane Bradley <sbradley(a)redhat.com>
AuthorDate: Thu Apr 7 09:59:51 2011 -0400
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Thu Apr 7 10:04:13 2011 -0400
cman: Clarify 'expected' option
Resolves: rhbz#688701
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
---
cman/man/cman_tool.8 | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/cman/man/cman_tool.8 b/cman/man/cman_tool.8
index a5b9f23..2f402a6 100644
--- a/cman/man/cman_tool.8
+++ b/cman/man/cman_tool.8
@@ -58,6 +58,12 @@ version of "leave force" so only use if if you really know what you are doing.
Tells CMAN a new value of expected votes and instructs it to recalculate
quorum based on this value.
.br
+The recalculation takes into account the number of currently
+active nodes, so this option should not be used in an attempt to
+artificially lower the quorum value in advance of a planned shutdown of
+cluster nodes. Instead, the 'cman_tool leave remove' command should be
+used (see the 'leave' subcommand above).
+.br
Use this option if your cluster has lost quorum due to nodes failing and
you need to get it running again in a hurry.
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=fe…
Commit: fe9bef6e01c83e87bee845caa6d763deb33da431
Parent: e51fbc090cb3b7a343aae3ff7d1ffcd94f7fbb5b
Author: Jonathan Brassow <jbrassow(a)f14.(none)>
AuthorDate: Wed Apr 6 11:23:29 2011 -0500
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Wed Apr 6 11:36:11 2011 -0500
Fix bug 683213 - mirror dev failure in HA LVM can cause service failure
A new option was added to 'vgreduce', --force. This argument is now
required.
Additionally, repair is attempted when deactivating a device as well as
when trying to activate. This is because a shutdown of a service can
race against a device failure. Adding the repair option to the shutdown
process adds resilience.
---
rgmanager/src/resources/lvm_by_lv.sh | 63 +++++++++++++++------------------
rgmanager/src/resources/lvm_by_vg.sh | 4 +-
2 files changed, 31 insertions(+), 36 deletions(-)
diff --git a/rgmanager/src/resources/lvm_by_lv.sh b/rgmanager/src/resources/lvm_by_lv.sh
index 759062a..4aead58 100644
--- a/rgmanager/src/resources/lvm_by_lv.sh
+++ b/rgmanager/src/resources/lvm_by_lv.sh
@@ -289,45 +289,40 @@ lv_activate()
if ! lv_activate_and_tag $1 $my_name $lv_path; then
ocf_log err "Failed to $1 $lv_path"
- if [ "$1" == "start" ]; then
- ocf_log notice "Attempting cleanup of $OCF_RESKEY_vg_name"
-
- if vgreduce --removemissing --config \
- "activation { volume_list = \"$OCF_RESKEY_vg_name\" }" \
- $OCF_RESKEY_vg_name; then
- ocf_log notice "$OCF_RESKEY_vg_name now consistent"
- owner=`lvs -o tags --noheadings $lv_path`
- if [ ! -z $owner ] && [ $owner != $my_name ]; then
- if is_node_member_clustat $owner ; then
- ocf_log err "$owner owns $lv_path unable to $1"
- return $OCF_ERR_GENERIC
- fi
- ocf_log notice "Owner of $lv_path is not in the cluster"
- ocf_log notice "Stealing $lv_path"
-
- lvchange --deltag $owner $lv_path
- if [ $? -ne 0 ]; then
- ocf_log err "Failed to steal $lv_path from $owner"
- return $OCF_ERR_GENERIC
- fi
-
- # Warning --deltag doesn't always result in failure
- if [ ! -z `lvs -o tags --noheadings $lv_path` ]; then
- ocf_log err "Failed to steal $lv_path from $owner."
- return $OCF_ERR_GENERIC
- fi
+ ocf_log notice "Attempting cleanup of $OCF_RESKEY_vg_name"
+
+ if vgreduce --removemissing --force --config \
+ "activation { volume_list = \"$OCF_RESKEY_vg_name\" }" \
+ $OCF_RESKEY_vg_name; then
+ ocf_log notice "$OCF_RESKEY_vg_name now consistent"
+ owner=`lvs -o tags --noheadings $lv_path`
+ if [ ! -z $owner ] && [ $owner != $my_name ]; then
+ if is_node_member_clustat $owner ; then
+ ocf_log err "$owner owns $lv_path unable to $1"
+ return $OCF_ERR_GENERIC
fi
+ ocf_log notice "Owner of $lv_path is not in the cluster"
+ ocf_log notice "Stealing $lv_path"
- if ! lv_activate_and_tag $1 $my_name $lv_path; then
- ocf_log err "Failed second attempt to $1 $lv_path"
+ lvchange --deltag $owner $lv_path
+ if [ $? -ne 0 ]; then
+ ocf_log err "Failed to steal $lv_path from $owner"
return $OCF_ERR_GENERIC
- else
- ocf_log notice "Second attempt to $1 $lv_path successful"
- return $OCF_SUCCESS
fi
- else
- ocf_log err "Failed to make $OCF_RESKEY_vg_name consistent"
+
+ # Warning --deltag doesn't always result in failure
+ if [ ! -z `lvs -o tags --noheadings $lv_path` ]; then
+ ocf_log err "Failed to steal $lv_path from $owner."
+ return $OCF_ERR_GENERIC
+ fi
+ fi
+
+ if ! lv_activate_and_tag $1 $my_name $lv_path; then
+ ocf_log err "Failed second attempt to $1 $lv_path"
return $OCF_ERR_GENERIC
+ else
+ ocf_log notice "Second attempt to $1 $lv_path successful"
+ return $OCF_SUCCESS
fi
else
ocf_log err "Failed to $1 $lv_path"
diff --git a/rgmanager/src/resources/lvm_by_vg.sh b/rgmanager/src/resources/lvm_by_vg.sh
index f0ca671..2cce7c9 100644
--- a/rgmanager/src/resources/lvm_by_vg.sh
+++ b/rgmanager/src/resources/lvm_by_vg.sh
@@ -160,7 +160,7 @@ function vg_start_clustered
ocf_log err "Failed to activate volume group, $OCF_RESKEY_vg_name"
ocf_log notice "Attempting cleanup of $OCF_RESKEY_vg_name"
- if ! vgreduce --removemissing $OCF_RESKEY_vg_name; then
+ if ! vgreduce --removemissing --force $OCF_RESKEY_vg_name; then
ocf_log err "Failed to make $OCF_RESKEY_vg_name consistent"
return $OCF_ERR_GENERIC
fi
@@ -238,7 +238,7 @@ function vg_start_single
ocf_log err "Failed to activate volume group, $OCF_RESKEY_vg_name"
ocf_log notice "Attempting cleanup of $OCF_RESKEY_vg_name"
- if ! vgreduce --removemissing --config \
+ if ! vgreduce --removemissing --force --config \
"activation { volume_list = \"$OCF_RESKEY_vg_name\" }" \
$OCF_RESKEY_vg_name; then