cluster: STABLE3 - cman: do not propagate old configurations around

Fabio M. Di Nitto fabbione at fedoraproject.org
Thu Aug 5 14:34:26 UTC 2010


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=9cd607e41482b408aedb1afb53d56f5b05d05d7a
Commit:        9cd607e41482b408aedb1afb53d56f5b05d05d7a
Parent:        e118d34dce64325a93c92833b1e074fbabb1a516
Author:        Fabio M. Di Nitto <fdinitto at redhat.com>
AuthorDate:    Thu Aug 5 16:32:18 2010 +0200
Committer:     Fabio M. Di Nitto <fdinitto at redhat.com>
CommitterDate: Thu Aug 5 16:32:18 2010 +0200

cman: do not propagate old configurations around

Add a check in ccs_config_validate to make sure that the new
configuration we are about to load in the running cluster is newer
than the running config.

This avoids unnecessary ccs_sync of a bad config around.

Resolves: rhbz#619680

Signed-off-by: Lon Hohberger <lhh at redhat.com>
Signed-off-by: Fabio M. Di Nitto <fdinitto at redhat.com>
---
 cman/cman_tool/main.c                   |   37 +++++++++++++++++++++++++------
 config/tools/xml/ccs_config_validate.in |   34 +++++++++++++++++++++++++++-
 2 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/cman/cman_tool/main.c b/cman/cman_tool/main.c
index af1cc18..886e6a7 100644
--- a/cman/cman_tool/main.c
+++ b/cman/cman_tool/main.c
@@ -649,11 +649,12 @@ static void set_votes(commandline_t *comline)
 	cman_finish(h);
 }
 
-static int validate_config(commandline_t *comline)
+static int validate_config(commandline_t *comline, int current_version)
 {
 	struct stat st;
 	char command[PATH_MAX];
 	char validator[PATH_MAX];
+	char ccs_quiet[8];
 	int cmd_res;
 
 	/* Look for ccs_config_validate */
@@ -663,14 +664,26 @@ static int validate_config(commandline_t *comline)
 		return 0;
 	}
 
-	snprintf(command, sizeof(command), "%s -q", validator);
+	if (comline->verbose > 1) {
+		snprintf(ccs_quiet, sizeof(ccs_quiet), " ");
+	} else {
+		snprintf(ccs_quiet, sizeof(ccs_quiet), "-q");
+	}
+
+	if (current_version) {
+		snprintf(command, sizeof(command), "%s %s -R %d",
+			 validator, ccs_quiet, current_version);
+	} else {
+		snprintf(command, sizeof(command), "%s %s",
+			 validator, ccs_quiet);
+	}
 
 	if (comline->verbose > 1)
 		printf("calling '%s'\n", command);
 
 	cmd_res = system(command);
 
-	return cmd_res;
+	return WEXITSTATUS(cmd_res);
 }
 
 /* Here we set the COROSYNC_ variables that might be needed by the corosync
@@ -759,9 +772,19 @@ static void version(commandline_t *comline)
 
 		if (comline->verbose)
 			printf("Validating configuration\n");
-		if (validate_config(comline) &&
-		    comline->config_validate_opt == VALIDATE_FAIL)
-			die("Not reloading, configuration is not valid\n");
+		result = validate_config(comline, ver.cv_config);
+		if (result == 253)
+			/* Unable to find new config version */
+			die("Unable to retrive the new config version\n");
+		if (result == 254)
+			/* Config regression = fail. */
+			die("Not reloading, config version older or equal the running config");
+		if (result == 255)
+			/* Generic error from ccs_config_validate */
+			die("Not reloading, generic error running ccs_config_validate\n"
+			    "Try re-running with -d options");
+		else if (result && comline->config_validate_opt == VALIDATE_FAIL)
+			die("Not reloading, configuration is not valid");
 	}
 
 	/* We don't bother looking for ccs_sync here - just assume it's in /usr/bin and
@@ -1176,7 +1199,7 @@ static void do_join(commandline_t *comline, char *envp[])
 		if (comline->verbose)
 			printf("Validating configuration\n");
 
-		if (validate_config(comline) &&
+		if (validate_config(comline, 0) &&
 		    comline->config_validate_opt == VALIDATE_FAIL)
 			die("Not joining, configuration is not valid\n");
 	}
diff --git a/config/tools/xml/ccs_config_validate.in b/config/tools/xml/ccs_config_validate.in
index 55ab4aa..f7d7c04 100644
--- a/config/tools/xml/ccs_config_validate.in
+++ b/config/tools/xml/ccs_config_validate.in
@@ -17,6 +17,15 @@ if [ -z "$COROSYNC_DEFAULT_CONFIG_IFACE" ]; then
 	export COROSYNC_DEFAULT_CONFIG_IFACE=$CONFIG_LOADER:cmanpreconfig
 fi
 
+get_config_version() {
+	local file=$1
+
+	echo "xpath /cluster/@config_version" | \
+		xmllint --shell "$file" | \
+		grep content | \
+	cut -f2 -d=
+}
+
 print_usage() {
 	echo "Usage:"
 	echo ""
@@ -38,6 +47,8 @@ print_usage() {
 	echo "  -t tempfile      Force temporay file to tempfile"
 	echo "  -n               Do not remove temporary file"
 	echo "  -o               Overwrite temporary file (dangerous)"
+	echo "  -R version       When validating configuration update, ensure the"
+	echo "                   new config is newer than the specified version."
 }
 
 check_opts() {
@@ -61,6 +72,10 @@ check_opts() {
 		-o)
 			overwritetempfile=1
 		;;
+		-R)	
+			shift
+			old_version=$1
+		;;
 		-C)
 			shift
 			export COROSYNC_DEFAULT_CONFIG_IFACE=$1:cmanpreconfig
@@ -131,7 +146,7 @@ lecho()
 	return 0
 }
 
-opts=$(getopt t:hVnC:f:l:rovq $@)
+opts=$(getopt t:hVnC:f:l:rR:ovq $@)
 if [ "$?" != 0 ]; then
 	print_usage >&2
 	exit 255
@@ -174,6 +189,23 @@ xmlout=$(xmllint --noout \
 	$tempfile 2>&1)
 res=$?
 
+if [ -n "$old_version" ] && [ $old_version -ne 0 ] && [ $res -eq 0 ]; then
+	new_version=$(get_config_version $tempfile)
+	if [ -z "$new_version" ]; then
+		[ -z "$quiet" ] && \
+			echo "Error: Unable to determine new config version!" >&2
+		[ -z "$notempfilerm" ] && rm -f $tempfile
+		exit 253
+	fi
+	lecho "Old version: $old_version   New version: $new_version"
+	if [ $new_version -le $old_version ]; then
+		[ -z "$quiet" ] && \
+			echo "Error: Configuration version is older than running config!" >&2
+		[ -z "$notempfilerm" ] && rm -f $tempfile
+		exit 254
+	fi
+fi
+
 if [ -z "$quiet" ] || [ "$res" != "0" ]; then
 	echo "$xmlout" | sed \
 		-e 's#.*validates$#Configuration validates#g' \


More information about the cluster-commits mailing list