This is the mail archive of the cluster-cvs@sourceware.org mailing list for the cluster.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RHEL5 - rgmanager: Add patch from Simone Gotti to implement servicefreeze/unfreeze.


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=9607c265d75b92add904085c9fc75d3ad29be6e6
Commit:        9607c265d75b92add904085c9fc75d3ad29be6e6
Parent:        481eda3eba49e4066c3314c04fdf98b32ccb131e
Author:        Lon Hohberger <lhh@redhat.com>
AuthorDate:    Fri Apr 27 18:10:10 2007 +0000
Committer:     Lon Hohberger <lhh@redhat.com>
CommitterDate: Mon Aug 25 14:53:10 2008 -0400

rgmanager: Add patch from Simone Gotti to implement service freeze/unfreeze.

This is a backport from master branch to RHEL5 and is
part 1 of 2 fixing rhbz #448046
---
 rgmanager/include/resgroup.h      |   15 ++++-
 rgmanager/src/clulib/rg_strings.c |   37 ++++++++++++
 rgmanager/src/daemons/groups.c    |    3 +
 rgmanager/src/daemons/rg_state.c  |  111 ++++++++++++++++++++++++++++++++++++-
 rgmanager/src/daemons/rg_thread.c |   12 ++++
 rgmanager/src/utils/clustat.c     |   30 +++++++++-
 rgmanager/src/utils/clusvcadm.c   |   31 ++++++++---
 7 files changed, 224 insertions(+), 15 deletions(-)

