  <appendix id="ap-ocf">
    <title>More About OCF Resource Agents</title>
    <section id="s-ocf-location">
      <title>Location of Custom Scripts</title>
      <para>OCF Resource Agents are found in <filename>/usr/lib/ocf/resource.d/<replaceable>provider</replaceable></filename>.</para>
      <para>
	When creating your own agents, you are encouraged to create a new directory under <filename>/usr/lib/ocf/resource.d/</filename> so that they are not confused with (or overwritten by) the agents shipped with Heartbeat.
	So, for example, if you chose the provider name of bigCorp and wanted a new resource named bigApp, you would create a script called <filename>/usr/lib/ocf/resource.d/bigCorp/bigApp</filename> and define a resource:
      </para>
      <programlisting>&lt;primitive id="custom-app" class="ocf" provider="bigCorp" type="bigApp"/></programlisting>
    </section>
    <section id="s-ocf-actions">
      <title>Actions</title>
      <para>All OCF Resource Agents are required to implement the following actions</para>
      <table frame="all">
	<title>Required Actions for OCF Agents</title>
	<tgroup cols="3">
          <thead>
            <row>
              <entry>Action</entry>
              <entry>Description</entry>
              <entry>Instructions</entry>
            </row>
          </thead>
	  <tbody>
	    <row>
              <entry>start</entry>
              <entry>Start the resource</entry>
              <entry>Return 0 on success and an appropriate error code otherwise. Must not report success until the resource is fully active.</entry>
            </row>
            <row>
              <entry>stop</entry>
              <entry>Stop the resource</entry>
              <entry>Return 0 on success and an appropriate error code otherwise. Must not report success until the resource is fully stopped.</entry>
            </row>
            <row>
              <entry>monitor</entry>
              <entry>Check the resource's state </entry>
              <entry>
		<para>Exit 0 if the resource is running, 7 if it is stopped and anything else if it is failed. </para>
		<para>NOTE: The monitor script should test the state of the resource on the local machine only.</para>
              </entry>
            </row>
            <row>
              <entry>meta-data</entry>
              <entry>Describe the resource</entry>
              <entry>
		<para>Provide information about this resource as an XML snippet. Exit with 0.</para>
		<para>NOTE: This is <emphasis>not</emphasis> performed as root.</para>
              </entry>
            </row>
            <row>
              <entry>validate-all</entry>
              <entry>Verify the supplied parameters are correct</entry>
              <entry>Exit with 0 if parameters are valid, 2 if not valid, 6 if resource is not configured.</entry>
        </row></tbody></tgroup>
      </table>
      <para>Additional requirements (not part of the OCF specs) are placed on agents that will be used for advanced concepts like <link linkend="s-resource-clone">clones</link> and <link linkend="s-resource-multistate">multi-state</link> resources.</para>
      <table frame="all">
	<title>Optional Actions for OCF Agents</title>
	<tgroup cols="3">
          <thead>
            <row>
              <entry>Action</entry>
              <entry>Description</entry>
              <entry>Instructions</entry>
            </row>
          </thead><tbody><row>
              <entry>promote</entry>
              <entry>Promote the local instance of a multi-state resource to the master/primary state</entry>
              <entry>Return 0 on success</entry>
            </row>
            <row>
              <entry>demote</entry>
              <entry>Demote the local instance of a multi-state resource to the slave/secondary state</entry>
              <entry>Return 0 on success</entry>
            </row>
            <row>
              <entry>notify</entry>
              <entry>Used by the cluster to send the agent pre and post notification events telling the resource what is or did just take place</entry>
              <entry>Must not fail. Must exit 0</entry>
        </row></tbody></tgroup>
      </table>
      <para>Some actions specified in the OCF specs are not currently used by the cluster</para>
      <itemizedlist>
	<listitem><para>reload - reload the configuration of the resource instance without disrupting the service </para></listitem>
	<listitem><para>recover - a variant of the start action, this should try to recover a resource locally.</para></listitem>
      </itemizedlist>
      <para/>
      <para>Remember to use ocf-tester to verify that your new agent complies with the OCF standard properly.</para>
    </section>
    <section id="s-ocf-return-codes">
      <title>How Does the Cluster Interpret the OCF Return Codes?</title>
      <para>The first thing the cluster does is check the return code against the expected result.
