cluster-devel.redhat.com archive mirror
 help / color / mirror / Atom feed
* [Cluster-devel] cluster/rgmanager ChangeLog include/res-ocf.h  ...
@ 2007-07-31 18:00 lhh
  0 siblings, 0 replies; 5+ messages in thread
From: lhh @ 2007-07-31 18:00 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	lhh at sourceware.org	2007-07-31 18:00:26

Modified files:
	rgmanager      : ChangeLog 
	rgmanager/include: res-ocf.h reslist.h 
	rgmanager/src/clulib: rg_strings.c 
	rgmanager/src/daemons: groups.c reslist.c resrules.c restree.c 
	                       test.c 
	rgmanager/src/resources: ra-api-1-modified.dtd service.sh vm.sh 

Log message:
	Fix bug #248727

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/ChangeLog.diff?cvsroot=cluster&r1=1.53&r2=1.54
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/res-ocf.h.diff?cvsroot=cluster&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/reslist.h.diff?cvsroot=cluster&r1=1.21&r2=1.22
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/clulib/rg_strings.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.37&r2=1.38
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/reslist.c.diff?cvsroot=cluster&r1=1.18&r2=1.19
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/resrules.c.diff?cvsroot=cluster&r1=1.22&r2=1.23
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/restree.c.diff?cvsroot=cluster&r1=1.34&r2=1.35
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/test.c.diff?cvsroot=cluster&r1=1.10&r2=1.11
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/ra-api-1-modified.dtd.diff?cvsroot=cluster&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/service.sh.diff?cvsroot=cluster&r1=1.10&r2=1.11
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/vm.sh.diff?cvsroot=cluster&r1=1.5&r2=1.6

--- cluster/rgmanager/ChangeLog	2007/07/23 20:49:13	1.53
+++ cluster/rgmanager/ChangeLog	2007/07/31 18:00:25	1.54
@@ -1,3 +1,23 @@
+2007-07-31 Lon Hohberger <lhh@redhat.com>
+	* general: Make VMs not change state when added/removed from the
+	cluster config or bounce services/VMs when minor config changes
+	are made. (#248727)
+	* include/res-ocf.h: Add reconfigure operation
+	* include/reslist.h: Add flags allowing reconfigurable options in
+	resource agent metadata, and per-agent flags which allow resources
+	to be added w/o initialization / removed w/o kill.
+	* src/clulib/rg_strings.c: Add string definition for reconfigure op
+	* src/daemons/groups.c: Allow no-init-on-add and no-kill-on-delete
+	flags to work
+	* src/daemons/reslist.c: Allow resource comparison to take into 
+	account reconfig flags and return a new value if the resource is
+	reconfigurable
+	* src/daemons/resrules.c: Code to support new flags
+	* src/daemons/restree.c: Code to support reconfiguration operation
+	* src/daemons/test.c: Code to support testing new reconfig ops and
+	behaviors
+	* src/resources/*: Add new flags to service and VM resource agents.
+
 2007-07-23 Lon Hohberger <lhh@redhat.com>
 	* general: make threads exit with pthread_exit() so we can wrap/track them.
 	Add internal statedump (SIGUSR1) support.
--- cluster/rgmanager/include/res-ocf.h	2007/03/10 00:20:54	1.2
+++ cluster/rgmanager/include/res-ocf.h	2007/07/31 18:00:25	1.3
@@ -62,5 +62,6 @@
 #define RS_META_DATA	(11)
 #define RS_VALIDATE	(12)
 #define RS_MIGRATE	(13)
+#define RS_RECONFIG	(14)
 
 #endif
--- cluster/rgmanager/include/reslist.h	2007/06/27 14:03:51	1.21
+++ cluster/rgmanager/include/reslist.h	2007/07/31 18:00:25	1.22
@@ -25,10 +25,11 @@
 #include <libxml/xpath.h>
 
 
-#define RA_PRIMARY	(1<<0)
-#define RA_UNIQUE	(1<<1)
-#define RA_REQUIRED	(1<<2)
-#define RA_INHERIT	(1<<3)
+#define RA_PRIMARY	(1<<0)	/** Primary key */
+#define RA_UNIQUE	(1<<1)	/** Unique for given type */
+#define RA_REQUIRED	(1<<2)	/** Required (or an error if not present */
+#define RA_INHERIT	(1<<3)	/** Inherit a parent resource's attr */
+#define RA_RECONFIG	(1<<4)	/** Allow inline reconfiguration */
 
 #define RF_INLINE	(1<<0)
 #define RF_DEFINED	(1<<1)
@@ -37,6 +38,15 @@
 #define RF_COMMON	(1<<4)	/** " */
 #define RF_INDEPENDENT	(1<<5)  /** Define this for a resource if it is
 				  otherwise an independent subtree */
+#define RF_RECONFIG	(1<<6)
+
+#define RF_INIT		(1<<7)	/** Resource rule: Initialize this resource
+				  class on startup */
+#define RF_DESTROY	(1<<8)	/** Resource rule flag: Destroy this
+				  resource class if you delete it from
+				  the configuration */
+
+
 
 #define RES_STOPPED	(0)
 #define RES_STARTED	(1)
--- cluster/rgmanager/src/clulib/rg_strings.c	2007/06/27 14:03:51	1.9
+++ cluster/rgmanager/src/clulib/rg_strings.c	2007/07/31 18:00:25	1.10
@@ -113,6 +113,7 @@
 	{RS_META_DATA, "meta-data"},		/* printenv */
 	{RS_VALIDATE, "validate-all"},
 	{RS_MIGRATE, "migrate"},
+	{RS_RECONFIG, "reconfig"},
 	{0 , NULL}
 };
 
--- cluster/rgmanager/src/daemons/groups.c	2007/07/23 20:49:13	1.37
+++ cluster/rgmanager/src/daemons/groups.c	2007/07/31 18:00:25	1.38
@@ -1225,6 +1225,7 @@
 do_condstops(void)
 {
 	resource_node_t *curr;
+	struct dlm_lksb lockp;
 	rg_state_t svcblk;
 	int need_kill;
 	char rg[64];
@@ -1252,6 +1253,24 @@
 			clulog(LOG_DEBUG, "Removing %s\n", rg);
 		}
 
+		if (!curr->rn_child && ((curr->rn_resource->r_rule->rr_flags &
+		    RF_DESTROY) == 0) && group_migratory(rg, 0) &&
+		    need_kill == 1) {
+			/* Do something smart here: flip state? */
+			clulog(LOG_NOTICE,
+			       "%s removed from the config, but I am not stopping it.\n",
+			       rg);
+			if (rg_lock(rg, &lockp) != 0)
+				continue;
+			if (get_rg_state(rg, &svcblk) < 0)
+		       		goto cont;
+			svcblk.rs_state = RG_STATE_DISABLED;
+			set_rg_state(rg, &svcblk);
+cont:
+			rg_unlock(&lockp);
+			continue;
+		}
+
 		rt_enqueue_request(rg, need_kill ? RG_DISABLE : RG_CONDSTOP,
 				   NULL, 0, 0, 0, 0);
 
@@ -1285,7 +1304,8 @@
 
 		/* New RG.  We'll need to initialize it. */
 		need_init = 0;
-		if (curr->rn_resource->r_flags & RF_NEEDSTART)
+		if (!(curr->rn_resource->r_flags & RF_RECONFIG) &&
+		    (curr->rn_resource->r_flags & RF_NEEDSTART))
 			need_init = 1;
 
 		if (!need_init) {
@@ -1308,7 +1328,17 @@
 
 		if (need_init) {
 			++new_groups;
-			clulog(LOG_DEBUG, "Initializing %s\n", rg);
+			clulog(LOG_NOTICE, "Initializing %s\n", rg);
+		}
+
+		if (!curr->rn_child && ((curr->rn_resource->r_rule->rr_flags &
+		    RF_INIT) == 0) && group_migratory(rg, 0) &&
+		    need_init == 1) {
+			/* Do something smart here? */
+			clulog(LOG_NOTICE,
+			       "%s was added to the config, but I am not initializing it.\n",
+			       rg);
+			continue;
 		}
 
 		rt_enqueue_request(rg, need_init ? RG_INIT : RG_CONDSTART,
--- cluster/rgmanager/src/daemons/reslist.c	2007/04/26 20:42:02	1.18
+++ cluster/rgmanager/src/daemons/reslist.c	2007/07/31 18:00:25	1.19
@@ -176,18 +176,29 @@
 /**
    Compare two resources.
 
+  @param left	Left resource
+  @param right	Right resource	
+  @return	-1 on different resource, 0 if the same, 1 if different,
+		2 if different, but only safe resources are different
+
  */
 int
 rescmp(resource_t *left, resource_t *right)
 {
-	int x, y = 0, found;
+	int x, y = 0, found = 0, ret = 0;
+
 
 	/* Completely different resource class... */
 	if (strcmp(left->r_rule->rr_type, right->r_rule->rr_type)) {
-		//printf("Er, wildly different resource type! ");
 		return -1;
 	}
 
+	/*
+	printf("Comparing %s:%s to %s:%s\n",
+	       left->r_rule->rr_type, left->r_attrs[0].ra_value,
+	       right->r_rule->rr_type, right->r_attrs[0].ra_value)
+	 */
+
 	for (x = 0; left->r_attrs && left->r_attrs[x].ra_name; x++) {
 
 		found = 0;
@@ -203,35 +214,52 @@
 			    left->r_attrs[x].ra_flags) {
 				/* Flags are different.  Change in
 				   resource agents? */
-				//printf("flags differ ");
+				/*
+				printf("* flags differ %08x vs %08x\n",
+				       left->r_attrs[x].ra_flags,
+				       right->r_attrs[y].ra_flags);
+				 */
 				return 1;
 			}
 
 			if (strcmp(right->r_attrs[y].ra_value,
 				   left->r_attrs[x].ra_value)) {
 				/* Different attribute value. */
-				//printf("different value for attr '%s'  ",
-				       //right->r_attrs[y].ra_name);
-				return 1;
+				/*
+				printf("* different value for attr '%s':"
+				       " '%s' vs '%s'",
+				       right->r_attrs[y].ra_name,
+				       left->r_attrs[x].ra_value,
+				       right->r_attrs[y].ra_value);
+				 */
+				if (left->r_attrs[x].ra_flags & RA_RECONFIG) {
+					/* printf(" [SAFE]\n"); */
+					ret = 2;
+			 	} else {
+					/* printf("\n"); */
+					return 1;
+				}
 			}
 		}
 
 		/* Attribute missing -> different attribute value. */
 		if (!found) {
-			//printf("Attribute %s deleted  ",
-			       //left->r_attrs[x].ra_name);
+			/*
+			printf("* Attribute '%s' deleted\n",
+			       left->r_attrs[x].ra_name);
+			 */
 			return 1;
 		}
 	}
 
 	/* Different attribute count */
 	if (x != y) {
-		//printf("Attribute count differ (attributes added!) ");
+		/* printf("* Attribute count differ (attributes added!) "); */
 		return 1;
 	}
 
 	/* All the same */
-	return 0;
+	return ret;
 }
 
 
@@ -288,7 +316,7 @@
 	resource_t *curr;
 	char ref_buf[128];
 	char *type;
-	char *name;
+	char *name = ref;
 	int x;
 
 	snprintf(ref_buf, sizeof(ref_buf), "%s", ref);
@@ -544,6 +572,8 @@
 		printf(" [NEEDSTOP]");
 	if (res->r_flags & RF_COMMON)
 		printf(" [COMMON]");
+	if (res->r_flags & RF_RECONFIG)
+		printf(" [RECONFIG]");
 	printf("\n");
 
 	if (res->r_rule->rr_maxrefs)
@@ -579,6 +609,8 @@
 			printf(" unique");
 		if (res->r_attrs[x].ra_flags & RA_REQUIRED)
 			printf(" required");
+		if (res->r_attrs[x].ra_flags & RA_RECONFIG)
+			printf(" reconfig");
 		if (res->r_attrs[x].ra_flags & RA_INHERIT)
 			printf(" inherit(\"%s\")", res->r_attrs[x].ra_value);
 		printf(" ]\n");
