From: lhh@sourceware.org <lhh@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] cluster/rgmanager TODO include/msgsimple.h inc ...
Date: 19 Jul 2006 18:43:34 -0000 [thread overview]
Message-ID: <20060719184334.25245.qmail@sourceware.org> (raw)
CVSROOT: /cvs/cluster
Module name: cluster
Changes by: lhh at sourceware.org 2006-07-19 18:43:32
Modified files:
rgmanager : TODO
rgmanager/include: msgsimple.h resgroup.h reslist.h rg_queue.h
rgmanager/src/daemons: fo_domain.c groups.c resrules.c restree.c
rg_queue.c rg_state.c rg_thread.c test.c
rgmanager/src/resources: ra-api-1-modified.dtd xenvm.sh
rgmanager/src/utils: Makefile clusvcadm.c
Log message:
Add preliminary live-migration support (e.g. for Xen for FC6
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/TODO.diff?cvsroot=cluster&r1=1.7&r2=1.8
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/msgsimple.h.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/resgroup.h.diff?cvsroot=cluster&r1=1.11&r2=1.12
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/reslist.h.diff?cvsroot=cluster&r1=1.13&r2=1.14
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/rg_queue.h.diff?cvsroot=cluster&r1=1.5&r2=1.6
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/fo_domain.c.diff?cvsroot=cluster&r1=1.9&r2=1.10
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/groups.c.diff?cvsroot=cluster&r1=1.19&r2=1.20
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/resrules.c.diff?cvsroot=cluster&r1=1.12&r2=1.13
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/restree.c.diff?cvsroot=cluster&r1=1.20&r2=1.21
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/rg_queue.c.diff?cvsroot=cluster&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/rg_state.c.diff?cvsroot=cluster&r1=1.17&r2=1.18
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/rg_thread.c.diff?cvsroot=cluster&r1=1.13&r2=1.14
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/test.c.diff?cvsroot=cluster&r1=1.5&r2=1.6
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/ra-api-1-modified.dtd.diff?cvsroot=cluster&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/xenvm.sh.diff?cvsroot=cluster&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/utils/Makefile.diff?cvsroot=cluster&r1=1.11&r2=1.12
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/utils/clusvcadm.c.diff?cvsroot=cluster&r1=1.9&r2=1.10
--- cluster/rgmanager/TODO 2006/07/12 17:15:14 1.7
+++ cluster/rgmanager/TODO 2006/07/19 18:43:32 1.8
@@ -2,3 +2,4 @@
can manually migrate Xen VMs to other nodes without telling the cluster
about it. That is, the cluster should be able to acquire running VMs
and update its state accordingly.
+* Test against a working Xen build and shake out bugs
--- cluster/rgmanager/include/msgsimple.h 2006/06/02 17:37:10 1.3
+++ cluster/rgmanager/include/msgsimple.h 2006/07/19 18:43:32 1.4
@@ -11,7 +11,7 @@
uint32_t gh_command;
uint32_t gh_arg1;
uint32_t gh_arg2;
- /* XXX alignment issue on ia64 */
+ uint32_t gh_arg3;
} generic_msg_hdr;
#define swab_generic_msg_hdr(ptr)\
@@ -29,9 +29,8 @@
char d_svcName[64];
uint32_t d_action;
uint32_t d_svcState;
- uint64_t d_svcOwner;
+ uint32_t d_svcOwner;
int32_t d_ret;
- uint32_t d_pad;
} sm_data;
} SmMessageSt;
@@ -40,7 +39,7 @@
swab_generic_msg_hdr(&((ptr)->sm_hdr));\
swab32((ptr)->sm_data.d_action);\
swab32((ptr)->sm_data.d_svcState);\
- swab64((ptr)->sm_data.d_svcOwner);\
+ swab32((ptr)->sm_data.d_svcOwner);\
swab32((ptr)->sm_data.d_ret);\
}
--- cluster/rgmanager/include/resgroup.h 2006/07/12 14:04:06 1.11
+++ cluster/rgmanager/include/resgroup.h 2006/07/19 18:43:32 1.12
@@ -27,8 +27,8 @@
*/
typedef struct {
char rs_name[64]; /**< Service name */
- uint64_t rs_owner; /**< Member ID running service. */
- uint64_t rs_last_owner; /**< Last member to run the service. */
+ uint32_t rs_owner; /**< Member ID running service. */
+ uint32_t rs_last_owner; /**< Last member to run the service. */
uint32_t rs_state; /**< State of service. */
uint32_t rs_restarts; /**< Number of cluster-induced
restarts */
@@ -39,8 +39,8 @@
#define swab_rg_state_t(ptr) \
{\
- swab64((ptr)->rs_owner);\
- swab64((ptr)->rs_last_owner);\
+ swab32((ptr)->rs_owner);\
+ swab32((ptr)->rs_last_owner);\
swab32((ptr)->rs_state);\
swab32((ptr)->rs_restarts);\
swab64((ptr)->rs_transition);\
@@ -56,6 +56,7 @@
#define RG_ACTION_REQUEST /* Message header */ 0x138582
#define RG_EVENT 0x138583
+/* Requests */
#define RG_SUCCESS 0
#define RG_FAIL 1
#define RG_START 2
@@ -78,6 +79,7 @@
#define RG_LOCK 19
#define RG_UNLOCK 20
#define RG_QUERY_LOCK 21
+#define RG_MIGRATE 22
#define RG_NONE 999
extern const char *rg_req_strings[];
@@ -102,6 +104,7 @@
#define RG_STATE_ERROR 117 /** Recoverable error */
#define RG_STATE_RECOVER 118 /** Pending recovery */
#define RG_STATE_DISABLED 119 /** Resource not allowd to run */
+#define RG_STATE_MIGRATE 120 /** Resource migrating */
#define DEFAULT_CHECK_INTERVAL 10
@@ -121,7 +124,7 @@
int svc_fail(char *svcName);
int rt_enqueue_request(const char *resgroupname, int request,
msgctx_t *resp_ctx,
- int max, uint64_t target, int arg0, int arg1);
+ int max, uint32_t target, int arg0, int arg1);
void send_response(int ret, request_t *req);
void send_ret(msgctx_t *ctx, char *name, int ret, int req);
@@ -135,7 +138,7 @@
/* from rg_state.c */
int set_rg_state(char *name, rg_state_t *svcblk);
int get_rg_state(char *servicename, rg_state_t *svcblk);
-uint64_t best_target_node(cluster_member_list_t *allowed, uint64_t owner,
+uint32_t best_target_node(cluster_member_list_t *allowed, uint32_t owner,
char *rg_name, int lock);
#ifdef DEBUG
@@ -158,22 +161,19 @@
cluster_member_list_t *member_list(void);
int my_id(void);
-#define RG_EDEPEND -7
-#define RG_EAGAIN -6
-#define RG_EDEADLCK -5
-#define RG_ENOSERVICE -4
-#define RG_EFORWARD -3
-#define RG_EABORT -2
-#define RG_EFAIL -1
+/* Return codes */
+#define RG_EQUORUM -9 /* Operation requires quorum */
+#define RG_EINVAL -8 /* Invalid operation for resource */
+#define RG_EDEPEND -7 /* Operation violates dependency */
+#define RG_EAGAIN -6 /* Try again */
+#define RG_EDEADLCK -5 /* Aborted - would deadlock */
+#define RG_ENOSERVICE -4 /* Service does not exist */
+#define RG_EFORWARD -3 /* Service not mastered locally */
+#define RG_EABORT -2 /* Abort; service unrecoverable */
+#define RG_EFAIL -1 /* Generic failure */
#define RG_ESUCCESS 0
-
-
-#define FORWARD -3
-#define ABORT -2
-#define FAIL -1
-#define SUCCESS 0
-#define YES 1
-#define NO 2
+#define RG_YES 1
+#define RG_NO 2
/*
* Fail-over domain states
--- cluster/rgmanager/include/reslist.h 2005/12/06 18:31:37 1.13
+++ cluster/rgmanager/include/reslist.h 2006/07/19 18:43:32 1.14
@@ -53,6 +53,10 @@
#define RS_RECOVER (7)
#define RS_CONDSTART (8) /** Start if flagged with RF_NEEDSTART */
#define RS_CONDSTOP (9) /** STOP if flagged with RF_NEEDSTOP */
+#define RS_MONITOR (10)
+#define RS_META_DATA (11)
+#define RS_VALIDATE (12)
+#define RS_MIGRATE (13)
#ifndef SHAREDIR
@@ -100,7 +104,7 @@
char * rr_type;
char * rr_agent;
char * rr_version; /** agent XML spec version; OCF-ism */
- int rr_root;
+ int rr_flags;
int rr_maxrefs;
resource_attr_t * rr_attrs;
resource_child_t * rr_childtypes;
--- cluster/rgmanager/include/rg_queue.h 2006/06/02 17:37:10 1.5
+++ cluster/rgmanager/include/rg_queue.h 2006/07/19 18:43:32 1.6
@@ -16,9 +16,10 @@
uint32_t rr_request; /** Request */
uint32_t rr_errorcode; /** Error condition */
uint32_t rr_orig_request; /** Original request */
- uint64_t rr_target; /** Target node */
+ uint32_t rr_target; /** Target node */
uint32_t rr_arg0; /** Integer argument */
uint32_t rr_arg1; /** Integer argument */
+ uint32_t rr_arg3; /** Integer argument */
uint32_t rr_line; /** Line no */
msgctx_t * rr_resp_ctx; /** FD to send response */
char *rr_file; /** Who made req */
@@ -28,7 +29,7 @@
int _rq_queue_request(request_t **queue, char *name, uint32_t request,
uint32_t err, uint32_t oldreq, msgctx_t *ctx, time_t when,
- uint64_t target, uint32_t arg0, uint32_t arg1, char *file,
+ uint32_t target, uint32_t arg0, uint32_t arg1, char *file,
int line);
#define rq_queue_request(queue, name, request, err, oldreq,\
--- cluster/rgmanager/src/daemons/fo_domain.c 2006/07/11 23:52:41 1.9
+++ cluster/rgmanager/src/daemons/fo_domain.c 2006/07/19 18:43:32 1.10
@@ -333,8 +333,10 @@
fod_t *fod = NULL;
int found = 0;
int owned_by_node = 0, started = 0, no_owner = 0;
+#ifndef NO_CCS
rg_state_t svc_state;
struct dlm_lksb lockp;
+#endif
ENTER();
@@ -408,7 +410,7 @@
RETURN(FOD_BEST);
}
- if (get_rg_state(rg_name, &svc_state) == FAIL) {
+ if (get_rg_state(rg_name, &svc_state) == RG_EFAIL) {
/*
* Couldn't get the service state, thats odd
*/
--- cluster/rgmanager/src/daemons/groups.c 2006/07/11 23:52:41 1.19
+++ cluster/rgmanager/src/daemons/groups.c 2006/07/19 18:43:32 1.20
@@ -36,6 +36,7 @@
#define cn_svccount cn_address.cna_address[0] /* Theses are uint8_t size */
#define cn_svcexcl cn_address.cna_address[1]
+extern char *res_ops[];
static int config_version = 0;
static resource_t *_resources = NULL;
static resource_rule_t *_rules = NULL;
@@ -61,7 +62,7 @@
@see node_should_start
*/
int
-node_should_start_safe(uint64_t nodeid, cluster_member_list_t *membership,
+node_should_start_safe(uint32_t nodeid, cluster_member_list_t *membership,
char *rg_name)
{
int ret;
@@ -78,7 +79,7 @@
count_resource_groups(cluster_member_list_t *ml)
{
resource_t *res;
- char *rgname, *val;
+ char rgname[64], *val;
int x;
rg_state_t st;
struct dlm_lksb lockp;
@@ -92,10 +93,8 @@
pthread_rwlock_rdlock(&resource_lock);
list_do(&_resources, res) {
- if (res->r_rule->rr_root == 0)
- continue;
- rgname = res->r_attrs[0].ra_value;
+ res_build_name(rgname, sizeof(rgname), res);
if (rg_lock(rgname, &lockp) < 0) {
clulog(LOG_ERR, "#XX: Unable to obtain cluster "
@@ -143,14 +142,14 @@
- Failover domain (ordering / restricted policy)
- Exclusive service policy
*/
-uint64_t
-best_target_node(cluster_member_list_t *allowed, uint64_t owner,
+uint32_t
+best_target_node(cluster_member_list_t *allowed, uint32_t owner,
char *rg_name, int lock)
{
int x;
int highscore = 1;
int score;
- uint64_t highnode = owner, nodeid;
+ uint32_t highnode = owner, nodeid;
char *val;
resource_t *res;
int exclusive;
@@ -364,7 +363,7 @@
void
-consider_relocate(char *svcName, rg_state_t *svcStatus, uint64_t nodeid,
+consider_relocate(char *svcName, rg_state_t *svcStatus, uint32_t nodeid,
cluster_member_list_t *membership)
{
int a, b;
@@ -409,7 +408,7 @@
* @see node_event
*/
int
-eval_groups(int local, uint64_t nodeid, int nodeStatus)
+eval_groups(int local, uint32_t nodeid, int nodeStatus)
{
struct dlm_lksb lockp;
char svcName[64], *nodeName;
@@ -611,6 +610,56 @@
}
+/**
+ Tells us if a resource group can be migrated.
+ */
+int
+group_migratory(char *groupname)
+{
+ resource_node_t *rn;
+ resource_t *res;
+ int migrate = 0, x;
+
+ pthread_rwlock_rdlock(&resource_lock);
+
+ res = find_root_by_ref(&_resources, groupname);
+ if (!res) {
+ pthread_rwlock_unlock(&resource_lock);
+ /* Nonexistent or non-TL RG cannot be migrated */
+ return 0;
+ }
+
+ for (x = 0; res->r_rule->rr_actions[x].ra_name; x++) {
+ if (!strcmp(res->r_rule->rr_actions[x].ra_name,
+ "migrate")) {
+ migrate = 1;
+ break;
+ }
+ }
+
+ if (!migrate) {
+ pthread_rwlock_unlock(&resource_lock);
+ /* resource rule missing 'migrate' command */
+ return 0;
+ }
+
+ list_do(&_tree, rn) {
+ if (rn->rn_resource == res && rn->rn_child) {
+ pthread_rwlock_unlock(&resource_lock);
+ /* TL service w/ children cannot be migrated */
+ return 0;
+ }
+ } while (!list_done(&_tree, rn));
+
+ pthread_rwlock_unlock(&resource_lock);
+
+ /* Ok, we have a migrate option to the resource group,
+ the resource group has no children, and the resource
+ group exists. We're all good */
+ return 1;
+}
+
+
/**
Perform an operation on a resource group. That is, walk down the
@@ -678,6 +727,38 @@
}
+int
+group_migrate(char *groupname, int target)
+{
+ resource_t *res;
+ char *tgt_name;
+ int ret = RG_ENOSERVICE;
+ cluster_member_list_t *membership;
+
+ membership = member_list();
+ if (!membership)
+ return RG_EFAIL;
+
+ pthread_rwlock_rdlock(&resource_lock);
+
+ tgt_name = memb_id_to_name(membership, target);
+ res = find_root_by_ref(&_resources, groupname);
+ if (!res)
+ goto out;
+
+ if (!tgt_name) {
+ ret = RG_EINVAL;
+ goto out;
+ }
+ ret = res_exec(res, res_ops[RG_MIGRATE], tgt_name);
+
+out:
+ pthread_rwlock_unlock(&resource_lock);
+ free_member_list(membership);
+ return ret;
+}
+
+
/**
Gets an attribute of a resource group.
--- cluster/rgmanager/src/daemons/resrules.c 2006/06/02 17:37:10 1.12
+++ cluster/rgmanager/src/daemons/resrules.c 2006/07/19 18:43:32 1.13
@@ -52,12 +52,6 @@
newrule->rr_type);
return -1;
}
- if (newrule->rr_root && curr->rr_root) {
- fprintf(stderr, "Error storing %s: root "
- "resource type %s exists already\n",
- newrule->rr_type, curr->rr_type);
- return -1;
- }
} while (!list_done(rulelist, curr));
@@ -185,30 +179,6 @@
}
-/**
- Get and store the root attribute.
-
- @param doc Pre-parsed XML document pointer.
- @param ctx Pre-allocated XML XPath context pointer.
- @param base XPath prefix to search
- @param rr Resource rule to store new information in.
- */
-void
-_get_root(xmlDocPtr doc, xmlXPathContextPtr ctx, char *base,
- resource_rule_t *rr)
-{
- char xpath[256];
- char *ret = NULL;
-
- snprintf(xpath, sizeof(xpath), "%s/attributes/@root", base);
- ret = xpath_get_one(doc, ctx, xpath);
- if (ret) {
- rr->rr_root = 1;
- free(ret);
- }
-}
-
-
int
expand_time(char *val)
{
@@ -355,8 +325,6 @@
free(act);
} while (1);
-
-
}
@@ -486,10 +454,7 @@
{
int x;
- printf("Resource Rules for \"%s\"", rr->rr_type);
- if (rr->rr_root)
- printf(" [ROOT]");
- printf("\n");
+ printf("Resource Rules for \"%s\"\n", rr->rr_type);
if (rr->rr_version)
printf("OCF API Version: %s\n", rr->rr_version);
@@ -550,7 +515,7 @@
children:
- printf("Recognized child resource types:\n");
+ printf("Explicitly defined child resource types:\n");
if (!rr->rr_childtypes) {
printf(" - None -\n\n");
return;
@@ -917,12 +882,11 @@
snprintf(base, sizeof(base),
"/resource-agent[%d]/special[@tag=\"rgmanager\"]",
ruleid);
- _get_root(doc, ctx, base, rr);
_get_maxparents(doc, ctx, base, rr);
rr->rr_agent = strdup(filename);
/*
- Second, add the allowable-children fields
+ Second, add the children fields
*/
_get_childtypes(doc, ctx, base, rr);
--- cluster/rgmanager/src/daemons/restree.c 2006/07/11 23:52:41 1.20
+++ cluster/rgmanager/src/daemons/restree.c 2006/07/19 18:43:32 1.21
@@ -70,7 +70,8 @@
"condstop",
"monitor",
"meta-data", /* printenv */
- "validate-all"
+ "validate-all",
+ "migrate"
};
@@ -215,14 +216,13 @@
Allocate and fill an environment variable array.
@param node Node in resource tree to use for parameters
- @param op Operation (start/stop/status/monitor/etc.)
@param depth Depth (status/monitor/etc.)
@return Newly allocated environment array or NULL if
one could not be formed.
@see kill_env res_exec add_ocf_stuff
*/
static char **
-build_env(resource_node_t *node, int op, int depth)
+build_env(resource_node_t *node, int depth)
{
resource_t *res = node->rn_resource;
char **env;
@@ -327,7 +327,7 @@
@see build_env
*/
int
-res_exec(resource_node_t *node, int op, int depth)
+res_exec(resource_node_t *node, const char *op, const char *arg, int depth)
{
int childpid, pid;
int ret = 0;
@@ -339,7 +339,7 @@
return 0;
#ifdef DEBUG
- env = build_env(node, op);
+ env = build_env(node, depth);
if (!env)
return -errno;
#endif
@@ -360,7 +360,7 @@
#endif
#ifndef DEBUG
- env = build_env(node, op, depth);
+ env = build_env(node, depth);
#endif
if (!env)
@@ -375,7 +375,10 @@
restore_signals();
- execle(fullpath, fullpath, res_ops[op], NULL, env);
+ if (arg)
+ execle(fullpath, fullpath, op, arg, NULL, env);
+ else
+ execle(fullpath, fullpath, op, NULL, env);
}
#ifdef DEBUG
@@ -395,7 +398,7 @@
if (ret) {
clulog(LOG_NOTICE,
"%s on %s \"%s\" returned %d (%s)\n",
- res_ops[op], res->r_rule->rr_type,
+ op, res->r_rule->rr_type,
res->r_attrs->ra_value, ret,
ocf_strerror(ret));
}
@@ -584,9 +587,6 @@
/* Find and build the list of root nodes */
list_do(rulelist, curr) {
- if (!curr->rr_root)
- continue;
-
build_tree(ccsfd, &root, NULL, curr, rulelist, reslist, tok);
} while (!list_done(rulelist, curr));
@@ -847,7 +847,7 @@
return 0;
node->rn_actions[idx].ra_last = now;
- if ((x = res_exec(node, RS_STATUS,
+ if ((x = res_exec(node, res_ops[RS_STATUS], NULL,
node->rn_actions[idx].ra_depth)) == 0)
return 0;
@@ -855,7 +855,7 @@
return x;
/* Strange/failed status. Try to recover inline. */
- if ((x = res_exec(node, RS_RECOVER, 0)) == 0)
+ if ((x = res_exec(node, res_ops[RS_RECOVER], NULL, 0)) == 0)
return 0;
return x;
@@ -1005,7 +1005,7 @@
if (me && (op == RS_START)) {
node->rn_flags &= ~RF_NEEDSTART;
- rv = res_exec(node, op, 0);
+ rv = res_exec(node, res_ops[op], NULL, 0);
if (rv != 0) {
node->rn_state = RES_FAILED;
return rv;
@@ -1029,7 +1029,7 @@
/* Stop/status/etc stops after children have stopped */
if (me && (op == RS_STOP)) {
node->rn_flags &= ~RF_NEEDSTOP;
- rv = res_exec(node, op, 0);
+ rv = res_exec(node, res_ops[op], NULL, 0);
if (rv != 0) {
node->rn_state = RES_FAILED;
--- cluster/rgmanager/src/daemons/rg_queue.c 2006/06/02 17:37:10 1.4
+++ cluster/rgmanager/src/daemons/rg_queue.c 2006/07/19 18:43:32 1.5
@@ -26,7 +26,7 @@
int
_rq_queue_request(request_t **queue, char *name, uint32_t request,
uint32_t err, uint32_t oldreq, msgctx_t *ctx, time_t when,
- uint64_t target, uint32_t arg0, uint32_t arg1, char *file,
+ uint32_t target, uint32_t arg0, uint32_t arg1, char *file,
int line)
{
request_t *req;
--- cluster/rgmanager/src/daemons/rg_state.c 2006/07/11 23:52:41 1.17
+++ cluster/rgmanager/src/daemons/rg_state.c 2006/07/19 18:43:32 1.18
@@ -32,9 +32,9 @@
#include <rg_queue.h>
#include <msgsimple.h>
-int node_should_start_safe(uint64_t, cluster_member_list_t *, char *);
+int node_should_start_safe(uint32_t, cluster_member_list_t *, char *);
-uint64_t next_node_id(cluster_member_list_t *membership, uint64_t me);
+uint32_t next_node_id(cluster_member_list_t *membership, uint32_t me);
int rg_exec_script(char *rgname, char *script, char *action);
static int _svc_stop_finish(char *svcName, int failed, uint32_t newstate);
@@ -43,13 +43,14 @@
int get_rg_state(char *servicename, rg_state_t *svcblk);
void get_recovery_policy(char *rg_name, char *buf, size_t buflen);
int check_depend_safe(char *servicename);
+int group_migratory(char *servicename);
-uint64_t
-next_node_id(cluster_member_list_t *membership, uint64_t me)
+uint32_t
+next_node_id(cluster_member_list_t *membership, uint32_t me)
{
- uint64_t low = (uint64_t)(-1);
- uint64_t next = me, curr;
+ uint32_t low = (uint32_t)(-1);
+ uint32_t next = me, curr;
int x;
for (x = 0; x < membership->cml_count; x++) {
@@ -293,7 +294,7 @@
if (ret != VFR_OK) {
free_member_list(membership);
printf("Couldn't initialize rg %s!\n", name);
- return FAIL;
+ return RG_EFAIL;
}
ret = vf_read(membership, res, &viewno, &data, &datalen);
@@ -302,7 +303,7 @@
free(data);
free_member_list(membership);
printf("Couldn't reread rg %s! (%d)\n", name, ret);
- return FAIL;
+ return RG_EFAIL;
}
}
@@ -312,7 +313,7 @@
if (data)
free(data);
free_member_list(membership);
- return FAIL;
+ return RG_EFAIL;
}
/* Copy out the data. */
@@ -353,7 +354,7 @@
svcblk->rs_transition = 0;
strncpy(svcblk->rs_name, name, sizeof(svcblk->rs_name));
- return FAIL;
+ return RG_EFAIL;
}
/* Copy out the data. */
@@ -370,7 +371,7 @@
* @param svcStatus Current service status.
* @param svcName Service name
* @param req Specify request to perform
- * @return 0 = DO NOT stop service, return FAIL
+ * @return 0 = DO NOT stop service, return RG_EFAIL
* 1 = STOP service - return whatever it returns.
* 2 = DO NOT stop service, return 0 (success)
* 3 = DO NOT stop service, return RG_EFORWARD
@@ -496,7 +497,7 @@
* @param svcName Service name
* @param flags Specify whether or not it's legal to start a
* disabled service, etc.
- * @return 0 = DO NOT start service, return FAIL
+ * @return 0 = DO NOT start service, return RG_EFAIL
* 1 = START service - return whatever it returns.
* 2 = DO NOT start service, return 0
* 3 = DO NOT start service, return RG_EAGAIN
@@ -563,7 +564,7 @@
}
/*
- * Service is running but owner is down -> FAILOVER
+ * Service is running but owner is down -> RG_EFAILOVER
*/
clulog(LOG_NOTICE,
"Taking over service %s from down member %s\n",
@@ -656,21 +657,21 @@
if (rg_lock(svcName, &lockp) < 0) {
clulog(LOG_ERR, "#45: Unable to obtain cluster lock: %s\n",
strerror(errno));
- return FAIL;
+ return RG_EFAIL;
}
if (get_rg_state(svcName, &svcStatus) != 0) {
rg_unlock(&lockp);
clulog(LOG_ERR, "#46: Failed getting status for RG %s\n",
svcName);
- return FAIL;
+ return RG_EFAIL;
}
/* LOCK HELD */
switch (svc_advise_start(&svcStatus, svcName, req)) {
- case 0: /* Don't start service, return FAIL */
+ case 0: /* Don't start service, return RG_EFAIL */
rg_unlock(&lockp);
- return FAIL;
+ return RG_EFAIL;
case 2: /* Don't start service, return 0 */
rg_unlock(&lockp);
return 0;
@@ -696,7 +697,7 @@
clulog(LOG_ERR,
"#47: Failed changing service status\n");
rg_unlock(&lockp);
- return FAIL;
+ return RG_EFAIL;
}
rg_unlock(&lockp);
@@ -708,7 +709,7 @@
if (rg_lock(svcName, &lockp) < 0) {
clulog(LOG_ERR, "#74: Unable to obtain cluster lock: %s\n",
strerror(errno));
- return FAIL;
+ return RG_EFAIL;
}
svcStatus.rs_state = RG_STATE_STARTED;
@@ -716,7 +717,7 @@
clulog(LOG_ERR,
"#75: Failed changing service status\n");
rg_unlock(&lockp);
- return FAIL;
+ return RG_EFAIL;
}
rg_unlock(&lockp);
@@ -737,40 +738,138 @@
/**
+ * Migrate a service to another node.
+ */
+int
+svc_migrate(char *svcName, int target)
+{
+ struct dlm_lksb lockp;
+ rg_state_t svcStatus;
+ int ret;
+
+ if (!group_migratory(svcName))
+ return RG_EINVAL;
+
+ if (rg_lock(svcName, &lockp) < 0) {
+ clulog(LOG_ERR, "#45: Unable to obtain cluster lock: %s\n",
+ strerror(errno));
+ return RG_EFAIL;
+ }
+
+ if (get_rg_state(svcName, &svcStatus) != 0) {
+ rg_unlock(&lockp);
+ clulog(LOG_ERR, "#46: Failed getting status for RG %s\n",
+ svcName);
+ return RG_EFAIL;
+ }
+
+ if (svcStatus.rs_owner != my_id()) {
+ rg_unlock(&lockp);
+ return RG_EFORWARD;
+ }
+
+ switch(svcStatus.rs_state) {
+ case RG_STATE_STARTED:
+ break;
+ case RG_STATE_STARTING:
+ case RG_STATE_STOPPING:
+ case RG_STATE_RECOVER:
+ case RG_STATE_MIGRATE:
+ case RG_STATE_ERROR:
+ rg_unlock(&lockp);
+ return RG_EAGAIN;
+ default:
+ rg_unlock(&lockp);
+ return RG_EFAIL;
+ }
+
+ /* LOCK HELD */
+ svcStatus.rs_owner = target;
+ svcStatus.rs_last_owner = my_id();
+ svcStatus.rs_state = RG_STATE_MIGRATE;
+ svcStatus.rs_transition = (uint64_t)time(NULL);
+
+ if (set_rg_state(svcName, &svcStatus) != 0) {
+ clulog(LOG_ERR,
+ "#75: Failed changing service status\n");
+ rg_unlock(&lockp);
+ return RG_EFAIL;
+ }
+ rg_unlock(&lockp);
+
+ ret = group_migrate(svcName, target);
+ return ret;
+}
+
+
+/**
* Check status of a cluster service
*
* @param svcName Service name to check.
- * @return RG_EFORWARD, FAIL, 0
+ * @return RG_EFORWARD, RG_EFAIL, 0
*/
int
svc_status(char *svcName)
{
struct dlm_lksb lockp;
rg_state_t svcStatus;
+ int ret;
if (rg_lock(svcName, &lockp) < 0) {
clulog(LOG_ERR, "#48: Unable to obtain cluster lock: %s\n",
strerror(errno));
- return FAIL;
+ return RG_EFAIL;
}
if (get_rg_state(svcName, &svcStatus) != 0) {
rg_unlock(&lockp);
clulog(LOG_ERR, "#49: Failed getting status for RG %s\n",
svcName);
- return FAIL;
+ return RG_EFAIL;
}
rg_unlock(&lockp);
if (svcStatus.rs_owner != my_id())
/* Don't check status for anything not owned */
- return SUCCESS;
+ return 0;
- if (svcStatus.rs_state != RG_STATE_STARTED)
+ if (svcStatus.rs_state != RG_STATE_STARTED &&
+ svcStatus.rs_state != RG_STATE_MIGRATE)
/* Not-running RGs should not be checked either. */
- return SUCCESS;
+ return 0;
- return group_op(svcName, RG_STATUS);
+ ret = group_op(svcName, RG_STATUS);
+
+ /* For running services, just check the return code */
+ if (svcStatus.rs_state == RG_STATE_STARTED)
+ return ret;
+
+ /* For service(s) migrating to the local node, ignore invalid
+ return codes.
+ XXX Should put a timeout on migrating services */
+ if (ret < 0)
+ return 0;
+
+ /* If the check succeeds (returns 0), then flip the state back to
+ 'started' - we now own the service */
+ if (rg_lock(svcName, &lockp) < 0) {
+ clulog(LOG_ERR, "#45: Unable to obtain cluster lock: %s\n",
+ strerror(errno));
+ return RG_EFAIL;
+ }
+
+ svcStatus.rs_state = RG_STATE_STARTED;
+ if (set_rg_state(svcName, &svcStatus) != 0) {
+ rg_unlock(&lockp);
+ clulog(LOG_ERR, "#46: Failed getting status for RG %s\n",
+ svcName);
+ return RG_EFAIL;
+ }
+ rg_unlock(&lockp);
+
+ clulog(LOG_NOTICE, "%s is now running locally\n", svcName);
+
+ return 0;
}
@@ -795,17 +894,17 @@
return group_op(svcName, RG_STOP);
}
- if (rg_lock(svcName, &lockp) == FAIL) {
+ if (rg_lock(svcName, &lockp) == RG_EFAIL) {
clulog(LOG_ERR, "#50: Unable to obtain cluster lock: %s\n",
strerror(errno));
- return FAIL;
+ return RG_EFAIL;
}
if (get_rg_state(svcName, &svcStatus) != 0) {
rg_unlock(&lockp);
clulog(LOG_ERR, "#51: Failed getting status for RG %s\n",
svcName);
- return FAIL;
+ return RG_EFAIL;
}
switch (svc_advise_stop(&svcStatus, svcName, req)) {
@@ -813,10 +912,10 @@
rg_unlock(&lockp);
clulog(LOG_DEBUG, "Unable to stop RG %s in %s state\n",
svcName, rg_state_str(svcStatus.rs_state));
- return FAIL;
+ return RG_EFAIL;
case 2:
rg_unlock(&lockp);
- return SUCCESS;
+ return RG_ESUCCESS;
case 3:
rg_unlock(&lockp);
return RG_EFORWARD;
@@ -840,7 +939,7 @@
if (set_rg_state(svcName, &svcStatus) != 0) {
rg_unlock(&lockp);
clulog(LOG_ERR, "#52: Failed changing RG status\n");
- return FAIL;
+ return RG_EFAIL;
}
rg_unlock(&lockp);
@@ -858,17 +957,17 @@
rg_state_t svcStatus;
struct dlm_lksb lockp;
- if (rg_lock(svcName, &lockp) == FAIL) {
+ if (rg_lock(svcName, &lockp) == RG_EFAIL) {
clulog(LOG_ERR, "#53: Unable to obtain cluster lock: %s\n",
strerror(errno));
- return FAIL;
+ return RG_EFAIL;
}
if (get_rg_state(svcName, &svcStatus) != 0) {
rg_unlock(&lockp);
clulog(LOG_ERR, "#54: Failed getting status for RG %s\n",
svcName);
- return FAIL;
+ return RG_EFAIL;
}
if ((svcStatus.rs_state != RG_STATE_STOPPING) &&
@@ -899,7 +998,7 @@
if (set_rg_state(svcName, &svcStatus) != 0) {
rg_unlock(&lockp);
clulog(LOG_ERR, "#55: Failed changing RG status\n");
- return FAIL;
+ return RG_EFAIL;
}
rg_unlock(&lockp);
@@ -944,10 +1043,10 @@
struct dlm_lksb lockp;
rg_state_t svcStatus;
- if (rg_lock(svcName, &lockp) == FAIL) {
+ if (rg_lock(svcName, &lockp) == RG_EFAIL) {
clulog(LOG_ERR, "#55: Unable to obtain cluster lock: %s\n",
strerror(errno));
- return FAIL;
+ return RG_EFAIL;
}
clulog(LOG_DEBUG, "Handling failure request for RG %s\n", svcName);
@@ -956,7 +1055,7 @@
rg_unlock(&lockp);
clulog(LOG_ERR, "#56: Failed getting status for RG %s\n",
svcName);
- return FAIL;
+ return RG_EFAIL;
}
if ((svcStatus.rs_state == RG_STATE_STARTED) &&
@@ -964,7 +1063,7 @@
rg_unlock(&lockp);
clulog(LOG_DEBUG, "Unable to disable RG %s in %s state\n",
svcName, rg_state_str(svcStatus.rs_state));
- return FAIL;
+ return RG_EFAIL;
}
/*
@@ -980,7 +1079,7 @@
if (set_rg_state(svcName, &svcStatus) != 0) {
rg_unlock(&lockp);
clulog(LOG_ERR, "#57: Failed changing RG status\n");
- return FAIL;
+ return RG_EFAIL;
}
rg_unlock(&lockp);
@@ -994,7 +1093,7 @@
* Send a message to the target node to start the service.
*/
static int
-relocate_service(char *svcName, int request, uint64_t target)
+relocate_service(char *svcName, int request, uint32_t target)
{
SmMessageSt msg_relo;
int msg_ret;
@@ -1049,7 +1148,7 @@
clulog(LOG_WARNING,
"#XX: Cancelling relocation: Shutting down\n");
msg_close(&ctx);
- return NO;
+ return RG_NO;
}
/* Check for node transition in the middle of a relocate */
@@ -1062,7 +1161,7 @@
"#XX: Cancelling relocation: Target node down\n");
free_member_list(ml);
msg_close(&ctx);
- return FAIL;
+ return RG_EFAIL;
} while (1);
if (msg_ret != sizeof (SmMessageSt)) {
@@ -1110,7 +1209,7 @@
int *new_owner)
{
cluster_member_list_t *allowed_nodes, *backup = NULL;
- uint64_t target = preferred_target, me = my_id();
+ uint32_t target = preferred_target, me = my_id();
int ret, x;
/*
@@ -1118,9 +1217,9 @@
*/
if (request != RG_START_RECOVER) {
ret = _svc_stop(svcName, request, 0, RG_STATE_STOPPED);
- if (ret == FAIL) {
+ if (ret == RG_EFAIL) {
svc_fail(svcName);
- return FAIL;
+ return RG_EFAIL;
}
if (ret == RG_EFORWARD)
return RG_EFORWARD;
@@ -1214,8 +1313,8 @@
case RG_EABORT:
svc_report_failure(svcName);
free_member_list(allowed_nodes);
- return FAIL;
- case NO:
+ return RG_EFAIL;
+ case RG_NO:
/* state uncertain */
free_member_list(allowed_nodes);
clulog(LOG_DEBUG, "State Uncertain: svc:%s "
@@ -1242,7 +1341,7 @@
* We're DONE.
*/
if (request == RG_START_RECOVER)
- return FAIL;
+ return RG_EFAIL;
/*
* All potential places for the service to start have been exhausted.
@@ -1255,7 +1354,7 @@
svcName);
if (svc_start(svcName, RG_START_RECOVER) == 0) {
*new_owner = me;
- return FAIL;
+ return RG_EFAIL;
}
}
@@ -1264,7 +1363,7 @@
svc_report_failure(svcName);
}
- return FAIL;
+ return RG_EFAIL;
}
@@ -1296,7 +1395,7 @@
(node_should_start_safe(my_id(), membership, svcName) <
tolerance)) {
free_member_list(membership);
- return FAIL;
+ return RG_EFAIL;
}
free_member_list(membership);
@@ -1320,14 +1419,14 @@
/*
* If we succeeded, then we're done.
*/
- if (ret == SUCCESS) {
+ if (ret == RG_ESUCCESS) {
*new_owner = my_id();
- return SUCCESS;
+ return RG_ESUCCESS;
}
/* Already running? */
- if (ret == NO) {
- return SUCCESS;
+ if (ret == RG_NO) {
+ return RG_ESUCCESS;
}
/*
@@ -1359,7 +1458,7 @@
/* If we leave the service stopped, instead of disabled, someone
will try to start it after the next node transition */
- if (ret == FAIL) {
+ if (ret == RG_EFAIL) {
if (svc_stop(svcName, RG_STOP) != 0) {
svc_fail(svcName);
svc_report_failure(svcName);
@@ -1384,7 +1483,7 @@
{
int tolerance = FOD_BEST;
int x;
- uint64_t me = my_id();
+ uint32_t me = my_id();
cluster_member_list_t *membership = member_list();
/* XXX ok, so we need to say "should I start this if I was the
@@ -1404,7 +1503,7 @@
*/
if (node_should_start_safe(me, membership, svcName) < tolerance){
free_member_list(membership);
- return FAIL;
+ return RG_EFAIL;
}
free_member_list(membership);
@@ -1412,7 +1511,7 @@
return 0;
if (svc_stop(svcName, RG_STOP_RECOVER) == 0)
- return FAIL;
+ return RG_EFAIL;
svc_fail(svcName);
return RG_EABORT;
--- cluster/rgmanager/src/daemons/rg_thread.c 2006/06/02 17:37:10 1.13
+++ cluster/rgmanager/src/daemons/rg_thread.c 2006/07/19 18:43:32 1.14
@@ -48,7 +48,7 @@
static resthread_t *find_resthread_byname(const char *resgroupname);
static int spawn_if_needed(const char *resgroupname);
int rt_enqueue_request(const char *resgroupname, int request,
- msgctx_t *response_ctx, int max, uint64_t target,
+ msgctx_t *response_ctx, int max, uint32_t target,
int arg0, int arg1);
@@ -248,6 +248,26 @@
ret = RG_NONE;
break;
+ case RG_MIGRATE:
+ error = svc_migrate(myname, req->rr_target);
+
+ if (error == 0) {
+ ret = RG_SUCCESS;
+
+ pthread_mutex_lock(&my_queue_mutex);
+ purge_status_checks(&my_queue);
+ pthread_mutex_unlock(&my_queue_mutex);
+ } else if (error == RG_EFORWARD) {
+ ret = RG_NONE;
+ break;
+ } else {
+ /*
+ * Bad news.
+ */
+ ret = RG_FAIL;
+ }
+ break;
+
case RG_INIT:
/* Stop without changing shared state of it */
error = group_op(myname, RG_STOP);
@@ -551,7 +571,7 @@
int
rt_enqueue_request(const char *resgroupname, int request,
msgctx_t *response_ctx,
- int max, uint64_t target, int arg0, int arg1)
+ int max, uint32_t target, int arg0, int arg1)
{
request_t *curr;
int count = 0, ret;
--- cluster/rgmanager/src/daemons/test.c 2006/07/11 23:52:41 1.5
+++ cluster/rgmanager/src/daemons/test.c 2006/07/19 18:43:32 1.6
@@ -90,7 +90,7 @@
conf_setconfig(argv[1]);
ccsfd = ccs_lock();
- if (ccsfd == FAIL) {
+ if (ccsfd < 0) {
printf("Error parsing %s\n", argv[1]);
goto out;
}
--- cluster/rgmanager/src/resources/ra-api-1-modified.dtd 2005/01/21 18:11:36 1.2
+++ cluster/rgmanager/src/resources/ra-api-1-modified.dtd 2006/07/19 18:43:32 1.3
@@ -42,7 +42,7 @@
<!ELEMENT action EMPTY>
<!ATTLIST action
- name (start|stop|recover|status|monitor|reload|meta-data|verify-all) #REQUIRED
+ name (start|stop|recover|status|monitor|reload|meta-data|verify-all|migrate) #REQUIRED
timeout CDATA #REQUIRED
interval CDATA #IMPLIED
start-delay CDATA #IMPLIED
--- cluster/rgmanager/src/resources/xenvm.sh 2006/07/12 16:53:09 1.2
+++ cluster/rgmanager/src/resources/xenvm.sh 2006/07/19 18:43:32 1.3
@@ -181,6 +181,7 @@
<!-- Suspend: if available, suspend this resource instead of
doing a full stop. -->
<!-- <action name="suspend" timeout="10m"/> -->
+ <action name="migrate" timeout="10m"/>
<action name="meta-data" timeout="5"/>
<action name="verify-all" timeout="5"/>
@@ -403,6 +404,15 @@
fi
}
+
+migrate()
+{
+ declare target=$1
+
+ # XXX TODO; requires working Xen
+ return 1
+}
+
#
# A Resource group is abstract, but the OCF RA API doesn't allow for abstract
# resources, so here it is.
@@ -427,6 +437,10 @@
status
exit $?
;;
+ migrate)
+ migrate $2 # Send Xen VM to this node
+ exit $?
+ ;;
reload)
exit 0
;;
--- cluster/rgmanager/src/utils/Makefile 2006/07/12 14:38:01 1.11
+++ cluster/rgmanager/src/utils/Makefile 2006/07/19 18:43:32 1.12
@@ -20,9 +20,9 @@
CFLAGS+= -g -Wstrict-prototypes -Wshadow -fPIC -D_GNU_SOURCE
-CFLAGS+= -L${libdir} -DPACKAGE_VERSION=\"${RELEASE}\"
+CFLAGS+= -DPACKAGE_VERSION=\"${RELEASE}\"
-LDFLAGS+= -L../../../cman/lib -L../../../ccs/lib -lcman -lpthread -ldl -lncurses -L../clulib -lclulib -lccs
+LDFLAGS+= -L${libdir} -L../../../cman/lib -L../../../ccs/lib -lcman -lpthread -ldl -lncurses -L../clulib -lclulib -lccs
TARGETS=clubufflush clufindhostname clustat clusvcadm clulog clunfslock
all: ${TARGETS}
@@ -44,7 +44,7 @@
$(CC) -o $@ $^ $(INLUDE) $(CFLAGS) $(LDFLAGS)
clufindhostname: clufindhostname.o
- $(CC) -o $@ $^ $(INLUDE) $(CFLAGS) $(LDFLAGS)
+ $(CC) -o $@ $^ $(INLUDE) $(CFLAGS)
clustat: clustat.o
$(CC) -o $@ $^ $(INLUDE) $(CFLAGS) $(LDFLAGS)
--- cluster/rgmanager/src/utils/clusvcadm.c 2006/07/11 23:52:41 1.9
+++ cluster/rgmanager/src/utils/clusvcadm.c 2006/07/19 18:43:32 1.10
@@ -158,6 +158,9 @@
" 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 Xen VMs)\n");
printf(" %s -q Quiet operation\n", name);
printf(" %s -R <group> Restart a group in place.\n",
name);
@@ -186,7 +189,7 @@
SmMessageSt msg;
int action = RG_STATUS;
int node_specified = 0;
- int msgtarget, me, svctarget = 0;
+ int me, svctarget = 0;
char *actionstr = NULL;
cluster_member_list_t *membership;
@@ -224,6 +227,12 @@
action = RG_RELOCATE;
svcname = optarg;
break;
+ case 'M':
+ /* MIGRATE */
+ actionstr = "trying to migrate";
+ action = RG_MIGRATE;
+ svcname = optarg;
+ break;
case 's':
/* stop */
actionstr = "stopping";
@@ -237,7 +246,6 @@
break;
case 'm': /* member ... */
case 'n': /* node .. same thing */
-
strncpy(nodename,optarg,sizeof(nodename));
node_specified = 1;
break;
@@ -277,15 +285,14 @@
me = get_my_nodeid(ch);
if (node_specified) {
- msgtarget = memb_name_to_id(membership, nodename);
- if (msgtarget == 0) {
+ svctarget = memb_name_to_id(membership, nodename);
+ if (svctarget == 0) {
fprintf(stderr, "Member %s not in membership list\n",
nodename);
return 1;
}
- svctarget = msgtarget;
} else {
- msgtarget = me;
+ svctarget = me;
/*
clu_local_nodename(RG_SERVICE_GROUP, nodename,
sizeof(nodename));
@@ -295,7 +302,7 @@
strcpy(nodename,"me");
build_message(&msg, action, svcname, svctarget);
- if (action != RG_RELOCATE) {
+ if (action != RG_RELOCATE && action != RG_MIGRATE) {
printf("Member %s %s %s", nodename, actionstr, svcname);
printf("...");
fflush(stdout);
@@ -330,7 +337,7 @@
/* Decode */
swab_SmMessageSt(&msg);
switch (msg.sm_data.d_ret) {
- case SUCCESS:
+ case RG_ESUCCESS:
printf("success\n");
break;
case RG_EFAIL:
reply other threads:[~2006-07-19 18:43 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060719184334.25245.qmail@sourceware.org \
--to=lhh@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.