If the result does not match the expected value, then the operation is considered to have failed and recovery action is initiated.
</para>
      <para>There are three types of failure recovery:</para>
      <table frame="all">
	<title>Types of recovery performed by the cluster</title>
	<tgroup cols="3">
          <thead>
            <row>
              <entry>Recovery Type</entry>
              <entry>Description</entry>
              <entry>Action Taken by the Cluster</entry>
            </row>
          </thead><tbody><row>
              <entry>soft</entry>
              <entry>A transient error occurred</entry>
              <entry>Restart the resource or move it to a new location</entry>
            </row>
            <row>
              <entry>hard</entry>
              <entry>A non-transient error that may be specific to the current node occurred</entry>
              <entry>Move the resource elsewhere and prevent it from being retried on the current node</entry>
            </row>
            <row>
              <entry>fatal</entry>
              <entry>A non-transient error that will be common to all cluster nodes (I.e. a bad configuration was specified)</entry>
              <entry>Stop the resource and prevent it from being started on any cluster node</entry>
        </row></tbody></tgroup>
      </table>
      <para>Assuming an action is considered to have failed, the following table outlines the different OCF return codes and the type of recovery the cluster will initiate when it is received. </para>
      <table frame="all">
	<title>OCF Return Codes and How They are Handled</title>
	<tgroup cols="4">
          <thead>
            <row>
              <entry>OCF Return Code</entry>
              <entry>OCF Alias</entry>
              <entry>Description</entry>
              <entry>Recovery Type</entry>
            </row>
          </thead><tbody><row>
              <entry>0</entry>
              <entry>OCF_SUCCESS</entry>
              <entry>Success. The command complete successfully. This is the expected result for all start, stop, promote and demote commands.</entry>
              <entry>soft</entry>
            </row>
            <row>
              <entry>1</entry>
              <entry>OCF_ERR_GENERIC</entry>
              <entry>Generic "there was a problem" error code.</entry>
              <entry>soft</entry>
            </row>
            <row>
              <entry>2</entry>
              <entry>OCF_ERR_ARGS</entry>
              <entry>The resource's configuration is not valid on this machine. Eg. Refers to a location/tool not found on the node. </entry>
              <entry>hard</entry>
            </row>
            <row>
              <entry>3</entry>
              <entry>OCF_ERR_UNIMPLEMENTED</entry>
              <entry>The requested action is not implemented.</entry>
              <entry>hard</entry>
            </row>
            <row>
              <entry>4</entry>
              <entry>OCF_ERR_PERM</entry>
              <entry>The resource agent does not have sufficient privileges to complete the task.</entry>
              <entry>hard</entry>
            </row>
            <row>
              <entry>5</entry>
              <entry>OCF_ERR_INSTALLED</entry>
              <entry>The tools required by the resource are not installed on this machine.</entry>
              <entry>hard</entry>
            </row>
            <row>
              <entry>6</entry>
              <entry>OCF_ERR_CONFIGURED</entry>
              <entry>The resource's configuration is invalid. Eg. A required parameters are missing.</entry>
              <entry>fatal</entry>
            </row>
            <row>
              <entry>7</entry>
              <entry>OCF_NOT_RUNNING</entry>
              <entry>The resource is safely stopped. The cluster will not attempt to stop a resource that returns this for any action.</entry>
              <entry>N/A</entry>
            </row>
            <row>
              <entry>8</entry>
              <entry>OCF_RUNNING_MASTER</entry>
              <entry>The resource is running in Master mode.</entry>
              <entry>soft</entry>
            </row>
            <row>
              <entry>9</entry>
              <entry>OCF_FAILED_MASTER</entry>
              <entry>The resource is in Master mode but has failed. The resource will be demoted, stopped and then started (and possibly promoted) again.</entry>
              <entry>soft</entry>
            </row>
            <row>
              <entry>other</entry>
              <entry>NA</entry>
              <entry>Custom error code.</entry>
              <entry>soft</entry>
        </row></tbody></tgroup>
      </table>
      <para>Although counter intuitive, even actions that return 0 (aka. <envar>OCF_SUCCESS</envar>) can be considered to have failed.
This can happen when a resource that is expected to be in the Master state is found running as a Slave, or when a resource is found active on multiple machines..</para><section><title>Exceptions</title>
	<itemizedlist>
	  <listitem><para>Non-recurring monitor actions (probes) that find a resource active (or in Master mode) will not result in recovery action unless it is also found active elsewhere</para></listitem>
	  <listitem><para>The recovery action taken when a resource is found active more than once is determined by the <literal>multiple-active</literal> property of the resource</para></listitem>
	  <listitem><para>Recurring actions that return <envar>OCF_ERR_UNIMPLEMENTED</envar> do not cause any type of recovery</para></listitem>
	</itemizedlist>
    </section></section>
  </appendix>
