Consider the following typical nodes section.
<nodes> <node id="f67904e0-4dfc-4db1-83a2-e930fc1d20f4" uname="c001n01" type="member"/> <node id="e9bdfde9-01b0-421f-acd8-8a65a53e775f" uname="c001n02" type="member"/> <node id="5d9a8c11-8684-43ea-9180-5e221530c193" uname="c001n03" type="member"/> <node id="c2896699-96b8-4dbc-a94e-6c3b9252b559" uname="c001n04" type="member"/> </nodes>
If I have a resource and I want it to only run on nodes 1 and 2, I could write a rule like this:
<rsc_location id="an_id" rsc="some_resource">
<rule id="another_id" score="-INFINITY" boolean_op="or">
<expression attribute="#uname" operation="eq" value="c001n03"/>
<expression attribute="#uname" operation="eq" value="c001n04"/>
</rule>
</rsc_location>
And if I had another resource I could do the same.
But what if there were many resources like this? And others that could only run on node 3 and 4? And what would happen if c001n05 was added and or replaced c001n01? What if there were dozens of nodes?
Clearly the result is a very hard to maintain cluster. Enter node attributes. What if instead, the nodes section looked like this:
<nodes>
<node id="f67904e0-4dfc-4db1-83a2-e930fc1d20f4" uname="c001n01" type="member">
<instance_attributes>
<attributes>
<nvpair name="cluster_group" value="front_office"/>
</attributes>
</instance_attributes>
</node>
<node id="e9bdfde9-01b0-421f-acd8-8a65a53e775f" uname="c001n02" type="member">
<instance_attributes>
<attributes>
<nvpair name="cluster_group" value="front_office"/>
</attributes>
</instance_attributes>
</node>
<node id="5d9a8c11-8684-43ea-9180-5e221530c193" uname="c001n03" type="member">
<instance_attributes>
<attributes>
<nvpair name="cluster_group" value="back_office"/>
</attributes>
</instance_attributes>
</node>
<node id="c2896699-96b8-4dbc-a94e-6c3b9252b559" uname="c001n04" type="member">
<instance_attributes>
<attributes>
<nvpair name="cluster_group" value="back_office"/>
</attributes>
</instance_attributes>
</node>
</nodes>
Then our constraints could be re-written as:
<rsc_location id="an_id" rsc="some_resource">
<rule id="another_id" score="-INFINITY" boolean_op="or">
<expression attribute="cluster_group" operation="ne" value="back_office"/>
</rule>
</rsc_location>
Then nodes could be moved between groups, added or removed without requiring updates to the rest of the configuration. One just needs to be sure the node has the right attributes.
Of course cluster_group is a completely made up name and you can use any name you like. You can even have nodes be part of multiple "groups".
<nodes>
<node id="f67904e0-4dfc-4db1-83a2-e930fc1d20f4" uname="c001n01" type="member">
<instance_attributes>
<attributes>
<nvpair name="cluster_group" value="front_office"/>
<nvpair name="shared_storage" value="connected"/>
<nvpair name="mumbo" value="jumbo"/>
<nvpair name="kernel" value="2.6"/>
<nvpair name="OS" value="linux"/>
</attributes>
</instance_attributes>
</node>
<node id="e9bdfde9-01b0-421f-acd8-8a65a53e775f" uname="c001n02" type="member">
<instance_attributes>
<attributes>
<nvpair name="cluster_group" value="front_office"/>
<nvpair name="cluster_group" value="back_office"/>
<nvpair name="OS" value="Solaris"/>
</attributes>
</instance_attributes>
</node>
<node id="5d9a8c11-8684-43ea-9180-5e221530c193" uname="c001n03" type="member">
<instance_attributes>
<attributes>
<nvpair name="cluster_group" value="back_office"/>
<nvpair name="shared_storage" value="connected"/>
<nvpair name="OS" value="linux"/>
<nvpair name="kernel" value="2.4"/>
</attributes>
</instance_attributes>
</node>
<node id="c2896699-96b8-4dbc-a94e-6c3b9252b559" uname="c001n04" type="member">
<instance_attributes>
<attributes>
<nvpair name="cluster_group" value="back_office"/>
<nvpair name="shared_storage" value="disconnected"/>
<nvpair name="kernel" value="2.4"/>
<nvpair name="OS" value="linux"/>
</attributes>
</instance_attributes>
</node>
</nodes>
Which allows you to write all sort of crazy constraints:
<rsc_location id="an_id" rsc="some_resource">
<rule id="another_id" score="INFINITY" boolean_op="and">
<expression attribute="OS" operation="eq" value="linux"/>
<expression attribute="kernel" operation="gt" value="2.4" type="version"/>
</rule>
</rsc_location>
or
<rsc_location id="an_id" rsc="some_resource">
<rule id="another_id" score="20" boolean_op="or">
<expression attribute="cluster_group" operation="eq" value="front_office"/>
<expression attribute="OS" operation="eq" value="Solaris"/>
</rule>
</rsc_location>
Indeed you could even have a process running on each machine (perhaps a ResourceAgent
) that updated any/some/all of these attributes in the CIB as required. Making this easier is likely to be a feature in a future release.