From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24382 invoked by alias); 26 Aug 2008 14:58:23 -0000 Received: (qmail 24343 invoked by alias); 26 Aug 2008 14:58:22 -0000 X-Spam-Status: No, hits=0.6 required=5.0 tests=AWL,BAYES_50,J_CHICKENPOX_43,J_CHICKENPOX_54,J_CHICKENPOX_64,KAM_MX,SPF_HELO_PASS X-Spam-Check-By: sourceware.org X-Spam-Checker-Version: SpamAssassin 3.2.4 (2008-01-01) on bastion.fedora.phx.redhat.com X-Spam-Level: Subject: RHEL5 - rgmanager: Add patch from Simone Gotti to implement service freeze/unfreeze. To: cluster-cvs-relay@redhat.com X-Project: Cluster Project X-Git-Module: cluster.git X-Git-Refname: refs/heads/RHEL5 X-Git-Reftype: branch X-Git-Oldrev: 481eda3eba49e4066c3314c04fdf98b32ccb131e X-Git-Newrev: 9607c265d75b92add904085c9fc75d3ad29be6e6 From: Lon Hohberger Message-Id: <20080826142341.9A4F712035E@lists.fedorahosted.org> Date: Tue, 26 Aug 2008 16:48:00 -0000 X-Scanned-By: MIMEDefang 2.58 on 172.16.52.254 Mailing-List: contact cluster-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: cluster-cvs-owner@sourceware.org X-SW-Source: 2008-q3/txt/msg00313.txt.bz2 Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=9607c265d75b92add904085c9fc75d3ad29be6e6 Commit: 9607c265d75b92add904085c9fc75d3ad29be6e6 Parent: 481eda3eba49e4066c3314c04fdf98b32ccb131e Author: Lon Hohberger AuthorDate: Fri Apr 27 18:10:10 2007 +0000 Committer: Lon Hohberger 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(" \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 Disable \n", name); printf(" %s -e Enable \n", name); printf(" %s -e -F Enable according to failover\n" - " domain rules\n", name); + " %-*.*s domain rules\n", name, pad, pad, " "); printf(" %s -e -m Enable " " on \n", name); printf(" %s -r -m Relocate [to ]\n", name); printf(" %s -M -m Migrate to \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 Restart a group in place.\n", name); @@ -174,13 +176,16 @@ printf(" %s -s Stop \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 Freeze group in place\n", name); +printf(" %s -U 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;