diff --git a/rgmanager/include/resgroup.h b/rgmanager/include/resgroup.h
index 21e36ba..36b002f 100644
--- a/rgmanager/include/resgroup.h
+++ b/rgmanager/include/resgroup.h
@@ -27,7 +27,7 @@
  */
 typedef struct {
 	char		rs_name[64];	/**< Service name */
-	uint32_t	rs_id;		/**< Service ID */
+	uint32_t	rs_flags;	/**< Service flags */
 	uint32_t	rs_magic;	/**< Magic ID */
 	uint32_t	rs_owner;	/**< Member ID running service. */
 	uint32_t	rs_last_owner;	/**< Last member to run the service. */
@@ -39,7 +39,7 @@ typedef struct {
 
 #define swab_rg_state_t(ptr) \
 {\
-	swab32((ptr)->rs_id);\
+	swab32((ptr)->rs_flags);\
 	swab32((ptr)->rs_magic);\
 	swab32((ptr)->rs_owner);\
 	swab32((ptr)->rs_last_owner);\
@@ -86,7 +86,8 @@ typedef struct {
 #define RG_UNLOCK	  20
 #define RG_QUERY_LOCK	  21
 #define RG_MIGRATE	  22
-/* Compat: FREEZE = 23, UNFREEZE = 24 */
+#define RG_FREEZE	  23
+#define RG_UNFREEZE	  24
 #define RG_STATUS_INQUIRY 25
 #define RG_NONE		  999
 
@@ -115,7 +116,11 @@ int handle_start_remote_req(char *svcName, int req);
 
 #define DEFAULT_CHECK_INTERVAL		10
 
+/* Resource group flags (for now) */
+#define RG_FLAG_FROZEN			(1<<0)	/** Resource frozen */
+
 const char *rg_state_str(int val);
+const char *rg_flags_str(char *flags_string, size_t size, int val, char *separator);
 int rg_state_str_to_id(const char *val);
 const char *agent_op_str(int val);
 
@@ -133,6 +138,8 @@ int svc_status(char *svcName);
 int svc_status_inquiry(char *svcName);
 int svc_disable(char *svcName);
 int svc_fail(char *svcName);
+int svc_freeze(char *svcName);
+int svc_unfreeze(char *svcName);
 int svc_migrate(char *svcName, int target);
 int check_restart(char *svcName);
 int add_restart(char *svcName);
@@ -188,7 +195,7 @@ int my_id(void);
 #define RG_ESCRIPT	-14		/* S/Lang script failed */
 #define RG_EFENCE	-13		/* Fencing operation pending */
 #define RG_ENODE	-12		/* Node is dead/nonexistent */
-//#define RG_EFROZEN    -11		/* Forward compat. with -HEAD */
+#define RG_EFROZEN	-11		/* Forward compat. with -HEAD */
 #define RG_ERUN		-10		/* Service is already running */
 #define RG_EQUORUM	-9		/* Operation requires quorum */
 #define RG_EINVAL	-8		/* Invalid operation for resource */
diff --git a/rgmanager/src/clulib/rg_strings.c b/rgmanager/src/clulib/rg_strings.c
index fb7598f..a215eca 100644
--- a/rgmanager/src/clulib/rg_strings.c
+++ b/rgmanager/src/clulib/rg_strings.c
@@ -40,6 +40,7 @@ const struct string_val rg_error_strings[] = {
 	{ RG_ENOSERVICE,"Service does not exist" },
 	{ RG_EFORWARD,	"Service not mastered locally" },
 	{ RG_EABORT,	"Aborted; service failed" },
+	{ RG_EFROZEN,	"Failure: Service is frozen"},
 	{ RG_EFAIL,	"Failure" },
 	{ RG_ESUCCESS,	"Success" },
 	{ RG_YES,	"Yes" },
@@ -94,6 +95,12 @@ const struct string_val rg_state_strings[] = {
 };
 
 
+const struct string_val rg_flags_strings[] = {
+	{RG_FLAG_FROZEN, "frozen"},
+	{0, NULL}
+};
+
+
 const struct string_val agent_ops[] = {
 	{RS_START, "start"},
 	{RS_STOP, "stop"},
@@ -144,6 +151,20 @@ rg_search_table_by_str(const struct string_val *table, const char *val)
 
 
 
+static inline const char *
+rg_flag_search_table(const struct string_val *table, int val)
+{
+	int x;
+
+	for (x = 0; table[x].str != NULL; x++) {
+		if (table[x].val == val) {
+			return table[x].str;
+		}
+	}
+
+	return "Unknown";
+}
+
 const char *
 rg_strerror(int val)
 {
@@ -171,6 +192,22 @@ rg_req_str(int val)
 	return rg_search_table(rg_req_strings, val);
 }
 
+const char *
+rg_flags_str(char *flags_string, size_t size, int val, char *separator)
+{
+	int i;
+	const char *string;
+
+	for (i = 0; i < sizeof(uint32_t); i++) {
+		if ( val & (1 << i)) {
+			if (strlen(flags_string))
+				strncat(flags_string, separator, size - (strlen(flags_string) + strlen(separator) + 1));
+			string = rg_search_table(rg_flags_strings, (1 << i));
+			strncat(flags_string, string, size - (strlen(flags_string) + strlen(string) + 1));
+		}
+	}
+	return flags_string;
+}
 
 const char *
 agent_op_str(int val)
diff --git a/rgmanager/src/daemons/groups.c b/rgmanager/src/daemons/groups.c
index 4895d6b..0a3451c 100644
--- a/rgmanager/src/daemons/groups.c
+++ b/rgmanager/src/daemons/groups.c
@@ -455,6 +455,9 @@ consider_start(resource_node_t *node, char *svcName, rg_state_t *svcStatus,
 	mp = memb_id_to_p(membership, my_id());
 	assert(mp);
 
+	/* Service cannot be started if Frozen */
+	if (svcStatus->rs_flags & RG_FLAG_FROZEN)
+		return;
 	/*
 	 * Service must be not be running elsewhere to consider for a
 	 * local start.
diff --git a/rgmanager/src/daemons/rg_state.c b/rgmanager/src/daemons/rg_state.c
index ffc5dfa..76c62f5 100644
--- a/rgmanager/src/daemons/rg_state.c
+++ b/rgmanager/src/daemons/rg_state.c
@@ -303,8 +303,10 @@ static int
 init_rg(char *name, rg_state_t *svcblk)
 {
 	svcblk->rs_owner = 0;
+	svcblk->rs_flags = 0;
 	svcblk->rs_last_owner = 0;
 	svcblk->rs_state = RG_STATE_STOPPED;
+       	svcblk->rs_flags = 0;
        	svcblk->rs_restarts = 0;
 	svcblk->rs_transition = 0;	
 	strncpy(svcblk->rs_name, name, sizeof(svcblk->rs_name));
@@ -442,6 +444,7 @@ get_rg_state_local(char *name, rg_state_t *svcblk)
 		svcblk->rs_owner = 0;
 		svcblk->rs_last_owner = 0;
 		svcblk->rs_state = RG_STATE_UNINITIALIZED;
+       		svcblk->rs_flags = 0;
        		svcblk->rs_restarts = 0;
 		svcblk->rs_transition = 0;	
 		strncpy(svcblk->rs_name, name, sizeof(svcblk->rs_name));
@@ -470,6 +473,7 @@ get_rg_state_local(char *name, rg_state_t *svcblk)
  *			2 = DO NOT stop service, return 0 (success)
  *                      3 = DO NOT stop service, return RG_EFORWARD
  *			4 = DO NOT stop service, return RG_EAGAIN
+ *			5 = DO NOT stop service, return RG_EFROZEN
  */
 int
 svc_advise_stop(rg_state_t *svcStatus, char *svcName, int req)
@@ -477,6 +481,11 @@ svc_advise_stop(rg_state_t *svcStatus, char *svcName, int req)
 	cluster_member_list_t *membership = member_list();
 	int ret = 0;
 	
+	if (svcStatus->rs_flags & RG_FLAG_FROZEN) {
+		clulog(LOG_DEBUG, "Service %s frozen.\n", svcName);
+		return 5;
+	}
+
 	switch(svcStatus->rs_state) {
 	case RG_STATE_FAILED:
 		if (req == RG_DISABLE)
@@ -594,6 +603,7 @@ svc_advise_stop(rg_state_t *svcStatus, char *svcName, int req)
  *			2 = DO NOT start service, return 0
  *			3 = DO NOT start service, return RG_EAGAIN
  *			4 = DO NOT start service, return RG_ERUN
+ *			5 = DO NOT start service, return RG_EFROZEN
  */
 int
 svc_advise_start(rg_state_t *svcStatus, char *svcName, int req)
@@ -601,6 +611,11 @@ svc_advise_start(rg_state_t *svcStatus, char *svcName, int req)
 	cluster_member_list_t *membership = member_list();
 	int ret = 0;
 	
+	if (svcStatus->rs_flags & RG_FLAG_FROZEN) {
+		clulog(LOG_DEBUG, "Service %s frozen.\n", svcName);
+		return 5;
+	}
+
 	switch(svcStatus->rs_state) {
 	case RG_STATE_FAILED:
 		clulog(LOG_ERR,
@@ -781,6 +796,9 @@ svc_start(char *svcName, int req)
 	case 4:
 		rg_unlock(&lockp);
 		return RG_ERUN;
+	case 5:
+		rg_unlock(&lockp);
+		return RG_EFROZEN;
 	default:
 		break;
 	}
@@ -1139,6 +1157,10 @@ svc_status(char *svcName)
 	}
 	rg_unlock(&lockp);
 
+	if (svcStatus.rs_flags & RG_FLAG_FROZEN)
+		/* Don't check status if the service is frozen */
+		return 0;
+
 	if (svcStatus.rs_owner != my_id())
 		/* Don't check status for anything not owned */
 		return 0;
@@ -1233,6 +1255,17 @@ handle_migrate_status(char *svcName, int ret, rg_state_t *svcStatus)
 int
 svc_status_inquiry(char *svcName)
 {
+	rg_state_t svcStatus;
+
+	if (get_rg_state_local(svcName, &svcStatus) != 0) {
+		clulog(LOG_ERR, "Failed getting local status for RG %s\n",
+		       svcName);
+		return RG_EFAIL;
+	}
+
+	if (svcStatus.rs_flags & RG_FLAG_FROZEN)
+		return 0;
+	
 	return group_op(svcName, RG_STATUS);
 }
 
@@ -1287,6 +1320,9 @@ _svc_stop(char *svcName, int req, int recover, uint32_t newstate)
 	case 4:
 		rg_unlock(&lockp);
 		return RG_EAGAIN;
+	case 5:
+		rg_unlock(&lockp);
+		return RG_EFROZEN;
 	default:
 		break;
 	}
@@ -1478,6 +1514,76 @@ svc_fail(char *svcName)
 	return 0;
 }
 
+/**
+ * Flag/Unflag a cluster service as frozen.
+ *
+ * @param svcName	Service ID to flag/unflag as frozen.
+ * @return		FAIL, 0
+ */
+int
+_svc_freeze(char *svcName, int enabled)
+{
+	struct dlm_lksb lockp;
+	rg_state_t svcStatus;
+
+	if (rg_lock(svcName, &lockp) == RG_EFAIL) {
+		clulog(LOG_ERR, "#55: Unable to obtain cluster lock: %s\n",
+		       strerror(errno));
+		return RG_EFAIL;
+	}
+
+	clulog(LOG_DEBUG, "Handling %s request for RG %s\n", svcName, enabled?"freeze":"unfreeze");
+
+	if (get_rg_state(svcName, &svcStatus) != 0) {
+		rg_unlock(&lockp);
+		clulog(LOG_ERR, "#56: Failed getting status for RG %s\n",
+		       svcName);
+		return RG_EFAIL;
+	}
+
+	switch(svcStatus.rs_state) {
+	case RG_STATE_STOPPED:
+	case RG_STATE_STARTED:
+	case RG_STATE_DISABLED:
+
+		if (enabled == 1) {
+			clulog(LOG_DEBUG, "Freezing RG %s\n", svcName);
+			svcStatus.rs_flags |= RG_FLAG_FROZEN;
+		} else {
+			clulog(LOG_DEBUG, "Unfreezing RG %s\n", svcName);
+			svcStatus.rs_flags &= ~RG_FLAG_FROZEN;
+		}
+
+		if (set_rg_state(svcName, &svcStatus) != 0) {
+			rg_unlock(&lockp);
+			clulog(LOG_ERR, "#57: Failed changing RG status\n");
+			return RG_EFAIL;
+		}
+		break;
+
+	default:
+		rg_unlock(&lockp);
+		return RG_EFAIL;
+		break;
+	}
+
+	rg_unlock(&lockp);
+
+	return 0;
+}
+
+int
+svc_freeze(char *svcName)
+{
+	return _svc_freeze(svcName, 1);
+}
+
+int
+svc_unfreeze(char *svcName)
+{
+	return _svc_freeze(svcName, 0);
+}
+
 
 /*
  * Send a message to the target node to start the service.
@@ -1641,6 +1747,9 @@ handle_relocate_req(char *svcName, int request, int preferred_target,
 			svc_fail(svcName);
 			return RG_EFAIL;
 		}
+		if (ret == RG_EFROZEN) {
+			return RG_EFROZEN;
+		}
 		if (ret == RG_EFORWARD)
 			return RG_EFORWARD;
 	}
@@ -1871,7 +1980,7 @@ handle_start_req(char *svcName, int req, int *new_owner)
 	/* 
 	   If services are locked, return the error 
 	  */
-	if (ret == RG_EAGAIN || ret == RG_ERUN)
+	if (ret == RG_EAGAIN || ret == RG_ERUN || ret == RG_EFROZEN)
 		return ret;
 
 	/*
diff --git a/rgmanager/src/daemons/rg_thread.c b/rgmanager/src/daemons/rg_thread.c
index 19bf470..0e84f2f 100644
--- a/rgmanager/src/daemons/rg_thread.c
+++ b/rgmanager/src/daemons/rg_thread.c
@@ -470,6 +470,18 @@ resgroup_thread_main(void *arg)
 
 			break;
 
+		case RG_FREEZE:
+			error = svc_freeze(myname);
+			if (error != 0)
+				ret = RG_EFAIL;
+			break;
+
+		case RG_UNFREEZE:
+			error = svc_unfreeze(myname);
+			if (error != 0)
+				ret = RG_EFAIL;
+			break;
+
 		default:
 			printf("Unhandled request %d\n", req->rr_request);
 			ret = RG_NONE;
diff --git a/rgmanager/src/utils/clustat.c b/rgmanager/src/utils/clustat.c
index 99ddbab..fa15515 100644
--- a/rgmanager/src/utils/clustat.c
+++ b/rgmanager/src/utils/clustat.c
@@ -454,6 +454,8 @@ _txt_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags,
 	      int svcsize, int nodesize, int statsize)
 {
 	char owner[MAXHOSTNAMELEN+1];
+	char flags_string[255] = "";
+	char state_string[255] = "";
 	char *name = rs->rs_name, *ptr;
 	int l;
 
@@ -482,11 +484,22 @@ _txt_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags,
 		snprintf(owner, sizeof(owner)-1, "%-.*s", nodesize,
 			 my_memb_id_to_name(members, rs->rs_owner));
 	}
+
+	/* Show a frozen service */
+	if (rs->rs_flags & RG_FLAG_FROZEN) {
+		snprintf(state_string, sizeof(state_string), 
+			 "%-*.*s[Z]", statsize-3, statsize-3,
+			 rg_state_str(rs->rs_state));
+	} else {
+		snprintf(state_string, sizeof(state_string),
+			 "%-*.*s", statsize, statsize,
+			 rg_state_str(rs->rs_state));
+	}
 	
 	printf(" %-*.*s %-*.*s %-*.*s\n",
 	       svcsize, svcsize, rs->rs_name,
 	       nodesize, nodesize, owner,
-	       statsize, statsize, rg_state_str(rs->rs_state));
+	       statsize, statsize, state_string);
 }
 
 
@@ -494,10 +507,19 @@ void
 _txt_rg_state_v(rg_state_t *rs, cluster_member_list_t *members, int flags)
 {
 	time_t t;
+	char flags_string[255] = "";
+
+	rg_flags_str(flags_string, sizeof(flags_string), rs->rs_flags, ", ");
 
 	printf("Service Name      : %s\n", rs->rs_name);
 	printf("  Current State   : %s (%d)\n",
 	       rg_state_str(rs->rs_state), rs->rs_state);
+	if (rs->rs_flags)
+		printf("  Flags           : %s (%d)\n",
+		       flags_string, rs->rs_flags);
+	else
+		printf("  Flags           : none (%d)\n",
+		       rs->rs_flags);
 	printf("  Owner           : %s\n",
 	       my_memb_id_to_name(members, rs->rs_owner));
 	printf("  Last Owner      : %s\n",
@@ -523,6 +545,7 @@ void
 xml_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags)
 {
 	char time_str[32];
+	char flags_string[255] = "";
 	int x;
 	time_t t;
 
@@ -536,12 +559,15 @@ xml_rg_state(rg_state_t *rs, cluster_member_list_t *members, int flags)
 		}
 	}
 
-	printf("    <group name=\"%s\" state=\"%d\" state_str=\"%s\" "
+	printf("    <group name=\"%s\" state=\"%d\" state_str=\"%s\""
+	       " flags=\"%d\" flags_str=\"%s\""
 	       " owner=\"%s\" last_owner=\"%s\" restarts=\"%d\""
 	       " last_transition=\"%llu\" last_transition_str=\"%s\"/>\n",
 	       rs->rs_name,
 	       rs->rs_state,
 	       rg_state_str(rs->rs_state),
+	       rs->rs_flags,
+	       rg_flags_str(flags_string, sizeof(flags_string), rs->rs_flags, " "),
 	       my_memb_id_to_name(members, rs->rs_owner),
 	       my_memb_id_to_name(members, rs->rs_last_owner),
 	       rs->rs_restarts,
diff --git a/rgmanager/src/utils/clusvcadm.c b/rgmanager/src/utils/clusvcadm.c
index 18427a2..789ab1b 100644
--- a/rgmanager/src/utils/clusvcadm.c
+++ b/rgmanager/src/utils/clusvcadm.c
@@ -153,20 +153,22 @@ do_query_lock(void)
 void
 usage(char *name)
 {
+	int pad = strlen(name);
+
 printf("Resource Group Control Commands:\n");
 printf("       %s -v                     Display version and exit\n",name);
 printf("       %s -d <group>             Disable <group>\n", name);
 printf("       %s -e <group>             Enable <group>\n",
        name);
 printf("       %s -e <group> -F          Enable <group> according to failover\n"
-       "                                 domain rules\n", name);
+       "       %-*.*s                        domain rules\n", name, pad, pad, " ");
 printf("       %s -e <group> -m <member> Enable <group>"
        " on <member>\n", name);
 printf("       %s -r <group> -m <member> Relocate <group> [to <member>]\n",
 	       name);
 printf("       %s -M <group> -m <member> Migrate <group> to <member>\n",
 	       name);
-printf("                                 (e.g. for live migration of VMs)\n");
+printf("       %-*.*s                          (e.g. for live migration of VMs)\n", pad, pad, " ");
 printf("       %s -q                     Quiet operation\n", name);
 printf("       %s -R <group>             Restart a group in place.\n",
        name);
@@ -174,13 +176,16 @@ printf("       %s -s <group>             Stop <group>\n", name);
 printf("\n");
 printf("Resource Group Locking (for cluster Shutdown / Debugging):\n");
 printf("       %s -l                     Lock local resource group manager.\n"
-       "                                 This prevents resource groups from\n"
-       "                                 starting on the local node.\n",
-       name);
+       "       %-*.*s                        This prevents resource groups from\n"
+       "       %-*.*s                        starting on the local node.\n",
+       name, pad, pad, " ", pad, pad, " ");
 printf("       %s -S                     Show lock state\n", name);
 printf("       %s -u                     Unlock local resource group manager.\n"
-       "                                 This allows resource groups to start\n"
-       "                                 on the local node.\n", name);
+       "       %-*.*s                        This allows resource groups to start\n"
+       "       %-*.*s                        on the local node.\n",
+       name, pad, pad, " ", pad, pad, " ");
+printf("       %s -Z <group>             Freeze group in place\n", name);
+printf("       %s -U <group>             Unfreeze/thaw group\n", name);
 }
 
 
@@ -246,7 +251,7 @@ main(int argc, char **argv)
 		return 1;
 	}
 
-	while ((opt = getopt(argc, argv, "lSue:M:d:r:n:m:FvR:s:qh?")) != EOF) {
+	while ((opt = getopt(argc, argv, "lSue:M:d:r:n:m:Z:U:FvR:s:qh?")) != EOF) {
 		switch (opt) {
 		case 'l':
 			return do_lock();
@@ -313,6 +318,16 @@ main(int argc, char **argv)
 		case 'v':
 			printf("%s\n",PACKAGE_VERSION);
 			return 0;
+		case 'Z':
+			actionstr = "freezing";
+			action = RG_FREEZE;
+			svcname = optarg;
+			break;
+		case 'U':
+			actionstr = "unfreezing";
+			action = RG_UNFREEZE;
+			svcname = optarg;
+			break;
 		case 'q':
 			close(STDOUT_FILENO);
 			break;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]