  <chapter id="ch-nodes">
    <title>Cluster Nodes</title>
    <section id="s-node-definition">
      <title>Defining a Cluster Node</title>
      <para>Each node in the cluster will have an entry in the nodes section containing its UUID, uname and type.</para>
      <example>
	<title>Example cluster node entry</title>
	<programlisting>
  <![CDATA[<node id="1186dc9a-324d-425a-966e-d757e693dc86" uname="pcmk-1" type="normal"/>]]>
	</programlisting>
      </example>
      <para>
	In normal circumstances, the admin should let the cluster populate this information automatically from the communications and membership data.
	However one can use the crm_uuid tool to read an existing UUID or define a value before the cluster starts.
      </para>
    </section>
    <section id="s-node-attributes">
      <title>Describing a Cluster Node</title>
      <para>
	Beyond the basic definition of a node, the administrator can also describe the node's attributes, such as how much RAM, disk, what OS or kernel version it has, perhaps even its physical location.
	This information can then be used by the cluster when deciding where to place resources.
	For more information on the use of node attributes, see the section on <xref linkend="ch-rules"/>.
      </para>
      <para>Node attributes can be specified ahead of time or populated later, when the cluster is running, using <command>crm_attribute</command>.</para>
      <para>Below is what the node's definition would look like if the admin ran the command:</para>
      <figure id="fig-node-attribute-set">
	<title>The result of using crm_attribute to specify which kernel pcmk-1 is running</title>
	<programlisting>
  <userinput>crm_attribute --type nodes --node-uname pcmk-1 --attr-name kernel --attr-value `uname -r` </userinput>
<![CDATA[
  <node uname="pcmk-1" type="normal" id="1186dc9a-324d-425a-966e-d757e693dc86">
   <instance_attributes id="nodes-1186dc9a-324d-425a-966e-d757e693dc86">
     <nvpair id="kernel-1186dc9a-324d-425a-966e-d757e693dc86" name="kernel" value="2.6.16.46-0.4-default"/>
   </instance_attributes>
  </node>
]]>
	</programlisting>
      </figure>
      <para>A simpler way to determine the current value of an attribute is to use crm_attribute command again:</para>
      <para><command>  crm_attribute --type nodes --node-uname pcmk-1 --attr-name kernel --get-value</command></para>
      <para/>
      <para>
	By specifying <parameter>--type</parameter> nodes the admin tells the cluster that this attribute is persistent.
	There are also transient attributes which are kept in the status section which are "forgotten" whenever the node rejoins the cluster.
	The cluster uses this area to store a record of how many times a resource has failed on that node but administrators can also read and write to this section by specifying <parameter>--type status</parameter>.
      </para>
    </section>
    <section id="s-node-add">
      <title>Adding a New Cluster Node</title>
      <section id="s-add-ais">
	<title>Corosync</title>
	<para>Adding a new is as simple as installing Corosync and Pacemaker, and copying <filename>/etc/corosync/corosync.conf</filename> and <filename>/etc/ais/authkey</filename> (if it exists) from an existing node.
You may need to modify the mcastaddr option to match the new node's IP address.</para>
	<para>If a log message containing "Invalid digest" appears from Corosync, the keys are not consistent between the machines.</para>
      </section>
      <section id="s-add-heartbeat">
	<title>Heartbeat</title>
	<para>Provided you specified autojoin any in <filename>ha.cf</filename>, adding a new is as simple as installing heartbeat and copying <filename>ha.cf</filename> and <filename>authkeys</filename> from an existing node.</para>
	<para>If not, then after setting up <filename>ha.cf</filename> and <filename>authkeys</filename>, you must use the hb_addnode command before starting the new node. </para>
      </section>
    </section>
    <section id="s-node-delete">
      <title>Removing a Cluster Node</title>
      <section id="s-del-ais">
	<title>Corosync</title>
	<para>
	  Because the messaging and membership layers are the authoritative source for cluster nodes, deleting them from the CIB is not a reliable solution.
	  First one must arrange for heartbeat to forget about the node (<replaceable>pcmk-1</replaceable> in the example below).
	</para>
	<para>On the host to be removed:</para>
	<orderedlist>
	  <listitem>
	    <para>Find and record the node's Corosync id: <command>crm_node -i</command></para>
	  </listitem>
	  <listitem>
	    <para>Stop the cluster: <command>/etc/init.d/corosync stop</command></para>
	  </listitem>
	</orderedlist>
	<para>Next, from one of the remaining active cluster nodes:</para>
	<orderedlist>
	  <listitem>
	    <para>Tell the cluster to forget about the removed host: <command>crm_node -R <replaceable>COROSYNC_ID</replaceable></command></para>
	  </listitem>
	  <listitem>
	    <para>Only now is it safe to delete the node from the CIB with:</para>
	    <para><command>cibadmin --delete --obj_type nodes --crm_xml '&lt;node uname="<replaceable>pcmk-1</replaceable>"/>'</command></para>
	    <para><command>cibadmin --delete --obj_type status --crm_xml '&lt;node_state uname="<replaceable>pcmk-1</replaceable>"/>'</command></para>
	  </listitem>
	</orderedlist>
      </section>
      <section id="s-del-heartbeat">
	<title>Heartbeat</title>
	<para>
	  Because the messaging and membership layers are the authoritative source for cluster nodes, deleting them from the CIB is not a reliable solution.
	  First one must arrange for heartbeat to forget about the node (pcmk-1 in the example below).
	  To do this, shut down heartbeat on the node and then, from one of the remaining active cluster nodes, run:
	</para>
	<para><command>hb_delnode pcmk-1</command></para>
	<para>Only then is it safe to delete the node from the CIB with:</para>
	<para><command>cibadmin --delete --obj_type nodes --crm_xml '&lt;node uname="pcmk-1"/>'</command></para>
	<para><command>cibadmin --delete --obj_type status --crm_xml '&lt;node_state uname="pcmk-1"/>'</command></para>
      </section>
    </section>
    <section id="s-node-replace">
      <title>Replacing a Cluster Node</title>
      <section id="s-replace-ais">
	<title>Corosync</title>
	<para>The five-step guide to replacing an existing cluster node:</para>
	<orderedlist>
	  <listitem><para>Make sure the old node is completely stopped</para></listitem>
	  <listitem><para>Give the new machine the same hostname and IP address as the old one</para></listitem>
	  <listitem><para>Install the cluster software :-)</para></listitem>
	  <listitem><para>Copy <filename>/etc/corosync/corosync.conf</filename> and <filename>/etc/ais/authkey</filename> (if it exists) to the new node</para></listitem>
	  <listitem><para>Start the new cluster node</para></listitem>
	</orderedlist>
	<para>If a log message containing "Invalid digest" appears from Corosync, the keys are not consistent between the machines.</para>
      </section>
      <section id="s-replace-heartbeat">
	<title>Heartbeat</title>
	<para>The seven-step guide to replacing an existing cluster node:</para>
	<orderedlist>
	  <listitem><para>Make sure the old node is completely stopped</para></listitem>
	  <listitem><para>Give the new machine the same hostname as the old one</para></listitem>
	  <listitem><para>Go to an active cluster node and look up the UUID for the old node in <filename>/var/lib/heartbeat/hostcache</filename></para></listitem>
	  <listitem><para>Install the cluster software</para></listitem>
	  <listitem><para>Copy ha.cf and authkeys to the new node</para></listitem>
	  <listitem><para>On the new node, populate it's UUID using crm_uuid -w and the UUID from step 2</para></listitem>
	  <listitem><para>Start the new cluster node</para></listitem>
	</orderedlist>
      </section>
    </section>
  </chapter>
