cluster: STABLE3 - rgmanager: Implement explicit ordering for failover

Lon Hohberger lon@fedoraproject.org
Thu May 21 14:54:00 GMT 2009


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=27fd9e088c46b4b135bb610c86657e8d51c6ffb5
Commit:        27fd9e088c46b4b135bb610c86657e8d51c6ffb5
Parent:        6c667e94643927342df40e90d0100a07c95286dd
Author:        Marc Grimme <grimme@atix.de>
AuthorDate:    Thu May 21 09:42:07 2009 -0400
Committer:     Lon Hohberger <lhh@redhat.com>
CommitterDate: Thu May 21 10:53:15 2009 -0400

rgmanager: Implement explicit ordering for failover

This allows users to define an explicit service
processing order when central_processing is enabled.
Previously, users would have to order things the
way they wanted in cluster.conf.

Resolves: 492828

Signed-off-by: Lon Hohberger <lhh@redhat.com>
---
 rgmanager/src/resources/default_event_script.sl |  150 ++++++++++++++++++++++-
 rgmanager/src/resources/service.sh              |   19 +++-
 2 files changed, 166 insertions(+), 3 deletions(-)

diff --git a/rgmanager/src/resources/default_event_script.sl b/rgmanager/src/resources/default_event_script.sl
index f2d4658..9144526 100644
--- a/rgmanager/src/resources/default_event_script.sl
+++ b/rgmanager/src/resources/default_event_script.sl
@@ -254,6 +254,154 @@ define allowed_nodes(service)
 	return anodes;
 }
 
+%
+% Returns the set of online nodes in preferred/shuffled order which
+% are allowed to run this service.  Gives highest preference to current
+% owner if nofailback is specified.
+% 
+define allowed_nodes(service)
+{
+	variable anodes;
+	variable online;
+	variable nodes_domain;
+	variable ordered, restricted, nofailback;
+	variable state, owner;
+	variable depends;
+
+	(nofailback, restricted, ordered, nodes_domain) =
+			service_domain_info(service);
+	(owner, state) = service_status(service);
+
+	anodes = nodes_online();
+
+	% Shuffle the array so we don't start all services on the same
+	% node.  TODO - add RR, Least-services, placement policies...
+	online = shuffle(anodes);
+
+	if (restricted == 1) {
+		anodes = intersection(nodes_domain, online);
+	} else {
+		% Ordered failover domains (nodes_domain) unioned with the
+		% online nodes basically just reorders the online node list
+		% according to failover domain priority rules.
+		anodes = union(intersection(nodes_domain, online),
+			       online);
+	}
+
+	if ((nofailback == 1) or (ordered == 0)) {
+		
+		if ((owner < 0) or (node_in_set(anodes, owner) == 0)) {
+			return anodes;
+		}
+		
+		% Because union takes left as priority, we can
+		% return the union of the current owner with the
+		% allowed node list.  This means the service will
+		% remain on the same node it's currently on.
+		return union(owner, anodes);
+	}
+
+	return anodes;
+}
+
+define string_list(thelist, delimiter)
+{
+	variable index;
+	variable output="";
+
+	if (length(thelist) == 0) {
+		return output;
+	}
+  
+	for (index=0; index < length(thelist)-1; index++) {
+		output=output+string(thelist[index])+delimiter;
+	}
+	return output+thelist[index];
+}
+
+% this function gets the smallest property from a given list of services
+% if the list only exists of one element the property itself is returned
+% if the given property is not found 0 is returned
+define services_min_attribute(services, property)
+{
+	variable x;
+	variable min_property=-1;
+	variable tmp_property;
+
+	for (x = 0; x < length(services); x++) {
+		tmp_property=service_property(services[x], property);
+		if (tmp_property == NULL) {
+			tmp_property=0;
+		} else {
+			tmp_property=atoi(tmp_property);
+		}
+		if ((min_property < 0) or (tmp_property < min_property)) {
+			min_property=tmp_property;
+		}
+		%debug("services_min_attribute: ",services[x]," attribute: ",min_property, "tmp: ", tmp_property, " min: ", min_property);
+	}
+
+	%debug("services_min_attribute: (", string_list(services, ", "),")[",property,"]: ",min_property);
+
+	return min_property;
+}
+
+% This function will sort a given service_list by the given attribute name and
+% return the list
+define sorted_service_list(services, attribute)
+{
+	variable work_queue={};
+	variable sorted_list={}, tmp, tmp2;
+	variable x, y;
+	variable cur_min_prop=0;
+	variable service_prop=0;
+
+	y=0;
+	%debug("sorted_service_list: ", strjoin(services, ", "));
+	for (x=0; x<length(services); x++) {
+		list_append(work_queue, string(services[x]));
+	}
+
+	%debug("sorted_service_list: work_queue ", string_list(work_queue, ", "));
+	while (length(work_queue) > 0) {
+		cur_min_prop=services_min_attribute(work_queue, attribute);
+		%debug("sorted_service_list sorting services list for attribute ", attribute, " cur_min: ",cur_min_prop);
+		for (x = 0; x < length(work_queue); x++) {
+			service_prop=service_property(work_queue[x], "priority");
+			if (service_prop == NULL) {
+				service_prop=0;
+			} else {
+				service_prop=atoi(service_prop);
+			}
+			%debug("sorted_service_list: ",work_queue[x], " property[", attribute,"]: ",service_prop);
+			if (cur_min_prop==service_prop) {
+				%debug("sorted_service_list: adding service ",work_queue[x]," to sorted. work_queue: ", string_list(work_queue, ", "));
+				list_append(sorted_list, work_queue[x]);
+				%debug("sorted_service_list: sorted_list: ", string_list(sorted_list, ", "));
+				%debug("sorted_service_list: removing service ",work_queue[x], " from work_queue ", string_list(work_queue, ", "));
+				list_delete(work_queue, x);
+				x=x-1;
+				%debug("sorted_service_list: work_queue: ",string_list(work_queue, ", "));
+				y=y+1;
+			}
+		}
+	}
+
+	debug("sorted_service_list ", string_list(sorted_list, ", "));
+	return sorted_list;
+}
+
+define sortedservices_node_event_handler(services, attribute) {
+	variable x;
+	variable nodes;
+
+	services=sorted_service_list(services, attribute);
+	for (x = 0; x < length(services); x++) {
+		debug("Executing sortedservices node event handler for service: ", services[x]);
+		nodes = allowed_nodes(services[x]);
+		()=move_or_start(services[x], nodes);
+	}
+}
 
 define default_node_event_handler()
 {
@@ -447,7 +595,7 @@ define default_user_event_handler()
 }
 
 if (event_type == EVENT_NODE)