--- cluster/rgmanager/src/daemons/resrules.c	2007/05/31 19:08:14	1.22
+++ cluster/rgmanager/src/daemons/resrules.c	2007/07/31 18:00:25	1.23
@@ -175,6 +175,36 @@
 
 
 /**
+   Get and store a bit field.
+
+   @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_rule_flag(xmlDocPtr doc, xmlXPathContextPtr ctx, char *base,
+	       resource_rule_t *rr, char *flag, int bit)
+{
+	char xpath[256];
+	char *ret = NULL;
+
+	snprintf(xpath, sizeof(xpath),
+		 "%s/attributes/@%s",
+		 base, flag);
+	ret = xpath_get_one(doc, ctx, xpath);
+	if (ret) {
+		if (atoi(ret)) {
+			rr->rr_flags |= bit;
+		} else {
+			rr->rr_flags &= ~bit;
+		}
+		free(ret);
+	}
+}
+
+
+/**
    Get and store the version
 
    @param doc		Pre-parsed XML document pointer.
@@ -367,8 +397,8 @@
 		ret = xpath_get_one(doc, ctx, xpath);
 		if (ret) {
 			interval = expand_time(ret);
-			if (interval < 0)
-				interval = 0;
+			if (interval < 1)
+				interval = 1;
 			free(ret);
 		}
 
@@ -529,6 +559,17 @@
 		printf("Max instances: %d\n", rr->rr_maxrefs);
 	if (rr->rr_agent)
 		printf("Agent: %s\n", basename(rr->rr_agent));
+
+	printf("Flags: ");
+	if (rr->rr_flags) {
+		if (rr->rr_flags & RF_INIT)
+			printf("init_on_add ");
+		if (rr->rr_flags & RF_DESTROY)
+			printf("destroy_on_delete ");
+	} else {
+		printf("(none)");
+	}
+	printf("\n");
 	
 	printf("Attributes:\n");
 	if (!rr->rr_attrs) {
@@ -544,18 +585,25 @@
 			continue;
 		}
 
-		printf(" [");
-		if (rr->rr_attrs[x].ra_flags & RA_PRIMARY)
-			printf(" primary");
-		if (rr->rr_attrs[x].ra_flags & RA_UNIQUE)
-			printf(" unique");
-		if (rr->rr_attrs[x].ra_flags & RA_REQUIRED)
-			printf(" required");
-		if (rr->rr_attrs[x].ra_flags & RA_INHERIT)
-			printf(" inherit");
-		else if (rr->rr_attrs[x].ra_value)
-			printf(" default=\"%s\"", rr->rr_attrs[x].ra_value);
-		printf(" ]\n");
+		if (rr->rr_attrs[x].ra_flags) {
+			printf(" [");
+			if (rr->rr_attrs[x].ra_flags & RA_PRIMARY)
+				printf(" primary");
+			if (rr->rr_attrs[x].ra_flags & RA_UNIQUE)
+				printf(" unique");
+			if (rr->rr_attrs[x].ra_flags & RA_REQUIRED)
+				printf(" required");
+			if (rr->rr_attrs[x].ra_flags & RA_INHERIT)
+				printf(" inherit");
+			if (rr->rr_attrs[x].ra_flags & RA_RECONFIG)
+				printf(" reconfig");
+			printf(" ]");
+		}
+
+		if (rr->rr_attrs[x].ra_value)
+			printf(" default=\"%s\"\n", rr->rr_attrs[x].ra_value);
+		else
+			printf("\n");
 	}
 
 actions:
@@ -691,6 +739,18 @@
 		}
 
 		/*
+		   See if this can be reconfigured on the fly without a 
+		   stop/start
+		 */
+		snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@reconfig",
+			 base, x);
+		if ((ret = xpath_get_one(doc,ctx,xpath))) {
+			if ((atoi(ret) != 0) || (ret[0] == 'y'))
+				flags |= RA_RECONFIG;
+			free(ret);
+		}
+
+		/*
 		   See if this is supposed to be inherited
 		 */
 		snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@inherit",
@@ -955,6 +1015,7 @@
 			break;
 		memset(rr,0,sizeof(*rr));
 
+		rr->rr_flags = RF_INIT | RF_DESTROY;
 		rr->rr_type = type;
 		snprintf(base, sizeof(base), "/resource-agent[%d]", ruleid);
 
@@ -967,6 +1028,8 @@
 			 "/resource-agent[%d]/special[@tag=\"rgmanager\"]",
 			 ruleid);
 		_get_maxparents(doc, ctx, base, rr);
