Contents
Clones were initially conceived as a convienient way to start N instances of an IP resource and have them distributed throughout the cluster for load balancing. They have turned out to quite useful for a number of purposes including integrating with Red Hat's DLM, the fencing subsystem and OCFS2.
In fact you can clone any resource provided the ResourceAgent supports it. Like regular resources you may even have it configured differently depending on which host it is active on.
Three types of cloned resources exist.
You can read more about them here: v2/Concepts/MultiState
ordered (default: FALSE)
interleave (default: FALSE)
notify (default: FALSE)
This requires the notify action to be implemented. See "Writing a Clone Resource Agent" for details below.
clone_max (default: 1)
clone_node_max (default: 1)
globally_unique (default: TRUE)
In the example below we have specified that the WebServerIP resource should be a ClusteredIP. It will be started on at most 3 nodes and at most there can be 2 clone active on any given node. Instance 1 will serve the first "bucket", instance 2 the second and so on.
<clone id="MyCorpWWW" ordered="false" interleave="false" notify="false">
<instance_attributes>
<attributes>
<nvpair name="clone_max" value="3"/>
<nvpair name="clone_node_max" value="2"/>
</attributes>
</instance_attributes>
<primitive id="WebServerIP" class="ocf" type="IPaddr" provider="heartbeat">
<instance_attributes>
<attributes>
<nvpair name="ip" value="127.0.0.26"/>
</attributes>
</instance_attributes>
</primitive>
</clone>
If there are >=3 nodes available:
Start order (with ordered=false)
Stop order (with ordered=false)
Start order (with ordered=true)
Start WebServerIP:0
Start WebServerIP:1
Start WebServerIP:2
Stop order (with ordered=true)
Stop WebServerIP:2
Stop WebServerIP:1
Stop WebServerIP:0
All OCF variables can normally be found in /usr/lib/ocf/resource.d/heartbeat/ocf-shellfuncs which should be the first thing included by a resource agent.
Only OCF ResourceAgents are supported for cloning. This is due to the extra variables that need to be sent to the agent.
ResourceAgents are required to accurately report how many instances are active. In order to recover from possible failures or administrative accidents, the CRM checks for active resources (generally this is done at startup). In CRM terminology, these are called "probes" and one is sent for every possible clone instance. Probes can be recognized in shell scripts with the following code:
[ "${__OCF_ACTION}" = "monitor" -a "${OCF_RESKEY_CRM_meta_interval}" = "0" ]
. For anonymous clones, the ResourceAgent must only respond with ${OCF_SUCCESS} to N of these probes. Where N is the number of active instances of the clone on that node. This is the minimum requirement but it is preferable for the ResourceAgent to act as defined for globally unique clones below.
. For globally unique clones, the ResourceAgent must only respond with ${OCF_SUCCESS} if the node has that exact instance active. Clone instances are identified as clone number OCF_RESKEY_CRM_meta_clone of OCF_RESKEY_CRM_meta_clone_max. These variables are available for ResourceAgents to use. All other probes for instances of the clone should result in ${OCF_NOT_RUNNING}. Unless of course they are failed, in which case they should return one of the other OCF error codes.
v2/Concepts/MultiState resources have additional requirements not discussed here.
A Clone Resource Agent can optionally implement the notify operation.
Notification can be enabled by adding notify="true" to the resource's definition.
Once enabled, your resource will receive pre and post notification events telling the resource what is or did just take place. Currently these are informational updates only and are not permitted to fail. Future version may allow notify actions to fail.
OCF_RESKEY_globally_unique (default: true)
These variables are available to notify actions.
OCF_RESKEY_CRM_meta_notify_type (pre|post)
OCF_RESKEY_CRM_meta_notify_operation (start|stop)
OCF_RESKEY_CRM_meta_notify_{x}_resource
OCF_RESKEY_CRM_meta_notify_ {x}_uname
Starting with 2.0.4, they will also be available to start and stop actions if notify="true" is set; notify_type and notify_operation is not provided there.
minus $OCF_RESKEY_notify_stop_resource
plus $OCF_RESKEY_CRM_meta_notify_stop_resource
minus $OCF_RESKEY_CRM_meta_notify_stop_resource
plus $OCF_RESKEY_CRM_meta_notify_start_resource
plus $OCF_RESKEY_CRM_meta_notify_stop_resource
minus $OCF_RESKEY_CRM_meta_notify_start_resource
An IP address on its own isnt much use. More than likely we'd like something like an apache instance to be started as well. What we can do is define the target of the clone to be a resource group.
<clone id="MyCorpWWW">
<instance_attributes>
<attributes>
<nvpair name="clone_max" value="3"/>
<nvpair name="clone_node_max" value="1"/>
</attributes>
</instance_attributes>
<group id="MyCorpWWW_group">
<primitive id="WebServerIP" class="ocf" type="IPaddr" provider="heartbeat">
<instance_attributes>
<attributes>
<nvpair name="ip" value="127.0.0.26"/>
</attributes>
</instance_attributes>
</primitive>
<primitive id="WebServerApache" class="ocf" type="Apache" provider="heartbeat">
<instance_attributes>
<attributes>
<nvpair name="apache_config" value="/home/www.mycorp.com/conf/apache.conf"/>
</attributes>
</instance_attributes>
</primitive>
</group>
</clone>
This will allocate one bucket and one apache instance to up to three nodes. If nothing was yet started and ordered=true, interleave=true, the startup order would be like this:
Start WebServerIP:0
Start WebServerApache:0
Start WebServerIP:1
Start WebServerApache:1
Start WebServerIP:2
Start WebServerApache:2
If instead ordered=true, interleave=false, the startup order would be like this:
Start WebServerIP:0
Start WebServerIP:1
Start WebServerIP:2
Start WebServerApache:0
Start WebServerApache:1
Start WebServerApache:2
Using constraints for the clone as a whole is no different to a native resource... you just use the id of the group.
<rsc_location id="run_MyCorpWWW" rsc="MyCorpWWW">
<rule id="pref_run_WebServerIP" score="100" boolean_op="or">
<expression attribute="#uname" operation="eq" value="c001n01"/>
<expression attribute="#uname" operation="eq" value="c001n02"/>
<expression attribute="#uname" operation="eq" value="c001n03"/>
</rule>
</rsc_location>
We specify 3 nodes since we will effectivly have 3 resources to place.
If we defined two more resources and had one start before MyCorpWWW and one after, the results are pretty much what you would expect.
<primitive id="Oracle" class="lsb" type="oracle"/> <primitive id="WwwStats" class="lsb" type="apache_stats"/> <rsc_order id="order_oracle_www" from="MyCorpWWW" action="start" type="after" to="Oracle"/> <rsc_order id="order_stats_www" from="MyCorpWWW" action="start" type="before" to="WwwStats"/>
If nothing was yet started, the order would be like this:
Start Oracle
Start WebServerIP:0
Start WebServerApache:0
Start WebServerIP:1
Start WebServerApache:1
Start WebServerIP:2
Start WebServerApache:2
Start WwwStats
and the reverse for stop.
If however, the "Oracle" resource was also a clone,
<clone id="Oracle">
<instance_attributes>
<attributes>
<nvpair name="clone_max" value="3"/>
<nvpair name="clone_node_max" value="1"/>
</attributes>
</instance_attributes>
<primitive id="Oracle_clone" class="lsb" type="oracle"/>
</clone>
the orders would be:
Start Oracle_clone:0
Start Oracle_clone:1
Start Oracle_clone:2
Start WebServerIP:0
Start WebServerApache:0
Start WebServerIP:1
Start WebServerApache:1
Start WebServerIP:2
Start WebServerApache:2
Start WwwStats
and the reverse for stop.
And if interleave=true was specified,
<clone id="Oracle_clones" interleave="true">
<instance_attributes>
<attributes>
<nvpair name="clone_max" value="3"/>
<nvpair name="clone_node_max" value="1"/>
</attributes>
</instance_attributes>
<primitive id="Oracle" class="lsb" type="oracle"/>
</clone>
then it would be:
Start Oracle:0
Start WebServerIP:0
Start WebServerApache:0
Start Oracle:1
Start WebServerIP:1
Start WebServerApache:1
Start Oracle:2
Start WebServerIP:2
Start WebServerApache:2
Start WwwStats
and the reverse for stop.
Co-locational -INFINITY constraints (ie. the resources must not be co-located) are the same as for any other resource.
<rsc_colocation id="not_same" from="www_prod_clones" to="www_test_clones" score="-INFINITY"/>Dont run production and test environments on the same machine.
Co-locational INFINITY constraints (ie. the resources must be co-located) for clones only make sense when the other resource is also a clone. Even then you are better off adding the resource to the resource group. All other cases are ignored.
to be filled in...