Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3155770
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
55 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/README b/README
index e69de29bb..2d46d3fc5 100644
--- a/README
+++ b/README
@@ -0,0 +1,3 @@
+Repository moved! Please use
+ https://github.com/ClusterLabs/resource-agents
+ git://github.com/ClusterLabs/resource-agents.git
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 0ebf46f05..6482251ed 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,155 +1,155 @@
#
# doc: Linux-HA resource agents
#
# Copyright (C) 2009 Florian Haas
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = $(doc_DATA) $(REFENTRY_STYLESHEET) \
mkappendix.sh ralist.sh
CLEANFILES = $(man_MANS) $(xmlfiles) metadata-*.xml
doc_DATA = README.webapps
STYLESHEET_PREFIX ?= http://docbook.sourceforge.net/release/xsl/current
MANPAGES_STYLESHEET ?= $(STYLESHEET_PREFIX)/manpages/docbook.xsl
HTML_STYLESHEET ?= $(STYLESHEET_PREFIX)/xhtml/docbook.xsl
FO_STYLESHEET ?= $(STYLESHEET_PREFIX)/fo/docbook.xsl
REFENTRY_STYLESHEET ?= ra2refentry.xsl
XSLTPROC_OPTIONS ?= --xinclude
XSLTPROC_MANPAGES_OPTIONS ?= $(XSLTPROC_OPTIONS)
XSLTPROC_HTML_OPTIONS ?= $(XSLTPROC_OPTIONS)
XSLTPROC_FO_OPTIONS ?= $(XSLTPROC_OPTIONS)
radir = $(top_srcdir)/heartbeat
# OCF_ROOT=. is necessary due to a sanity check in ocf-shellfuncs
# (which tests whether $OCF_ROOT points to a directory
metadata-%.xml: $(radir)/%
OCF_ROOT=. OCF_FUNCTIONS_DIR=$(radir) $< meta-data > $@
metadata-IPv6addr.xml: ../heartbeat/IPv6addr
OCF_ROOT=. OCF_FUNCTIONS_DIR=$(radir) $< meta-data > $@
# Please note: we can't name the man pages
# ocf:heartbeat:<name>. Believe me, I've tried. It looks like it
# works, but then it doesn't. While make can deal correctly with
# colons in target names (when properly escaped), it royally messes up
# when it is deals with _dependencies_ that contain colons. See Bug
# 12126 on savannah.gnu.org. But, maybe it gets fixed soon, it was
# first reported in 1995 and added to Savannah in in 2005...
if BUILD_DOC
man_MANS = ocf_heartbeat_AoEtarget.7 \
ocf_heartbeat_AudibleAlarm.7 \
ocf_heartbeat_ClusterMon.7 \
ocf_heartbeat_CTDB.7 \
ocf_heartbeat_Delay.7 \
ocf_heartbeat_Dummy.7 \
ocf_heartbeat_EvmsSCC.7 \
ocf_heartbeat_Evmsd.7 \
ocf_heartbeat_Filesystem.7 \
ocf_heartbeat_ICP.7 \
ocf_heartbeat_IPaddr.7 \
ocf_heartbeat_IPaddr2.7 \
ocf_heartbeat_IPsrcaddr.7 \
ocf_heartbeat_LVM.7 \
ocf_heartbeat_LinuxSCSI.7 \
ocf_heartbeat_MailTo.7 \
ocf_heartbeat_ManageRAID.7 \
ocf_heartbeat_ManageVE.7 \
ocf_heartbeat_Pure-FTPd.7 \
ocf_heartbeat_Raid1.7 \
ocf_heartbeat_Route.7 \
ocf_heartbeat_SAPDatabase.7 \
ocf_heartbeat_SAPInstance.7 \
ocf_heartbeat_SendArp.7 \
ocf_heartbeat_ServeRAID.7 \
ocf_heartbeat_SphinxSearchDaemon.7 \
ocf_heartbeat_Squid.7 \
ocf_heartbeat_Stateful.7 \
ocf_heartbeat_SysInfo.7 \
ocf_heartbeat_VIPArip.7 \
ocf_heartbeat_VirtualDomain.7 \
ocf_heartbeat_WAS.7 \
ocf_heartbeat_WAS6.7 \
ocf_heartbeat_WinPopup.7 \
ocf_heartbeat_Xen.7 \
ocf_heartbeat_Xinetd.7 \
ocf_heartbeat_anything.7 \
ocf_heartbeat_apache.7 \
ocf_heartbeat_conntrackd.7 \
ocf_heartbeat_db2.7 \
ocf_heartbeat_drbd.7 \
ocf_heartbeat_eDir88.7 \
ocf_heartbeat_exportfs.7 \
ocf_heartbeat_fio.7 \
ocf_heartbeat_iSCSILogicalUnit.7 \
ocf_heartbeat_iSCSITarget.7 \
ocf_heartbeat_ids.7 \
ocf_heartbeat_iscsi.7 \
ocf_heartbeat_jboss.7 \
ocf_heartbeat_mysql.7 \
ocf_heartbeat_mysql-proxy.7 \
ocf_heartbeat_nfsserver.7 \
ocf_heartbeat_nginx.7 \
ocf_heartbeat_oracle.7 \
ocf_heartbeat_oralsnr.7 \
ocf_heartbeat_pgsql.7 \
ocf_heartbeat_pingd.7 \
ocf_heartbeat_portblock.7 \
ocf_heartbeat_postfix.7 \
ocf_heartbeat_proftpd.7 \
ocf_heartbeat_rsyncd.7 \
ocf_heartbeat_scsi2reservation.7 \
ocf_heartbeat_sfex.7 \
ocf_heartbeat_syslog-ng.7 \
ocf_heartbeat_tomcat.7 \
ocf_heartbeat_vmware.7
if USE_IPV6ADDR
man_MANS += ocf_heartbeat_IPv6addr.7
endif
xmlfiles = $(man_MANS:.7=.xml)
%.1 %.5 %.7 %.8: %.xml
$(XSLTPROC) \
$(XSLTPROC_MANPAGES_OPTIONS) \
$(MANPAGES_STYLESHEET) $<
ocf_heartbeat_%.xml: metadata-%.xml $(srcdir)/$(REFENTRY_STYLESHEET)
$(XSLTPROC) --novalid \
--stringparam package $(PACKAGE_NAME) \
--stringparam version $(VERSION) \
--output $@ \
$(srcdir)/$(REFENTRY_STYLESHEET) $<
ocf_resource_agents.xml: $(xmlfiles) mkappendix.sh
./mkappendix.sh $(xmlfiles) > $@
%.html: %.xml
$(XSLTPROC) \
$(XSLTPROC_HTML_OPTIONS) \
--output $@ \
$(HTML_STYLESHEET) $<
-xml: $(xmlfiles)
+xml: ocf_resource_agents.xml
endif
diff --git a/doc/ra2refentry.xsl b/doc/ra2refentry.xsl
index 5f4ddd7c6..063ab2bb8 100644
--- a/doc/ra2refentry.xsl
+++ b/doc/ra2refentry.xsl
@@ -1,467 +1,470 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes"
doctype-public="-//OASIS//DTD DocBook XML V4.4//EN"
doctype-system="http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"/>
<!--<xsl:strip-space elements="longdesc shortdesc"/>-->
<!-- Package name. -->
<xsl:param name="package">resource-agents</xsl:param>
<!-- Package version number. Must be passed in. -->
<xsl:param name="version"/>
<!-- RA class -->
<xsl:param name="class">ocf</xsl:param>
<!-- RA provider -->
<xsl:param name="provider">heartbeat</xsl:param>
<!-- Man volume number -->
<xsl:param name="manvolum">7</xsl:param>
<!-- -->
<xsl:param name="variable.prefix"/>
<!-- Separator between different action/@name -->
<xsl:param name="separator"> | </xsl:param>
<xsl:variable name="manpagetitleprefix"><xsl:value-of select="$class"/>_<xsl:value-of select="$provider"/>_</xsl:variable>
<xsl:template match="/">
<refentry>
<xsl:apply-templates mode="root"/>
</refentry>
</xsl:template>
<xsl:template match="resource-agent" mode="root">
<xsl:param name="this" select="self::resource-agent"/>
<xsl:attribute name="id">
<xsl:text>re-ra-</xsl:text>
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:apply-templates select="$this" mode="refentryinfo"/>
<xsl:apply-templates select="$this" mode="refmeta"/>
<xsl:apply-templates select="$this" mode="refnamediv"/>
<xsl:apply-templates select="$this" mode="synopsis"/>
<xsl:apply-templates select="$this" mode="description"/>
<xsl:apply-templates select="$this" mode="parameters"/>
<xsl:apply-templates select="$this" mode="actions"/>
<xsl:apply-templates select="$this" mode="example"/>
<xsl:apply-templates select="$this" mode="seealso"/>
</xsl:template>
<!-- Empty Templates -->
<xsl:template match="node()" mode="root"/>
<xsl:template match="*" mode="refmeta"/>
<xsl:template match="*" mode="refnamediv"/>
<xsl:template match="*" mode="synopsis"/>
<xsl:template match="*" mode="description"/>
<xsl:template match="*" mode="parameters"/>
<!-- Mode refentryinfo -->
<xsl:template match="resource-agent" mode="refentryinfo">
<refentryinfo>
<productname><xsl:value-of select="$package"/></productname>
<productnumber><xsl:value-of select="$version"/></productnumber>
<corpauthor>Linux-HA contributors (see the resource agent source for information about individual authors)</corpauthor>
</refentryinfo>
</xsl:template>
<!-- Mode refmeta -->
<xsl:template match="resource-agent" mode="refmeta">
<refmeta>
<refentrytitle><xsl:value-of select="$manpagetitleprefix"/><xsl:value-of select="@name"/></refentrytitle>
<manvolnum><xsl:value-of select="$manvolum"/></manvolnum>
<refmiscinfo class="manual">OCF resource agents</refmiscinfo>
</refmeta>
</xsl:template>
<!-- Mode refnamediv -->
<xsl:template match="resource-agent" mode="refnamediv">
<refnamediv>
<refname><xsl:value-of select="$manpagetitleprefix"/><xsl:value-of select="@name"/></refname>
<refpurpose><xsl:apply-templates select="shortdesc"/></refpurpose>
</refnamediv>
</xsl:template>
<!-- Mode synopsis -->
<xsl:template match="resource-agent" mode="synopsis">
<refsynopsisdiv>
<cmdsynopsis sepchar=" ">
<command moreinfo="none">
<xsl:value-of select="@name"/>
</command>
<xsl:apply-templates select="actions" mode="synopsis"/>
</cmdsynopsis>
</refsynopsisdiv>
</xsl:template>
<xsl:template match="actions" mode="synopsis">
<group choice="opt" rep="norepeat">
<xsl:apply-templates select="action[@name = 'start'][1]" mode="synopsis"/>
<xsl:apply-templates select="action[@name = 'stop'][1]" mode="synopsis"/>
<xsl:apply-templates select="action[@name = 'status'][1]" mode="synopsis"/>
<xsl:apply-templates select="action[@name = 'monitor'][1]" mode="synopsis"/>
<xsl:apply-templates select="action[@name = 'migrate_to'][1]" mode="synopsis"/>
<xsl:apply-templates select="action[@name = 'migrate_from'][1]" mode="synopsis"/>
<xsl:apply-templates select="action[@name = 'promote'][1]" mode="synopsis"/>
<xsl:apply-templates select="action[@name = 'demote'][1]" mode="synopsis"/>
<xsl:apply-templates select="action[@name = 'meta-data'][1]" mode="synopsis"/>
<xsl:apply-templates select="action[@name = 'validate-all'][1]" mode="synopsis"/>
</group>
</xsl:template>
<xsl:template match="action" mode="synopsis">
<arg choice="plain" rep="norepeat">
<xsl:value-of select="@name"/>
</arg>
</xsl:template>
<!-- Mode Description -->
<!-- break string into <para> elements on linefeeds -->
<xsl:template name="break_into_para">
<xsl:param name="string" />
<xsl:variable name="lf" select="'