+		_get_rule_flag(doc, ctx, base, rr, "init_on_add", RF_INIT);
+		_get_rule_flag(doc, ctx, base, rr, "destroy_on_delete", RF_DESTROY);
 		rr->rr_agent = strdup(filename);
 
 		/*
--- cluster/rgmanager/src/daemons/restree.c	2007/06/27 14:03:51	1.34
+++ cluster/rgmanager/src/daemons/restree.c	2007/07/31 18:00:25	1.35
@@ -1213,9 +1213,15 @@
 
 	/* Start starts before children */
 	if (me && (op == RS_START)) {
-		node->rn_flags &= ~RF_NEEDSTART;
 
-		rv = res_exec(node, op, NULL, 0);
+		if (node->rn_flags & RF_RECONFIG &&
+		    realop == RS_CONDSTART) {
+			rv = res_exec(node, RS_RECONFIG, NULL, 0);
+			op = realop; /* reset to CONDSTART */
+		} else {
+			rv = res_exec(node, op, NULL, 0);
+		}
+		node->rn_flags &= ~(RF_NEEDSTART | RF_RECONFIG);
 		if (rv != 0) {
 			node->rn_state = RES_FAILED;
 			return SFL_FAILURE;
@@ -1435,6 +1441,7 @@
 resource_delta(resource_t **leftres, resource_t **rightres)
 {
 	resource_t *lc, *rc;
+	int ret;
 
 	list_do(leftres, lc) {
 		rc = find_resource_by_ref(rightres, lc->r_rule->rr_type,
@@ -1447,10 +1454,25 @@
 		}
 
 		/* Ok, see if the resource is the same */
-		if (rescmp(lc, rc) == 0) {
+		ret = rescmp(lc, rc);
+		if (ret	== 0) {
 			rc->r_flags |= RF_COMMON;
 			continue;
 		}
+
+		if (ret == 2) {
+			/* return of 2 from rescmp means
+			   the two resources differ only 
+			   by reconfigurable bits */
+			/* Do nothing on condstop phase;
+			   do a "reconfig" instead of 
+			   "start" on conststart phase */
+			rc->r_flags |= RF_COMMON;
+			rc->r_flags |= RF_NEEDSTART;
+			rc->r_flags |= RF_RECONFIG;
+			continue;
+		}
+
 		rc->r_flags |= RF_COMMON;
 
 		/* Resource has changed.  Flag it. */
@@ -1512,12 +1534,17 @@
 			   or is new), then we don't really care about its
 			   children.
 			 */
+
 			if (rn->rn_resource->r_flags & RF_NEEDSTART) {
 				rn->rn_flags |= RF_NEEDSTART;
-				continue;
+				if ((rn->rn_resource->r_flags & RF_RECONFIG) == 0)
+					continue;
 			}
 
-			if (rc == 0) {
+			if (rc == 0 || rc == 2) {
+				if (rc == 2)
+					rn->rn_flags |= RF_NEEDSTART | RF_RECONFIG;
+
 				/* Ok, same resource.  Recurse. */
 				ln->rn_flags |= RF_COMMON;
 				rn->rn_flags |= RF_COMMON;
--- cluster/rgmanager/src/daemons/test.c	2007/06/27 14:03:51	1.10
+++ cluster/rgmanager/src/daemons/test.c	2007/07/31 18:00:25	1.11
@@ -33,6 +33,50 @@
 #error "Can not be built with CCS support."
 #endif
 
+/**
+  Tells us if a resource group can be migrated.
+ */
+int
+group_migratory(resource_t **resources, resource_node_t **tree, char *groupname)
+{
+	resource_node_t *rn;
+	resource_t *res;
+	int migrate = 0, x, ret = 0;
+
+	res = find_root_by_ref(resources, groupname);
+	if (!res) {
+		/* 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)
+		goto out_unlock;
+
+	list_do(tree, rn) {
+		if (rn->rn_resource == res && rn->rn_child) {
+			/* TL service w/ children cannot be migrated */
+			goto out_unlock;
+		}
+	} while (!list_done(tree, rn));
+
+
+	/* 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 */
+	ret = 1;
+
+out_unlock:
+	return ret;
+}
+
 #define shift() {++argv; --argc;}
 
 #define USAGE_TEST \
@@ -252,7 +296,9 @@
 	resource_rule_t *rulelist = NULL, *currule, *rulelist2 = NULL;
 	resource_t *reslist = NULL, *curres, *reslist2 = NULL;
 	resource_node_t *tree = NULL, *tree2 = NULL;
-	int ccsfd, ret = 0;
+	resource_node_t *tn;
+	int ccsfd, ret = 0, need_init, need_kill;
+	char rg[64];
 
 	if (argc < 2) {
 		printf("Operation requires two arguments\n");
@@ -309,6 +355,57 @@
 	print_resource_tree(&tree);
 	printf("=== New Resource Tree ===\n");
 	print_resource_tree(&tree2);
+	printf("=== Operations (down-phase) ===\n");
+	list_do(&tree, tn) {
+		res_build_name(rg, sizeof(rg), tn->rn_resource);
+		/* Set state to uninitialized if we're killing a RG */
+		need_init = 0;
+
+		/* Set state to uninitialized if we're killing a RG */
+		need_kill = 0;
+		if (tn->rn_resource->r_flags & RF_NEEDSTOP) {
+			need_kill = 1;
+			printf("[kill] ");
+		}
+
+		if (!tn->rn_child && ((tn->rn_resource->r_rule->rr_flags &
+		    RF_DESTROY) == 0) && group_migratory(&reslist, &tree, rg) &&
+		    need_kill == 1) {
+			/* Do something smart here: flip state? */
+			printf("[no-op] %s was removed from the config, but I am not stopping it.\n",
+			       rg);
+			continue;
+		}
+
+		res_condstop(&tn, tn->rn_resource, NULL);
+	} while (!list_done(&tree, tn));
+	printf("=== Operations (up-phase) ===\n");
+	list_do(&tree2, tn) {
+		res_build_name(rg, sizeof(rg), tn->rn_resource);
+		/* New RG.  We'll need to initialize it. */
+		need_init = 0;
+		if (!(tn->rn_resource->r_flags & RF_RECONFIG) &&
+		    (tn->rn_resource->r_flags & RF_NEEDSTART))
+			need_init = 1;
+
+		if (need_init) {
+			printf("[init] ");
+		}
+
+		if (!tn->rn_child && ((tn->rn_resource->r_rule->rr_flags &
+		    RF_INIT) == 0) && group_migratory(&reslist2, &tree2, rg) &&
+		    need_init == 1) {
+			/* Do something smart here? */
+			printf("[noop] %s was added, but I am not initializing it\n", rg);
+			continue;
+		}
+
+		if (need_init) {
+			res_stop(&tn, tn->rn_resource, NULL);
+		} else {
+			res_condstart(&tn, tn->rn_resource, NULL);
+		}
+	} while (!list_done(&tree2, tn));
 
 out:
 	destroy_resource_tree(&tree2);
@@ -368,6 +465,7 @@
 			goto out;
 		} else if (!strcmp(argv[1], "delta")) {
 			shift();
+			_no_op_mode(1);
 			ret = tree_delta_test(argc, argv);
 			goto out;
 		} else {
--- cluster/rgmanager/src/resources/ra-api-1-modified.dtd	2006/08/18 15:26:22	1.4
+++ cluster/rgmanager/src/resources/ra-api-1-modified.dtd	2007/07/31 18:00:25	1.5
@@ -24,6 +24,7 @@
 	name	CDATA	#REQUIRED
 	primary (1|0)   "0"
 	required (1|0)	"0"
+	reconfig (1|0)	"0"
 	inherit CDATA	""
 	unique	(1|0)	"0"
 	reconfig (1|0)  "0">
@@ -43,7 +44,7 @@
 
 <!ELEMENT action EMPTY>
 <!ATTLIST action
-	name	(start|stop|recover|status|reconfig|monitor|reload|meta-data|verify-all|migrate)	#REQUIRED
+	name	(start|stop|recover|status|reconfig|monitor|reload|meta-data|verify-all|migrate|reconfig)	#REQUIRED
 	timeout		CDATA	#REQUIRED
 	interval 	CDATA	#IMPLIED
 	start-delay 	CDATA	#IMPLIED
@@ -56,7 +57,6 @@
 
 <!ELEMENT attributes EMPTY>
 <!ATTLIST attributes
-	root (1|0) "0"
 	maxinstances CDATA "0">
 
 <!ELEMENT child EMPTY>
--- cluster/rgmanager/src/resources/service.sh	2007/07/23 20:49:13	1.10
+++ cluster/rgmanager/src/resources/service.sh	2007/07/31 18:00:25	1.11
@@ -56,7 +56,7 @@
             <content type="string"/>
         </parameter>
     
-        <parameter name="domain">
+        <parameter name="domain" reconfig="1">
             <longdesc lang="en">
                 Fail over domains define lists of cluster members
                 to try in the event that a resource group fails.
@@ -164,6 +164,7 @@
         <action name="status" timeout="5" interval="1h"/>
         <action name="monitor" timeout="5" interval="1h"/>
 
+        <action name="reconfig" timeout="5"/>
         <action name="recover" timeout="5"/>
         <action name="reload" timeout="5"/>
         <action name="meta-data" timeout="5"/>
@@ -227,6 +228,9 @@
 	validate-all)
 		exit 0
 		;;
+	reconfig)
+  		exit 0
+  		;;
 	*)
 		exit 0
 		;;
--- cluster/rgmanager/src/resources/vm.sh	2007/06/27 14:03:51	1.5
+++ cluster/rgmanager/src/resources/vm.sh	2007/07/31 18:00:25	1.6
@@ -53,7 +53,7 @@
             <content type="string"/>
         </parameter>
     
-        <parameter name="domain">
+        <parameter name="domain" reconfig="1">
             <longdesc lang="en">
                 Fail over domains define lists of cluster members
                 to try in the event that the host of the virtual machine
@@ -65,7 +65,7 @@
             <content type="string"/>
         </parameter>
 
-        <parameter name="autostart">
+        <parameter name="autostart" reconfig="1">
             <longdesc lang="en">
 	    	If set to yes, this resource group will automatically be started
 		after the cluster forms a quorum.  If set to no, this virtual
@@ -200,7 +200,11 @@
     </actions>
     
     <special tag="rgmanager">
-        <attributes maxinstances="1"/>
+     	<!-- Destroy_on_delete / init_on_add are currently only
+ 	     supported for migratory resources (no children
+ 	     and the 'migrate' action; see above.  Do not try this
+ 	     with normal services -->
+	<attributes maxinstances="1" destroy_on_delete="0" init_on_add="0"/>
     </special>
 </resource-agent>
 EOT



^ permalink raw reply	[flat|nested] 5+ messages in thread
* [Cluster-devel] cluster/rgmanager ChangeLog include/res-ocf.h  ...
@ 2007-12-19 21:07 lhh
  0 siblings, 0 replies; 5+ messages in thread
From: lhh @ 2007-12-19 21:07 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	lhh at sourceware.org	2007-12-19 21:07:14

Modified files:
	rgmanager      : ChangeLog 
	rgmanager/include: res-ocf.h 
	rgmanager/src/daemons: restree.c 
	rgmanager/src/resources: clusterfs.sh 

Log message:
	Fix #254111 - when stopping a service using a shared GFS resource, it umounts it even if other services are using it.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/ChangeLog.diff?cvsroot=cluster&r1=1.66&r2=1.67
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/res-ocf.h.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/restree.c.diff?cvsroot=cluster&r1=1.40&r2=1.41
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/clusterfs.sh.diff?cvsroot=cluster&r1=1.22&r2=1.23

--- cluster/rgmanager/ChangeLog	2007/12/14 22:10:52	1.66
+++ cluster/rgmanager/ChangeLog	2007/12/19 21:07:13	1.67
@@ -1,3 +1,10 @@
+2007-12-19 Lon Hohberger <lhh@redhat.com>
+	* include/res-ocf.h: Fix typo
+	* src/daemons/restree.c: Export reference counts to resource agents.
+	* src/resources/clusterfs.sh: Use reference counts to ensure we
+	don't unmount a GFS file system if it's in use by multiple services
+	on the same node.  #254111
+
 2007-12-14 Lon Hohberger <lhh@redhat.com>
 	(Misc central_events fixes)
 	* Add return code for inability to run because of exclusive 
--- cluster/rgmanager/include/res-ocf.h	2007/07/31 18:00:25	1.3
+++ cluster/rgmanager/include/res-ocf.h	2007/12/19 21:07:13	1.4
@@ -31,6 +31,7 @@
 #define OCF_RESOURCE_INSTANCE_STR "OCF_RESOURCE_INSTANCE"
 #define OCF_CHECK_LEVEL_STR "OCF_CHECK_LEVEL"
 #define OCF_RESOURCE_TYPE_STR "OCF_RESOURCE_TYPE"
+#define OCF_REFCNT_STR "OCF_RESKEY_RGMANAGER_meta_refcnt"
 
 /*
    LSB return codes 
--- cluster/rgmanager/src/daemons/restree.c	2007/11/30 21:36:28	1.40
+++ cluster/rgmanager/src/daemons/restree.c	2007/12/19 21:07:14	1.41
@@ -130,7 +130,7 @@
    @see			build_env
  */
 static void
-add_ocf_stuff(resource_t *res, char **env, int depth)
+add_ocf_stuff(resource_t *res, char **env, int depth, int refcnt)
 {
 	char ver[10];
 	char *minor, *val;
@@ -214,6 +214,17 @@
 		return;
 	snprintf(val, n, "%s=%s", OCF_CHECK_LEVEL_STR, ver);
 	*env = val; env++;
+
+	/*
+	   Store the resource local refcnt (0 for now)
+	 */
+	snprintf(ver, sizeof(ver), "%d", refcnt);
+	n = strlen(OCF_REFCNT_STR) + strlen(ver) + 2;
+	val = malloc(n);
+	if (!val)
+		return;
+	snprintf(val, n, "%s=%s", OCF_REFCNT_STR, ver);
+	*env = val; env++;
 }
 
 
@@ -227,7 +238,7 @@
    @see			kill_env res_exec add_ocf_stuff
  */
 static char **
-build_env(resource_node_t *node, int depth)
+build_env(resource_node_t *node, int depth, int refcnt)
 {
 	resource_t *res = node->rn_resource;
 	char **env;
@@ -235,7 +246,7 @@
 	int x, attrs, n;
 
 	for (attrs = 0; res->r_attrs && res->r_attrs[attrs].ra_name; attrs++);
-	attrs += 7; /*
+	attrs += 8; /*
 		   Leave space for:
 		   OCF_RA_VERSION_MAJOR
 		   OCF_RA_VERSION_MINOR
@@ -243,6 +254,7 @@
 		   OCF_RESOURCE_INSTANCE
 		   OCF_RESOURCE_TYPE
 		   OCF_CHECK_LEVEL
+		   OCF_RESKEY_RGMANAGER_meta_refcnt
 		   (null terminator)
 		 */
 
@@ -282,7 +294,7 @@
 		++attrs;
 	}
 
-	add_ocf_stuff(res, &env[attrs], depth);
+	add_ocf_stuff(res, &env[attrs], depth, refcnt);
 
 	return env;
 }
@@ -345,7 +357,7 @@
 		return 0;
 
 #ifdef DEBUG
-	env = build_env(node, depth);
+	env = build_env(node, depth, node->rn_resource->r_incarnations);
 	if (!env)
 		return -errno;
 #endif
@@ -374,7 +386,7 @@
 #endif
 
 #ifndef DEBUG
-		env = build_env(node, depth);
+		env = build_env(node, depth, node->rn_resource->r_incarnations);
 #endif
 
 		if (!env)
--- cluster/rgmanager/src/resources/clusterfs.sh	2007/12/19 20:54:07	1.22
+++ cluster/rgmanager/src/resources/clusterfs.sh	2007/12/19 21:07:14	1.23
@@ -766,6 +766,7 @@
 	typeset -i try=1
 	typeset -i max_tries=3		# how many times to try umount
 	typeset -i sleep_time=2		# time between each umount failure
+	typeset -i refs=0
 	typeset done=""
 	typeset umount_failed=""
 	typeset force_umount=""
@@ -820,6 +821,18 @@
 		esac
 	fi
 
+	#
+	# Check the rgmanager-supplied reference count if one exists.
+	# If the reference count is <= 1, we can safely proceed
+	#
+	if [ -n "$OCF_RESKEY_RGMANAGER_meta_refcnt" ]; then
+		refs=$OCF_RESKEY_RGMANAGER_meta_refcnt
+		if [ $refs -gt 1 ]; then
+			((refs--))
+			ocf_log debug "Not unmounting $OCF_RESOURCE_INSTANCE - still in use by $refs other service(s)"
+			return $OCF_SUCCESS
+		fi
+	fi
 
 	#
 	# Always do this hackery on clustered file systems.



^ permalink raw reply	[flat|nested] 5+ messages in thread
* [Cluster-devel] cluster/rgmanager ChangeLog include/res-ocf.h  ...
@ 2007-12-19 21:04 lhh
  0 siblings, 0 replies; 5+ messages in thread
From: lhh @ 2007-12-19 21:04 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL5
Changes by:	lhh at sourceware.org	2007-12-19 21:04:41

Modified files:
	rgmanager      : ChangeLog 
	rgmanager/include: res-ocf.h 
	rgmanager/src/daemons: restree.c 
	rgmanager/src/resources: clusterfs.sh 

Log message:
	Fix #254111 - when stopping a service using a shared GFS resource, it umounts it even if other services are using it.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/ChangeLog.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.31.2.32&r2=1.31.2.33
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/res-ocf.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1.16.3&r2=1.1.16.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/restree.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.23.2.13&r2=1.23.2.14
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/clusterfs.sh.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.15.2.6&r2=1.15.2.7

--- cluster/rgmanager/ChangeLog	2007/12/18 17:52:55	1.31.2.32
+++ cluster/rgmanager/ChangeLog	2007/12/19 21:04:40	1.31.2.33
@@ -1,3 +1,10 @@
+2007-12-19 Lon Hohberger <lhh@redhat.com>
+	* include/res-ocf.h: Fix typo
+	* src/daemons/restree.c: Export reference counts to resource agents
+	* src/resources/clusterfs.sh: Use reference counts to ensure we
+	don't unmount a GFS file system if it's in use by multiple services
+	on the same node.  #254111
+
 2007-12-18 Lon Hohberger <lhh@redhat.com>
 	* Merge RIND 0.8.1 + bugfixes from head branch to RHEL5
 	branch.  Must be explicitly enabled by administrators in
--- cluster/rgmanager/include/res-ocf.h	2007/12/18 17:52:56	1.1.16.3
+++ cluster/rgmanager/include/res-ocf.h	2007/12/19 21:04:40	1.1.16.4
@@ -31,7 +31,7 @@
 #define OCF_RESOURCE_INSTANCE_STR "OCF_RESOURCE_INSTANCE"
 #define OCF_CHECK_LEVEL_STR "OCF_CHECK_LEVEL"
 #define OCF_RESOURCE_TYPE_STR "OCF_RESOURCE_TYPE"
-#define OCF_RECFNT_STR "OCF_RESKEY_RGMANAGER_meta_refcnt"
+#define OCF_REFCNT_STR "OCF_RESKEY_RGMANAGER_meta_refcnt"
 
 /*
    LSB return codes 
--- cluster/rgmanager/src/daemons/restree.c	2007/11/26 21:46:27	1.23.2.13
+++ cluster/rgmanager/src/daemons/restree.c	2007/12/19 21:04:41	1.23.2.14
@@ -130,7 +130,7 @@
    @see			build_env
  */
 static void
-add_ocf_stuff(resource_t *res, char **env, int depth)
+add_ocf_stuff(resource_t *res, char **env, int depth, int refcnt)
 {
 	char ver[10];
 	char *minor, *val;
@@ -214,6 +214,17 @@
 		return;
 	snprintf(val, n, "%s=%s", OCF_CHECK_LEVEL_STR, ver);
 	*env = val; env++;
+
+	/*
+	   Store the resource local refcnt (0 for now)
+	 */
+	snprintf(ver, sizeof(ver), "%d", refcnt);
+	n = strlen(OCF_REFCNT_STR) + strlen(ver) + 2;
+	val = malloc(n);
+	if (!val)
+		return;
+	snprintf(val, n, "%s=%s", OCF_REFCNT_STR, ver);
+	*env = val; env++;
 }
 
 
@@ -227,7 +238,7 @@
    @see			kill_env res_exec add_ocf_stuff
  */
 static char **
-build_env(resource_node_t *node, int depth)
+build_env(resource_node_t *node, int depth, int refcnt)
 {
 	resource_t *res = node->rn_resource;
 	char **env;
@@ -235,7 +246,7 @@
 	int x, attrs, n;
 
 	for (attrs = 0; res->r_attrs && res->r_attrs[attrs].ra_name; attrs++);
-	attrs += 7; /*
+	attrs += 8; /*
 		   Leave space for:
 		   OCF_RA_VERSION_MAJOR
 		   OCF_RA_VERSION_MINOR
@@ -243,6 +254,7 @@
 		   OCF_RESOURCE_INSTANCE
 		   OCF_RESOURCE_TYPE
 		   OCF_CHECK_LEVEL
+		   OCF_RESKEY_RGMANAGER_meta_refcnt
 		   (null terminator)
 		 */
 
@@ -282,7 +294,7 @@
 		++attrs;
 	}
 
-	add_ocf_stuff(res, &env[attrs], depth);
+	add_ocf_stuff(res, &env[attrs], depth, refcnt);
 
 	return env;
 }
@@ -345,7 +357,7 @@
 		return 0;
 
 #ifdef DEBUG
-	env = build_env(node, depth);
+	env = build_env(node, depth, node->rn_resource->r_incarnations);
 	if (!env)
 		return -errno;
 #endif
@@ -374,7 +386,7 @@
 #endif
 
 #ifndef DEBUG
-		env = build_env(node, depth);
+		env = build_env(node, depth, node->rn_resource->r_incarnations);
 #endif
 
 		if (!env)
@@ -1063,7 +1075,8 @@
 
 		/* Ok, it's a 'status' action. See if enough time has
 		   elapsed for a given type of status action */
-		if (delta < node->rn_actions[x].ra_interval)
+		if (delta < node->rn_actions[x].ra_interval ||
+		    !node->rn_actions[x].ra_interval)
 			continue;
 
 		if (idx == -1 ||
--- cluster/rgmanager/src/resources/clusterfs.sh	2007/12/19 20:53:35	1.15.2.6
+++ cluster/rgmanager/src/resources/clusterfs.sh	2007/12/19 21:04:41	1.15.2.7
@@ -766,6 +766,7 @@
 	typeset -i try=1
 	typeset -i max_tries=3		# how many times to try umount
 	typeset -i sleep_time=2		# time between each umount failure
+	typeset -i refs=0
 	typeset done=""
 	typeset umount_failed=""
 	typeset force_umount=""
@@ -820,6 +821,18 @@
 		esac
 	fi
 
+	#
+	# Check the rgmanager-supplied reference count if one exists.
+	# If the reference count is <= 1, we can safely proceed
+	#
+	if [ -n "$OCF_RESKEY_RGMANAGER_meta_refcnt" ]; then
+		refs=$OCF_RESKEY_RGMANAGER_meta_refcnt
+		if [ $refs -gt 1 ]; then
+			((refs--))
+			ocf_log debug "Not unmounting $OCF_RESOURCE_INSTANCE - still in use by $refs other service(s)"
+			return $OCF_SUCCESS
+		fi
+	fi
 
 	#
 	# Always do this hackery on clustered file systems.



^ permalink raw reply	[flat|nested] 5+ messages in thread
* [Cluster-devel] cluster/rgmanager ChangeLog include/res-ocf.h  ...
@ 2007-07-31 17:56 lhh
  0 siblings, 0 replies; 5+ messages in thread
From: lhh @ 2007-07-31 17:56 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL51
Changes by:	lhh at sourceware.org	2007-07-31 17:56:10

Modified files:
	rgmanager      : ChangeLog 
	rgmanager/include: res-ocf.h reslist.h 
	rgmanager/src/clulib: rg_strings.c 
	rgmanager/src/daemons: groups.c reslist.c resrules.c restree.c 
	                       test.c 
	rgmanager/src/resources: ra-api-1-modified.dtd service.sh vm.sh 

Log message:
	Fix bug #248727

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/ChangeLog.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.31.2.19.2.1&r2=1.31.2.19.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/res-ocf.h.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.1.16.1&r2=1.1.16.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/reslist.h.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.15.2.4&r2=1.15.2.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/clulib/rg_strings.c.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.5.2.4&r2=1.5.2.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/groups.c.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.25.2.9.2.1&r2=1.25.2.9.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/reslist.c.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.14.2.3&r2=1.14.2.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/resrules.c.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.16.2.6&r2=1.16.2.6.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/restree.c.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.23.2.8&r2=1.23.2.8.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/test.c.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.6.2.4&r2=1.6.2.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/ra-api-1-modified.dtd.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.4&r2=1.4.6.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/service.sh.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.7.2.4&r2=1.7.2.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/vm.sh.diff?cvsroot=cluster&only_with_tag=RHEL51&r1=1.1.2.4.2.1&r2=1.1.2.4.2.2

--- cluster/rgmanager/ChangeLog	2007/07/24 18:49:17	1.31.2.19.2.1
+++ cluster/rgmanager/ChangeLog	2007/07/31 17:56:10	1.31.2.19.2.2
@@ -1,3 +1,23 @@
+2007-07-31 Lon Hohberger <lhh@redhat.com>
+	* general: Make VMs not change state when added/removed from the
+	cluster config or bounce services/VMs when minor config changes
+	are made. (#248727)
+	* include/res-ocf.h: Add reconfigure operation
+	* include/reslist.h: Add flags allowing reconfigurable options in
+	resource agent metadata, and per-agent flags which allow resources
+	to be added w/o initialization / removed w/o kill.
+	* src/clulib/rg_strings.c: Add string definition for reconfigure op
+	* src/daemons/groups.c: Allow no-init-on-add and no-kill-on-delete
+	flags to work
+	* src/daemons/reslist.c: Allow resource comparison to take into 
+	account reconfig flags and return a new value if the resource is
+	reconfigurable
+	* src/daemons/resrules.c: Code to support new flags
+	* src/daemons/restree.c: Code to support reconfiguration operation
+	* src/daemons/test.c: Code to support testing new reconfig ops and
+	behaviors
+	* src/resources/*: Add new flags to service and VM resource agents.
+
 2007-07-24 Lon Hohberger <lhh@redhat.com>
 	* general: make threads exit with pthread_exit() so we can wrap/track them.
 	Add internal statedump (SIGUSR1) support.
--- cluster/rgmanager/include/res-ocf.h	2007/03/20 17:09:11	1.1.16.1
+++ cluster/rgmanager/include/res-ocf.h	2007/07/31 17:56:10	1.1.16.1.2.1
@@ -62,5 +62,6 @@
 #define RS_META_DATA	(11)
 #define RS_VALIDATE	(12)
 #define RS_MIGRATE	(13)
+#define RS_RECONFIG	(14)
 
 #endif
--- cluster/rgmanager/include/reslist.h	2007/06/26 21:55:45	1.15.2.4
+++ cluster/rgmanager/include/reslist.h	2007/07/31 17:56:10	1.15.2.4.2.1
@@ -25,10 +25,11 @@
 #include <libxml/xpath.h>
 
 
-#define RA_PRIMARY	(1<<0)
-#define RA_UNIQUE	(1<<1)
-#define RA_REQUIRED	(1<<2)
-#define RA_INHERIT	(1<<3)
+#define RA_PRIMARY	(1<<0)	/** Primary key */
+#define RA_UNIQUE	(1<<1)	/** Unique for given type */
+#define RA_REQUIRED	(1<<2)	/** Required (or an error if not present */
+#define RA_INHERIT	(1<<3)	/** Inherit a parent resource's attr */
+#define RA_RECONFIG	(1<<4)	/** Allow inline reconfiguration */
 
 #define RF_INLINE	(1<<0)
 #define RF_DEFINED	(1<<1)
@@ -37,6 +38,15 @@
 #define RF_COMMON	(1<<4)	/** " */
 #define RF_INDEPENDENT	(1<<5)  /** Define this for a resource if it is
 				  otherwise an independent subtree */
+#define RF_RECONFIG	(1<<6)
+
+#define RF_INIT		(1<<7)	/** Resource rule: Initialize this resource
+				  class on startup */
+#define RF_DESTROY	(1<<8)	/** Resource rule flag: Destroy this
+				  resource class if you delete it from
+				  the configuration */
+
+
 
 #define RES_STOPPED	(0)
 #define RES_STARTED	(1)
--- cluster/rgmanager/src/clulib/rg_strings.c	2007/07/06 18:50:22	1.5.2.4
+++ cluster/rgmanager/src/clulib/rg_strings.c	2007/07/31 17:56:10	1.5.2.4.2.1
@@ -106,6 +106,7 @@
 	{RS_META_DATA, "meta-data"},		/* printenv */
 	{RS_VALIDATE, "validate-all"},
 	{RS_MIGRATE, "migrate"},
+	{RS_RECONFIG, "reconfig"},
 	{0 , NULL}
 };
 
--- cluster/rgmanager/src/daemons/groups.c	2007/07/24 18:49:18	1.25.2.9.2.1
+++ cluster/rgmanager/src/daemons/groups.c	2007/07/31 17:56:10	1.25.2.9.2.2
@@ -1222,6 +1222,7 @@
 do_condstops(void)
 {
 	resource_node_t *curr;
+	struct dlm_lksb lockp;
 	rg_state_t svcblk;
 	int need_kill;
 	char rg[64];
@@ -1249,6 +1250,24 @@
 			clulog(LOG_DEBUG, "Removing %s\n", rg);
 		}
 
+		if (!curr->rn_child && ((curr->rn_resource->r_rule->rr_flags &
+		    RF_DESTROY) == 0) && group_migratory(rg, 0) &&
+		    need_kill == 1) {
+			/* Do something smart here: flip state? */
+			clulog(LOG_NOTICE,
+			       "%s removed from the config, but I am not stopping it.\n",
+			       rg);
+			if (rg_lock(rg, &lockp) != 0)
+				continue;
+			if (get_rg_state(rg, &svcblk) < 0)
+		       		goto cont;
+			svcblk.rs_state = RG_STATE_DISABLED;
+			set_rg_state(rg, &svcblk);
+cont:
+			rg_unlock(&lockp);
+			continue;
+		}
+
 		rt_enqueue_request(rg, need_kill ? RG_DISABLE : RG_CONDSTOP,
 				   NULL, 0, 0, 0, 0);
 
@@ -1282,7 +1301,8 @@
 
 		/* New RG.  We'll need to initialize it. */
 		need_init = 0;
-		if (curr->rn_resource->r_flags & RF_NEEDSTART)
+		if (!(curr->rn_resource->r_flags & RF_RECONFIG) &&
+		    (curr->rn_resource->r_flags & RF_NEEDSTART))
 			need_init = 1;
 
 		if (!need_init) {
@@ -1305,7 +1325,17 @@
 
 		if (need_init) {
 			++new_groups;
-			clulog(LOG_DEBUG, "Initializing %s\n", rg);
+			clulog(LOG_NOTICE, "Initializing %s\n", rg);
+		}
+
+		if (!curr->rn_child && ((curr->rn_resource->r_rule->rr_flags &
+		    RF_INIT) == 0) && group_migratory(rg, 0) &&
+		    need_init == 1) {
+			/* Do something smart here? */
+			clulog(LOG_NOTICE,
+			       "%s was added to the config, but I am not initializing it.\n",
+			       rg);
+			continue;
 		}
 
 		rt_enqueue_request(rg, need_init ? RG_INIT : RG_CONDSTART,
--- cluster/rgmanager/src/daemons/reslist.c	2007/04/26 20:40:28	1.14.2.3
+++ cluster/rgmanager/src/daemons/reslist.c	2007/07/31 17:56:10	1.14.2.3.2.1
@@ -176,18 +176,29 @@
 /**
    Compare two resources.
 
+  @param left	Left resource
+  @param right	Right resource	
+  @return	-1 on different resource, 0 if the same, 1 if different,
+		2 if different, but only safe resources are different
+
  */
 int
 rescmp(resource_t *left, resource_t *right)
 {
-	int x, y = 0, found;
+	int x, y = 0, found = 0, ret = 0;
+
 
 	/* Completely different resource class... */
 	if (strcmp(left->r_rule->rr_type, right->r_rule->rr_type)) {
-		//printf("Er, wildly different resource type! ");
 		return -1;
 	}
 
+	/*
+	printf("Comparing %s:%s to %s:%s\n",
+	       left->r_rule->rr_type, left->r_attrs[0].ra_value,
+	       right->r_rule->rr_type, right->r_attrs[0].ra_value)
+	 */
+
 	for (x = 0; left->r_attrs && left->r_attrs[x].ra_name; x++) {
 
 		found = 0;
@@ -203,35 +214,52 @@
 			    left->r_attrs[x].ra_flags) {
 				/* Flags are different.  Change in
 				   resource agents? */
-				//printf("flags differ ");
+				/*
+				printf("* flags differ %08x vs %08x\n",
+				       left->r_attrs[x].ra_flags,
+				       right->r_attrs[y].ra_flags);
+				 */
 				return 1;
 			}
 
 			if (strcmp(right->r_attrs[y].ra_value,
 				   left->r_attrs[x].ra_value)) {
 				/* Different attribute value. */
-				//printf("different value for attr '%s'  ",
-				       //right->r_attrs[y].ra_name);
-				return 1;
+				/*
+				printf("* different value for attr '%s':"
+				       " '%s' vs '%s'",
+				       right->r_attrs[y].ra_name,
+				       left->r_attrs[x].ra_value,
+				       right->r_attrs[y].ra_value);
+				 */
+				if (left->r_attrs[x].ra_flags & RA_RECONFIG) {
+					/* printf(" [SAFE]\n"); */
+					ret = 2;
+			 	} else {
+					/* printf("\n"); */
+					return 1;
+				}
 			}
 		}
 
 		/* Attribute missing -> different attribute value. */
 		if (!found) {
-			//printf("Attribute %s deleted  ",
-			       //left->r_attrs[x].ra_name);
+			/*
+			printf("* Attribute '%s' deleted\n",
+			       left->r_attrs[x].ra_name);
+			 */
 			return 1;
 		}
 	}
 
 	/* Different attribute count */
 	if (x != y) {
-		//printf("Attribute count differ (attributes added!) ");
+		/* printf("* Attribute count differ (attributes added!) "); */
 		return 1;
 	}
 
 	/* All the same */
-	return 0;
+	return ret;
 }
 
 
@@ -288,7 +316,7 @@
 	resource_t *curr;
 	char ref_buf[128];
 	char *type;
-	char *name;
+	char *name = ref;
 	int x;
 
 	snprintf(ref_buf, sizeof(ref_buf), "%s", ref);
@@ -300,6 +328,7 @@
 	} else {
 		/* Default type */
 		type = "service";
+		name = ref;
 	}
 
 	list_do(reslist, curr) {
@@ -543,6 +572,8 @@
 		printf(" [NEEDSTOP]");
 	if (res->r_flags & RF_COMMON)
 		printf(" [COMMON]");
+	if (res->r_flags & RF_RECONFIG)
+		printf(" [RECONFIG]");
 	printf("\n");
 
 	if (res->r_rule->rr_maxrefs)
@@ -578,6 +609,8 @@
 			printf(" unique");
 		if (res->r_attrs[x].ra_flags & RA_REQUIRED)
 			printf(" required");
+		if (res->r_attrs[x].ra_flags & RA_RECONFIG)
+			printf(" reconfig");
 		if (res->r_attrs[x].ra_flags & RA_INHERIT)
 			printf(" inherit(\"%s\")", res->r_attrs[x].ra_value);
 		printf(" ]\n");
--- cluster/rgmanager/src/daemons/resrules.c	2007/06/26 21:55:46	1.16.2.6
+++ cluster/rgmanager/src/daemons/resrules.c	2007/07/31 17:56:10	1.16.2.6.2.1
@@ -163,6 +163,36 @@
 
 
 /**
+   Get and store a bit field.
+
+   @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_rule_flag(xmlDocPtr doc, xmlXPathContextPtr ctx, char *base,
+	       resource_rule_t *rr, char *flag, int bit)
+{
+	char xpath[256];
+	char *ret = NULL;
+
+	snprintf(xpath, sizeof(xpath),
+		 "%s/attributes/@%s",
+		 base, flag);
+	ret = xpath_get_one(doc, ctx, xpath);
+	if (ret) {
+		if (atoi(ret)) {
+			rr->rr_flags |= bit;
+		} else {
+			rr->rr_flags &= ~bit;
+		}
+		free(ret);
+	}
+}
+
+
+/**
    Get and store the version
 
    @param doc		Pre-parsed XML document pointer.
@@ -516,6 +546,17 @@
 		printf("Max instances: %d\n", rr->rr_maxrefs);
 	if (rr->rr_agent)
 		printf("Agent: %s\n", basename(rr->rr_agent));
+
+	printf("Flags: ");
+	if (rr->rr_flags) {
+		if (rr->rr_flags & RF_INIT)
+			printf("init_on_add ");
+		if (rr->rr_flags & RF_DESTROY)
+			printf("destroy_on_delete ");
+	} else {
+		printf("(none)");
+	}
+	printf("\n");
 	
 	printf("Attributes:\n");
 	if (!rr->rr_attrs) {
@@ -531,18 +572,25 @@
 			continue;
 		}
 
-		printf(" [");
-		if (rr->rr_attrs[x].ra_flags & RA_PRIMARY)
-			printf(" primary");
-		if (rr->rr_attrs[x].ra_flags & RA_UNIQUE)
-			printf(" unique");
-		if (rr->rr_attrs[x].ra_flags & RA_REQUIRED)
-			printf(" required");
-		if (rr->rr_attrs[x].ra_flags & RA_INHERIT)
-			printf(" inherit");
-		else if (rr->rr_attrs[x].ra_value)
-			printf(" default=\"%s\"", rr->rr_attrs[x].ra_value);
-		printf(" ]\n");
+		if (rr->rr_attrs[x].ra_flags) {
+			printf(" [");
+			if (rr->rr_attrs[x].ra_flags & RA_PRIMARY)
+				printf(" primary");
+			if (rr->rr_attrs[x].ra_flags & RA_UNIQUE)
+				printf(" unique");
+			if (rr->rr_attrs[x].ra_flags & RA_REQUIRED)
+				printf(" required");
+			if (rr->rr_attrs[x].ra_flags & RA_INHERIT)
+				printf(" inherit");
+			if (rr->rr_attrs[x].ra_flags & RA_RECONFIG)
+				printf(" reconfig");
+			printf(" ]");
+		}
+
+		if (rr->rr_attrs[x].ra_value)
+			printf(" default=\"%s\"\n", rr->rr_attrs[x].ra_value);
+		else
+			printf("\n");
 	}
 
 actions:
@@ -678,6 +726,18 @@
 		}
 
 		/*
+		   See if this can be reconfigured on the fly without a 
+		   stop/start
+		 */
+		snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@reconfig",
+			 base, x);
+		if ((ret = xpath_get_one(doc,ctx,xpath))) {
+			if ((atoi(ret) != 0) || (ret[0] == 'y'))
+				flags |= RA_RECONFIG;
+			free(ret);
+		}
+
+		/*
 		   See if this is supposed to be inherited
 		 */
 		snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@inherit",
@@ -942,6 +1002,7 @@
 			break;
 		memset(rr,0,sizeof(*rr));
 
+		rr->rr_flags = RF_INIT | RF_DESTROY;
 		rr->rr_type = type;
 		snprintf(base, sizeof(base), "/resource-agent[%d]", ruleid);
 
@@ -954,6 +1015,8 @@
 			 "/resource-agent[%d]/special[@tag=\"rgmanager\"]",
 			 ruleid);
 		_get_maxparents(doc, ctx, base, rr);
+		_get_rule_flag(doc, ctx, base, rr, "init_on_add", RF_INIT);
+		_get_rule_flag(doc, ctx, base, rr, "destroy_on_delete", RF_DESTROY);
 		rr->rr_agent = strdup(filename);
 
 		/*
--- cluster/rgmanager/src/daemons/restree.c	2007/06/26 21:55:46	1.23.2.8
+++ cluster/rgmanager/src/daemons/restree.c	2007/07/31 17:56:10	1.23.2.8.2.1
@@ -1186,9 +1186,15 @@
 
 	/* Start starts before children */
 	if (me && (op == RS_START)) {
-		node->rn_flags &= ~RF_NEEDSTART;
 
-		rv = res_exec(node, op, NULL, 0);
+		if (node->rn_flags & RF_RECONFIG &&
+		    realop == RS_CONDSTART) {
+			rv = res_exec(node, RS_RECONFIG, NULL, 0);
+			op = realop; /* reset to CONDSTART */
+		} else {
+			rv = res_exec(node, op, NULL, 0);
+		}
+		node->rn_flags &= ~(RF_NEEDSTART | RF_RECONFIG);
 		if (rv != 0) {
 			node->rn_state = RES_FAILED;
 			return SFL_FAILURE;
@@ -1408,6 +1414,7 @@
 resource_delta(resource_t **leftres, resource_t **rightres)
 {
 	resource_t *lc, *rc;
+	int ret;
 
 	list_do(leftres, lc) {
 		rc = find_resource_by_ref(rightres, lc->r_rule->rr_type,
@@ -1420,10 +1427,25 @@
 		}
 
 		/* Ok, see if the resource is the same */
-		if (rescmp(lc, rc) == 0) {
+		ret = rescmp(lc, rc);
+		if (ret	== 0) {
 			rc->r_flags |= RF_COMMON;
 			continue;
 		}
+
+		if (ret == 2) {
+			/* return of 2 from rescmp means
+			   the two resources differ only 
+			   by reconfigurable bits */
+			/* Do nothing on condstop phase;
+			   do a "reconfig" instead of 
+			   "start" on conststart phase */
+			rc->r_flags |= RF_COMMON;
+			rc->r_flags |= RF_NEEDSTART;
+			rc->r_flags |= RF_RECONFIG;
+			continue;
+		}
+
 		rc->r_flags |= RF_COMMON;
 
 		/* Resource has changed.  Flag it. */
@@ -1485,12 +1507,17 @@
 			   or is new), then we don't really care about its
 			   children.
 			 */
+
 			if (rn->rn_resource->r_flags & RF_NEEDSTART) {
 				rn->rn_flags |= RF_NEEDSTART;
-				continue;
+				if ((rn->rn_resource->r_flags & RF_RECONFIG) == 0)
+					continue;
 			}
 
-			if (rc == 0) {
+			if (rc == 0 || rc == 2) {
+				if (rc == 2)
+					rn->rn_flags |= RF_NEEDSTART | RF_RECONFIG;
+
 				/* Ok, same resource.  Recurse. */
 				ln->rn_flags |= RF_COMMON;
 				rn->rn_flags |= RF_COMMON;
--- cluster/rgmanager/src/daemons/test.c	2007/06/27 14:03:20	1.6.2.4
+++ cluster/rgmanager/src/daemons/test.c	2007/07/31 17:56:10	1.6.2.4.2.1
@@ -32,6 +32,50 @@
 #error "Can not be built with CCS support."
 #endif
 
+/**
+  Tells us if a resource group can be migrated.
+ */
+int
+group_migratory(resource_t **resources, resource_node_t **tree, char *groupname)
+{
+	resource_node_t *rn;
+	resource_t *res;
+	int migrate = 0, x, ret = 0;
+
+	res = find_root_by_ref(resources, groupname);
+	if (!res) {
+		/* 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)
+		goto out_unlock;
+
+	list_do(tree, rn) {
+		if (rn->rn_resource == res && rn->rn_child) {
+			/* TL service w/ children cannot be migrated */
+			goto out_unlock;
+		}
+	} while (!list_done(tree, rn));
+
+
+	/* 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 */
+	ret = 1;
+
+out_unlock:
+	return ret;
+}
+
 #define shift() {++argv; --argc;}
 
 #define USAGE_TEST \
@@ -217,7 +261,9 @@
 	resource_rule_t *rulelist = NULL, *currule, *rulelist2 = NULL;
 	resource_t *reslist = NULL, *curres, *reslist2 = NULL;
 	resource_node_t *tree = NULL, *tree2 = NULL;
-	int ccsfd, ret = 0;
+	resource_node_t *tn;
+	int ccsfd, ret = 0, need_init, need_kill;
+	char rg[64];
 
 	if (argc < 2) {
 		printf("Operation requires two arguments\n");
@@ -276,6 +322,57 @@
 	print_resource_tree(&tree);
 	printf("=== New Resource Tree ===\n");
 	print_resource_tree(&tree2);
+	printf("=== Operations (down-phase) ===\n");
+	list_do(&tree, tn) {
+		res_build_name(rg, sizeof(rg), tn->rn_resource);
+		/* Set state to uninitialized if we're killing a RG */
+		need_init = 0;
+
+		/* Set state to uninitialized if we're killing a RG */
+		need_kill = 0;
+		if (tn->rn_resource->r_flags & RF_NEEDSTOP) {
+			need_kill = 1;
+			printf("[kill] ");
+		}
+
+		if (!tn->rn_child && ((tn->rn_resource->r_rule->rr_flags &
+		    RF_DESTROY) == 0) && group_migratory(&reslist, &tree, rg) &&
+		    need_kill == 1) {
+			/* Do something smart here: flip state? */
+			printf("[no-op] %s was removed from the config, but I am not stopping it.\n",
+			       rg);
+			continue;
+		}
+
+		res_condstop(&tn, tn->rn_resource, NULL);
+	} while (!list_done(&tree, tn));
+	printf("=== Operations (up-phase) ===\n");
+	list_do(&tree2, tn) {
+		res_build_name(rg, sizeof(rg), tn->rn_resource);
+		/* New RG.  We'll need to initialize it. */
+		need_init = 0;
+		if (!(tn->rn_resource->r_flags & RF_RECONFIG) &&
+		    (tn->rn_resource->r_flags & RF_NEEDSTART))
+			need_init = 1;
+
+		if (need_init) {
+			printf("[init] ");
+		}
+
+		if (!tn->rn_child && ((tn->rn_resource->r_rule->rr_flags &
+		    RF_INIT) == 0) && group_migratory(&reslist2, &tree2, rg) &&
+		    need_init == 1) {
+			/* Do something smart here? */
+			printf("[noop] %s was added, but I am not initializing it\n", rg);
+			continue;
+		}
+
+		if (need_init) {
+			res_stop(&tn, tn->rn_resource, NULL);
+		} else {
+			res_condstart(&tn, tn->rn_resource, NULL);
+		}
+	} while (!list_done(&tree2, tn));
 
 out:
 	destroy_resource_tree(&tree2);
@@ -331,6 +428,7 @@
 			goto out;
 		} else if (!strcmp(argv[1], "delta")) {
 			shift();
+			_no_op_mode(1);
 			ret = tree_delta_test(argc, argv);
 			goto out;
 		} else {
--- cluster/rgmanager/src/resources/ra-api-1-modified.dtd	2006/08/18 15:26:22	1.4
+++ cluster/rgmanager/src/resources/ra-api-1-modified.dtd	2007/07/31 17:56:10	1.4.6.1
@@ -24,6 +24,7 @@
 	name	CDATA	#REQUIRED
 	primary (1|0)   "0"
 	required (1|0)	"0"
+	reconfig (1|0)	"0"
 	inherit CDATA	""
 	unique	(1|0)	"0"
 	reconfig (1|0)  "0">
@@ -43,7 +44,7 @@
 
 <!ELEMENT action EMPTY>
 <!ATTLIST action
-	name	(start|stop|recover|status|reconfig|monitor|reload|meta-data|verify-all|migrate)	#REQUIRED
+	name	(start|stop|recover|status|reconfig|monitor|reload|meta-data|verify-all|migrate|reconfig)	#REQUIRED
 	timeout		CDATA	#REQUIRED
 	interval 	CDATA	#IMPLIED
 	start-delay 	CDATA	#IMPLIED
@@ -56,7 +57,6 @@
 
 <!ELEMENT attributes EMPTY>
 <!ATTLIST attributes
-	root (1|0) "0"
 	maxinstances CDATA "0">
 
 <!ELEMENT child EMPTY>
--- cluster/rgmanager/src/resources/service.sh	2007/05/02 18:28:52	1.7.2.4
+++ cluster/rgmanager/src/resources/service.sh	2007/07/31 17:56:10	1.7.2.4.2.1
@@ -56,7 +56,7 @@
             <content type="string"/>
         </parameter>
     
-        <parameter name="domain">
+        <parameter name="domain" reconfig="1">
             <longdesc lang="en">
                 Fail over domains define lists of cluster members
                 to try in the event that a resource group fails.
@@ -67,7 +67,7 @@
             <content type="string"/>
         </parameter>
 
-        <parameter name="autostart">
+        <parameter name="autostart" reconfig="1">
             <longdesc lang="en">
 	    	If set to yes, this resource group will automatically be started
 		after the cluster forms a quorum.  If set to no, this resource
@@ -80,7 +80,7 @@
             <content type="boolean"/>
         </parameter>
 
-        <parameter name="hardrecovery">
+        <parameter name="hardrecovery" reconfig="1">
             <longdesc lang="en">
 	    	If set to yes, the last owner will reboot if this resource
 		group fails to stop cleanly, thus allowing the resource
@@ -128,7 +128,7 @@
 	    <content type="boolean"/>
 	</parameter>
                 
-        <parameter name="recovery">
+        <parameter name="recovery" reconfig="1">
             <longdesc lang="en">
 	        This currently has three possible options: "restart" tries
 		to restart failed parts of this resource group locally before
@@ -164,10 +164,11 @@
         <action name="status" timeout="5" interval="1h"/>
         <action name="monitor" timeout="5" interval="1h"/>
 
+        <action name="reconfig" timeout="5"/>
         <action name="recover" timeout="5"/>
         <action name="reload" timeout="5"/>
         <action name="meta-data" timeout="5"/>
-        <action name="verify-all" timeout="5"/>
+        <action name="validate-all" timeout="5"/>
     </actions>
     
     <special tag="rgmanager">
@@ -224,7 +225,10 @@
 		meta_data
 		exit 0
 		;;
-	verify-all)
+	validate-all)
+		exit 0
+		;;
+	reconfig)
 		exit 0
 		;;
 	*)
--- cluster/rgmanager/src/resources/vm.sh	2007/07/24 18:49:18	1.1.2.4.2.1
+++ cluster/rgmanager/src/resources/vm.sh	2007/07/31 17:56:10	1.1.2.4.2.2
@@ -51,7 +51,7 @@
             <content type="string"/>
         </parameter>
     
-        <parameter name="domain">
+        <parameter name="domain" reconfig="1">
             <longdesc lang="en">
                 Fail over domains define lists of cluster members
                 to try in the event that the host of the virtual machine
@@ -63,7 +63,7 @@
             <content type="string"/>
         </parameter>
 
-        <parameter name="autostart">
+        <parameter name="autostart" reconfig="1">
             <longdesc lang="en">
 	    	If set to yes, this resource group will automatically be started
 		after the cluster forms a quorum.  If set to no, this virtual
@@ -193,12 +193,16 @@
 	<action name="migrate" timeout="10m"/>
 
         <action name="meta-data" timeout="5"/>
-        <action name="verify-all" timeout="5"/>
+        <action name="validate-all" timeout="5"/>
 
     </actions>
     
     <special tag="rgmanager">
-        <attributes maxinstances="1"/>
+    	<!-- Destroy_on_delete / init_on_add are currently only
+	     supported for migratory resources (no children
+	     and the 'migrate' action; see above.  Do not try this
+	     with normal services -->
+        <attributes maxinstances="1" destroy_on_delete="0" init_on_add="0"/>
     </special>
 </resource-agent>
 EOT
@@ -417,12 +421,12 @@
 		meta_data
 		exit 0
 		;;
-	verify-all)
+	validate-all)
 		verify_all
 		exit $?
 		;;
 	*)
-		echo "usage: $0 {start|stop|restart|status|reload|reconfig|meta-data|verify-all}"
+		echo "usage: $0 {start|stop|restart|status|reload|reconfig|meta-data|validate-all}"
 		exit 1
 		;;
 esac



^ permalink raw reply	[flat|nested] 5+ messages in thread
* [Cluster-devel] cluster/rgmanager ChangeLog include/res-ocf.h  ...
@ 2007-07-31 17:54 lhh
  0 siblings, 0 replies; 5+ messages in thread
From: lhh @ 2007-07-31 17:54 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL5
Changes by:	lhh at sourceware.org	2007-07-31 17:54:55

Modified files:
	rgmanager      : ChangeLog 
	rgmanager/include: res-ocf.h reslist.h 
	rgmanager/src/clulib: rg_strings.c 
	rgmanager/src/daemons: groups.c reslist.c resrules.c restree.c 
	                       test.c 
	rgmanager/src/resources: ra-api-1-modified.dtd service.sh vm.sh 

Log message:
	Fix bug #248727

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/ChangeLog.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.31.2.22&r2=1.31.2.23
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/res-ocf.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1.16.1&r2=1.1.16.2
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/include/reslist.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.15.2.4&r2=1.15.2.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/clulib/rg_strings.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5.2.4&r2=1.5.2.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/groups.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.25.2.10&r2=1.25.2.11
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/reslist.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.14.2.3&r2=1.14.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/resrules.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.16.2.6&r2=1.16.2.7
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/restree.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.23.2.8&r2=1.23.2.9
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/daemons/test.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6.2.4&r2=1.6.2.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/ra-api-1-modified.dtd.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/service.sh.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.7.2.4&r2=1.7.2.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/rgmanager/src/resources/vm.sh.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.1.2.5&r2=1.1.2.6

--- cluster/rgmanager/ChangeLog	2007/07/24 13:53:07	1.31.2.22
+++ cluster/rgmanager/ChangeLog	2007/07/31 17:54:54	1.31.2.23
@@ -1,3 +1,23 @@
+2007-07-31 Lon Hohberger <lhh@redhat.com>
+	* general: Make VMs not change state when added/removed from the
+	cluster config or bounce services/VMs when minor config changes
+	are made. (#248727)
+	* include/res-ocf.h: Add reconfigure operation
+	* include/reslist.h: Add flags allowing reconfigurable options in
+	resource agent metadata, and per-agent flags which allow resources
+	to be added w/o initialization / removed w/o kill.
+	* src/clulib/rg_strings.c: Add string definition for reconfigure op
+	* src/daemons/groups.c: Allow no-init-on-add and no-kill-on-delete
+	flags to work
+	* src/daemons/reslist.c: Allow resource comparison to take into 
+	account reconfig flags and return a new value if the resource is
+	reconfigurable
+	* src/daemons/resrules.c: Code to support new flags
+	* src/daemons/restree.c: Code to support reconfiguration operation
+	* src/daemons/test.c: Code to support testing new reconfig ops and
+	behaviors
+	* src/resources/*: Add new flags to service and VM resource agents.
+
 2007-07-24 Lon Hohberger <lhh@redhat.com>
 	* general: make threads exit with pthread_exit() so we can wrap/track them.
 	Add internal statedump (SIGUSR1) support.
--- cluster/rgmanager/include/res-ocf.h	2007/03/20 17:09:11	1.1.16.1
+++ cluster/rgmanager/include/res-ocf.h	2007/07/31 17:54:54	1.1.16.2
@@ -62,5 +62,6 @@
 #define RS_META_DATA	(11)
 #define RS_VALIDATE	(12)
 #define RS_MIGRATE	(13)
+#define RS_RECONFIG	(14)
 
 #endif
--- cluster/rgmanager/include/reslist.h	2007/06/26 21:55:45	1.15.2.4
+++ cluster/rgmanager/include/reslist.h	2007/07/31 17:54:54	1.15.2.5
@@ -25,10 +25,11 @@
 #include <libxml/xpath.h>
 
 
-#define RA_PRIMARY	(1<<0)
-#define RA_UNIQUE	(1<<1)
-#define RA_REQUIRED	(1<<2)
-#define RA_INHERIT	(1<<3)
+#define RA_PRIMARY	(1<<0)	/** Primary key */
+#define RA_UNIQUE	(1<<1)	/** Unique for given type */
+#define RA_REQUIRED	(1<<2)	/** Required (or an error if not present */
+#define RA_INHERIT	(1<<3)	/** Inherit a parent resource's attr */
+#define RA_RECONFIG	(1<<4)	/** Allow inline reconfiguration */
 
 #define RF_INLINE	(1<<0)
 #define RF_DEFINED	(1<<1)
@@ -37,6 +38,15 @@
 #define RF_COMMON	(1<<4)	/** " */
 #define RF_INDEPENDENT	(1<<5)  /** Define this for a resource if it is
 				  otherwise an independent subtree */
+#define RF_RECONFIG	(1<<6)
+
+#define RF_INIT		(1<<7)	/** Resource rule: Initialize this resource
+				  class on startup */
+#define RF_DESTROY	(1<<8)	/** Resource rule flag: Destroy this
+				  resource class if you delete it from
+				  the configuration */
+
+
 
 #define RES_STOPPED	(0)
 #define RES_STARTED	(1)
--- cluster/rgmanager/src/clulib/rg_strings.c	2007/07/06 18:50:22	1.5.2.4
+++ cluster/rgmanager/src/clulib/rg_strings.c	2007/07/31 17:54:54	1.5.2.5
@@ -106,6 +106,7 @@
 	{RS_META_DATA, "meta-data"},		/* printenv */
 	{RS_VALIDATE, "validate-all"},
 	{RS_MIGRATE, "migrate"},
+	{RS_RECONFIG, "reconfig"},
 	{0 , NULL}
 };
 
--- cluster/rgmanager/src/daemons/groups.c	2007/07/24 13:53:08	1.25.2.10
+++ cluster/rgmanager/src/daemons/groups.c	2007/07/31 17:54:54	1.25.2.11
@@ -1222,6 +1222,7 @@
 do_condstops(void)
 {
 	resource_node_t *curr;
+	struct dlm_lksb lockp;
 	rg_state_t svcblk;
 	int need_kill;
 	char rg[64];
@@ -1249,6 +1250,24 @@
 			clulog(LOG_DEBUG, "Removing %s\n", rg);
 		}
 
+		if (!curr->rn_child && ((curr->rn_resource->r_rule->rr_flags &
+		    RF_DESTROY) == 0) && group_migratory(rg, 0) &&
+		    need_kill == 1) {
+			/* Do something smart here: flip state? */
+			clulog(LOG_NOTICE,
+			       "%s removed from the config, but I am not stopping it.\n",
+			       rg);
+			if (rg_lock(rg, &lockp) != 0)
+				continue;
+			if (get_rg_state(rg, &svcblk) < 0)
+		       		goto cont;
+			svcblk.rs_state = RG_STATE_DISABLED;
+			set_rg_state(rg, &svcblk);
+cont:
+			rg_unlock(&lockp);
+			continue;
+		}
+
 		rt_enqueue_request(rg, need_kill ? RG_DISABLE : RG_CONDSTOP,
 				   NULL, 0, 0, 0, 0);
 
@@ -1282,7 +1301,8 @@
 
 		/* New RG.  We'll need to initialize it. */
 		need_init = 0;
-		if (curr->rn_resource->r_flags & RF_NEEDSTART)
+		if (!(curr->rn_resource->r_flags & RF_RECONFIG) &&
+		    (curr->rn_resource->r_flags & RF_NEEDSTART))
 			need_init = 1;
 
 		if (!need_init) {
@@ -1305,7 +1325,17 @@
 
 		if (need_init) {
 			++new_groups;
-			clulog(LOG_DEBUG, "Initializing %s\n", rg);
+			clulog(LOG_NOTICE, "Initializing %s\n", rg);
+		}
+
+		if (!curr->rn_child && ((curr->rn_resource->r_rule->rr_flags &
+		    RF_INIT) == 0) && group_migratory(rg, 0) &&
+		    need_init == 1) {
+			/* Do something smart here? */
+			clulog(LOG_NOTICE,
+			       "%s was added to the config, but I am not initializing it.\n",
+			       rg);
+			continue;
 		}
 
 		rt_enqueue_request(rg, need_init ? RG_INIT : RG_CONDSTART,
--- cluster/rgmanager/src/daemons/reslist.c	2007/04/26 20:40:28	1.14.2.3
+++ cluster/rgmanager/src/daemons/reslist.c	2007/07/31 17:54:54	1.14.2.4
@@ -176,18 +176,29 @@
 /**
    Compare two resources.
 
+  @param left	Left resource
+  @param right	Right resource	
+  @return	-1 on different resource, 0 if the same, 1 if different,
+		2 if different, but only safe resources are different
+
  */
 int
 rescmp(resource_t *left, resource_t *right)
 {
-	int x, y = 0, found;
+	int x, y = 0, found = 0, ret = 0;
+
 
 	/* Completely different resource class... */
 	if (strcmp(left->r_rule->rr_type, right->r_rule->rr_type)) {
-		//printf("Er, wildly different resource type! ");
 		return -1;
 	}
 
+	/*
+	printf("Comparing %s:%s to %s:%s\n",
+	       left->r_rule->rr_type, left->r_attrs[0].ra_value,
+	       right->r_rule->rr_type, right->r_attrs[0].ra_value)
+	 */
+
 	for (x = 0; left->r_attrs && left->r_attrs[x].ra_name; x++) {
 
 		found = 0;
@@ -203,35 +214,52 @@
 			    left->r_attrs[x].ra_flags) {
 				/* Flags are different.  Change in
 				   resource agents? */
-				//printf("flags differ ");
+				/*
+				printf("* flags differ %08x vs %08x\n",
+				       left->r_attrs[x].ra_flags,
+				       right->r_attrs[y].ra_flags);
+				 */
 				return 1;
 			}
 
 			if (strcmp(right->r_attrs[y].ra_value,
 				   left->r_attrs[x].ra_value)) {
 				/* Different attribute value. */
-				//printf("different value for attr '%s'  ",
-				       //right->r_attrs[y].ra_name);
-				return 1;
+				/*
+				printf("* different value for attr '%s':"
+				       " '%s' vs '%s'",
+				       right->r_attrs[y].ra_name,
+				       left->r_attrs[x].ra_value,
+				       right->r_attrs[y].ra_value);
+				 */
+				if (left->r_attrs[x].ra_flags & RA_RECONFIG) {
+					/* printf(" [SAFE]\n"); */
+					ret = 2;
+			 	} else {
+					/* printf("\n"); */
+					return 1;
+				}
 			}
 		}
 
 		/* Attribute missing -> different attribute value. */
 		if (!found) {
-			//printf("Attribute %s deleted  ",
-			       //left->r_attrs[x].ra_name);
+			/*
+			printf("* Attribute '%s' deleted\n",
+			       left->r_attrs[x].ra_name);
+			 */
 			return 1;
 		}
 	}
 
 	/* Different attribute count */
 	if (x != y) {
-		//printf("Attribute count differ (attributes added!) ");
+		/* printf("* Attribute count differ (attributes added!) "); */
 		return 1;
 	}
 
 	/* All the same */
-	return 0;
+	return ret;
 }
 
 
@@ -288,7 +316,7 @@
 	resource_t *curr;
 	char ref_buf[128];
 	char *type;
-	char *name;
+	char *name = ref;
 	int x;
 
 	snprintf(ref_buf, sizeof(ref_buf), "%s", ref);
@@ -300,6 +328,7 @@
 	} else {
 		/* Default type */
 		type = "service";
+		name = ref;
 	}
 
 	list_do(reslist, curr) {
@@ -543,6 +572,8 @@
 		printf(" [NEEDSTOP]");
 	if (res->r_flags & RF_COMMON)
 		printf(" [COMMON]");
+	if (res->r_flags & RF_RECONFIG)
+		printf(" [RECONFIG]");
 	printf("\n");
 
 	if (res->r_rule->rr_maxrefs)
@@ -578,6 +609,8 @@
 			printf(" unique");
 		if (res->r_attrs[x].ra_flags & RA_REQUIRED)
 			printf(" required");
+		if (res->r_attrs[x].ra_flags & RA_RECONFIG)
+			printf(" reconfig");
 		if (res->r_attrs[x].ra_flags & RA_INHERIT)
 			printf(" inherit(\"%s\")", res->r_attrs[x].ra_value);
 		printf(" ]\n");
--- cluster/rgmanager/src/daemons/resrules.c	2007/06/26 21:55:46	1.16.2.6
+++ cluster/rgmanager/src/daemons/resrules.c	2007/07/31 17:54:54	1.16.2.7
@@ -163,6 +163,36 @@
 
 
 /**
+   Get and store a bit field.
+
+   @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_rule_flag(xmlDocPtr doc, xmlXPathContextPtr ctx, char *base,
+	       resource_rule_t *rr, char *flag, int bit)
+{
+	char xpath[256];
+	char *ret = NULL;
+
+	snprintf(xpath, sizeof(xpath),
+		 "%s/attributes/@%s",
+		 base, flag);
+	ret = xpath_get_one(doc, ctx, xpath);
+	if (ret) {
+		if (atoi(ret)) {
+			rr->rr_flags |= bit;
+		} else {
+			rr->rr_flags &= ~bit;
+		}
+		free(ret);
+	}
+}
+
+
+/**
    Get and store the version
 
    @param doc		Pre-parsed XML document pointer.
@@ -516,6 +546,17 @@
 		printf("Max instances: %d\n", rr->rr_maxrefs);
 	if (rr->rr_agent)
 		printf("Agent: %s\n", basename(rr->rr_agent));
+
+	printf("Flags: ");
+	if (rr->rr_flags) {
+		if (rr->rr_flags & RF_INIT)
+			printf("init_on_add ");
+		if (rr->rr_flags & RF_DESTROY)
+			printf("destroy_on_delete ");
+	} else {
+		printf("(none)");
+	}
+	printf("\n");
 	
 	printf("Attributes:\n");
 	if (!rr->rr_attrs) {
@@ -531,18 +572,25 @@
 			continue;
 		}
 
-		printf(" [");
-		if (rr->rr_attrs[x].ra_flags & RA_PRIMARY)
-			printf(" primary");
-		if (rr->rr_attrs[x].ra_flags & RA_UNIQUE)
-			printf(" unique");
-		if (rr->rr_attrs[x].ra_flags & RA_REQUIRED)
-			printf(" required");
-		if (rr->rr_attrs[x].ra_flags & RA_INHERIT)
-			printf(" inherit");
-		else if (rr->rr_attrs[x].ra_value)
-			printf(" default=\"%s\"", rr->rr_attrs[x].ra_value);
-		printf(" ]\n");
+		if (rr->rr_attrs[x].ra_flags) {
+			printf(" [");
+			if (rr->rr_attrs[x].ra_flags & RA_PRIMARY)
+				printf(" primary");
+			if (rr->rr_attrs[x].ra_flags & RA_UNIQUE)
+				printf(" unique");
+			if (rr->rr_attrs[x].ra_flags & RA_REQUIRED)
+				printf(" required");
+			if (rr->rr_attrs[x].ra_flags & RA_INHERIT)
+				printf(" inherit");
+			if (rr->rr_attrs[x].ra_flags & RA_RECONFIG)
+				printf(" reconfig");
+			printf(" ]");
+		}
+
+		if (rr->rr_attrs[x].ra_value)
+			printf(" default=\"%s\"\n", rr->rr_attrs[x].ra_value);
+		else
+			printf("\n");
 	}
 
 actions:
@@ -678,6 +726,18 @@
 		}
 
 		/*
+		   See if this can be reconfigured on the fly without a 
+		   stop/start
+		 */
+		snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@reconfig",
+			 base, x);
+		if ((ret = xpath_get_one(doc,ctx,xpath))) {
+			if ((atoi(ret) != 0) || (ret[0] == 'y'))
+				flags |= RA_RECONFIG;
+			free(ret);
+		}
+
+		/*
 		   See if this is supposed to be inherited
 		 */
 		snprintf(xpath, sizeof(xpath), "%s/parameter[%d]/@inherit",
@@ -942,6 +1002,7 @@
 			break;
 		memset(rr,0,sizeof(*rr));
 
+		rr->rr_flags = RF_INIT | RF_DESTROY;
 		rr->rr_type = type;
 		snprintf(base, sizeof(base), "/resource-agent[%d]", ruleid);
 
@@ -954,6 +1015,8 @@
 			 "/resource-agent[%d]/special[@tag=\"rgmanager\"]",
 			 ruleid);
 		_get_maxparents(doc, ctx, base, rr);