-	default_node_event_handler();
+	sortedservices_node_event_handler(service_list(), "priority");
 if (event_type == EVENT_SERVICE)
 	default_service_event_handler();
 if (event_type == EVENT_CONFIG)
diff --git a/rgmanager/src/resources/service.sh b/rgmanager/src/resources/service.sh
index 6e35ee5..5adcc37 100644
--- a/rgmanager/src/resources/service.sh
+++ b/rgmanager/src/resources/service.sh
@@ -197,16 +197,31 @@ meta_data()
             <content type="string" default="0"/>
         </parameter>
 
+	<parameter name="priority">
+	    <longdesc lang="en">
+		Priority for the service.  In a failover scenario, this
+		indicates the ordering of the service (1 is processed
+		first, 2 is processed second, etc.).  This overrides the
+		order presented in cluster.conf.  This option only has
+		an effect if central processing within rgmanager is turned
+		on.
+	    </longdesc>
+	    <shortdesc lang="en">
+		Service priority
+	    </shortdesc>
+	    <content type="integer" default="0"/>
+	</parameter>
+
     </parameters>
 
     <actions>
         <action name="start" timeout="5"/>
         <action name="stop" timeout="5"/>
 	
-	<!-- No-ops.  Groups are abstract resource types.
+	<!-- No-ops.  Groups are abstract resource types. 
         <action name="status" timeout="5" interval="1h"/>
         <action name="monitor" timeout="5" interval="1h"/>
-       	 -->
+ -->
 
         <action name="reconfig" timeout="5"/>
         <action name="recover" timeout="5"/>



More information about the Cluster-cvs mailing list