public inbox for cluster-cvs@sourceware.org
help / color / mirror / Atom feed
* RHEL5 - rgmanager: Add patch from Simone Gotti to implement service freeze/unfreeze.
@ 2008-08-26 16:48 Lon Hohberger
0 siblings, 0 replies; only message in thread
From: Lon Hohberger @ 2008-08-26 16:48 UTC (permalink / raw)
To: cluster-cvs-relay
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;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2008-08-26 14:58 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-08-26 16:48 RHEL5 - rgmanager: Add patch from Simone Gotti to implement service freeze/unfreeze Lon Hohberger
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).