+		_get_rule_flag(doc, ctx, base, rr, "init_on_add", RF_INIT);
+		_get_rule_flag(doc, ctx, base, rr, "destroy_on_delete", RF_DESTROY);
 		rr->rr_agent = strdup(filename);
 
 		/*
--- cluster/rgmanager/src/daemons/restree.c	2007/06/26 21:55:46	1.23.2.8
+++ cluster/rgmanager/src/daemons/restree.c	2007/07/31 17:54:54	1.23.2.9
@@ -1186,9 +1186,15 @@
 
 	/* Start starts before children */
 	if (me && (op == RS_START)) {
-		node->rn_flags &= ~RF_NEEDSTART;
 
-		rv = res_exec(node, op, NULL, 0);
+		if (node->rn_flags & RF_RECONFIG &&
+		    realop == RS_CONDSTART) {
+			rv = res_exec(node, RS_RECONFIG, NULL, 0);
+			op = realop; /* reset to CONDSTART */
+		} else {
+			rv = res_exec(node, op, NULL, 0);
+		}
+		node->rn_flags &= ~(RF_NEEDSTART | RF_RECONFIG);
 		if (rv != 0) {
 			node->rn_state = RES_FAILED;
 			return SFL_FAILURE;
@@ -1408,6 +1414,7 @@
 resource_delta(resource_t **leftres, resource_t **rightres)
 {
 	resource_t *lc, *rc;
+	int ret;
 
 	list_do(leftres, lc) {
 		rc = find_resource_by_ref(rightres, lc->r_rule->rr_type,
@@ -1420,10 +1427,25 @@
 		}
 
 		/* Ok, see if the resource is the same */
-		if (rescmp(lc, rc) == 0) {
+		ret = rescmp(lc, rc);
+		if (ret	== 0) {
 			rc->r_flags |= RF_COMMON;
 			continue;
 		}
+
+		if (ret == 2) {
+			/* return of 2 from rescmp means
+			   the two resources differ only 
+			   by reconfigurable bits */
+			/* Do nothing on condstop phase;
+			   do a "reconfig" instead of 
+			   "start" on conststart phase */
+			rc->r_flags |= RF_COMMON;
+			rc->r_flags |= RF_NEEDSTART;
+			rc->r_flags |= RF_RECONFIG;
+			continue;
+		}
+
 		rc->r_flags |= RF_COMMON;
 
 		/* Resource has changed.  Flag it. */
@@ -1485,12 +1507,17 @@
 			   or is new), then we don't really care about its
 			   children.
 			 */
+
 			if (rn->rn_resource->r_flags & RF_NEEDSTART) {
 				rn->rn_flags |= RF_NEEDSTART;
-				continue;
+				if ((rn->rn_resource->r_flags & RF_RECONFIG) == 0)
+					continue;
 			}
 
-			if (rc == 0) {
+			if (rc == 0 || rc == 2) {
+				if (rc == 2)
+					rn->rn_flags |= RF_NEEDSTART | RF_RECONFIG;
+
 				/* Ok, same resource.  Recurse. */
 				ln->rn_flags |= RF_COMMON;
 				rn->rn_flags |= RF_COMMON;
--- cluster/rgmanager/src/daemons/test.c	2007/06/27 14:03:20	1.6.2.4
+++ cluster/rgmanager/src/daemons/test.c	2007/07/31 17:54:54	1.6.2.5
@@ -32,6 +32,50 @@
 #error "Can not be built with CCS support."
 #endif
 
+/**
+  Tells us if a resource group can be migrated.
+ */
+int
+group_migratory(resource_t **resources, resource_node_t **tree, char *groupname)
+{
+	resource_node_t *rn;
+	resource_t *res;
+	int migrate = 0, x, ret = 0;
+
+	res = find_root_by_ref(resources, groupname);
+	if (!res) {
+		/* 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)
+		goto out_unlock;
+
+	list_do(tree, rn) {
+		if (rn->rn_resource == res && rn->rn_child) {
+			/* TL service w/ children cannot be migrated */
+			goto out_unlock;
+		}
+	} while (!list_done(tree, rn));
+
+
+	/* 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 */
+	ret = 1;
+
+out_unlock:
+	return ret;
+}
+
 #define shift() {++argv; --argc;}
 
 #define USAGE_TEST \
@@ -217,7 +261,9 @@
 	resource_rule_t *rulelist = NULL, *currule, *rulelist2 = NULL;
 	resource_t *reslist = NULL, *curres, *reslist2 = NULL;
 	resource_node_t *tree = NULL, *tree2 = NULL;
-	int ccsfd, ret = 0;
+	resource_node_t *tn;
+	int ccsfd, ret = 0, need_init, need_kill;
+	char rg[64];
 
 	if (argc < 2) {
 		printf("Operation requires two arguments\n");
@@ -276,6 +322,57 @@
 	print_resource_tree(&tree);
 	printf("=== New Resource Tree ===\n");
 	print_resource_tree(&tree2);
+	printf("=== Operations (down-phase) ===\n");
+	list_do(&tree, tn) {
+		res_build_name(rg, sizeof(rg), tn->rn_resource);
+		/* Set state to uninitialized if we're killing a RG */
+		need_init = 0;
+
+		/* Set state to uninitialized if we're killing a RG */
+		need_kill = 0;
+		if (tn->rn_resource->r_flags & RF_NEEDSTOP) {
+			need_kill = 1;
+			printf("[kill] ");
+		}
+
+		if (!tn->rn_child && ((tn->rn_resource->r_rule->rr_flags &
+		    RF_DESTROY) == 0) && group_migratory(&reslist, &tree, rg) &&
+		    need_kill == 1) {
+			/* Do something smart here: flip state? */
+			printf("[no-op] %s was removed from the config, but I am not stopping it.\n",
+			       rg);
+			continue;
+		}
+
+		res_condstop(&tn, tn->rn_resource, NULL);
+	} while (!list_done(&tree, tn));
+	printf("=== Operations (up-phase) ===\n");
+	list_do(&tree2, tn) {
+		res_build_name(rg, sizeof(rg), tn->rn_resource);
+		/* New RG.  We'll need to initialize it. */
+		need_init = 0;
+		if (!(tn->rn_resource->r_flags & RF_RECONFIG) &&
+		    (tn->rn_resource->r_flags & RF_NEEDSTART))
+			need_init = 1;
+
+		if (need_init) {
+			printf("[init] ");
+		}
+
+		if (!tn->rn_child && ((tn->rn_resource->r_rule->rr_flags &
+		    RF_INIT) == 0) && group_migratory(&reslist2, &tree2, rg) &&
+		    need_init == 1) {
+			/* Do something smart here? */
+			printf("[noop] %s was added, but I am not initializing it\n", rg);
+			continue;
+		}
+
+		if (need_init) {
+			res_stop(&tn, tn->rn_resource, NULL);
+		} else {
+			res_condstart(&tn, tn->rn_resource, NULL);
+		}
+	} while (!list_done(&tree2, tn));
 
 out:
 	destroy_resource_tree(&tree2);
@@ -331,6 +428,7 @@
 			goto out;
 		} else if (!strcmp(argv[1], "delta")) {
 			shift();
+			_no_op_mode(1);
 			ret = tree_delta_test(argc, argv);
 			goto out;
 		} else {
--- cluster/rgmanager/src/resources/ra-api-1-modified.dtd	2006/08/18 15:26:22	1.4
+++ cluster/rgmanager/src/resources/ra-api-1-modified.dtd	2007/07/31 17:54:55	1.4.2.1
@@ -24,6 +24,7 @@
 	name	CDATA	#REQUIRED
 	primary (1|0)   "0"
 	required (1|0)	"0"
+	reconfig (1|0)	"0"
 	inherit CDATA	""
 	unique	(1|0)	"0"
 	reconfig (1|0)  "0">
@@ -43,7 +44,7 @@
 
 <!ELEMENT action EMPTY>
 <!ATTLIST action
-	name	(start|stop|recover|status|reconfig|monitor|reload|meta-data|verify-all|migrate)	#REQUIRED
+	name	(start|stop|recover|status|reconfig|monitor|reload|meta-data|verify-all|migrate|reconfig)	#REQUIRED
 	timeout		CDATA	#REQUIRED
 	interval 	CDATA	#IMPLIED
 	start-delay 	CDATA	#IMPLIED
@@ -56,7 +57,6 @@
 
 <!ELEMENT attributes EMPTY>
 <!ATTLIST attributes
-	root (1|0) "0"
 	maxinstances CDATA "0">
 
 <!ELEMENT child EMPTY>
--- cluster/rgmanager/src/resources/service.sh	2007/05/02 18:28:52	1.7.2.4
+++ cluster/rgmanager/src/resources/service.sh	2007/07/31 17:54:55	1.7.2.5
@@ -56,7 +56,7 @@
             <content type="string"/>
         </parameter>
     
-        <parameter name="domain">
+        <parameter name="domain" reconfig="1">
             <longdesc lang="en">
                 Fail over domains define lists of cluster members
                 to try in the event that a resource group fails.
@@ -67,7 +67,7 @@
             <content type="string"/>
         </parameter>
 
-        <parameter name="autostart">
+        <parameter name="autostart" reconfig="1">
             <longdesc lang="en">
 	    	If set to yes, this resource group will automatically be started
 		after the cluster forms a quorum.  If set to no, this resource
@@ -80,7 +80,7 @@
             <content type="boolean"/>
         </parameter>
 
-        <parameter name="hardrecovery">
+        <parameter name="hardrecovery" reconfig="1">
             <longdesc lang="en">
 	    	If set to yes, the last owner will reboot if this resource
 		group fails to stop cleanly, thus allowing the resource
@@ -128,7 +128,7 @@
 	    <content type="boolean"/>
 	</parameter>
                 
-        <parameter name="recovery">
+        <parameter name="recovery" reconfig="1">
             <longdesc lang="en">
 	        This currently has three possible options: "restart" tries
 		to restart failed parts of this resource group locally before
@@ -164,10 +164,11 @@
         <action name="status" timeout="5" interval="1h"/>
         <action name="monitor" timeout="5" interval="1h"/>
 
+        <action name="reconfig" timeout="5"/>
         <action name="recover" timeout="5"/>
         <action name="reload" timeout="5"/>
         <action name="meta-data" timeout="5"/>
-        <action name="verify-all" timeout="5"/>
+        <action name="validate-all" timeout="5"/>
     </actions>
     
     <special tag="rgmanager">
@@ -224,7 +225,10 @@
 		meta_data
 		exit 0
 		;;
-	verify-all)
+	validate-all)
+		exit 0
+		;;
+	reconfig)
 		exit 0
 		;;
 	*)
--- cluster/rgmanager/src/resources/vm.sh	2007/07/11 19:35:06	1.1.2.5
+++ cluster/rgmanager/src/resources/vm.sh	2007/07/31 17:54:55	1.1.2.6
@@ -51,7 +51,7 @@
             <content type="string"/>
         </parameter>
     
-        <parameter name="domain">
+        <parameter name="domain" reconfig="1">
             <longdesc lang="en">
                 Fail over domains define lists of cluster members
                 to try in the event that the host of the virtual machine
@@ -63,7 +63,7 @@
             <content type="string"/>
         </parameter>
 
-        <parameter name="autostart">
+        <parameter name="autostart" reconfig="1">
             <longdesc lang="en">
 	    	If set to yes, this resource group will automatically be started
 		after the cluster forms a quorum.  If set to no, this virtual
@@ -193,12 +193,16 @@
 	<action name="migrate" timeout="10m"/>
 
         <action name="meta-data" timeout="5"/>
-        <action name="verify-all" timeout="5"/>
+        <action name="validate-all" timeout="5"/>
 
     </actions>
     
     <special tag="rgmanager">
-        <attributes maxinstances="1"/>
+    	<!-- Destroy_on_delete / init_on_add are currently only
+	     supported for migratory resources (no children
+	     and the 'migrate' action; see above.  Do not try this
+	     with normal services -->
+        <attributes maxinstances="1" destroy_on_delete="0" init_on_add="0"/>
     </special>
 </resource-agent>
 EOT
@@ -417,12 +421,12 @@
 		meta_data
 		exit 0
 		;;
-	verify-all)
+	validate-all)
 		verify_all
 		exit $?
 		;;
 	*)
-		echo "usage: $0 {start|stop|restart|status|reload|reconfig|meta-data|verify-all}"
+		echo "usage: $0 {start|stop|restart|status|reload|reconfig|meta-data|validate-all}"
 		exit 1
 		;;
 esac



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-12-19 21:07 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-31 18:00 [Cluster-devel] cluster/rgmanager ChangeLog include/res-ocf.h lhh
  -- strict thread matches above, loose matches on Subject: below --
2007-12-19 21:07 lhh
2007-12-19 21:04 lhh
2007-07-31 17:56 lhh
2007-07-31 17:54 lhh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).