'" />
<xsl:choose>
<xsl:when test="contains($string, $lf)">
<xsl:variable name="first" select="substring-before($string, $lf)" />
- <!-- skip empty lines as <para> spacing generates one -->
-
- <xsl:if test="string-length($first) > 0">
- <para>
- <xsl:value-of select="$first"/>
- </para>
- </xsl:if>
+ <para>
+ <xsl:value-of select="'
'" />
+ <xsl:value-of select="$first"/>
+ <xsl:value-of select="'
'" />
+ </para>
+ <xsl:value-of select="'
'" />
<!-- recursively call an remaining string -->
<xsl:call-template name="break_into_para">
<xsl:with-param name="string"
select="substring-after($string, $lf)" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
- <xsl:value-of select="$string"/>
+ <para>
+ <xsl:value-of select="$string"/>
+ </para>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="resource-agent" mode="description">
<refsection>
<title>Description</title>
<xsl:apply-templates mode="description"/>
</refsection>
</xsl:template>
- <xsl:template match="longdesc" mode="description">
- <xsl:call-template name="break_into_para">
- <xsl:with-param name="string" select="." />
- </xsl:call-template>
- <!-- xsl:apply-templates mode="description"/ -->
- </xsl:template>
+ <xsl:template match="text()" mode="longdesc">
+ <xsl:call-template name="break_into_para">
+ <xsl:with-param name="string" select="." />
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template match="longdesc" mode="description">
+ <xsl:apply-templates mode="longdesc"/>
+ </xsl:template>
<!-- Mode Parameters -->
<xsl:template match="resource-agent" mode="parameters">
<refsection>
<title>Supported Parameters</title>
<xsl:choose>
<xsl:when test="parameters">
<xsl:apply-templates mode="parameters"/>
</xsl:when>
<xsl:otherwise>
<para>
<xsl:text>This resource agent does not support any parameters.</xsl:text>
</para>
</xsl:otherwise>
</xsl:choose>
</refsection>
</xsl:template>
<xsl:template match="resource-agent/shortdesc|resource-agent/longdesc" mode="parameters"/>
<xsl:template match="parameters" mode="parameters">
<variablelist>
<xsl:apply-templates mode="parameters"/>
</variablelist>
</xsl:template>
<xsl:template match="parameter" mode="parameters">
<varlistentry>
<term>
<option><xsl:value-of select="concat($variable.prefix, @name)"/></option>
</term>
<listitem>
<para>
<xsl:apply-templates select="longdesc" mode="parameters"/>
<xsl:apply-templates select="content" mode="parameters"/>
</para>
</listitem>
</varlistentry>
</xsl:template>
<xsl:template match="longdesc" mode="parameters">
- <xsl:apply-templates select="text()" mode="parameters"/>
+ <xsl:apply-templates select="node()" mode="longdesc"/>
</xsl:template>
<xsl:template match="shortdesc" mode="parameters">
<xsl:apply-templates select="text()" mode="parameters"/>
</xsl:template>
<xsl:template match="content" mode="parameters">
<xsl:if test="@type != '' or @default != ''">
<xsl:text> (</xsl:text>
<xsl:choose>
<xsl:when test="../@required = 1">
<xsl:text>required</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>optional</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:text>, </xsl:text>
<xsl:if test="@parameter != ''">
<xsl:value-of select="@type"/>
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:if test="@type != ''">
<xsl:value-of select="@type"/>
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:choose>
<xsl:when test="@default != ''">
<xsl:text>default </xsl:text>
<code>
<xsl:value-of select="@default"/>
</code>
</xsl:when>
<xsl:otherwise>
<xsl:text>no default</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:text>)</xsl:text>
</xsl:if>
</xsl:template>
<!-- Mode Actions -->
<xsl:template match="resource-agent" mode="actions">
<refsection>
<title>Supported Actions</title>
<xsl:choose>
<xsl:when test="actions">
<xsl:apply-templates select="actions" mode="actions"/>
</xsl:when>
<xsl:otherwise>
<!-- This should actually never happen. Every RA must
advertise the actions it supports. -->
<para>
<xsl:text>This resource agent does not advertise any supported actions.</xsl:text>
</para>
</xsl:otherwise>
</xsl:choose>
</refsection>
</xsl:template>
<xsl:template match="actions" mode="actions">
<para>This resource agent supports the following actions (operations):</para>
<variablelist>
<xsl:apply-templates select="action" mode="actions"/>
</variablelist>
</xsl:template>
<xsl:template match="action" mode="actions">
<varlistentry>
<term>
<option>
<xsl:value-of select="@name"/>
<xsl:if test="@role != ''">
<xsl:text> (</xsl:text>
<xsl:value-of select="@role"/>
<xsl:text> role)</xsl:text>
</xsl:if>
</option>
</term>
<listitem>
<para>
<xsl:choose>
<xsl:when test="@name = 'start'">
<xsl:text>Starts the resource.</xsl:text>
</xsl:when>
<xsl:when test="@name = 'stop'">
<xsl:text>Stops the resource.</xsl:text>
</xsl:when>
<xsl:when test="@name = 'status'">
<xsl:text>Performs a status check.</xsl:text>
</xsl:when>
<xsl:when test="@name = 'monitor'">
<xsl:text>Performs a detailed status check.</xsl:text>
</xsl:when>
<xsl:when test="@name = 'promote'">
<xsl:text>Promotes the resource to the Master role.</xsl:text>
</xsl:when>
<xsl:when test="@name = 'demote'">
<xsl:text>Demotes the resource to the Slave role.</xsl:text>
</xsl:when>
<xsl:when test="@name = 'migrate_from'">
<xsl:text>Executes steps necessary for migrating the
resource </xsl:text>
<emphasis>away from</emphasis>
<xsl:text> the node.</xsl:text>
</xsl:when>
<xsl:when test="@name = 'migrate_to'">
<xsl:text>Executes steps necessary for migrating the
resource </xsl:text>
<emphasis>to</emphasis>
<xsl:text> the node.</xsl:text>
</xsl:when>
<xsl:when test="@name = 'validate-all'">
<xsl:text>Performs a validation of the resource configuration.</xsl:text>
</xsl:when>
<xsl:when test="@name = 'meta-data'">
<xsl:text>Retrieves resource agent metadata (internal use only).</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:if test="@timeout != ''">
<xsl:text> Suggested minimum timeout: </xsl:text>
<xsl:value-of select="@timeout"/>
<xsl:text>.</xsl:text>
</xsl:if>
<xsl:if test="@interval != ''">
<xsl:text> Suggested interval: </xsl:text>
<xsl:value-of select="@interval"/>
<xsl:text>.</xsl:text>
</xsl:if>
</para>
</listitem>
</varlistentry>
</xsl:template>
<!-- Mode Example -->
<xsl:template match="resource-agent" mode="example">
<refsection>
<title>Example</title>
<para>
<xsl:text>The following is an example configuration for a </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text> resource using the </xsl:text>
<citerefentry><refentrytitle>crm</refentrytitle><manvolnum>8</manvolnum></citerefentry>
<xsl:text> shell:</xsl:text>
</para>
<programlisting>
<xsl:text>primitive example_</xsl:text>
<xsl:value-of select="@name"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$class"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="$provider"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="@name"/>
<xsl:text> \
</xsl:text>
<xsl:if test="parameters/parameter[@required = 1]">
<xsl:text> params \
</xsl:text>
<xsl:apply-templates select="parameters" mode="example"/>
</xsl:if>
<!-- Insert a suggested allow-migrate meta attribute if the
resource agent supports migration -->
<xsl:if test="actions/action/@name = 'migrate_from' or actions/action/@name = 'migrate_to'">
<xsl:text>
meta allow-migrate="true" \</xsl:text>
</xsl:if>
<xsl:apply-templates select="actions" mode="example"/>
</programlisting>
</refsection>
</xsl:template>
<xsl:template match="parameters" mode="example">
<xsl:apply-templates select="parameter[@required = 1]" mode="example"/>
</xsl:template>
<xsl:template match="parameter" mode="example">
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>=</xsl:text>
<xsl:apply-templates select="content" mode="example"/>
<xsl:text> \</xsl:text>
<xsl:if test="following-sibling::parameter/@required = 1">
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="content" mode="example">
<xsl:choose>
<xsl:when test="@default != ''">
<xsl:text>"</xsl:text>
<xsl:value-of select="@default"/>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:otherwise>
<replaceable><xsl:value-of select="@type"/></replaceable>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="actions" mode="example">
<!-- In the CRM shell example, show only the monitor action -->
<xsl:apply-templates select="action[@name = 'monitor']" mode="example"/>
</xsl:template>
<xsl:template match="action" mode="example">
<xsl:text>
op </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="@*" mode="example"/>
</xsl:template>
<xsl:template match="action/@*" mode="example">
<xsl:choose>
<xsl:when test="name() = 'name'"><!-- suppress --></xsl:when>
<xsl:otherwise>
<xsl:value-of select="name()"/>
<xsl:text>="</xsl:text>
<xsl:value-of select="current()"/>
<xsl:text>" </xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="following-sibling::*">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="longdesc" mode="example"/>
<xsl:template match="shortdesc" mode="example"/>
<xsl:template match="resource-agent" mode="seealso">
<refsection>
<title>See also</title>
<para>
<ulink>
<xsl:attribute name="url">
<xsl:text>http://www.linux-ha.org/wiki/</xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>_(resource_agent)</xsl:text>
</xsl:attribute>
</ulink>
</para>
</refsection>
</xsl:template>
</xsl:stylesheet>
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
index 5854b2c1a..d4c9ef145 100755
--- a/heartbeat/VirtualDomain
+++ b/heartbeat/VirtualDomain
@@ -1,461 +1,504 @@
#!/bin/sh
#
# Support: linux-ha@lists.linux-ha.org
# License: GNU General Public License (GPL)
#
# Resource Agent for domains managed by the libvirt API.
# Requires a running libvirt daemon (libvirtd).
#
# (c) 2008-2010 Florian Haas, Dejan Muhamedagic,
# and Linux-HA contributors
#
# usage: $0 {start|stop|status|monitor|migrate_to|migrate_from|meta-data|validate-all}
#
#######################################################################
# Initialization:
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
# Defaults
OCF_RESKEY_force_stop_default=0
OCF_RESKEY_hypervisor_default="$(virsh --quiet uri)"
: ${OCF_RESKEY_force_stop=${OCF_RESKEY_force_stop_default}}
: ${OCF_RESKEY_hypervisor=${OCF_RESKEY_hypervisor_default}}
#######################################################################
## I'd very much suggest to make this RA use bash,
## and then use magic $SECONDS.
## But for now:
NOW=$(date +%s)
usage() {
echo "usage: $0 {start|stop|status|monitor|migrate_to|migrate_from|meta-data|validate-all}"
}
meta_data() {
cat <<EOF
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="VirtualDomain">
-<version>1.0</version>
+<version>1.1</version>
<longdesc lang="en">
Resource agent for a virtual domain (a.k.a. domU, virtual machine,
virtual environment etc., depending on context) managed by libvirtd.
</longdesc>
<shortdesc lang="en">Manages virtual domains through the libvirt virtualization framework</shortdesc>
<parameters>
<parameter name="config" unique="1" required="1">
<longdesc lang="en">
Absolute path to the libvirt configuration file,
for this virtual domain.
</longdesc>
<shortdesc lang="en">Virtual domain configuration file</shortdesc>
<content type="string" default="" />
</parameter>
<parameter name="hypervisor" unique="0" required="0">
<longdesc lang="en">
Hypervisor URI to connect to. See the libvirt documentation for
details on supported URI formats. The default is system dependent.
</longdesc>
<shortdesc lang="en">Hypervisor URI</shortdesc>
<content type="string" default="${OCF_RESKEY_hypervisor_default}"/>
</parameter>
<parameter name="force_stop" unique="0" required="0">
<longdesc lang="en">
Always forcefully shut down ("destroy") the domain on stop. The default
behavior is to resort to a forceful shutdown only after a graceful
shutdown attempt has failed. You should only set this to true if
your virtual domain (or your virtualization backend) does not support
graceful shutdown.
</longdesc>
<shortdesc lang="en">Always force shutdown on stop</shortdesc>
<content type="boolean" default="${OCF_RESKEY_force_stop_default}" />
</parameter>
<parameter name="migration_transport" unique="0" required="0">
<longdesc lang="en">
Transport used to connect to the remote hypervisor while
migrating. Please refer to the libvirt documentation for details on
transports available. If this parameter is omitted, the resource will
use libvirt's default transport to connect to the remote hypervisor.
</longdesc>
<shortdesc lang="en">Remote hypervisor transport</shortdesc>
<content type="string" default="" />
</parameter>
+<parameter name="migration_network_suffix" unique="0" required="0">
+<longdesc lang="en">
+Use a dedicated migration network. The migration URI is composed by
+adding this parameters value to the end of the node name. If the node
+name happens to be an FQDN (as opposed to an unqualified host name),
+insert the suffix immediately prior to the first period (.) in the FQDN.
+At the moment Qemu/KVM and Xen migration via a dedicated network is supported.
+
+Note: Be sure this composed host name is locally resolveable and the
+associated IP is reachable through the favored network.
+</longdesc>
+<shortdesc lang="en">Migration network host name suffix</shortdesc>
+<content type="string" default="" />
+</parameter>
+
<parameter name="monitor_scripts" unique="0" required="0">
<longdesc lang="en">
To additionally monitor services within the virtual domain, add this
parameter with a list of scripts to monitor.
Note: when monitor scripts are used, the start and migrate_from operations
will complete only when all monitor scripts have completed successfully.
Be sure to set the timeout of these operations to accommodate this delay.
</longdesc>
<shortdesc lang="en">space-separated list of monitor scripts</shortdesc>
<content type="string" default="" />
</parameter>
</parameters>
<actions>
<action name="start" timeout="90" />
<action name="stop" timeout="90" />
<action name="status" depth="0" timeout="30" interval="10" />
<action name="monitor" depth="0" timeout="30" interval="10" />
<action name="migrate_from" timeout="60" />
<action name="migrate_to" timeout="120" />
<action name="meta-data" timeout="5" />
<action name="validate-all" timeout="5" />
</actions>
</resource-agent>
EOF
}
# Set options to be passed to virsh:
VIRSH_OPTIONS="--connect=${OCF_RESKEY_hypervisor} --quiet"
# A state file where we record the domain name:
STATEFILE="${HA_RSCTMP}/VirtualDomain-${OCF_RESOURCE_INSTANCE}.state"
VirtualDomain_Define() {
local virsh_output
local domain_name
# Note: passing in the domain name from outside the script is
# intended for testing and debugging purposes only. Don't do this
# in production, instead let the script figure out the domain name
# from the config file. You have been warned.
if [ -z "$DOMAIN_NAME" ]; then
# Spin until we have a domain name
while true; do
virsh_output=`virsh ${VIRSH_OPTIONS} define ${OCF_RESKEY_config}`
domain_name=`echo "$virsh_output" | sed -e 's/Domain \(.*\) defined from .*$/\1/'`
if [ -n $domain_name ]; then
break;
fi
ocf_log debug "Domain not defined yet, probably unable to connect to hypervisor. Retrying."
sleep 1
done
echo "$domain_name" > $STATEFILE
ocf_log info "Domain name \"$domain_name\" saved to $STATEFILE."
else
ocf_log warn "Domain name ${DOMAIN_NAME} already defined, overriding configuration file ${OCF_RESKEY_config}. You should do this for testing only."
fi
}
VirtualDomain_Cleanup_Statefile() {
rm -f $STATEFILE || ocf_log warn "Failed to remove $STATEFILE during $__OCF_ACTION."
}
VirtualDomain_Status() {
local try=0
rc=$OCF_ERR_GENERIC
status="no state"
while [ "$status" = "no state" ]; do
try=$(($try + 1 ))
status="`virsh $VIRSH_OPTIONS domstate $DOMAIN_NAME`"
case "$status" in
"shut off")
# shut off: domain is defined, but not started
ocf_log debug "Virtual domain $DOMAIN_NAME is currently $status."
rc=$OCF_NOT_RUNNING
;;
running|paused|idle|blocked)
# running: domain is currently actively consuming cycles
# paused: domain is paused (suspended)
# idle: domain is running but idle
# blocked: synonym for idle used by legacy Xen versions
ocf_log debug "Virtual domain $DOMAIN_NAME is currently $status."
rc=$OCF_SUCCESS
;;
""|"no state")
# Empty string may be returned when virsh does not
# receive a reply from libvirtd.
# "no state" may occur when the domain is currently
# being migrated (on the migration target only), or
# whenever virsh can't reliably obtain the domain
# state.
status="no state"
if [ "$__OCF_ACTION" = "stop" ] && [ $try -ge 3 ]; then
# During the stop operation, we want to bail out
# quickly, so as to be able to force-stop (destroy)
# the domain if necessary.
ocf_log error "Virtual domain $DOMAIN_NAME has no state during stop operation, bailing out."
return $OCF_ERR_GENERIC;
else
# During all other actions, we just wait and try
# again, relying on the CRM/LRM to time us out if
# this takes too long.
ocf_log info "Virtual domain $DOMAIN_NAME currently has no state, retrying."
sleep 1
fi
;;
*)
# any other output is unexpected.
ocf_log error "Virtual domain $DOMAIN_NAME has unknown status \"$status\"!"
;;
esac
done
return $rc
}
VirtualDomain_Start() {
if VirtualDomain_Status; then
ocf_log info "Virtual domain $DOMAIN_NAME already running."
return $OCF_SUCCESS
fi
virsh $VIRSH_OPTIONS start ${DOMAIN_NAME}
rc=$?
if [ $rc -ne 0 ]; then
ocf_log error "Failed to start virtual domain ${DOMAIN_NAME}."
return $OCF_ERR_GENERIC
fi
while ! VirtualDomain_Monitor; do
sleep 1
done
return $OCF_SUCCESS
}
VirtualDomain_Stop() {
local i
local status
local shutdown_timeout
local out ex
VirtualDomain_Status
status=$?
case $status in
$OCF_SUCCESS)
if ! ocf_is_true $OCF_RESKEY_force_stop; then
# Issue a graceful shutdown request
ocf_log info "Issuing graceful shutdown request for domain ${DOMAIN_NAME}."
virsh $VIRSH_OPTIONS shutdown ${DOMAIN_NAME}
# The "shutdown_timeout" we use here is the operation
# timeout specified in the CIB, minus 5 seconds
shutdown_timeout=$(( $NOW + ($OCF_RESKEY_CRM_meta_timeout/1000) -5 ))
# Loop on status until we reach $shutdown_timeout
while [ $NOW -lt $shutdown_timeout ]; do
VirtualDomain_Status
status=$?
case $status in
$OCF_NOT_RUNNING)
# This was a graceful shutdown. Clean
# up and return.
VirtualDomain_Cleanup_Statefile
return $OCF_SUCCESS
;;
$OCF_SUCCESS)
# Domain is still running, keep
# waiting (until shutdown_timeout
# expires)
sleep 1
;;
*)
# Something went wrong. Bail out and
# resort to forced stop (destroy).
break;
esac
NOW=$(date +%s)
done
fi
;;
$OCF_NOT_RUNNING)
ocf_log info "Domain $DOMAIN_NAME already stopped."
return $OCF_SUCCESS
esac
# OK. Now if the above graceful shutdown hasn't worked, kill
# off the domain with destroy. If that too does not work,
# have the LRM time us out.
ocf_log info "Issuing forced shutdown (destroy) request for domain ${DOMAIN_NAME}."
out=$(virsh $VIRSH_OPTIONS destroy ${DOMAIN_NAME} 2>&1)
ex=$?
echo >&2 "$out"
# unconditionally clean up.
VirtualDomain_Cleanup_Statefile
case $ex$out in
*"error: Requested operation is not valid: domain is not running"*)
: ;; # unexpected path to the intended outcome, all is well
[!0]*)
return $OCF_ERR_GENERIC ;;
0*)
while [ $status != $OCF_NOT_RUNNING ]; do
VirtualDomain_Status
status=$?
done ;;
esac
return $OCF_SUCCESS
}
VirtualDomain_Migrate_To() {
local target_node
local remoteuri
local transport_suffix
+ local migrateuri
+ local migrateport
+ local migrate_target
+ local hypervisor
target_node="$OCF_RESKEY_CRM_meta_migrate_target"
if VirtualDomain_Status; then
# Find out the remote hypervisor to connect to. That is, turn
# something like "qemu://foo:9999/system" into
# "qemu+tcp://bar:9999/system"
if [ -n "${OCF_RESKEY_migration_transport}" ]; then
transport_suffix="+${OCF_RESKEY_migration_transport}"
fi
+ # A typical migration URI via a special migration network looks
+ # like "tcp://bar-mig:49152". The port would be randomly chosen
+ # by libvirt from the range 49152-49215 if omitted, at least since
+ # version 0.7.4 ...
+ if [ -n "${OCF_RESKEY_migration_network_suffix}" ]; then
+ hypervisor="${OCF_RESKEY_hypervisor%%[+:]*}"
+ # Hostname might be a FQDN
+ migrate_target=$(echo ${target_node} | sed -e "s,^\([^.]\+\),\1${OCF_RESKEY_migration_network_suffix},")
+ case $hypervisor in
+ qemu)
+ # For quiet ancient libvirt versions a migration port is needed
+ # and the URI must not contain the "//". Newer versions can handle
+ # the "bad" URI.
+ migrateport=$(( 49152 + $(ocf_maybe_random) % 64 ))
+ migrateuri="tcp:${migrate_target}:${migrateport}"
+ ;;
+ xen)
+ migrateuri="xenmigr://${migrate_target}"
+ ;;
+ *)
+ ocf_log warn "$DOMAIN_NAME: Migration via dedicated network currently not supported for ${hypervisor}."
+ ;;
+ esac
+ fi
# Scared of that sed expression? So am I. :-)
remoteuri=$(echo ${OCF_RESKEY_hypervisor} | sed -e "s,\(.*\)://[^/:]*\(:\?[0-9]*\)/\(.*\),\1${transport_suffix}://${target_node}\2/\3,")
# OK, we know where to connect to. Now do the actual migration.
- ocf_log info "$DOMAIN_NAME: Starting live migration to ${target_node} (using remote hypervisor URI ${remoteuri})."
- virsh ${VIRSH_OPTIONS} migrate --live $DOMAIN_NAME ${remoteuri}
+ ocf_log info "$DOMAIN_NAME: Starting live migration to ${target_node} (using remote hypervisor URI ${remoteuri} ${migrateuri})."
+ virsh ${VIRSH_OPTIONS} migrate --live $DOMAIN_NAME ${remoteuri} ${migrateuri}
rc=$?
if [ $rc -ne 0 ]; then
- ocf_log err "$DOMAIN_NAME: live migration to ${remoteuri} failed: $rc"
+ ocf_log err "$DOMAIN_NAME: live migration to ${remoteuri} ${migrateuri} failed: $rc"
return $OCF_ERR_GENERIC
else
ocf_log info "$DOMAIN_NAME: live migration to ${target_node} succeeded."
VirtualDomain_Cleanup_Statefile
return $OCF_SUCCESS
fi
else
ocf_log err "$DOMAIN_NAME: migrate_to: Not active locally!"
return $OCF_ERR_GENERIC
fi
}
VirtualDomain_Migrate_From() {
while ! VirtualDomain_Monitor; do
sleep 1
done
ocf_log info "$DOMAIN_NAME: live migration from ${OCF_RESKEY_CRM_meta_migrate_source} succeeded."
return $OCF_SUCCESS
}
VirtualDomain_Monitor() {
# First, check the domain status. If that returns anything other
# than $OCF_SUCCESS, something is definitely wrong.
VirtualDomain_Status
rc=$?
if [ ${rc} -eq ${OCF_SUCCESS} ]; then
# OK, the generic status check turned out fine. Now, if we
# have monitor scripts defined, run them one after another.
for script in ${OCF_RESKEY_monitor_scripts}; do
script_output="$($script 2>&1)"
script_rc=$?
if [ ${script_rc} -ne ${OCF_SUCCESS} ]; then
# A monitor script returned a non-success exit
# code. Stop iterating over the list of scripts, log a
# warning message, and propagate $OCF_ERR_GENERIC.
ocf_log warn "Monitor command \"${script}\" for domain ${DOMAIN_NAME} returned ${script_rc} with output: ${script_output}"
rc=$OCF_ERR_GENERIC
break
else
ocf_log debug "Monitor command \"${script}\" for domain ${DOMAIN_NAME} completed successfully with output: ${script_output}"
fi
done
fi
return ${rc}
}
VirtualDomain_Validate_All() {
# Required binaries:
for binary in virsh sed; do
check_binary $binary
done
if [ -z $OCF_RESKEY_config ]; then
ocf_log error "Missing configuration parameter \"config\"."
return $OCF_ERR_CONFIGURED
fi
# check if we can read the config file (otherwise we're unable to
# deduce $DOMAIN_NAME from it, see below)
if [ ! -r $OCF_RESKEY_config ]; then
if ocf_is_probe; then
ocf_log info "Configuration file $OCF_RESKEY_config not readable during probe."
else
ocf_log error "Configuration file $OCF_RESKEY_config does not exist or is not readable."
return $OCF_ERR_INSTALLED
fi
fi
}
if [ $# -ne 1 ]; then
usage
exit $OCF_ERR_ARGS
fi
case $1 in
meta-data) meta_data
exit $OCF_SUCCESS
;;
usage) usage
exit $OCF_SUCCESS
;;
esac
# Everything except usage and meta-data must pass the validate test
VirtualDomain_Validate_All || exit $?
# During a probe, it is permissible for the config file to not be
# readable (it might be on shared storage not available during the
# probe). In that case, VirtualDomain_Define can't work and we're
# unable to get the domain name. Thus, we also can't check whether the
# domain is running. The only thing we can do here is to assume that
# it is not running.
if ocf_is_probe && [ ! -r $OCF_RESKEY_config ]; then
exit $OCF_NOT_RUNNING
fi
# Define the domain on startup, and re-define whenever someone deleted
# the state file, or touched the config.
if [ ! -e $STATEFILE ] || [ $OCF_RESKEY_config -nt $STATEFILE ]; then
VirtualDomain_Define
fi
# By now, we should definitely be able to read from the state file.
# If not, something went wrong.
if [ ! -r $STATEFILE ]; then
ocf_log err "$STATEFILE not found or unreadable. This is unexpected. Cannot determine domain name."
exit $OCF_ERR_GENERIC
fi
# Finally, retrieve the domain name from the state file.
DOMAIN_NAME=`cat $STATEFILE 2>/dev/null`
if [ -z $DOMAIN_NAME ]; then
ocf_log err "$STATEFILE is empty. This is unexpected. Cannot determine domain name."
exit $OCF_ERR_GENERIC
fi
case $1 in
start)
VirtualDomain_Start
;;
stop)
VirtualDomain_Stop
;;
migrate_to)
VirtualDomain_Migrate_To
;;
migrate_from)
VirtualDomain_Migrate_From
;;
status)
VirtualDomain_Status
;;
monitor)
VirtualDomain_Monitor
;;
validate-all)
;;
*)
usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
exit $?
diff --git a/tools/ocf-tester.in b/tools/ocf-tester.in
index 218e5239a..291bd4028 100755
--- a/tools/ocf-tester.in
+++ b/tools/ocf-tester.in
@@ -1,406 +1,409 @@
#!/bin/sh
#
# $Id: ocf-tester,v 1.2 2006/08/14 09:38:20 andrew Exp $
#
# Copyright (c) 2006 Novell Inc, Andrew Beekhof
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Further, this software is distributed without any warranty that it is
# free of the rightful claim of any third person regarding infringement
# or the like. Any license provided herein, whether implied or
# otherwise, applies only to this software file. Patent licenses, if
# any, provided herein do not apply to combinations of this program with
# other software, or any other product whatsoever.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
#
LRMD=@libdir@/heartbeat/lrmd
LRMADMIN=@sbindir@/lrmadmin
METADATA_LINT="xmllint --noout --valid -"
# set some common meta attributes, which are expected to be
# present by resource agents
export OCF_RESKEY_CRM_meta_timeout=20000 # 20 seconds timeout
export OCF_RESKEY_CRM_meta_interval=10000 # reset this for probes
num_errors=0
usage() {
+ # make sure to output errors on stderr
+ [ "x$1" = "x0" ] || exec >&2
+
echo "Tool for testing if a cluster resource is OCF compliant"
echo ""
echo "Usage: ocf-tester [-Lh] -n resource_name [-o name=value]* /full/path/to/resource/agent"
echo ""
echo "Options:"
- echo " -h,--help This text"
+ echo " -h This text"
echo " -n name Name of the resource"
echo " -o name=value Name and value of any parameters required by the agent"
echo " -L Use lrmadmin/lrmd for tests"
exit $1
}
assert() {
rc=$1; shift
target=$1; shift
msg=$1; shift
if [ $# = 0 ]; then
exit_code=0
else
exit_code=$1; shift
fi
if [ $rc -ne $target ]; then
num_errors=`expr $num_errors + 1`
echo "* rc=$rc: $msg"
if [ $exit_code != 0 ]; then
[ -n "$command_output" ] && cat<<EOF
$command_output
EOF
echo "Aborting tests"
exit $exit_code
fi
fi
command_output=""
}
done=0
ra_args=""
verbose=0
while test "$done" = "0"; do
case "$1" in
-n) OCF_RESOURCE_INSTANCE=$2; ra_args="$ra_args OCF_RESOURCE_INSTANCE=$2"; shift; shift;;
-o) name=${2%%=*}; value=${2#*=};
lrm_ra_args="$lrm_ra_args $2";
ra_args="$ra_args OCF_RESKEY_$name=$value"; shift; shift;;
-L) use_lrmd=1; shift;;
-v) verbose=1; shift;;
-?|--help) usage 0;;
--version) echo "@PACKAGE_VERSION@"; exit 0;;
- -*) echo "unknown option: $1"; usage 1;;
+ -*) echo "unknown option: $1" >&2; usage 1;;
*) done=1;;
esac
done
if [ "x" = "x$OCF_ROOT" ]; then
if [ -d /usr/lib/ocf ]; then
export OCF_ROOT=/usr/lib/ocf
else
- echo "You must supply the location of OCF_ROOT (common location is /usr/lib/ocf)"
+ echo "You must supply the location of OCF_ROOT (common location is /usr/lib/ocf)" >&2
usage 1
fi
fi
if [ "x" = "x$OCF_RESOURCE_INSTANCE" ]; then
- echo "You must give your resource a name, set OCF_RESOURCE_INSTANCE"
+ echo "You must give your resource a name, set OCF_RESOURCE_INSTANCE" >&2
usage 1
fi
agent=$1
if [ ! -e $agent ]; then
- echo "You must provide the full path to your resource agent"
+ echo "You must provide the full path to your resource agent" >&2
usage 1
fi
stopped_rc=7
has_demote=1
has_promote=1
start_lrmd() {
lrmd_timeout=0
lrmd_interval=0
lrmd_target_rc=EVERYTIME
lrmd_started=""
$LRMD -s 2>/dev/null
rc=$?
if [ $rc -eq 3 ]; then
lrmd_started=1
$LRMD &
sleep 1
$LRMD -s 2>/dev/null
else
return $rc
fi
}
add_resource() {
$LRMADMIN -A $OCF_RESOURCE_INSTANCE \
ocf \
`basename $agent` \
$(basename `dirname $agent`) \
$lrm_ra_args > /dev/null
}
del_resource() {
$LRMADMIN -D $OCF_RESOURCE_INSTANCE
}
parse_lrmadmin_output() {
awk '
BEGIN{ rc=1; }
/Waiting for lrmd to callback.../ { n=1; next; }
n==1 && /----------------operation--------------/ { n++; next; }
n==2 && /return code:/ { rc=$0; sub("return code: *","",rc); next }
n==2 && /---------------------------------------/ {
n++;
next;
}
END{
if( n!=3 ) exit 1;
else exit rc;
}
'
}
exec_resource() {
op="$1"
args="$2"
$LRMADMIN -E $OCF_RESOURCE_INSTANCE \
$op $lrmd_timeout $lrmd_interval \
$lrmd_target_rc \
$args | parse_lrmadmin_output
}
if [ "$use_lrmd" = 1 ]; then
echo "Using lrmd/lrmadmin for all tests"
start_lrmd || {
- echo "could not start lrmd"
+ echo "could not start lrmd" >&2
exit 1
}
trap '
[ "$lrmd_started" = 1 ] && $LRMD -k
' EXIT
add_resource || {
- echo "failed to add resource to lrmd"
+ echo "failed to add resource to lrmd" >&2
exit 1
}
fi
lrm_test_command() {
action="$1"
msg="$2"
[ "$verbose" -eq 0 ] || echo "$msg"
exec_resource $action "$lrm_ra_args"
}
test_permissions() {
action=meta-data
msg=${1:-"Testing permissions with uid nobody"}
if [ $verbose -ne 0 ]; then
echo $msg
fi
su nobody -s /bin/sh $agent $action > /dev/null
}
test_metadata() {
action=meta-data
msg=${1:-"Testing: $action"}
if [ $verbose -ne 0 ]; then
echo $msg
fi
bash $agent $action | (cd /usr/share/resource-agents && $METADATA_LINT)
rc=$?
#echo rc: $rc
return $rc
}
test_command() {
action=$1; shift
export __OCF_ACTION=$action
msg=${1:-"Testing: $action"}
if [ "$use_lrmd" = 1 ]; then
lrm_test_command $action "$msg"
return $?
fi
#echo Running: "export $ra_args; bash $agent $action 2>&1 > /dev/null"
if [ $verbose -eq 0 ]; then
command_output=`bash $agent $action 2>&1`
else
echo $msg
bash $agent $action
fi
rc=$?
#echo rc: $rc
return $rc
}
# Begin tests
echo Beginning tests for $agent...
if [ ! -f $agent ]; then
assert 7 0 "Could not find file: $agent"
fi
if [ `id -u` = 0 ]; then
test_permissions
assert $? 0 "Your agent has too restrictive permissions: should be 755"
else
echo "WARN: Can't check agent's permissions because we're not root; they should be 755"
fi
test_metadata
assert $? 0 "Your agent produces meta-data which does not conform to ra-api-1.dtd"
OCF_TESTER_FAIL_HAVE_BINARY=1
export OCF_TESTER_FAIL_HAVE_BINARY
test_command meta-data
rc=$?
if [ $rc -eq 3 ]; then
assert $rc 0 "Your agent does not support the meta-data action"
else
assert $rc 0 "The meta-data action cannot fail and must return 0"
fi
unset OCF_TESTER_FAIL_HAVE_BINARY
export $ra_args;
test_command validate-all
rc=$?
if [ $rc -eq 3 ]; then
assert $rc 0 "Your agent does not support the validate-all action"
elif [ $rc -ne 0 ]; then
assert $rc 0 "Validation failed. Did you supply enough options with -o ?" 1
usage $rc
fi
test_command monitor "Checking current state"
rc=$?
if [ $rc -eq 3 ]; then
assert $rc 7 "Your agent does not support the monitor action" 1
elif [ $rc -eq 8 ]; then
test_command demote "Cleanup, demote"
assert $? 0 "Your agent was a master and could not be demoted" 1
test_command stop "Cleanup, stop"
assert $? 0 "Your agent was a master and could not be stopped" 1
elif [ $rc -ne 7 ]; then
test_command stop
assert $? 0 "Your agent was active and could not be stopped" 1
fi
test_command monitor
assert $? $stopped_rc "Monitoring a stopped resource should return $stopped_rc"
OCF_TESTER_FAIL_HAVE_BINARY=1
export OCF_TESTER_FAIL_HAVE_BINARY
OCF_RESKEY_CRM_meta_interval=0
test_command monitor
assert $? $stopped_rc "The initial probe for a stopped resource should return $stopped_rc even if all binaries are missing"
unset OCF_TESTER_FAIL_HAVE_BINARY
OCF_RESKEY_CRM_meta_interval=20000
test_command start
assert $? 0 "Start failed. Did you supply enough options with -o ?" 1
test_command monitor
assert $? 0 "Monitoring an active resource should return 0"
test_command notify
rc=$?
if [ $rc -eq 3 ]; then
echo "* Your agent does not support the notify action (optional)"
else
assert $rc 0 "The notify action cannot fail and must return 0"
fi
test_command demote "Checking for demote action"
if [ $? -eq 3 ]; then
has_demote=0
echo "* Your agent does not support the demote action (optional)"
fi
test_command promote "Checking for promote action"
if [ $? -eq 3 ]; then
has_promote=0
echo "* Your agent does not support the promote action (optional)"
fi
if [ $has_promote -eq 1 -a $has_demote -eq 1 ]; then
test_command demote "Testing: demotion of started resource"
assert $? 0 "Demoting a start resource should not fail"
test_command promote
assert $? 0 "Promote failed"
test_command demote
assert $? 0 "Demote failed" 1
test_command demote "Testing: demotion of demoted resource"
assert $? 0 "Demoting a demoted resource should not fail"
test_command promote "Promoting resource"
assert $? 0 "Promote failed" 1
test_command promote "Testing: promotion of promoted resource"
assert $? 0 "Promoting a promoted resource should not fail"
test_command demote "Demoting resource"
assert $? 0 "Demote failed" 1
elif [ $has_promote -eq 0 -a $has_demote -eq 0 ]; then
echo "* Your agent does not support master/slave (optional)"
else
echo "* Your agent partially supports master/slave"
num_errors=`expr $num_errors + 1`
fi
test_command stop
assert $? 0 "Stop failed" 1
test_command monitor
assert $? $stopped_rc "Monitoring a stopped resource should return $stopped_rc"
test_command start "Restarting resource..."
assert $? 0 "Start failed" 1
test_command monitor
assert $? 0 "Monitoring an active resource should return 0"
test_command start "Testing: starting a started resource"
assert $? 0 "Starting a running resource is required to succeed"
test_command monitor
assert $? 0 "Monitoring an active resource should return 0"
test_command stop "Stopping resource"
assert $? 0 "Stop could not clean up after multiple starts" 1
test_command monitor
assert $? $stopped_rc "Monitoring a stopped resource should return $stopped_rc"
test_command stop "Testing: stopping a stopped resource"
assert $? 0 "Stopping a stopped resource is required to succeed"
test_command monitor
assert $? $stopped_rc "Monitoring a stopped resource should return $stopped_rc"
test_command migrate_to "Checking for migrate_to action"
rc=$?
if [ $rc -ne 3 ]; then
test_command migrate_from "Checking for migrate_from action"
fi
if [ $? -eq 3 ]; then
echo "* Your agent does not support the migrate action (optional)"
fi
test_command reload "Checking for reload action"
if [ $? -eq 3 ]; then
echo "* Your agent does not support the reload action (optional)"
fi
if [ $num_errors -gt 0 ]; then
- echo Tests failed: $agent failed $num_errors tests
+ echo "Tests failed: $agent failed $num_errors tests" >&2
exit 1
else
echo $agent passed all tests
exit 0
fi
# vim:et:ts=8:sw=4
diff --git a/tools/ocft/db2 b/tools/ocft/db2
index 0af51a849..4bcd23ab1 100644
--- a/tools/ocft/db2
+++ b/tools/ocft/db2
@@ -1,162 +1,162 @@
# db2
#
# This test assumes a db2 ESE instance with two partions and a database.
# Default is instance=db2inst1, database=ocft
# adapt this in set_testenv below
#
# Simple steps to generate a test environment (if you don't have one):
#
# A virtual machine with 1200MB RAM is sufficient
#
# - download an eval version of DB2 server from IBM
# - create an user "db2inst1" in group "db2inst1"
#
# As root
# - install DB2 software in some location
# - create instance
# cd <this_location>/instance
# ./db2icrt -s ese -u db2inst1 db2inst1
# - adapt profile of db2inst1 as instructed by db2icrt
#
# As db2inst1
# # allow to run with small memory footprint
# db2set DB2_FCM_SETTINGS=FCM_MAXIMIZE_SET_SIZE:FALSE
# db2start
# db2start dbpartitionnum 1 add dbpartitionnum hostname $(uname -n) port 1 without tablespaces
# db2stop
# db2start
# db2 create database ocft
# Done
# In order to install a real cluster refer to http://www.linux-ha.org/wiki/db2_(resource_agent)
CONFIG
HangTimeout 40
SETUP-AGENT
# nothing
CASE-BLOCK set_testenv
- Var OCFT_instance=db2inst
+ Var OCFT_instance=db2inst1
Var OCFT_db=ocft
CASE-BLOCK crm_setting
Var OCF_RESKEY_instance=$OCFT_instance
Var OCF_RESKEY_CRM_meta_timeout=30000
CASE-BLOCK default_status
AgentRun stop
CASE-BLOCK prepare
Include set_testenv
Include crm_setting
Include default_status
CASE "check base env"
Include prepare
AgentRun start OCF_SUCCESS
CASE "check base env: invalid 'OCF_RESKEY_instance'"
Include prepare
Var OCF_RESKEY_instance=no_such
AgentRun start OCF_ERR_INSTALLED
CASE "invalid instance config"
Include prepare
Bash eval mv ~$OCFT_instance/sqllib ~$OCFT_instance/sqllib-
BashAtExit eval mv ~$OCFT_instance/sqllib- ~$OCFT_instance/sqllib
AgentRun start OCF_ERR_INSTALLED
CASE "unimplemented command"
Include prepare
AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
CASE "normal start"
Include prepare
AgentRun start OCF_SUCCESS
CASE "normal stop"
Include prepare
AgentRun start
AgentRun stop OCF_SUCCESS
CASE "double start"
Include prepare
AgentRun start
AgentRun start OCF_SUCCESS
CASE "double stop"
Include prepare
AgentRun stop OCF_SUCCESS
CASE "started: monitor"
Include prepare
AgentRun start
AgentRun monitor OCF_SUCCESS
CASE "not started: monitor"
Include prepare
AgentRun monitor OCF_NOT_RUNNING
CASE "killed instance: monitor"
Include prepare
AgentRun start OCF_SUCCESS
AgentRun monitor OCF_SUCCESS
BashAtExit rm /tmp/ocft-helper1
Bash echo "su $OCFT_instance -c '. ~$OCFT_instance/sqllib/db2profile; db2nkill 0 >/dev/null 2>&1'" > /tmp/ocft-helper1
Bash sh -x /tmp/ocft-helper1
AgentRun monitor OCF_NOT_RUNNING
CASE "overload param instance by admin"
Include prepare
Var OCF_RESKEY_instance=no_such
Var OCF_RESKEY_admin=$OCFT_instance
AgentRun start OCF_SUCCESS
CASE "check start really activates db"
Include prepare
AgentRun start OCF_SUCCESS
BashAtExit rm /tmp/ocft-helper2
Bash echo "su $OCFT_instance -c '. ~$OCFT_instance/sqllib/db2profile; db2 get snapshot for database on $OCFT_db>/dev/null'" > /tmp/ocft-helper2
Bash sh -x /tmp/ocft-helper2
CASE "multipartion test"
Include prepare
AgentRun start OCF_SUCCESS
AgentRun monitor OCF_SUCCESS
# start does not start partion 1
Var OCF_RESKEY_dbpartitionnum=1
AgentRun monitor OCF_NOT_RUNNING
# now start 1
AgentRun start OCF_SUCCESS
AgentRun monitor OCF_SUCCESS
# now stop 1
AgentRun stop OCF_SUCCESS
AgentRun monitor OCF_NOT_RUNNING
# does not affect 0
Var OCF_RESKEY_dbpartitionnum=0
AgentRun monitor OCF_SUCCESS
# fault injection does not work on the 1.0.4 client due to a hardcoded path
CASE "simulate hanging db2stop (not meaningful for 1.0.4 agent)"
Include prepare
AgentRun start OCF_SUCCESS
Bash [ ! -f /usr/local/bin/db2stop ]
BashAtExit rm /usr/local/bin/db2stop
Bash echo -e "#!/bin/sh\necho fake db2stop\nsleep 10000" > /usr/local/bin/db2stop
Bash chmod +x /usr/local/bin/db2stop
AgentRun stop OCF_SUCCESS
# fault injection does not work on the 1.0.4 client due to a hardcoded path
CASE "simulate not stopping db2stop (not meaningful for 1.0.4 agent)"
Include prepare
AgentRun start OCF_SUCCESS
Bash [ ! -f /usr/local/bin/db2stop ]
BashAtExit rm /usr/local/bin/db2stop
Bash echo -e "#!/bin/sh\necho fake db2stop\nexit 0" > /usr/local/bin/db2stop
Bash chmod +x /usr/local/bin/db2stop
AgentRun stop OCF_SUCCESS
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Feb 27, 1:08 AM (16 h, 49 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1465977
Default Alt Text
(55 KB)
Attached To
Mode
rR Resource Agents
Attached
Detach File
Event Timeline
Log In to Comment