All of lore.kernel.org
 help / color / mirror / Atom feed
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.