[Debian-ha-commits] [resource-agents] 01/04: Imported Upstream version 3.9.5+git+a626847

Richard Winters devrik-guest at moszumanska.debian.org
Thu Apr 16 08:08:14 UTC 2015


This is an automated email from the git hooks/post-receive script.

devrik-guest pushed a commit to branch master
in repository resource-agents.

commit a41405c7f8201b4c9c4929899859e7fcad3f4023
Author: Richard B Winters <rik at mmogp.com>
Date:   Thu Apr 16 03:47:08 2015 -0400

    Imported Upstream version 3.9.5+git+a626847
---
 .gitattributes                                     |    2 +
 .gitignore                                         |   80 +
 AUTHORS                                            |   59 +
 COPYING                                            |  339 ++
 COPYING.GPLv3                                      |  674 +++
 COPYING.LGPL                                       |  502 ++
 ChangeLog                                          |  475 ++
 Makefile.am                                        |  171 +
 NEWS                                               |    0
 README                                             |   12 +
 autogen.sh                                         |    3 +
 configure.ac                                       |  904 ++++
 doc/Makefile.am                                    |   27 +
 doc/README.webapps                                 |  143 +
 doc/dev-guides/ra-dev-guide-docinfo.xml            |   89 +
 doc/dev-guides/ra-dev-guide.txt                    | 2021 ++++++++
 doc/man/Makefile.am                                |  165 +
 doc/man/mkappendix.sh                              |   18 +
 doc/man/ra2refentry.xsl                            |  539 ++
 doc/man/ralist.sh                                  |    9 +
 heartbeat/AoEtarget                                |  245 +
 heartbeat/AudibleAlarm                             |  188 +
 heartbeat/CTDB                                     |  737 +++
 heartbeat/ClusterMon                               |  261 +
 heartbeat/Delay                                    |  223 +
 heartbeat/Dummy                                    |  174 +
 heartbeat/EvmsSCC                                  |  216 +
 heartbeat/Evmsd                                    |  155 +
 heartbeat/Filesystem                               |  810 +++
 heartbeat/ICP                                      |  296 ++
 heartbeat/IPaddr                                   |  892 ++++
 heartbeat/IPaddr2                                  | 1075 ++++
 heartbeat/IPsrcaddr                                |  486 ++
 heartbeat/IPv6addr.c                               |  876 ++++
 heartbeat/IPv6addr_utils.c                         |  147 +
 heartbeat/LVM                                      |  672 +++
 heartbeat/LinuxSCSI                                |  314 ++
 heartbeat/MailTo                                   |  191 +
 heartbeat/Makefile.am                              |  147 +
 heartbeat/ManageRAID                               |  384 ++
 heartbeat/ManageVE                                 |  313 ++
 heartbeat/Pure-FTPd                                |  251 +
 heartbeat/README                                   |   44 +
 heartbeat/Raid1                                    |  556 +++
 heartbeat/Route                                    |  313 ++
 heartbeat/SAPDatabase                              |  331 ++
 heartbeat/SAPInstance                              |  942 ++++
 heartbeat/SendArp                                  |  267 +
 heartbeat/ServeRAID                                |  419 ++
 heartbeat/SphinxSearchDaemon                       |  223 +
 heartbeat/Squid                                    |  446 ++
 heartbeat/Stateful                                 |  188 +
 heartbeat/SysInfo                                  |  365 ++
 heartbeat/VIPArip                                  |  302 ++
 heartbeat/VirtualDomain                            |  638 +++
 heartbeat/WAS                                      |  572 +++
 heartbeat/WAS6                                     |  546 ++
 heartbeat/WinPopup                                 |  231 +
 heartbeat/Xen                                      |  535 ++
 heartbeat/Xinetd                                   |  240 +
 heartbeat/anything                                 |  316 ++
 heartbeat/apache                                   |  651 +++
 heartbeat/apache-conf.sh                           |  194 +
 heartbeat/asterisk                                 |  479 ++
 heartbeat/conntrackd                               |  335 ++
 heartbeat/db2                                      |  864 ++++
 heartbeat/dhcpd                                    |  545 ++
 heartbeat/eDir88                                   |  460 ++
 heartbeat/ethmonitor                               |  454 ++
 heartbeat/exportfs                                 |  350 ++
 heartbeat/findif.sh                                |  180 +
 heartbeat/fio                                      |  172 +
 heartbeat/http-mon.sh                              |  140 +
 heartbeat/iSCSILogicalUnit                         |  580 +++
 heartbeat/iSCSITarget                              |  597 +++
 heartbeat/ids                                      |  738 +++
 heartbeat/iface-bridge                             |  843 ++++
 heartbeat/iface-vlan                               |  475 ++
 heartbeat/iscsi                                    |  503 ++
 heartbeat/jboss                                    |  658 +++
 heartbeat/lxc                                      |  323 ++
 heartbeat/mysql                                    | 1274 +++++
 heartbeat/mysql-proxy                              |  719 +++
 heartbeat/named                                    |  489 ++
 heartbeat/nfsserver                                |  489 ++
 heartbeat/nginx                                    |  947 ++++
 heartbeat/ocf-binaries.in                          |   74 +
 heartbeat/ocf-directories.in                       |   22 +
 heartbeat/ocf-rarun                                |  146 +
 heartbeat/ocf-returncodes                          |   55 +
 heartbeat/ocf-shellfuncs.in                        |  780 +++
 heartbeat/ora-common.sh                            |   84 +
 heartbeat/oracle                                   |  659 +++
 heartbeat/oralsnr                                  |  281 ++
 heartbeat/pgsql                                    | 1872 +++++++
 heartbeat/pingd                                    |  279 ++
 heartbeat/portblock                                |  477 ++
 heartbeat/postfix                                  |  415 ++
 heartbeat/pound                                    |  339 ++
 heartbeat/proftpd                                  |  301 ++
 heartbeat/ra-api-1.dtd                             |   40 +
 heartbeat/rsyncd                                   |  270 +
 heartbeat/rsyslog                                  |  254 +
 heartbeat/sapdb-nosha.sh                           |  744 +++
 heartbeat/sapdb.sh                                 |  340 ++
 heartbeat/scsi2reservation                         |  170 +
 heartbeat/send_ua.c                                |  127 +
 heartbeat/sfex                                     |  297 ++
 heartbeat/shellfuncs.in                            |   96 +
 heartbeat/slapd                                    |  591 +++
 heartbeat/symlink                                  |  245 +
 heartbeat/syslog-ng                                |  372 ++
 heartbeat/tomcat                                   |  720 +++
 heartbeat/varnish                                  |  454 ++
 heartbeat/vmware                                   |  393 ++
 heartbeat/zabbixserver                             |  336 ++
 include/IPv6addr.h                                 |   58 +
 include/Makefile.am                                |   24 +
 include/agent_config.h.in                          |    2 +
 ldirectord/Makefile.am                             |   45 +
 ldirectord/OCF/Makefile.am                         |   26 +
 ldirectord/OCF/ldirectord.in                       |  269 +
 ldirectord/init.d/Makefile.am                      |   28 +
 ldirectord/init.d/ldirectord.debian.default.in     |    6 +
 ldirectord/init.d/ldirectord.debian.in             |   35 +
 ldirectord/init.d/ldirectord.in                    |   90 +
 ldirectord/ldirectord.cf                           |  341 ++
 ldirectord/ldirectord.in                           | 5258 ++++++++++++++++++++
 ldirectord/logrotate.d/Makefile.am                 |   26 +
 ldirectord/logrotate.d/ldirectord                  |    3 +
 make/git-version-gen                               |  161 +
 make/gitlog-to-changelog                           |  191 +
 make/release.mk                                    |   73 +
 resource-agents.spec.in                            |  306 ++
 rgmanager/Makefile.am                              |   21 +
 rgmanager/src/Makefile.am                          |   21 +
 rgmanager/src/resources/ASEHAagent.sh              |  900 ++++
 rgmanager/src/resources/Makefile.am                |  117 +
 rgmanager/src/resources/SAPDatabase                | 1026 ++++
 rgmanager/src/resources/SAPInstance                |  630 +++
 rgmanager/src/resources/apache.metadata            |   96 +
 rgmanager/src/resources/apache.sh                  |  290 ++
 rgmanager/src/resources/clusterfs.sh               |  341 ++
 rgmanager/src/resources/drbd.metadata              |   51 +
 rgmanager/src/resources/drbd.sh                    |  144 +
 rgmanager/src/resources/fs.sh.in                   |  509 ++
 rgmanager/src/resources/ip.sh                      | 1027 ++++
 rgmanager/src/resources/lvm.metadata               |   86 +
 rgmanager/src/resources/lvm.sh                     |  180 +
 rgmanager/src/resources/lvm_by_lv.sh               |  532 ++
 rgmanager/src/resources/lvm_by_vg.sh               |  529 ++
 rgmanager/src/resources/mysql.metadata             |  107 +
 rgmanager/src/resources/mysql.sh                   |  213 +
 rgmanager/src/resources/named.metadata             |  116 +
 rgmanager/src/resources/named.sh                   |  215 +
 rgmanager/src/resources/netfs.sh                   |  493 ++
 rgmanager/src/resources/nfsclient.sh               |  471 ++
 rgmanager/src/resources/nfsexport.sh               |  256 +
 rgmanager/src/resources/nfsserver.sh               |  500 ++
 rgmanager/src/resources/ocf-shellfuncs             |  167 +
 rgmanager/src/resources/openldap.metadata          |   98 +
 rgmanager/src/resources/openldap.sh                |  227 +
 rgmanager/src/resources/oracledb.sh                | 1030 ++++
 rgmanager/src/resources/orainstance.metadata       |   98 +
 rgmanager/src/resources/orainstance.sh             |  577 +++
 rgmanager/src/resources/oralistener.metadata       |   73 +
 rgmanager/src/resources/oralistener.sh             |  191 +
 rgmanager/src/resources/postgres-8.metadata        |   97 +
 rgmanager/src/resources/postgres-8.sh              |  233 +
 rgmanager/src/resources/ra-api-1-modified.dtd      |   68 +
 rgmanager/src/resources/ra2man.xsl                 |  158 +
 rgmanager/src/resources/ra2ref.xsl                 |   10 +
 rgmanager/src/resources/ra2rng.xsl                 |  330 ++
 rgmanager/src/resources/resources.rng.head         |    1 +
 rgmanager/src/resources/resources.rng.mid          |    3 +
 rgmanager/src/resources/resources.rng.tail         |   23 +
 rgmanager/src/resources/samba.metadata             |   89 +
 rgmanager/src/resources/samba.sh                   |  241 +
 rgmanager/src/resources/script.sh                  |  171 +
 rgmanager/src/resources/service.sh                 |  300 ++
 rgmanager/src/resources/smb.sh                     |  698 +++
 rgmanager/src/resources/svclib_nfslock             |  281 ++
 rgmanager/src/resources/tomcat-5.metadata          |  104 +
 rgmanager/src/resources/tomcat-5.sh                |  274 +
 rgmanager/src/resources/tomcat-6.metadata          |   74 +
 rgmanager/src/resources/tomcat-6.sh                |  250 +
 rgmanager/src/resources/utils/Makefile.am          |   37 +
 rgmanager/src/resources/utils/config-utils.sh      |  295 ++
 rgmanager/src/resources/utils/fs-lib.sh            | 1195 +++++
 .../src/resources/utils/httpd-parse-config.pl      |   83 +
 rgmanager/src/resources/utils/member_util.sh       |  102 +
 rgmanager/src/resources/utils/messages.sh          |  269 +
 .../src/resources/utils/named-parse-config.pl      |   49 +
 rgmanager/src/resources/utils/ra-skelet.sh         |  156 +
 rgmanager/src/resources/utils/rhev-check.sh        |   55 +
 .../src/resources/utils/tomcat-parse-config.pl     |   63 +
 rgmanager/src/resources/vm.sh                      | 1109 +++++
 tools/Makefile.am                                  |   75 +
 tools/README.sfex                                  |  336 ++
 tools/findif.c                                     |  842 ++++
 tools/ocf-tester.8                                 |   56 +
 tools/ocf-tester.in                                |  432 ++
 tools/ocft/ChangeLog                               |   57 +
 tools/ocft/Filesystem                              |  110 +
 tools/ocft/IPaddr2                                 |  137 +
 tools/ocft/IPaddr2v4                               |  323 ++
 tools/ocft/IPaddr2v6                               |  250 +
 tools/ocft/IPsrcaddr                               |   63 +
 tools/ocft/IPv6addr                                |  150 +
 tools/ocft/LVM                                     |   86 +
 tools/ocft/MailTo                                  |   57 +
 tools/ocft/Makefile.am                             |   56 +
 tools/ocft/README.in                               |  147 +
 tools/ocft/README.zh_CN.in                         |  124 +
 tools/ocft/Raid1                                   |  146 +
 tools/ocft/SendArp                                 |   74 +
 tools/ocft/Xinetd                                  |   56 +
 tools/ocft/apache                                  |   63 +
 tools/ocft/caselib.in                              |  294 ++
 tools/ocft/db2                                     |  164 +
 tools/ocft/drbd.linbit                             |  183 +
 tools/ocft/exportfs                                |   74 +
 tools/ocft/iscsi                                   |   82 +
 tools/ocft/jboss                                   |   83 +
 tools/ocft/mysql                                   |   77 +
 tools/ocft/mysql-proxy                             |   83 +
 tools/ocft/named                                   |   69 +
 tools/ocft/nfsserver                               |   75 +
 tools/ocft/ocft.in                                 |  865 ++++
 tools/ocft/oracle                                  |   81 +
 tools/ocft/pgsql                                   |   71 +
 tools/ocft/portblock                               |   69 +
 tools/ocft/postfix                                 |  102 +
 tools/ocft/tomcat                                  |   73 +
 tools/send_arp.libnet.c                            |  758 +++
 tools/send_arp.linux.c                             |  577 +++
 tools/sfex.h                                       |  176 +
 tools/sfex_daemon.c                                |  345 ++
 tools/sfex_init.8                                  |   19 +
 tools/sfex_init.c                                  |  177 +
 tools/sfex_lib.c                                   |  474 ++
 tools/sfex_lib.h                                   |   42 +
 tools/sfex_stat.c                                  |  218 +
 tools/test-findif.sh                               |  352 ++
 tools/tickle_tcp.c                                 |  379 ++
 245 files changed, 82145 insertions(+)

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..7b49a0f
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+configure.ac export-subst
+heartbeat/ocf-shellfuncs.in export-subst
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7bdd5cf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,80 @@
+*.swp
+Makefile.in
+aclocal.m4
+autoconf
+autoheader
+autom4te.cache
+automake
+autoscan.log
+compile
+configure
+configure.scan
+config.guess
+config.log
+config.sub
+config.status
+Makefile
+depcomp
+install-sh
+libtoolize
+ltmain.sh
+libtool
+make/stamp-h1
+m4
+make/clusterautoconfig.h*
+missing
+*.pc
+.deps
+.libs
+*.o
+*.la
+*.lo
+*.loT
+rgmanager/src/resources/fs.sh
+rgmanager/src/resources/oracledb.sh
+rgmanager/src/resources/utils/config-utils.sh
+resource-agents-*
+.version
+
+*.cache
+*.upgrade.xml
+py-compile
+ylwrap
+
+# BEAM Entries
+*.beam
+parser-messages
+MISC_ERRORS
+cscope.files
+cscope.out
+patches
+updates
+logs
+
+# OS and Editor Artifacts
+.DS_Store
+.bomb
+*.rej
+*.bz2
+*.gz
+*.xz
+*.sed
+*.diff
+*.patch
+*.gres
+*~
+
+# Misc
+HTML
+TAGS
+GPATH
+GRTAGS
+GSYMS
+GTAGS
+.gres.*
+*.orig
+.gdb_history
+*~ 
+\#*
+.changes
+pacemaker.tar.gz
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..ee0169a
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,59 @@
+Authors:  
+--------  
+A. J. Lewis <alewis at redhat.com>
+Abhijith Das <adas at redhat.com>
+Adam Manthei <amanthei at redhat.com>
+Akamatsu Hiroshi <akamatsu.hiroshi at yes.nttcom.ne.jp>
+Alan Robertson <alanr at unix.sh>
+Alasdair G. Kergon <agk at redhat.com>
+Andrew Beekhof <andrew at beekhof.net>  
+Andrew Price <andy at andrewprice.me.uk>
+Benjamin Marzinski <bmarzins at redhat.com>
+Bob Peterson <rpeterso at redhat.com>
+Chris Feist <cfeist at redhat.com>
+Christian Rishoj <christian at rishoj.net>
+Christine Caulfield <ccaulfie at redhat.com>
+Daiki Matsuda <d.matuda at gmail.com>
+Daniel Phillips <phillips at redhat.com>
+David Lee <t.d.lee at durham.ac.uk>
+David Teigland <teigland at redhat.com>
+Dejan Muhamedagic <dejan at hello-penguin.com>
+Dominik Klein <dk at in-telegence.net>
+Fabio M. Di Nitto <fdinitto at redhat.com>
+Florian Haas <florian at linbit.com>
+Hideo Yamauchi <renayama19661014 at ybb.ne.jp>
+Horms <horms at verge.net.au>
+Huang Zhen <zhen.huang at gmail.com>
+James Parsons <jparsons at redhat.com>
+Jean-Francois Larvoire <jf.larvoire at hp.com>
+Joel Becker <joel.becker at oracle.com>
+Jonathan Brassow <jbrassow at redhat.com>
+Keisuke MORI <kskmori at intellilink.co.jp>
+Ken Preslan <kpreslan at redhat.com>
+Lars Marowsky-Bree <lmb at suse.de>
+Lon Hohberger <lhh at redhat.com>
+Marc - A. Dahlhaus <mad at wol.de>
+Marek 'marx' Grac <mgrac at redhat.com>
+Mark Hlawatschek <hlawatschek at atix.de>
+Matthew Soffen
+Michael Conrad Tadpol Tilstra <mtilstra at redhat.com>
+Michael Schwartzkopff <misch at multinet.de>
+Nakahira Kazutomo <nakahira at intellilink.co.jp>
+Patrick Caulfield <pcaulfie at redhat.com>
+Philipp Kolmann <philipp at kolmann.at>
+Raoul Bhatia <r.bhatia at ipax.at>
+Robert Peterson <rpeterso at redhat.com>
+Ron Terry <rterry at novell.com>
+Ross Vandegrift <ross at kallisti.us>
+Ryan McCabe <rmccabe at redhat.com>
+Ryan O'Hara <rohara at redhat.com>
+Sebastian Reitenbach <itlistuser at rapideye.de>
+Serge Dubrouski <sergeyfd at gmail.com>
+Simon Horman <horms at verge.net.au>
+Stanko Kupcevic <kupcevic at redhat.com>
+Stephan Berlet <SBerlet at sysdesign-edv.de>
+Steven Whitehouse <swhiteho at redhat.com>
+Takenaka Kazuhiro <takenaka.kazuhiro at oss.ntt.co.jp>
+Wendy Cheng <wcheng at redhat.com>
+Xinwei Hu <hxinwei at gmail.com>
+jparsons <jparsons at redhat.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/COPYING.GPLv3 b/COPYING.GPLv3
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING.GPLv3
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/COPYING.LGPL b/COPYING.LGPL
new file mode 100644
index 0000000..4362b49
--- /dev/null
+++ b/COPYING.LGPL
@@ -0,0 +1,502 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+

+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+

+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+

+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+

+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+

+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+

+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+

+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+

+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+

+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..3eeb3ee
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,475 @@
+* Thu Feb  7 2013 Linux-HA contributors
+- stable release 3.9.5
+- IPaddr2: support nic:iflabel format in nic parameter
+- VirtualDomain: allow for custom migrateport
+* Wed Jan 30 2013 Linux-HA contributors
+- release candidate 3.9.5 rc1
+- ocf-shellfuncs: RA tracing
+- IPaddr2: make sure that some ARP send program runs
+- pgsql: add check_wal_receiver parameter
+- pgsql: support starting as Hot Standby
+- nfsserver: improve rpc.statd support
+- nfsserver: add option -n for rpc.statd (bnc#794479)
+- nfsserver: make the retry time for sm-notify configurable
+- nfsserver: make sm-notify running in the foreground configurable
+- exportfs: handle '<world>' exportfs embelishment for '*' (bnc#791690)
+- jboss: set JAVA_OPTS correctly
+- pound: use correct default for control-binary
+- pound: No error when stopping pound and no pound is running
+- Squid: support systems using IPv6
+- Xinetd: do not fail in stop if the daemon is not running
+- Xinetd: improve finding Xinetd process (thanks to Vadym Chepkov)
+- SendArp: add background parameter
+- SendArp: fix monitor
+- ocft: print the actual case names when testing
+- ocft: make only the updated test-case file
+- ocft: add "incremental" mode (ocft test -i)
+- include a copy of LGPL license file
+
+* Tue Nov 22 2012 Linux-HA contributors
+- stable release 3.9.4
+- IPaddr2: fix waiting the completion of IPv6 address allocation
+- zabbixserver: RA for zabbix servers management
+* Tue Nov 13 2012 Linux-HA contributors
+- release candidate 3.9.4 rc1
+- ocf-rarun: add the RA driver
+- IPaddr2: use better test for infiniband (bnc#783353)
+- IPaddr2: replace the findif binary by findif.sh
+- IPaddr2: add IPv6 support
+- IPaddr2: really send arps in background if requested
+- IPaddr2: use send_arp instead of ipoibarping if not available
+- Filesystem: include ceph in the list of non-blockdev filesystems
+- Raid1: stop processes using raiddev
+- Raid1: manage multiple arrays
+- Raid1: discover block size for dd (bnc#781137)
+- exportfs: cleanup exportfs cache on stop (bnc#770210)
+- iscsi: don't fail on stop of the iscsi server fails
+- iscsi: use iscsiadm -m session -r in stop
+- iscsi: do discovery in start only
+- iscsi: check session status in monitor
+- iscsi: add try_recovery parameter
+- oracle: ignore password expiry warning in monitor (bnc#770250)
+- oracle: connect as a regular user in monitor
+- pgsql: add option recovery_end_command
+- Xen: repair node_ip_attribute use
+- SAPDatabase: improvement of cleanup of saphostctrl process
+- SAPInstance: monitor-master not advertised (bnc#782482)
+- SAPInstance: don't wait for timeout if the stop attempt failed
+- SAPInstance: failes on sapcontrol message Unauthorized (bnc#782486)
+- mysql-proxy: copy in-depth monitoring action from the mysql resource agent
+- mysql-proxy: add test_table, test_user and test_passwd parameters
+- mysql-proxy: implement "parameters" parameter
+- mysql-proxy: add the 'plugins' parameter
+- mysql-proxy: version specific checks 
+- mysql-proxy: admin plugin auto loading
+- mysql-proxy: perform SELECT for OCF_CHECK_LEVEL 20 only
+- mysql-proxy: create pid/socket directories if needed
+- conntrackd: resync from other hosts in start
+- slapd: Gracefully handle config check during probe
+- tomcat: Correction of the time-out level of the stop processing.
+- tomcat: Correction of the process alive monitoring.
+- ldirectord: Added READDQUIESCENT parameter 
+- sfex: fix sfex_init for 64-bit big endian platforms
+- SendArp: exit with the right code when not properly configured
+- Squid: fix getting PIDs of squid processes (lf#2653)
+- portblock: use end-of-word instead of space at the end of the line
+- named: use pgrep instead of searching in ps(1) output
+- named: fix monitor if named_rootdir is set to /
+- VIPArip: fix exit codes
+- VIPArip: make start idempotent
+- tools: add test-findif.sh
+- tools: add send_ua binary for IPv6 support in IPaddr2
+- ocft: new test for Raid1
+
+* Fri May 25 2012 Linux-HA contributors
+- stable release 3.9.3
+- dhcpd: new RA to manage ISC DHCP servers
+- Filesystem: add nfs4 to the list of well known types
+- IPaddr2: fix regression introduce in d93b5fd, nic=lo always
+  "stopped"
+- iSCSILogicalUnit: correctly match for target IQN and backing
+  device name (iet and tgt)
+- jboss: implememnt rotating of console log
+- mysql: improve handling of reset slave
+- oracle, oralsnr: get rid of eval
+- slapd: pass bind_dn correctly to ldapsearch
+* Wed May 16 2012 Linux-HA contributors
+- release candidate 3.9.3 rc1
+- asterisk: new resource agent
+- named: new RA to manage bind servers
+- pound: new RA for Pound HTTP/HTTPS reverse-proxy and
+  load-balancer
+- rsyslog: new RA to manage rsyslog servers
+- slapd: new RA to manage OpenLDAP servers
+- varnish: new resource agent
+- apache: add support for IPv6 in monitor
+- apache: create /var/run/apache2 if it doesn't exist
+- apache: fix sysconfig includes & enable status for default SUSE
+  conf
+- conntrackd: test for socket existence in monitor instead of
+  process grep
+- conntrackd: rename parameter "conntrackd" to "binary"
+- CTDB: Add smb_fileid_algorithm parameter (bnc#696978)
+- CTDB: Improve monitor op (check output of ctdb status,
+  bnc#712192)
+- CTDB: Set ctdb_start_as_disabled=no by default (bnc#712410,
+  required by samba 3.6)
+- exportfs: allow expanding the fsid parameter to produce correct
+  exportfs options
+- exportfs: don't grow /var/lib/nfs/rmtab indefinitely
+- exportfs: fix monitor action for special characters and common
+  suffixes
+- Filesystem: add support for glusterfs (lf#2620)
+- Filesystem: add tmpfs to the list of supported filesystems
+- Filesystem: allow to force cloning for local mounts
+- Filesystem: don't use direct dd option in monitor depth 20 for
+  non-blockdevice fs
+- Filesystem: fix determining if the device is a block device
+- Filesystem: improve read/write checks for CHECK_LEVEL 10, 20
+- Filesystem: repair the fast_stop parameter use (its value was
+  always false)
+- Filesystem: support ceph
+- Filesystem: remove a status file only when OCF_CHECK_LEVEL is
+  set to 20
+- IPaddr: add back the local_start/stop_script code
+- IPaddr: remove colon at the end of the interface name
+- IPv6addr: always use the provided nic and cidr_netmask when
+  specified
+- IPv6addr: handle a link-local address properly in send_ua
+- iscsi: do not rely on iscsid.startup being set correctly
+  (bnc#751783)
+- iscsi: proceed if iscsid is not running if iscsid.startup is
+  present in iscsid.conf
+- iSCSILogicalUnit: fix default for scsi_sn
+- iSCSITarget: treat an empty "implementation" parameter
+  specially
+- jboss: add the java_opts parameter for java options
+- ldirectord: precedence error with perl v5.8.8 in IPv6 code
+- LVM: drop vgck(8) from monitor
+- LVM: force dmevent monitoring for clones
+- LVM: use ls instead of vgdisplay in status
+- lxc: fix LXC_status to work with lxc-0.7.5 or later
+- mysql: improve replication support
+- mysql: check mysql status more thoroughly before stopping
+- mysql: fix validation return codes
+- mysql: support 5.5 slave status message format
+- nfsserver: Support of multiple IP addresses (bnc#684143)
+- nfsserver: don't run sm-notify in foreground (bnc#759616)
+- ocf-shellfuncs: fix loglevel variable scope in ha_log
+- ocft: new tests for named, IPv6addr, oracle, Xinetd
+- ocft: several improvements
+- oracle: improve managing IPC objects
+- oracle: improve matching instance specific files and processes
+- pgsql: support for replication
+- postfix: multiple fixes
+- Raid1: support for multiple MD arrays, as specified in raidconf
+- SAPDatabase: add support for Sybase ASE and SAP HANA database
+- SAPDatabase: correcting the unique values of RAs parameters
+- SAPDatabase: replace method for checking responsiveness of
+  saphostexec
+- SAPDatabase: version 2.00 make use of saphostagent
+- SAPInstance : correcting the unique values of RAs parameters
+- slapd: always set the exit code correctly in monitor
+- tomcat: remove pidfile before start, it may prevent some tomcat
+  releases from starting
+- VirtualDomain: add a functionality that modifies utilization of
+  resource automatically
+- VirtualDomain: if the configuration file is missing on stop
+  exit with success
+- VirtualDomain: honor virsh "in shutdown" state
+- Xen: add support for HVM ACPI graceful shutdown
+- Xen: wait in migrate_from for the migration to finish instead
+  of bailing out immediately
+- Tools: findif: Use most specific matching route (bnc#740738)
+- Tools: send_arp.libnet: fix for big endian platforms
+  (bnc#721334)
+- doc: add the RA developer's guide
+
+* Wed Jun 29 2011 Dejan Muhamedagic <dejan at suse.de> and others
+- stable release 3.9.2
+- ethermon: new resource agent
+- iscsi: fix regression in 3.9.1 for open-iscsi version 2.0-872 (lf#2562)
+- pgsql: fix regression in 3.9.1 in directories on probes
+- VirtualDomain: if there's no config exit on stop with success
+- doc: add sfex_init(8) man page
+* Wed Jun 15 2011 Dejan Muhamedagic <dejan at suse.de> and others
+- stable release 3.9.1
+- ocf-tester: tolerate OCF_ERR_INSTALLED on probes and missing binaries
+- pgsql: improve configuration check and probe handling
+* Wed Jun 01 2011 Dejan Muhamedagic <dejan at suse.de> and others
+- release candidate 3.9.1 rc1
+- first release since establishing joined repository with RHCS agents
+- build: new spec file and autoconf to support both agents' sets
+- build: use ./configure --with-ras-set=linux-ha to configure for
+  heartbeat RA set
+- build: create compatibility symlinks in autofoo not in spec
+- build: GNUmakefile removed
+- lxc: new RA to manage lxc linux containers
+- symlink: new RA to manage symbolic links
+- db2: new implementation with master/slave mode
+- oracle: improve oracle process list test (bnc#673027)
+- exportfs: backup and restore rmtab to ensure smooth client
+  failover on node failures
+- CTDB: Allow stop to succeed when using pkill on ctdbd (bnc#695829)
+- mysql: --skip-slave-start option is default now
+- mysql: set connect timeout to 10 seconds rather than 1 second
+- mysql: keep replication state (prevents data loss on master reset)
+- mysql: don't rely on state information from pacemaker, but
+  check if the instance is in the read-only mode
+- mysql: if test parameters are all set, assume OCF_CHECK_LEVEL=10
+- mysql: support for master/slave for more than two nodes
+- mysql: don't wait for replication to finish, when not replicating
+- mysql: store replication state in separate attributes for each master
+- VirtualDomain: correctly create migration URI when target is an FQDN
+- VirtualDomain: properly wait until domain_name is non-empty
+- ldirectord: add a support of "netmask" directive for IPv6
+- ldirectord: fix fwmark behavior for IPv6
+- ldirectord: ignore children in Net::DNS
+- iscsi: add support for open-iscsi version 2.0-872 (lf#2562)
+- postfix: issue error if 'postfix abort' failed
+- postfix: improve exit codes on installation problems
+- postfix: use monitor to test if postfix works after the start action
+- ocft: fix make command for compatibility with mawk/Debian (lf#2600)
+- ocft: test case for pgsql
+- ocft: test case for postfix
+- ocft: test case for iscsi
+- doc: improve man pages output
+- doc: add examples for master/slave resource agents
+
+* Wed Feb 16 2011 Dejan Muhamedagic <dejan at suse.de> and others
+- stable release 1.0.4
+- ocft: testcases for db2, LVM, and Filesystem
+* Fri Feb 11 2011 Dejan Muhamedagic <dejan at suse.de> and others
+- release candidate 1.0.4
+- add GPLv3 license file (bnc#655700)
+- ocf-shellfuncs: allow ocf_run to return the actual exit code
+- ocf-shellfuncs: handle properly syslog facility set to none (bnc#621818)
+- ocf-shellfuncs: correctly identify root by id only (bnc#602312)
+- RA: add OCF_ROOT/lib/heartbeat directory (development)
+- RA: set the HA_RSCTMP directory to /var/run/resource-agents (lf#2378)
+- build: install jboss
+- conntrackd: new RA
+- exportfs: new RA
+- nginx: new RA
+- fio: new RA for IO load simulation
+- Filesystem: allow cloning of some filesystems as read-only (lf#2440)
+- Filesystem: add fast_stop parameter (lf#2402)
+- Filesystem: Clarify metadata and improve non-clone warning
+- Filesystem: new run_fsck parameter
+- LVM: add partial_activation parameter (lf#2490)
+- IPaddr2: fix reference to Infiniband arping binary (bnc#668447)
+- IPaddr2: optionally flush kernel routing table on interface stop
+- IPaddr2: exit with the right code when not properly configured
+- IPaddr2: exit early and with the right code if the ip parameter is not set
+- IPaddr2: unique_clone_address should work without CIP (lf#2442)
+- IPaddr: return the correct code if interface delete failed
+- IPv6addr: allow link-local addresses in case the interface name is provided
+- IPv6addr: interface index in /proc/net/if_inet6 may be longer than 2
+  chars (lf#2462)
+- IPsrcaddr: exit with the right code when not properly configured
+- IPsrcaddr: add the cidr_netmask parameter
+- Tools: findif: differentiate between error conditions
+- nfsserver: fix the default string for the notification parameter
+- nfsserver: don't use -v in the notify cmd with rpc.statd
+- iSCSITarget: fix race for target IDs when using IET (lf#2432)
+- iSCSITarget: follow changed IET access policy
+- Raid1: Support attempting to re-add mirrors on deep monitor action
+  (bnc#619121)
+- Raid1: Fix graceful stop code path
+- Raid1: Handle stop for failed arrays properly (bnc#618775)
+- sfex: output log messages also to stderr in sfex_init
+- sfex: add the sfex_stat command
+- sfex: wait in the start and stop actions until sfex_daemon starts/exits
+- Xen: implement stop of a migrating domain (bnc#656227)
+- Xen: check the allow_mem_management boolean properly (bnc#637525)
+- Xen: Always run destroy in stop sequence.
+- Xen: use xen-list command for status check if available (bnc#628735)
+- Xen: use xen-destroy for stop, if available.
+- Xen: Allow node configurable attribute to specify which IP to 
+  use for live migration (bnc#628735)
+- VirtualDomain: fix spurious stop failures
+- VirtualDomain: don't timeout in stop before escalating to "forced stop"
+- ManageVE: add migration capability
+- MailTo: don't check if user exists for email address (might be an
+  alias or remote)
+- CTDB: Remove hard-coded timeout on start op
+- CTDB: Don't manage Samba and Winbind by default
+- CTDB: Deprecate (and make optional) smb_private_dir param (bnc#623788)
+- tomcat: Ensure name of tomcat resource is only used on start operation
+  and expose JAVA_OPTS variable for use
+- tomcat: Fix to ensure default OCF_RESKEY_xx values are observed
+- tomcat: Add CATALINA_BASE parameter, defaults to CATALINA_HOME,
+  permits multiple tomcat instances
+- tomcat: Use Tomcat stop TIMEOUT -force to improve stop
+- Dummy: migrate_from/to: correct OCF_RESKEY_CRM_meta_migrate_xxx
+  variable names
+- Dummy: make method reload work
+- anything: add the workdir parameter
+- mysql: clone and master-slave functionality
+- mysql: add replication monitoring
+- mysql: check for write permissions after creating pid and socket directory
+- mysql: make client binary path configurable
+- pgsql: cd to pgdata before running commands (fixes permission error)
+- pgsql: add optional username, password, and sqlcode parameters for monitor
+- pgsql: add new "config" parameter
+- pgsql: properly implement pghost parameter
+- pgsql: socketdir parameter to manage non-default UNIX socket directories
+- oracle: reduce output from sqlplus to the last line for queries (bnc#567815)
+- db2: Replace call to db2_local_ps with db2nps
+- db2: guard against a hanging db2stop by spawning this into the
+  background. Use db2_kill after grace period.
+- db2: add multi partition support
+- db2: improve behaviour on probes
+- db2: support for v9.x instances (bnc#608952)
+- SAPDatabase,SAPInstance: improve LD_LIBRARY_PATH processing (bnc#640026)
+- SAPInstance: prevent premature expansion of [:upper:] [:lower:] when
+  producing sidadm uid
+- SAPInstance: Moved testing of SAP profile directory and START profile
+  to a later stage (only when needed), for more robustness
+- SAPInstance: fix return codes in probes
+- SAPInstance: New parameter: SHUTDOWN_METHOD
+- SAPInstance: ensure enqueue failover in monitor_clone on process
+  failure
+- SAPInstance: don't rely on op target rc when monitoring clones (lf#2371)
+- SAPDatabase: prevent premature expansion of [:upper:] and [:lower:]
+  when producing sidadm/orasid/db2sid uids
+- SAPdatabase: Changed Oracle recovery method from "recover automatic
+  database" to "end backup"
+- SAPDatabase: Adapt process search pattern for DB/2 9.5
+- SAPDatabase: start listener only if database processes are found
+- SAPDatabase: avoid continuous output to syslog in monitor with SAP
+  7.20 and J2EE_ONLY=1
+- ldirectord: http: connect to server instead of protocol (Debian#594958)
+- ldirectord: add implicit support for submission RFC4409
+- ldirectord: example configuration for a submission virtual service
+- ldirectord: Shutdown write-side of client connection after writing has
+  finished
+- ldirectord: port number mismatch of imaps and pops
+- ldirectord: Oracle compatibility
+- ldirectord: don't exit on timeout in HTTP/HTTPS check
+- ldirectord: allow underscore in service name
+- ldirectord: use $1 instead of \1 in pattern replace (bnc#605086)
+- Tools: ocf-tester: Extend to cover initial probe (monitor_0) test.
+- Tools: ocf-tester: set and export some common meta variables (lf#2524)
+- Tools: ocf-tester: meta-data also should never be affected by missing
+  binaries.
+- Tools: ocf-tester: show output from the agent in case of error
+
+* Tue Apr 13 2010 Dejan Muhamedagic <dejan at suse.de> and others
+- stable release 1.0.3
+- meta-data: improve timeouts in most resource agents (reduce the number of warnings by the shell)
+- RA: log messages to stderr if attached to a terminal
+- ocf-shellfuncs: tests to check for clone/ms resources
+- ocf-shellfuncs: don't output to stderr if using syslog (prevents double logging from the RA and lrmd)
+- make sure that OCF_RESKEY_CRM_meta_interval is always defined (lf#2284)
+- ocft: new RA test suite
+- VirtualDomain: bail out early if config file can't be read
+  during probe (nbc#593988)
+- VirtualDomain: spin on define until we definitely have a domain name
+- VirtualDomain: fix incorrect use of __OCF_ACTION (the stop operation may timeout otherwise)
+- Filesystem: prefer /proc/mounts to /etc/mtab for non-bind mounts (lf#2388)
+- IPaddr2: don't bring the interface down on stop (otherwise IPv6 addresses may be removed)
+- oracle/oralsnr: improve exit codes if the environment isn't valid
+- oracle/oralsnr: improve logging
+- Route: don't assume that OCF_RESKEY_CRM_meta_clone_node_max is set to a number (lf#2375)
+- Route: add route table parameter (lf#2335)
+- sfex: don't use pid file (lf#2363,bnc#585416)
+- SFEX daemon: fix logging
+- ldirectord: fix the configfile default (bnc#589457)
+- drbd: fix metadata (bnc#588684)
+- IPsrcaddr: modify the interface route (lf#2367)
+- ldirectord: Allow multiple email addresses (lf#2168)
+- vmware: fix set_environment() invocation (lf#2342)
+- vmware: updated to version 0.2
+- apache: return the right exit code from monitor (bnc#578628)
+- iSCSILogicalUnit: fix monitor for STGT
+
+* Mon Feb 01 2010 Dejan Muhamedagic <dejan at suse.de> and others
+- stable release 1.0.2
+- EvmsSCC, Evmsd, LinuxSCSI, drbd, pingd: marked as deprecated (lf#2244)
+- CTDB: new resource agent for clustered samba
+- postfix: new resource agent
+- proftpd: new resource agent
+- AoEtarget: new resource agent to export ATA-over-Ethernet (AoE) targets
+- Squid: new resource agent
+- VirtualDomain: new resource agent (manage virtual domains using libvirt/virsh)
+- anything: new resource agent for arbitrary daemons
+- mysql-proxy: new resource agent
+- iSCSITarget/iSCSILogicalUnit: two new resource agents
+- portblock: fast reconnect/tickle ACK (new feature)
+- IPv6addr: new nic and cidr_netmask parameters
+- mysql-proxy: log_level and keepalive parameters
+- Filesystem: implement deep monitor operation
+- apache: monitor operation of depth 10 for web applications (lf#2234)
+- SAPDatabase + SAPInstance: New versions from SAP
+- CTDB: auto-generate cluster-specific part of smb.conf (lf#2308)
+- ClusterMon: don't fail in stop if the process is missing (bnc#569957)
+- Filesystem: allow configuring smbfs mounts as clones
+- IPaddr2: CLUSTERIP/iptables rule not always inserted on failed monitor (lf#2281)
+- IPaddr2: behave if the interface is down (lf#2147)
+- IPaddr2: check binaries when it makes sense
+- IPaddr2: fix invalid default value for OCF_RESKEY_clusterip_hash (bnc#553753)
+- IPaddr2: include netmask in search for the right interface
+- IPaddr2: remove all colons from the mac address before passing it to send_arp (lf#2165)
+- IPsrcaddr: replace 0/0 with proper ip prefix
+- IPv6addr: recognize network masks properly
+- IPv6addr: supply checksum for ICMPv6 packets
+- IPv6addr: ifdef out the ip offset hack for libnet v1.1.4 (lf#2034)
+- IPv6addr: supply checksum for ICMPv6 packets
+- LVM: Make monitor operation quiet in logs (bnc#546353)
+- MailTo: Provide a default for MAILCMD (bnc#534803, bnc#556366)
+- MailTo: allow multiple word subject line
+- Raid1: improve monitor function (bnc#546551)
+- Route: improve validate (lf#2232)
+- Squid: make the regexp match more precisely output of netstat
+- VIParip: Pathname needed to be configurable (lf#1331)
+- VirtualDomain: avoid needlessly invoking "virsh define"
+- VirtualDomain: destroy domain shortly before timeout expiry
+- VirtualDomain: fix forceful stop (lf#2283)
+- VirtualDomain: loop on status if libvirtd is unreachable
+- Xen: Remove instance_attribute "allow_migrate" (bnc#539968)
+- apache: make sure that proxies are not used for monitor
+- iSCSILogicalUnit: add support for SCSI ID, SCSI SN, Vendor ID, and Product ID
+- iSCSILogicalUnit: add support for per-LU parameters
+- iSCSILogicalUnit: set default for SCSI SN, truncate SCSI ID default to 24 bytes
+- iSCSILogicalUnit: use a 16-byte default SCSI ID
+- iSCSITarget, iSCSILogicalUnit: add support for tgt
+- iSCSITarget: reintroduce "tid" parameter
+- iSCSITarget, iSCSILogicalUnit: identify targets by IQN, not by tid
+- iSCSITarget, iSCSILogicalUnit: support LIO
+- iSCSITarget: add support for CHAP authentication
+- iSCSITarget: add support for restricting target access
+- iSCSITarget: be more persistent deleting targets on stop
+- include ldirectord (formerly known as heartbeat-ldirectord)
+- iscsi: replace wrong variable reference (bnc#499291)
+- jboss: Added JBoss support
+- ldirectord: fix setting defaults for configfile and ldirectord (lf#2328)
+- ldirectord: fix various bugs in OCF RA (lf#1949)
+- mysql: escalate stop to KILL if regular shutdown doesn't work
+- mysql: handle monitor and stop properly on invalid environment
+- nfsserver: use default values (lf#2321)
+- nfsserver: validate should not check if nfs_shared_infodir exists (lf#2219)
+- nfsserver: use check_binary properly in validate (lf#2211)
+- nfsserver: exit properly in nfsserver_validate (lf#2173)
+- oracle/oralsnr: export variables properly
+- oracle: drop spurious output from sqlplus
+- pgsql: remove the previous backup_label if it exists
+- portblock: add per-IP filtering capability
+- portblock: fix invalid exit codes on monitor
+- postfix: fix double stop
+- scsi2reservation: fix wrong logic in check for scsi_reserve
+- vmware: make meta-data work and several cleanups (lf#2212)
+- shellfuncs: make the mktemp wrappers work
+- ocf-shellfuncs: add mercurial repository version information
+- ocf-shellfuncs: add ocf_is_probe function
+- doc: add resource agents' man pages including examples
+
+* Thu Oct 23 2008 Lars Marowsky-Bree <lmb at suse.de> and MANY others
+- beta release 2.99.2
+- LVM: stop correctly in case vol group does not exist
+
+* Tue Sep 23 2008 Lars Marowsky-Bree <lmb at suse.de> and MANY others
+- beta release 2.99.1
+
+* Tue Aug 19 2008 Andrew Beekhof <abeekhof at suse.de> and MANY others
+- beta release 2.99.0
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..0d75a9a
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,171 @@
+#
+# Copyright (C) 2008 Andrew Beekhof
+# Copyright (C) 2011 Fabio M. Di Nitto
+#
+# 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 aclocal.m4 configure DRF/config-h.in \
+			  missing install-sh autoscan.log configure.scan \
+			  DRF/stamp-h.in libtool.m4 ltdl.m4 libltdl.tar \
+			  compile config.guess config.sub depcomp
+
+SPEC			= $(PACKAGE_NAME).spec
+
+TARFILES		= $(PACKAGE_NAME)-$(VERSION).tar.bz2 \
+			  $(PACKAGE_NAME)-$(VERSION).tar.gz
+
+SUBDIRS =
+
+if BUILD_RGMANAGER
+SUBDIRS += rgmanager
+RGMANAGER = without
+else
+RGMANAGER = with
+endif
+
+if BUILD_LINUX_HA
+SUBDIRS	+= include heartbeat tools ldirectord doc
+LINUX_HA = without
+else
+LINUX_HA = with
+endif
+
+EXTRA_DIST		= autogen.sh .version make/release.mk \
+			  make/git-version-gen make/gitlog-to-changelog \
+			  AUTHORS COPYING COPYING.GPLv3 COPYING.LGPL ChangeLog \
+			  $(SPEC).in
+
+install-exec-local:
+if BUILD_LINUX_HA
+	$(INSTALL) -d -m 1755 $(DESTDIR)$(HA_RSCTMPDIR)
+	$(LN_S) ../../lib/heartbeat/ocf-binaries $(DESTDIR)${OCF_RA_DIR_PREFIX}/heartbeat/.ocf-binaries
+	$(LN_S) ../../lib/heartbeat/ocf-directories $(DESTDIR)${OCF_RA_DIR_PREFIX}/heartbeat/.ocf-directories
+	$(LN_S) ../../lib/heartbeat/ocf-returncodes $(DESTDIR)${OCF_RA_DIR_PREFIX}/heartbeat/.ocf-returncodes
+	$(LN_S) ../../lib/heartbeat/ocf-shellfuncs $(DESTDIR)${OCF_RA_DIR_PREFIX}/heartbeat/.ocf-shellfuncs
+endif
+if BUILD_RGMANAGER
+if BUILD_LINUX_HA
+	$(LN_S) ${CLUSTERDATA} $(DESTDIR)${OCF_RA_DIR_PREFIX}/redhat
+endif
+	$(INSTALL) -d $(DESTDIR)/$(LOGDIR)
+endif
+
+dist-clean-local:
+	rm -f autoconf automake autoheader $(TARFILES)
+
+uninstall-local:
+			rmdir $(DESTDIR)/$(LOGDIR) || :;
+if BUILD_LINUX_HA
+	rm -f $(DESTDIR)${OCF_RA_DIR_PREFIX}/heartbeat/.ocf-binaries
+	rm -f $(DESTDIR)${OCF_RA_DIR_PREFIX}/heartbeat/.ocf-directories
+	rm -f $(DESTDIR)${OCF_RA_DIR_PREFIX}/heartbeat/.ocf-returncodes
+	rm -f $(DESTDIR)${OCF_RA_DIR_PREFIX}/heartbeat/.ocf-shellfuncs
+if BUILD_RGMANAGER
+	rm -f $(DESTDIR)${OCF_RA_DIR_PREFIX}/redhat
+endif
+endif
+
+BUILT_SOURCES = .version
+.version:
+	echo $(VERSION) > $@-t && mv $@-t $@
+
+dist-hook: gen-ChangeLog $(SPEC)
+	echo $(VERSION) > $(distdir)/.tarball-version
+	rm -f $(distdir)/$(SPEC) && \
+		cp $(top_srcdir)/$(SPEC) $(distdir)/$(SPEC)
+
+gen_start_date = 2000-01-01
+.PHONY: gen-ChangeLog
+gen-ChangeLog:
+	if test -d .git; then 						\
+		LC_ALL=C $(top_srcdir)/make/gitlog-to-changelog		\
+			--since=$(gen_start_date) > $(distdir)/cl-t;	\
+		rm -f $(distdir)/ChangeLog.devel;			\
+		mv $(distdir)/cl-t $(distdir)/ChangeLog.devel;		\
+	fi
+
+## make rpm/srpm section.
+$(SPEC): $(SPEC).in
+	rm -f $@-t $@
+	date="$(shell LC_ALL=C date "+%a %b %d %Y")" && \
+	specver="1" && \
+	rcver="" && \
+	dirty="" && \
+	alphatag="" && \
+	numcomm="" && \
+	ver="$(VERSION)" && \
+	if echo $$ver | grep -q -- "-dirty$$"; then \
+		dirty="dirty" && \
+		echo VERSION IS DIRTY && \
+		ver=`echo $$ver | sed -e "s/-dirty$$//"`; \
+	fi && \
+	echo $$ver && \
+	if echo $$ver | grep -q -- "-"; then \
+		alphatag=`echo $$ver | sed -e "s/.*-//"` && \
+		echo VERSION HAS ALPHATAG && \
+		ver=`echo $$ver | sed -e "s/-.*//"`; \
+	fi && \
+	echo $$ver && \
+	if [ -n "$$alphatag" ]; then \
+		echo VERSION HAS NUMCOMMITS && \
+		numcomm=`echo $$ver | sed -e 's/.*\.//'` && \
+		ver=`echo $$ver | sed -e 's/.'$$numcomm'$$//'`; \
+	fi && \
+	if echo $$ver | grep -q "\.[[:digit:]]rc[[:digit:]]"; then \
+		rpmver=`echo $$ver | sed -e "s/rc[[:digit:]].*//g"` && \
+		rcver=`echo $$ver | sed -e "s/.*\(rc[[:digit:]]\).*/\1/g"` && \
+		specver="0"; \
+	else \
+		rpmver=$$ver; \
+	fi && \
+	echo $$rpmver $$rcver && \
+	sed \
+		-e "s#@version@#$$rpmver#g" \
+		-e "s#@alphatag@#$$alphatag#g" \
+		-e "s#@numcomm@#$$numcomm#g" \
+		-e "s#@dirty@#$$dirty#g" \
+		-e "s#@date@#$$date#g" \
+		-e "s#@specver@#$$specver#g" \
+		-e "s#@rcver@#$$rcver#g" \
+		-e "s#@rgmanager@#$(RGMANAGER)#g" \
+		-e "s#@linux-ha@#$(LINUX_HA)#g" \
+	$< > $@-t; \
+	if [ -z "$$dirty" ]; then sed -i -e "s#%glo.*dirty.*##g" $@-t; fi; \
+	if [ -z "$$alphatag" ]; then sed -i -e "s#%glo.*alphatag.*##g" $@-t; fi; \
+	if [ -z "$$numcomm" ]; then sed -i -e "s#%glo.*numcomm.*##g" $@-t; fi; \
+	if [ -z "$$rcver" ]; then sed -i -e "s#%glo.*rcver.*##g" $@-t; fi
+	chmod a-w $@-t
+	mv $@-t $@
+
+$(TARFILES):
+	$(MAKE) dist
+
+RPMBUILDOPTS    = --define "_sourcedir $(abs_builddir)" \
+		  --define "_specdir $(abs_builddir)" \
+		  --define "_builddir $(abs_builddir)" \
+		  --define "_srcrpmdir $(abs_builddir)" \
+		  --define "_rpmdir $(abs_builddir)"
+
+srpm: clean
+	$(MAKE) $(SPEC) $(TARFILES)
+	rpmbuild $(RPMBUILDOPTS) --nodeps -bs $(SPEC)
+
+rpm: clean
+	$(MAKE) $(SPEC) $(TARFILES)
+	rpmbuild $(RPMBUILDOPTS) -ba $(SPEC)
+
+clean-generic:
+	rm -rf $(SPEC) $(TARFILES)
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644
index 0000000..09d1f1c
--- /dev/null
+++ b/README
@@ -0,0 +1,12 @@
+This repository contains resource agents (RAs) compliant
+with the Open Cluster Framework (OCF) specification.
+
+These resource agents are used by two cluster resource
+management implementations:
+
+- Pacemaker
+- rgmanager
+
+More information about OCF resource agents is available
+in the OCF Resource Agent Developer's guide, in the
+doc/dev-guides subdirectory.
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..a10bf96
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+autoreconf -i -v && echo Now run ./configure and make
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..9e55960
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,904 @@
+dnl
+dnl autoconf for Agents
+dnl
+dnl License: GNU General Public License (GPL)
+
+dnl ===============================================
+dnl Bootstrap 
+dnl ===============================================
+AC_PREREQ(2.63)
+
+dnl Suggested structure:
+dnl     information on the package
+dnl     checks for programs
+dnl     checks for libraries
+dnl     checks for header files
+dnl     checks for types
+dnl     checks for structures
+dnl     checks for compiler characteristics
+dnl     checks for library functions
+dnl     checks for system services
+
+AC_INIT([resource-agents], 
+	m4_esyscmd([make/git-version-gen .tarball-version]),
+	[to_be_defined at foobar.org])
+
+AC_USE_SYSTEM_EXTENSIONS
+
+CRM_DTD_VERSION="1.0"
+
+PKG_FEATURES=""
+
+AC_CONFIG_AUX_DIR(.)
+AC_CANONICAL_HOST
+
+dnl Where #defines go (e.g. `AC_CHECK_HEADERS' below)
+dnl
+dnl Internal header: include/config.h
+dnl   - Contains ALL defines
+dnl   - include/config.h.in is generated automatically by autoheader
+dnl   - NOT to be included in any header files except lha_internal.h
+dnl     (which is also not to be included in any other header files)
+dnl
+dnl External header: include/agent_config.h
+dnl   - Contains a subset of defines checked here
+dnl   - Manually edit include/agent_config.h.in to have configure include new defines
+dnl   - Should not include HAVE_* defines
+dnl   - Safe to include anywhere
+AM_CONFIG_HEADER(include/config.h include/agent_config.h)
+ALL_LINGUAS="en fr"
+
+AC_ARG_WITH(version,
+    [  --with-version=version   Override package version (if you're a packager needing to pretend) ],
+    [ PACKAGE_VERSION="$withval" ])
+
+AC_ARG_WITH(pkg-name,
+    [  --with-pkg-name=name     Override package name (if you're a packager needing to pretend) ],
+    [ PACKAGE_NAME="$withval" ])
+
+dnl 
+dnl AM_INIT_AUTOMAKE([1.11.1 foreign dist-bzip2 dist-xz])
+dnl
+
+AM_INIT_AUTOMAKE([1.10.1 foreign dist-bzip2])
+
+AC_DEFINE_UNQUOTED(AGENTS_VERSION, "$PACKAGE_VERSION", Current agents version)
+
+CC_IN_CONFIGURE=yes
+export CC_IN_CONFIGURE
+
+LDD=ldd
+
+dnl ========================================================================
+dnl Compiler characteristics
+dnl ========================================================================
+
+# check stolen from gnulib/m4/gnu-make.m4
+if ! ${MAKE-make} --version /cannot/make/this >/dev/null 2>&1; then
+	AC_MSG_ERROR([you don't seem to have GNU make; it is required])
+fi
+
+AC_PROG_CC dnl Can force other with environment variable "CC".
+AM_PROG_CC_C_O
+AC_PROG_CC_STDC
+AC_PROG_AWK
+AC_PROG_LN_S
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
+AC_C_STRINGIZE
+AC_C_INLINE
+
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UID_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT8_T
+AC_TYPE_UINT32_T
+
+AC_CHECK_SIZEOF(char)
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(long long)
+AC_STRUCT_TIMEZONE
+
+dnl ===============================================
+dnl Helpers 
+dnl ===============================================
+cc_supports_flag() {
+	local CPPFLAGS="$@"
+	AC_MSG_CHECKING(whether $CC supports "$@")
+	AC_PREPROC_IFELSE([AC_LANG_PROGRAM([])],
+			  [RC=0; AC_MSG_RESULT([yes])],
+			  [RC=1; AC_MSG_RESULT([no])])
+	return $RC
+}
+
+extract_header_define() {
+	  AC_MSG_CHECKING(for $2 in $1)
+	  Cfile=$srcdir/extract_define.$2.${$}
+	  printf "#include <stdio.h>\n" > ${Cfile}.c
+	  printf "#include <%s>\n" $1 >> ${Cfile}.c
+	  printf "int main(int argc, char **argv) { printf(\"%%s\", %s); return 0; }\n" $2 >> ${Cfile}.c
+	  $CC $CFLAGS ${Cfile}.c -o ${Cfile}
+	  value=`${Cfile}`
+	  AC_MSG_RESULT($value)
+	  printf $value
+	  rm -f ${Cfile}.c ${Cfile}
+	}
+
+AC_MSG_NOTICE(Sanitizing prefix: ${prefix})
+case $prefix in
+  NONE)
+	prefix=/usr
+	dnl Fix default variables - "prefix" variable if not specified
+	if test "$localstatedir" = "\${prefix}/var"; then
+		localstatedir="/var"
+	fi
+	if test "$sysconfdir" = "\${prefix}/etc"; then
+		sysconfdir="/etc"
+	fi
+	;;
+esac
+
+dnl ===============================================
+dnl Configure Options
+dnl ===============================================
+
+dnl Some systems, like Solaris require a custom package name
+AC_ARG_WITH(pkgname,
+    [  --with-pkgname=name     name for pkg (typically for Solaris) ],
+    [ PKGNAME="$withval" ],
+    [ PKGNAME="LXHAhb" ],
+  )
+AC_SUBST(PKGNAME)
+
+AC_ARG_ENABLE([ansi],
+[  --enable-ansi force GCC to compile to ANSI/ANSI standard for older compilers.
+     [default=yes]])
+
+AC_ARG_ENABLE([fatal-warnings],
+[  --enable-fatal-warnings very pedantic and fatal warnings for gcc
+     [default=yes]])
+
+INITDIR=""
+AC_ARG_WITH(initdir,
+    [  --with-initdir=DIR      directory for init (rc) scripts [${INITDIR}]],
+    [ INITDIR="$withval" ])
+
+OCF_ROOT_DIR="/usr/lib/ocf"
+AC_ARG_WITH(ocf-root,
+    [  --with-ocf-root=DIR      directory for OCF scripts [${OCF_ROOT_DIR}]],
+    [ if test x"$withval" = xprefix; then OCF_ROOT_DIR=${prefix}; else
+	 OCF_ROOT_DIR="$withval"; fi ])
+HA_RSCTMPDIR=${localstatedir}/run/resource-agents
+AC_ARG_WITH(rsctmpdir,
+    [  --with-rsctmpdir=DIR      directory for resource agents state files [${HA_RSCTMPDIR}]],
+    [ if test x"$withval" = xprefix; then HA_RSCTMPDIR=${prefix}; else
+	 HA_RSCTMPDIR="$withval"; fi ])
+
+AC_ARG_ENABLE([libnet],
+ [  --enable-libnet 	Use libnet for ARP based funcationality, [default=try]], 
+ [enable_libnet="$enableval"], [enable_libnet=try])
+
+BUILD_RGMANAGER=0
+BUILD_LINUX_HA=0
+
+RASSET=all
+AC_ARG_WITH(ras-set,
+    [  --with-ras-set=SET     build/install only linux-ha or rgmanager resource-agents [default: all]],
+    [ RASSET="$withval" ])
+
+if test x$RASSET = xyes || test x$RASSET = xall ; then
+	BUILD_RGMANAGER=1
+	BUILD_LINUX_HA=1
+fi
+
+if test x$RASSET = xlinux-ha; then
+	BUILD_LINUX_HA=1
+fi
+
+if test x$RASSET = xrgmanager; then
+	BUILD_RGMANAGER=1
+fi
+
+if test $BUILD_LINUX_HA -eq 0 && test $BUILD_RGMANAGER -eq 0; then
+	AC_MSG_ERROR([Are you really sure you want this package?])
+	exit 1
+fi
+
+AM_CONDITIONAL(BUILD_LINUX_HA, test $BUILD_LINUX_HA -eq 1)
+AM_CONDITIONAL(BUILD_RGMANAGER, test $BUILD_RGMANAGER -eq 1)
+
+dnl ===============================================
+dnl General Processing
+dnl ===============================================
+
+echo Our Host OS: $host_os/$host
+
+AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix})
+case $exec_prefix in
+  dnl For consistency with Heartbeat, map NONE->$prefix
+  NONE)	  exec_prefix=$prefix;;
+  prefix) exec_prefix=$prefix;;
+esac
+
+AC_MSG_NOTICE(Sanitizing INITDIR: ${INITDIR})
+case $INITDIR in
+  prefix) INITDIR=$prefix;;
+  "")
+    AC_MSG_CHECKING(which init (rc) directory to use)
+      for initdir in /etc/init.d /etc/rc.d/init.d /sbin/init.d	\
+	   /usr/local/etc/rc.d /etc/rc.d
+      do
+        if
+          test -d $initdir
+        then
+          INITDIR=$initdir
+          break
+        fi
+      done
+      if 
+      	 test -z $INITDIR
+      then
+          INITDIR=${sysconfdir}/init.d
+      fi
+      AC_MSG_RESULT($INITDIR);;
+esac
+AC_SUBST(INITDIR)
+
+if test "${prefix}" = "/usr"; then
+ INITDIRPREFIX="$INITDIR" 
+else
+ INITDIRPREFIX="${prefix}/$INITDIR"
+fi
+
+AC_SUBST(INITDIRPREFIX)
+
+AC_MSG_NOTICE(Sanitizing libdir: ${libdir})
+case $libdir in
+  dnl For consistency with Heartbeat, map NONE->$prefix
+  *prefix*|NONE)
+    AC_MSG_CHECKING(which lib directory to use)
+    for aDir in lib64 lib
+    do
+      trydir="${exec_prefix}/${aDir}"
+      if
+        test -d ${trydir}
+      then
+        libdir=${trydir}
+        break
+      fi
+    done
+    AC_MSG_RESULT($libdir);
+    ;;
+esac
+
+dnl Expand autoconf variables so that we dont end up with '${prefix}' 
+dnl in #defines and python scripts
+dnl NOTE: Autoconf deliberately leaves them unexpanded to allow
+dnl    make exec_prefix=/foo install
+dnl No longer being able to do this seems like no great loss to me...
+
+eval prefix="`eval echo ${prefix}`"
+eval exec_prefix="`eval echo ${exec_prefix}`"
+eval bindir="`eval echo ${bindir}`"
+eval sbindir="`eval echo ${sbindir}`"
+eval libexecdir="`eval echo ${libexecdir}`"
+eval datadir="`eval echo ${datadir}`"
+eval sysconfdir="`eval echo ${sysconfdir}`"
+eval sharedstatedir="`eval echo ${sharedstatedir}`"
+eval localstatedir="`eval echo ${localstatedir}`"
+eval libdir="`eval echo ${libdir}`"
+eval includedir="`eval echo ${includedir}`"
+eval oldincludedir="`eval echo ${oldincludedir}`"
+eval infodir="`eval echo ${infodir}`"
+eval mandir="`eval echo ${mandir}`"
+
+dnl docdir is a recent addition to autotools
+eval docdir="`eval echo ${docdir}`"
+if test "x$docdir" = "x"; then
+   docdir="`eval echo ${datadir}/doc`"
+fi
+AC_SUBST(docdir)
+
+dnl Home-grown variables
+eval INITDIR="${INITDIR}"
+
+for j in prefix exec_prefix bindir sbindir libexecdir datadir sysconfdir \
+    sharedstatedir localstatedir libdir includedir oldincludedir infodir \
+    mandir INITDIR docdir
+do 
+  dirname=`eval echo '${'${j}'}'`
+  if
+    test ! -d "$dirname"
+  then
+    AC_MSG_WARN([$j directory ($dirname) does not exist!])
+  fi
+done
+
+dnl This OS-based decision-making is poor autotools practice;
+dnl feature-based mechanisms are strongly preferred.
+dnl
+dnl So keep this section to a bare minimum; regard as a "necessary evil". 
+
+REBOOT_OPTIONS="-f"
+POWEROFF_OPTIONS="-f"
+
+case "$host_os" in
+*bsd*)		LIBS="-L/usr/local/lib"
+		CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+		;;
+*solaris*)
+		REBOOT_OPTIONS="-n"
+		POWEROFF_OPTIONS="-n"
+		;;
+*linux*)	
+		AC_DEFINE_UNQUOTED(ON_LINUX, 1, Compiling for Linux platform)
+		POWEROFF_OPTIONS="-nf"
+		REBOOT_OPTIONS="-nf"
+ 		;;
+darwin*)	
+		AC_DEFINE_UNQUOTED(ON_DARWIN, 1, Compiling for Darwin platform)
+  		LIBS="$LIBS -L${prefix}/lib"
+  		CFLAGS="$CFLAGS -I${prefix}/include"
+		;;
+esac
+
+AC_DEFINE_UNQUOTED(HA_LOG_FACILITY, LOG_DAEMON, Default logging facility)
+
+AC_MSG_NOTICE(Host CPU: $host_cpu)
+
+case "$host_cpu" in
+  ppc64|powerpc64)
+    case $CFLAGS in
+     *powerpc64*)			;;
+     *)	if test "$GCC" = yes; then
+	  CFLAGS="$CFLAGS -m64"
+	fi				;;
+    esac
+esac
+
+AC_MSG_CHECKING(which format is needed to print uint64_t)
+case "$host_cpu" in
+  s390x)U64T="%lu";;
+  *64*) U64T="%lu";;
+  *)    U64T="%llu";;
+esac
+AC_MSG_RESULT($U64T)
+AC_DEFINE_UNQUOTED(U64T, "$U64T", Correct printf format for logging uint64_t)
+
+
+dnl Variables needed for substitution
+
+AC_CHECK_HEADERS(heartbeat/glue_config.h)
+
+if test "$ac_cv_header_heartbeat_glue_config_h" = "yes"; then
+  OCF_ROOT_DIR=`extract_header_define heartbeat/glue_config.h OCF_ROOT_DIR`
+else
+  enable_libnet=no
+fi
+
+AC_DEFINE_UNQUOTED(OCF_ROOT_DIR,"$OCF_ROOT_DIR", OCF root directory - specified by the OCF standard)
+AC_SUBST(OCF_ROOT_DIR)
+
+GLUE_STATE_DIR=${localstatedir}/run
+AC_DEFINE_UNQUOTED(GLUE_STATE_DIR,"$GLUE_STATE_DIR", Where to keep state files and sockets)
+AC_SUBST(GLUE_STATE_DIR)
+
+AC_DEFINE_UNQUOTED(HA_VARRUNDIR,"$GLUE_STATE_DIR", Where Heartbeat keeps state files and sockets - old name)
+HA_VARRUNDIR="$GLUE_STATE_DIR"
+AC_SUBST(HA_VARRUNDIR)
+
+# Expand $prefix
+eval HA_RSCTMPDIR="`eval echo ${HA_RSCTMPDIR}`"
+AC_DEFINE_UNQUOTED(HA_RSCTMPDIR,"$HA_RSCTMPDIR", Where Resouce agents keep state files)
+AC_SUBST(HA_RSCTMPDIR)
+
+dnl Eventually move out of the heartbeat dir tree and create symlinks when needed
+HA_VARLIBHBDIR=${localstatedir}/lib/heartbeat
+AC_DEFINE_UNQUOTED(HA_VARLIBHBDIR,"$HA_VARLIBHBDIR", Whatever this used to mean)
+AC_SUBST(HA_VARLIBHBDIR)
+
+OCF_RA_DIR="${OCF_ROOT_DIR}/resource.d/"
+AC_DEFINE_UNQUOTED(OCF_RA_DIR,"$OCF_RA_DIR", Location for OCF RAs)
+AC_SUBST(OCF_RA_DIR)
+
+if test "${prefix}" = "/usr"; then
+ OCF_RA_DIR_PREFIX="$OCF_RA_DIR"
+else
+ OCF_RA_DIR_PREFIX="${prefix}/$OCF_RA_DIR"
+fi
+AC_SUBST(OCF_RA_DIR_PREFIX)
+
+OCF_LIB_DIR="${OCF_ROOT_DIR}/lib/"
+AC_DEFINE_UNQUOTED(OCF_LIB_DIR,"$OCF_LIB_DIR", Location for shared code for OCF RAs)
+AC_SUBST(OCF_LIB_DIR)
+
+if test "${prefix}" = "/usr"; then
+ OCF_LIB_DIR_PREFIX="$OCF_LIB_DIR"
+else
+ OCF_LIB_DIR_PREFIX="${prefix}/$OCF_LIB_DIR"
+fi
+AC_SUBST(OCF_LIB_DIR_PREFIX)
+
+dnl ===============================================
+dnl rgmanager ras bits
+dnl ===============================================
+
+LOGDIR=${localstatedir}/log/cluster
+CLUSTERDATA=${datadir}/cluster
+
+AC_SUBST([LOGDIR])
+AC_SUBST([CLUSTERDATA])
+
+dnl ===============================================
+dnl Program Paths
+dnl ===============================================
+
+PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin"
+export PATH
+
+AM_PATH_PYTHON
+AC_CHECK_PROGS(MAKE, gmake make)
+AC_PATH_PROGS(SSH, ssh, /usr/bin/ssh)
+AC_PATH_PROGS(SCP, scp, /usr/bin/scp)
+AC_PATH_PROGS(TAR, tar)
+AC_PATH_PROGS(MD5, md5)
+AC_PATH_PROGS(TEST, test)
+AC_PATH_PROGS(PING, ping, /bin/ping)
+AC_PATH_PROGS(IFCONFIG, ifconfig, /sbin/ifconfig)
+AC_PATH_PROGS(MAILCMD, mailx mail, mail)
+AC_PATH_PROGS(EGREP, egrep)
+AC_PATH_PROGS(PKGCONFIG, pkg-config)
+
+AC_SUBST(MAILCMD)
+AC_SUBST(EGREP)
+AC_SUBST(SHELL)
+AC_SUBST(PING)
+AC_SUBST(TEST)
+
+AC_PATH_PROGS(ROUTE, route)
+AC_DEFINE_UNQUOTED(ROUTE, "$ROUTE", path to route command)
+
+AC_MSG_CHECKING(ifconfig option to list interfaces)
+for IFCONFIG_A_OPT in  "-A" "-a" ""
+do
+  $IFCONFIG $IFCONFIG_A_OPT > /dev/null 2>&1
+  if
+    test "$?" = 0
+  then
+    AC_DEFINE_UNQUOTED(IFCONFIG_A_OPT, "$IFCONFIG_A_OPT", option for ifconfig command)
+    AC_MSG_RESULT($IFCONFIG_A_OPT)
+    break
+  fi
+done
+
+AC_SUBST(IFCONFIG_A_OPT)
+
+if test x"${MAKE}" = x""; then
+   AC_MSG_ERROR(You need (g)make installed in order to build ${PACKAGE})
+fi
+
+dnl ===============================================
+dnl Libraries
+dnl ===============================================
+AC_CHECK_LIB(socket, socket)			
+AC_CHECK_LIB(gnugetopt, getopt_long)		dnl if available
+
+if test x"${PKGCONFIG}" = x""; then
+   AC_MSG_ERROR(You need pkgconfig installed in order to build ${PACKAGE})
+fi
+
+if test "x${enable_thread_safe}" = "xyes"; then
+        GPKGNAME="gthread-2.0"
+else
+        GPKGNAME="glib-2.0"
+fi
+
+if 
+   $PKGCONFIG --exists $GPKGNAME
+then
+	GLIBCONFIG="$PKGCONFIG $GPKGNAME"
+else
+	set -x
+        echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH
+	$PKGCONFIG --exists $GPKGNAME; echo $?
+	$PKGCONFIG --cflags $GPKGNAME; echo $?
+	$PKGCONFIG $GPKGNAME; echo $?
+	set +x
+        
+	AC_MSG_ERROR(You need glib2-devel installed in order to build ${PACKAGE})
+fi
+AC_MSG_RESULT(using $GLIBCONFIG)
+
+if test "X$GLIBCONFIG" != X; then
+	AC_MSG_CHECKING(for special glib includes: )
+	GLIBHEAD=`$GLIBCONFIG --cflags`
+	AC_MSG_RESULT($GLIBHEAD)
+	CPPFLAGS="$CPPFLAGS $GLIBHEAD"
+
+	AC_MSG_CHECKING(for glib library flags)
+	GLIBLIB=`$GLIBCONFIG --libs`
+	AC_MSG_RESULT($GLIBLIB)
+	LIBS="$LIBS $GLIBLIB"
+fi
+
+dnl ========================================================================
+dnl Headers
+dnl ========================================================================
+
+AC_HEADER_STDC
+AC_CHECK_HEADERS(sys/socket.h)
+AC_CHECK_HEADERS(sys/sockio.h)
+AC_CHECK_HEADERS([arpa/inet.h])
+AC_CHECK_HEADERS([fcntl.h])
+AC_CHECK_HEADERS([limits.h])
+AC_CHECK_HEADERS([malloc.h])
+AC_CHECK_HEADERS([netdb.h])
+AC_CHECK_HEADERS([netinet/in.h])
+AC_CHECK_HEADERS([sys/file.h])
+AC_CHECK_HEADERS([sys/ioctl.h])
+AC_CHECK_HEADERS([sys/param.h])
+AC_CHECK_HEADERS([sys/time.h])
+AC_CHECK_HEADERS([syslog.h])
+
+dnl ========================================================================
+dnl Functions
+dnl ========================================================================
+
+AC_FUNC_FORK
+AC_FUNC_STRNLEN
+AC_CHECK_FUNCS([alarm gettimeofday inet_ntoa memset mkdir socket uname])
+AC_CHECK_FUNCS([strcasecmp strchr strdup strerror strrchr strspn strstr strtol strtoul])
+
+AC_PATH_PROGS(REBOOT, reboot, /sbin/reboot)
+AC_SUBST(REBOOT)
+AC_SUBST(REBOOT_OPTIONS)
+AC_DEFINE_UNQUOTED(REBOOT, "$REBOOT", path to the reboot command)
+AC_DEFINE_UNQUOTED(REBOOT_OPTIONS, "$REBOOT_OPTIONS", reboot options)
+
+AC_PATH_PROGS(POWEROFF_CMD, poweroff, /sbin/poweroff)
+AC_SUBST(POWEROFF_CMD)
+AC_SUBST(POWEROFF_OPTIONS)
+AC_DEFINE_UNQUOTED(POWEROFF_CMD, "$POWEROFF_CMD", path to the poweroff command)
+AC_DEFINE_UNQUOTED(POWEROFF_OPTIONS, "$POWEROFF_OPTIONS", poweroff options)
+
+AC_PATH_PROGS(XSLTPROC, xsltproc)
+AM_CONDITIONAL(BUILD_DOC, test "x$XSLTPROC" != "x" )
+if test "x$XSLTPROC" = "x"; then
+   AC_MSG_WARN([xsltproc not installed, unable to (re-)build manual pages])
+fi
+AC_SUBST(XSLTPROC)
+
+AC_PATH_PROGS(POD2MAN, pod2man)
+AM_CONDITIONAL(BUILD_POD_DOC, test "x$POD2MAN" != "x" )
+if test "x$POD2MAN" = "x"; then
+   AC_MSG_WARN([pod2man not installed, unable to (re-)build ldirector manual page])
+fi
+AC_SUBST(POD2MAN)
+
+dnl ========================================================================
+dnl Functions
+dnl ========================================================================
+
+AC_CHECK_FUNCS(getopt, AC_DEFINE(HAVE_DECL_GETOPT,  1, [Have getopt function]))
+
+dnl ========================================================================
+dnl   sfex
+dnl ========================================================================
+
+build_sfex=no
+case $host_os in
+    *Linux*|*linux*) 
+	if test "$ac_cv_header_heartbeat_glue_config_h" = "yes"; then
+	    build_sfex=yes
+	fi
+	;;
+esac
+
+AM_CONDITIONAL(BUILD_SFEX, test "$build_sfex" = "yes" )
+
+
+dnl ========================================================================
+dnl   tickle (needs port to BSD platforms)
+dnl ========================================================================
+
+AC_CHECK_MEMBERS([struct iphdr.saddr],,,[[#include <netinet/ip.h>]])
+AM_CONDITIONAL(BUILD_TICKLE, test "$ac_cv_member_struct_iphdr_saddr" = "yes" )
+
+dnl ========================================================================
+dnl   libnet
+dnl ========================================================================
+
+libnet=""
+libnet_version="none"
+LIBNETLIBS=""
+LIBNETDEFINES=""
+
+AC_MSG_CHECKING(if libnet is required)
+libnet_fatal=$enable_libnet
+case $enable_libnet in
+     no) ;;
+     yes|libnet10|libnet11|10|11) libnet_fatal=yes;;
+     try)
+	case $host_os in
+	     *Linux*|*linux*) libnet_fatal=no;;
+	     *) libnet_fatal=yes;; dnl legacy behavior
+	esac
+	;;
+     *) libnet_fatal=yes; enable_libnet=try;;
+esac
+AC_MSG_RESULT($libnet_fatal)
+
+if test "x$enable_libnet" != "xno"; then
+   AC_PATH_PROGS(LIBNETCONFIG, libnet-config)
+
+   AC_CHECK_LIB(nsl, t_open)			dnl -lnsl
+   AC_CHECK_LIB(socket, socket)			dnl -lsocket
+   AC_CHECK_LIB(net, libnet_get_hwaddr, LIBNETLIBS=" -lnet", [])
+ fi
+ 
+AC_MSG_CHECKING(for libnet)
+if test "x$LIBNETLIBS" != "x" -o "x$enable_libnet" = "xlibnet11"; then
+      LIBNETDEFINES=""
+      if test "$ac_cv_lib_nsl_t_open" = yes; then
+         LIBNETLIBS="-lnsl $LIBNETLIBS"
+      fi
+      if test "$ac_cv_lib_socket_socket" = yes; then
+         LIBNETLIBS="-lsocket $LIBNETLIBS"
+      fi
+
+      libnet=net
+      libnet_version="libnet1.1"
+fi
+
+if test "x$enable_libnet" = "xtry" -o "x$enable_libnet" = "xlibnet10"; then
+   if test "x$LIBNETLIBS" = x -a "x${LIBNETCONFIG}" != "x" ; then
+      LIBNETDEFINES="`$LIBNETCONFIG --defines` `$LIBNETCONFIG --cflags`";
+      LIBNETLIBS="`$LIBNETCONFIG --libs`";
+      libnet_version="libnet1.0 (old)"
+      case $LIBNETLIBS in
+        *-l*)	libnet=`echo $LIBNETLIBS | sed 's%.*-l%%'`;;
+        *)	libnet_version=none;;
+      esac
+
+      CPPFLAGS="$CPPFLAGS $LIBNETDEFINES"
+
+      AC_CHECK_HEADERS(libnet.h)
+      if test "$ac_cv_header_libnet_h" = no; then
+	libnet_version=none
+      fi
+   fi
+fi
+AC_MSG_RESULT(found $libnet_version)
+
+if test "$libnet_version" = none; then
+   LIBNETLIBS=""
+   LIBNETDEFINES=""
+   if test $libnet_fatal = yes; then
+        AC_MSG_ERROR(libnet not found)
+   fi
+
+else
+   AC_CHECK_LIB($libnet,libnet_init,
+      [new_libnet=yes; AC_DEFINE(HAVE_LIBNET_1_1_API, 1, Libnet 1.1 API)],
+      [new_libnet=no; AC_DEFINE(HAVE_LIBNET_1_0_API, 1, Libnet 1.0 API)],$LIBNETLIBS)
+   AC_SUBST(LIBNETLIBS)
+fi
+
+if test "$new_libnet" = yes; then
+   AC_MSG_CHECKING(for libnet API 1.1.4: )
+   save_CFLAGS="$CFLAGS"
+   CFLAGS="$CFLAGS -fgnu89-inline -Wall -Werror"
+   AC_COMPILE_IFELSE([
+	AC_LANG_SOURCE(#include <libnet.h>
+			  int main(){libnet_t *l=NULL; libnet_pblock_record_ip_offset(l, l->total_size); return(0); })],
+      [AC_MSG_RESULT(no)],
+      [AC_DEFINE(HAVE_LIBNET_1_1_4_API, 1, Libnet 1.1.4 API) AC_MSG_RESULT(yes)])
+   CFLAGS="$save_CFLAGS"
+fi
+
+sendarp_linux=0
+case $host_os in
+     *Linux*|*linux*) sendarp_linux=1;;
+esac
+
+AC_SUBST(LIBNETLIBS)
+AC_SUBST(LIBNETDEFINES)
+
+AM_CONDITIONAL(SENDARP_LINUX, test $sendarp_linux = 1 )
+AM_CONDITIONAL(USE_LIBNET, test "x$libnet_version" != "xnone" )
+
+dnl ************************************************************************
+dnl * Check for netinet/icmp6.h to enable the IPv6addr resource agent
+AC_CHECK_HEADERS(netinet/icmp6.h,[],[],[#include <sys/types.h>])
+AM_CONDITIONAL(USE_IPV6ADDR_AGENT, test "$ac_cv_header_netinet_icmp6_h" = yes && test "$ac_cv_header_heartbeat_glue_config_h" = yes)
+AM_CONDITIONAL(IPV6ADDR_COMPATIBLE, test "$ac_cv_header_netinet_icmp6_h" = yes)
+
+dnl ========================================================================
+dnl Compiler flags
+dnl ========================================================================
+
+dnl Make sure that CFLAGS is not exported. If the user did
+dnl not have CFLAGS in their environment then this should have
+dnl no effect. However if CFLAGS was exported from the user's
+dnl environment, then the new CFLAGS will also be exported
+dnl to sub processes.
+
+CC_ERRORS=""
+CC_EXTRAS=""
+
+if export | fgrep " CFLAGS=" > /dev/null; then
+	export -n CFLAGS || true # We don't want to bomb out if this fails
+	SAVED_CFLAGS="$CFLAGS"
+	unset CFLAGS
+	CFLAGS="$SAVED_CFLAGS"
+	unset SAVED_CFLAGS
+fi
+
+if test "$GCC" != yes; then
+        CFLAGS="$CFLAGS -g"
+	enable_fatal_warnings=no
+else
+        CFLAGS="$CFLAGS -ggdb3"
+
+	# We had to eliminate -Wnested-externs because of libtool changes
+	# Also remove -Waggregate-return because we use one libnet
+	# call which returns a struct
+        EXTRA_FLAGS="-fgnu89-inline
+		-fstack-protector-all
+		-Wall
+		-Wbad-function-cast 
+		-Wcast-qual 
+		-Wcast-align 
+		-Wdeclaration-after-statement
+		-Wendif-labels
+		-Wfloat-equal
+		-Wformat=2
+		-Wformat-security
+		-Wformat-nonliteral
+		-Winline
+		-Wmissing-prototypes 
+		-Wmissing-declarations 
+		-Wmissing-format-attribute
+		-Wnested-externs
+		-Wno-long-long
+		-Wno-strict-aliasing
+		-Wpointer-arith 
+		-Wstrict-prototypes
+    		-Wunsigned-char
+		-Wwrite-strings"
+
+# Additional warnings it might be nice to enable one day
+#		-Wshadow
+#		-Wunreachable-code
+
+	for j in $EXTRA_FLAGS
+	do
+	  if
+	    cc_supports_flag $j
+	  then
+	    CC_EXTRAS="$CC_EXTRAS $j"
+	  fi
+	done
+
+dnl In lib/ais/Makefile.am there's a gcc option available as of v4.x
+
+	GCC_MAJOR=`gcc -v 2>&1 | awk 'END{print $3}' | sed 's/[.].*//'`
+	AM_CONDITIONAL(GCC_4, test "${GCC_MAJOR}" = 4)
+
+dnl System specific options
+
+	case "$host_os" in
+  	*linux*|*bsd*)
+		if test "${enable_fatal_warnings}" = "unknown"; then
+        		enable_fatal_warnings=yes
+        	fi
+          	;;
+	esac
+
+	if test "x${enable_fatal_warnings}" != xno && cc_supports_flag -Werror ; then
+	   enable_fatal_warnings=yes
+	else
+	   enable_fatal_warnings=no
+        fi
+
+	if test "x${enable_ansi}" != xno && cc_supports_flag -std=iso9899:199409 ; then
+	  AC_MSG_NOTICE(Enabling ANSI Compatibility)
+	  CC_EXTRAS="$CC_EXTRAS -ansi -D_GNU_SOURCE -DANSI_ONLY"
+	fi
+
+  	AC_MSG_NOTICE(Activated additional gcc flags: ${CC_EXTRAS})
+fi
+
+CFLAGS="$CFLAGS $CC_EXTRAS"
+
+NON_FATAL_CFLAGS="$CFLAGS"
+AC_SUBST(NON_FATAL_CFLAGS)
+
+dnl
+dnl We reset CFLAGS to include our warnings *after* all function
+dnl checking goes on, so that our warning flags don't keep the
+dnl AC_*FUNCS() calls above from working.  In particular, -Werror will
+dnl *always* cause us troubles if we set it before here.
+dnl
+dnl
+if test "x${enable_fatal_warnings}" = xyes ; then
+   AC_MSG_NOTICE(Enabling Fatal Warnings)
+   CFLAGS="$CFLAGS -Werror"
+fi
+AC_SUBST(CFLAGS)
+
+dnl This is useful for use in Makefiles that need to remove one specific flag
+CFLAGS_COPY="$CFLAGS"
+AC_SUBST(CFLAGS_COPY)
+
+AC_SUBST(LOCALE)
+
+AC_SUBST(CC)
+AC_SUBST(MAKE)
+
+dnl The Makefiles and shell scripts we output
+AC_CONFIG_FILES(Makefile				        \
+include/Makefile						\
+heartbeat/Makefile						\
+   heartbeat/ocf-binaries					\
+   heartbeat/ocf-directories					\
+   heartbeat/ocf-shellfuncs					\
+   heartbeat/shellfuncs						\
+tools/Makefile							\
+   tools/ocf-tester						\
+   tools/ocft/Makefile						\
+   tools/ocft/ocft						\
+   tools/ocft/caselib						\
+   tools/ocft/README						\
+   tools/ocft/README.zh_CN					\
+ldirectord/Makefile						\
+ldirectord/ldirectord   					\
+	ldirectord/init.d/Makefile				\
+	ldirectord/init.d/ldirectord   				\
+	ldirectord/init.d/ldirectord.debian			\
+	ldirectord/init.d/ldirectord.debian.default		\
+	ldirectord/logrotate.d/Makefile				\
+	ldirectord/OCF/Makefile					\
+	ldirectord/OCF/ldirectord				\
+doc/Makefile							\
+	doc/man/Makefile					\
+rgmanager/Makefile						\
+	rgmanager/src/Makefile					\
+	rgmanager/src/resources/Makefile			\
+	rgmanager/src/resources/utils/Makefile			\
+		)
+
+dnl Now process the entire list of files added by previous 
+dnl  calls to AC_CONFIG_FILES()
+AC_OUTPUT()
+
+dnl *****************
+dnl Configure summary
+dnl *****************
+
+AC_MSG_RESULT([])
+AC_MSG_RESULT([$PACKAGE configuration:])
+AC_MSG_RESULT([  Version                  = ${VERSION}])
+AC_MSG_RESULT([  Build Version            = 32dd79a119834cd3482b01d4bba623e7b8c0d8b4])
+AC_MSG_RESULT([  Features                 =${PKG_FEATURES}])
+AC_MSG_RESULT([])
+AC_MSG_RESULT([  Prefix                   = ${prefix}])
+AC_MSG_RESULT([  Executables              = ${sbindir}])
+AC_MSG_RESULT([  Man pages                = ${mandir}])
+AC_MSG_RESULT([  Libraries                = ${libdir}])
+AC_MSG_RESULT([  Header files             = ${includedir}])
+AC_MSG_RESULT([  Arch-independent files   = ${datadir}])
+AC_MSG_RESULT([  Documentation            = ${docdir}])
+AC_MSG_RESULT([  State information        = ${localstatedir}])
+AC_MSG_RESULT([  System configuration     = ${sysconfdir}])
+AC_MSG_RESULT([  RA state files           = ${HA_RSCTMPDIR}])
+AC_MSG_RESULT([  AIS Plugins              = ${LCRSODIR}])
+AC_MSG_RESULT([])
+AC_MSG_RESULT([  CFLAGS                   = ${CFLAGS}])
+AC_MSG_RESULT([  Libraries                = ${LIBS}])
+AC_MSG_RESULT([  Stack Libraries          = ${CLUSTERLIBS}])
+
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..dd9644b
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+SUBDIRS			= man
+
+MAINTAINERCLEANFILES    = Makefile.in
+
+EXTRA_DIST 		= $(doc_DATA)
+
+doc_DATA		= README.webapps
diff --git a/doc/README.webapps b/doc/README.webapps
new file mode 100644
index 0000000..bd9f534
--- /dev/null
+++ b/doc/README.webapps
@@ -0,0 +1,143 @@
+Monitoring web applications with the Apache RA
+
+One of typical uses of apache is as an interface to the one or
+the other kind of web application. It could be expressed thus in
+terms of a resource group:
+
+	IP address
+	apache
+	web_app
+
+where web_app is a JSP application (tomcat,jeronimo) or similar.
+
+Rumour has it that the web applications suffer from occasional
+instability which may make them an administration nightmare. But,
+typical remedy is simply an application restart.
+
+How do we increase availability in this situation?
+
+The web applications are most commonly represented as one or more
+processes in a UNIX environment. The afore mentioned instability
+is most commonly not reflected in the process state. Hence,
+checking the process status makes us no wiser.  What could help,
+though, is probing the application just as our unhappy user
+does---through the web interface. We can ask the application
+developers to provide a URL which should exercise the application
+and then provide predictable output.
+
+Now, given our generic resource group and the failed web
+application, which we established using a http client, we have
+the following situation:
+
+	IP address
+	apache FAILED
+	web_app
+
+Some might argue that it's not apache that is the culprit or has
+failed, but this nevertheless should serve our purpose well. The
+cluster will stop web_app and apache and then start them, either
+on the some node or elsewhere. There's an extra apache restart
+which was not needed, but then again it cannot really hurt.
+
+What to monitor?
+
+Choose carefully the URL to monitor. It should probe exactly what
+is further up in the resource group, no more and no less. In
+other words, if you have a database backend running elsewhere, it
+would be of no use to specify a URL which depends on the
+database. You should monitor only what is within reach.
+
+Configuration and usage
+
+It is possible to configure the monitoring either through CIB or
+using an extra configuration file. If your monitoring spec
+consists only of a URL and a regular expression to be matched in
+the output, then something like this should suffice:
+
+primitive apache_a1 ocf:heartbeat:apache \
+	params configfile="/apps/a1.conf" \
+	op monitor interval=120s timeout=60s start-delay=120s \
+		OCF_CHECK_LEVEL=10 testurl="/webapp1_mon" testregex="This application is alive"
+
+The testurl parameter is where we connect and the testregex is
+what we should look for. The OCF_CHECK_LEVEL must be set to "10".
+Note that testurl specifies a URL which is relative to where the
+apache listens for connections. Obviously, this should be
+preferred to specifying the full URL.
+
+It is important to set start-delay to a value larger than the
+time needed to start the web application (the next resource). If
+we don't, then the first monitor operation is likely to fail.
+
+In case you need more complex configuration, it can be set
+in an extra configuration file:
+
+primitive apache_a1 ocf:heartbeat:apache \
+	params configfile="/apps/a1.conf" testconffile="/apps/webmon.cf" \
+	op monitor ... OCF_CHECK_LEVEL=10
+
+/etc/apache2/webmon.cf:
+
+test webapp1
+url /webapp1_mon
+match This application is alive
+client curl
+end
+
+This test configuration is equivalent to the first one, it's just
+that in the latter we want to use curl(1) as an http client
+instead of wget(1).
+
+Another example:
+
+test webapp1
+url /webapp1_mon
+match This application is alive
+client curl
+client_opts --header 'Host: www.webapp1.megacorp.com'
+end
+
+Here we use the curl's --header option to specify the virtual
+host we want to talk to.
+
+It is also possible to set the credentials using the "user" and
+"password" keywords.
+
+The configuration file may contain more than one test definition
+which is handy in case one should monitor more than one web
+application. In that case you should specify the test name in the
+CIB:
+
+primitive apache_common ocf:heartbeat:apache \
+	params configfile="/apps/httpd.conf" testconffile="/apps/webmon.cf" \
+	op monitor ... OCF_CHECK_LEVEL=10 testname="a1" \
+	op monitor ... OCF_CHECK_LEVEL=10 testname="b1"
+
+The apache OCF RA supports wget(1) (the default) and curl(1) http
+clients. If neither will do, then you can specify your own using
+the client and client_opts keywords. Your client must allow URL
+as the last parameter and it must dump output from the web server
+to stdout.
+
+All configuration file keywords:
+
+test	The name of the text.
+url		The url to test. If it doesn't start with http, it's
+		considered to be relative to the apache Listen directive.
+match	The regular expression to match.
+user	Username to authenticate with.
+password	Password to authenticate with.
+client	The http client.
+client_opts	 Options for the http client.
+end		Marks the end of the test definition.
+#		Comment. May be used only at the start of line.
+
+Notes
+
+We could support more depth levels, but it is not clear if
+anybody really needs that. Different check levels could be
+defined as different monitor operations.
+
+In case you are using the external configuration file, don't
+forget to replicate it to all cluster members and to keep it
+synchronized.
diff --git a/doc/dev-guides/ra-dev-guide-docinfo.xml b/doc/dev-guides/ra-dev-guide-docinfo.xml
new file mode 100644
index 0000000..a003fc3
--- /dev/null
+++ b/doc/dev-guides/ra-dev-guide-docinfo.xml
@@ -0,0 +1,89 @@
+<author>
+  <firstname>Florian</firstname>
+  <surname>Haas</surname>
+  <affiliation>
+    <orgname>hastexo</orgname>
+  </affiliation>
+  <email>florian.haas at hastexo.com</email>
+</author>
+<collab>
+  <firstname>John</firstname>
+  <surname>Shi</surname>
+  <affiliation>
+    <orgname>SUSE</orgname>
+  </affiliation>
+  <contrib>Original ocft README</contrib>
+  <email>jshi at suse.com</email>
+</collab>
+<collab>
+  <firstname>Dejan</firstname>
+  <surname>Muhamedagic</surname>
+  <affiliation>
+    <orgname>SUSE</orgname>
+  </affiliation>
+  <contrib>ocft documentation rewrite</contrib>
+  <email>dmuhamedagic at suse.com</email>
+</collab>
+<copyright>
+  <year>2010</year>
+  <year>2011</year>
+  <holder>
+    <ulink url="http://www.linbit.com">LINBIT HA-Solutions GmbH</ulink>
+  </holder>
+</copyright>
+<copyright>
+  <year>2011</year>
+  <holder>
+    <ulink url="http://www.novell.com">Novell, Inc.</ulink>
+  </holder>
+</copyright>
+<copyright>
+  <year>2011</year>
+  <holder>
+    <ulink url="http://www.suse.com">SUSE Linux GmbH</ulink>
+  </holder>
+</copyright>
+<copyright>
+  <year>2011</year>
+  <holder>
+    <ulink url="http://www.hastexo.com">hastexo Professional Services GmbH</ulink>
+  </holder>
+</copyright>
+<legalnotice>
+  <title>License information</title>
+  <para>The text of and illustrations in this document are licensed
+  under a Creative Commons Attribution–Share Alike 3.0 Unported
+  license ("CC-BY-SA").</para>
+  <itemizedlist>
+    <listitem>
+      <para>A summary of CC-BY-SA is available at <ulink
+      url="http://creativecommons.org/licenses/by-sa/3.0/"/>.</para>
+    </listitem>
+    <listitem>
+      <para>The full license text is available at <ulink
+      url="http://creativecommons.org/licenses/by-sa/3.0/legalcode"/>.</para>
+    </listitem>
+    <listitem>
+      <para>In accordance with CC-BY-SA, if you distribute this document
+      or an adaptation of it, you must provide the URL for the original
+      version.</para>
+    </listitem>
+  </itemizedlist>
+</legalnotice>
+<revhistory>
+  <revision>
+    <revnumber>1.0.2</revnumber>
+    <date>November 18, 2011</date>
+    <authorinitials>FGH</authorinitials>
+  </revision>
+  <revision>
+    <revnumber>1.0.1</revnumber>
+    <date>January 3, 2011</date>
+    <authorinitials>FGH</authorinitials>
+  </revision>
+  <revision>
+    <revnumber>1.0.0</revnumber>
+    <date>December 13, 2010</date>
+    <authorinitials>FGH</authorinitials>
+  </revision>
+</revhistory>
diff --git a/doc/dev-guides/ra-dev-guide.txt b/doc/dev-guides/ra-dev-guide.txt
new file mode 100644
index 0000000..11e9a5d
--- /dev/null
+++ b/doc/dev-guides/ra-dev-guide.txt
@@ -0,0 +1,2021 @@
+= The OCF Resource Agent Developer's Guide
+
+== Introduction
+
+This document is to serve as a guide and reference for all developers,
+maintainers, and contributors working on OCF (Open Cluster Framework)
+compliant cluster resource agents. It explains the anatomy and general
+functionality of a resource agent, illustrates the resource agent API,
+and provides valuable hints and tips to resource agent authors.
+
+=== What is a resource agent?
+
+A resource agent is an executable that manages a cluster resource. No
+formal definition of a cluster resource exists, other than "anything a
+cluster manages is a resource." Cluster resources can be as diverse as
+IP addresses, file systems, database services, and entire virtual
+machines -- to name just a few examples.
+
+=== Who or what uses a resource agent?
+
+Any Open Cluster Framework (OCF) compliant cluster management
+application is capable of managing resources using the resource agents
+described in this document. At the time of writing, two OCF compliant
+cluster management applications exist for the Linux platform:
+
+* _Pacemaker_, a cluster manager supporting both the Corosync and
+  Heartbeat cluster messaging frameworks. Pacemaker evolved out of the
+  Linux-HA project.
+* _RGmanager_, the cluster manager bundled in Red Hat Cluster
+  Suite. It supports the Corosync cluster messaging framework
+  exclusively.
+
+=== Which language is a resource agent written in?
+
+An OCF compliant resource agent can be implemented in _any_
+programming language. The API is not language specific. However, most
+resource agents are implemented as shell scripts, which is why this
+guide primarily uses example code written in shell language.
+
+== API definitions
+
+=== Environment variables
+
+A resource agent receives all configuration information about the
+resource it manages via environment variables. The names of these
+environment variables are always the name of the resource parameter,
+prefixed with +OCF_RESKEY_+. For example, if the resource has an +ip+
+parameter set to +192.168.1.1+, then the resource agent will have
+access to an environment variable +OCF_RESKEY_ip+ holding that value.
+
+For any resource parameter that is not required to be set by the user
+-- that is, its parameter definition in the resource agent metadata
+does not specify +required="true"+ -- then the resource agent must
+
+* Provide a reasonable default. This should be advertised in the
+  metadata. By convention, the resource agent uses a variable named
+  +OCF_RESKEY_<parametername>_default+ that holds this default.
+* Alternatively, cater correctly for the value being empty.
+
+In addition, the cluster manager may also support _meta_ resource
+parameters. These do not apply directly to the resource configuration,
+but rather specify _how_ the cluster resource manager is expected to manage
+the resource. For example, the Pacemaker cluster manager uses the
++target-role+ meta parameter to specify whether the resource should be
+started or stopped.
+
+Meta parameters are passed into the resource agent in the
++OCF_RESKEY_CRM_meta_+ namespace, with any hypens converted to
+underscores. Thus, the +target-role+ attribute maps to an environment
+variable named +OCF_RESKEY_CRM_meta_target_role+.
+
+=== Actions
+
+Any resource agent must support one command-line argument which
+specifies the action the resource agent is about to execute. The
+following actions must be supported by any resource agent:
+
+* +start+ -- starts the resource.
+* +stop+ -- shuts down the resource.
+* +monitor+ -- queries the resource for its state.
+* +meta-data+ -- dumps the resource agent metadata.
+
+In addition, resource agents may optionally support the following
+actions:
+
+* +promote+ -- turns a resource into the +Master+ role (Master/Slave
+  resources only).
+* +demote+ -- turns a resource into the +Slave+ role (Master/Slave
+  resources only).
+* +migrate_to+ and +migrate_from+ -- implement live migration of
+  resources.
+* +validate-all+ -- validates a resource's configuration.
+* +usage+ or +help+ -- displays a usage message when the resource
+  agent is invoked from the command line, rather than by the cluster
+  manager.
+* +status+ -- historical (deprecated) synonym for +monitor+.
+
+=== Timeouts
+
+Action timeouts are enforced outside the resource agent proper. It is
+the cluster manager's responsibility to monitor how long a resource
+agent action has been running, and terminate it if it does not meet
+its completion deadline. Thus, resource agents need not themselves
+check for any timeout expiry.
+
+Resource agents can, however, _advise_ the user of sensible timeout
+values (which, when correctly set, will be duly enforced by the
+cluster manager). See <<_metadata,the following section>> for details
+on how a resource agent advertises its suggested timeouts.
+
+=== Metadata
+
+Every resource agent must describe its own purpose and supported
+parameters in a set of XML metadata. This metadata is used by cluster
+management applications for on-line help, and resource agent man pages
+are generated from it as well. The following is a fictitious set of
+metadata from an imaginary resource agent:
+
+[source,xml]
+--------------------------------------------------------------------------
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="foobar" version="0.1">
+  <version>0.1</version>
+  <longdesc lang="en">
+This is a fictitious example resource agent written for the
+OCF Resource Agent Developers Guide.
+  </longdesc>
+  <shortdesc lang="en">Example resource agent 
+  for budding OCF RA developers</shortdesc>
+  <parameters>
+    <parameter name="eggs" unique="0" required="1">
+      <longdesc lang="en">
+      Number of eggs, an example numeric parameter
+      </longdesc>
+      <shortdesc lang="en">Number of eggs</shortdesc>
+      <content type="integer"/>
+    </parameter>
+    <parameter name="superfrobnicate" unique="0" required="0">
+      <longdesc lang="en">
+      Enable superfrobnication, an example boolean parameter
+      </longdesc>
+      <shortdesc lang="en">Enable superfrobnication</shortdesc>
+      <content type="boolean" default="false"/>
+    </parameter>
+    <parameter name="datadir" unique="0" required="1">
+      <longdesc lang="en">
+      Data directory, an example string parameter
+      </longdesc>
+      <shortdesc lang="en">Data directory</shortdesc>
+      <content type="string"/>
+    </parameter>
+  </parameters>
+  <actions>
+    <action name="start"        timeout="20" />
+    <action name="stop"         timeout="20" />
+    <action name="monitor"      timeout="20"
+                                interval="10" depth="0" />
+    <action name="reload"       timeout="20" />
+    <action name="migrate_to"   timeout="20" />
+    <action name="migrate_from" timeout="20" />
+    <action name="meta-data"    timeout="5" />
+    <action name="validate-all"   timeout="20" />
+  </actions>
+</resource-agent>
+--------------------------------------------------------------------------
+
+The +resource-agent+ element, of which there must only be one per
+resource agent, defines the resource agent +name+ and +version+.
+
+The +longdesc+ and +shortdesc+ elements in +resource-agent+ provide a
+long and short description of the resource agent's
+functionality. While +shortdesc+ is a one-line description of what
+the resource agent does and is usually used in terse listings,
++longdesc+ should give a full-blown description of the resource agent
+in as much detail as possible.
+
+The +parameters+ element describes the resource agent parameters, and
+should hold any number of +parameter+ children -- one for each
+parameter that the resource agent supports.
+
+Every +parameter+ should, like the +resource-agent+ as a whole, come
+with a +shortdesc+ and a +longdesc+, and also a +content+ child that
+describes the parameter's expected content.
+
+On the +content+ element, there may be four different attributes:
+
+* +type+ describes the parameter type (+string+, +integer+, or
+  +boolean+). If unset, +type+ defaults to +string+.
+
+* +required+ indicates whether setting the parameter is mandatory
+  (+required="true"+) or optional (+required="false"+).
+
+* For optional parameters, it is customary to provide a sensible
+  default via the +default+ attribute.
+
+* Finally, the +unique+ attribute (allowed values: +true+ or +false+)
+  indicates that a specific value must be unique across the cluster,
+  for this parameter of this particular resource type. For example, a
+  highly available floating IP address is declared +unique+ -- as that
+  one IP address should run only once throughout the cluster, avoiding
+  duplicates.
+
+The +actions+ list defines the actions that the resource agent
+advertises as supported.
+
+Every +action+ should list its own +timeout+ value. This is a
+hint to the user what _minimal_ timeout should be configured for the
+action. This is meant to cater for the fact that some resources are
+quick to start and stop (IP addresses or filesystems, for example),
+some may take several minutes to do so (such as databases).
+
+In addition, recurring actions (such as +monitor+) should also specify
+a recommended minimum +interval+, which is the time between two
+consecutive invocations of the same action. Like +timeout+, this value
+does not constitute a default -- it is merely a hint for the user
+which action interval to configure, at minimum.
+
+== Return codes
+
+For any invocation, resource agents must exit with a defined return
+code that informs the caller of the outcome of the invoked
+action. The return codes are explained in detail in the following
+subsections.
+
+=== +OCF_SUCCESS+ (0)
+
+The action completed successfully. This is the expected return code
+for any successful +start+, +stop+, +promote+, +demote+,
++migrate_from+, +migrate_to+, +meta_data+, +help+, and +usage+ action.
+
+For +monitor+ (and its deprecated alias, +status+), however, a
+modified convention applies:
+
+* For primitive (stateless) resources, +OCF_SUCCESS+ from +monitor+
+  means that the resource is running. Non-running and gracefully
+  shut-down resources must instead return +OCF_NOT_RUNNING+.
+
+* For master/slave (stateful) resources, +OCF_SUCCESS+ from +monitor+
+  means that the resource is running _in Slave mode_. Resources
+  running in Master mode must instead return +OCF_RUNNING_MASTER+, and
+  gracefully shut-down resources must instead return
+  +OCF_NOT_RUNNING+.
+
+=== +OCF_ERR_GENERIC+ (1)
+
+The action returned a generic error. A resource agent should use this
+exit code only when none of the more specific error codes, defined
+below, accurately describes the problem.
+
+The cluster resource manager interprets this exit code as a _soft_
+error. This means that unless specifically configured otherwise, the
+resource manager will attempt to recover a resource which failed with
++OCF_ERR_GENERIC+ in-place -- usually by restarting the resource on
+the same node.
+
+=== +OCF_ERR_ARGS+ (2)
+
+The resource agent was invoked with incorrect arguments. This is a
+safety net "can't happen" error which the resource agent should only
+return when invoked with, for example, an incorrect number of command
+line arguments.
+
+NOTE: The resource agent should not return this error when instructed
+to perform an action that it does not support. Instead, under those
+circumstances, it should return +OCF_ERR_UNIMPLEMENTED+.
+
+=== +OCF_ERR_UNIMPLEMENTED+ (3)
+
+The resource agent was instructed to execute an action that the agent
+does not implement.
+
+Not all resource agent actions are mandatory. +promote+, +demote+,
++migrate_to+, +migrate_from+, and +notify+, are all optional actions
+which the resource agent may or may not implement. When a non-stateful
+resource agent is misconfigured as a master/slave resource, for
+example, then the resource agent should alert the user about this
+misconfiguration by returning +OCF_ERR_UNIMPLEMENTED+ on the +promote+
+and +demote+ actions.
+
+=== +OCF_ERR_PERM+ (4)
+
+The action failed due to insufficient permissions. This may be due to
+the agent not being able to open a certain file, to listen on a
+specific socket, to write to a directory, or similar.
+
+The cluster resource manager interprets this exit code as a _hard_
+error. This means that unless specifically configured otherwise, the
+resource manager will attempt to recover a resource which failed with
+this error by restarting the resource on a different node (where the
+permission problem may not exist).
+
+=== +OCF_ERR_INSTALLED+ (5)
+
+The action failed because a required component is missing on the node
+where the action was executed. This may be due to a required binary
+not being executable, or a vital configuration file being unreadable.
+
+The cluster resource manager interprets this exit code as a _hard_
+error. This means that unless specifically configured otherwise, the
+resource manager will attempt to recover a resource which failed with
+this error by restarting the resource on a different node (where the
+required files or binaries may be present).
+
+=== +OCF_ERR_CONFIGURED+ (6)
+
+The action failed because the user misconfigured the resource. For
+example, the user may have configured an alphanumeric string for a
+parameter that really should be an integer.
+
+The cluster resource manager interprets this exit code as a _fatal_
+error. Since this is a configuration error that is present
+cluster-wide, it would make no sense to recover such a resource on a
+different node, let alone in-place. When a resource fails with this
+error, the cluster manager will attempt to shut down the resource, and
+wait for administrator intervention.
+
+=== +OCF_NOT_RUNNING+ (7)
+
+The resource was found not to be running. This is an exit code that
+may be returned by the +monitor+ action exclusively. Note that this
+implies that the resource has either _gracefully_ shut down, or has
+never been started.
+
+If the resource is not running due to an error condition, the
++monitor+ action should instead return one of the +OCF_ERR_+ exit
+codes or +OCF_FAILED_MASTER+.
+
+=== +OCF_RUNNING_MASTER+ (8)
+
+The resource was found to be running in the +Master+ role. This
+applies only to stateful (Master/Slave) resources, and only to
+their +monitor+ action.
+
+Note that there is no specific exit code for "running in slave
+mode". This is because their is no functional distinction between a
+primitive resource running normally, and a stateful resource running
+as a slave. The +monitor+ action of a stateful resource running
+normally in the +Slave+ role should simply return +OCF_SUCCESS+.
+
+=== +OCF_FAILED_MASTER+ (9)
+
+The resource was found to have failed in the +Master+ role. This
+applies only to stateful (Master/Slave) resources, and only to their
++monitor+ action.
+
+The cluster resource manager interprets this exit code as a _soft_
+error. This means that unless specifically configured otherwise, the
+resource manager will attempt to recover a resource which failed with
++$OCF_FAILED_MASTER+ in-place -- usually by demoting, stopping,
+starting and then promoting the resource on the same node.
+
+
+== Resource agent structure
+
+A typical (shell-based) resource agent contains standard structural
+items, in the order as listed in this section.  It describes the
+expected behavior of a resource agent with respect to the various
+actions it supports, using a fictitous resource agent named +foobar+
+as an example.
+
+=== Resource agent interpreter
+
+Any resource agent implemented as a script must specify its
+interpreter using standard "shebang" (+#!+) header syntax.
+
+[source,bash]
+--------------------------------------------------------------------------
+#!/bin/sh
+--------------------------------------------------------------------------
+
+If a resource agent is written in shell, specifying the generic shell
+interpreter (+#!/bin/sh+) is generally preferred, though not
+required. Resource agents declared as +/bin/sh+ compatible must not
+use constructs native to a specific shell (such as, for example,
++${!variable}+ syntax native to +bash+). It is advisable to
+occasionally run such resource agents through a sanitization utility
+such as +checkbashisms+.
+
+It is considered a regression to introduce a patch that will make a
+previously +sh+ compatible resource agent suitable only for +bash+,
++ksh+, or any other non-generic shell. It is, however, perfectly
+acceptable for a new resource agent to explicitly define a specific
+shell, such as +/bin/bash+, as its interpreter.
+
+=== Author and license information
+
+The resource agent should contain a comment listing the resource agent
+author(s) and/or copyright holder(s), and stating the license that
+applies to the resource agent:
+
+[source,bash]
+--------------------------------------------------------------------------
+#
+#   Resource Agent for managing foobar resources.
+#
+#   License:      GNU General Public License (GPL)
+#   (c) 2008-2010 John Doe, Jane Roe,
+#                 and Linux-HA contributors
+--------------------------------------------------------------------------
+
+When a resource agent refers to a license for which multiple versions
+exist, it is assumed that the current version applies.
+
+=== Initialization
+
+Any shell resource agent should source the +ocf-shellfuncs+ function
+library. With the syntax below, this is done in terms of
++$OCF_FUNCTIONS_DIR+, which -- for testing purposes, and also for
+generating documentation -- may be overridden from the command line.
+
+[source,bash]
+--------------------------------------------------------------------------
+# Initialization:
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+--------------------------------------------------------------------------
+
+=== Functions implementing resource agent actions
+
+What follows next are the functions implementing the resource agent's
+advertised actions. The individual actions are described in detail in
+<<_resource_agent_actions>>.
+
+=== Execution block
+
+This is the part of the resource agent that actually executes when the
+resource agent is invoked. It typically follows a fairly standard
+structure:
+
+[source,bash]
+--------------------------------------------------------------------------
+# Make sure meta-data and usage always succeed
+case $__OCF_ACTION in
+meta-data)	foobar_meta_data
+		exit $OCF_SUCCESS
+		;;
+usage|help)	foobar_usage
+		exit $OCF_SUCCESS
+		;;
+esac
+
+# Anything other than meta-data and usage must pass validation
+foobar_validate_all || exit $?
+
+# Translate each action into the appropriate function call
+case $__OCF_ACTION in
+start)		foobar_start;;
+stop)		foobar_stop;;
+status|monitor)	foobar_monitor;;
+promote)	foobar_promote;;
+demote)		foobar_demote;;
+reload)		ocf_log info "Reloading..."
+	        foobar_start
+		;;
+validate-all)	;;
+*)		foobar_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+rc=$?
+
+# The resource agent may optionally log a debug message
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION returned $rc"
+exit $rc
+--------------------------------------------------------------------------
+
+
+== Resource agent actions
+
+Each action is typically implemented in a separate function or method
+in the resource agent. By convention, these are usually named
++<agent>_<action>+, so the function implementing the +start+ action in
++foobar+ would be named +foobar_start()+.
+
+As a general rule, whenever the resource agent encounters an error
+that it is not able to recover, it is permitted to immediately exit,
+throw an exception, or otherwise cease execution. Examples for this
+include configuration issues, missing binaries, permission problems,
+etc. It is not necessary to pass these errors up the call stack.
+
+It is the cluster manager's responsibility to initiate the appropriate
+recovery action based on the user's configuration. The resource agent
+should not guess at said configuration.
+
+=== +start+ action
+
+When invoked with the +start+ action, the resource agent must start
+the resource if it is not yet running. This means that the agent must
+verify the resource's configuration, query its state, and then start
+it only if it is not running. A common way of doing this would be to
+invoke the +validate_all+ and +monitor+ function first, as in the
+following example:
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_start() {
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    # if resource is already running, bail out early
+    if foobar_monitor; then
+	ocf_log info "Resource is already running"
+	return $OCF_SUCCESS
+    fi
+    
+    # actually start up the resource here (make sure to immediately
+    # exit with an $OCF_ERR_ error code if anything goes seriously
+    # wrong)
+    ...
+
+    # After the resource has been started, check whether it started up
+    # correctly. If the resource starts asynchronously, the agent may
+    # spin on the monitor function here -- if the resource does not
+    # start up within the defined timeout, the cluster manager will
+    # consider the start action failed
+    while ! foobar_monitor; do
+	ocf_log debug "Resource has not started yet, waiting"
+	sleep 1
+    done
+
+    # only return $OCF_SUCCESS if _everything_ succeeded as expected
+    return $OCF_SUCCESS
+}
+--------------------------------------------------------------------------
+
+
+=== +stop+ action
+
+When invoked with the +stop+ action, the resource agent must stop the
+resource, if it is running. This means that the agent must verify the
+resource configuration, query its state, and then stop it only if it
+is currently running. A common way of doing this would be to invoke
+the +validate_all+ and +monitor+ function first. It is important to
+understand that +stop+ is a force operation -- the resource agent must
+do everything in its power to shut down, the resource, short of
+rebooting the node or shutting it off. Consider the following example:
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_stop() {
+    local rc
+
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    foobar_monitor
+    rc=$?
+    case "$rc" in
+        "$OCF_SUCCESS")
+            # Currently running. Normal, expected behavior.
+            ocf_log debug "Resource is currently running"
+            ;;
+        "$OCF_RUNNING_MASTER")
+            # Running as a Master. Need to demote before stopping.
+            ocf_log info "Resource is currently running as Master"
+	    foobar_demote || \
+                ocf_log warn "Demote failed, trying to stop anyway"
+            ;;
+        "$OCF_NOT_RUNNING")
+            # Currently not running. Nothing to do.
+	    ocf_log info "Resource is already stopped"
+	    return $OCF_SUCCESS
+            ;;
+    esac
+    
+    # actually shut down the resource here (make sure to immediately
+    # exit with an $OCF_ERR_ error code if anything goes seriously
+    # wrong)
+    ...
+
+    # After the resource has been stopped, check whether it shut down
+    # correctly. If the resource stops asynchronously, the agent may
+    # spin on the monitor function here -- if the resource does not
+    # shut down within the defined timeout, the cluster manager will
+    # consider the stop action failed
+    while foobar_monitor; do
+	ocf_log debug "Resource has not stopped yet, waiting"
+	sleep 1
+    done
+
+    # only return $OCF_SUCCESS if _everything_ succeeded as expected
+    return $OCF_SUCCESS
+
+}
+--------------------------------------------------------------------------
+
+NOTE: The expected exit code for a successful stop operation is
++$OCF_SUCCESS+, _not_ +$OCF_NOT_RUNNING+.
+
+IMPORTANT: A failed stop operation is a potentially dangerous
+situation which the cluster manager will almost invariably try to
+resolve by means of node fencing. In other words, the cluster manager
+will forcibly evict from the cluster a node on which a stop operation
+has failed. While this measure serves ultimately to protect data, it
+does cause disruption to applications and their users. Thus, a
+resource agent should make sure that it exits with an error only if
+all avenues for proper resource shutdown have been exhausted.
+
+=== +monitor+ action
+
+The +monitor+ action queries the current status of a resource. It must
+discern between three different states:
+
+* resource is currently running (return +$OCF_SUCCESS+);
+* resource has stopped gracefully (return +$OCF_NOT_RUNNING+);
+* resource has run into a problem and must be considered failed
+  (return the appropriate +$OCF_ERR_+ code to indicate the nature of the
+  problem).
+
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_monitor() {
+    local rc
+
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    ocf_run frobnicate --test
+
+    # This example assumes the following exit code convention
+    # for frobnicate:
+    # 0: running, and fully caught up with master
+    # 1: gracefully stopped
+    # any other: error
+    case "$?" in
+	0)
+            rc=$OCF_SUCCESS
+	    ocf_log debug "Resource is running"
+            ;;
+	1)
+            rc=$OCF_NOT_RUNNING
+	    ocf_log debug "Resource is not running"
+	    ;;
+	*)
+	    ocf_log err "Resource has failed"
+	    exit $OCF_ERR_GENERIC
+    esac
+
+    return $rc
+}
+--------------------------------------------------------------------------
+
+Stateful (master/slave) resource agents may use a more elaborate
+monitoring scheme where they can provide "hints" to the cluster
+manager identifying which instance is best suited to assume the
++Master+ role. <<_specifying_a_master_preference>> explains the
+details.
+
+NOTE: The cluster manager may invoke the +monitor+ action for a
+_probe_, which is a test whether the resource is currently
+running. Normally, the monitor operation would behave exactly the same
+during a probe and a "real" monitor action. If a specific resource
+does require special treatment for probes, however, the +ocf_is_probe+
+convenience function is available in the OCF shell functions library
+for that purpose.
+
+=== +validate-all+ action
+
+The +validate-all+ action tests for correct resource agent
+configuration and a working environment. +validate-all+ should exit
+with one of the following return codes:
+
+* +$OCF_SUCCESS+ -- all is well, the configuration is valid and
+  usable.
+* +$OCF_ERR_CONFIGURED+ -- the user has misconfigured the resource.
+* +$OCF_ERR_INSTALLED+ -- the resource has possibly been configured
+  correctly, but a vital component is missing on the node where
+  +validate-all+ is being executed.
+* +$OCF_ERR_PERM+ -- the resource is configured correctly and is not
+  missing any required components, but is suffering from a permission
+  issue (such as not being able to create a necessary file).
+
++validate-all+ is usually wrapped in a function that is not only
+called when explicitly invoking the corresponding action, but also --
+as a sanity check -- from just about any other function. Therefore,
+the resource agent author must keep in mind that the function may be
+invoked during the +start+, +stop+, and +monitor+ operations, and also
+during probes.
+
+Probes pose a separate challenge for validation. During a probe (when
+the cluster manager may expect the resource _not_ to be running on the
+node where the probe is executed), some required components may be
+_expected_ to not be available on the affected node. For example, this
+includes any shared data on storage devices not available for reading
+during the probe. The +validate-all+ function may thus need to treat
+probes specially, using the +ocf_is_probe+ convenience function:
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_validate_all() {
+    # Test for configuration errors first
+    if ! ocf_is_decimal $OCF_RESKEY_eggs; then
+       ocf_log err "eggs is not numeric!"
+       exit $OCF_ERR_CONFIGURED
+    fi
+
+    # Test for required binaries
+    check_binary frobnicate
+
+    # Check for data directory (this may be on shared storage, so
+    # disable this test during probes)
+    if ! ocf_is_probe; then
+       if ! [ -d $OCF_RESKEY_datadir ]; then
+       	  ocf_log err "$OCF_RESKEY_datadir does not exist or is not a directory!"
+          exit $OCF_ERR_INSTALLED
+       fi
+    fi
+
+    return $OCF_SUCCESS
+}
+--------------------------------------------------------------------------
+
+=== +meta-data+ action
+
+The +meta-data+ action dumps the resource agent metadata to standard
+output. The output must follow the metadata format as specified in
+<<_metadata>>.
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_meta_data {
+    cat <<EOF
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="foobar" version="0.1">
+  <version>0.1</version>
+  <longdesc lang="en">
+...
+EOF
+}
+--------------------------------------------------------------------------
+
+=== +promote+ action
+
+The +promote+ action is optional. It must only be supported by
+_stateful_ resource agents, which means agents that discern between
+two distinct _roles_: +Master+ and +Slave+. +Slave+ is functionally
+identical to the +Started+ state in a stateless resource agent. Thus,
+while a regular (stateless) resource agent only needs to implement
++start+ and +stop+, a stateful resource agent must also support the
++promote+ action to be able to make a transition between the +Started+
+(+Slave+) and +Master+ roles.
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_promote() {
+    local rc
+
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    # test the resource's current state
+    foobar_monitor
+    rc=$?
+    case "$rc" in
+        "$OCF_SUCCESS")
+            # Running as slave. Normal, expected behavior.
+            ocf_log debug "Resource is currently running as Slave"
+            ;;
+        "$OCF_RUNNING_MASTER")
+            # Already a master. Unexpected, but not a problem.
+            ocf_log info "Resource is already running as Master"
+	    return $OCF_SUCCESS
+            ;;
+        "$OCF_NOT_RUNNING")
+            # Currently not running. Need to start before promoting.
+            ocf_log info "Resource is currently not running"
+            foobar_start
+            ;;
+        *)
+            # Failed resource. Let the cluster manager recover.
+            ocf_log err "Unexpected error, cannot promote"
+            exit $rc
+            ;;
+    esac
+    
+    # actually promote the resource here (make sure to immediately
+    # exit with an $OCF_ERR_ error code if anything goes seriously
+    # wrong)
+    ocf_run frobnicate --master-mode || exit $OCF_ERR_GENERIC
+
+    # After the resource has been promoted, check whether the
+    # promotion worked. If the resource promotion is asynchronous, the
+    # agent may spin on the monitor function here -- if the resource
+    # does not assume the Master role within the defined timeout, the
+    # cluster manager will consider the promote action failed.
+    while true; do
+        foobar_monitor
+        if [ $? -eq $OCF_RUNNING_MASTER ]; then
+            ocf_log debug "Resource promoted"
+            break
+        else
+            ocf_log debug "Resource still awaiting promotion"
+            sleep 1
+        fi
+    done
+
+    # only return $OCF_SUCCESS if _everything_ succeeded as expected
+    return $OCF_SUCCESS
+}
+--------------------------------------------------------------------------
+
+=== +demote+ action
+
+The +demote+ action is optional. It must only be supported by
+_stateful_ resource agents, which means agents that discern between
+two distict _roles_: +Master+ and +Slave+. +Slave+ is functionally
+identical to the +Started+ state in a stateless resource agent. Thus,
+while a regular (stateless) resource agent only needs to implement
++start+ and +stop+, a stateful resource agent must also support the
++demote+ action to be able to make a transition between the +Master+
+and +Started+ (+Slave+) roles.
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_demote() {
+    local rc
+
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    # test the resource's current state
+    foobar_monitor
+    rc=$?
+    case "$rc" in
+        "$OCF_RUNNING_MASTER")
+            # Running as master. Normal, expected behavior.
+            ocf_log debug "Resource is currently running as Master"
+            ;;
+        "$OCF_SUCCESS")
+            # Alread running as slave. Nothing to do.
+            ocf_log debug "Resource is currently running as Slave"
+	    return $OCF_SUCCESS
+            ;;
+        "$OCF_NOT_RUNNING")
+            # Currently not running. Getting a demote action
+            # in this state is unexpected. Exit with an error
+            # and let the cluster manager recover.
+            ocf_log err "Resource is currently not running"
+            exit $OCF_ERR_GENERIC
+            ;;
+        *)
+            # Failed resource. Let the cluster manager recover.
+            ocf_log err "Unexpected error, cannot demote"
+            exit $rc
+            ;;
+    esac
+    
+    # actually demote the resource here (make sure to immediately
+    # exit with an $OCF_ERR_ error code if anything goes seriously
+    # wrong)
+    ocf_run frobnicate --unset-master-mode || exit $OCF_ERR_GENERIC
+
+    # After the resource has been demoted, check whether the
+    # demotion worked. If the resource demotion is asynchronous, the
+    # agent may spin on the monitor function here -- if the resource
+    # does not assume the Slave role within the defined timeout, the
+    # cluster manager will consider the demote action failed.
+    while true; do
+        foobar_monitor
+        if [ $? -eq $OCF_RUNNING_MASTER ]; then
+            ocf_log debug "Resource still awaiting promotion"
+            sleep 1
+        else
+            ocf_log debug "Resource demoted"
+            break
+        fi
+    done
+
+    # only return $OCF_SUCCESS if _everything_ succeeded as expected
+    return $OCF_SUCCESS
+}
+--------------------------------------------------------------------------
+
+=== +migrate_to+ action
+
+The +migrate_to+ action can serve one of two purposes:
+
+* Initiate a native _push_ type migration for the resource. In other
+  words, instruct the resource to move _to_ a specific node from the
+  node it is currently running on. The resource agent knows about its
+  destination node via the +$OCF_RESKEY_CRM_meta_migrate_target+ environment
+  variable.
+
+* Freeze the resource in a _freeze/thaw_ (also known as
+  _suspend/resume_) type migration. In this mode, the resource does
+  not need any information about its destination node at this point.
+
+The example below illustrates a push type migration:
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_migrate_to() {
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    # if resource is not running, bail out early
+    if ! foobar_monitor; then
+	ocf_log err "Resource is not running"
+	exit $OCF_ERR_GENERIC
+    fi
+    
+    # actually start up the resource here (make sure to immediately
+    # exit with an $OCF_ERR_ error code if anything goes seriously
+    # wrong)
+    ocf_run frobnicate --migrate \
+                       --dest=$OCF_RESKEY_CRM_meta_migrate_target \
+                       || exit OCF_ERR_GENERIC
+    ...
+
+    # only return $OCF_SUCCESS if _everything_ succeeded as expected
+    return $OCF_SUCCESS
+}
+--------------------------------------------------------------------------
+
+In contrast, a freeze/thaw type migration may implement its freeze
+operation like this:
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_migrate_to() {
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    # if resource is not running, bail out early
+    if ! foobar_monitor; then
+	ocf_log err "Resource is not running"
+	exit $OCF_ERR_GENERIC
+    fi
+    
+    # actually start up the resource here (make sure to immediately
+    # exit with an $OCF_ERR_ error code if anything goes seriously
+    # wrong)
+    ocf_run frobnicate --freeze || exit OCF_ERR_GENERIC
+    ...
+
+    # only return $OCF_SUCCESS if _everything_ succeeded as expected
+    return $OCF_SUCCESS
+}
+--------------------------------------------------------------------------
+
+
+=== +migrate_from+ action
+
+The +migrate_from+ action can serve one of two purposes:
+
+* Complete a native _push_ type migration for the resource. In other
+  words, check whether the migration has succeeded properly, and the
+  resource is running on the local node. The resource agent knows
+  about its the migration source via the
+  +$OCF_RESKEY_CRM_meta_migrate_source+ environment variable.
+
+* Thaw the resource in a _freeze/thaw_ (also known as
+  _suspend/resume_) type migration. In this mode, the resource usually
+  not need any information about its source node at this point.
+
+The example below illustrates a push type migration:
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_migrate_from() {
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    # After the resource has been migrated, check whether it resumed
+    # correctly. If the resource starts asynchronously, the agent may
+    # spin on the monitor function here -- if the resource does not
+    # run within the defined timeout, the cluster manager will
+    # consider the migrate_from action failed
+    while ! foobar_monitor; do
+	ocf_log debug "Resource has not yet migrated, waiting"
+	sleep 1
+    done
+
+    # only return $OCF_SUCCESS if _everything_ succeeded as expected
+    return $OCF_SUCCESS
+}
+--------------------------------------------------------------------------
+
+In contrast, a freeze/thaw type migration may implement its thaw
+operation like this:
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_migrate_from() {
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    # actually start up the resource here (make sure to immediately
+    # exit with an $OCF_ERR_ error code if anything goes seriously
+    # wrong)
+    ocf_run frobnicate --thaw || exit OCF_ERR_GENERIC
+
+    # After the resource has been migrated, check whether it resumed
+    # correctly. If the resource starts asynchronously, the agent may
+    # spin on the monitor function here -- if the resource does not
+    # run within the defined timeout, the cluster manager will
+    # consider the migrate_from action failed
+    while ! foobar_monitor; do
+	ocf_log debug "Resource has not yet migrated, waiting"
+	sleep 1
+    done
+
+    # only return $OCF_SUCCESS if _everything_ succeeded as expected
+    return $OCF_SUCCESS
+}
+--------------------------------------------------------------------------
+
+
+=== +notify+ action
+
+With notifications, instances of clones (and of master/slave
+resources, which are an extended kind of clones) can inform each other
+about their state. When notifications are enabled, any action on any
+instance of a clone carries a +pre+ and +post+ notification. Then, the
+cluster manager invokes the +notify+ operation on _all_ clone
+instances. For +notify+ operations, additional environment variables
+are passed into the resource agent during execution:
+
+* +$OCF_RESKEY_CRM_meta_notify_type+ -- the notification type (+pre+
+  or +post+)
+
+* +$OCF_RESKEY_CRM_meta_notify_operation+ -- the operation (action)
+  that the notification is about (+start+, +stop+, +promote+, +demote+
+  etc.)
+
+* +$OCF_RESKEY_CRM_meta_notify_start_uname+ -- node name of the node
+  where the resource is being started (+start+ notifications only)
+
+* +$OCF_RESKEY_CRM_meta_notify_stop_uname+ -- node name of the node
+  where the resource is being stopped (+stop+ notifications only)
+
+* +$OCF_RESKEY_CRM_meta_notify_master_uname+ -- node name of the node
+  where the resource currently _is in_ the Master role
+
+* +$OCF_RESKEY_CRM_meta_notify_promote_uname+ -- node name of the node
+  where the resource currently _is being promoted to_ the Master role
+  (+promote+ notifications only)
+
+* +$OCF_RESKEY_CRM_meta_notify_demote_uname+ -- node name of the node
+  where the resource currently _is being demoted to_ the Slave role
+  (+demote+ notifications only)
+
+Notifications come in particularly handy for master/slave resources
+using a "pull" scheme, where the master is a publisher and the slave a
+subscriber. Since the master is obviously only available as such when
+a promotion has occurred, the slaves can use a "pre-promote"
+notification to configure themselves to subscribe to the right
+publisher.
+
+Likewise, the subscribers may want to unsubscribe from the publisher
+after it has relinquished its master status, and a "post-demote"
+notification can be used for that purpose.
+
+Consider the example below to illustrate the concept.
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_notify() {
+    local type_op
+    type_op="${OCF_RESKEY_CRM_meta_notify_type}-${OCF_RESKEY_CRM_meta_notify_operation}"
+
+    ocf_log debug "Received $type_op notification."
+    case "$type_op" in
+	'pre-promote')
+	    ocf_run frobnicate --slave-mode \
+                               --master=$OCF_RESKEY_CRM_meta_notify_promote_uname \
+                               || exit $OCF_ERR_GENERIC
+	    ;;
+	'post-demote')
+	    ocf_run frobnicate --unset-slave-mode || exit $OCF_ERR_GENERIC
+	    ;;
+    esac
+
+    return $OCF_SUCCESS
+}
+--------------------------------------------------------------------------
+
+NOTE: A master/slave resource agent may support a _multi-master_
+configuration, where there is possibly more than one master at any
+given time. If that is the case, then the
++$OCF_RESKEY_CRM_meta_notify_*_uname+ variables may each contain a
+space-separated lists of hostnames, rather than a single host name as
+shown in the example. Under those circumstances the resource agent
+would have to properly iterate over this list.
+
+== Script variables
+
+This section outlines variables typically available to resource agents,
+primarily for convenience purposes. For additional variables
+available while the agent is being executed, refer to
+<<_environment_variables>> and <<_return_codes>>.
+
+=== +$OCF_ROOT+
+
+The root of the OCF resource agent hierarchy. This should never be
+changed by a resource agent. This is usually +/usr/lib/ocf+.
+
+=== +$OCF_FUNCTIONS_DIR+
+
+The directory where the resource agents shell function library,
++ocf-shellfuncs+, resides. This is usually defined in terms of
++$OCF_ROOT+ and should never be changed by a resource agent. This
+variable may, however, be overridden from the command line while
+testing a new or modified resource agent.
+
+=== +$OCF_RESOURCE_INSTANCE+
+
+The resource instance name. For primitive (non-clone, non-stateful)
+resources, this is simply the resource name. For clones and stateful
+resources, this is the primitive name, followed by a colon an the
+clone instance number (such as +p_foobar:0+).
+
+=== +$__OCF_ACTION+
+
+The currently invoked action. This is exactly the first command-line
+argument that the cluster manager specifies when it invokes the
+resource agent.
+
+=== +$__SCRIPT_NAME+
+
+The name of the resource agent. This is exactly the base name of the
+resource agent script, with leading directory names removed.
+
+=== +$HA_RSCTMP+
+
+A temporary directory for use by resource agents. The system startup
+sequence (on any LSB compliant Linux distribution) guarantees that
+this directory is emptied on system startup, so this directory will
+not contain any stale data after a node reboot.
+
+== Convenience functions
+
+=== Logging: +ocf_log+
+
+Resource agents should use the +ocf_log+ function for logging
+purposes. This convenient logging wrapper is invoked as follows:
+
+[source,bash]
+--------------------------------------------------------------------------
+ocf_log <severity> "Log message"
+--------------------------------------------------------------------------
+
+It supports following the following severity levels:
+
+* +debug+ -- for debugging messages. Most logging configurations
+  suppress this level by default.
+* +info+ -- for informational messages about the agent's behavior or
+  status.
+* +warn+ -- for warnings. This is for any messages which reflect
+  unexpected behavior that does _not_ constitute an unrecoverable
+  error.
+* +err+ -- for errors. As a general rule, this logging level should
+  only be used immediately prior to an +exit+ with the appropriate
+  error code.
+* +crit+ -- for critical errors. As with +err+, this logging level
+  should not be used unless the resource agent also exits with an
+  error code. Very rarely used.
+
+=== Testing for binaries: +have_binary+ and +check_binary+
+
+A resource agent may need to test for the availability of a specific
+executable. The +have_binary+ convenience function comes in handy
+here:
+
+[source,bash]
+--------------------------------------------------------------------------
+if ! have_binary frobnicate; then
+   ocf_log warn "Missing frobnicate binary, frobnication disabled!"
+fi
+--------------------------------------------------------------------------
+
+If a missing binary is a fatal problem for the resource, then the
++check_binary+ function should be used:
+
+[source,bash]
+--------------------------------------------------------------------------
+check_binary frobnicate
+--------------------------------------------------------------------------
+
+Using +check_binary+ is a shorthand method for testing for the
+existence (and executability) of the specified binary, and exiting
+with +$OCF_ERR_INSTALLED+ if it cannot be found or executed.
+
+NOTE: Both +have_binary+ and +check_binary+ honor +$PATH+ when the
+binary to test for is not specified as a full path. It is usually wise
+to _not_ test for a full path, as binary installations path may vary
+by distribution or user policy.
+
+=== Executing commands and capturing their output: +ocf_run+
+
+Whenever a resource agent needs to execute a command and capture its
+output, it should use the +ocf_run+ convenience function, invoked as
+in this example:
+
+[source,bash]
+--------------------------------------------------------------------------
+ocf_run "frobnicate --spam=eggs" || exit $OCF_ERR_GENERIC
+--------------------------------------------------------------------------
+
+With the command specified above, the resource agent will invoke
++frobnicate --spam=eggs+ and capture its output and
+exit code. If the exit code is nonzero (indicating an error),
++ocf_run+ logs the command output with the +err+ logging severity, and
+the resource agent subsequently exits.  If the exit code is zero
+(indicating success), any command output will be logged with the +info+
+logging severity.
+
+If the resource agent wishes to ignore the output of a successful
+command execution, it can use the +-q+ flag with +ocf_run+. In the
+example below, +ocf_run+ will only log output if the command exit code
+is nonzero.
+
+[source,bash]
+--------------------------------------------------------------------------
+ocf_run -q "frobnicate --spam=eggs" || exit $OCF_ERR_GENERIC
+--------------------------------------------------------------------------
+
+Finally, if the resource agent wants to log the output of a command
+with a nonzero exit code with a severity _other_ than error, it may do
+so by adding the +-info+ or +-warn+ option to +ocf_run+:
+
+[source,bash]
+--------------------------------------------------------------------------
+ocf_run -warn "frobnicate --spam=eggs"
+--------------------------------------------------------------------------
+
+=== Locks: +ocf_take_lock+ and +ocf_release_lock_on_exit+
+
+Occasionally, there may be different resources of the same type in a
+cluster configuration that should not execute actions in
+parallel. When a resource agent needs to guard against parallel
+execution on the same machine, it can use the +ocf_take_lock+ and
++ocf_release_lock_on_exit+ convenience functions:
+
+[source,bash]
+--------------------------------------------------------------------------
+LOCKFILE=${HA_RSCTMP}/foobar
+ocf_release_lock_on_exit $LOCKFILE
+
+foobar_start() {
+    ...
+    ocf_take_lock $LOCKFILE
+    ...
+}
+--------------------------------------------------------------------------
+
++ocf_take_lock+ attempts to acquire the designated +$LOCKFILE+. When
+it is unavailable, it sleeps a random amount of time between 0 and 1
+seconds, and retries. +ocf_release_lock_on_exit+ releases the lock
+file when the agent exits (for any reason).
+
+=== Testing for numerical values: +ocf_is_decimal+
+
+Specifically for parameter validation, it can be helpful to test
+whether a given value is numeric. The +ocf_is_decimal+ function exists
+for that purpose:
+--------------------------------------------------------------------------
+foobar_validate_all() {
+    if ! ocf_is_decimal $OCF_RESKEY_eggs; then
+        ocf_log err "eggs is not numeric!"
+        exit $OCF_ERR_CONFIGURED
+    fi
+    ...
+}
+--------------------------------------------------------------------------
+
+=== Testing for boolean values: +ocf_is_true+
+
+When a resource agent defines a boolean parameter, the value
+for this parameter may be specified by the user as +0+/+1+,
++true+/+false+, or +on+/+off+. Since it is tedious to test for all
+these values from within the resource agent, the agent should instead
+use the +ocf_is_true+ convenience function:
+
+[source,bash]
+--------------------------------------------------------------------------
+if ocf_is_true $OCF_RESKEY_superfrobnicate; then
+    ocf_run "frobnicate --super"
+fi
+--------------------------------------------------------------------------
+
+NOTE: If +ocf_is_true+ is used against an empty or non-existant
+variable, it always returns an exit code of +1+, which is equivalent
+to +false+.
+
+=== Version comparison: +ocf_version_cmp+
+
+A resource agent may want to check the version of software
+installed. +ocf_version_cmp+ takes care of all the necessary
+details.
+
+The return codes are
+
+* +0+ -- the first version is smaller (earlier) than the second
+* +1+ -- the two versions are equal
+* +2+ -- the first version is greater (later) than the second
+* +3+ -- one of arguments is not recognized as a version string
+
+The versions are allowed to contain digits, dots, and dashes.
+
+[source,bash]
+--------------------------------------------------------------------------
+local v=`gooey --version`
+ocf_version_cmp "$v" 12.0.8-1
+case $? in
+	0) ocf_log err "we do not support version $v, it is too old"
+	   exit $OCF_ERR_INSTALLED
+	;;
+	[12]) ;; # we can work with versions >= 12.0.8-1
+	3) ocf_log err "gooey produced version <$v>, too funky for me"
+	   exit $OCF_ERR_INSTALLED
+	;;
+esac
+--------------------------------------------------------------------------
+
+=== Pseudo resources: +ha_pseudo_resource+
+
+"Pseudo resources" are those where the resource agent in fact does not
+actually start or stop something akin to a runnable process, but
+merely executes a single action and then needs some form of tracing
+whether that action has been executed or not. The +portblock+ resource
+agent is an example of this.
+
+Resource agents for pseudo resources can use a convenience function,
++ha_pseudo_resource+, which makes use of _tracking files_ to keep tabs
+on the status of a resource. If +foobar+ was designed to manage a
+pseudo resource, then its +start+ action could look like this:
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_start() {
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    # if resource is already running, bail out early
+    if foobar_monitor; then
+	ocf_log info "Resource is already running"
+	return $OCF_SUCCESS
+    fi
+
+    # start the pseudo resource
+    ha_pseudo_resource ${OCF_RESOURCE_INSTANCE} start
+
+    # After the resource has been started, check whether it started up
+    # correctly. If the resource starts asynchronously, the agent may
+    # spin on the monitor function here -- if the resource does not
+    # start up within the defined timeout, the cluster manager will
+    # consider the start action failed
+    while ! foobar_monitor; do
+	ocf_log debug "Resource has not started yet, waiting"
+	sleep 1
+    done
+
+    # only return $OCF_SUCCESS if _everything_ succeeded as expected
+    return $OCF_SUCCESS
+}
+--------------------------------------------------------------------------
+
+
+== Conventions
+
+This section contains a collection of conventions that have emerged in
+the resource agent repositories over the years. Following these
+conventions is by no means mandatory for resource agent authors, but
+it is a good idea based on the
+http://en.wikipedia.org/wiki/Principle_of_least_surprise[Principle of
+Least Surprise] -- resource agents following these conventions will be
+easier to understand, review, and use than those that do not.
+
+=== Well-known parameter names
+
+Several parameter names are supported by a number of resource
+agents. For new resource agents, following these examples is generally
+a good idea:
+
+* +binary+ -- the name of a binary that principally manages the
+  resource, such as a server daemon
+* +config+ -- the full path to a configuration file
+* +pid+ -- the full path to a file holding a process ID (PID)
+* +log+ -- the full path to a log file
+* +socket+ -- the full path to a UNIX socket that the resource manages
+* +ip+ -- an IP address that a daemon binds to
+* +port+ -- a TCP or UDP port that a daemon binds to
+
+Needless to say, resource agents should only implement any of these
+parameters if they are sensible to use in the agent's context.
+
+=== Parameter defaults
+
+Defaults for resource agent parameters should be set by initializing
+variables with the suffix +_default+:
+
+[source,bash]
+--------------------------------------------------------------------------
+# Defaults
+OCF_RESKEY_superfrobnicate_default=0
+
+: ${OCF_RESKEY_superfrobnicate=${OCF_RESKEY_superfrobnicate_default}}
+--------------------------------------------------------------------------
+
+NOTE: The resource agent should make sure that it sets a default for
+any parameter not marked as +required+ in the metadata.
+
+
+=== Honoring +PATH+ for binaries
+
+When a resource agent supports a parameter designed to hold the name
+of a binary (such as a daemon, or a client utility for querying
+status), then that parameter should honor the +PATH+ environment
+variable. Do not supply full paths. Thus, the following approach:
+
+[source,bash]
+--------------------------------------------------------------------------
+# Good example -- do it this way
+OCF_RESKEY_frobnicate_default="frobnicate"
+: ${OCF_RESKEY_frobnicate="${OCF_RESKEY_frobnicate_default}"}
+--------------------------------------------------------------------------
+
+is much preferred over specifying a full path, as shown here:
+
+[source,bash]
+--------------------------------------------------------------------------
+# Bad example -- avoid if you can
+OCF_RESKEY_frobnicate_default="/usr/local/sbin/frobnicate"
+: ${OCF_RESKEY_frobnicate="${OCF_RESKEY_frobnicate_default}"}
+--------------------------------------------------------------------------
+
+This rule holds for defaults, as well.
+
+
+
+== Special considerations
+
+=== Licensing
+
+Whenever possible, resource agent contributors are _encouraged_ to use
+the GNU General Public License (GPL), version 2 and later, for any new
+resource agents. The shell functions library does not strictly mandate
+this, however, as it is licensed under the GNU Lesser General Public
+License (LGPL), version 2.1 and later (so it can be used by non-GPL
+agents).
+
+The resource agent _must_ explicitly state its own license in the
+agent source code.
+
+
+=== Locale settings
+
+When sourcing +ocf-shellfuncs+ as explained in <<_initialization>>,
+any resource agent automatically sets +LANG+ and +LC_ALL+ to the +C+
+locale. Resource agents can thus expect to always operate in the +C+
+locale, and need not reset +LANG+ or any of the +LC_+ environment
+variables themselves.
+
+
+=== Testing for running processes
+
+For testing whether a particular process (with a known process ID) is
+currently running, a frequently found method is to send it a +0+
+signal and catch errors, similar to this example:
+
+[source,bash]
+--------------------------------------------------------------------------
+if kill -s 0 `cat $daemon_pid_file`; then
+    ocf_log debug "Process is currently running"
+else
+    ocf_log warn "Process is dead, removing pid file"
+    rm -f $daemon_pid_file
+if
+--------------------------------------------------------------------------
+
+IMPORTANT: An approach far superior to this example is to instead test
+the _functionality_ of the daemon by connecting to it with a client
+process, as shown in the example in
+<<_literal_monitor_literal_action>>.
+
+
+=== Specifying a master preference
+
+Stateful (master/slave) resources must set their own _master
+preference_ -- they can thus provide hints to the cluster manager
+which is the the best instance to promote to the +Master+ role.
+
+IMPORTANT: It is acceptable for multiple instances to have identical
+positive master preferences. In that case, the cluster resource
+manager will automatically select a resource agent to
+promote. However, if _all_ instances have the (default) master score
+of zero, the cluster manager will not promote any instance at
+all. Thus, it is crucial that at least one instance has a positive
+master score.
+
+For this purpose, +crm_master+ comes in handy. This convenience
+wrapper around the +crm_attribute+ sets a node attribute named
++master-<<_literal_ocf_resource_instance_literal,$OCF_RESOURCE_INSTANCE>>+
+for the node it is being executed on, and fills this attribute with
+the specified value. The cluster manager is then expected to translate
+this into a promotion score for the corresponding instance, and base
+its promotion preference on that score.
+
+Stateful resource agents typically execute +crm_master+ during the
+<<_literal_monitor_literal_action,+monitor+>> and/or
+<<_literal_notify_literal_action,+notify+>> action.
+
+The following example assumes that the +foobar+ resource agent can
+test the application's status by executing a binary that returns
+certain exit codes based on whether
+
+* the resource is either in the master role, or is a slave that is
+  fully caught up with the master (at any rate, it has current data),
+  or
+* the resource is in the slave role, but through some form of
+  asynchronous replication has "fallen behind" the master, or
+* the resource has gracefully stopped, or
+* the resource has unexpectedly failed.
+
+[source,bash]
+--------------------------------------------------------------------------
+foobar_monitor() {
+    local rc
+
+    # exit immediately if configuration is not valid
+    foobar_validate_all || exit $?
+
+    ocf_run frobnicate --test
+
+    # This example assumes the following exit code convention
+    # for frobnicate:
+    # 0: running, and fully caught up with master
+    # 1: gracefully stopped
+    # 2: running, but lagging behind master
+    # any other: error
+    case "$?" in
+	0)
+            rc=$OCF_SUCCESS
+	    ocf_log debug "Resource is running"
+            # Set a high master preference. The current master
+            # will always get this, plus 1. Any current slaves
+            # will get a high preference so that if the master
+            # fails, they are next in line to take over.
+            crm_master -l reboot -v 100
+            ;;
+	1)
+            rc=$OCF_NOT_RUNNING
+	    ocf_log debug "Resource is not running"
+            # Remove the master preference for this node
+            crm_master -l reboot -D
+	    ;;
+        2)
+            rc=$OCF_SUCCESS
+            ocf_log debug "Resource is lagging behind master"
+            # Set a low master preference: if the master fails
+            # right now, and there is another slave that does
+            # not lag behind the master, its higher master
+            # preference will win and that slave will become
+            # the new master
+            crm_master -l reboot -v 5
+            ;;
+	*)
+	    ocf_log err "Resource has failed"
+	    exit $OCF_ERR_GENERIC
+    esac
+
+    return $rc
+}
+--------------------------------------------------------------------------
+
+
+== Testing resource agents
+
+This section discusses automated testing for resource agents. Testing
+is a vital aspect of development; it is crucial both for creating new
+resource agents, and for modifying existing ones.
+
+
+=== Testing with +ocf-tester+
+
+The resource agents repository (and hence, any installed resource
+agents package) contains a utility named +ocf-tester+. This shell
+script allows you to conveniently and easily test the functionality of
+your resource agent.
+
++ocf-tester+ is commonly invoked, as +root+, like this:
+
+--------------------------------------------------------------------------
+ocf-tester -n <name> [-o <param>=<value> ... ] <resource agent>
+--------------------------------------------------------------------------
+
+* +<name>+ is an arbitrary resource name.
+
+* You may set any number of +<param>=<value>+ with the +-o+ option,
+  corresponding to any resource parameters you wish to set for
+  testing.
+
+* +<resource agent>+ is the full path to your resource agent.
+
+When invoked, +ocf-tester+ executes all mandatory actions and enforces
+action behavior as explained in <<_resource_agent_actions>>.
+
+It also tests for optional actions. Optional actions must behave as
+expected when advertised, but do not cause +ocf-tester+ to flag an
+error if not implemented.
+
+IMPORTANT: +ocf-tester+ does not initiate "dry runs" of actions, nor
+does it create resource dummies of any kind. Instead, it exercises the
+actual resource agent as-is, whether that may include opening and
+closing databases, mounting file systems, starting or stopping virtual
+machines, etc. Use with care.
+
+For example, you could run +ocf-tester+ on the +foobar+ resource agent
+as follows:
+
+--------------------------------------------------------------------------
+# ocf-tester -n foobartest \
+             -o superfrobnicate=true \
+             -o datadir=/tmp \
+             /home/johndoe/ra-dev/foobar
+Beginning tests for /home/johndoe/ra-dev/foobar...
+* Your agent does not support the notify action (optional)
+* Your agent does not support the reload action (optional)
+/home/johndoe/ra-dev/foobar passed all tests
+--------------------------------------------------------------------------
+
+If the resource agent exhibits some difficult to grasp behaviour,
+which is typically the case with just developed software, there
+are +-v+ and +-d+ options to dump more output. If that does not
+help, instruct +ocf-tester+ to trace the resource agent with
++-X+ (make sure to redirect output to a file, unless you are a
+really fast reader).
+
+=== Testing with +ocft+
+
++ocft+ is a testing tool for resource agents. The main difference
+to +ocf-tester+ is that +ocft+ can automate creating complex
+testing environments. That includes package installation and
+arbitrary shell scripting.
+
+==== +ocft+ components
+
++ocft+ consists of the following components:
+
+* A test case generator (+/usr/sbin/ocft+) -- generates shell
+  scripts from test case configuration files
+
+* Configuration files (+/usr/share/resource-agents/ocft/configs/+) --
+  a configuration file contains environment setup and test cases
+  for one resource agent
+
+* The testing scripts are stored in +/var/lib/resource-agents/ocft/cases/+,
+  but normally there is no need to inspect them
+
+==== Customizing the testing environment
+
++ocft+ modifies the runtime environment of the resource agent
+either by changing environment variables (through the interface
+defined by OCF) or by running ad-hoc shell scripts which can for
+instance change permissions of a file or unmount a file system.
+
+==== How to test
+
+You need to know the software (resource) you want to test. Draw a
+sketch of all interesting scenarios, with all expected and
+unexpected conditions and how the resource agent should react to
+them. Then you need to encode these conditions and the expected
+outcomes as +ocft+ test cases. Running ocft is then simple:
+
+---------------------------------------
+# ocft make <RA>
+# ocft test <RA>
+---------------------------------------
+
+The first subcommand generates the scripts for your test cases
+whereas the second runs them and checks the outcome.
+
+==== +ocft+ configuration file syntax
+
+There are four top level options each of which can contain
+one or more sub-options.
+
+===== +CONFIG+ (top level option)
+
+This option is global and influences every test case.
+
+  ** +AgentRoot+ (sub-option)
+---------------------------------------
+AgentRoot /usr/lib/ocf/resource.d/xxx
+---------------------------------------
+
+Normally, we assume that the resource agent lives under the
++heartbeat+ provider. Use `AgentRoot` to test agent which is
+distributed by another vendor.
+
+  ** +InstallPackage+ (sub-option)
+---------------------------------------
+InstallPackage package [package2 [...]]
+---------------------------------------
+
+Install packages necessary for testing. The installation is
+skipped if the packages have already been installed.
+
+  ** 'HangTimeout' (sub-option)
+---------------------------------------
+HangTimeout secs
+---------------------------------------
+
+The maximum time allowed for a single RA action. If this timer
+expires, the action is considered as failed.
+
+===== +SETUP-AGENT+ (top level option)
+---------------------------------------
+SETUP-AGENT
+  bash commands
+---------------------------------------
+
+If the RA needs to be initialized before testing, you can put
+bash code here for that purpose. The initialization is done only
+once. If you need to reinitialize then delete the
++/tmp/.[AGENT_NAME]_set+ stamp file.
+
+===== +CASE+ (top level option)
+---------------------------------------
+CASE "description"
+---------------------------------------
+
+This is the main building block of the test suite. Each test
+case is to be described in one +CASE+ top level option.
+
+One case consists of several suboptions typically followed by the
++RunAgent+ suboption.
+
+  ** +Var+ (sub-option)
+---------------------------------------
+Var VARIABLE=value
+---------------------------------------
+
+It is to set up an environment variable of the resource agent. They
+usually appear to be OCF_RESKEY_xxx. One point is to be noted is there
+is no blank by both sides of "=".
+
+  ** +Unvar+ (sub-option)
+---------------------------------------
+Unvar VARIABLE [VARIABLE2 [...]]
+---------------------------------------
+
+Remove the environment variable.
+
+  ** +Include+ (sub-option)
+---------------------------------------
+Include macro_name
+---------------------------------------
+
+Include statements in 'macro_name'. See below for description of
++CASE-BLOCK+.
+
+** +Bash+ (sub-option)
+---------------------------------------
+Bash bash_codes
+---------------------------------------
+
+This option is to set up the environment of OS, where you can insert
+BASH code to customize the system randomly. Note, do not cause
+unrecoverable consequences to the system.
+
+** +BashAtExit+ (sub-option)
+---------------------------------------
+BashAtExit bash_codes
+---------------------------------------
+
+This option is to recover the OS environment in order to run another
+test case correctly. Of cause you can use 'Bash' option to recover
+it. However, if mistakes occur in the process, the script will quit
+directly instead of running your recovery codes.  If it happens, you
+ought to use BashAtExit which can restore the system environment
+before you quit.
+
+** +RunAgent+ (sub-option)
+---------------------------------------
+RunAgent cmd [ret_value]
+---------------------------------------
+
+This option is to run resource agent. "cmd" is the parameter of the
+resource agent, such as "start, status, stop ...". The second
+parameter is optional. It will compare the actual returned value with
+the expected value when the script has run recourse agent.  If
+differs, bugs will be found.
+
+It is also possible to execute a suboption on a remote host
+instead of locally. The protocol used is ssh and the command is
+run in the background. Just add the +@<ipaddr>+ suffix to the
+suboption name. For instance:
+
+---------------------------------------
+Bash at 192.168.1.100 date
+---------------------------------------
+
+would run the date program. Remote commands are run in
+background.
+
+NB: Not clear how can ssh be automated as we don't know in
+advance the environment. Perhaps use "well-known" host names such
+as "node2"? Also, if the command runs in the background, it's not
+clear how is the exit code checked. Finally, does Var at node make
+sense? Or is the current environment somehow copied over? We
+probably need an example here.
+
+Need examples in general.
+
+===== +CASE-BLOCK+ (top level option)
+---------------------------------------
+CASE-BLOCK macro_name
+---------------------------------------
+
+The +CASE-BLOCK+ option defines a macro which can be +Include+d
+in any +CASE+. All +CASE+ suboptions are valid in +CASE-BLOCK+.
+
+
+== Installing and packaging resource agents
+
+This section discusses what to do with your resource agent once it is
+done and tested -- where to install it, and how to include it in either
+your own application package or in the Linux-HA resource agents
+repository.
+
+=== Installing resource agents
+
+If you choose to include your resource agent in your own project, make
+sure it installs into the correct location. Resource agents should
+install into the +/usr/lib/ocf/resource.d/<provider>+ directory, where
++<provider>+ is the name of your project or any other name you wish to
+identify the resource agent with.
+
+For example, if your +foobar+ resource agent is being packaged as part
+of a project named +fortytwo+, then the correct full path to your
+resource agent would be
++/usr/lib/ocf/resource.d/fortytwo/foobar+. Make sure your resource
+agent installs with +0755+ (+-rwxr-xr-x+) permission bits.
+
+When installed this way, OCF-compliant cluster resource managers will
+be able to properly identify, parse, and execute your resource
+agent. The Pacemaker cluster manager, for example, would map the
+above-mentioned installation path to the +ocf:fortytwo:foobar+
+resource type identifier.
+
+=== Packaging resource agents
+
+When you package resource agents as part of your own project, you
+should apply the considerations outlined in this section.
+
+NOTE: If you instead prefer to submit your resource agent to the
+Linux-HA resource agents repository, see
+<<_submitting_resource_agents>> for information on doing so.
+
+==== RPM packaging
+
+It is recommended to put your OCF resource agent(s) in an RPM
+sub-package, with the name +<toppackage>-resource-agents+. Ensure that
+the package owns its provider directory, and depends on the upstream
++resource-agents+ package which lays out the directory hierarchy and
+provides convenience shell functions. An example RPM spec snippet is
+given below:
+
+--------------------------------------------------------------------------
+%package resource-agents
+Summary: OCF resource agent for Foobar
+Group: System Environment/Base
+Requires: %{name} = %{version}-%{release}, resource-agents
+
+%description resource-agents
+This package contains the OCF-compliant resource agents for Foobar.
+
+%files resource-agents
+%defattr(755,root,root,-)
+%dir %{_prefix}/lib/ocf/resource.d/fortytwo
+%{_prefix}/lib/ocf/resource.d/fortytwo/foobar
+--------------------------------------------------------------------------
+
+NOTE: If an RPM spec file contains a +%package+ declaration, then RPM
+considers this a sub-package which inherits top-level fields such as
++Name+, +Version+, +License+, etc. Sub-packages have the top-level
+package name automatically prepended to their own name. Thus the snippet
+above would create a sub-package named +foobar-resource-agents+
+(presuming the package +Name+ is +foobar+).
+
+==== Debian packaging
+
+For Debian packages, like for <<_rpm_packaging,RPMs>>, it is
+recommended to create a separate package holding your resource agents,
+which then should depend on the +cluster-agents+ package.
+
+NOTE: This section assumes that you are packaging with +debhelper+.
+
+An example +debian/control+ snippet is given below:
+
+--------------------------------------------------------------------------
+Package: foobar-cluster-agents
+Priority: extra
+Architecture: all
+Depends: cluster-agents
+Description: OCF-compliant resource agents for Foobar
+--------------------------------------------------------------------------
+
+You will also create a separate +.install+ file. Sticking with the
+example of installing the +foobar+ resource agent as a sub-package of
++fortytwo+, the +debian/fortytwo-cluster-agents.install+ file could
+consist of the following content:
+
+--------------------------------------------------------------------------
+usr/lib/ocf/resource.d/fortytwo/foobar
+--------------------------------------------------------------------------
+
+=== Submitting resource agents
+
+If you choose not to bundle your resource agent with your own package,
+but instead wish to submit it to the upstream resource agent
+repository hosted on
+https://github.com/ClusterLabs/resource-agents[the ClusterLabs
+repository on GitHub], please follow the steps outlined in this section.
+
+Create a working copy (a Git _clone_) of the upstream repository
+with the following command:
+
+--------------------------------------------------------------------------
+git clone git://github.com/ClusterLabs/resource-agents
+--------------------------------------------------------------------------
+
+Then, copy your resource agent into the +heartbeat+ subdirectory:
+--------------------------------------------------------------------------
+cd resource-agents/heartbeat
+cp /path/to/your/local/copy/of/foobar .
+chmod 0755 foobar
+cd ..
+--------------------------------------------------------------------------
+
+Next, modify the +Makefile.am+ file in +resource-agents/heartbeat+ and
+add your new resource agent to the +ocf_SCRIPTS+ list. This will make
+sure the agent is properly installed.
+
+Lastly, open Makefile.am in +resource-agents/doc/man+ and add
++ocf_heartbeat_<name>.7+ to the +man_MANS+ variable. This will
+automatically generate a resource agent manual page from its metadata,
+and then install that man page into the correct location.
+
+Now, add your new resource agents, and the two modifications to the
+Makefiles, to your changeset:
+
+--------------------------------------------------------------------------
+git add heartbeat/foobar
+git add heartbeat/Makefile.am
+git add doc/man/Makefile.am
+git commit
+--------------------------------------------------------------------------
+
+In your commit message, be sure to include a meaningful description,
+for example:
+--------------------------------------------------------------------------
+High: foobar: new resource agent
+
+This new resource agent adds functionality to manage a foobar service.
+It supports being configured as a primitive or as a master/slave set,
+and also optionally supports superfrobnication.
+--------------------------------------------------------------------------
+
+Now the patch set is good for review on the mailing list:
+--------------------------------------------------------------------------
+git send-email --to=linux-ha-dev at lists.linux-ha.org
+--------------------------------------------------------------------------
+
++git send-email+ will now roll all local commits not in the upstream
+repository into a nicely formatted email, and submit that to the
+mailing list. Please consult +man git-send-email+ for details on
+configuring and using +git send-email+.
+
+Once your new resource agent has been accepted for merging, one of the
+upstream developers will push your patch into the upstream
+repository. At that point, you can update your checkout from upstream,
+and remove your own patch set.
+
+--------------------------------------------------------------------------
+git reset --hard origin/master
+git pull
+--------------------------------------------------------------------------
+
+=== Maintaining resource agents
+
+If you maintain a specific resource agent, or you are making repeated
+contributions to the codebase, it's usually a good idea to maintain
+your own _fork_ of the +ClusterLabs/resource-agents+ repository on
+GitHub.
+
+To do so,
+
+* https://github.com/signup[Create a GitHub account] if you do not
+  have one already.
+* http://help.github.com/fork-a-repo/[Fork] the
+  https://github.com/ClusterLabs/resource-agents[+resource-agents+
+  repository].
+* Clone your personal fork into a local working copy.
+
+As you work on resource agents, *please* commit early, and commit
+often. You can always fold commits later with +git rebase -i+.
+
+Once you have made a number of changes that you would like others to
+review, push them to your GitHub fork and send a post to the
++linux-ha-dev+ mailing list pointing people to it.
+
+After the review is done, fix up your tree with any requested changes,
+and then issue a pull request. There are two ways of doing so:
+
+* You can use the +git request-pull+ utility to get a pre-populated
+  email skeleton summarizing your changesets. Add any information you
+  see fit, and send it to the list. It is a good idea to prefix your
+  email subject with +[GIT PULL]+ so upstream maintainers can pick the
+  message out easily.
+
+* You can also issue a pull request directly on GitHub. GitHub
+  automatically notifies upstream maintainers about new pull requests
+  by email. Please refer to
+  http://help.github.com/send-pull-requests/[github:help] for details
+  on initiating pull requests.
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
new file mode 100644
index 0000000..3bf569a
--- /dev/null
+++ b/doc/man/Makefile.am
@@ -0,0 +1,165 @@
+#
+# 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
+
+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_asterisk.7 \
+                          ocf_heartbeat_conntrackd.7 \
+                          ocf_heartbeat_db2.7 \
+                          ocf_heartbeat_dhcpd.7 \
+                          ocf_heartbeat_eDir88.7 \
+                          ocf_heartbeat_ethmonitor.7 \
+                          ocf_heartbeat_exportfs.7 \
+                          ocf_heartbeat_fio.7 \
+                          ocf_heartbeat_iSCSILogicalUnit.7 \
+                          ocf_heartbeat_iSCSITarget.7 \
+                          ocf_heartbeat_iface-bridge.7 \
+                          ocf_heartbeat_iface-vlan.7 \
+                          ocf_heartbeat_ids.7 \
+                          ocf_heartbeat_iscsi.7 \
+                          ocf_heartbeat_jboss.7 \
+                          ocf_heartbeat_lxc.7 \
+                          ocf_heartbeat_mysql.7 \
+                          ocf_heartbeat_mysql-proxy.7 \
+                          ocf_heartbeat_named.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_pound.7 \
+                          ocf_heartbeat_proftpd.7 \
+                          ocf_heartbeat_rsyncd.7 \
+                          ocf_heartbeat_rsyslog.7 \
+                          ocf_heartbeat_scsi2reservation.7 \
+                          ocf_heartbeat_sfex.7 \
+                          ocf_heartbeat_slapd.7 \
+                          ocf_heartbeat_symlink.7 \
+                          ocf_heartbeat_syslog-ng.7 \
+                          ocf_heartbeat_tomcat.7 \
+                          ocf_heartbeat_varnish.7 \
+                          ocf_heartbeat_vmware.7 \
+                          ocf_heartbeat_zabbixserver.7
+
+if USE_IPV6ADDR_AGENT
+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: ocf_resource_agents.xml
+endif
diff --git a/doc/man/mkappendix.sh b/doc/man/mkappendix.sh
new file mode 100755
index 0000000..8f8a622
--- /dev/null
+++ b/doc/man/mkappendix.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+cat <<EOF
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<appendix id="ap-ra-man-pages">
+  <title>Resource agent manual pages</title>
+EOF
+
+for manpage in `printf "%s\n" $@ | sort -f`; do
+    cat <<EOF
+  <xi:include href="./$manpage" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+EOF
+done
+
+cat <<EOF
+</appendix>
+EOF
diff --git a/doc/man/ra2refentry.xsl b/doc/man/ra2refentry.xsl
new file mode 100644
index 0000000..41a60aa
--- /dev/null
+++ b/doc/man/ra2refentry.xsl
@@ -0,0 +1,539 @@
+<?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 -->
+ <!-- would be so much easier with replace(...) -->
+
+<xsl:template name="break_into_para">
+    <xsl:param name="string" />
+
+    <xsl:choose>
+    <xsl:when test="starts-with($string, '&#xA;') or starts-with($string, ' ')" >
+	<!-- trim leading newlines and other witespace -->
+	<xsl:variable name="normalized" select="normalize-space($string)" />
+	<xsl:variable name="nlen" select="string-length($normalized)" />
+	<xsl:if test="$nlen > 0" >
+	    <xsl:variable name="leading" select="string-length(substring-before($string, substring($normalized, 1, 1)))" />
+            <xsl:call-template name="break_into_para">
+	    <xsl:with-param name="string" select="substring($string, $leading + 1)" />
+            </xsl:call-template>
+	</xsl:if>
+    </xsl:when>
+    <xsl:otherwise>
+
+    <xsl:variable name="lf" select="'&#xA;&#xA;'" />
+    <xsl:variable name="lf_dash" select="'&#xA;-'" />
+    <xsl:choose>
+        <xsl:when test="contains($string, $lf)">
+            <xsl:variable name="first" select="substring-before($string, $lf)" />
+           <!-- recursively call on remaining string -->
+            <xsl:call-template name="break_into_para">
+	    <xsl:with-param name="string" select="$first"/>
+            </xsl:call-template>
+            <xsl:call-template name="break_into_para">
+	    <xsl:with-param name="string" select="substring-after($string, $lf)" />
+            </xsl:call-template>
+        </xsl:when>
+        <xsl:when test="contains($string, $lf_dash)">
+            <xsl:variable name="first" select="substring-before($string, $lf_dash)" />
+           <!-- recursively call on remaining string -->
+            <xsl:call-template name="break_into_para">
+	    <xsl:with-param name="string" select="$first"/>
+            </xsl:call-template>
+            <xsl:call-template name="break_into_para">
+	    <xsl:with-param name="string" select="concat('-',substring-after($string, $lf_dash))" />
+            </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+            <para>
+	    <xsl:value-of select="'&#xA;'"/>
+	    <xsl:value-of select="$string"/>
+	    <xsl:value-of select="'&#xA;'"/>
+            </para>
+	    <xsl:value-of select="'&#xA;'"/>
+        </xsl:otherwise>
+    </xsl:choose>
+    </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="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>
+
+  <xsl:template match="actions" mode="description">
+    <xsl:if test="action[@name = 'migrate_from' or @name = 'migrate_to']">
+      <para>This resource agent may be configured for <emphasis>native
+      migration</emphasis> if available in the cluster manager. For
+      Pacemaker, the
+      <parameter>allow-migrate="true"</parameter> meta
+      attribute enables native migration.</para>
+    </xsl:if>
+    <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>
+	<xsl:apply-templates select="longdesc" mode="parameters"/>
+	<para>
+	<xsl:apply-templates select="content" mode="parameters"/>
+	</para>
+    </listitem>
+   </varlistentry>
+  </xsl:template>
+
+  <xsl:template match="longdesc" 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:if test="../@unique = 1">
+	<xsl:text>unique, </xsl:text>
+      </xsl:if>
+      <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>
+	    <xsl:if test="@type = 'string'">
+	      <xsl:text>"</xsl:text>
+	    </xsl:if>
+	    <code>
+	      <xsl:value-of select="@default"/>
+	    </code>
+	    <xsl:if test="@type = 'string'">
+	      <xsl:text>"</xsl:text>
+	    </xsl:if>
+	  </xsl:when>
+	  <xsl:when test="@type='boolean' and @default = ''">
+	    <xsl:text>default </xsl:text>
+	    <code>false</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 p_</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:choose>
+	  <xsl:when test="parameters/parameter[@required = 1]">
+	    <xsl:value-of select="@name"/>
+	    <xsl:text> \
+  params \
+</xsl:text>
+	    <xsl:apply-templates select="parameters" mode="example"/>
+	  </xsl:when>
+	  <xsl:otherwise>
+	  <xsl:value-of select="@name"/><xsl:text> \</xsl:text>
+	  </xsl:otherwise>
+	</xsl:choose>
+	<!-- Insert a suggested allow-migrate meta attribute if the
+	     resource agent supports migration -->
+	<xsl:if test="actions/action[@name = 'migrate_from' or @name = 'migrate_to']">
+	  <xsl:text>
+  meta allow-migrate="true" \</xsl:text>
+	</xsl:if>
+	<xsl:apply-templates select="actions" mode="example"/>
+      </programlisting>
+      <!-- Insert a master/slave set definition if the resource
+      agent supports promotion and demotion -->
+      <xsl:if test="actions/action/@name = 'promote' and actions/action/@name = 'demote'">
+	<programlisting>
+	  <xsl:text>ms ms_</xsl:text>
+	  <xsl:value-of select="@name"/>
+	  <xsl:text> p_</xsl:text>
+	  <xsl:value-of select="@name"/>
+	<xsl:text> \
+  meta notify="true" interleave="true"</xsl:text>
+	</programlisting>
+      </xsl:if>
+    </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:if test="following-sibling::action/@name = 'monitor'">
+      <xsl:text>\</xsl:text>
+    </xsl:if>
+  </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/doc/man/ralist.sh b/doc/man/ralist.sh
new file mode 100755
index 0000000..ef8f528
--- /dev/null
+++ b/doc/man/ralist.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+RADIR=$1
+PREFIX=$2
+SUFFIX=$3
+
+for f in `find $RADIR -type f -executable`; do
+    echo ${PREFIX}`basename $f`${SUFFIX}
+done
diff --git a/heartbeat/AoEtarget b/heartbeat/AoEtarget
new file mode 100755
index 0000000..b18b3a0
--- /dev/null
+++ b/heartbeat/AoEtarget
@@ -0,0 +1,245 @@
+#!/bin/bash
+#
+#
+# AoEtarget OCF RA. 
+# Manages an ATA-over-Ethernet (AoE) target utilizing the vblade utility.
+#
+#   (c) 2009-2010 Florian Haas, Dejan Muhamedagic,
+#                 and Linux-HA contributors
+#
+# 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.
+#
+
+######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+OCF_RESKEY_nic_default="eth0"
+OCF_RESKEY_pid_default="${HA_RSCTMP}/AoEtarget-${OCF_RESOURCE_INSTANCE}.pid"
+OCF_RESKEY_binary_default="/usr/sbin/vblade"
+
+: ${OCF_RESKEY_nic=${OCF_RESKEY_nic_default}}
+: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
+: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
+
+#######################################################################
+
+meta_data() {
+    cat <<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="AoEtarget" version="0.1">
+  <version>1.0</version>
+  <longdesc lang="en">
+This resource agent manages an ATA-over-Ethernet (AoE) target using vblade.
+It exports any block device, or file, as an AoE target using the 
+specified Ethernet device, shelf, and slot number.
+</longdesc>
+  <shortdesc lang="en">Manages ATA-over-Ethernet (AoE) target exports</shortdesc>
+  <parameters>
+    <parameter name="device" required="1">
+      <longdesc lang="en">
+The local block device (or file) to export as an AoE target.
+</longdesc>
+      <shortdesc lang="en">Device to export</shortdesc>
+      <content type="string"/>
+    </parameter>
+    <parameter name="nic" required="1">
+      <longdesc lang="en">
+The local Ethernet interface to use for exporting this AoE target.
+</longdesc>
+      <shortdesc lang="en">Ethernet interface</shortdesc>
+      <content type="string" default="${OCF_RESKEY_nic_default}"/>
+    </parameter>
+    <parameter name="shelf" required="0">
+      <longdesc lang="en">
+The AoE shelf number to use when exporting this target.
+</longdesc>
+      <shortdesc lang="en">AoE shelf number</shortdesc>
+      <content type="integer"/>
+    </parameter>
+    <parameter name="slot" required="1">
+      <longdesc lang="en">
+The AoE slot number to use when exporting this target.
+</longdesc>
+      <shortdesc lang="en">AoE slot number</shortdesc>
+      <content type="integer"/>
+    </parameter>
+    <parameter name="pid" required="0" unique="1">
+      <longdesc lang="en">
+The file to record the daemon pid to.
+</longdesc>
+      <shortdesc lang="en">Daemon pid file</shortdesc>
+      <content type="string" default="${OCF_RESKEY_pid_default}"/>
+    </parameter>
+    <parameter name="binary" required="0">
+      <longdesc lang="en">
+Location of the vblade binary.
+</longdesc>
+      <shortdesc lang="en">vblade binary</shortdesc>
+      <content type="string" default="${OCF_RESKEY_binary_default}"/>
+    </parameter>
+  </parameters>
+  <actions>
+    <action name="start" timeout="15"/>
+    <action name="stop" timeout="15"/>
+    <action name="monitor" timeout="15" interval="10" depth="0"/>
+    <action name="reload" timeout="15"/>
+    <action name="meta-data" timeout="5"/>
+    <action name="validate-all" timeout="15"/>
+  </actions>
+</resource-agent>
+EOF
+}
+
+#######################################################################
+
+AoEtarget_usage() {
+	cat <<END
+usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+AoEtarget_start() {
+    AoEtarget_monitor
+    if [ $? =  $OCF_SUCCESS ]; then
+	return $OCF_SUCCESS
+    fi
+    ocf_log info "Exporting device ${OCF_RESKEY_device} on ${OCF_RESKEY_nic} as shelf ${OCF_RESKEY_shelf}, slot ${OCF_RESKEY_slot}"
+    ${OCF_RESKEY_binary} ${OCF_RESKEY_shelf} ${OCF_RESKEY_slot} \
+	${OCF_RESKEY_nic} ${OCF_RESKEY_device} 2>&1 &
+    rc=$?
+    pid=$!
+    if [ $rc -ne 0 ]; then
+	return $OCF_ERR_GENERIC
+    fi
+    echo $pid > ${OCF_RESKEY_pid} && return $OCF_SUCCESS
+    return $OCF_ERR_GENERIC
+}
+
+AoEtarget_stop() {
+    AoEtarget_monitor
+    if [ $? -eq  $OCF_SUCCESS ]; then
+	ocf_log info "Unxporting device ${OCF_RESKEY_device} on ${OCF_RESKEY_nic} as shelf ${OCF_RESKEY_shelf}, slot ${OCF_RESKEY_slot}"
+	pid=$(cat ${OCF_RESKEY_pid})
+	kill -TERM $pid
+	# loop until we're really stopped, wait for the LRM to time us
+	# out if not
+	while AoEtarget_monitor; do
+	    sleep 1
+	done
+    fi
+    # Clean up pid file
+    rm -f ${OCF_RESKEY_pid}
+    return $OCF_SUCCESS
+}
+
+AoEtarget_monitor() {
+    ocf_pidfile_status ${OCF_RESKEY_pid} >/dev/null 2>&1
+    rc=$?
+    if [ $rc -eq 2 ]; then
+	# no pid file, must assume we're not running
+	return $OCF_NOT_RUNNING
+    elif [ $rc -eq 1 ]; then
+	# stale pid file, assume something went wrong
+	return $OCF_ERR_GENERIC
+    fi
+    return $OCF_SUCCESS
+}
+
+AoEtarget_validate() {
+    # Is our binary executable?
+    if [ ! -x ${OCF_RESKEY_binary} ]; then
+	ocf_log error "${OCF_RESKEY_binary} not found or not executable"
+	return $OCF_ERR_INSTALLED
+    fi
+
+    # Do we have all required variables?
+    for var in device nic shelf slot pid; do
+	param="OCF_RESKEY_${var}"
+	if [ -z "${!param}" ]; then
+	    ocf_log error "Missing resource parameter \"$var\"!"
+	    return $OCF_ERR_CONFIGURED
+	fi
+    done
+
+    # Is the pid file directory writable? 
+    pid_dir=`dirname "$OCF_RESKEY_pid"`
+    touch "$pid_dir/$$"
+    if [ $? != 0 ]; then
+	ocf_log error "Cannot create pid file in $pid_dir -- check directory permissions"
+	return $OCF_ERR_INSTALLED
+    fi
+    rm "$pid_dir/$$"
+
+    # Does the device we are trying to export exist?
+    if [ ! -e ${OCF_RESKEY_device} ]; then
+	ocf_log error "${OCF_RESKEY_device} does not exist"
+	return $OCF_ERR_INSTALLED
+    fi
+    return $OCF_SUCCESS
+}
+
+case $1 in
+  meta-data)
+	meta_data
+	exit $OCF_SUCCESS
+	;;
+  usage|help)
+	AoEtarget_usage
+	exit $OCF_SUCCESS
+	;;
+esac
+
+# Everything except usage and meta-data must pass the validate test
+AoEtarget_validate || exit $?
+
+case $__OCF_ACTION in
+    start)
+	AoEtarget_start
+	;;
+    stop)
+	AoEtarget_stop
+	;;
+    status|monitor)
+	AoEtarget_monitor
+	;;
+    reload)
+	ocf_log err "Reloading..."
+	AoEtarget_start
+	;;
+    validate-all)
+	AoEtarget_validate
+	;;
+    *)
+	AoEtarget_usage
+	exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
+
diff --git a/heartbeat/AudibleAlarm b/heartbeat/AudibleAlarm
new file mode 100755
index 0000000..d3c1149
--- /dev/null
+++ b/heartbeat/AudibleAlarm
@@ -0,0 +1,188 @@
+#!/bin/sh
+#
+# Startup script for the Audible Alarm
+#
+# author: Kirk Lawson <lklawson at heapy.com> 
+#         Horms <horms at vergenet.net>
+#
+# description: sets an audible alarm running by beeping at a set interval
+# processname: alarm
+# config: /etc/AudibleAlarm/AudibleAlarm.conf - not yet implemented
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_nodelist
+#		
+# License: GNU General Public License (GPL)
+
+#######################################################################
+# Source function library.
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+PIDFILE=${HA_VARRUN}/heartbeat-bell
+#For testing
+#PIDFILE=/tmp/heartbeat-bell
+
+# What host are we running on?
+us=`uname -n`
+
+usage() {
+	echo "Usage: $0 {start|stop|restart|status|monitor|meta-data|validate-all}"
+	echo "  The node list is an optional space delimited"
+	echo "  list of hosts that should never sound the alarm."
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="AudibleAlarm">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for AudibleAlarm. It sets an audible alarm running by beeping 
+at a set interval. 
+</longdesc>
+<shortdesc lang="en">Emits audible beeps at a configurable interval</shortdesc>
+
+<parameters>
+<parameter name="nodelist" unique="0">
+<longdesc lang="en">
+The node list that should never sound the alarm.
+</longdesc>
+<shortdesc lang="en">Node list</shortdesc>
+<content type="string" default="" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="10" />
+<action name="stop" timeout="10" />
+<action name="restart" timeout="10" />
+<action name="status" depth="0" timeout="10" interval="10" />
+<action name="monitor" depth="0" timeout="10" interval="10" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+audiblealarm_start () {
+	ocf_log info "$0: Starting"
+    	if [ -f $PIDFILE ]; then
+        	PID=`head -n 1 $PIDFILE`
+		if [ -n "$PID" ]; then
+		  ocf_log info "$0: Appears to already be running, killing [$PID]"
+		  kill $PID > /dev/null
+		fi
+	fi
+	# Use () to create a subshell to make the redirection be synchronized.
+	( while [ 1 ]; do 
+		sleep 1  #Sleep first, incase we bail out
+		printf "\a" > /dev/console
+		# Uncomment this line to cause floppy drive light
+		# to flash (requires fdutils package).
+		# /usr/bin/floppycontrol --pollstate > /dev/null
+		#
+		# To avoid issues when called by lrmd, redirect stdout->stderr.
+	done &
+	if echo $! >  $PIDFILE; then
+		:
+	else
+		ocf_log info "$0: Could not write to pid file \"$PIDFILE\", bailing"
+		kill $!
+		return $OCF_ERR_GENERIC
+	fi) >&2
+
+	return $?
+}
+
+audiblealarm_stop () {
+	ocf_log info "$0: Shutting down"
+  	if [ -f $PIDFILE ]; then
+		PID=`head -n 1 $PIDFILE`
+		# ocf_log info "$0: Appears to already be running, killing [$PID]"
+		# commented by Phost, since the confusion in the log.
+
+		if [ -n "$PID" ]; then
+		# Donnot remove PIDFILE in case the `kill` fails.
+		  kill $PID > /dev/null && rm -f $PIDFILE
+		fi	
+	fi
+
+	return $?
+}
+
+audiblealarm_restart () {
+	audiblealarm_stop 
+	audiblealarm_start 
+
+	return $?
+}
+
+audiblealarm_status () {
+  	if [ -f $PIDFILE ]; then
+		PID=`head -n 1 $PIDFILE`
+		if [ -n "$PID" ]; then
+			echo running
+			return $OCF_SUCCESS
+		fi
+	fi
+
+	echo stopped
+	return $OCF_NOT_RUNNING
+}
+
+audiblealarm_validate_all () {
+	check_binary printf
+
+	echo "Validate OK"
+	return $OCF_SUCCESS
+}
+if [ $# -ne 1 ]; then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+case "$1" in
+   meta-data)		
+	meta_data
+	exit $OCF_SUCCESS
+	;;
+   start)
+	for arg in $OCF_RESKEY_nodelist
+ 	  do
+	    if [ "$us" = "$arg" ]; then
+	      # We should not start because we are on a host
+	      # listed in our argument list.
+              exit $OCF_SUCCESS
+	    fi
+	  done
+	audiblealarm_start
+	;;
+  stop)
+	audiblealarm_stop
+	;;
+  restart)
+	audiblealarm_restart 
+	;;
+  status|monitor)
+	audiblealarm_status 
+	;;
+  validate-all)
+	audiblealarm_validate_all
+	;;
+  usage)
+	usage 
+	exit $OCF_SUCCESS
+	;;
+
+  *)
+	usage
+	exit $OCF_ERR_ARGS
+	;;
+esac
+
+exit $?
diff --git a/heartbeat/CTDB b/heartbeat/CTDB
new file mode 100755
index 0000000..8c82322
--- /dev/null
+++ b/heartbeat/CTDB
@@ -0,0 +1,737 @@
+#!/bin/sh
+#
+#             OCF Resource Agent for managing CTDB
+#
+# Copyright (c) 2009-2010 Novell Inc., Tim Serong
+#                    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.
+#
+#
+# OVERVIEW
+#
+# When run by itself, CTDB can handle IP failover and includes scripts
+# to manage various services (Samba, Winbind, HTTP, etc.).  When run as
+# a resource in a Pacemaker cluster, this additional functionality
+# should not be used; instead one should define separate resources for
+# CTDB, Samba, Winbind, IP addresses, etc.
+#
+# As of 2010-11-17, there is no separate OCF Samba or Winbind RA, so
+# it is still possible to configure CTDB so that it manages these
+# resources itself.  In future, once Samba and Winbind RAs are
+# available, this ability will be deprecated and ultimately removed.
+#
+# This RA intentionally provides no ability to configure CTDB such that
+# it manages IP failover, HTTP, NFS, etc.
+#
+#
+# TODO:
+# - ctdb_stop doesn't really support multiple independent CTDB instances,
+#   unless they're running from distinct ctdbd binaries (it uses pkill
+#   $OCF_RESKEY_ctdbd_binary if "ctdb stop" doesn't work, which it might
+#   not under heavy load - this will kill all ctdbd instances on the
+#   system).  OTOH, running multiple CTDB instances per node is, well,
+#   AFAIK, completely crazy.  Can't run more than one in a vanilla CTDB
+#   cluster, with the CTDB init script.  So it might be nice to address
+#   this for complete semantic correctness of the RA, but shouldn't
+#   actually cause any trouble in real life.
+# - As much as possible, get rid of auto config generation
+#   - Especially smb.conf
+# - Verify timeouts are sane
+# - Monitor differentiate between error and not running?
+# - Do we need to verify globally unique setting?
+# - Should set CTDB_NODES to ${HA_RSCTMP}/ctdb (generated based on
+#   current nodes)
+# - Look at enabling set_ctdb_variables() if necessary.
+# - Probably possible for sysconfig file to not be restored if
+#   CTDB dies unexpectedly.
+#
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+# Default parameter values:
+
+# Some distro's ctdb package stores the persistent db in /var/lib/ctdb,
+# others store in /var/ctdb. This attempts to detect the correct default
+# directory.
+var_prefix="/var/lib/ctdb"
+if [ ! -d "$var_prefix" ] && [ -d "/var/ctdb" ]; then
+	var_prefix="/var/ctdb"
+fi
+
+: ${OCF_RESKEY_ctdb_manages_samba:=no}
+: ${OCF_RESKEY_ctdb_manages_winbind:=no}
+: ${OCF_RESKEY_ctdb_service_smb:=""}
+: ${OCF_RESKEY_ctdb_service_nmb:=""}
+: ${OCF_RESKEY_ctdb_service_winbind:=""}
+: ${OCF_RESKEY_ctdb_samba_skip_share_check:=yes}
+: ${OCF_RESKEY_ctdb_monitor_free_memory:=100}
+: ${OCF_RESKEY_ctdb_start_as_disabled:=no}
+
+: ${OCF_RESKEY_ctdb_config_dir:=/etc/ctdb}
+: ${OCF_RESKEY_ctdb_binary:=/usr/bin/ctdb}
+: ${OCF_RESKEY_ctdbd_binary:=/usr/sbin/ctdbd}
+: ${OCF_RESKEY_ctdb_socket:=${var_prefix}/ctdb.socket}
+: ${OCF_RESKEY_ctdb_dbdir:=${var_prefix}}
+: ${OCF_RESKEY_ctdb_logfile:=/var/log/ctdb/log.ctdb}
+: ${OCF_RESKEY_ctdb_debuglevel:=2}
+
+: ${OCF_RESKEY_smb_conf:=/etc/samba/smb.conf}
+: ${OCF_RESKEY_smb_passdb_backend:=tdbsam}
+: ${OCF_RESKEY_smb_idmap_backend:=tdb2}
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="CTDB" version="1.0">
+<version>1.0</version>
+
+<longdesc lang="en">
+This resource agent manages CTDB, allowing one to use Clustered Samba in a
+Linux-HA/Pacemaker cluster.  You need a shared filesystem (e.g. OCFS2 or GFS2) on
+which the CTDB lock will be stored.  Create /etc/ctdb/nodes containing a list
+of private IP addresses of each node in the cluster, then configure this RA
+as a clone.  This agent expects the samba and windbind resources
+to be managed outside of CTDB's control as a separate set of resources controlled
+by the cluster manager.  The optional support for enabling CTDB management of these
+daemons will be depreciated.
+
+For more information see http://linux-ha.org/wiki/CTDB_(resource_agent)
+</longdesc>
+<shortdesc lang="en">CTDB Resource Agent</shortdesc>
+
+<parameters>
+
+<parameter name="ctdb_recovery_lock" unique="1" required="1">
+<longdesc lang="en">
+The location of a shared lock file, common across all nodes.
+This must be on shared storage, e.g.: /shared-fs/samba/ctdb.lock
+</longdesc>
+<shortdesc lang="en">CTDB shared lock file</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="ctdb_manages_samba" unique="0" required="0">
+<longdesc lang="en">
+Should CTDB manage starting/stopping the Samba service for you?
+This will be deprecated in future, in favor of configuring a
+separate Samba resource.
+</longdesc>
+<shortdesc lang="en">Should CTDB manage Samba?</shortdesc>
+<content type="boolean" default="no" />
+</parameter>
+
+<parameter name="ctdb_manages_winbind" unique="0" required="0">
+<longdesc lang="en">
+Should CTDB manage starting/stopping the Winbind service for you?
+This will be deprecated in future, in favor of configuring a
+separate Winbind resource.
+</longdesc>
+<shortdesc lang="en">Should CTDB manage Winbind?</shortdesc>
+<content type="boolean" default="no" />
+</parameter>
+
+<parameter name="ctdb_service_smb" unique="0" required="0">
+<longdesc lang="en">
+Name of smb init script.  Only necessary if CTDB is managing
+Samba directly.  Will usually be auto-detected.
+</longdesc>
+<shortdesc lang="en">Name of smb init script</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="ctdb_service_nmb" unique="0" required="0">
+<longdesc lang="en">
+Name of nmb init script.  Only necessary if CTDB is managing
+Samba directly.  Will usually be auto-detected.
+</longdesc>
+<shortdesc lang="en">Name of nmb init script</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="ctdb_service_winbind" unique="0" required="0">
+<longdesc lang="en">
+Name of winbind init script.  Only necessary if CTDB is managing
+Winbind directly.  Will usually be auto-detected.
+</longdesc>
+<shortdesc lang="en">Name of winbind init script</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="ctdb_samba_skip_share_check" unique="0" required="0">
+<longdesc lang="en">
+If there are very many shares it may not be feasible to check that all
+of them are available during each monitoring interval.  In that case
+this check can be disabled.
+</longdesc>
+<shortdesc lang="en">Skip share check during monitor?</shortdesc>
+<content type="boolean" default="yes" />
+</parameter>
+
+<parameter name="ctdb_monitor_free_memory" unique="0" required="0">
+<longdesc lang="en">
+If the amount of free memory drops below this value the node will
+become unhealthy and ctdb and all managed services will be shutdown.
+Once this occurs, the administrator needs to find the reason for the
+OOM situation, rectify it and restart ctdb with "service ctdb start".
+</longdesc>
+<shortdesc lang="en">Minimum amount of free memory (MB)</shortdesc>
+<content type="integer" default="100" />
+</parameter>
+
+<parameter name="ctdb_start_as_disabled" unique="0" required="0">
+<longdesc lang="en">
+When set to yes, the CTDB node will start in DISABLED mode and not
+host any public ip addresses.
+</longdesc>
+<shortdesc lang="en">Start CTDB disabled?</shortdesc>
+<content type="boolean" default="no" />
+</parameter>
+
+<parameter name="ctdb_config_dir" unique="0" required="0">
+<longdesc lang="en">
+The directory containing various CTDB configuration files.
+The "nodes" and "notify.sh" scripts are expected to be
+in this directory, as is the "events.d" subdirectory.
+</longdesc>
+<shortdesc lang="en">CTDB config file directory</shortdesc>
+<content type="string" default="/etc/ctdb" />
+</parameter>
+
+<parameter name="ctdb_binary" unique="0" required="0">
+<longdesc lang="en">
+Full path to the CTDB binary.
+</longdesc>
+<shortdesc lang="en">CTDB binary path</shortdesc>
+<content type="string" default="/usr/bin/ctdb" />
+</parameter>
+
+<parameter name="ctdbd_binary" unique="0" required="0">
+<longdesc lang="en">
+Full path to the CTDB cluster daemon binary.
+</longdesc>
+<shortdesc lang="en">CTDB Daemon binary path</shortdesc>
+<content type="string" default="/usr/sbin/ctdbd" />
+</parameter>
+
+<parameter name="ctdb_socket" unique="1" required="0">
+<longdesc lang="en">
+Full path to the domain socket that ctdbd will create, used for
+local clients to attach and communicate with the ctdb daemon.
+</longdesc>
+<shortdesc lang="en">CTDB socket location</shortdesc>
+<content type="string" default="${OCF_RESKEY_ctdb_socket}" />
+</parameter>
+
+<parameter name="ctdb_dbdir" unique="1" required="0">
+<longdesc lang="en">
+The directory to put the local CTDB database files in.
+Persistent database files will be put in ctdb_dbdir/persistent.
+</longdesc>
+<shortdesc lang="en">CTDB database directory</shortdesc>
+<content type="string" default="${OCF_RESKEY_ctdb_dbdir}" />
+</parameter>
+
+<parameter name="ctdb_logfile" unique="0" required="0">
+<longdesc lang="en">
+Full path to log file. To log to syslog instead, use the
+value "syslog".
+</longdesc>
+<shortdesc lang="en">CTDB log file location</shortdesc>
+<content type="string" default="/var/log/ctdb/log.ctdb" />
+</parameter>
+
+<parameter name="ctdb_debuglevel" unique="0" required="0">
+<longdesc lang="en">
+What debug level to run at (0-10). Higher means more verbose.
+</longdesc>
+<shortdesc lang="en">CTDB debug level</shortdesc>
+<content type="integer" default="2" />
+</parameter>
+
+<parameter name="smb_conf" unique="0" required="0">
+<longdesc lang="en">
+Path to default samba config file.  Only necessary if CTDB
+is managing Samba.
+</longdesc>
+<shortdesc lang="en">Path to smb.conf</shortdesc>
+<content type="string" default="/etc/samba/smb.conf" />
+</parameter>
+
+<parameter name="smb_private_dir" unique="1" required="0">
+<longdesc lang="en">
+The directory for smbd to use for storing such files as
+smbpasswd and secrets.tdb.  Old versions of CTBD (prior to 1.0.50)
+required this to be on shared storage.  This parameter should not
+be set for current versions of CTDB, and only remains in the RA
+for backwards compatibility.
+</longdesc>
+<shortdesc lang="en">Samba private dir (deprecated)</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="smb_passdb_backend" unique="0" required="0">
+<longdesc lang="en">
+Which backend to use for storing user and possibly group
+information.  Only necessary if CTDB is managing Samba.
+</longdesc>
+<shortdesc lang="en">Samba passdb backend</shortdesc>
+<content type="string" default="tdbsam" />
+</parameter>
+
+<parameter name="smb_idmap_backend" unique="0" required="0">
+<longdesc lang="en">
+Which backend to use for SID/uid/gid mapping.  Only necessary
+if CTDB is managing Samba.
+</longdesc>
+<shortdesc lang="en">Samba idmap backend</shortdesc>
+<content type="string" default="tdb2" />
+</parameter>
+
+<parameter name="smb_fileid_algorithm" unique="0" required="0">
+<longdesc lang="en">
+Which fileid:algorithm to use with vfs_fileid.  The correct
+value depends on which clustered filesystem is in use, e.g.:
+for OCFS2, this should be set to "fsid".  Only necessary if
+CTDB is managing Samba.
+</longdesc>
+<shortdesc lang="en">Samba VFS fileid algorithm</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="90" />
+<action name="stop"         timeout="100" />
+<action name="monitor"      timeout="20" interval="10" depth="0" />
+<action name="meta-data"    timeout="5" />
+<action name="validate-all"   timeout="30" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+# Figure out path to /etc/sysconfig/ctdb (same logic as
+# loadconfig() from /etc/ctdb/functions
+if [ -f /etc/sysconfig/ctdb ]; then
+	CTDB_SYSCONFIG=/etc/sysconfig/ctdb
+elif [ -f /etc/default/ctdb ]; then
+	CTDB_SYSCONFIG=/etc/default/ctdb
+elif [ -f $OCF_RESKEY_ctdb_config_dir/ctdb ]; then
+	CTDB_SYSCONFIG=$OCF_RESKEY_ctdb_config_dir/ctdb
+fi
+
+# Backup paths
+CTDB_SYSCONFIG_BACKUP=${CTDB_SYSCONFIG}.ctdb-ra-orig
+
+invoke_ctdb() {
+	# CTDB's defaults are:
+	local timeout=3
+	local timelimit=120
+	# ...but we override with the timeout for the current op:
+	if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
+		timeout=$((OCF_RESKEY_CRM_meta_timeout/1000))
+		timelimit=$((OCF_RESKEY_CRM_meta_timeout/1000))
+	fi
+	$OCF_RESKEY_ctdb_binary --socket=$OCF_RESKEY_ctdb_socket \
+		-t $timeout -T $timelimit \
+		"$@"
+}
+
+# Enable any event scripts that are explicitly required.
+# Any others will ultimately be invoked or not based on how they ship
+# with CTDB, but will generally have no effect, beacuase the relevant
+# CTDB_MANAGES_* options won't be set in /etc/sysconfig/ctdb.
+enable_event_scripts() {
+	local event_dir=$OCF_RESKEY_ctdb_config_dir/events.d
+
+	if [ -f "${OCF_RESKEY_ctdb_config_dir}/public_addresses" ]; then
+		chmod u+x $event_dir/10.interface
+	else
+		chmod a-x $event_dir/10.interface
+	fi
+	if [ -f "${OCF_RESKEY_ctdb_config_dir}/static-routes" ]; then
+		chmod u+x $event_dir/11.routing
+	else
+		chmod a-x $event_dir/11.routing
+	fi
+	if ocf_is_true "$OCF_RESKEY_ctdb_manages_samba" || \
+	   ocf_is_true "$OCF_RESKEY_ctdb_manages_winbind"; then
+		chmod u+x $event_dir/50.samba
+	else
+		chmod a-x $event_dir/50.samba
+	fi
+}
+
+# This function has no effect (currently no way to set CTDB_SET_*)
+# but remains here in case we need it in future.
+set_ctdb_variables() {
+	rv=$OCF_SUCCESS
+	set | grep ^CTDB_SET_ | cut -d_ -f3- |
+	while read v; do
+		varname=`echo $v | cut -d= -f1`
+		value=`echo $v | cut -d= -f2`
+		invoke_ctdb setvar $varname $value || rv=$OCF_ERR_GENERIC
+	done || rv=$OCF_ERR_GENERIC
+	return $rv
+}
+
+
+# Add necessary settings to /etc/samba/smb.conf.  In a perfect world,
+# we'd be able to generate a new, temporary, smb.conf file somewhere,
+# something like:
+#     include = /etc/samba/smb.conf
+#     [global]
+#       clustering = yes
+#       # ...etc...
+# Unfortunately, we can't do this, because there's no way to tell the
+# smb init script where the temporary config is, so we just edit
+# the default config file.
+init_smb_conf() {
+	# Don't screw around with the config if CTDB isn't managing Samba!
+	ocf_is_true "$OCF_RESKEY_ctdb_manages_samba" || return 0
+
+	# replace these things in smb.conf
+	local repl='# CTDB-RA:|passdb backend|clustering|idmap backend|private dir|ctdbd socket'
+
+	local private_dir
+	[ -n "$OCF_RESKEY_smb_private_dir" ] && private_dir="\tprivate dir = $OCF_RESKEY_smb_private_dir\n"
+
+	local vfs_fileid
+	local do_vfs=0
+	if  [ -n "$OCF_RESKEY_smb_fileid_algorithm" ]; then
+		repl="${repl}|fileid:algorithm|fileid:mapping"
+		vfs_fileid="\tfileid:algorithm = $OCF_RESKEY_smb_fileid_algorithm\n"
+		if sed -n '/^[[:space:]]*\[global\]/,/^[[:space:]]*\[/p' $OCF_RESKEY_smb_conf | \
+		   grep -Eq '^[[:space:]]*vfs objects'; then
+			# vfs objects already specified, will append fileid to existing line
+			do_vfs=1
+		else
+			vfs_fileid="$vfs_fileid\tvfs objects = fileid\n"
+		fi
+	fi
+	awk '
+		/^[[:space:]]*\[/ { global = 0 }
+		/^[[:space:]]*\[global\]/ { global = 1 }
+		{
+			if(global) {
+				if ('$do_vfs' && $0 ~ /^[[:space:]]vfs objects/ && $0 !~ /fileid/) {
+					print $0" fileid"
+				} else if ($0 !~ /^[[:space:]]*('"$repl"')/) {
+					print
+				}
+			} else {
+				print
+			}
+		}' $OCF_RESKEY_smb_conf | sed "/^[[:space:]]*\[global\]/ a\\
+\t# CTDB-RA: Begin auto-generated section (do not change below)\n\
+\tpassdb backend = $OCF_RESKEY_smb_passdb_backend\n\
+\tclustering = yes\n\
+\tidmap backend = $OCF_RESKEY_smb_idmap_backend\n\
+\tctdbd socket = $OCF_RESKEY_ctdb_socket\n$private_dir$vfs_fileid\
+\t# CTDB-RA: End auto-generated section (do not change above)" > $OCF_RESKEY_smb_conf.$$
+	mv -f $OCF_RESKEY_smb_conf.$$ $OCF_RESKEY_smb_conf
+}
+
+
+# Get rid of that section we added
+cleanup_smb_conf() {
+	ocf_is_true "$OCF_RESKEY_ctdb_manages_samba" || return 0
+
+	sed '/# CTDB-RA: Begin/,/# CTDB-RA: End/d' $OCF_RESKEY_smb_conf > $OCF_RESKEY_smb_conf.$$
+	mv -f $OCF_RESKEY_smb_conf.$$ $OCF_RESKEY_smb_conf
+}
+
+append_ctdb_sysconfig() {
+	[ -n "$2" ] && echo "$1=$2" >> $CTDB_SYSCONFIG
+}
+
+# Generate a new, minimal CTDB config file that's just enough
+# to get CTDB running as configured by the RA parameters.
+generate_ctdb_sysconfig() {
+	# Backup existing sysconfig if we're not already using an auto-generated one
+	grep -qa '# CTDB-RA: Auto-generated' $CTDB_SYSCONFIG || cp -p $CTDB_SYSCONFIG $CTDB_SYSCONFIG_BACKUP
+	if [ $? -ne 0 ]; then
+		ocf_log warn "Unable to backup $CTDB_SYSCONFIG to $CTDB_SYSCONFIG_BACKUP"
+	fi
+
+	ocf_log info "Generating new $CTDB_SYSCONFIG"
+
+	# Note to maintainers and other random hackers:
+	# Parameters may need to be set here, for CTDB event
+	# scripts to pick up, or may need to be passed to ctdbd
+	# when starting, or both.  Be careful.  The CTDB source
+	# tree and manpages are your friends.  As a concrete
+	# example, setting CTDB_START_AS_DISABLED here is
+	# completely useless, as this is actually a command line
+	# argument for ctdbd; it's not used anywhere else.
+
+	cat >$CTDB_SYSCONFIG <<EOF
+# CTDB-RA: Auto-generated by ${0}, backup is at $CTDB_SYSCONFIG_BACKUP
+CTDB_MONITOR_FREE_MEMORY=$OCF_RESKEY_ctdb_monitor_free_memory
+CTDB_SAMBA_SKIP_SHARE_CHECK=$(ocf_is_true "$OCF_RESKEY_ctdb_samba_skip_share_check" && echo 'yes' || echo 'no')
+CTDB_MANAGES_SAMBA=$(ocf_is_true "$OCF_RESKEY_ctdb_manages_samba" && echo 'yes' || echo 'no')
+CTDB_MANAGES_WINBIND=$(ocf_is_true "$OCF_RESKEY_ctdb_manages_winbind" && echo 'yes' || echo 'no')
+EOF
+	append_ctdb_sysconfig CTDB_SERVICE_SMB $OCF_RESKEY_ctdb_service_smb
+	append_ctdb_sysconfig CTDB_SERVICE_NMB $OCF_RESKEY_ctdb_service_nmb
+	append_ctdb_sysconfig CTDB_SERVICE_WINBIND $OCF_RESKEY_ctdb_service_winbind
+}
+
+
+ctdb_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+
+ctdb_start() {
+	# Do nothing if already running
+	ctdb_monitor && return $OCF_SUCCESS
+
+	# Make sure config is adequate
+	ctdb_validate
+	rv=$?
+	[ $rv -ne 0 ] && return $rv
+
+	# Die if databases are corrupted
+	persistent_db_dir="${OCF_RESKEY_ctdb_dbdir}/persistent"
+	mkdir -p $persistent_db_dir 2>/dev/null
+	for pdbase in $(ls $persistent_db_dir/*.tdb.[0-9] 2>/dev/null$) ; do
+		/usr/bin/tdbdump $pdbase >/dev/null 2>/dev/null || {
+			ocf_log err "Persistent database $pdbase is corrupted!  CTDB will not start."
+			return $OCF_ERR_GENERIC
+		}
+	done
+
+	# Add necessary configuration to smb.conf
+	init_smb_conf
+	if [ $? -ne 0 ]; then
+		ocf_log err "Failed to update $OCF_RESKEY_smb_conf."
+		return $OCF_ERR_GENERIC
+	fi
+
+	# Generate new CTDB sysconfig
+	generate_ctdb_sysconfig
+	enable_event_scripts
+
+	# Use logfile by default, or syslog if asked for
+	local log_option="--logfile=$OCF_RESKEY_ctdb_logfile"
+	if [ "$OCF_RESKEY_ctdb_logfile" = "syslog" ]; then
+		log_option="--syslog"
+	elif [ ! -d "$(dirname $OCF_RESKEY_ctdb_logfile)" ]; then
+		# ensure the logfile's directory exists, otherwise ctdb will fail to start
+		mkdir -p $(dirname $OCF_RESKEY_ctdb_logfile)
+	fi
+
+	# public addresses file (should not be present, but need to set for correctness if it is)
+	local pub_addr_option=""
+	[ -f "${OCF_RESKEY_ctdb_config_dir}/public_addresses" ] && \
+		pub_addr_option="--public-addresses=${OCF_RESKEY_ctdb_config_dir}/public_addresses"
+	# start as disabled
+	local start_as_disabled="--start-as-disabled"
+	ocf_is_true "$OCF_RESKEY_ctdb_start_as_disabled" || start_as_disabled=""
+
+	# Start her up
+	$OCF_RESKEY_ctdbd_binary \
+		--reclock=$OCF_RESKEY_ctdb_recovery_lock \
+		--nlist=$OCF_RESKEY_ctdb_config_dir/nodes \
+		--socket=$OCF_RESKEY_ctdb_socket \
+		--dbdir=$OCF_RESKEY_ctdb_dbdir \
+		--dbdir-persistent=$OCF_RESKEY_ctdb_dbdir/persistent \
+		--event-script-dir=$OCF_RESKEY_ctdb_config_dir/events.d \
+		--notification-script=$OCF_RESKEY_ctdb_config_dir/notify.sh \
+		--transport=tcp \
+		$start_as_disabled $log_option $pub_addr_option \
+		-d $OCF_RESKEY_ctdb_debuglevel
+	if [ $? -ne 0 ]; then
+		# cleanup smb.conf
+		cleanup_smb_conf
+		
+		ocf_log err "Failed to execute $OCF_RESKEY_ctdbd_binary."
+		return $OCF_ERR_GENERIC
+	else
+		# Wait a bit for CTDB to stabilize
+		# (until start times out if necessary)
+		while true; do
+			# Initial sleep is intentional (ctdb init script
+			# has sleep after ctdbd start, but before invoking
+			# ctdb to talk to it)
+			sleep 1
+			status=$(invoke_ctdb status 2>/dev/null)
+			if [ $? -ne 0 ]; then
+				# CTDB will be running, kill it before returning
+				ctdb_stop
+				ocf_log err "Can't invoke $OCF_RESKEY_ctdb_binary --socket=$OCF_RESKEY_ctdb_socket status"
+				return $OCF_ERR_GENERIC
+			fi
+			if ! echo $status | grep -qs 'UNHEALTHY (THIS'; then
+				# Status does not say this node is unhealthy,
+				# so we're good to go.  Do a bit of final
+				# setup and (hopefully) return success.
+				set_ctdb_variables
+				return $?
+			fi
+		done
+	fi
+	
+	# ctdbd will (or can) actually still be running at this point, so kill it
+	ctdb_stop
+	
+	ocf_log err "Timeout waiting for CTDB to stabilize"
+	return $OCF_ERR_GENERIC
+}
+
+
+ctdb_stop() {
+	# Do nothing if already stopped
+	pkill -0 -f $OCF_RESKEY_ctdbd_binary || return $OCF_SUCCESS
+	
+	# Tell it to die nicely
+	invoke_ctdb shutdown >/dev/null 2>&1
+	rv=$?
+
+	# No more Mr. Nice Guy
+	count=0
+	while pkill -0 -f $OCF_RESKEY_ctdbd_binary ; do
+		sleep 1
+		count=$(($count + 1))
+		[ $count -gt 10 ] && {
+			ocf_log info "killing ctdbd "
+			pkill -9 -f $OCF_RESKEY_ctdbd_binary
+			pkill -9 -f ${OCF_RESKEY_ctdb_config_dir}/events.d/
+		}
+	done
+
+	# Cleanup smb.conf
+	cleanup_smb_conf
+
+	# It was a clean shutdown, return success
+	[ $rv -eq $OCF_SUCCESS ] && return $OCF_SUCCESS
+
+	# Unclean shutdown, return success if there's no ctdbds left (we
+	# killed them forcibly, but at least they're good and dead).
+	pkill -0 -f $OCF_RESKEY_ctdbd_binary || return $OCF_SUCCESS
+
+	# Problem: ctdb shutdown didn't work and neither did some vigorous
+	# kill -9ing.  Only thing to do is report failure.
+	return $OCF_ERR_GENERIC
+}
+
+
+ctdb_monitor() {
+	local status
+	# "ctdb status" exits non-zero if CTDB isn't running.
+	# It can also exit non-zero if there's a timeout (ctdbd blocked,
+	# stalled, massive load, or otherwise wedged).  If it's actually
+	# not running, STDERR will say "Errno:Connection refused(111)",
+	# whereas if it's wedged, it'll say various other unpleasant things.
+	status=$(invoke_ctdb status 2>&1)
+	if [ $? -ne 0 ]; then
+		if echo $status | grep -qs 'Connection refused'; then
+			return $OCF_NOT_RUNNING
+		else
+			ocf_log err "CTDB status call failed: $status"
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+	if echo $status | grep -Eqs '(OK|DISABLED) \(THIS'; then
+		return $OCF_SUCCESS
+	fi
+
+	ocf_log err "CTDB status is bad: $status"
+	return $OCF_ERR_GENERIC
+}
+
+
+ctdb_validate() {
+	# Required binaries (full path to tdbdump is intentional, as that's
+	# what's used in ctdb_start, which was lifted from the init script)
+	for binary in pkill /usr/bin/tdbdump; do
+		check_binary $binary
+	done
+
+	if [ -z "$CTDB_SYSCONFIG" ]; then
+		ocf_log err "Can't find CTDB config file (expecting /etc/sysconfig/ctdb, /etc/default/ctdb or similar)"
+		return $OCF_ERR_INSTALLED
+	fi
+
+	if ocf_is_true "$OCF_RESKEY_ctdb_manages_samba" && [ ! -f "$OCF_RESKEY_smb_conf" ]; then
+		ocf_log err "Samba config file '$OCF_RESKEY_smb_conf' does not exist."
+		return $OCF_ERR_INSTALLED
+	fi
+
+	if [ -f "${OCF_RESKEY_ctdb_config_dir}/public_addresses" ]; then
+		ocf_log warn "CTDB file '${OCF_RESKEY_ctdb_config_dir}/public_addresses' exists - CTDB will try to manage IP failover!"
+	fi
+
+	if [ ! -f "$OCF_RESKEY_ctdb_config_dir/nodes" ]; then
+		ocf_log err "$OCF_RESKEY_ctdb_config_dir/nodes does not exist."
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_ctdb_recovery_lock" ]; then
+		ocf_log err "ctdb_recovery_lock not specified."
+		return $OCF_ERR_CONFIGURED
+	fi
+
+	lock_dir=$(dirname "$OCF_RESKEY_ctdb_recovery_lock")
+	touch "$lock_dir/$$" 2>/dev/null
+	if [ $? != 0 ]; then
+		ocf_log err "Directory for lock file '$OCF_RESKEY_ctdb_recovery_lock' does not exist, or is not writable."
+		return $OCF_ERR_ARGS
+	fi
+	rm "$lock_dir/$$"
+
+	return $OCF_SUCCESS
+}
+
+
+case $__OCF_ACTION in
+meta-data)	meta_data
+		exit $OCF_SUCCESS
+		;;
+start)		ctdb_start;;
+stop)		ctdb_stop;;
+monitor)	ctdb_monitor;;
+validate-all)	ctdb_validate;;
+usage|help)	ctdb_usage
+		exit $OCF_SUCCESS
+		;;
+*)		ctdb_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
diff --git a/heartbeat/ClusterMon b/heartbeat/ClusterMon
new file mode 100755
index 0000000..0e15664
--- /dev/null
+++ b/heartbeat/ClusterMon
@@ -0,0 +1,261 @@
+#!/bin/sh
+#
+#
+#	ClusterMon OCF RA.
+#	Starts crm_mon in background which logs cluster status as
+#	html to the specified file.
+#
+# Copyright (c) 2004 SUSE LINUX AG, Lars Marowsky-Br�e
+#                    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.
+#
+# OCF instance parameters:
+#	OCF_RESKEY_user
+#	OCF_RESKEY_pidfile
+#	OCF_RESKEY_update
+#	OCF_RESKEY_extra_options
+#	OCF_RESKEY_htmlfile
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="ClusterMon">
+<version>1.0</version>
+
+<longdesc lang="en">
+This is a ClusterMon Resource Agent.
+It outputs current cluster status to the html.
+</longdesc>
+<shortdesc lang="en">Runs crm_mon in the background, recording the cluster status to an HTML file</shortdesc>
+
+<parameters>
+
+<parameter name="user" unique="0">
+<longdesc lang="en">
+The user we want to run crm_mon as
+</longdesc>
+<shortdesc lang="en">The user we want to run crm_mon as</shortdesc>
+<content type="string" default="root" />
+</parameter>
+
+<parameter name="update" unique="0">
+<longdesc lang="en">
+How frequently should we update the cluster status
+</longdesc>
+<shortdesc lang="en">Update interval</shortdesc>
+<content type="integer" default="15" />
+</parameter>
+
+<parameter name="extra_options" unique="0">
+<longdesc lang="en">
+Additional options to pass to crm_mon.  Eg. -n -r
+</longdesc>
+<shortdesc lang="en">Extra options</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="pidfile" unique="1">
+<longdesc lang="en">
+PID file location to ensure only one instance is running
+</longdesc>
+<shortdesc lang="en">PID file</shortdesc>
+<content type="string" default="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.pid" />
+</parameter>
+
+<parameter name="htmlfile" unique="1" required="0">
+<longdesc lang="en">
+Location to write HTML output to.
+</longdesc>
+<shortdesc lang="en">HTML output</shortdesc>
+<content type="string" default="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.html" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start"   timeout="20" />
+<action name="stop"    timeout="20" />
+<action name="monitor" depth="0"  timeout="20" interval="10" />
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="30" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+ClusterMon_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+ClusterMon_exit() {
+	if [ $1 != 0 ]; then
+		exit $OCF_ERR_GENERIC
+	else
+		exit $OCF_SUCCESS
+	fi
+}
+
+ClusterMon_start() {
+    cmd_prefix=""
+    cmd_suffix=""
+    if [ ! -z $OCF_RESKEY_user ]; then
+	su - $OCF_RESKEY_user -c "${HA_SBIN_DIR}/crm_mon -p $OCF_RESKEY_pidfile -d -i $OCF_RESKEY_update $OCF_RESKEY_extra_options -h $OCF_RESKEY_htmlfile"
+    else
+	${HA_SBIN_DIR}/crm_mon -p $OCF_RESKEY_pidfile -d -i $OCF_RESKEY_update $OCF_RESKEY_extra_options -h $OCF_RESKEY_htmlfile
+    fi
+    ClusterMon_exit $?
+}
+
+ClusterMon_stop() {
+    if [ -f $OCF_RESKEY_pidfile ]; then
+	pid=`cat $OCF_RESKEY_pidfile`
+	if [ ! -z $pid ]; then
+	    kill -s 9 $pid
+	    rm -f $OCF_RESKEY_pidfile
+	fi
+    fi
+    ClusterMon_exit 0
+}
+
+ClusterMon_monitor() {
+    if [ -f $OCF_RESKEY_pidfile ]; then
+	pid=`cat $OCF_RESKEY_pidfile`
+	[ "$pid" ] && kill -s 0 $pid &&
+	    exit $OCF_SUCCESS
+    fi
+    exit $OCF_NOT_RUNNING
+}
+
+CheckOptions() {
+while getopts Vi:nrh:cdp: OPTION
+do
+    case $OPTION in
+    V|n|r|c|d);;
+    i)	ocf_log warn "You should not have specified the -i option, since OCF_RESKEY_update is set already!";;
+    h)	ocf_log warn "You should not have specified the -h option, since OCF_RESKEY_htmlfile is set already!";;
+    p)	ocf_log warn "You should not have specified the -p option, since OCF_RESKEY_pidfile is set already!";;
+    *)  return $OCF_ERR_ARGS;;
+    esac
+done		
+
+if [ $? -ne 0 ]; then
+    return $OCF_ERR_ARGS
+fi
+
+# We should have eaten all options at this stage
+shift $(($OPTIND -1))
+if [ $# -gt 0 ]; then
+    false
+else
+    true
+fi
+}
+
+ClusterMon_validate() {
+# Existence of the user
+    if [ ! -z $OCF_RESKEY_user ]; then
+	getent passwd "$OCF_RESKEY_user" >/dev/null
+	if [ $? -eq 0 ]; then
+	    : Yes, user exists. We can further check his permission on crm_mon if necessary
+	else
+	    ocf_log err "The user $OCF_RESKEY_user does not exist!"
+	    exit $OCF_ERR_ARGS
+	fi
+    fi
+
+# Pidfile better be an absolute path
+    case $OCF_RESKEY_pidfile in
+	/*) ;;
+	*) ocf_log warn "You should have pidfile($OCF_RESKEY_pidfile) of absolute path!" ;;
+    esac
+
+# Check the update interval
+    if ocf_is_decimal "$OCF_RESKEY_update" && [ $OCF_RESKEY_update -gt 0 ]; then
+	:
+    else
+	ocf_log err "Invalid update interval $OCF_RESKEY_update. It should be positive integer!"
+	exit $OCF_ERR_ARGS
+    fi
+
+    if CheckOptions $OCF_RESKEY_extra_options; then
+	:
+    else
+	ocf_log err "Invalid options $OCF_RESKEY_extra_options!"
+	exit $OCF_ERR_ARGS
+    fi
+
+# Htmlfile better be an absolute path
+    case $OCF_RESKEY_htmlfile in
+	/*) ;;
+	*) ocf_log warn "You should have htmlfile($OCF_RESKEY_htmlfile) of absolute path!" ;;
+    esac
+
+     
+    echo "Validate OK"
+    return $OCF_SUCCESS
+}
+
+if [ $# -ne 1 ]; then
+    ClusterMon_usage
+    exit $OCF_ERR_ARGS
+fi
+
+: ${OCF_RESKEY_update:="15000"}
+: ${OCF_RESKEY_pidfile:="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.pid"}
+: ${OCF_RESKEY_htmlfile:="/tmp/ClusterMon_${OCF_RESOURCE_INSTANCE}.html"}
+
+OCF_RESKEY_update=`expr $OCF_RESKEY_update / 1000`
+
+case $__OCF_ACTION in
+meta-data)	meta_data
+		exit $OCF_SUCCESS
+		;;
+start)		ClusterMon_start
+		;;
+stop)		ClusterMon_stop
+		;;
+monitor)	ClusterMon_monitor
+		;;
+validate-all)	ClusterMon_validate
+		;;
+usage|help)	ClusterMon_usage
+		exit $OCF_SUCCESS
+		;;
+*)		ClusterMon_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+
+exit $?
diff --git a/heartbeat/Delay b/heartbeat/Delay
new file mode 100755
index 0000000..f505391
--- /dev/null
+++ b/heartbeat/Delay
@@ -0,0 +1,223 @@
+#!/bin/sh
+#
+#
+# Support:      linux-ha at lists.linux-ha.org
+# License:      GNU General Public License (GPL)
+#
+#	This script is a test resource for introducing delay.
+#
+#	usage: $0  {start|stop|status|monitor|meta-data}
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_startdelay
+#		OCF_RESKEY_stopdelay
+#		OCF_RESKEY_mondelay
+#
+#	
+#		OCF_RESKEY_startdelay defaults to 30 (seconds)
+#		OCF_RESKEY_stopdelay defaults to $OCF_RESKEY_startdelay
+#		OCF_RESKEY_mondelay defaults to $OCF_RESKEY_startdelay
+#
+#
+#	This is really a test resource script.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+usage() {
+  cat <<-!
+	usage: $0 {start|stop|status|monitor|meta-data|validate-all}
+	!
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Delay">
+<version>1.0</version>
+
+<longdesc lang="en">
+This script is a test resource for introducing delay.
+</longdesc>
+<shortdesc lang="en">Waits for a defined timespan</shortdesc>
+
+<parameters>
+
+<parameter name="startdelay" unique="0" required="0">
+<longdesc lang="en">
+How long in seconds to delay on start operation.
+</longdesc>
+<shortdesc lang="en">Start delay</shortdesc>
+<content type="integer" default="30" />
+</parameter>
+
+<parameter name="stopdelay" unique="0"  required="0">
+<longdesc lang="en">
+How long in seconds to delay on stop operation.
+Defaults to "startdelay" if unspecified.
+</longdesc>
+<shortdesc lang="en">Stop delay</shortdesc>
+<content type="integer" default="30" />
+</parameter>
+
+<parameter name="mondelay" unique="0"  required="0">
+<longdesc lang="en">
+How long in seconds to delay on monitor operation.
+Defaults to "startdelay" if unspecified.
+</longdesc>
+<shortdesc lang="en">Monitor delay</shortdesc>
+<content type="integer" default="30" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="30" />
+<action name="stop" timeout="30" />
+<action name="status" depth="0" timeout="30" interval="10" />
+<action name="monitor" depth="0" timeout="30" interval="10" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+Delay_stat() {
+	ha_pseudo_resource Delay_${OCF_RESOURCE_INSTANCE} monitor
+}
+
+Delay_Status() {
+  if
+    Delay_stat
+  then
+    ocf_log info "Delay is running OK"
+    return $OCF_SUCCESS
+  else
+    ocf_log info "Delay is stopped"
+    return $OCF_NOT_RUNNING
+  fi
+}
+
+Delay_Monitor() {
+  Delay_Validate_All -q
+  sleep $OCF_RESKEY_mondelay
+  Delay_Status
+}
+
+Delay_Start() {
+  if
+    Delay_stat
+  then
+    ocf_log info "Delay already running."
+    return $OCF_SUCCESS
+  else
+    Delay_Validate_All -q
+	ha_pseudo_resource Delay_${OCF_RESOURCE_INSTANCE} start
+    rc=$?
+    sleep $OCF_RESKEY_startdelay
+    if
+      [ $rc -ne 0 ]
+    then
+      return $OCF_ERR_PERM
+    fi
+    return $OCF_SUCCESS
+  fi
+}
+
+Delay_Stop() {
+  if
+    Delay_stat
+  then
+    Delay_Validate_All -q
+	ha_pseudo_resource Delay_${OCF_RESOURCE_INSTANCE} stop
+    rc=$?
+    sleep $OCF_RESKEY_stopdelay
+    if
+      [ $rc -ne 0 ]
+    then
+      return $OCF_ERR_PERM
+    fi
+    return $OCF_SUCCESS
+  else
+    ocf_log info "Delay already stopped."
+    return $OCF_SUCCESS
+  fi
+}
+
+# Check if all the arguments are valid numbers, a string is considered valid if:
+# 1. It does not contain any character but digits and period ".";
+# 2. The period "." does not occur more than once
+
+Are_Valid_Numbers() {
+  for i in "$@"; do
+	echo $i |grep -v [^0-9.] |grep -q -v [.].*[.]
+	if test $? -ne 0; then
+	  return $OCF_ERR_ARGS
+	fi
+  done
+  return $OCF_SUCCESS
+}
+
+Delay_Validate_All() {
+# Be quiet when specified -q option _and_ validation succeded
+  getopts "q" option
+
+  if test $option = "q"; then
+	quiet=yes
+  else
+	quiet=no
+  fi
+  shift $(($OPTIND -1))
+
+  if Are_Valid_Numbers $OCF_RESKEY_startdelay $OCF_RESKEY_stopdelay \
+	$OCF_RESKEY_mondelay; then
+    if test $quiet = "no"; then
+	echo "Validate OK"
+    fi
+# _Return_ on validation success
+	return $OCF_SUCCESS
+  else
+	echo "Some of the instance parameters are invalid"
+# _Exit_ on validation failure
+	exit $OCF_ERR_ARGS
+  fi
+}
+
+if [ $# -ne 1 ]; then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+: ${OCF_RESKEY_startdelay=30}
+: ${OCF_RESKEY_stopdelay=$OCF_RESKEY_startdelay}
+: ${OCF_RESKEY_mondelay=$OCF_RESKEY_startdelay}
+
+case $1 in
+  meta-data)		meta_data
+			exit $OCF_SUCCESS
+			;;
+  start)		Delay_Start
+			;;
+  stop)			Delay_Stop
+			;;
+  monitor)		Delay_Monitor
+			;;
+  status)		Delay_Status
+			;;
+  validate-all)		Delay_Validate_All
+			;;
+  usage)		usage
+			exit $OCF_SUCCESS
+			;;
+  *)			usage
+			exit $OCF_ERR_ARGS
+			;;
+esac
+exit $?
diff --git a/heartbeat/Dummy b/heartbeat/Dummy
new file mode 100755
index 0000000..dd79814
--- /dev/null
+++ b/heartbeat/Dummy
@@ -0,0 +1,174 @@
+#!/bin/sh
+#
+#
+#	Dummy OCF RA. Does nothing but wait a few seconds, can be
+#	configured to fail occassionally.
+#
+# Copyright (c) 2004 SUSE LINUX AG, Lars Marowsky-Br�e
+#                    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.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Dummy" version="0.9">
+<version>1.0</version>
+
+<longdesc lang="en">
+This is a Dummy Resource Agent. It does absolutely nothing except 
+keep track of whether its running or not.
+Its purpose in life is for testing and to serve as a template for RA writers.
+
+NB: Please pay attention to the timeouts specified in the actions
+section below. They should be meaningful for the kind of resource
+the agent manages. They should be the minimum advised timeouts,
+but they shouldn't/cannot cover _all_ possible resource
+instances. So, try to be neither overly generous nor too stingy,
+but moderate. The minimum timeouts should never be below 10 seconds.
+</longdesc>
+<shortdesc lang="en">Example stateless resource agent</shortdesc>
+
+<parameters>
+<parameter name="state" unique="1">
+<longdesc lang="en">
+Location to store the resource state in.
+</longdesc>
+<shortdesc lang="en">State file</shortdesc>
+<content type="string" default="${HA_RSCTMP}/Dummy-${OCF_RESOURCE_INSTANCE}.state" />
+</parameter>
+
+<parameter name="fake" unique="0">
+<longdesc lang="en">
+Fake attribute that can be changed to cause a reload
+</longdesc>
+<shortdesc lang="en">Fake attribute that can be changed to cause a reload</shortdesc>
+<content type="string" default="dummy" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="20" />
+<action name="stop"         timeout="20" />
+<action name="monitor"      timeout="20" interval="10" depth="0" />
+<action name="reload"       timeout="20" />
+<action name="migrate_to"   timeout="20" />
+<action name="migrate_from" timeout="20" />
+<action name="meta-data"    timeout="5" />
+<action name="validate-all"   timeout="20" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+dummy_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+dummy_start() {
+    dummy_monitor
+    if [ $? =  $OCF_SUCCESS ]; then
+	return $OCF_SUCCESS
+    fi
+    touch ${OCF_RESKEY_state}
+}
+
+dummy_stop() {
+    dummy_monitor
+    if [ $? =  $OCF_SUCCESS ]; then
+	rm ${OCF_RESKEY_state}
+    fi
+    return $OCF_SUCCESS
+}
+
+dummy_monitor() {
+	# Monitor _MUST!_ differentiate correctly between running
+	# (SUCCESS), failed (ERROR) or _cleanly_ stopped (NOT RUNNING).
+	# That is THREE states, not just yes/no.
+	
+	if [ -f ${OCF_RESKEY_state} ]; then
+	    return $OCF_SUCCESS
+	fi
+	if false ; then
+		return $OCF_ERR_GENERIC
+	fi
+	return $OCF_NOT_RUNNING
+}
+
+dummy_validate() {
+    
+    # Is the state directory writable? 
+    state_dir=`dirname "$OCF_RESKEY_state"`
+    touch "$state_dir/$$"
+    if [ $? != 0 ]; then
+	return $OCF_ERR_ARGS
+    fi
+    rm "$state_dir/$$"
+
+    return $OCF_SUCCESS
+}
+
+: ${OCF_RESKEY_state=${HA_RSCTMP}/Dummy-${OCF_RESOURCE_INSTANCE}.state}
+: ${OCF_RESKEY_fake="dummy"}
+
+case $__OCF_ACTION in
+meta-data)	meta_data
+		exit $OCF_SUCCESS
+		;;
+start)		dummy_start;;
+stop)		dummy_stop;;
+monitor)	dummy_monitor;;
+migrate_to)	ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} to ${OCF_RESKEY_CRM_meta_migrate_target}."
+	        dummy_stop
+		;;
+migrate_from)	ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} from ${OCF_RESKEY_CRM_meta_migrate_source}."
+	        dummy_start
+		;;
+reload)		ocf_log info "Reloading ${OCF_RESOURCE_INSTANCE} ..."
+		;;
+validate-all)	dummy_validate;;
+usage|help)	dummy_usage
+		exit $OCF_SUCCESS
+		;;
+*)		dummy_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
+
diff --git a/heartbeat/EvmsSCC b/heartbeat/EvmsSCC
new file mode 100755
index 0000000..802bac4
--- /dev/null
+++ b/heartbeat/EvmsSCC
@@ -0,0 +1,216 @@
+#!/bin/sh
+#
+# Support:      linux-ha at lists.linux-ha.org
+# License:      GNU General Public License (GPL)
+#
+# EvmsSCC
+#      Description: Runs evms_activate in a heartbeat cluster to activate a
+#		    EVMS shared cluster container in the cluster.
+#  Original Author: Jo De Baer (jdebaer at novell.com)
+# Original Release: 06 Nov 2006
+#
+# usage: ./EvmsSCC {start|stop|status|monitor|meta-data}
+#
+# The goal of this resource agent is to provoke the creation of device file
+# in /dev/emvs which correspond to EVMS2 volumes that reside in a EVMS2 shared
+# cluster container. As such it should be run as a clone resource in the
+# cluster. Logic inside the resource agent will make sure that "evms_activate"
+# is run on only one node in the cluster, both at cluster startup time as well
+# as when a node joins the cluster.
+#
+# Typically, resources that need to mount EVMS2 volumes should run after this
+# resource agent has finished it's run. As such those resources should be made
+# "dependent" on this resource agent by the cluster administrator. An example
+# of resources that should depend on this resource agent are Filesystem resource
+# agent that mount OCFS2 volumes that reside on EVMS2 volumes in a shared
+# EVMS2 cluster container.
+#
+# For this resource agent to do it's job correctly, evmsd must be running on
+# the node where the agent is started. Usually evmsd is started by the cluster
+# software via a respawn statement in /etc/ha.d/ha.cf. If you encounter timing
+# issues where evmsd is not yet started but where the cluster already starts
+# the EvmsSCC clone, then you should comment out the evmsd respawn statement
+# in /etc/ha.d/ha.cf and start evmsd on each node in the cluster via a separate
+# clone resource agent. The EvmsSCC resource agent cloneset should then be made
+# dependent to this evmsd cloneset. This will guarantee that emvsd is running
+# before EvmsSCC is started, on each node in the cluster.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+
+# Utilities used by this script
+CUT=cut
+EVMSACTIVATE=evms_activate
+
+usage() {
+	cat <<-EOT
+	usage: $0 {start|stop|status|monitor|meta-data}
+	EOT
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="EvmsSCC">
+<version>1.0</version>
+
+<longdesc lang="en">
+Deprecation warning: EVMS is no longer actively maintained and should not be used. This agent is deprecated and may be removed from a future release. --
+Resource script for EVMS shared cluster container. It runs evms_activate on one node in the cluster.
+</longdesc>
+<shortdesc lang="en">Manages EVMS Shared Cluster Containers (SCCs) (deprecated)</shortdesc>
+
+<parameters>
+<parameter name="ignore_deprecation">
+<longdesc lang="en">
+If set to true, suppresses the deprecation warning for this agent.
+</longdesc>
+<shortdesc lang="en">Suppress deprecation warning</shortdesc>
+<content type="boolean" default="false" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="60" />
+<action name="stop" timeout="60" />
+<action name="notify" timeout="60" />
+<action name="status" depth="0" timeout="10" interval="10" />
+<action name="monitor" depth="0" timeout="10" interval="10" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+EvmsSCC_status()
+{
+	# At the moment we don't support monitoring EVMS activations. We just return "not running" to cope with the pre-start monitor call.
+	return $OCF_NOT_RUNNING
+}
+
+EvmsSCC_notify()
+{
+	local n_type="$OCF_RESKEY_CRM_meta_notify_type"
+        local n_op="$OCF_RESKEY_CRM_meta_notify_operation"
+        local n_active="$OCF_RESKEY_CRM_meta_notify_active_uname"
+        local n_stop="$OCF_RESKEY_CRM_meta_notify_stop_uname"
+        local n_start="$OCF_RESKEY_CRM_meta_notify_start_uname"
+
+	case "$n_type" in
+        pre)
+                case "$n_op" in
+                start)  ocf_log debug "EvmsSCC: Notify: Starting node(s): $n_start."
+			EvmsSCC_start_notify_common
+                        ;;
+                esac
+                ;;
+	esac
+	
+
+	return $OCF_SUCCESS
+}
+
+EvmsSCC_start()
+{
+	local n_type="$OCF_RESKEY_CRM_meta_notify_type"
+	local n_op="$OCF_RESKEY_CRM_meta_notify_operation"
+	local n_active="$OCF_RESKEY_CRM_meta_notify_active_uname"
+	local n_stop="$OCF_RESKEY_CRM_meta_notify_stop_uname"
+	local n_start="$OCF_RESKEY_CRM_meta_notify_start_uname"
+
+        ocf_log debug "EvmsSCC: Start: starting node(s): $n_start."
+	
+	EvmsSCC_start_notify_common
+
+	return $OCF_SUCCESS
+}
+
+EvmsSCC_stop()
+{
+	return $OCF_SUCCESS
+}
+
+EvmsSCC_start_notify_common()
+{
+	local n_myself=${HA_CURHOST:-$(uname -n | tr A-Z a-z)}
+        ocf_log debug "EvmsSCC: Start_Notify: I am node $n_myself."
+
+        n_active="$n_active $n_start"
+        case " $n_active " in
+        *" $n_myself "*) ;;
+        *)      ocf_log err "EvmsSCC: $n_myself (local) not on active list!"
+                return $OCF_ERR_GENERIC
+                ;;
+        esac
+
+	#pick the first node from the starting list
+	#when the cluster boots this will be one of the many booting nodes
+	#when a node later joins the cluster, this will be the joining node
+        local n_first=$(echo $n_start | cut -d ' ' -f 1)
+        ocf_log debug "EvmsSCC: Start_Notify: First node in starting list is $n_first."
+
+        if [ "$n_myself" = "$n_first" ] ; then
+                ocf_log debug "EvmsSCC: Start_Notify: I am running ${EVMSACTIVATE}."
+                while true ; do
+                        if ! ${EVMSACTIVATE} -q 2> /dev/null ; then
+                                SLEEP_TIME=$(($(ocf_maybe_random) % 40))
+                                ocf_log info "EvmsSCC: Evms call failed - sleeping for $SLEEP_TIME seconds and then trying again."
+                                sleep $SLEEP_TIME
+                        else
+                                break
+                        fi
+                done
+
+        fi
+
+        return $OCF_SUCCESS
+}
+
+# Check the arguments passed to this script
+if
+  [ $# -ne 1 ]
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+OP=$1
+
+case $OP in
+  meta-data)		meta_data
+			exit $OCF_SUCCESS
+			;;
+  usage)		usage
+			exit $OCF_SUCCESS
+			;;
+esac
+
+# Be obnoxious, log deprecation warning on every invocation (unless
+# suppressed by resource configuration).
+ocf_deprecated
+
+check_binary $CUT
+check_binary $EVMSACTIVATE
+
+case $OP in
+  start)	        EvmsSCC_start
+			;;
+  notify)		EvmsSCC_notify	
+			;;
+  stop)			EvmsSCC_stop	
+			;;
+  status|monitor)	EvmsSCC_status
+			;;
+  *)			usage
+			exit $OCF_ERR_UNIMPLEMENTED
+			;;
+esac
+exit $?
diff --git a/heartbeat/Evmsd b/heartbeat/Evmsd
new file mode 100755
index 0000000..40c4aec
--- /dev/null
+++ b/heartbeat/Evmsd
@@ -0,0 +1,155 @@
+#!/bin/sh
+#
+#	Evmsd OCF RA.
+#
+# Copyright (c) 2004 SUSE LINUX AG, Jo De Baer
+#                    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.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Evmsd" version="0.9">
+<version>1.0</version>
+
+<longdesc lang="en">
+Deprecation warning: EVMS is no longer actively maintained and should not be used. This agent is deprecated and may be removed from a future release. --
+This is a Evmsd Resource Agent.
+</longdesc>
+<shortdesc lang="en">Controls clustered EVMS volume management
+(deprecated)</shortdesc>
+
+<parameters>
+<parameter name="ignore_deprecation">
+<longdesc lang="en">
+If set to true, suppresses the deprecation warning for this agent.
+</longdesc>
+<shortdesc lang="en">Suppress deprecation warning</shortdesc>
+<content type="boolean" default="false" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start"        timeout="20" />
+<action name="stop"         timeout="20" />
+<action name="monitor"      timeout="20" interval="10" depth="0" />
+<action name="meta-data"    timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+evmsd_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+evmsd_start() {
+	local PID=`pgrep evmsd`
+	if [ -z $PID ] ; then
+		nohup /sbin/evmsd &
+		# Spin waiting for the server to come up.
+    		# Let the CRM/LRM time us out if required
+    		start_wait=1
+    		while [ $start_wait = 1 ]; do
+			if evmsd_monitor ; then
+				sleep 1
+				return $OCF_SUCCESS
+			else
+				sleep 1
+			fi
+    		done
+	else
+		# already running
+		return $OCF_SUCCESS
+	fi
+}
+
+evmsd_stop() {
+	local PID=`pgrep evmsd`
+	if [ -z $PID ] ; then
+		# not running
+		return $OCF_SUCCESS
+	else
+		/bin/kill -15 $PID
+		sleep 1
+		/bin/kill -9 $PID
+		# Spin waiting for the server to go down.
+    		# Let the CRM/LRM time us out if required
+    		stop_wait=1
+    		while [ $stop_wait = 1 ]; do
+			if evmsd_monitor ; then
+				sleep 1
+			else
+				return $OCF_SUCCESS
+			fi
+    		done
+	fi
+}
+
+evmsd_monitor() {
+	local PID=`pgrep evmsd`
+	if [ -z $PID ] ; then
+		return $OCF_NOT_RUNNING
+	else
+		return $OCF_SUCCESS
+	fi
+}
+
+if [ "$__OCF_ACTION" = "meta-data" ]; then
+    meta_data
+    exit $OCF_SUCCESS
+fi
+
+# Be obnoxious, log deprecation warning on every invocation (unless
+# suppressed by resource configuration).
+ocf_deprecated
+
+case $__OCF_ACTION in
+start)		evmsd_start;;
+stop)		evmsd_stop;;
+monitor)	evmsd_monitor;;
+usage|help)	evmsd_usage
+		exit $OCF_SUCCESS
+		;;
+*)		evmsd_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
+
diff --git a/heartbeat/Filesystem b/heartbeat/Filesystem
new file mode 100755
index 0000000..1902c62
--- /dev/null
+++ b/heartbeat/Filesystem
@@ -0,0 +1,810 @@
+#!/bin/sh
+#
+# Support:      linux-ha at lists.linux-ha.org
+# License:      GNU General Public License (GPL)
+# 
+# Filesystem
+#      Description: Manages a Filesystem on a shared storage medium.
+#  Original Author: Eric Z. Ayers (eric.ayers at compgen.com)
+# Original Release: 25 Oct 2000
+#
+# usage: ./Filesystem {start|stop|status|monitor|validate-all|meta-data}
+#
+#	OCF parameters are as below:
+#		OCF_RESKEY_device
+#		OCF_RESKEY_directory
+#		OCF_RESKEY_fstype
+#		OCF_RESKEY_options
+#		OCF_RESKEY_statusfile_prefix
+#		OCF_RESKEY_run_fsck
+#		OCF_RESKEY_fast_stop
+#		OCF_RESKEY_force_clones
+#
+#OCF_RESKEY_device    : name of block device for the filesystem. e.g. /dev/sda1, /dev/md0
+#                       Or a -U or -L option for mount, or an NFS mount specification
+#OCF_RESKEY_directory : the mount point for the filesystem
+#OCF_RESKEY_fstype    : optional name of the filesystem type. e.g. ext2
+#OCF_RESKEY_options   : options to be given to the mount command via -o
+#OCF_RESKEY_statusfile_prefix : the prefix used for a status file for monitoring
+#OCF_RESKEY_run_fsck  : fsck execution mode: auto(default)/force/no
+#OCF_RESKEY_fast_stop : fast stop: yes(default)/no
+#OCF_RESKEY_force_clones : allow running the resource as clone. e.g. local xfs mounts
+#                         for each brick in a glusterfs setup
+#
+#
+# This assumes you want to manage a filesystem on a shared (SCSI) bus,
+# on a replicated device (such as DRBD), or a network filesystem (such
+# as NFS or Samba).
+#
+# Do not put this filesystem in /etc/fstab.  This script manages all of
+# that for you.
+#
+# NOTE: If 2 or more nodes mount the same file system read-write, and
+#       that file system is not designed for that specific purpose
+#       (such as GFS or OCFS2), and is not a network file system like
+#       NFS or Samba, then the filesystem is going to become
+#       corrupted.
+#
+#	As a result, you should use this together with the stonith
+#	option and redundant, independent communications paths.
+#
+#	If you don't do this, don't blame us when you scramble your
+#	disk.
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+DFLT_STATUSDIR=".Filesystem_status/"
+
+# Variables used by multiple methods
+HOSTOS=`uname`
+
+# The status file is going to an extra directory, by default
+#
+prefix=${OCF_RESKEY_statusfile_prefix}
+: ${prefix:=$DFLT_STATUSDIR}
+suffix="${OCF_RESOURCE_INSTANCE}"
+[ "$OCF_RESKEY_CRM_meta_clone" ] &&
+	suffix="${suffix}_$OCF_RESKEY_CRM_meta_clone"
+suffix="${suffix}_`uname -n`"
+STATUSFILE=${OCF_RESKEY_directory}/$prefix$suffix
+
+#######################################################################
+
+usage() {
+	cat <<-EOT
+	usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+	EOT
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Filesystem">
+<version>1.1</version>
+
+<longdesc lang="en">
+Resource script for Filesystem. It manages a Filesystem on a
+shared storage medium. 
+
+The standard monitor operation of depth 0 (also known as probe)
+checks if the filesystem is mounted. If you want deeper tests,
+set OCF_CHECK_LEVEL to one of the following values:
+
+10: read first 16 blocks of the device (raw read)
+
+This doesn't exercise the filesystem at all, but the device on
+which the filesystem lives. This is noop for non-block devices
+such as NFS, SMBFS, or bind mounts.
+
+20: test if a status file can be written and read
+
+The status file must be writable by root. This is not always the
+case with an NFS mount, as NFS exports usually have the
+"root_squash" option set. In such a setup, you must either use
+read-only monitoring (depth=10), export with "no_root_squash" on
+your NFS server, or grant world write permissions on the
+directory where the status file is to be placed.
+</longdesc>
+<shortdesc lang="en">Manages filesystem mounts</shortdesc>
+
+<parameters>
+<parameter name="device" required="1">
+<longdesc lang="en">
+The name of block device for the filesystem, or -U, -L options for mount, or NFS mount specification.
+</longdesc>
+<shortdesc lang="en">block device</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="directory" required="1">
+<longdesc lang="en">
+The mount point for the filesystem.
+</longdesc>
+<shortdesc lang="en">mount point</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="fstype" required="1">
+<longdesc lang="en">
+The type of filesystem to be mounted.
+</longdesc>
+<shortdesc lang="en">filesystem type</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="options">
+<longdesc lang="en">
+Any extra options to be given as -o options to mount.
+
+For bind mounts, add "bind" here and set fstype to "none".
+We will do the right thing for options such as "bind,ro".
+</longdesc>
+<shortdesc lang="en">options</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="statusfile_prefix">
+<longdesc lang="en">
+The prefix to be used for a status file for resource monitoring
+with depth 20. If you don't specify this parameter, all status
+files will be created in a separate directory.
+</longdesc>
+<shortdesc lang="en">status file prefix</shortdesc>
+<content type="string" default="$DFLT_STATUSDIR" />
+</parameter>
+
+<parameter name="run_fsck">
+<longdesc lang="en">
+Specify how to decide whether to run fsck or not.
+
+"auto"  : decide to run fsck depending on the fstype(default)
+"force" : always run fsck regardless of the fstype
+"no"    : do not run fsck ever.
+</longdesc>
+<shortdesc lang="en">run_fsck</shortdesc>
+<content type="string" default="auto" />
+</parameter>
+
+<parameter name="fast_stop">
+<longdesc lang="en">
+Normally, we expect no users of the filesystem and the stop
+operation to finish quickly. If you cannot control the filesystem
+users easily and want to prevent the stop action from failing,
+then set this parameter to "no" and add an appropriate timeout
+for the stop operation.
+</longdesc>
+<shortdesc lang="en">fast stop</shortdesc>
+<content type="boolean" default="yes" />
+</parameter>
+
+<parameter name="force_clones">
+<longdesc lang="en">
+The use of a clone setup for local filesystems is forbidden
+by default. For special setups like glusterfs, cloning a mount
+of a local device with a filesystem like ext4 or xfs independently
+on several nodes is a valid use case.
+
+Only set this to "true" if you know what you are doing!
+</longdesc>
+<shortdesc lang="en">allow running as a clone, regardless of filesystem type</shortdesc>
+<content type="boolean" default="false" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="60" />
+<action name="stop" timeout="60" />
+<action name="notify" timeout="60" />
+<action name="monitor" depth="0" timeout="40" interval="20" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+#
+#	Make sure the kernel does the right thing with the FS buffers
+#	This function should be called after unmounting and before mounting
+#	It may not be necessary in 2.4 and later kernels, but it shouldn't hurt
+#	anything either...
+#
+#	It's really a bug that you have to do this at all...
+#
+flushbufs() {
+	if have_binary $BLOCKDEV ; then
+		if [ "$blockdevice" = "yes" ] ; then
+			$BLOCKDEV --flushbufs $1
+			return $?
+		fi
+	fi
+	return 0
+}
+
+# Take advantage of /etc/mtab if present, use portable mount command
+# otherwise. Normalize format to "dev mountpoint fstype".
+is_bind_mount() {
+	echo "$options" | grep -w bind >/dev/null 2>&1
+}
+list_mounts() {
+	local inpf=""
+	if [ -e "/proc/mounts" ] && ! is_bind_mount; then
+		inpf=/proc/mounts
+	elif [ -f "/etc/mtab" -a -r "/etc/mtab" ]; then
+		inpf=/etc/mtab
+	fi
+	if [ "$inpf" ]; then
+		cut -d' ' -f1,2,3 < $inpf
+	else
+		$MOUNT | cut -d' ' -f1,3,5
+	fi
+}
+
+determine_blockdevice() {
+	if [ $blockdevice = "yes" ]; then
+		return
+	fi
+
+	# Get the current real device name, if possible.
+	# (specified devname could be -L or -U...)
+	case "$FSTYPE" in
+	nfs4|nfs|smbfs|cifs|glusterfs|ceph|tmpfs|none)
+		: ;;
+	*)
+		DEVICE=`list_mounts | grep " $MOUNTPOINT " | cut -d' ' -f1`
+		if [ -b "$DEVICE" ]; then
+			blockdevice=yes
+		fi
+		;;
+	esac
+}
+
+# Lists all filesystems potentially mounted under a given path,
+# excluding the path itself.
+list_submounts() {
+	list_mounts | grep " $1/" | cut -d' ' -f2 | sort -r
+}
+
+# kernels < 2.6.26 can't handle bind remounts
+bind_kernel_check() {
+	echo "$options" | grep -w ro >/dev/null 2>&1 ||
+		return
+	uname -r | awk -F. '
+	$1==2 && $2==6 {
+		sub("[^0-9].*","",$3);
+		if ($3<26)
+			exit(1);
+	}'
+	[ $? -ne 0 ] &&
+		ocf_log warn "kernel `uname -r` cannot handle read only bind mounts"
+}
+bind_mount() {
+	if is_bind_mount && [ "$options" != "-o bind" ]
+	then
+		bind_kernel_check
+		bind_opts=`echo $options | sed 's/bind/remount/'`
+		$MOUNT $bind_opts $MOUNTPOINT
+	else
+		true # make sure to return OK
+	fi
+}
+
+is_option() {
+	echo $OCF_RESKEY_options | grep -w "$1" >/dev/null 2>&1
+}
+
+is_fsck_needed() {
+	case $OCF_RESKEY_run_fsck in
+		force) true;;
+		no)    false;;
+		""|auto)
+		case $FSTYPE in
+			ext4|ext4dev|ext3|reiserfs|reiser4|nss|xfs|jfs|vfat|fat|nfs4|nfs|cifs|smbfs|ocfs2|gfs2|none|lustre|glusterfs|ceph|tmpfs)
+			false;;
+			*)
+			true;;
+		esac;;
+		*)
+		ocf_log warn "Invalid parameter value for fsck: '$OCF_RESKEY_run_fsck'; setting to 'auto'"
+		OCF_RESKEY_run_fsck="auto"
+		is_fsck_needed;;
+	esac
+}
+
+#
+# START: Start up the filesystem
+#
+Filesystem_start()
+{
+	# See if the device is already mounted.
+	if Filesystem_status >/dev/null 2>&1 ; then
+		ocf_log info "Filesystem $MOUNTPOINT is already mounted."
+		return $OCF_SUCCESS
+	fi
+
+	if [ "X${HOSTOS}" != "XOpenBSD" ];then
+		if [ -z "$FSTYPE" -o "$FSTYPE" = none ]; then
+			: No FSTYPE specified, rely on the system has the right file-system support already 
+		else
+			local support="$FSTYPE"
+			# support fuse-filesystems (e.g. GlusterFS)
+			case $FSTYPE in
+				glusterfs) support="fuse";;
+			esac
+			grep -w "$support"'$' /proc/filesystems >/dev/null ||
+				$MODPROBE $support >/dev/null
+			grep -w "$support"'$' /proc/filesystems >/dev/null
+			if [ $? -ne 0 ] ; then
+				ocf_log err "Couldn't find filesystem $FSTYPE in /proc/filesystems"
+				return $OCF_ERR_INSTALLED
+			fi
+		fi
+	fi
+
+	# Check the filesystem & auto repair.  
+	# NOTE: Some filesystem types don't need this step...  Please modify
+	#       accordingly
+
+	if [ $blockdevice = "yes" ]; then
+		if [ "$DEVICE" != "/dev/null" -a ! -b "$DEVICE" ] ; then
+			ocf_log err "Couldn't find device [$DEVICE]. Expected /dev/??? to exist"
+			exit $OCF_ERR_INSTALLED
+		fi
+
+		if is_fsck_needed; then
+			ocf_log info  "Starting filesystem check on $DEVICE"
+			if [ -z "$FSTYPE" ]; then
+				$FSCK -p $DEVICE
+			else
+				$FSCK -t $FSTYPE -p $DEVICE
+			fi
+
+			# NOTE: if any errors at all are detected, it returns non-zero
+			# if the error is >= 4 then there is a big problem
+			if [ $? -ge 4 ]; then
+				ocf_log err "Couldn't sucessfully fsck filesystem for $DEVICE"
+				return $OCF_ERR_GENERIC
+			fi
+		fi
+	fi
+
+	[ -d "$MOUNTPOINT" ] ||
+		ocf_run mkdir -p $MOUNTPOINT
+	if [ ! -d "$MOUNTPOINT" ] ; then
+		ocf_log err "Couldn't find directory  [$MOUNTPOINT] to use as a mount point"
+		exit $OCF_ERR_INSTALLED
+	fi
+
+	flushbufs $DEVICE
+	# Mount the filesystem.
+	case "$FSTYPE" in
+		none) $MOUNT $options $DEVICE $MOUNTPOINT &&
+			bind_mount
+			;;
+		"") $MOUNT $options $DEVICE $MOUNTPOINT ;;
+		*) $MOUNT -t $FSTYPE $options $DEVICE $MOUNTPOINT ;;
+	esac
+
+	if [ $? -ne 0 ]; then
+		ocf_log err "Couldn't mount filesystem $DEVICE on $MOUNTPOINT"
+		return $OCF_ERR_GENERIC
+	fi
+	return $OCF_SUCCESS
+}
+# end of Filesystem_start
+
+signal_processes() {
+	local dir=$1
+	local sig=$2
+	local pids pid
+	# fuser returns a non-zero return code if none of the
+	# specified files is accessed or in case of a fatal 
+	# error.
+	pids=$(
+		if [ "X${HOSTOS}" = "XOpenBSD" ];then
+			fstat | grep $dir | awk '{print $3}'
+		else
+			$FUSER -m $dir 2>/dev/null
+		fi
+	)
+	if [ -z "$pids" ]; then
+		ocf_log info "No processes on $dir were signalled"
+		return
+	fi
+	for pid in $pids; do
+		ocf_log info "sending signal $sig to: `ps -f $pid | tail -1`"
+		kill -s $sig $pid
+	done
+}
+try_umount() {
+	local SUB=$1
+	$UMOUNT $umount_force $SUB
+	list_mounts | grep -q " $SUB " >/dev/null 2>&1 || {
+		ocf_log info "unmounted $SUB successfully"
+		return $OCF_SUCCESS
+	}
+	return $OCF_ERR_GENERIC
+}
+fs_stop() {
+	local SUB=$1 timeout=$2 sig cnt
+	for sig in TERM KILL; do
+		cnt=$((timeout/2)) # try half time with TERM
+		while [ $cnt -gt 0 ]; do
+			try_umount $SUB &&
+				return $OCF_SUCCESS
+			ocf_log err "Couldn't unmount $SUB; trying cleanup with $sig"
+			signal_processes $SUB $sig
+			cnt=$((cnt-1))
+			sleep 1
+		done
+	done
+	return $OCF_ERR_GENERIC
+}
+
+#
+# STOP: Unmount the filesystem
+#
+Filesystem_stop()
+{
+	# See if the device is currently mounted
+	Filesystem_status >/dev/null 2>&1
+	if [ $? -eq $OCF_NOT_RUNNING ]; then
+		# Already unmounted, wonderful.
+		rc=$OCF_SUCCESS
+	else
+		# Wipe the status file, but continue with a warning if
+		# removal fails -- the file system might be read only
+		if [ $OCF_CHECK_LEVEL -eq 20 ]; then
+			rm -f ${STATUSFILE}
+			if [ $? -ne 0 ]; then
+				ocf_log warn "Failed to remove status file ${STATUSFILE}."
+			fi
+		fi
+
+		# Determine the real blockdevice this is mounted on (if
+		# possible) prior to unmounting.
+		determine_blockdevice
+
+		# For networked filesystems, there's merit in trying -f:
+		case "$FSTYPE" in
+		nfs4|nfs|cifs|smbfs) umount_force="-f" ;;
+		esac
+
+		# Umount all sub-filesystems mounted under $MOUNTPOINT/ too.
+		local timeout
+		for SUB in `list_submounts $MOUNTPOINT` $MOUNTPOINT; do
+			ocf_log info "Trying to unmount $SUB"
+			if ocf_is_true "$FAST_STOP"; then
+				timeout=6
+			else
+				timeout=${OCF_RESKEY_CRM_meta_timeout:="20000"}
+				timeout=$((timeout/1000))
+			fi
+			fs_stop $SUB $timeout
+			rc=$?
+			if [ $rc -ne $OCF_SUCCESS ]; then
+				ocf_log err "Couldn't unmount $SUB, giving up!"
+			fi
+		done
+	fi
+
+	flushbufs $DEVICE
+
+	return $rc
+}
+# end of Filesystem_stop
+
+#
+# STATUS: is the filesystem mounted or not?
+#
+Filesystem_status()
+{
+	if list_mounts | grep -q " $MOUNTPOINT " >/dev/null 2>&1; then
+		rc=$OCF_SUCCESS
+		msg="$MOUNTPOINT is mounted (running)"
+	else
+		rc=$OCF_NOT_RUNNING
+		msg="$MOUNTPOINT is unmounted (stopped)"
+	fi
+
+	# Special case "monitor" to check whether the UUID cached and
+	# on-disk still match?
+	case "$OP" in
+		status)	ocf_log info "$msg";;
+	esac
+
+	return $rc
+}
+# end of Filesystem_status
+
+
+# Note: the read/write tests below will stall in case the
+# underlying block device (or in the case of a NAS mount, the
+# NAS server) has gone away. In that case, if I/O does not
+# return to normal in time, the operation hits its timeout
+# and it is up to the CRM to initiate appropriate recovery
+# actions (such as fencing the node).
+#
+# MONITOR 10: read the device
+#
+Filesystem_monitor_10()
+{
+	if [ "$blockdevice" = "no" ] ; then
+		ocf_log warn "$DEVICE is not a block device, monitor 10 is noop"
+		return $OCF_SUCCESS
+	fi
+	dd_opts="iflag=direct bs=4k count=1"
+	err_output=`dd if=$DEVICE $dd_opts 2>&1 >/dev/null`
+	if [ $? -ne 0 ]; then
+		ocf_log err "Failed to read device $DEVICE"
+		ocf_log err "dd said: $err_output"
+		return $OCF_ERR_GENERIC
+	fi
+	return $OCF_SUCCESS
+}
+#
+# MONITOR 20: write and read a status file
+#
+Filesystem_monitor_20()
+{
+	if [ "$blockdevice" = "no" ] ; then
+		# O_DIRECT not supported on cifs/smbfs
+		dd_opts="oflag=sync bs=4k conv=fsync,sync"
+	else
+		# Writing to the device in O_DIRECT mode is imperative
+		# to bypass caches.
+		dd_opts="oflag=direct,sync bs=4k conv=fsync,sync"
+	fi
+	status_dir=`dirname $STATUSFILE`
+	[ -d "$status_dir" ] || mkdir -p "$status_dir"
+	err_output=`echo "${OCF_RESOURCE_INSTANCE}" | dd of=${STATUSFILE} $dd_opts 2>&1`
+	if [ $? -ne 0 ]; then
+		ocf_log err "Failed to write status file ${STATUSFILE}"
+		ocf_log err "dd said: $err_output"
+		return $OCF_ERR_GENERIC
+	fi
+	test -f ${STATUSFILE}
+	if [ $? -ne 0 ]; then
+		ocf_log err "Cannot stat the status file ${STATUSFILE}"
+		return $OCF_ERR_GENERIC
+	fi
+	cat ${STATUSFILE} > /dev/null
+	if [ $? -ne 0 ]; then
+		ocf_log err "Cannot read the status file ${STATUSFILE}"
+		return $OCF_ERR_GENERIC
+	fi
+	return $OCF_SUCCESS
+}
+Filesystem_monitor()
+{
+	Filesystem_status
+	rc=$?
+	if [ $rc -ne $OCF_SUCCESS ]; then
+		return $rc
+	fi
+
+	if [ $rc -eq $OCF_SUCCESS -a $OCF_CHECK_LEVEL -gt 0 ]; then
+		case "$OCF_CHECK_LEVEL" in
+		10) Filesystem_monitor_10; rc=$?;;
+		20) Filesystem_monitor_20; rc=$?;;
+		*)
+			ocf_log err "unsupported monitor level $OCF_CHECK_LEVEL"
+			rc=$OCF_ERR_CONFIGURED
+		;;
+		esac
+	fi
+	return $rc
+}
+# end of Filesystem_monitor
+
+
+#
+#	VALIDATE_ALL: Are the instance parameters valid?
+#	FIXME!!  The only part that's useful is the return code.
+#	This code always returns $OCF_SUCCESS (!)
+#
+Filesystem_validate_all()
+{
+	if [ -n $MOUNTPOINT -a ! -d $MOUNTPOINT ]; then
+		ocf_log warn "Mountpoint $MOUNTPOINT does not exist"
+	fi
+
+	# Check if the $FSTYPE is workable
+	# NOTE: Without inserting the $FSTYPE module, this step may be imprecise
+	# TODO: This is Linux specific crap.
+	if [ ! -z "$FSTYPE" -a "$FSTYPE" != none ]; then
+		cut -f2 /proc/filesystems |grep -q ^$FSTYPE$
+		if [ $? -ne 0 ]; then
+			modpath=/lib/modules/`uname -r` 
+			moddep=$modpath/modules.dep
+			# Do we have $FSTYPE in modules.dep?
+			cut -d' ' -f1 $moddep |grep -q "^$modpath.*$FSTYPE\.k\?o:$"
+			if [ $? -ne 0 ]; then
+				ocf_log info "It seems we do not have $FSTYPE support"
+			fi
+		fi
+	fi
+
+	# If we are supposed to do monitoring with status files, then
+	# we need a utility to write in O_DIRECT mode.
+	if [ $OCF_CHECK_LEVEL -gt 0 ]; then
+		check_binary dd
+		# Note: really old coreutils version do not support
+		# the "oflag" option for dd. We don't check for that
+		# here. In case dd does not support oflag, monitor is
+		# bound to fail, with dd spewing an error message to
+		# the logs. On such systems, we must do without status
+		# file monitoring.
+	fi
+
+	#TODO: How to check the $options ?
+	return $OCF_SUCCESS
+}
+
+#
+# set the blockdevice variable to "no" or "yes"
+#
+set_blockdevice_var() {
+	blockdevice=no
+
+	# these are definitely not block devices
+	case $FSTYPE in
+	nfs4|nfs|smbfs|cifs|none|glusterfs|ceph) return;;
+	esac
+
+	if `is_option "loop"`; then
+		return
+	fi
+
+	case $DEVICE in
+	-*) # Oh... An option to mount instead...  Typically -U or -L
+		;;
+	/dev/null) # Special case for BSC
+		blockdevice=yes
+		;;
+	*)
+		if [ ! -b "$DEVICE"  -a ! -d "$DEVICE" -a "X$OP" != Xstart ] ; then
+			ocf_log warn "Couldn't find device [$DEVICE]. Expected /dev/??? to exist"
+		fi
+		if [ ! -d "$DEVICE" ]; then
+			blockdevice=yes
+		fi
+		;;
+	esac
+}
+
+# Check the arguments passed to this script
+if [ $# -ne 1 ]; then
+	usage
+	exit $OCF_ERR_ARGS
+fi
+
+# Check the OCF_RESKEY_ environment variables...
+DEVICE=$OCF_RESKEY_device
+FSTYPE=$OCF_RESKEY_fstype
+if [ ! -z "$OCF_RESKEY_options" ]; then
+	options="-o $OCF_RESKEY_options"
+fi
+FAST_STOP=${OCF_RESKEY_fast_stop:="yes"}
+
+OP=$1
+
+# These operations do not require instance parameters
+case $OP in
+	meta-data) meta_data
+		exit $OCF_SUCCESS
+		;;
+	usage) usage
+		exit $OCF_SUCCESS
+		;;
+esac
+
+if [ x = x"$DEVICE" ]; then
+	ocf_log err "Please set OCF_RESKEY_device to the device to be managed"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+set_blockdevice_var
+
+# Normalize instance parameters:
+
+# It is possible that OCF_RESKEY_directory has one or even multiple trailing "/".
+# But the output of `mount` and /proc/mounts do not.
+if [ -z "$OCF_RESKEY_directory" ]; then
+	if [ X$OP = "Xstart" -o $blockdevice = "no" ]; then
+		ocf_log err "Please specify the directory"
+		exit $OCF_ERR_CONFIGURED 
+	fi
+else
+	MOUNTPOINT=$(echo $OCF_RESKEY_directory | sed 's/\/*$//')
+	: ${MOUNTPOINT:=/}
+	# At this stage, $MOUNTPOINT does not contain trailing "/" unless it is "/"
+	# TODO: / mounted via Filesystem sounds dangerous. On stop, we'll
+	# kill the whole system. Is that a good idea?
+fi
+
+# Check to make sure the utilites are found
+if [ "X${HOSTOS}" != "XOpenBSD" ];then
+check_binary $MODPROBE
+check_binary $FUSER
+fi
+check_binary $FSCK
+check_binary $MOUNT
+check_binary $UMOUNT
+
+if [ "$OP" != "monitor" ]; then
+	ocf_log info "Running $OP for $DEVICE on $MOUNTPOINT"
+fi
+
+case $OP in
+	status) Filesystem_status
+		exit $?
+		;;
+	monitor) Filesystem_monitor
+		exit $?
+		;;
+	validate-all) Filesystem_validate_all
+		exit $?
+		;;
+	stop) Filesystem_stop
+		exit $?
+		;;
+esac
+
+CLUSTERSAFE=0
+is_option "ro" &&
+	CLUSTERSAFE=2
+
+case $FSTYPE in
+nfs4|nfs|smbfs|cifs|none|gfs2|glusterfs|ceph|ocfs2)
+	CLUSTERSAFE=1 # this is kind of safe too
+	;;
+# add here CLUSTERSAFE=0 for all filesystems which are not
+# cluster aware and which, even if when mounted read-only,
+# could still modify parts of it such as journal/metadata
+ext4|ext4dev|ext3|reiserfs|reiser4|xfs|jfs)
+	if ocf_is_true "$OCF_RESKEY_force_clones"; then
+		CLUSTERSAFE=2
+	else
+		CLUSTERSAFE=0 # these are not allowed
+	fi
+	;;
+esac
+
+if ocf_is_clone; then
+	case $CLUSTERSAFE in
+	0)
+		ocf_log err "DANGER! $FSTYPE on $DEVICE is NOT cluster-aware!"
+		ocf_log err "DO NOT RUN IT AS A CLONE!"
+		ocf_log err "Politely refusing to proceed to avoid data corruption."
+		exit $OCF_ERR_CONFIGURED
+		;;
+	2)
+		ocf_log warn "$FSTYPE on $DEVICE is NOT cluster-aware!"
+		if ocf_is_true "$OCF_RESKEY_force_clones"; then
+			ocf_log warn "But we'll let it run because we trust _YOU_ verified it's safe to do so."
+		else
+			ocf_log warn "But we'll let it run because it is mounted read-only."
+			ocf_log warn "Please make sure that it's meta data is read-only too!"
+		fi
+		;;
+	esac
+fi
+
+case $OP in
+	start) Filesystem_start
+		;;
+	*) usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+	esac
+exit $?
+
+
diff --git a/heartbeat/ICP b/heartbeat/ICP
new file mode 100755
index 0000000..c427e7a
--- /dev/null
+++ b/heartbeat/ICP
@@ -0,0 +1,296 @@
+#!/bin/sh
+#
+# 
+# ICP
+#
+# Description:	Manages an ICP Vortex clustered host drive as an HA resource
+#
+#
+# Author:	Lars Marowsky-Bree <lmb at suse.de>
+# Support:	linux-ha at lists.linux-ha.org
+# License:	GNU General Public License (GPL)
+# Copyright:	(C) 2002 SuSE Linux AG
+#
+#
+# An example usage in /etc/ha.d/haresources: 
+#       node1  10.0.0.170 LinuxSCSI::0:0 ICP::c0h1::/dev/sdb1 LVM::myvolname
+#
+# Notice that you will need to get the utility "icpclucon" from the ICP
+# support to use this.
+#
+# See usage() function below for more details...
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_driveid
+#		OCF_RESKEY_device
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+#
+ICPCLUCON=/usr/sbin/icpclucon
+#
+
+usage() {
+  methods=`ICP_methods | grep -v methods`
+  methods=`echo $methods | tr ' ' '|'`
+  cat <<-!
+	usage: $0 ($methods)
+
+	$0 manages an ICP Vortex clustered host drive.
+
+	The 'start' operation reserves the given host drive.
+	The 'stop' operation releses the given host drive.
+	The 'status' operation reports whether the host drive is reserved.
+	The 'monitor' operation reports whether the host drive is reserved.
+	The 'validate-all' operation reports whether OCF instance parameters are valid.
+	The 'methods' operation reports on the methods $0 supports
+
+	!
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="ICP">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for ICP. It Manages an ICP Vortex clustered host drive as an 
+HA resource. 
+</longdesc>
+<shortdesc lang="en">Manages an ICP Vortex clustered host drive</shortdesc>
+
+<parameters>
+<parameter name="driveid" unique="0" required="1">
+<longdesc lang="en">
+The ICP cluster drive ID.
+</longdesc>
+<shortdesc lang="en">ICP cluster drive ID</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="device" unique="0" required="1">
+<longdesc lang="en">
+The device name.
+</longdesc>
+<shortdesc lang="en">device</shortdesc>
+<content type="string" default="" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="20" />
+<action name="stop" timeout="20" />
+<action name="status" depth="0" timeout="20" interval="10" />
+<action name="monitor" depth="0" timeout="20" interval="10" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+#
+# methods: What methods/operations do we support?
+#
+ICP_methods() {
+  cat <<-!
+	start
+	stop
+	status
+	monitor
+	methods
+	validate-all
+	meta-data
+	usage
+	!
+}
+
+ICP_status() {
+        local icp_out
+        
+        icp_out=$($ICPCLUCON -v -status $1)
+        if [ $? -ne 0 ]; then
+                ocf_log "err" "Hostdrive not reserved by us."
+                return $OCF_ERR_GENERIC
+        fi
+
+        if expr match "$icp_out" \
+                '.*Drive is reserved by this host.*' >/dev/null 2>&1 ; then
+                ocf_log "info" "Volume $1 is reserved by us."
+                return $OCF_SUCCESS
+        elif expr match "$icp_out" \
+                '.*Drive is not reserved by any host.*' >/dev/null 2>&1 ; then
+                ocf_log "err" "Volume $1 not reserved by any host."
+                return $OCF_NOT_RUNNING
+        else
+                ocf_log "err" "Unknown output from icpclucon. Assuming we do not have a reservation:"
+		ocf_log "err" "$icp_out"
+                return $OCF_NOT_RUNNING
+        fi
+}
+
+ICP_report_status() {
+  if ICP_status $1 ; then
+	echo "$1: running"
+	return $OCF_SUCCESS
+  else
+	echo "$1: not running"
+	return $OCF_NOT_RUNNING
+  fi
+}
+
+
+#
+#	Monitor the host drive - does it really seem to be working?
+#
+#
+ICP_monitor() {
+
+  if
+    ICP_status $1
+  then
+    return $?
+  else
+    ocf_log "err" "ICP host drive $1 is offline"
+    return $OCF_NOT_RUNNING
+  fi
+
+}
+
+Clear_bufs() {
+    $BLOCKDEV --flushbufs $1
+}
+
+#
+#	Enable ICP host drive
+#
+ICP_start() {
+
+  ocf_log "info" "Activating host drive $1"
+  ocf_run $ICPCLUCON -v -reserve $1
+  if [ $? -ne 0 ]; then
+  	ocf_log "info" "Forcing reservation of $1"
+	ocf_run $ICPCLUCON -v -force $1 || return $OCF_ERR_GENERIC
+  fi
+
+  if
+    ICP_status $1
+  then
+    : OK
+    # A reservation isn't as prompt as it should be
+    sleep 3
+    return $OCF_SUCCESS
+  else
+    ocf_log "err" "ICP: $1 was not reserved correctly"
+    return $OCF_ERR_GENERIC
+  fi
+}
+
+#
+#	Release the ICP host drive
+#
+ICP_stop() {
+
+  ocf_log "info" "Releasing ICP host drive $1"
+  ocf_run $ICPCLUCON -v -release $1 || return $OCF_ERR_GENERIC
+
+  ocf_log "info" "Verifying reservation"
+  if ICP_status $1 ; then
+    ocf_log "err" "ICP: $1 was not released correctly"
+    return $OCF_ERR_GENERIC
+  fi
+  return $OCF_SUCCESS
+}
+
+ICP_validate_all() {
+  check_binary $BLOCKDEV
+  check_binary $ICPCLUCON
+  $ICPCLUCON -v -status $driveid >/dev/null 2>&1
+  if [ $? -ne 0 ]; then
+	ocf_log err "Invalid driveid $driveid"
+	exit $OCF_ERR_ARGS
+  fi
+
+  if [ ! -b $device ]; then
+	ocf_log err "Device $device is not a block device"
+	exit $OCF_ERR_ARGS
+  fi
+
+# Do not know how to check the association of $device with $driveid.
+
+  return $OCF_SUCCESS
+}
+
+#
+#	'main' starts here...
+#
+
+if
+  ( [ $# -ne 1 ] )
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+# These operations do not require OCF instance parameters to be set
+case "$1" in
+
+  meta-data)	meta_data
+		exit $OCF_SUCCESS;;
+
+  methods)	ICP_methods
+		exit $OCF_SUCCESS;;
+  
+  usage)	usage
+		exit $OCF_SUCCESS;;
+
+  *)		;;
+esac
+
+if 
+  [ -z "$OCF_RESKEY_driveid" ] 
+then
+  ocf_log err "Please specify OCF_RESKEY_driveid"
+  exit $OCF_ERR_ARGS
+fi
+
+if [ -z "$OCF_RESKEY_device" ]; then
+  ocf_log err "Please specify OCF_RESKEY_device"
+  exit $OCF_ERR_ARGS
+fi
+
+driveid=$OCF_RESKEY_driveid
+device=$OCF_RESKEY_device
+
+# What kind of method was invoked?
+case "$1" in
+
+  start)	ICP_validate_all
+		ICP_start $driveid
+		Clear_bufs $device
+		exit $?;;
+
+  stop)		ICP_stop $driveid
+		Clear_bufs $device
+		exit $?;;
+
+  status)	ICP_report_status $driveid
+		exit $?;;
+
+  monitor)	ICP_monitor $driveid
+		exit $?;;
+
+  validate-all)	ICP_validate_all
+		exit $?;;
+
+  *)		usage
+		exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/heartbeat/IPaddr b/heartbeat/IPaddr
new file mode 100755
index 0000000..8ada6c4
--- /dev/null
+++ b/heartbeat/IPaddr
@@ -0,0 +1,892 @@
+#!/bin/sh
+#
+# License:      GNU General Public License (GPL) 
+# Support:      linux-ha at lists.linux-ha.org
+#
+#	This script manages IP alias IP addresses
+#
+#	It can add an IP alias, or remove one.
+#
+#	usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+#
+#	The "start" arg adds an IP alias.
+#
+#	Surprisingly, the "stop" arg removes one.	:-)
+#
+#       OCF parameters are as below
+#       OCF_RESKEY_ip
+#       OCF_RESKEY_broadcast
+#       OCF_RESKEY_nic
+#       OCF_RESKEY_cidr_netmask
+#       OCF_RESKEY_lvs_support  ( e.g. true, on, 1 )
+#       OCF_RESKEY_ARP_INTERVAL_MS
+#       OCF_RESKEY_ARP_REPEAT
+#       OCF_RESKEY_ARP_BACKGROUND (e.g. yes )
+#       OCF_RESKEY_ARP_NETMASK
+#       OCF_RESKEY_local_start_script
+#       OCF_RESKEY_local_stop_script
+#
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+SENDARP=$HA_BIN/send_arp
+FINDIF=$HA_BIN/findif
+VLDIR=$HA_RSCTMP
+SENDARPPIDDIR=$HA_RSCTMP
+SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$OCF_RESKEY_ip"
+USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}";
+
+#######################################################################
+
+SYSTYPE="`uname -s`"
+case "$SYSTYPE" in
+    SunOS)
+        # `uname -r` = 5.9 -> SYSVERSION = 9
+        SYSVERSION="`uname -r | cut -d. -f 2`"
+	;;
+    Darwin)
+	# Treat Darwin the same as the other BSD variants (matched as *BSD)
+	SYSTYPE="${SYSTYPE}BSD"
+	;;
+    *)
+        ;;
+esac
+
+
+
+meta_data() {
+        cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="IPaddr">
+<version>1.0</version>
+<longdesc lang="en">
+This script manages IP alias IP addresses
+It can add an IP alias, or remove one.
+</longdesc>
+<shortdesc lang="en">Manages virtual IPv4 addresses (portable version)</shortdesc>
+
+<parameters>
+<parameter name="ip" unique="1" required="1">
+<longdesc lang="en">
+The IPv4 address to be configured in dotted quad notation, for example
+"192.168.1.1".
+</longdesc>
+<shortdesc lang="en">IPv4 address</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="nic" unique="0">
+<longdesc lang="en">
+The base network interface on which the IP address will be brought
+online.
+
+If left empty, the script will try and determine this from the
+routing table.
+
+Do NOT specify an alias interface in the form eth0:1 or anything here;
+rather, specify the base interface only.
+
+Prerequisite:
+
+There must be at least one static IP address, which is not managed by
+the cluster, assigned to the network interface.
+
+If you can not assign any static IP address on the interface,
+modify this kernel parameter:
+sysctl -w net.ipv4.conf.all.promote_secondaries=1
+(or per device)
+
+</longdesc>
+<shortdesc lang="en">Network interface</shortdesc>
+<content type="string" default="eth0"/>
+</parameter>
+
+<parameter name="cidr_netmask">
+<longdesc lang="en">
+The netmask for the interface in CIDR format. (ie, 24), or in
+dotted quad notation  255.255.255.0).
+
+If unspecified, the script will also try to determine this from the
+routing table.
+</longdesc>
+<shortdesc lang="en">Netmask</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="broadcast">
+<longdesc lang="en">
+Broadcast address associated with the IP. If left empty, the script will
+determine this from the netmask.
+</longdesc>
+<shortdesc lang="en">Broadcast address</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="iflabel">
+<longdesc lang="en">
+You can specify an additional label for your IP address here.
+</longdesc>
+<shortdesc lang="en">Interface label</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="lvs_support">
+<longdesc lang="en">
+Enable support for LVS Direct Routing configurations. In case a IP
+address is stopped, only move it to the loopback device to allow the
+local node to continue to service requests, but no longer advertise it
+on the network.
+</longdesc>
+<shortdesc lang="en">Enable support for LVS DR</shortdesc>
+<content type="boolean" default="false"/>
+</parameter>
+
+<parameter name="local_stop_script">
+<longdesc lang="en">
+Script called when the IP is released
+</longdesc>
+<shortdesc lang="en">Script called when the IP is released</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="local_start_script">
+<longdesc lang="en">
+Script called when the IP is added
+</longdesc>
+<shortdesc lang="en">Script called when the IP is added</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="ARP_INTERVAL_MS">
+<longdesc lang="en">
+milliseconds between ARPs
+</longdesc>
+<shortdesc lang="en">milliseconds between gratuitous ARPs</shortdesc>
+<content type="integer" default="500"/>
+</parameter>
+
+<parameter name="ARP_REPEAT">
+<longdesc lang="en">
+How many gratuitous ARPs to send out when bringing up a new address
+</longdesc>
+<shortdesc lang="en">repeat count</shortdesc>
+<content type="integer" default="10"/>
+</parameter>
+
+<parameter name="ARP_BACKGROUND">
+<longdesc lang="en">
+run in background (no longer any reason to do this)
+</longdesc>
+<shortdesc lang="en">run in background</shortdesc>
+<content type="boolean" default="yes"/>
+</parameter>
+
+<parameter name="ARP_NETMASK">
+<longdesc lang="en">
+netmask for ARP - in nonstandard hexadecimal format.
+</longdesc>
+<shortdesc lang="en">netmask for ARP</shortdesc>
+<content type="string" default="ffffffffffff"/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" depth="0"  timeout="20s" interval="5s" />
+<action name="validate-all"  timeout="20s" />
+<action name="meta-data"  timeout="5s" />
+</actions>
+</resource-agent>
+END
+        exit $OCF_SUCCESS
+}
+
+# The 'ping' command takes highly OS-dependent arguments, so this
+# function creates a suitable argument list for the host OS's 'ping'.
+# We use a subset of its functionality:
+# 1. single packet
+# 2. reasonable timeout (say 1 second)
+#
+# arguments:
+#	$1: IP address to ping
+# result string:
+#	arguments for ping command
+#
+# If more flexibility is needed, they could be specified in the environment
+# to this function, to adjust the resulting 'ping' arguments.
+#	David Lee <t.d.lee at durham.ac.uk> May 2007
+pingargs() {
+	_baseip=$1
+	_timeout=1	# seconds
+	_pktcount=1
+	_systype="`uname -s`"
+	case $_systype in
+		Linux)
+			# Default is perpetual ping: need "-c $_pktcount".
+			# -c count -t timetolive -q(uiet) -n(umeric) -W timeout
+			_pingargs="-c $_pktcount -q -n $_baseip"
+			;;
+		SunOS)
+			# Default is immediate (or timeout) return.
+			_pingargs="$_baseip $_timeout"
+			;;
+		*)
+			_pingargs="-c $_pktcount $_baseip"
+			;;
+	esac
+
+	echo "$_pingargs"
+}
+
+#      On Linux systems the (hidden) loopback interface may
+#      conflict with the requested IP address. If so, this
+#      unoriginal code will remove the offending loopback address
+#      and save it in VLDIR so it can be added back in later
+#      when the IPaddr is released.
+#
+lvs_remove_conflicting_loopback() {
+	ipaddr="$1"
+	ifname="$2"
+
+	ocf_log info "Removing conflicting loopback $ifname."
+	if 
+	  echo $ifname > "$VLDIR/$ipaddr"
+	then
+	  : Saved loopback information in $VLDIR/$ipaddr
+	else
+	  ocf_log err "Could not save conflicting loopback $ifname." \
+	  "it will not be restored."
+	fi
+
+	if [ ! -z "${OCF_RESKEY_local_stop_script}" ]; then
+		if [ -x "${OCF_RESKEY_local_stop_script}" ]; then
+			${OCF_RESKEY_local_stop_script} $*
+		fi
+	fi
+
+	delete_interface "$ifname" "$ipaddr"
+
+	# Forcibly remove the route (if it exists) to the loopback.
+	delete_route "$ipaddr"
+}
+
+#
+#      On Linux systems the (hidden) loopback interface may
+#      need to be restored if it has been taken down previously
+#      by lvs_remove_conflicting_loopback()
+#
+lvs_restore_loopback() {
+    ipaddr="$1"
+    
+    if [ ! -s "$VLDIR/$ipaddr" ]; then
+	return
+    fi
+
+    ifname=`cat "$VLDIR/$ipaddr"`
+    ocf_log info "Restoring loopback IP Address $ipaddr on $ifname."
+    
+    CMD="OCF_RESKEY_cidr_netmask=32 OCF_RESKEY_ip=$1 OCF_RESKEY_nic=$ifname $FINDIF"
+    if
+      NICINFO=`eval $CMD`
+      NICINFO=`echo $NICINFO | tr "	" " " | tr -s " "`
+    then
+	netmask_text=`echo "$NICINFO" | cut -f3 -d " "`
+	broadcast=`echo "$NICINFO" | cut -f5 -d " "`
+    else
+	echo "ERROR: $CMD failed (rc=$rc)"
+	exit $OCF_ERR_GENERIC
+    fi
+    
+    add_interface "$ipaddr" "$ifname" "$ifname" $netmask_text $broadcast
+    rm -f "$VLDIR/$ipaddr"
+}
+
+#
+#      Find out which alias serves the given IP address
+#      The argument is an IP address, and its output
+#      is an aliased interface name (e.g., "eth0:0").
+#
+find_interface_solaris() {
+    ipaddr="$1"
+
+    $IFCONFIG $IFCONFIG_A_OPT | $AWK '{if ($0 ~ /.*: / && NR > 1) {print "\n"$0} else {print}}' |
+    while read ifname linkstuff
+    do
+	: ifname = $ifname
+	read inet addr junk
+	: inet = $inet addr = $addr
+	while
+	read line && [ "X$line" != "X" ]
+	do
+	    : Nothing
+	done
+	
+	case $ifname in
+	    *:*)	;;
+	    *)	continue;;
+	esac
+	
+    #  This doesn't look right for a box with multiple NICs.
+    #  It looks like it always selects the first interface on
+    #  a machine.  Yet, we appear to use the results for this case too...
+	ifname=`echo "$ifname" | sed s'%:$%%'`
+	
+	case $addr in
+	    addr:$ipaddr) echo $ifname; return $OCF_SUCCESS;;
+            $ipaddr)	  echo $ifname; return $OCF_SUCCESS;;
+	esac
+     done
+  return $OCF_ERR_GENERIC
+}
+
+find_interface_bsd() {
+    $IFCONFIG $IFCONFIG_A_OPT | awk -v ip_addr="$ipaddr" '
+					/UP,/ && $0 ~ /^[a-z]+[0-9]:/ { 
+    						if_name=$1; sub(":$","",if_name); 
+					}
+					$1 == "inet" && $2 == ip_addr {
+    						print if_name 
+    						exit(0)
+					}'
+
+}
+
+#
+#	Find out which alias serves the given IP address
+#	The argument is an IP address, and its output
+#	is an aliased interface name (e.g., "eth0:0").
+#
+find_interface_generic() {
+    ipaddr="$1"
+    $IFCONFIG $IFCONFIG_A_OPT  |
+    while read ifname linkstuff
+    do
+	: Read gave us ifname = $ifname
+	
+	read inet addr junk
+	: Read gave us inet = $inet addr = $addr
+	
+	while
+	read line && [ "X$line" != "X" ]
+	do
+	    : Nothing
+	done
+	
+	case $ifname in
+	    *:*)	ifname=`echo $ifname | sed 's/:$//'`;;
+	    *)	continue;;
+	esac
+	
+	: "comparing $ipaddr to $addr (from ifconfig)"
+	case $addr in
+	    addr:$ipaddr)   echo $ifname; return $OCF_SUCCESS;;
+	    $ipaddr)	    echo $ifname; return $OCF_SUCCESS;;
+	esac
+     done
+     return $OCF_ERR_GENERIC 
+}
+
+#
+#       Find out which alias serves the given IP address
+#       The argument is an IP address, and its output
+#       is an aliased interface name (e.g., "eth0:0").
+#
+find_interface() {
+    ipaddr="$1"
+    case "$SYSTYPE" in
+	SunOS)
+	    NIC=`find_interface_solaris $ipaddr`;;
+	*BSD)
+	    NIC=`find_interface_bsd $ipaddr`;;
+	*)
+	    NIC=`find_interface_generic $ipaddr`;;
+       esac
+
+  echo $NIC
+  return $OCF_SUCCESS;
+}
+
+#
+#	Find an unused interface/alias name for us to use for new IP alias
+#	The argument is an IP address, and the output
+#	is an aliased interface name (e.g., "eth0:0", "dc0", "le0:0").
+#
+find_free_interface() {
+    NIC="$1"
+
+    if [ "X$NIC" = "X" ]; then
+	ocf_log err "No free interface found for $OCF_RESKEY_ip"
+	return $OCF_ERR_GENERIC;
+    fi
+
+  NICBASE="$VLDIR/IPaddr-$NIC"
+  touch "$NICBASE"
+
+  case "$SYSTYPE" in
+	*BSD)
+		echo $NIC;
+		return $OCF_SUCCESS;;
+	SunOS)
+		j=1
+		IFLIST=`$IFCONFIG $IFCONFIG_A_OPT | \
+			grep "^$NIC:[0-9]" | sed 's%: .*%%'`;;
+	*)
+		j=0
+		IFLIST=`$IFCONFIG $IFCONFIG_A_OPT | \
+			grep "^$NIC:[0-9]" | sed 's% .*%%'`
+                TRYADRCNT=`ls "${NICBASE}:"* 2>/dev/null | wc -w | tr -d ' '`
+		if [ -f "${NICBASE}:${TRYADRCNT}" ]; then
+		  : OK
+		else
+		  j="${TRYADRCNT}"
+		fi
+		;;
+  esac
+
+  IFLIST=" `echo $IFLIST` "
+  while
+     [ $j -lt 512 ]
+  do
+      case $IFLIST in
+	  *" "$NIC:$j" "*)	
+		;;
+	  *)
+		NICLINK="$NICBASE:$j"
+		if
+		    ln "$NICBASE" "$NICLINK" 2>/dev/null
+		then
+		    echo "$NIC:$j"
+		    return $OCF_SUCCESS
+		fi
+		;;
+       esac
+       j=`expr $j + 1`
+  done
+  return $OCF_ERR_GENERIC
+}
+
+delete_route () {
+  ipaddr="$1"
+
+  case "$SYSTYPE" in
+	SunOS)	return 0;;
+	*BSD)	CMD="$ROUTE -n delete -host $ipaddr";;
+	*)	CMD="$ROUTE -n del -host $ipaddr";;
+  esac
+
+  $CMD
+
+  return $?
+}
+
+delete_interface () {
+  ifname="$1"
+  ipaddr="$2"
+
+  case "$SYSTYPE" in
+      SunOS)
+		if [ "$SYSVERSION" -ge 8 ] ; then
+		    CMD="$IFCONFIG $ifname unplumb"
+		else
+		    CMD="$IFCONFIG $ifname 0 down"
+		fi;;
+      Darwin*)
+		CMD="$IFCONFIG $ifname $ipaddr delete";;
+      *BSD)
+		CMD="$IFCONFIG $ifname inet $ipaddr delete";;
+      *)
+		CMD="$IFCONFIG $ifname down";;
+  esac
+
+  ocf_log info "$CMD"
+  $CMD
+
+  return $?
+}
+
+
+add_interface () {
+  ipaddr="$1"
+  iface_base="$2"
+  iface="$3"
+  netmask="$4"
+  broadcast="$5"
+
+  if [ $# != 5 ]; then
+      ocf_log err "Insufficient arguments to add_interface: $*"
+      exit $OCF_ERR_ARGS
+  fi
+
+  case "$SYSTYPE" in
+    SunOS)
+	  if [ "$SYSVERSION" -ge 8 ] ; then
+	      $IFCONFIG $iface plumb
+	      rc=$?
+	      if [ $rc -ne 0 ] ; then
+		  echo "ERROR: '$IFCONFIG $iface plumb' failed."
+		  return $rc
+	      fi
+	  fi
+	  # At Solaris 10, this single-command version sometimes broke.
+	  # Almost certainly an S10 bug.
+	  #	CMD="$IFCONFIG $iface inet $ipaddr $text up"
+	  # So hack the following workaround:
+	  CMD="$IFCONFIG $iface inet $ipaddr"
+	  CMD="$CMD && $IFCONFIG $iface netmask $netmask"
+	  CMD="$CMD && $IFCONFIG $iface up"
+	  ;;
+      
+    *BSD)
+	  # netmask is always set to 255.255.255.255 for an alias 
+	  CMD="$IFCONFIG $iface inet $ipaddr netmask 255.255.255.255 alias";;
+    *)		
+	  CMD="$IFCONFIG $iface $ipaddr netmask $netmask broadcast $broadcast";;
+  esac
+
+  # Use "eval $CMD" (not "$CMD"): it might be a chain of two or more commands.
+  ocf_log info "eval $CMD"
+  eval $CMD
+  rc=$?
+  if [ $rc != 0 ]; then
+      echo "ERROR: eval $CMD failed (rc=$rc)"
+  fi
+
+  return $rc
+}
+
+#
+#	Remove the IP alias for the requested IP address...
+#
+ip_stop() {
+  SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$OCF_RESKEY_ip"
+  NIC=`find_interface $OCF_RESKEY_ip`
+
+  if [ -f "$SENDARPPIDFILE" ]; then
+	cat "$SENDARPPIDFILE" | xargs kill
+	rm -f "$SENDARPPIDFILE"
+  fi
+
+  if [ -z "$NIC" ]; then
+      : Requested interface not in use
+      return $OCF_SUCCESS
+  fi
+
+  if [ ${OCF_RESKEY_lvs_support} = 1 ]; then 
+      case $NIC in
+	  lo*)
+	      : Requested interface is on loopback
+	      return $OCF_SUCCESS;;
+      esac
+  fi
+
+  delete_route "$OCF_RESKEY_ip"
+  delete_interface "$NIC" "$OCF_RESKEY_ip"
+  rc=$?
+
+  if [ ${OCF_RESKEY_lvs_support} = 1 ]; then
+      lvs_restore_loopback "$OCF_RESKEY_ip"
+  fi
+
+  # remove lock file...
+  rm -f "$VLDIR/IPaddr-$NIC"
+
+  if [ $rc != 0 ]; then
+      ocf_log warn "IP Address $OCF_RESKEY_ip NOT released: rc=$rc"
+      return $OCF_ERR_GENERIC
+  fi
+  return $OCF_SUCCESS
+}
+
+
+#
+#	Add an IP alias for the requested IP address...
+#
+#	It could be that we already have taken it, in which case it should
+#	do nothing.
+#
+
+ip_start() {
+  #
+  #	Do we already service this IP address?
+  #
+    ip_status_internal
+    if [ $? = $OCF_SUCCESS ]; then
+	# Nothing to do, the IP is already active
+	return $OCF_SUCCESS;
+    fi
+
+    NIC_unique=`find_free_interface $OCF_RESKEY_nic`
+    if [ -n "$NIC_unique" ]; then
+	: OK got interface [$NIC_unique] for $OCF_RESKEY_ip 
+    else
+	return $OCF_ERR_GENERIC
+    fi
+    
+    # This logic is mostly to support LVS (If I understand it correctly)
+    if [ ${OCF_RESKEY_lvs_support} = 1 ]; then
+	NIC_current=`find_interface $OCF_RESKEY_ip`
+	case $NIC_unique in
+	    lo*) 
+		if [ x"$NIC_unique" = x"$NIC_current" ]; then
+		    # Its already "running" and not moving, nothing to do.
+		    ocf_log err "Could not find a non-loopback device to move $OCF_RESKEY_ip to"
+		    return $OCF_ERR_GENERIC
+		fi;;
+	    *)   lvs_remove_conflicting_loopback "$OCF_RESKEY_ip" "$NIC_current";;
+	esac
+    fi
+
+	if [ ! -z "${OCF_RESKEY_local_start_script}" ]; then
+		if [ -x "${OCF_RESKEY_local_start_script}" ]; then
+			${OCF_RESKEY_local_start_script} $*
+		fi
+	fi
+
+    add_interface "$OCF_RESKEY_ip" "$OCF_RESKEY_nic" "$NIC_unique" \
+		 "$OCF_RESKEY_cidr_netmask" "$OCF_RESKEY_broadcast"
+    rc=$?
+    if [ $rc != 0 ]; then
+	ocf_log err "Could not add $OCF_RESKEY_ip to $OCF_RESKEY_nic: rc=$rc"
+	return $rc
+    fi
+
+    # The address is active, now notify others about it using sendarp
+
+    if [ "$SYSTYPE" = "DarwinBSD" -a "$NIC_unique" = "lo0" ]; then
+	# Darwin can't send ARPs on loopback devices
+	SENDARP="x$SENDARP" # Prevent the binary from being found
+    fi
+
+    if [ -x $SENDARP ]; then
+	TARGET_INTERFACE=`echo $NIC_unique | sed 's%:.*%%'`
+	SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$OCF_RESKEY_ip"    
+       
+	ARGS="-i $OCF_RESKEY_ARP_INTERVAL_MS -r $OCF_RESKEY_ARP_REPEAT"
+	ARGS="$ARGS -p $SENDARPPIDFILE $TARGET_INTERFACE $OCF_RESKEY_ip"
+	ARGS="$ARGS auto $OCF_RESKEY_ip $OCF_RESKEY_ARP_NETMASK"
+
+	ocf_log debug "Sending Gratuitous Arp for $OCF_RESKEY_ip on $NIC_unique [$TARGET_INTERFACE]"
+	case $OCF_RESKEY_ARP_BACKGROUND in
+	    yes) ($SENDARP $ARGS || ocf_log err "Could not send gratuitous arps. rc=$?" & ) >&2 ;;
+	    *)   $SENDARP $ARGS || ocf_log err "Could not send gratuitous arps. rc=$?";;
+	esac
+    fi
+
+    ip_status_internal
+    return $?
+}
+
+ip_status_internal() {
+    NIC=`find_interface "$OCF_RESKEY_ip"`
+
+    if [ "x$NIC" = x ]; then
+	return $OCF_NOT_RUNNING
+
+    elif [ "${OCF_RESKEY_lvs_support}" = "1" ]; then 
+	case $NIC in
+	    lo*) return $OCF_NOT_RUNNING;;
+	    *)	 return $OCF_SUCCESS;;
+	esac
+    else
+	if [ x$OCF_RESKEY_nic != x ]; then
+	    simple_OCF_NIC=`echo $OCF_RESKEY_nic | awk -F: '{print $1}'`
+	    simple_NIC=`echo $NIC | awk -F: '{print $1}'`
+	    if [ $simple_OCF_NIC != $simple_NIC ]; then
+		ocf_log err "$OCF_RESKEY_ip is running an interface ($simple_NIC) instead of the configured one ($simple_OCF_NIC)"
+		return $OCF_ERR_GENERIC
+	    fi
+	fi
+	return $OCF_SUCCESS
+    fi
+}
+
+ip_status() {
+    ip_status_internal
+    rc=$?
+    if [ $rc = $OCF_SUCCESS ]; then
+	echo "running"
+    elif [ $rc = $OCF_NOT_RUNNING ]; then
+	echo "stopped"
+    else
+	echo "unknown"
+    fi
+    return $rc;
+}
+
+#
+#	Determine if this IP address is really being served, or not.
+#	Note that we must distinguish if *we're* serving it locally...
+#
+ip_monitor() {
+    ip_status_internal
+    rc=$?
+
+    if [ $OCF_CHECK_LEVEL = 0 -o $rc != 0 ]; then
+	return $rc
+    fi
+    
+    ocf_log info "Checking IP stack"
+
+    PINGARGS="`pingargs $OCF_RESKEY_ip`"
+    for j in 1 2 3 4 5 6 7 8 9 10; do
+        MSG=`$PING $PINGARGS 2>&1`
+        if [ $? = 0 ]; then
+            return $OCF_SUCCESS
+        fi
+    done
+
+    ocf_log err "$MSG"
+    return $OCF_ERR_GENERIC
+}
+
+is_positive_integer() {
+    ocf_is_decimal $1 && [ $1 -ge 1 ]
+    if [ $? = 0 ]; then
+	return 1
+    fi
+    return 0
+}
+
+ip_validate_all() {
+    : ${OCF_RESKEY_ARP_BACKGROUND=yes}
+    : ${OCF_RESKEY_ARP_NETMASK=ffffffffffff}
+    : ${OCF_RESKEY_ARP_INTERVAL_MS=500}
+    : ${OCF_RESKEY_ARP_REPEAT=10}
+
+
+    check_binary $AWK
+    check_binary $IFCONFIG
+    check_binary $ROUTE
+    check_binary $PING
+
+    if is_positive_integer $OCF_RESKEY_ARP_INTERVAL_MS
+    then
+	ocf_log err "Invalid parameter value: ARP_INTERVAL_MS [$OCF_RESKEY_ARP_INTERVAL_MS]"
+	return $OCF_ERR_ARGS
+    fi
+
+    if is_positive_integer $OCF_RESKEY_ARP_REPEAT
+    then
+	ocf_log err "Invalid parameter value: ARP_REPEAT [$OCF_RESKEY_ARP_REPEAT]"
+	return $OCF_ERR_ARGS
+    fi
+
+    : ${OCF_RESKEY_lvs_support=0}
+    if [ "$SYSTYPE" = "Linux" -o "$SYSTYPE" = "SunOS" ]; then
+	:
+    else 
+	if [ "${OCF_RESKEY_lvs_support}" = "1" ]; then
+	    ocf_log err "$SYSTYPE does not support LVS"
+	    return $OCF_ERR_GENERIC
+	fi
+    fi
+
+    case $OCF_RESKEY_ip in
+	"")	ocf_log err "Required parameter OCF_RESKEY_ip is missing"
+	    return $OCF_ERR_CONFIGURED;;
+        [0-9]*.[0-9]*.[0-9]*.*[0-9])	: OK;;
+	*)	ocf_log err "Parameter OCF_RESKEY_ip [$OCF_RESKEY_ip] not an IP address"
+	    return $OCF_ERR_CONFIGURED;;
+    esac
+
+    # Unconditionally do this?
+    case $OCF_RESKEY_nic in
+        *:*)
+            OCF_RESKEY_nic=`echo $OCF_RESKEY_nic | sed 's/:.*//'`
+            ;;
+    esac
+
+    NICINFO=`$FINDIF`
+    rc=$?
+
+    if [ $rc != 0 ]; then
+	ocf_log err "$FINDIF failed [rc=$rc]."
+	return $OCF_ERR_GENERIC
+    fi
+    
+    tmp=`echo "$NICINFO" | cut -f1`
+    if
+      [ "x$OCF_RESKEY_nic" = "x" ]
+    then
+      ocf_log info "Using calculated nic for ${OCF_RESKEY_ip}: $tmp"
+      OCF_RESKEY_nic=$tmp
+    elif
+      [ x$tmp != x${OCF_RESKEY_nic} ]
+    then
+      ocf_log err "Invalid parameter value: nic [$OCF_RESKEY_nic] Calculated nic: [$tmp]"
+      return $OCF_ERR_ARGS
+    fi
+
+    tmp=`echo "$NICINFO" | cut -f2 | cut -d ' ' -f2`
+    if
+      [ "x$OCF_RESKEY_cidr_netmask" != "x$tmp" ]
+    then
+      ocf_log info "Using calculated netmask for ${OCF_RESKEY_ip}: $tmp"
+    fi
+
+    # Always use the calculated version becuase it might have been specified 
+    #  using CIDR notation which not every system accepts
+    OCF_RESKEY_netmask=$tmp
+    OCF_RESKEY_cidr_netmask=$tmp; export OCF_RESKEY_cidr_netmask
+    
+    tmp=`echo "$NICINFO" | cut -f3 | cut -d ' ' -f2`
+    if
+      [ "x$OCF_RESKEY_broadcast" = "x" ]
+    then
+      ocf_log debug "Using calculated broadcast for ${OCF_RESKEY_ip}: $tmp"
+      OCF_RESKEY_broadcast=$tmp
+
+    elif [ x$tmp != x${OCF_RESKEY_broadcast} ]; then
+      ocf_log err "Invalid parameter value: broadcast [$OCF_RESKEY_broadcast] Calculated broadcast: [$tmp]"
+      return $OCF_ERR_ARGS
+    fi
+    
+    return $OCF_SUCCESS
+}
+  
+usage() {
+    echo $USAGE >&2
+    return $1
+}
+
+if [ $# -ne 1 ]; then
+    usage $OCF_ERR_ARGS
+fi
+
+: ${OCF_RESKEY_lvs_support=0}
+# Normalize the value of lvs_support
+if [ "${OCF_RESKEY_lvs_support}" = "true" \
+    -o "${OCF_RESKEY_lvs_support}" = "on" \
+    -o "${OCF_RESKEY_lvs_support}" = "yes" \
+    -o "${OCF_RESKEY_lvs_support}" = "1" ]; then
+    OCF_RESKEY_lvs_support=1
+else
+    OCF_RESKEY_lvs_support=0
+fi
+
+# Note: We had a version out there for a while which used
+# netmask instead of cidr_netmask. So, don't remove this aliasing code!
+if
+  [ ! -z "$OCF_RESKEY_netmask" -a -z "$OCF_RESKEY_cidr_netmask" ]
+then
+  OCF_RESKEY_cidr_netmask=$OCF_RESKEY_netmask
+  export OCF_RESKEY_cidr_netmask
+fi
+
+case $1 in
+    meta-data)		meta_data;;
+    start)		ip_validate_all	&& ip_start;;
+    stop)		ip_stop;;
+    status)		ip_status;;
+    monitor)		ip_monitor;;
+    validate-all)	ip_validate_all;;
+    usage)		usage $OCF_SUCCESS;;
+    *)			usage $OCF_ERR_UNIMPLEMENTED;;
+esac
+
+exit $?
diff --git a/heartbeat/IPaddr2 b/heartbeat/IPaddr2
new file mode 100755
index 0000000..014744d
--- /dev/null
+++ b/heartbeat/IPaddr2
@@ -0,0 +1,1075 @@
+#!/bin/sh
+#
+#	$Id: IPaddr2.in,v 1.24 2006/08/09 13:01:54 lars Exp $
+#
+#       OCF Resource Agent compliant IPaddr2 script.
+#
+# 	Based on work by Tuomo Soini, ported to the OCF RA API by Lars
+# 	Marowsky-Brée. Implements Cluster Alias IP functionality too.
+#
+#	Cluster Alias IP cleanup, fixes and testing by Michael Schwartzkopff
+#
+#
+# Copyright (c) 2003 Tuomo Soini
+# Copyright (c) 2004-2006 SUSE LINUX AG, Lars Marowsky-Brée
+#                    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.
+#
+#
+
+
+# TODO: 
+# - There ought to be an ocf_run_cmd function which does all logging,
+#   timeout handling etc for us
+# - Make this the standard IP address agent on Linux; the other
+#   platforms simply should ignore the additional parameters OR can use
+#   the legacy heartbeat resource script...
+# - Check LVS <-> clusterip incompatibilities.
+#
+#	OCF parameters are as below
+#	OCF_RESKEY_ip
+#	OCF_RESKEY_broadcast
+#	OCF_RESKEY_nic
+#	OCF_RESKEY_cidr_netmask
+#	OCF_RESKEY_iflabel
+#	OCF_RESKEY_mac
+#	OCF_RESKEY_clusterip_hash
+#	OCF_RESKEY_arp_interval
+#	OCF_RESKEY_arp_count
+#	OCF_RESKEY_arp_bg
+#	OCF_RESKEY_arp_mac
+#
+#	OCF_RESKEY_CRM_meta_clone
+#	OCF_RESKEY_CRM_meta_clone_max
+
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+. ${OCF_FUNCTIONS_DIR}/findif.sh
+
+# Defaults
+OCF_RESKEY_lvs_support_default=false
+OCF_RESKEY_lvs_ipv6_addrlabel_default=false
+OCF_RESKEY_lvs_ipv6_addrlabel_value_default=99
+OCF_RESKEY_clusterip_hash_default="sourceip-sourceport"
+OCF_RESKEY_unique_clone_address_default=false
+OCF_RESKEY_arp_interval_default=200
+OCF_RESKEY_arp_count_default=5
+OCF_RESKEY_arp_bg_default=true
+OCF_RESKEY_arp_mac_default="ffffffffffff"
+
+: ${OCF_RESKEY_lvs_support=${OCF_RESKEY_lvs_support_default}}
+: ${OCF_RESKEY_lvs_ipv6_addrlabel=${OCF_RESKEY_lvs_ipv6_addrlabel_default}}
+: ${OCF_RESKEY_lvs_ipv6_addrlabel_value=${OCF_RESKEY_lvs_ipv6_addrlabel_value_default}}
+: ${OCF_RESKEY_clusterip_hash=${OCF_RESKEY_clusterip_hash_default}}
+: ${OCF_RESKEY_unique_clone_address=${OCF_RESKEY_unique_clone_address_default}}
+: ${OCF_RESKEY_arp_interval=${OCF_RESKEY_arp_interval_default}}
+: ${OCF_RESKEY_arp_count=${OCF_RESKEY_arp_count_default}}
+: ${OCF_RESKEY_arp_bg=${OCF_RESKEY_arp_bg_default}}
+: ${OCF_RESKEY_arp_mac=${OCF_RESKEY_arp_mac_default}}
+#######################################################################
+
+SENDARP=$HA_BIN/send_arp
+SENDUA=$HA_BIN/send_ua
+FINDIF=findif
+VLDIR=$HA_RSCTMP
+SENDARPPIDDIR=$HA_RSCTMP
+CIP_lockfile=$HA_RSCTMP/IPaddr2-CIP-${OCF_RESKEY_ip}
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="IPaddr2">
+<version>1.0</version>
+
+<longdesc lang="en">
+This Linux-specific resource manages IP alias IP addresses.
+It can add an IP alias, or remove one.
+In addition, it can implement Cluster Alias IP functionality
+if invoked as a clone resource.
+
+If used as a clone, you should explicitly set clone-node-max >= 2,
+and/or clone-max < number of nodes. In case of node failure,
+clone instances need to be re-allocated on surviving nodes.
+This would not be possible if there is already an instance on those nodes,
+and clone-node-max=1 (which is the default).
+</longdesc>
+
+<shortdesc lang="en">Manages virtual IPv4 and IPv6 addresses (Linux specific version)</shortdesc>
+
+<parameters>
+<parameter name="ip" unique="1" required="1">
+<longdesc lang="en">
+The IPv4 (dotted quad notation) or IPv6 address (colon hexadecimal notation)
+example IPv4 "192.168.1.1".
+example IPv6 "2001:db8:DC28:0:0:FC57:D4C8:1FFF".
+</longdesc>
+<shortdesc lang="en">IPv4 or IPv6 address</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="nic" unique="0">
+<longdesc lang="en">
+The base network interface on which the IP address will be brought
+online. 
+If left empty, the script will try and determine this from the
+routing table.
+
+Do NOT specify an alias interface in the form eth0:1 or anything here;
+rather, specify the base interface only.
+If you want a label, see the iflabel parameter.
+
+Prerequisite:
+
+There must be at least one static IP address, which is not managed by
+the cluster, assigned to the network interface.
+If you can not assign any static IP address on the interface,
+modify this kernel parameter:
+
+sysctl -w net.ipv4.conf.all.promote_secondaries=1 # (or per device)
+</longdesc>
+<shortdesc lang="en">Network interface</shortdesc>
+<content type="string"/>
+</parameter>
+
+<parameter name="cidr_netmask">
+<longdesc lang="en">
+The netmask for the interface in CIDR format
+(e.g., 24 and not 255.255.255.0)
+
+If unspecified, the script will also try to determine this from the
+routing table.
+</longdesc>
+<shortdesc lang="en">CIDR netmask</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="broadcast">
+<longdesc lang="en">
+Broadcast address associated with the IP. If left empty, the script will
+determine this from the netmask.
+</longdesc>
+<shortdesc lang="en">Broadcast address</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="iflabel">
+<longdesc lang="en">
+You can specify an additional label for your IP address here.
+This label is appended to your interface name.
+
+The kernel allows alphanumeric labels up to a maximum length of 15
+characters including the interface name and colon (e.g. eth0:foobar1234)
+
+A label can be specified in nic parameter but it is deprecated.
+If a label is specified in nic name, this parameter has no effect.
+</longdesc>
+<shortdesc lang="en">Interface label</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="lvs_support">
+<longdesc lang="en">
+Enable support for LVS Direct Routing configurations. In case a IP
+address is stopped, only move it to the loopback device to allow the
+local node to continue to service requests, but no longer advertise it
+on the network.
+
+Notes for IPv6:
+It is not necessary to enable this option on IPv6.
+Instead, enable 'lvs_ipv6_addrlabel' option for LVS-DR usage on IPv6.
+</longdesc>
+<shortdesc lang="en">Enable support for LVS DR</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_lvs_support_default}"/>
+</parameter>
+
+<parameter name="lvs_ipv6_addrlabel">
+<longdesc lang="en">
+Enable adding IPv6 address label so IPv6 traffic originating from
+the address's interface does not use this address as the source.
+This is necessary for LVS-DR health checks to realservers to work. Without it,
+the most recently added IPv6 address (probably the address added by IPaddr2)
+will be used as the source address for IPv6 traffic from that interface and
+since that address exists on loopback on the realservers, the realserver
+response to pings/connections will never leave its loopback.
+See RFC3484 for the detail of the source address selection.
+
+See also 'lvs_ipv6_addrlabel_value' parameter.
+</longdesc>
+<shortdesc lang="en">Enable adding IPv6 address label.</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_lvs_ipv6_addrlabel_default}"/>
+</parameter>
+
+<parameter name="lvs_ipv6_addrlabel_value">
+<longdesc lang="en">
+Specify IPv6 address label value used when 'lvs_ipv6_addrlabel' is enabled.
+The value should be an unused label in the policy table
+which is shown by 'ip addrlabel list' command.
+You would rarely need to change this parameter.
+</longdesc>
+<shortdesc lang="en">IPv6 address label value.</shortdesc>
+<content type="integer" default="${OCF_RESKEY_lvs_ipv6_addrlabel_value_default}"/>
+</parameter>
+
+<parameter name="mac">
+<longdesc lang="en">
+Set the interface MAC address explicitly. Currently only used in case of
+the Cluster IP Alias. Leave empty to chose automatically.
+
+</longdesc>
+<shortdesc lang="en">Cluster IP MAC address</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="clusterip_hash">
+<longdesc lang="en">
+Specify the hashing algorithm used for the Cluster IP functionality.
+
+</longdesc>
+<shortdesc lang="en">Cluster IP hashing function</shortdesc>
+<content type="string" default="${OCF_RESKEY_clusterip_hash_default}"/>
+</parameter>
+
+<parameter name="unique_clone_address">
+<longdesc lang="en">
+If true, add the clone ID to the supplied value of IP to create
+a unique address to manage 
+</longdesc>
+<shortdesc lang="en">Create a unique address for cloned instances</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_unique_clone_address_default}"/>
+</parameter>
+
+<parameter name="arp_interval">
+<longdesc lang="en">
+Specify the interval between unsolicited ARP packets in milliseconds.
+</longdesc>
+<shortdesc lang="en">ARP packet interval in ms</shortdesc>
+<content type="integer" default="${OCF_RESKEY_arp_interval_default}"/>
+</parameter>
+
+<parameter name="arp_count">
+<longdesc lang="en">
+Number of unsolicited ARP packets to send.
+</longdesc>
+<shortdesc lang="en">ARP packet count</shortdesc>
+<content type="integer" default="${OCF_RESKEY_arp_count_default}"/>
+</parameter>
+
+<parameter name="arp_bg">
+<longdesc lang="en">
+Whether or not to send the ARP packets in the background.
+</longdesc>
+<shortdesc lang="en">ARP from background</shortdesc>
+<content type="string" default="${OCF_RESKEY_arp_bg_default}"/>
+</parameter>
+
+<parameter name="arp_mac">
+<longdesc lang="en">
+MAC address to send the ARP packets to.
+
+You really shouldn't be touching this.
+
+</longdesc>
+<shortdesc lang="en">ARP MAC</shortdesc>
+<content type="string" default="${OCF_RESKEY_arp_mac_default}"/>
+</parameter>
+
+<parameter name="arp_sender">
+<longdesc lang="en">
+The program to send ARP packets with on start. For infiniband
+interfaces, default is ipoibarping. If ipoibarping is not
+available, set this to send_arp.
+</longdesc>
+<shortdesc lang="en">ARP sender</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="flush_routes">
+<longdesc lang="en">
+Flush the routing table on stop. This is for
+applications which use the cluster IP address
+and which run on the same physical host that the
+IP address lives on. The Linux kernel may force that
+application to take a shortcut to the local loopback
+interface, instead of the interface the address
+is really bound to. Under those circumstances, an
+application may, somewhat unexpectedly, continue
+to use connections for some time even after the
+IP address is deconfigured. Set this parameter in
+order to immediately disable said shortcut when the
+IP address goes away.
+</longdesc>
+<shortdesc lang="en">Flush kernel routing table on stop</shortdesc>
+<content type="boolean" default="false"/>
+</parameter>
+
+</parameters>
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="status" depth="0"  timeout="20s" interval="10s" />
+<action name="monitor" depth="0"  timeout="20s" interval="10s" />
+<action name="meta-data"  timeout="5s" />
+<action name="validate-all"  timeout="20s" />
+</actions>
+</resource-agent>
+END
+
+	exit $OCF_SUCCESS
+}
+
+ip_init() {
+	local rc
+
+	if [ X`uname -s` != "XLinux" ]; then
+		ocf_log err "IPaddr2 only supported Linux."
+		exit $OCF_ERR_INSTALLED
+	fi
+
+	if [ X"$OCF_RESKEY_ip" = "X" ]; then
+		ocf_log err "IP address (the ip parameter) is mandatory"
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	if
+          case $__OCF_ACTION in
+            start|stop)		ocf_is_root;;
+            *)			true;;
+          esac
+        then
+          : YAY!
+        else
+		ocf_log err "You must be root for $__OCF_ACTION operation."
+		exit $OCF_ERR_PERM
+	fi
+
+	BASEIP="$OCF_RESKEY_ip"
+	BRDCAST="$OCF_RESKEY_broadcast"
+	NIC="$OCF_RESKEY_nic"
+        # Note: We had a version out there for a while which used
+        # netmask instead of cidr_netmask. Don't remove this aliasing code!
+        if
+          [ ! -z "$OCF_RESKEY_netmask" -a -z "$OCF_RESKEY_cidr_netmask" ]
+        then
+	  OCF_RESKEY_cidr_netmask=$OCF_RESKEY_netmask
+	  export OCF_RESKEY_cidr_netmask
+        fi
+	NETMASK="$OCF_RESKEY_cidr_netmask"
+	IFLABEL="$OCF_RESKEY_iflabel"
+	IF_MAC="$OCF_RESKEY_mac"
+
+	IP_INC_GLOBAL=${OCF_RESKEY_CRM_meta_clone_max:-1}
+	IP_INC_NO=`expr ${OCF_RESKEY_CRM_meta_clone:-0} + 1`
+
+	if ocf_is_true ${OCF_RESKEY_lvs_support} && [ $IP_INC_GLOBAL -gt 1 ]; then
+		ocf_log err "LVS and load sharing do not go together well"
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	if ocf_is_decimal "$IP_INC_GLOBAL" && [ $IP_INC_GLOBAL -gt 0 ]; then
+		:
+	else
+		ocf_log err "Invalid OCF_RESKEY_incarnations_max_global [$IP_INC_GLOBAL], should be positive integer"
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	echo $OCF_RESKEY_ip | grep -qs ":"
+	if [ $? -ne 0 ];then
+		FAMILY=inet
+		if ocf_is_true $OCF_RESKEY_lvs_ipv6_addrlabel ;then
+			ocf_log err "IPv4 does not support lvs_ipv6_addrlabel"
+			exit $OCF_ERR_CONFIGURED
+		fi
+	else
+		FAMILY=inet6
+		if ocf_is_true $OCF_RESKEY_lvs_support ;then
+			ocf_log err "The IPv6 does not support lvs_support"
+			exit $OCF_ERR_CONFIGURED
+		fi
+		if ocf_is_true $OCF_RESKEY_lvs_ipv6_addrlabel ;then
+			if ocf_is_decimal "$OCF_RESKEY_lvs_ipv6_addrlabel_value" && [ $OCF_RESKEY_lvs_ipv6_addrlabel_value -ge 0 ]; then
+			    :
+			else
+			    ocf_log err "Invalid lvs_ipv6_addrlabel_value [$OCF_RESKEY_lvs_ipv6_addrlabel_value], should be positive integer"
+			    exit $OCF_ERR_CONFIGURED
+			fi
+		fi
+	fi
+
+	# support nic:iflabel format in nic parameter
+	case $NIC in
+	    *:*)
+		IFLABEL=`echo $NIC | sed 's/[^:]*://'`
+		NIC=`echo $NIC | sed 's/:.*//'`
+		# only the base name should be passed to findif
+		OCF_RESKEY_nic=$NIC
+		;;
+	esac
+
+	# $FINDIF takes its parameters from the environment
+	#
+	NICINFO=`$FINDIF`
+	rc=$?
+	if
+	  [ $rc -eq 0 ]
+        then
+	    NICINFO=`echo "$NICINFO" | sed -e 's/netmask\ //;s/broadcast\ //'`
+	    NIC=`echo "$NICINFO" | cut -d" " -f1`
+	    NETMASK=`echo "$NICINFO" | cut -d" " -f2`
+	    BRDCAST=`echo "$NICINFO" | cut -d" " -f3`
+	else
+		# findif couldn't find the interface
+		if ocf_is_probe; then
+			ocf_log info "[$FINDIF] failed"
+			exit $OCF_NOT_RUNNING
+		elif [ "$__OCF_ACTION" = stop ]; then
+			ocf_log warn "[$FINDIF] failed"
+			exit $OCF_SUCCESS
+		else
+			ocf_log err "[$FINDIF] failed"
+			exit $rc
+		fi
+	fi
+	
+	SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$OCF_RESKEY_ip"
+
+	if [ -n "$IFLABEL" ]; then
+		IFLABEL=${NIC}:${IFLABEL}
+		if [ ${#IFLABEL} -gt 15 ]; then
+			ocf_log err "Interface label [$IFLABEL] exceeds maximum character limit of 15"
+			exit $OCF_ERR_CONFIGURED
+		fi
+	fi
+
+	if [ "$IP_INC_GLOBAL" -gt 1 ] && ! ocf_is_true "$OCF_RESKEY_unique_clone_address"; then
+		IP_CIP="yes"
+		IP_CIP_HASH="${OCF_RESKEY_clusterip_hash}"
+		if [ -z "$IF_MAC" ]; then
+			# Choose a MAC
+			# 1. Concatenate some input together
+			# 2. This doesn't need to be a cryptographically
+			#    secure hash.
+			# 3. Drop everything after the first 6 octets (12 chars)
+			# 4. Delimit the octets with ':'
+			# 5. Make sure the first octet is odd,
+			#    so the result is a multicast MAC
+			IF_MAC=`echo $OCF_RESKEY_ip $NETMASK $BRDCAST |	\
+				md5sum |				\
+				sed -e 's#\(............\).*#\1#'	\
+				    -e 's#..#&:#g; s#:$##'		\
+				    -e 's#^\(.\)[02468aAcCeE]#\11#'`
+		fi
+		IP_CIP_FILE="/proc/net/ipt_CLUSTERIP/$OCF_RESKEY_ip"
+	fi
+}
+
+#
+#	Find out which interfaces serve the given IP address and netmask.
+#	The arguments are an IP address and a netmask.
+#	Its output are interface names devided by spaces (e.g., "eth0 eth1").
+#
+find_interface() {
+	local ipaddr="$1"
+	local netmask="$2"
+
+	#
+	# List interfaces but exclude FreeS/WAN ipsecN virtual interfaces
+	#
+	local iface="`$IP2UTIL -o -f $FAMILY addr show \
+		| grep "\ $ipaddr/$netmask" \
+		| cut -d ' ' -f2 \
+		| grep -v '^ipsec[0-9][0-9]*$'`"
+
+	echo "$iface"
+	return 0
+}
+
+#
+#        Delete an interface
+#
+delete_interface () {
+	ipaddr="$1"
+	iface="$2"
+	netmask="$3"
+
+	CMD="$IP2UTIL -f $FAMILY addr delete $ipaddr/$netmask dev $iface"
+
+	ocf_run $CMD || return $OCF_ERR_GENERIC
+
+	if ocf_is_true $OCF_RESKEY_flush_routes; then
+	    ocf_run $IP2UTIL route flush cache
+	fi
+
+	if [ "$FAMILY" = "inet6" ] && ocf_is_true $OCF_RESKEY_lvs_ipv6_addrlabel ;then
+	    delete_ipv6_addrlabel $ipaddr
+	fi
+
+	return $OCF_SUCCESS
+}
+
+#
+#        Add an interface
+#
+add_interface () {
+	local cmd msg ipaddr netmask broadcast iface label
+
+	ipaddr="$1"
+	netmask="$2"
+	broadcast="$3"
+	iface="$4"
+	label="$5"
+
+	if [ "$FAMILY" = "inet6" ] && ocf_is_true $OCF_RESKEY_lvs_ipv6_addrlabel ;then
+	    add_ipv6_addrlabel $ipaddr
+	fi
+
+	cmd="$IP2UTIL -f $FAMILY addr add $ipaddr/$netmask dev $iface"
+	msg="Adding $FAMILY address $ipaddr/$netmask to device $iface"
+	if [ "$broadcast" != "none" ]; then
+		cmd="$IP2UTIL -f $FAMILY addr add $ipaddr/$netmask brd $broadcast dev $iface"
+		msg="Adding $FAMILY address $ipaddr/$netmask with broadcast address $broadcast to device $iface"
+	fi
+
+	if [ ! -z "$label" ]; then
+		cmd="$cmd label $label"
+		msg="${msg} (with label $label)"
+	fi
+
+	ocf_log info "$msg"
+	ocf_run $cmd || return $OCF_ERR_GENERIC
+
+	msg="Bringing device $iface up"
+	cmd="$IP2UTIL link set $iface up"
+	ocf_log info "$msg"
+	ocf_run $cmd || return $OCF_ERR_GENERIC
+
+	return $OCF_SUCCESS
+}
+
+#
+#        Delete a route
+#
+delete_route () {
+	prefix="$1"
+	iface="$2"
+
+	CMD="$IP2UTIL route delete $prefix dev $iface"
+
+	ocf_log info "$CMD"
+	$CMD
+
+	return $?
+}
+
+#      On Linux systems the (hidden) loopback interface may
+#      conflict with the requested IP address. If so, this
+#      unoriginal code will remove the offending loopback address
+#      and save it in VLDIR so it can be added back in later
+#      when the IPaddr is released.
+#
+#      TODO: This is very ugly and should be controlled by an additional
+#      instance parameter. Or even: multi-state, with the IP only being
+#      "active" on the master!?
+#
+remove_conflicting_loopback() {
+	ipaddr="$1"
+	netmask="$2"
+	broadcast="$3"
+	ifname="$4"
+
+	ocf_log info "Removing conflicting loopback $ifname."
+	if
+		echo "$ipaddr $netmask $broadcast $ifname" > "$VLDIR/$ipaddr"
+	then
+		: Saved loopback information in $VLDIR/$ipaddr
+	else
+		ocf_log err "Could not save conflicting loopback $ifname." \
+		       "it will not be restored."
+	fi
+	delete_interface "$ipaddr" "$ifname" "$netmask"
+	# Forcibly remove the route (if it exists) to the loopback.
+	delete_route "$ipaddr" "$ifname"
+}
+
+#
+#	On Linux systems the (hidden) loopback interface may
+#	need to be restored if it has been taken down previously
+#	by remove_conflicting_loopback()
+#
+restore_loopback() {
+	ipaddr="$1"
+
+	if [ -s "$VLDIR/$ipaddr" ]; then
+		ifinfo=`cat "$VLDIR/$ipaddr"`
+		ocf_log info "Restoring loopback IP Address " \
+		    "$ifinfo."
+		add_interface $ifinfo
+		rm -f "$VLDIR/$ipaddr"
+	fi
+}
+
+add_ipv6_addrlabel() {
+	local cmd ipaddr value
+	ipaddr="$1"
+	value="$OCF_RESKEY_lvs_ipv6_addrlabel_value"
+
+	cmd="$IP2UTIL addrlabel add prefix $ipaddr label $value"
+	ocf_log info "Adding IPv6 address label prefix $ipaddr label $value"
+	ocf_run $cmd || ocf_log warn "$cmd failed."
+}
+
+delete_ipv6_addrlabel() {
+	local cmd ipaddr value
+	ipaddr="$1"
+	value="$OCF_RESKEY_lvs_ipv6_addrlabel_value"
+
+	cmd="$IP2UTIL addrlabel del prefix $ipaddr label $value"
+	ocf_run $cmd # an error can be ignored
+}
+
+is_infiniband() {
+	$IP2UTIL link show $NIC | grep link/infiniband >/dev/null
+}
+
+#
+# Run send_arp to note peers about new mac address
+#
+run_send_arp() {
+	ARGS="-i $OCF_RESKEY_arp_interval -r $OCF_RESKEY_arp_count -p $SENDARPPIDFILE $NIC $OCF_RESKEY_ip auto not_used not_used"
+	if [ "x$IP_CIP" = "xyes" ] ; then
+	    if [ x = "x$IF_MAC" ] ; then
+		MY_MAC=auto
+	    else
+		MY_MAC=`echo ${IF_MAC} | sed -e 's/://g'`
+	    fi
+	    ARGS="-i $OCF_RESKEY_arp_interval -r $OCF_RESKEY_arp_count -p $SENDARPPIDFILE $NIC $OCF_RESKEY_ip $MY_MAC not_used not_used"
+	fi
+	ocf_log info "$SENDARP $ARGS"
+	if ocf_is_true $OCF_RESKEY_arp_bg; then
+		($SENDARP $ARGS || ocf_log err "Could not send gratuitous arps")& >&2
+	else
+		$SENDARP $ARGS || ocf_log err "Could not send gratuitous arps"
+	fi
+}
+
+#
+# Run send_ua to note send ICMPv6 Unsolicited Neighbor Advertisements.
+#
+run_send_ua() {
+	local i
+	# Wait until the allocated IPv6 address gets ready by checking
+	# "tentative" flag is disappeared, otherwise send_ua can not
+	# send the unsolicited advertisement requests.
+	for i in 1 2 3 4 5; do
+		$IP2UTIL -o -f $FAMILY addr show dev $NIC \
+			| grep -q -e "$OCF_RESKEY_ip/$NETMASK .* tentative"
+		[ $? -ne 0 ] && break
+		if [ $i -eq 5 ]; then
+			ocf_log warn "$OCF_RESKEY_ip still has 'tentative' status. (ignored)"
+			break
+		fi
+		sleep 1
+	done
+	ARGS="-i $OCF_RESKEY_arp_interval -c $OCF_RESKEY_arp_count $OCF_RESKEY_ip $NETMASK $NIC"
+	ocf_log info "$SENDUA $ARGS"
+	$SENDUA $ARGS || ocf_log err "Could not send ICMPv6 Unsolicited Neighbor Advertisements."
+}
+
+#
+# Run ipoibarping to note peers about new Infiniband address
+#
+run_send_ib_arp() {
+	ARGS="-q -c $OCF_RESKEY_arp_count -U -I $NIC $OCF_RESKEY_ip"
+	ocf_log info "ipoibarping $ARGS"
+	if ocf_is_true $OCF_RESKEY_arp_bg; then
+		(ipoibarping $ARGS || ocf_log err "Could not send gratuitous arps")& >&2
+	else
+		ipoibarping $ARGS || ocf_log err "Could not send gratuitous arps"
+	fi
+}
+
+# Do we already serve this IP address on the given $NIC?
+#
+# returns:
+# ok = served (for CIP: + hash bucket)
+# partial = served and no hash bucket (CIP only)
+# partial2 = served and no CIP iptables rule
+# no = nothing
+#
+ip_served() {
+	if [ -z "$NIC" ]; then # no nic found or specified
+		echo "no"
+		return 0
+	fi
+
+	cur_nic="`find_interface $OCF_RESKEY_ip $NETMASK`"
+
+	if [ -z "$cur_nic" ]; then
+		echo "no"
+		return 0
+	fi
+
+	if [ -z "$IP_CIP" ]; then
+		for i in $cur_nic; do
+			# only mark as served when on the same interfaces as $NIC
+			[ "$i" = "$NIC" ] || continue
+			echo "ok"
+			return 0
+		done
+		# There used to be logic here to pretend "not served",
+		# if ${OCF_RESKEY_lvs_support} was enabled, and the IP was
+		# found active on "lo*" only.  With lvs_support on, you should
+		# have NIC != lo, so thats already filtered
+		# by the continue above.
+
+		echo "no"
+		return 0
+	fi
+
+	# Special handling for the CIP:
+	if [ ! -e $IP_CIP_FILE ]; then
+		echo "partial2"
+		return 0
+	fi
+	if egrep -q "(^|,)${IP_INC_NO}(,|$)" $IP_CIP_FILE ; then
+		echo "ok"
+		return 0
+	else
+		echo "partial"
+		return 0
+	fi
+
+	exit $OCF_ERR_GENERIC
+}
+
+#######################################################################
+
+ip_usage() {
+	cat <<END
+usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+ip_start() {
+	if [ -z "$NIC" ]; then # no nic found or specified
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	if [ -n "$IP_CIP" ]; then
+	    # Cluster IPs need special processing when the first bucket
+	    #  is added to the node... take a lock to make sure only one
+	    #  process executes that code
+	    ocf_take_lock $CIP_lockfile
+	    ocf_release_lock_on_exit $CIP_lockfile
+	fi
+
+	#
+	#	Do we already service this IP address on $NIC?
+	#
+	local ip_status=`ip_served`
+
+	if [ "$ip_status" = "ok" ]; then
+		exit $OCF_SUCCESS
+	fi
+	
+	if [ -n "$IP_CIP" ] && [ $ip_status = "no" ] || [ $ip_status = "partial2" ]; then
+		$MODPROBE ip_conntrack
+		$IPTABLES -I INPUT -d $OCF_RESKEY_ip -i $NIC -j CLUSTERIP \
+				--new \
+				--clustermac $IF_MAC \
+				--total-nodes $IP_INC_GLOBAL \
+				--local-node $IP_INC_NO \
+				--hashmode $IP_CIP_HASH
+		if [ $? -ne 0 ]; then
+			ocf_log err "iptables failed"
+			exit $OCF_ERR_GENERIC
+		fi
+	fi
+
+	if [ -n "$IP_CIP" ] && [ $ip_status = "partial" ]; then
+		echo "+$IP_INC_NO" >$IP_CIP_FILE
+	fi
+	
+	if [ "$ip_status" = "no" ]; then
+		if ocf_is_true ${OCF_RESKEY_lvs_support}; then
+			for i in `find_interface $OCF_RESKEY_ip 32`; do
+				case $i in
+				lo*)
+					remove_conflicting_loopback $OCF_RESKEY_ip 32 255.255.255.255 lo
+					;;
+				esac
+			done
+		fi
+		
+		add_interface $OCF_RESKEY_ip $NETMASK ${BRDCAST:-none} $NIC $IFLABEL
+		
+		if [ $? -ne 0 ]; then
+			ocf_log err "$CMD failed."
+			exit $OCF_ERR_GENERIC
+		fi
+	fi
+
+	case $NIC in
+	lo*)
+		: no need to run send_arp on loopback
+		;;
+	*)
+		if [ $FAMILY = "inet" ];then
+		    $ARP_SEND_FUN
+		else
+		    if [ -x $SENDUA ]; then
+			run_send_ua
+		    fi
+		fi
+		;;
+	esac
+	exit $OCF_SUCCESS
+}
+
+ip_stop() {
+	local ip_del_if="yes"
+	if [ -n "$IP_CIP" ]; then
+	    # Cluster IPs need special processing when the last bucket
+	    #  is removed from the node... take a lock to make sure only one
+	    #  process executes that code
+	    ocf_take_lock $CIP_lockfile
+	    ocf_release_lock_on_exit $CIP_lockfile
+	fi
+	
+	if [ -f "$SENDARPPIDFILE" ] ; then
+		kill `cat "$SENDARPPIDFILE"`
+		if [ $? -ne 0 ]; then
+			ocf_log warn "Could not kill previously running send_arp for $OCF_RESKEY_ip"
+		else
+			ocf_log info "killed previously running send_arp for $OCF_RESKEY_ip"
+			rm -f "$SENDARPPIDFILE"
+		fi
+	fi
+	local ip_status=`ip_served`
+	ocf_log info "IP status = $ip_status, IP_CIP=$IP_CIP"
+
+	if [ $ip_status = "no" ]; then
+		: Requested interface not in use
+		exit $OCF_SUCCESS
+	fi
+
+	if [ -n "$IP_CIP" ] && [ $ip_status != "partial2" ]; then
+		if [ $ip_status = "partial" ]; then
+			exit $OCF_SUCCESS
+		fi
+		echo "-$IP_INC_NO" >$IP_CIP_FILE
+		if [ "x$(cat $IP_CIP_FILE)" = "x" ]; then
+			ocf_log info $OCF_RESKEY_ip, $IP_CIP_HASH
+			i=1
+			while [ $i -le $IP_INC_GLOBAL ]; do
+				ocf_log info $i
+				$IPTABLES -D INPUT -d $OCF_RESKEY_ip -i $NIC -j CLUSTERIP \
+					--new \
+					--clustermac $IF_MAC \
+					--total-nodes $IP_INC_GLOBAL \
+					--local-node $i \
+					--hashmode $IP_CIP_HASH
+				i=`expr $i + 1`
+			done
+		else
+			ip_del_if="no"		
+		fi
+	fi
+	
+	if [ "$ip_del_if" = "yes" ]; then
+		delete_interface $OCF_RESKEY_ip $NIC $NETMASK
+		if [ $? -ne 0 ]; then
+			exit $OCF_ERR_GENERIC
+		fi
+	
+		if ocf_is_true ${OCF_RESKEY_lvs_support}; then
+			restore_loopback "$OCF_RESKEY_ip"
+		fi
+	fi
+
+	exit $OCF_SUCCESS
+}
+
+ip_monitor() {
+	# TODO: Implement more elaborate monitoring like checking for
+	# interface health maybe via a daemon like FailSafe etc...
+
+	local ip_status=`ip_served`
+	case $ip_status in
+	ok)
+		return $OCF_SUCCESS
+		;;
+	partial|no|partial2)
+		exit $OCF_NOT_RUNNING
+		;;
+	*)
+		# Errors on this interface?
+		return $OCF_ERR_GENERIC
+		;;
+	esac
+}
+
+# make sure that we have something to send ARPs with
+set_send_arp_program() {
+    ARP_SEND_FUN=run_send_arp
+    if [ -n "$OCF_RESKEY_arp_sender" ]; then
+	case "$OCF_RESKEY_arp_sender" in
+	send_arp)
+	    check_binary $SENDARP
+	;;
+	ipoibarping)
+	    check_binary ipoibarping
+	    ARP_SEND_FUN=run_send_ib_arp
+	;;
+	*)
+	    ocf_log err "unrecognized arp_sender value: $OCF_RESKEY_arp_sender"
+	    exit $OCF_ERR_CONFIGURED
+	;;
+	esac
+    else
+	if is_infiniband; then
+	    ARP_SEND_FUN=run_send_ib_arp
+	    if ! have_binary ipoibarping; then
+	    	[ "$__OCF_ACTION" = start ] &&
+		    ocf_log warn "using send_arp for infiniband because ipoibarping is not available (set arp_sender to \"send_arp\" to suppress this message)"
+		check_binary $SENDARP
+		ARP_SEND_FUN=run_send_arp
+	    fi
+	fi
+    fi
+}
+
+ip_validate() {
+    check_binary $IP2UTIL
+    IP_CIP=
+
+    ip_init
+
+    set_send_arp_program
+
+    if [ -n "$IP_CIP" ]; then
+	check_binary $IPTABLES
+	check_binary $MODPROBE
+    fi
+
+# $BASEIP, $NETMASK, $NIC , $IP_INC_GLOBAL, and $BRDCAST have been checked within ip_init,
+# do not bother here.
+
+    if ocf_is_true "$OCF_RESKEY_unique_clone_address" &&
+	    ! ocf_is_true "$OCF_RESKEY_CRM_meta_globally_unique"; then
+	ocf_log err "unique_clone_address makes sense only with meta globally_unique set"
+	exit $OCF_ERR_CONFIGURED
+    fi
+
+    if ocf_is_decimal "$OCF_RESKEY_arp_interval" && [ $OCF_RESKEY_arp_interval -gt 0 ]; then
+	:
+    else
+	ocf_log err "Invalid OCF_RESKEY_arp_interval [$OCF_RESKEY_arp_interval]"
+	exit $OCF_ERR_CONFIGURED
+    fi
+
+    if ocf_is_decimal "$OCF_RESKEY_arp_count" && [ $OCF_RESKEY_arp_count -gt 0 ]; then
+	:
+    else
+	ocf_log err "Invalid OCF_RESKEY_arp_count [$OCF_RESKEY_arp_count]"
+	exit $OCF_ERR_CONFIGURED
+    fi
+
+    if [ -n "$IP_CIP" ]; then
+
+	local valid=1
+
+	case $IP_CIP_HASH in
+	sourceip|sourceip-sourceport|sourceip-sourceport-destport)
+		;;
+	*)
+		ocf_log err "Invalid OCF_RESKEY_clusterip_hash [$IP_CIP_HASH]"
+		exit $OCF_ERR_CONFIGURED
+		;;
+	esac
+
+	if ocf_is_true ${OCF_RESKEY_lvs_support}; then
+		ecf_log err "LVS and load sharing not advised to try"
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	case $IF_MAC in
+	[0-9a-zA-Z][13579bBdDfF][!0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][!0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][!0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][!0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][!0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z])
+		;;
+	*)
+		valid=0
+		;;
+	esac
+
+	if [ $valid -eq 0 ]; then
+	  ocf_log err "Invalid IF_MAC [$IF_MAC]"
+	  exit $OCF_ERR_CONFIGURED
+	fi
+
+    fi
+}
+
+if ocf_is_true "$OCF_RESKEY_unique_clone_address"; then
+    prefix=`echo $OCF_RESKEY_ip | awk -F. '{print $1"."$2"."$3}'`
+    suffix=`echo $OCF_RESKEY_ip | awk -F. '{print $4}'`
+    suffix=`expr ${OCF_RESKEY_CRM_meta_clone:-0} + $suffix`
+    OCF_RESKEY_ip="$prefix.$suffix"
+fi
+
+case $__OCF_ACTION in
+meta-data)	meta_data
+		;;
+usage|help)	ip_usage
+		exit $OCF_SUCCESS
+		;;
+esac
+
+ip_validate
+
+case $__OCF_ACTION in
+start)		ip_start
+		;;
+stop)		ip_stop
+		;;
+status)		ip_status=`ip_served`
+		if [ $ip_status = "ok" ]; then
+			echo "running"
+			exit $OCF_SUCCESS
+		else
+			echo "stopped"
+			exit $OCF_NOT_RUNNING
+		fi
+		;;
+monitor)	ip_monitor
+		;;
+validate-all)	;;
+*)		ip_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+# vi:sw=4:ts=8:
diff --git a/heartbeat/IPsrcaddr b/heartbeat/IPsrcaddr
new file mode 100755
index 0000000..e8c0f77
--- /dev/null
+++ b/heartbeat/IPsrcaddr
@@ -0,0 +1,486 @@
+#!/bin/sh
+#
+#	Description:	IPsrcaddr - Preferred source address modification
+#
+#	Author:			John Sutton <john at scl.co.uk>
+#	Support:		linux-ha at lists.linux-ha.org
+#	License:		GNU General Public License (GPL)
+#	Copyright:		SCL Internet
+#
+#	Based on the IPaddr script.
+#
+#	This script manages the preferred source address associated with
+#	packets which originate on the localhost and are routed through the
+#	default route.  By default, i.e. without the use of this script or
+#	similar, these packets will carry the IP of the primary i.e. the
+#	non-aliased interface.  This can be a nuisance if you need to ensure
+#	that such packets carry the same IP irrespective of which host in
+#	a redundant cluster they actually originate from.
+#
+#	It can add a preferred source address, or remove one.
+#
+#	usage: IPsrcaddr {start|stop|status|monitor|validate-all|meta-data}
+#
+#	The "start" arg adds a preferred source address.
+#
+#	Surprisingly, the "stop" arg removes it.	:-)
+#
+#	NOTES:
+#
+#	1) There must be one and not more than 1 default route!  Mainly because
+#	I can't see why you should have more than one.  And if there is more
+#	than one, we would have to box clever to find out which one is to be
+#	modified, or we would have to pass its identity as an argument.
+#
+#	2) The script depends on Alexey Kuznetsov's ip utility from the
+#	iproute aka iproute2 package.
+#
+#	3) No checking is done to see if the passed in IP address can
+#	reasonably be associated with the interface on which the default
+#	route exists.  So unless you want to deliberately spoof your source IP,
+#	check it!  Normally, I would expect that your haresources looks
+#	something like:
+#
+#		nodename ip1 ip2 ... ipN IPsrcaddr::ipX
+#
+#	where ipX is one of the ip1 to ipN.
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_ipaddress
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}";
+
+  CMDSHOW="$IP2UTIL route show   to exact 0.0.0.0/0"
+CMDCHANGE="$IP2UTIL route change to "
+
+SYSTYPE="`uname -s`"
+
+usage() {
+	echo $USAGE >&2
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="IPsrcaddr">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for IPsrcaddr. It manages the preferred source address
+modification. 
+</longdesc>
+<shortdesc lang="en">Manages the preferred source address for outgoing IP packets</shortdesc>
+
+<parameters>
+<parameter name="ipaddress" unique="0" required="1">
+<longdesc lang="en">
+The IP address. 
+</longdesc>
+<shortdesc lang="en">IP address</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="cidr_netmask">
+<longdesc lang="en">
+The netmask for the interface in CIDR format. (ie, 24), or in
+dotted quad notation  255.255.255.0).
+</longdesc>
+<shortdesc lang="en">Netmask</shortdesc>
+<content type="string" default=""/>
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="20s" />
+<action name="stop" timeout="20s" />
+<action name="monitor" depth="0" timeout="20s" interval="10" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+errorexit() {
+	ocf_log err "$*"
+	exit $OCF_ERR_GENERIC
+}
+
+#
+#	We can distinguish 3 cases: no preferred source address, a
+#	preferred source address exists which matches that specified, and one
+#	exists but doesn't match that specified.  srca_read() returns 1,0,2
+#	respectively.
+#
+#	The output of route show is something along the lines of:
+#
+#		default via X.X.X.X dev eth1 src Y.Y.Y.Y
+#
+#	where the src clause "src Y.Y.Y.Y" may or may not be present
+
+WS="[`echo -en ' \t'`]"
+OCTET="[0-9]\{1,3\}"
+IPADDR="\($OCTET\.\)\{3\}$OCTET"
+SRCCLAUSE="src$WS$WS*\($IPADDR\)"
+MATCHROUTE="\(.*${WS}\)\($SRCCLAUSE\)\($WS.*\|$\)"
+FINDIF=$HA_BIN/findif
+
+# findif needs that to be set
+export OCF_RESKEY_ip=$OCF_RESKEY_ipaddress
+
+srca_read() {
+	# Capture the default route - doublequotes prevent word splitting...
+	DEFROUTE="`$CMDSHOW`" || errorexit "command '$CMDSHOW' failed"
+
+	# ... so we can make sure there is only 1 default route
+	[ 1 -eq `echo "$DEFROUTE" | wc -l` ] || \
+		errorexit "more than 1 default route exists"
+
+	# But there might still be no default route
+	[ -z "$DEFROUTE" ] && errorexit "no default route exists"
+
+	# Sed out the source ip address if it exists
+	SRCIP=`echo $DEFROUTE | sed -n "s/$MATCHROUTE/\3/p"`
+
+	# and what remains after stripping out the source ip address clause
+	ROUTE_WO_SRC=`echo $DEFROUTE | sed "s/$MATCHROUTE/\1\5/"`
+
+	[ -z "$SRCIP" ] && return 1
+	[ $SRCIP = $1 ] && return 0
+	return 2
+}
+
+#
+#	Add (or change if it already exists) the preferred source address
+#	The exit code should conform to LSB exit codes.
+#
+
+srca_start() {
+	srca_read $1
+
+	rc=$?
+	if [ $rc = 0 ]; then 
+		rc=$OCF_SUCCESS
+		ocf_log info "The ip route has been already set.($NETWORK, $INTERFACE, $ROUTE_WO_SRC)"
+	else
+		ip route replace $NETWORK dev $INTERFACE src $1 || \
+			errorexit "command 'ip route replace $NETWORK dev $INTERFACE src $1' failed"
+
+		$CMDCHANGE $ROUTE_WO_SRC src $1 || \
+			errorexit "command '$CMDCHANGE $ROUTE_WO_SRC src $1' failed"
+		rc=$?
+	fi
+
+	return $rc
+}
+
+#
+#	Remove (if it exists) the preferred source address.
+#	If one exists but it's not the same as the one specified, that's
+#	an error.  Maybe that's the wrong behaviour because if this fails
+#	then when IPaddr releases the associated interface (if there is one)
+#	your default route will also get dropped ;-(
+#	The exit code should conform to LSB exit codes.
+#
+
+srca_stop() {
+	srca_read $1
+	rc=$?
+
+	if [ $rc = 1 ]; then
+	# We do not have a preferred source address for now
+	  ocf_log info "No preferred source address defined, nothing to stop"
+	  exit $OCF_SUCCESS
+	fi
+	  
+	[ $rc = 2 ] && errorexit "The address you specified to stop does not match the preferred source address"
+
+	ip route replace $NETWORK dev $INTERFACE || \
+		errorexit "command 'ip route replace $NETWORK dev $INTERFACE' failed"
+
+	$CMDCHANGE $ROUTE_WO_SRC || \
+		errorexit "command '$CMDCHANGE $ROUTE_WO_SRC' failed"
+
+	return $?
+}
+
+srca_status() {
+	srca_read $1
+
+	case $? in
+		0)	echo "OK"
+			return $OCF_SUCCESS;;
+
+		1)	echo "No preferred source address defined"
+			return $OCF_NOT_RUNNING;;
+
+		2)	echo "Preferred source address has incorrect value"
+			return $OCF_ERR_GENERIC;;
+	esac
+}
+
+# A not reliable IP address checking function, which only picks up those _obvious_ violations...
+#
+# It accepts IPv4 address in dotted quad notation, for example "192.168.1.1"
+#
+# 100% confidence whenever it reports "negative", 
+# but may get false "positive" answer. 
+# 
+CheckIP() {
+  ip="$1"
+  case $ip in
+    *[!0-9.]*) #got invalid char
+	false;;
+    .*|*.) #begin or end by ".", which is invalid
+	false;;
+    *..*) #consecutive ".", which is invalid
+	false;;
+    *.*.*.*.*) #four decimal dots, which is too many
+	false;;
+    *.*.*.*) #exactly three decimal dots, candidate, evaluate each field
+	local IFS=.
+	set -- $ip
+	if
+	    ( [ $1 -le 254 ] && [ $2 -le 254 ] && [ $3 -le 254 ] && [ $4 -le 254 ] )
+	then
+	    if [ $1 -eq 127 ]; then
+		ocf_log err "IP address [$ip] is a loopback address, thus can not be preferred source address"
+		exit $OCF_ERR_CONFIGURED
+	    fi
+	else
+	    true
+	fi	   
+	;;
+    *) #less than three decimal dots
+	false;;
+  esac
+  return $? # This return is unnecessary, this comment too :)
+}
+
+#
+#       Find out which interface or alias serves the given IP address
+#       The argument is an IP address, and its output
+#       is an (aliased) interface name (e.g., "eth0" and "eth0:0").
+#
+find_interface_solaris() {
+
+
+  $IFCONFIG $IFCONFIG_A_OPT | $AWK '{if ($0 ~ /.*: / && NR > 1) {print "\n"$0} else {print}}' |
+  while read ifname linkstuff
+  do
+    : ifname = $ifname
+    read inet addr junk
+    : inet = $inet addr = $addr
+    while
+      read line && [ "X$line" != "X" ]
+    do
+      : Nothing
+    done
+
+    #  This doesn't look right for a box with multiple NICs.
+    #  It looks like it always selects the first interface on
+    #  a machine.  Yet, we appear to use the results for this case too...
+    ifname=`echo "$ifname" | sed s'%:*$%%'`
+
+    case $addr in
+      addr:$BASEIP)	echo $ifname; return $OCF_SUCCESS;;
+      $BASEIP)	echo $ifname; return $OCF_SUCCESS;;
+    esac
+  done
+  return $OCF_ERR_GENERIC
+}
+
+
+#
+#       Find out which interface or alias serves the given IP address
+#       The argument is an IP address, and its output
+#       is an (aliased) interface name (e.g., "eth0" and "eth0:0").
+#
+find_interface_generic() {
+
+	local iface=`$IP2UTIL -o -f inet addr show | grep "\ $BASEIP" \
+            | cut -d ' ' -f2 | grep -v '^ipsec[0-9][0-9]*$'`
+        if [ -z "$iface" ]; then
+            return $OCF_ERR_GENERIC
+        else 
+            echo $iface
+            return $OCF_SUCCESS
+        fi
+}
+
+
+#
+#       Find out which interface or alias serves the given IP address
+#       The argument is an IP address, and its output
+#       is an (aliased) interface name (e.g., "eth0" and "eth0:0").
+#
+find_interface() {
+    case "$SYSTYPE" in
+	SunOS)
+	 	IF=`find_interface_solaris $BASEIP`
+        ;;
+      *)
+	 	IF=`find_interface_generic $BASEIP`
+       ;;
+       esac
+
+  echo $IF
+  return $OCF_SUCCESS;
+}
+
+
+ip_status() {
+
+  BASEIP="$1"
+  case "$SYSTYPE" in
+    Darwin)
+	# Treat Darwin the same as the other BSD variants (matched as *BSD)
+	SYSTYPE="${SYSTYPE}BSD"
+	;;
+    *)
+        ;;
+  esac
+
+
+  case "$SYSTYPE" in
+      *BSD)
+	  $IFCONFIG $IFCONFIG_A_OPT | grep "inet.*[: ]$BASEIP " >/dev/null 2>&1
+	  if [ $? = 0 ]; then
+	      return $OCF_SUCCESS
+	  else
+	      return $OCF_NOT_RUNNING
+	  fi;;
+      
+      Linux|SunOS)		
+	  IF=`find_interface "$BASEIP"`
+	  if [ -z "$IF" ]; then
+	      return $OCF_NOT_RUNNING
+	  fi
+
+	  case $IF in
+	  	lo*)  
+		    ocf_log err "IP address [$BASEIP] is served by loopback, thus can not be preferred source address"
+		    exit $OCF_ERR_CONFIGURED
+		    ;;
+		*)return $OCF_SUCCESS;;
+	  esac
+	  ;;
+	  
+      *)		
+	  if [ -z "$IF" ]; then
+	      return $OCF_NOT_RUNNING
+	  else
+	      return $OCF_SUCCESS
+	  fi;;
+  esac
+}
+
+
+srca_validate_all() {
+
+    check_binary $AWK
+    check_binary $IFCONFIG
+
+#	The IP address should be in good shape
+	if CheckIP "$ipaddress"; then
+	  : 
+	else
+	  ocf_log err "Invalid IP address [$ipaddress]"
+	  exit $OCF_ERR_CONFIGURED
+	fi
+
+	if ocf_is_probe; then
+	  return $OCF_SUCCESS
+	fi
+
+#	We should serve this IP address of course
+	if ip_status "$ipaddress"; then
+	  :
+	else
+	  ocf_log err "We are not serving [$ipaddress], hence can not make it a preferred source address"
+	  exit $OCF_ERR_INSTALLED
+	fi
+}
+
+if
+  ( [ $# -ne 1 ] )
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+# These operations do not require the OCF instance parameters to be set
+case $1 in
+	meta-data)	meta_data 
+			exit $OCF_SUCCESS
+			;;
+	usage)		usage
+			exit $OCF_SUCCESS
+			;;
+	*)	
+			;;
+esac
+
+if 
+  [ -z "$OCF_RESKEY_ipaddress" ]
+then
+#  usage
+  ocf_log err "Please set OCF_RESKEY_ipaddress to the preferred source IP address!"
+  exit $OCF_ERR_CONFIGURED
+fi
+
+ipaddress="$OCF_RESKEY_ipaddress"
+
+if [ "x$SYSTYPE" = "xLinux" ]; then
+	srca_validate_all
+fi
+
+findif_out=`$FINDIF -C`
+rc=$?
+[ $rc -ne 0 ] && {
+    ocf_log err "[$FINDIF -C] failed"
+    exit $rc
+}
+
+INTERFACE=`echo $findif_out | awk '{print $1}'`
+NETWORK=`ip route list dev $INTERFACE scope link match $ipaddress|grep -o '^[^ ]*'`
+
+case $1 in
+	start)		srca_start $ipaddress
+			;;
+	stop)		srca_stop $ipaddress
+			;;
+	status)		srca_status $ipaddress
+			;;
+	monitor)	srca_status $ipaddress
+			;;
+	validate-all)	srca_validate_all
+			;;
+	*)		usage
+			exit $OCF_ERR_UNIMPLEMENTED
+			;;
+esac
+
+exit $?
+
+#
+# Version 0.3  2002/11/04 17:00:00 John Sutton <john at scl.co.uk>
+# Name changed from IPsrcroute to IPsrcaddr and now reports errors
+# using ha_log rather than on stderr.
+#
+# Version 0.2  2002/11/02 17:00:00 John Sutton <john at scl.co.uk>
+# Changed status output to "OK" to satisfy ResourceManager's
+# we_own_resource() function.
+#
+# Version 0.1  2002/11/01 17:00:00 John Sutton <john at scl.co.uk>
+# First effort but does the job?
+#
diff --git a/heartbeat/IPv6addr.c b/heartbeat/IPv6addr.c
new file mode 100644
index 0000000..7c1d20d
--- /dev/null
+++ b/heartbeat/IPv6addr.c
@@ -0,0 +1,876 @@
+
+/*
+ * This program manages IPv6 address with OCF Resource Agent standard.
+ *
+ * Author: Huang Zhen <zhenh at cn.ibm.com>
+ * Copyright (c) 2004 International Business Machines
+ *
+ * This library 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 library 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.
+ */
+ 
+/*
+ * It can add an IPv6 address, or remove one.
+ *
+ * Usage:  IPv6addr {start|stop|status|monitor|meta-data}
+ *
+ * The "start" arg adds an IPv6 address.
+ * The "stop" arg removes one.
+ * The "status" arg shows whether the IPv6 address exists
+ * The "monitor" arg shows whether the IPv6 address can be pinged (ICMPv6 ECHO)
+ * The "meta_data" arg shows the meta data(XML)
+ */
+ 
+/*
+ * ipv6-address:
+ *
+ * currently the following forms are legal:
+ *	address
+ *	address/prefix
+ *
+ *     E.g.
+ *	3ffe:ffff:0:f101::3
+ *	3ffe:ffff:0:f101::3/64
+ *
+ * It should be passed by environment variant:
+ *	OCF_RESKEY_ipv6addr=3ffe:ffff:0:f101::3
+ *	OCF_RESKEY_cidr_netmask=64
+ *	OCF_RESKEY_nic=eth0
+ *
+ */
+ 
+/*
+ * start:
+ * 	1.IPv6addr will choice a proper interface for the new address.
+ *	2.Then assign the new address to the interface.
+ *	3.Wait until the new address is available (reply ICMPv6 ECHO packet)
+ *	4.Send out the unsolicited advertisements.
+ *
+ *	return 0(OCF_SUCCESS) for success
+ *	return 1(OCF_ERR_GENERIC) for failure
+ *	return 2(OCF_ERR_ARGS) for invalid or excess argument(s)
+ *
+ *
+ * stop:
+ *	remove the address from the inferface.
+ *
+ *	return 0(OCF_SUCCESS) for success
+ *	return 1(OCF_ERR_GENERIC) for failure
+ *	return 2(OCF_ERR_ARGS) for invalid or excess argument(s)
+ *
+ * status:
+ *	return the status of the address. only check whether it exists.
+ *
+ *	return 0(OCF_SUCCESS) for existing
+ *	return 1(OCF_NOT_RUNNING) for not existing
+ *	return 2(OCF_ERR_ARGS) for invalid or excess argument(s)
+ *
+ *
+ * monitor:
+ *	ping the address by ICMPv6 ECHO request.
+ *
+ *	return 0(OCF_SUCCESS) for response correctly.
+ *	return 1(OCF_NOT_RUNNING) for no response.
+ *	return 2(OCF_ERR_ARGS) for invalid or excess argument(s)
+ */
+
+#include <config.h>
+#include <IPv6addr.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/icmp6.h>
+#include <arpa/inet.h> /* for inet_pton */
+#include <net/if.h> /* for if_nametoindex */
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <syslog.h>
+#include <signal.h>
+#include <errno.h>
+#include <clplumbing/cl_log.h>
+
+
+#define PIDFILE_BASE HA_RSCTMPDIR  "/IPv6addr-"
+
+/*
+0	No error, action succeeded completely
+1 	generic or unspecified error (current practice)
+	The "monitor" operation shall return this for a crashed, hung or
+	otherwise non-functional resource.
+2 	invalid or excess argument(s)
+	Likely error code for validate-all, if the instance parameters
+	do not validate. Any other action is free to also return this
+	exit status code for this case.
+3 	unimplemented feature (for example, "reload")
+4 	user had insufficient privilege
+5 	program is not installed
+6 	program is not configured
+7 	program is not running
+8	resource is running in "master" mode and fully operational
+9	resource is in "master" mode but in a failed state
+*/
+#define	OCF_SUCCESS		0
+#define	OCF_ERR_GENERIC		1
+#define	OCF_ERR_ARGS		2
+#define	OCF_ERR_UNIMPLEMENTED	3
+#define	OCF_ERR_PERM		4
+#define	OCF_ERR_INSTALLED	5
+#define	OCF_ERR_CONFIGURED	6
+#define	OCF_NOT_RUNNING		7
+
+const char* APP_NAME		= "IPv6addr";
+
+const char*	START_CMD 	= "start";
+const char*	STOP_CMD  	= "stop";
+const char*	STATUS_CMD 	= "status";
+const char*	MONITOR_CMD 	= "monitor";
+const char*	ADVT_CMD	= "advt";
+const char*	RECOVER_CMD 	= "recover";
+const char*	RELOAD_CMD 	= "reload";
+const char*	META_DATA_CMD 	= "meta-data";
+const char*	VALIDATE_CMD 	= "validate-all";
+
+const int	QUERY_COUNT	= 5;
+
+struct in6_ifreq {
+	struct in6_addr ifr6_addr;
+	uint32_t ifr6_prefixlen;
+	unsigned int ifr6_ifindex;
+};
+
+static int start_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname);
+static int stop_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname);
+static int status_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname);
+static int monitor_addr6(struct in6_addr* addr6, int prefix_len);
+static int advt_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname);
+static int meta_data_addr6(void);
+
+
+static void usage(const char* self);
+int write_pid_file(const char *pid_file);
+int create_pid_directory(const char *pid_file);
+static void byebye(int nsig);
+
+static char* scan_if(struct in6_addr* addr_target, int* plen_target,
+		     int use_mask, char* prov_ifname);
+static char* find_if(struct in6_addr* addr_target, int* plen_target, char* prov_ifname);
+static char* get_if(struct in6_addr* addr_target, int* plen_target, char* prov_ifname);
+static int assign_addr6(struct in6_addr* addr6, int prefix_len, char* if_name);
+static int unassign_addr6(struct in6_addr* addr6, int prefix_len, char* if_name);
+int is_addr6_available(struct in6_addr* addr6);
+
+int
+main(int argc, char* argv[])
+{
+	char		pid_file[256];
+	char*		ipv6addr;
+	char*		cidr_netmask;
+	int		ret;
+	char*		cp;
+	char*		prov_ifname = NULL;
+	int		prefix_len = -1;
+	struct in6_addr	addr6;
+
+	/* Check the count of parameters first */
+	if (argc < 2) {
+		usage(argv[0]);
+		return OCF_ERR_ARGS;
+	}
+
+	/* set termination signal */
+	siginterrupt(SIGTERM, 1);
+	signal(SIGTERM, byebye);
+
+	/* open system log */
+	cl_log_set_entity(APP_NAME);
+	cl_log_set_facility(LOG_DAEMON);
+
+	/* the meta-data dont need any parameter */
+	if (0 == strncmp(META_DATA_CMD, argv[1], strlen(META_DATA_CMD))) {
+		ret = meta_data_addr6();
+		return OCF_SUCCESS;
+	}
+
+	/* check the OCF_RESKEY_ipv6addr parameter, should be an IPv6 address */
+	ipv6addr = getenv("OCF_RESKEY_ipv6addr");
+
+	if (ipv6addr == NULL) {
+		cl_log(LOG_ERR, "Please set OCF_RESKEY_ipv6addr to the IPv6 address you want to manage.");
+		usage(argv[0]);
+		return OCF_ERR_ARGS;
+	}
+
+	/* legacy option */
+	if ((cp = strchr(ipv6addr, '/'))) {
+		prefix_len = atol(cp + 1);
+		if ((prefix_len < 0) || (prefix_len > 128)) {
+			cl_log(LOG_ERR, "Invalid prefix_len [%s], should be an integer in [0, 128]", cp+1);
+			usage(argv[0]);
+			return OCF_ERR_ARGS;
+		}
+		*cp=0;
+	}
+
+	/* get provided netmask (optional) */
+	cidr_netmask = getenv("OCF_RESKEY_cidr_netmask");
+
+	if (cidr_netmask != NULL) {
+		if ((atol(cidr_netmask) < 0) || (atol(cidr_netmask) > 128)) {
+			cl_log(LOG_ERR, "Invalid prefix_len [%s], "
+				"should be an integer in [0, 128]", cidr_netmask);
+			usage(argv[0]);
+			return OCF_ERR_ARGS;
+		}
+		if (prefix_len != -1 && prefix_len != atol(cidr_netmask)) {
+			cl_log(LOG_DEBUG, "prefix_len(%d) is overwritted by cidr_netmask(%s)",
+				prefix_len, cidr_netmask);
+		}
+		prefix_len = atol(cidr_netmask);
+
+	} else if (prefix_len == -1) {
+		prefix_len = 0;
+	}
+
+	/* get provided interface name (optional) */
+	prov_ifname = getenv("OCF_RESKEY_nic");
+
+	if (inet_pton(AF_INET6, ipv6addr, &addr6) <= 0) {
+		cl_log(LOG_ERR, "Invalid IPv6 address [%s]", ipv6addr);
+		usage(argv[0]);
+		return OCF_ERR_ARGS;
+	}
+
+	/* Check whether this system supports IPv6 */
+	if (access(IF_INET6, R_OK)) {
+		cl_log(LOG_ERR, "No support for INET6 on this system.");
+		return OCF_ERR_GENERIC;
+	}
+
+	/* create the pid file so we can make sure that only one IPv6addr
+	 * for this address is running
+	 */
+	if (snprintf(pid_file, sizeof(pid_file), "%s%s", PIDFILE_BASE, ipv6addr)
+		>= (int)sizeof(pid_file)) {
+		cl_log(LOG_ERR, "Pid file truncated");
+		return OCF_ERR_GENERIC;
+	}
+
+	if (write_pid_file(pid_file) < 0) {
+		return OCF_ERR_GENERIC;
+	}
+
+
+	/* switch the command */
+	if (0 == strncmp(START_CMD,argv[1], strlen(START_CMD))) {
+		ret = start_addr6(&addr6, prefix_len, prov_ifname);
+	}else if (0 == strncmp(STOP_CMD,argv[1], strlen(STOP_CMD))) {
+		ret = stop_addr6(&addr6, prefix_len, prov_ifname);
+	}else if (0 == strncmp(STATUS_CMD,argv[1], strlen(STATUS_CMD))) {
+		ret = status_addr6(&addr6, prefix_len, prov_ifname);
+	}else if (0 ==strncmp(MONITOR_CMD,argv[1], strlen(MONITOR_CMD))) {
+		ret = monitor_addr6(&addr6, prefix_len);
+	}else if (0 ==strncmp(RELOAD_CMD,argv[1], strlen(RELOAD_CMD))) {
+		ret = OCF_ERR_UNIMPLEMENTED;
+	}else if (0 ==strncmp(RECOVER_CMD,argv[1], strlen(RECOVER_CMD))) {
+		ret = OCF_ERR_UNIMPLEMENTED;
+	}else if (0 ==strncmp(VALIDATE_CMD,argv[1], strlen(VALIDATE_CMD))) {
+	/* ipv6addr has been validated by inet_pton, hence a valid IPv6 address */
+		ret = OCF_SUCCESS;
+	}else if (0 ==strncmp(ADVT_CMD,argv[1], strlen(MONITOR_CMD))) {
+		ret = advt_addr6(&addr6, prefix_len, prov_ifname);
+	}else{
+		usage(argv[0]);
+		ret = OCF_ERR_ARGS;
+	}
+
+	/* release the pid file */
+	unlink(pid_file);
+
+	return ret;
+}
+int
+start_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname)
+{
+	int	i;
+	char*	if_name;
+	if(OCF_SUCCESS == status_addr6(addr6,prefix_len,prov_ifname)) {
+		return OCF_SUCCESS;
+	}
+
+	/* we need to find a proper device to assign the address */
+	if_name = find_if(addr6, &prefix_len, prov_ifname);
+	if (NULL == if_name) {
+		cl_log(LOG_ERR, "no valid mechanisms");
+		return OCF_ERR_GENERIC;
+	}
+
+	/* Assign the address */
+	if (0 != assign_addr6(addr6, prefix_len, if_name)) {
+		cl_log(LOG_ERR, "failed to assign the address to %s", if_name);
+		return OCF_ERR_GENERIC;
+	}
+
+	/* Check whether the address available */
+	for (i = 0; i < QUERY_COUNT; i++) {
+		if (0 == is_addr6_available(addr6)) {
+			break;
+		}
+		sleep(1);
+	}
+	if (i == QUERY_COUNT) {
+		cl_log(LOG_ERR, "failed to ping the address");
+		return OCF_ERR_GENERIC;
+	}
+
+	/* Send unsolicited advertisement packet to neighbor */
+	for (i = 0; i < UA_REPEAT_COUNT; i++) {
+		send_ua(addr6, if_name);
+		sleep(1);
+	}
+	return OCF_SUCCESS;
+}
+
+int
+advt_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname)
+{
+	/* First, we need to find a proper device to assign the address */
+	char*	if_name = get_if(addr6, &prefix_len, prov_ifname);
+	int	i;
+	if (NULL == if_name) {
+		cl_log(LOG_ERR, "no valid mechanisms");
+		return OCF_ERR_GENERIC;
+	}
+	/* Send unsolicited advertisement packet to neighbor */
+	for (i = 0; i < UA_REPEAT_COUNT; i++) {
+		send_ua(addr6, if_name);
+		sleep(1);
+	}
+	return OCF_SUCCESS;
+}
+
+int
+stop_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname)
+{
+	char* if_name;
+	if(OCF_NOT_RUNNING == status_addr6(addr6,prefix_len,prov_ifname)) {
+		return OCF_SUCCESS;
+	}
+
+	if_name = get_if(addr6, &prefix_len, prov_ifname);
+
+	if (NULL == if_name) {
+		cl_log(LOG_ERR, "no valid mechanisms.");
+		/* I think this should be a success exit according to LSB. */
+		return OCF_ERR_GENERIC;
+	}
+
+	/* Unassign the address */
+	if (0 != unassign_addr6(addr6, prefix_len, if_name)) {
+		cl_log(LOG_ERR, "failed to assign the address to %s", if_name);
+		return OCF_ERR_GENERIC;
+	}
+
+	return OCF_SUCCESS;
+}
+
+int
+status_addr6(struct in6_addr* addr6, int prefix_len, char* prov_ifname)
+{
+	char* if_name = get_if(addr6, &prefix_len, prov_ifname);
+	if (NULL == if_name) {
+		return OCF_NOT_RUNNING;
+	}
+	return OCF_SUCCESS;
+}
+
+int
+monitor_addr6(struct in6_addr* addr6, int prefix_len)
+{
+	if(0 == is_addr6_available(addr6)) {
+		return OCF_SUCCESS;
+	}
+	return OCF_NOT_RUNNING;
+}
+
+/* find the network interface associated with an address */
+char*
+scan_if(struct in6_addr* addr_target, int* plen_target, int use_mask, char* prov_ifname)
+{
+	FILE *f;
+	static char devname[21]="";
+	struct in6_addr addr;
+	struct in6_addr mask;
+	unsigned int plen, scope, dad_status, if_idx;
+	unsigned int addr6p[4];
+
+	/* open /proc/net/if_inet6 file */
+	if ((f = fopen(IF_INET6, "r")) == NULL) {
+		return NULL;
+	}
+
+	/* Loop for each entry */
+	while (1) {
+		int		i;
+		int		n;
+		int		s;
+		gboolean	same = TRUE;
+
+		i = fscanf(f, "%08x%08x%08x%08x %x %02x %02x %02x %20s\n",
+		       	   &addr6p[0], &addr6p[1], &addr6p[2], &addr6p[3],
+			   &if_idx, &plen, &scope, &dad_status, devname);
+		if (i == EOF) {
+			break;
+		}
+		else if (i != 9) {
+			cl_log(LOG_INFO, "Error parsing %s, "
+			       "perhaps the format has changed\n", IF_INET6);
+			break;
+		}
+
+		/* Consider link-local addresses (scope == 0x20) only when
+		 * the inerface name is provided, and global addresses
+		 * (scope == 0). Skip everything else.
+		 */
+		if (scope != 0) {
+			if (scope != 0x20 || prov_ifname == 0
+				|| *prov_ifname == 0)
+				continue;
+		}
+
+		/* If specified prefix, only same prefix entry
+		 * would be considered.
+		 */
+		if (*plen_target!=0 && plen != *plen_target) {
+			continue;
+		}
+
+		/* If interface name provided, only same devname entry
+		 * would be considered
+		 */
+		if (prov_ifname!=0 && *prov_ifname!=0)
+		{
+			if (strcmp(devname, prov_ifname))
+				continue;
+		}
+
+		for (i = 0; i< 4; i++) {
+			addr.s6_addr32[i] = htonl(addr6p[i]);
+		}
+
+		/* Make the mask based on prefix length */
+		memset(mask.s6_addr, 0xff, 16);
+		if (use_mask && plen < 128) {
+			n = plen / 32;
+			memset(mask.s6_addr32 + n + 1, 0, (3 - n) * 4);
+			s = 32 - plen % 32;
+			if (s == 32) 
+				mask.s6_addr32[n] = 0x0;
+			else
+				mask.s6_addr32[n] = 0xffffffff << s;
+			mask.s6_addr32[n] = htonl(mask.s6_addr32[n]);
+		}
+
+		/* compare addr and addr_target */
+		same = TRUE;
+		for (i = 0; i < 4; i++) {
+			if ((addr.s6_addr32[i]&mask.s6_addr32[i]) !=
+			    (addr_target->s6_addr32[i]&mask.s6_addr32[i])) {
+				same = FALSE;
+				break;
+			}
+		}
+		
+		/* We found it!	*/
+		if (same) {
+			fclose(f);
+			*plen_target = plen;
+			return devname;
+		}
+	}
+	fclose(f);
+	return NULL;
+}
+/* find a proper network interface to assign the address */
+char*
+find_if(struct in6_addr* addr_target, int* plen_target, char* prov_ifname)
+{
+	char *best_ifname = scan_if(addr_target, plen_target, 1, prov_ifname);
+
+	/* use the provided ifname and prefix if the address did not match */
+	if (best_ifname == NULL &&
+	    prov_ifname != 0 &&  *prov_ifname != 0 && *plen_target != 0) {
+		cl_log(LOG_INFO, "Could not find a proper interface by the ipv6addr. Using the specified nic:'%s' and cidr_netmask:'%d'", prov_ifname, *plen_target);
+		return prov_ifname;
+	}
+	return best_ifname;
+}
+/* get the device name and the plen_target of a special address */
+char*
+get_if(struct in6_addr* addr_target, int* plen_target, char* prov_ifname)
+{
+	return scan_if(addr_target, plen_target, 0, prov_ifname);
+}
+int
+assign_addr6(struct in6_addr* addr6, int prefix_len, char* if_name)
+{
+	struct in6_ifreq ifr6;
+
+	/* Get socket first */
+	int		fd;
+	struct ifreq	ifr;
+
+	fd = socket(AF_INET6, SOCK_DGRAM, 0);
+	if (fd < 0) {
+		return 1;
+	}
+
+	/* Query the index of the if */
+	strcpy(ifr.ifr_name, if_name);
+	if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
+		return -1;
+	}
+
+	/* Assign the address to the if */
+	ifr6.ifr6_addr = *addr6;
+	ifr6.ifr6_ifindex = ifr.ifr_ifindex;
+	ifr6.ifr6_prefixlen = prefix_len;
+	if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) {
+		return -1;
+	}
+	close (fd);
+	return 0;
+}
+int
+unassign_addr6(struct in6_addr* addr6, int prefix_len, char* if_name)
+{
+	int			fd;
+	struct ifreq		ifr;
+	struct in6_ifreq	ifr6;
+
+	/* Get socket first */
+	fd = socket(AF_INET6, SOCK_DGRAM, 0);
+	if (fd < 0) {
+		return 1;
+	}
+
+	/* Query the index of the if */
+	strcpy(ifr.ifr_name, if_name);
+	if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
+		return -1;
+	}
+
+	/* Unassign the address to the if */
+	ifr6.ifr6_addr = *addr6;
+	ifr6.ifr6_ifindex = ifr.ifr_ifindex;
+	ifr6.ifr6_prefixlen = prefix_len;
+	if (ioctl(fd, SIOCDIFADDR, &ifr6) < 0) {
+		return -1;
+	}
+	
+	close (fd);
+	return 0;
+}
+
+#define	MINPACKSIZE	64
+int
+is_addr6_available(struct in6_addr* addr6)
+{
+	struct sockaddr_in6		addr;
+	struct icmp6_hdr		icmph;
+	u_char				outpack[MINPACKSIZE];
+	int				icmp_sock;
+	int				ret;
+	struct iovec			iov;
+	u_char				packet[MINPACKSIZE];
+	struct msghdr			msg;
+
+	if ((icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1) {
+		return -1;
+	}
+
+	memset(&icmph, 0, sizeof(icmph));
+	icmph.icmp6_type = ICMP6_ECHO_REQUEST;
+	icmph.icmp6_code = 0;
+	icmph.icmp6_cksum = 0;
+	icmph.icmp6_seq = htons(0);
+	icmph.icmp6_id = 0;
+
+	memset(&outpack, 0, sizeof(outpack));
+	memcpy(&outpack, &icmph, sizeof(icmph));
+
+	memset(&addr, 0, sizeof(struct sockaddr_in6));
+	addr.sin6_family = AF_INET6;
+	addr.sin6_port = htons(IPPROTO_ICMPV6);
+	memcpy(&addr.sin6_addr,addr6,sizeof(struct in6_addr));
+
+	/* Only the first 8 bytes of outpack are meaningful... */
+	ret = sendto(icmp_sock, (char *)outpack, sizeof(outpack), 0,
+			   (struct sockaddr *) &addr,
+			   sizeof(struct sockaddr_in6));
+	if (0 >= ret) {
+		return -1;
+	}
+
+	iov.iov_base = (char *)packet;
+	iov.iov_len = sizeof(packet); 
+
+	msg.msg_name = &addr;
+	msg.msg_namelen = sizeof(addr);
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = NULL;
+	msg.msg_controllen = 0;
+
+	ret = recvmsg(icmp_sock, &msg, MSG_DONTWAIT);
+	if (0 >= ret) {
+		return -1;
+	}
+	
+	return 0;
+}
+
+static void usage(const char* self)
+{
+	printf("usage: %s {start|stop|status|monitor|validate-all|meta-data}\n",self);
+	return;
+}
+
+/* Following code is copied from send_arp.c, linux-HA project. */
+void
+byebye(int nsig)
+{
+	(void)nsig;
+	/* Avoid an "error exit" log message if we're killed */
+	exit(0);
+}
+
+int
+create_pid_directory(const char *pid_file)
+{
+	int status;
+	int return_status = -1;
+	struct stat stat_buf;
+	char* dir;
+
+	dir = strdup(pid_file);
+	if (!dir) {
+		cl_log(LOG_INFO, "Memory allocation failure: %s",
+				strerror(errno));
+		return -1;
+	}
+
+	dirname(dir);
+
+	status = stat(dir, &stat_buf);
+
+	if (status < 0 && errno != ENOENT && errno != ENOTDIR) {
+		cl_log(LOG_INFO, "Could not stat pid-file directory "
+				"[%s]: %s", dir, strerror(errno));
+		goto err;
+	}
+
+	if (!status) {
+		if (S_ISDIR(stat_buf.st_mode)) {
+			goto out;
+		}
+		cl_log(LOG_INFO, "Pid-File directory exists but is "
+				"not a directory [%s]", dir);
+		goto err;
+        }
+
+	if (mkdir(dir, S_IRUSR|S_IWUSR|S_IXUSR | S_IRGRP|S_IXGRP) < 0) {
+		cl_log(LOG_INFO, "Could not create pid-file directory "
+				"[%s]: %s", dir, strerror(errno));
+		goto err;
+	}
+
+out:
+	return_status = 0;
+err:
+	free(dir);
+	return return_status;
+}
+
+int
+write_pid_file(const char *pid_file)
+{
+
+	int     	pidfilefd;
+	char    	pidbuf[11];
+	unsigned long   pid;
+	ssize_t 	bytes;
+
+	if (*pid_file != '/') {
+		cl_log(LOG_INFO, "Invalid pid-file name, must begin with a "
+				"'/' [%s]\n", pid_file);
+		return -1;
+	}
+
+	if (create_pid_directory(pid_file) < 0) {
+		return -1;
+	}
+
+	while (1) {
+		pidfilefd = open(pid_file, O_CREAT|O_EXCL|O_RDWR,
+				S_IRUSR|S_IWUSR);
+		if (pidfilefd < 0) {
+			if (errno != EEXIST) { /* Old PID file */
+				cl_log(LOG_INFO, "Could not open pid-file "
+						"[%s]: %s", pid_file,
+						strerror(errno));
+				return -1;
+			}
+		}
+		else {
+			break;
+		}
+
+		pidfilefd = open(pid_file, O_RDONLY, S_IRUSR|S_IWUSR);
+		if (pidfilefd < 0) {
+			cl_log(LOG_INFO, "Could not open pid-file "
+					"[%s]: %s", pid_file,
+					strerror(errno));
+			return -1;
+		}
+
+		while (1) {
+			bytes = read(pidfilefd, pidbuf, sizeof(pidbuf)-1);
+			if (bytes < 0) {
+				if (errno == EINTR) {
+					continue;
+				}
+				cl_log(LOG_INFO, "Could not read pid-file "
+						"[%s]: %s", pid_file,
+						strerror(errno));
+				return -1;
+			}
+			pidbuf[bytes] = '\0';
+			break;
+		}
+
+		if(unlink(pid_file) < 0) {
+			cl_log(LOG_INFO, "Could not delete pid-file "
+	 				"[%s]: %s", pid_file,
+					strerror(errno));
+			return -1;
+		}
+
+		if (!bytes) {
+			cl_log(LOG_INFO, "Invalid pid in pid-file "
+	 				"[%s]: %s", pid_file,
+					strerror(errno));
+			return -1;
+		}
+
+		close(pidfilefd);
+
+		pid = strtoul(pidbuf, NULL, 10);
+		if (pid == ULONG_MAX && errno == ERANGE) {
+			cl_log(LOG_INFO, "Invalid pid in pid-file "
+	 				"[%s]: %s", pid_file,
+					strerror(errno));
+			return -1;
+		}
+
+		if (kill(pid, SIGKILL) < 0 && errno != ESRCH) {
+			cl_log(LOG_INFO, "Error killing old proccess [%lu] "
+	 				"from pid-file [%s]: %s", pid,
+					pid_file, strerror(errno));
+			return -1;
+		}
+
+		cl_log(LOG_INFO, "Killed old send_arp process [%lu]", pid);
+	}
+
+	if (snprintf(pidbuf, sizeof(pidbuf), "%u"
+	,	getpid()) >= (int)sizeof(pidbuf)) {
+		cl_log(LOG_INFO, "Pid too long for buffer [%u]", getpid());
+		return -1;
+	}
+
+	while (1) {
+		bytes = write(pidfilefd, pidbuf, strlen(pidbuf));
+		if (bytes != strlen(pidbuf)) {
+			if (bytes < 0 && errno == EINTR) {
+				continue;
+			}
+			cl_log(LOG_INFO, "Could not write pid-file "
+					"[%s]: %s", pid_file,
+					strerror(errno));
+			return -1;
+		}
+		break;
+	}
+
+	close(pidfilefd);
+
+	return 0;
+}
+static int
+meta_data_addr6(void)
+{
+	const char* meta_data=
+	"<?xml version=\"1.0\"?>\n"
+	"<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
+	"<resource-agent name=\"IPv6addr\">\n"
+	"  <version>1.0</version>\n"
+	"  <longdesc lang=\"en\">\n"
+	"   This script manages IPv6 alias IPv6 addresses,It can add an IP6\n"
+	"   alias, or remove one.\n"
+	"  </longdesc>\n"
+	"  <shortdesc lang=\"en\">Manages IPv6 aliases</shortdesc>\n"
+	"  <parameters>\n"
+	"    <parameter name=\"ipv6addr\" unique=\"0\" required=\"1\">\n"
+	"      <longdesc lang=\"en\">\n"
+	"	The IPv6 address this RA will manage \n"
+	"      </longdesc>\n"
+	"      <shortdesc lang=\"en\">IPv6 address</shortdesc>\n"
+	"      <content type=\"string\" default=\"\" />\n"
+	"    </parameter>\n"
+	"    <parameter name=\"cidr_netmask\" unique=\"0\">\n"
+	"      <longdesc lang=\"en\">\n"
+	"	The netmask for the interface in CIDR format. (ie, 24).\n"
+	"	The value of this parameter overwrites the value of _prefix_\n"
+	"	of ipv6addr parameter.\n"
+	"      </longdesc>\n"
+	"      <shortdesc lang=\"en\">Netmask</shortdesc>\n"
+	"      <content type=\"string\" default=\"\" />\n"
+	"    </parameter>\n"
+	"    <parameter name=\"nic\" unique=\"0\">\n"
+	"      <longdesc lang=\"en\">\n"
+	"	The base network interface on which the IPv6 address will\n"
+	"	be brought online.\n"
+	"      </longdesc>\n"
+	"      <shortdesc lang=\"en\">Network interface</shortdesc>\n"
+	"      <content type=\"string\" default=\"\" />\n"
+	"    </parameter>\n"
+	"  </parameters>\n"
+	"  <actions>\n"
+	"    <action name=\"start\"   timeout=\"15\" />\n"
+	"    <action name=\"stop\"    timeout=\"15\" />\n"
+	"    <action name=\"status\"  timeout=\"15\" interval=\"15\" />\n"
+	"    <action name=\"monitor\" timeout=\"15\" interval=\"15\" />\n"
+	"    <action name=\"validate-all\"  timeout=\"5\" />\n"
+	"    <action name=\"meta-data\"  timeout=\"5\" />\n"
+	"  </actions>\n"
+	"</resource-agent>\n";
+	printf("%s\n",meta_data);
+	return OCF_SUCCESS;
+}
diff --git a/heartbeat/IPv6addr_utils.c b/heartbeat/IPv6addr_utils.c
new file mode 100644
index 0000000..7672b70
--- /dev/null
+++ b/heartbeat/IPv6addr_utils.c
@@ -0,0 +1,147 @@
+
+/*
+ * This program manages IPv6 address with OCF Resource Agent standard.
+ *
+ * Author: Huang Zhen <zhenh at cn.ibm.com>
+ * Copyright (c) 2004 International Business Machines
+ *
+ * This library 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 library 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.
+ */
+
+#include <IPv6addr.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <arpa/inet.h> /* for inet_pton */
+#include <net/if.h> /* for if_nametoindex */
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+
+/* Send an unsolicited advertisement packet
+ * Please refer to rfc4861 / rfc3542
+ */
+int
+send_ua(struct in6_addr* src_ip, char* if_name)
+{
+	int status = -1;
+	int fd;
+
+	int ifindex;
+	int hop;
+	struct ifreq ifr;
+	u_int8_t *payload = NULL;
+	int    payload_size;
+	struct nd_neighbor_advert *na;
+	struct nd_opt_hdr *opt;
+	struct sockaddr_in6 src_sin6;
+	struct sockaddr_in6 dst_sin6;
+
+	if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1) {
+		printf("ERROR: socket(IPPROTO_ICMPV6) failed: %s",
+		       strerror(errno));
+		return status;
+	}
+	/* set the outgoing interface */
+	ifindex = if_nametoindex(if_name);
+	if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+		       &ifindex, sizeof(ifindex)) < 0) {
+		printf("ERROR: setsockopt(IPV6_MULTICAST_IF) failed: %s",
+		       strerror(errno));
+		goto err;
+	}
+	/* set the hop limit */
+	hop = 255; /* 255 is required. see rfc4861 7.1.2 */
+	if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+		       &hop, sizeof(hop)) < 0) {
+		printf("ERROR: setsockopt(IPV6_MULTICAST_HOPS) failed: %s",
+		       strerror(errno));
+		goto err;
+	}
+
+	/* set the source address */
+	memset(&src_sin6, 0, sizeof(src_sin6));
+	src_sin6.sin6_family = AF_INET6;
+	src_sin6.sin6_addr = *src_ip;
+	src_sin6.sin6_port = 0;
+	if (IN6_IS_ADDR_LINKLOCAL(&src_sin6.sin6_addr) ||
+	    IN6_IS_ADDR_MC_LINKLOCAL(&src_sin6.sin6_addr)) {
+		src_sin6.sin6_scope_id = ifindex;
+	}
+
+	if (bind(fd, (struct sockaddr *)&src_sin6, sizeof(src_sin6)) < 0) {
+		printf("ERROR: bind() failed: %s", strerror(errno));
+		goto err;
+	}
+
+
+	/* get the hardware address */
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name) - 1);
+	if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
+		printf("ERROR: ioctl(SIOCGIFHWADDR) failed: %s", strerror(errno));
+		goto err;
+	}
+
+	/* build a neighbor advertisement message */
+	payload_size = sizeof(struct nd_neighbor_advert)
+			 + sizeof(struct nd_opt_hdr) + HWADDR_LEN;
+	payload = memalign(sysconf(_SC_PAGESIZE), payload_size);
+	if (!payload) {
+		printf("ERROR: malloc for payload failed");
+		goto err;
+	}
+	memset(payload, 0, payload_size);
+
+	/* Ugly typecast from ia64 hell! */
+	na = (struct nd_neighbor_advert *)((void *)payload);
+	na->nd_na_type = ND_NEIGHBOR_ADVERT;
+	na->nd_na_code = 0;
+	na->nd_na_cksum = 0; /* calculated by kernel */
+	na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE;
+	na->nd_na_target = *src_ip;
+
+	/* options field; set the target link-layer address */
+	opt = (struct nd_opt_hdr *)(payload + sizeof(struct nd_neighbor_advert));
+	opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
+	opt->nd_opt_len = 1; /* The length of the option in units of 8 octets */
+	memcpy(payload + sizeof(struct nd_neighbor_advert)
+			+ sizeof(struct nd_opt_hdr),
+	       &ifr.ifr_hwaddr.sa_data, HWADDR_LEN);
+
+	/* sending an unsolicited neighbor advertisement to all */
+	memset(&dst_sin6, 0, sizeof(dst_sin6));
+	dst_sin6.sin6_family = AF_INET6;
+	inet_pton(AF_INET6, BCAST_ADDR, &dst_sin6.sin6_addr); /* should not fail */
+
+	if (sendto(fd, payload, payload_size, 0,
+		   (struct sockaddr *)&dst_sin6, sizeof(dst_sin6))
+	    != payload_size) {
+		printf("ERROR: sendto(%s) failed: %s",
+		       if_name, strerror(errno));
+		goto err;
+	}
+
+	status = 0;
+
+err:
+	close(fd);
+	free(payload);
+	return status;
+}
diff --git a/heartbeat/LVM b/heartbeat/LVM
new file mode 100755
index 0000000..ec1ee7d
--- /dev/null
+++ b/heartbeat/LVM
@@ -0,0 +1,672 @@
+#!/bin/sh
+#
+# 
+# LVM
+#
+# Description:	Manages an LVM volume as an HA resource
+#
+#
+# Author:	Alan Robertson
+# Support:	linux-ha at lists.linux-ha.org
+# License:	GNU General Public License (GPL)
+# Copyright:	(C) 2002 - 2005 International Business Machines, Inc.
+#
+#	This code significantly inspired by the LVM resource
+#	in FailSafe by Lars Marowsky-Bree
+#
+#
+# An example usage in /etc/ha.d/haresources: 
+#			 node1	10.0.0.170 ServeRAID::1::1 LVM::myvolname
+#
+# See usage() function below for more details...
+#
+#		OCF parameters are as below:
+#		OCF_RESKEY_volgrpname
+#		
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+
+usage() {
+	methods=`LVM_methods`
+	methods=`echo $methods | tr ' ' '|'`
+	cat <<EOF
+	usage: $0 $methods
+
+	$0 manages an	Linux Volume Manager volume (LVM) as an HA resource
+
+	The 'start' operation brings the given volume online
+	The 'stop' operation takes the given volume offline
+	The 'status' operation reports whether the volume is available
+	The 'monitor' operation reports whether the volume seems present
+	The 'validate-all' operation checks whether the OCF parameters are valid
+	The 'meta-data' operation show meta data 
+	The 'methods' operation reports on the methods $0 supports
+
+EOF
+}
+
+# default for "tag"
+OUR_TAG="pacemaker"
+
+meta_data() {
+	cat <<EOF
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="LVM">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for LVM. It manages an Linux Volume Manager volume (LVM) 
+as an HA resource. 
+</longdesc>
+<shortdesc lang="en">Controls the availability of an LVM Volume Group</shortdesc>
+
+<parameters>
+<parameter name="volgrpname" unique="0" required="1">
+<longdesc lang="en">
+The name of volume group.
+</longdesc>
+<shortdesc lang="en">Volume group name</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="exclusive" unique="0" required="0">
+<longdesc lang="en">
+If set, the volume group will be activated exclusively.  This option works one of
+two ways.  If the volume group has the cluster attribute set, then the volume group
+will be activated exclusively using clvmd across the cluster.  If the cluster attribute
+is not set, the volume group will be activated exclusively using a tag and the volume_list 
+filter. When the tag option is in use, the volume_list in lvm.con must be initialized. This 
+can be as simple as setting 'volume_list = []' depending on your setup.
+</longdesc>
+<shortdesc lang="en">Exclusive activation</shortdesc>
+<content type="boolean" default="false" />
+</parameter>
+
+<parameter name="tag" unique="0" required="0">
+<longdesc lang="en">
+If "exclusive" is set on a non clustered volume group, this overrides the tag to be used.
+</longdesc>
+<shortdesc lang="en">Exclusive activation tag</shortdesc>
+<content type="string" default="$OUR_TAG" />
+</parameter>
+
+<parameter name="partial_activation" unique="0" required="0">
+<longdesc lang="en">
+If set, the volume group will be activated even only partial of the physical
+volumes available. It helps to set to true, when you are using mirroring
+logical volumes.
+</longdesc>
+<shortdesc lang="en">Activate VG even with partial PV only</shortdesc>
+<content type="string" default="false" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="30" />
+<action name="stop" timeout="30" />
+<action name="status" timeout="30" />
+<action name="monitor" depth="0" timeout="30" interval="10" />
+<action name="methods" timeout="5" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+</actions>
+</resource-agent>
+EOF
+}
+
+#
+# methods: What methods/operations do we support?
+#
+LVM_methods() {
+	cat <<EOF
+	start
+	stop
+	status
+	monitor
+	methods
+	validate-all
+	meta-data
+	usage
+EOF
+}
+
+##
+# returns mode
+#
+# 0 = normal (non-exclusive) local activation
+# 1 = tagged-exclusive activation
+# 2 = clvm-exclusive activation
+##
+VG_MODE=
+get_vg_mode()
+{
+	if [ -n "$VG_MODE" ]; then
+		echo "$VG_MODE"
+		return
+	fi
+
+	VG_MODE=0
+	if ocf_is_true "$OCF_RESKEY_exclusive"; then
+		case $(vgs -o attr --noheadings $OCF_RESKEY_volgrpname | tr -d ' ') in
+		?????c*)
+			VG_MODE=2 ;;
+		*)
+			VG_MODE=1 ;;
+		esac
+	fi
+
+	echo "$VG_MODE"
+}
+
+##
+# Verify tags setup
+##
+verify_tags_environment()
+{
+	##
+	# The volume_list must be initialized to something in order to
+	# guarantee our tag will be filtered on startup
+	##
+	if ! lvm dumpconfig activation/volume_list; then
+		ocf_log err "LVM: Improper setup detected"
+		ocf_log err "The volume_list filter must be initialized in lvm.conf for exclusive activation without clvmd"
+		return $OCF_ERR_GENERIC
+	fi
+
+	##
+	# Our tag must _NOT_ be in the volume_list.  This agent
+	# overrides the volume_list during activation using the
+	# special tag reserved for cluster activation
+	##
+	if lvm dumpconfig activation/volume_list | grep -e "\"@$OUR_TAG\"" -e "\"${OCF_RESKEY_volgrpname}\""; then
+		ocf_log err "LVM:  Improper setup detected"
+		ocf_log err "The volume_list in lvm.conf must not contain the cluster tag, \"$OUR_TAG\", or volume group, $OCF_RESKEY_volgrpname"
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+check_initrd_warning()
+{
+	# First check to see if there is an initrd img we can safely
+	# compare timestamps agaist.  If not, don't even bother with
+	# this check.  This is known to work in rhel/fedora distros
+	ls "/boot/*$(uname -r)*.img" > /dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		return
+	fi
+
+	##
+	# Now check to see if the initrd has been updated.
+	# If not, the machine could boot and activate the VG outside
+	# the control of pacemaker
+	##
+	if [ "$(find /boot -name *.img -newer /etc/lvm/lvm.conf)" = "" ]; then
+		ocf_log warn "LVM:  Improper setup detected"
+		ocf_log warn "* initrd image needs to be newer than lvm.conf"
+
+		# While dangerous if not done the first time, there are many
+		# cases where we don't simply want to fail here.  Instead,
+		# keep warning until the user remakes the initrd - or has
+		# it done for them by upgrading the kernel.
+		#
+		# initrd can be updated using this command.
+		# dracut -H -f /boot/initramfs-$(uname -r).img $(uname -r)
+		#
+	fi
+}
+
+##
+# does this vg have our tag
+##
+check_tags()
+{
+	local owner=`vgs -o tags --noheadings $OCF_RESKEY_volgrpname | tr -d ' '`
+
+	if [ -z "$owner" ]; then
+		# No-one owns this VG yet
+		return 1
+	fi
+
+	if [ "$OUR_TAG" = "$owner" ]; then
+		# yep, this is ours
+		return 0
+	fi
+
+	# some other tag is set on this vg
+	return 2
+}
+
+strip_tags()
+{
+	local i
+
+	for i in `vgs --noheadings -o tags $OCF_RESKEY_volgrpname | sed s/","/" "/g`; do
+		ocf_log info "Stripping tag, $i"
+
+		# LVM version 2.02.98 allows changing tags if PARTIAL
+		vgchange --deltag $i $OCF_RESKEY_volgrpname
+	done
+
+	if [ ! -z `vgs -o tags --noheadings $OCF_RESKEY_volgrpname | tr -d ' '` ]; then
+		ocf_log err "Failed to remove ownership tags from $OCF_RESKEY_volgrpname"
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+set_tags()
+{
+	check_tags
+	case $? in
+	0)
+		# we already own it.
+		return $OCF_SUCCESS
+		;;
+	2)
+		# other tags are set, strip them before setting
+		if ! strip_tags; then
+			return $OCF_ERR_GENERIC
+		fi
+		;;
+	*)
+		: ;;
+	esac
+
+	vgchange --addtag $OUR_TAG $OCF_RESKEY_volgrpname
+	if [ $? -ne 0 ]; then
+		ocf_log err "Failed to add ownership tag to $OCF_RESKEY_volgrpname"
+		return $OCF_ERR_GENERIC
+	fi
+
+	ocf_log info "New tag \"$OUR_TAG\" added to $OCF_RESKEY_volgrpname"
+	return $OCF_SUCCESS
+}
+
+#
+#	Return LVM status (silently)
+#
+LVM_status() {
+	local rc=1
+	loglevel="debug"
+
+	# Set the log level of the error message
+	if [ "X${2}" = "X" ]; then
+		loglevel="err"
+		if ocf_is_probe; then
+			loglevel="warn"
+		else 
+			if [ ${OP_METHOD} = "stop" ]; then
+				loglevel="info"
+			fi
+		fi
+	fi
+	
+	if [ -d /dev/$1 ]; then
+		test "`cd /dev/$1 && ls`" != ""
+		rc=$?
+		if [ $rc -ne 0 ]; then
+			ocf_log err "VG $1 with no logical volumes is not supported by this RA!"
+		fi
+	fi
+
+	if [ $rc -ne 0 ]; then
+		ocf_log $loglevel "LVM Volume $1 is not available (stopped)"
+		rc=$OCF_NOT_RUNNING
+	else
+		case $(get_vg_mode) in
+		1) # exclusive with tagging.
+			# If vg is running, make sure the correct tag is present. Otherwise we
+			# can not guarantee exclusive activation.
+			if ! check_tags; then
+				ocf_log err "WARNING: $OCF_RESKEY_volgrpname is active without the cluster tag, \"$OUR_TAG\""
+				rc=$OCF_ERR_GENERIC
+			fi
+
+			# make sure the environment for tags activation is still valid
+			if ! verify_tags_environment; then
+				rc=$OCF_ERR_GENERIC
+			fi
+			# let the user know if their initrd is older than lvm.conf.
+			check_initrd_warning
+			;;
+		*)
+			: ;;
+		esac
+	fi
+
+	if [ "X${2}" = "X" ]; then
+		# status call return
+		return $rc
+	fi
+
+	# Report on LVM volume status to stdout...
+	if [ $rc -eq 0 ]; then
+		echo "Volume $1 is available (running)"
+	else
+		echo "Volume $1 is not available (stopped)"
+	fi
+	return $rc
+}
+
+get_activate_options()
+{
+	local options="-a"
+
+	case $(get_vg_mode) in
+	0) options="${options}ly";;
+	1) options="${options}y --config activation{volume_list=[\"@${OUR_TAG}\"]}";;
+	2) options="${options}ey";;
+	esac
+
+	if ocf_is_true "$OCF_RESKEY_partial_activation" ; then
+		options="${options} --partial"
+	fi
+
+	# for clones (clustered volume groups), we'll also have to force
+	# monitoring, even if disabled in lvm.conf.
+	if ocf_is_clone; then
+		options="$options --monitor y"
+	fi
+	
+	echo $options
+}
+
+##
+# Attempt to deactivate vg cluster wide and then start the vg exclusively
+##
+retry_exclusive_start()
+{
+	local vgchange_options=$(get_activate_options)
+
+	# Deactivate each LV in the group one by one cluster wide
+	set -- $(lvs -o name,attr --noheadings $OCF_RESKEY_volgrpname 2> /dev/null)
+	while [ $# -ge 2 ]; do
+		case $2 in
+		????ao*)
+			# open LVs cannot be deactivated.
+			return $OCF_ERR_GENERIC;;
+		*)
+			if ! lvchange -an $OCF_RESKEY_volgrpname/$1; then
+				ocf_log err "Unable to perform required deactivation of $OCF_RESKEY_volgrpname/$1 before starting"
+				return $OCF_ERR_GENERIC
+			fi
+			;;
+		esac
+		shift 2
+	done
+
+	ocf_run vgchange $vgchange_options $OCF_RESKEY_volgrpname
+}
+
+#
+#	Enable LVM volume
+#
+LVM_start() {
+	local vgchange_options=$(get_activate_options)
+	local vg=$1
+	local clvmd=0
+
+	# TODO: This MUST run vgimport as well
+	ocf_log info "Activating volume group $vg"
+	if [ "$LVM_MAJOR" -eq "1" ]; then
+		ocf_run vgscan $vg
+	else
+		ocf_run vgscan
+	fi
+
+	case $(get_vg_mode) in
+	2)
+		clvmd=1
+		;;
+	1)
+		if ! set_tags; then
+			return $OCF_ERR_GENERIC
+		fi
+		;;
+	*)
+		: ;;
+	esac
+
+	if ! ocf_run vgchange $vgchange_options $vg; then
+		if [ $clvmd -eq 0 ]; then
+			return $OCF_ERR_GENERIC
+		fi
+
+		# Failure to exclusively activate cluster vg.:
+		# This could be caused by a remotely active LV, Attempt
+		# to disable volume group cluster wide and try again.
+		# Allow for some settling
+		sleep 5
+		if ! retry_exclusive_start; then
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+
+	if LVM_status $vg; then
+		: OK Volume $vg activated just fine!
+		return $OCF_SUCCESS 
+	else
+		ocf_log err "LVM: $vg did not activate correctly"
+		return $OCF_NOT_RUNNING
+	fi
+}
+
+#
+#	Disable the LVM volume
+#
+LVM_stop() {
+	local res=$OCF_ERR_GENERIC
+	local vgchange_options="-aln"
+	local vg=$1
+
+	if ! vgs $vg > /dev/null 2>&1; then
+		ocf_log info "Volume group $vg not found"
+		return $OCF_SUCCESS
+	fi
+
+	ocf_log info "Deactivating volume group $vg"
+
+	case $(get_vg_mode) in
+		1) vgchange_options="-an" ;;
+	esac
+
+	for i in $(seq 10)
+	do
+		ocf_run vgchange $vgchange_options $vg
+		res=$?
+		if LVM_status $vg; then
+			ocf_log err "LVM: $vg did not stop correctly"
+			res=1
+		fi
+
+		if [ $res -eq 0 ]; then
+			break
+		fi
+
+		res=$OCF_ERR_GENERIC
+		ocf_log warn "$vg still Active"
+		ocf_log info "Retry deactivating volume group $vg"
+		sleep 1
+		which udevadm > /dev/null 2>&1 && udevadm settle --timeout=5
+	done
+
+	case $(get_vg_mode) in
+	1)
+		if [ $res -eq 0 ]; then
+			strip_tags
+			res=$?
+		fi
+		;;
+	esac
+
+	return $res
+}
+
+#
+#	Check whether the OCF instance parameters are valid
+#
+LVM_validate_all() {
+	check_binary $AWK
+
+	##
+	# Off-the-shelf tests...
+	##
+	VGOUT=`vgck ${VOLUME} 2>&1`
+	if [ $? -ne 0 ]; then
+		ocf_log err "Volume group [$VOLUME] does not exist or contains error! ${VGOUT}"
+		exit $OCF_ERR_GENERIC
+	fi
+
+	##
+	# Does the Volume Group exist?
+	##
+	if [ "$LVM_MAJOR" = "1" ]; then
+		VGOUT=`vgdisplay ${VOLUME} 2>&1`
+	else
+		VGOUT=`vgdisplay -v ${VOLUME} 2>&1`
+	fi
+	if [ $? -ne 0 ]; then
+		ocf_log err "Volume group [$VOLUME] does not exist or contains error! ${VGOUT}"
+		exit $OCF_ERR_GENERIC
+	fi
+
+	##
+	# If exclusive activation is not enabled, then
+	# further checking of proper setup is not necessary
+	##
+	if ! ocf_is_true "$OCF_RESKEY_exclusive"; then
+		return $OCF_SUCCESS;
+	fi
+
+	##
+	# Having cloned lvm resources with exclusive vg activation makes no sense at all.
+	##
+	if ocf_is_clone; then
+		ocf_log_err "cloned lvm resources can not be activated exclusively"
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	##
+	# Make sure the cluster attribute is set and clvmd is up when exclusive
+	# activation is enabled. Otherwise we can't exclusively activate the volume group.
+	##
+	case $(get_vg_mode) in
+	1)  # exclusive activation using tags
+		if ! verify_tags_environment; then
+			exit $OCF_ERR_GENERIC
+		fi
+		;;
+	2)  # exclusive activation with clvmd
+		##
+		# verify is clvmd running
+		##
+		if ! ps -C clvmd > /dev/null 2>&1; then
+			ocf_log err "$OCF_RESKEY_volgrpname has the cluster attribute set, but 'clvmd' is not running"
+			exit $OCF_ERR_GENERIC
+		fi
+		;;
+	*)
+		: ;;
+	esac
+
+	return $OCF_SUCCESS
+}
+
+#
+#	'main' starts here...
+#
+
+if
+	[ $# -ne 1 ]
+then
+	usage
+	exit $OCF_ERR_ARGS 
+fi
+
+case $1 in
+	meta-data)	meta_data
+		exit $OCF_SUCCESS;;
+
+	methods)	LVM_methods
+		exit $?;;
+
+	usage)	usage
+		exit $OCF_SUCCESS;;
+	*)		;;
+esac
+
+if 
+	[ -z "$OCF_RESKEY_volgrpname" ]
+then
+	ocf_log err "You must identify the volume group name!"
+	exit $OCF_ERR_CONFIGURED 
+fi
+
+# Get the LVM version number, for this to work we assume(thanks to panjiam):
+# 
+# LVM1 outputs like this
+#
+#	# vgchange --version
+#	vgchange: Logical Volume Manager 1.0.3
+#	Heinz Mauelshagen, Sistina Software	19/02/2002 (IOP 10)
+#
+# LVM2 and higher versions output in this format
+#
+#	# vgchange --version
+#	LVM version:		 2.00.15 (2004-04-19)
+#	Library version: 1.00.09-ioctl (2004-03-31)
+#	Driver version:	4.1.0
+
+LVM_VERSION=`vgchange --version 2>&1 | \
+	$AWK '/Logical Volume Manager/ {print $5"\n"; exit; }
+			 /LVM version:/ {printf $3"\n"; exit;}'`
+rc=$?
+
+if
+	( [ $rc -ne 0 ] || [ -z "$LVM_VERSION" ] )
+then
+	ocf_log err "LVM: $1 could not determine LVM version. Try 'vgchange --version' manually and modify $0 ?"
+	exit $OCF_ERR_INSTALLED
+fi
+LVM_MAJOR="${LVM_VERSION%%.*}"
+
+VOLUME=$OCF_RESKEY_volgrpname
+OP_METHOD=$1
+
+if [ -n "$OCF_RESKEY_tag" ]; then
+	OUR_TAG=$OCF_RESKEY_tag
+fi
+
+# What kind of method was invoked?
+case "$1" in
+
+	start)
+		LVM_validate_all
+		LVM_start $VOLUME
+		exit $?;;
+
+	stop)	LVM_stop $VOLUME
+		exit $?;;
+
+	status)	LVM_status $VOLUME $1
+		exit $?;;
+
+	monitor)	LVM_status $VOLUME
+		exit $?;;
+
+	validate-all)	LVM_validate_all
+		;;
+
+	*)		usage
+		exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/heartbeat/LinuxSCSI b/heartbeat/LinuxSCSI
new file mode 100755
index 0000000..ce033c0
--- /dev/null
+++ b/heartbeat/LinuxSCSI
@@ -0,0 +1,314 @@
+#!/bin/sh
+#
+#
+# LinuxSCSI
+#
+# Description:	Enables/Disables SCSI devices to protect them from being
+#		used by mistake
+#
+#
+# Author:	Alan Robertson
+#		Support: linux-ha at lists.linux-ha.org
+# License:	GNU General Public License (GPL)
+# Copyright:	(C) 2002 - 2005 IBM
+#
+# CAVEATS:	See the usage message for some important warnings
+#
+# usage: ./LinuxSCSI (start|stop|status|monitor|meta-data|validate-all|methods)
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_scsi
+#
+# An example usage in /etc/ha.d/haresources:
+#       node1  10.0.0.170 LinuxSCSI:0:0:11
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+zeropat="[ 0]0"
+
+PROCSCSI=/proc/scsi/scsi
+
+usage() {
+  cat <<EOF
+	usage: $0 (start|stop|status|monitor|meta-data|validate-all|methods)
+
+	$0 manages the availability of a SCSI device from the point
+	of view of the linux kernel.  It make Linux believe the
+	device has gone away, and it can make it come back again.
+
+	The purpose of this resource script is to keep admins from
+	accidentally messing with a shared disk that is managed by the
+	HA subsystem and is currently owned by the other side.
+
+	To get maximum benefit from this feature, you should (manually)
+	disable the resources on boot, and let your HA software enable
+	them when it wants to acquire the disk.
+	
+	The kernel code says this is potentially dangerous.  DO NOT USE
+	IT ON AN ACTIVE DEVICE.  If the device is inactive, this script
+	will make it stay inactive, when given "off".  If you inactivate
+	the wrong device, you may have to reboot your machine, and your
+	data may take a hit.
+
+	On the other hand, at least one RAID controller requires the
+	use of this technique for it to work correctly in a failover
+	environment - so it is believed that it is more stable in this
+	usage than the comments in the code imply.
+
+	Here are the warnings from the kernel source about the "stop"
+	operation as of 2.4.10:
+
+	------------------------------
+	Consider this feature pre-BETA.
+	    CAUTION: This is not for hotplugging your peripherals. As
+	    SCSI was not designed for this, you could damage your
+	    hardware and thoroughly confuse the SCSI subsystem.
+
+	Similar warnings apply to the "start" operation...
+
+	 Consider this feature BETA.
+	     CAUTION: This is not for hotplugging your peripherals.
+	     As SCSI was not designed for this you could damage your
+	     hardware !
+	However perhaps it is legal to switch on an already connected
+	device. It is perhaps not guaranteed this device doesn't corrupt
+	an ongoing data transfer.
+	-------------------------
+
+	So, Caveat Emptor, and test this feature thoroughly on
+	your kernel and your configuration with real load on the SCSI
+	bus before using it in production!
+
+	Another potential trouble spot...
+	The order in which you bring up LinuxSCSI resources determines which
+	SCSI device they show up as on Linux.  If you have two SCSI devices
+	in different resource groups they will be brought up asyncronously
+	resulting in indeterminate device name assignments.  This usually
+	happens in an active-active configuration.
+	
+	To solve this you probably should use LVM or EVMS to manage these
+	volumes.  LVM and EVMS solve this problem for you by labels they
+	keep in the volumes.  If you don't use a reasonable volume manager,
+	then you'll have to mount by UUID.
+
+EOF
+}
+
+meta_data() {
+	cat <<EOF
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="LinuxSCSI">
+<version>1.0</version>
+
+<longdesc lang="en">
+Deprecation warning: This agent makes use of Linux SCSI hot-plug
+functionality which has been superseded by SCSI reservations. It is
+deprecated and may be removed from a future release. See the
+scsi2reservation and sfex agents for alternatives. --
+This is a resource agent for LinuxSCSI. It manages the availability of a
+SCSI device from the point of view of the linux kernel. It make Linux
+believe the device has gone away, and it can make it come back again.
+</longdesc>
+<shortdesc lang="en">Enables and disables SCSI devices through the
+kernel SCSI hot-plug subsystem (deprecated)</shortdesc>
+
+<parameters>
+<parameter name="scsi" unique="0" required="1">
+<longdesc lang="en">
+The SCSI instance to be managed.
+</longdesc>
+<shortdesc lang="en">SCSI instance</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="ignore_deprecation">
+<longdesc lang="en">
+If set to true, suppresses the deprecation warning for this agent.
+</longdesc>
+<shortdesc lang="en">Suppress deprecation warning</shortdesc>
+<content type="boolean" default="false" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="20s" />
+<action name="stop" timeout="20s" />
+<action name="methods" timeout="5" />
+<action name="status" depth="0" timeout="20s" interval="10" />
+<action name="monitor" depth="0" timeout="20s" interval="10" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+</actions>
+</resource-agent>
+EOF
+}
+
+scsi_methods() {
+  cat <<EOF
+	start
+	stop
+	status
+	monitor
+	validate-all
+	methods
+EOF
+}
+
+
+parseinst() {
+  lun=0
+  case "$1" in
+	
+    [0-9]*:[0-9]*:[0-9]*);;
+
+    [0-9]*:[0-9]*:[0-9]*:[0-9]*)
+	lun=`echo "$1" | cut -d: -f4`;;
+
+    *)	#host=error
+	#channel=error
+	#target=error
+	#lun=error
+	ocf_log err "Invalid SCSI instance $1"
+	exit $OCF_ERR_ARGS
+  esac
+  host=`echo "$1" | cut -d: -f1`
+  channel=`echo "$1" | cut -d: -f2`
+  target=`echo "$1" | cut -d: -f3`
+}
+
+#
+# start: Enable the given SCSI device in the kernel
+#
+scsi_start() {
+  parseinst "$1"
+#  [ $target = error ] && exit 1
+#  echo "scsi-add-single-device $host $channel $target $lun" >>$PROCSCSI
+  echo "scsi add-single-device $host $channel $target $lun" >>$PROCSCSI
+  if
+    scsi_status "$1"
+  then
+    return $OCF_SUCCESS
+  else
+    ocf_log err "SCSI device $1 not active!"
+    return $OCF_ERR_GENERIC
+  fi
+}
+
+
+#
+# stop: Disable the given SCSI device in the kernel
+#
+scsi_stop() {
+  parseinst "$1"
+#  [ $target = error ] && exit 1
+  echo "scsi remove-single-device $host $channel $target $lun" >>$PROCSCSI
+  if
+    scsi_status "$1"
+  then
+    ocf_log err "SCSI device $1 still active!"
+    return $OCF_ERR_GENERIC
+  else
+    return $OCF_SUCCESS
+  fi
+}
+
+
+#
+# status: is the given device now available?
+#
+scsi_status() {
+  parseinst "$1"
+#  [ $target = error ] && exit 1
+  [ $channel -eq 0 ]	&& channel=$zeropat
+  [ $target -eq 0 ]	&& target=$zeropat
+  [ $lun -eq 0 ]	&& lun=$zeropat
+  greppat="Host: *scsi$host *Channel: *$channel *Id: *$target *Lun: *$lun"
+  grep -i "$greppat" $PROCSCSI >/dev/null
+  if [ $? -eq 0 ]; then
+	return $OCF_SUCCESS
+  else
+	return $OCF_NOT_RUNNING
+  fi
+}
+
+#
+# validate_all: Check the OCF instance parameters
+#
+scsi_validate_all() {
+  parseinst $instance
+  return $OCF_SUCCESS
+}
+
+if
+  ( [ $# -ne 1 ] )
+then
+  ocf_log err "Parameter number error."
+  usage
+  exit $OCF_ERR_GENERIC
+fi
+
+#if
+#  [ -z "$OCF_RESKEY_scsi" ] && [ "X$1" = "Xmethods" ]
+#then
+#  scsi_methods
+#  exit #?
+#fi
+case $1 in
+  methods)		scsi_methods
+			exit $OCF_SUCCESS
+			;;
+  meta-data)		meta_data
+			exit $OCF_SUCCESS
+			;;
+  usage)		usage
+			exit $OCF_SUCCESS
+			;;
+  *)			;;
+esac
+
+# Be obnoxious, log deprecation warning on every invocation (unless
+# suppressed by resource configuration).
+ocf_deprecated
+
+if
+  [ -z "$OCF_RESKEY_scsi" ]
+then
+  ocf_log err "You have to set a valid scsi id at least!"
+#  usage
+  exit $OCF_ERR_GENERIC
+fi
+
+instance=$OCF_RESKEY_scsi
+
+case $1 in
+  start)		scsi_start $instance
+			;;
+  stop)			scsi_stop $instance
+			;;
+  status|monitor)	
+	 		if
+			  scsi_status $instance
+			then
+			  ocf_log info "SCSI device $instance is running"
+			  return $OCF_SUCCESS
+			else
+			  ocf_log info "SCSI device $instance is stopped"
+			  exit $OCF_NOT_RUNNING
+			fi
+			;;
+  validate-all)		scsi_validate_all
+			;;
+  *)			usage
+			exit $OCF_ERR_UNIMPLEMENTED
+			;;
+esac
+exit $?
diff --git a/heartbeat/MailTo b/heartbeat/MailTo
new file mode 100755
index 0000000..acf6730
--- /dev/null
+++ b/heartbeat/MailTo
@@ -0,0 +1,191 @@
+#!/bin/sh
+#
+# Resource script for MailTo
+#
+# Author: Alan Robertson <alanr at unix.sh>
+#
+# Description: sends email to a sysadmin whenever a takeover occurs.
+#
+#	Note: This command requires an argument, unlike normal init scripts.
+#
+#	This can be given in the haresources file as:
+#
+#	You can also give a mail subject line or even multiple addresses
+#		MailTo::alanr at unix.sh::BigImportantWebServer
+#		MailTo::alanr at unix.sh,spoppi at gmx.de::BigImportantWebServer
+#
+#	This will then be put into the message subject and body.
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_email
+#		OCF_RESKEY_subject
+#
+# License:  GNU General Public License (GPL)
+#
+# Copyright:	(C) 2005 International Business Machines
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+ARGS="$0 $*"
+
+us=`uname -n`
+
+usage() {
+  echo "Usage: $0 {start|stop|status|monitor|meta-data|validate-all}"
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="MailTo">
+<version>1.0</version>
+
+<longdesc lang="en">
+This is a resource agent for MailTo. It sends email to a sysadmin whenever 
+a takeover occurs.
+</longdesc>
+<shortdesc lang="en">Notifies recipients by email in the event of resource takeover</shortdesc>
+
+<parameters>
+<parameter name="email" unique="0" required="1">
+<longdesc lang="en">
+The email address of sysadmin.
+</longdesc>
+<shortdesc lang="en">Email address</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="subject" unique="0">
+<longdesc lang="en">
+The subject of the email.
+</longdesc>
+<shortdesc lang="en">Subject</shortdesc>
+<content type="string" default="" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="10" />
+<action name="stop" timeout="10" />
+<action name="status" depth="0" timeout="10" interval="10" />
+<action name="monitor" depth="0" timeout="10" interval="10" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+MailProgram() {
+	$MAILCMD -s "$1" "$email"  <<EOF
+        $Subject
+ 
+        Command line was:
+        $ARGS
+EOF
+	return $?
+}
+
+SubjectLine() {
+  case $1 in
+    ??*)	echo $@;;
+    *)		echo "Resource Group";;
+  esac
+}
+
+
+MailToStart() {
+
+	Subject="`SubjectLine $subject` Takeover in progress at `date` on $us"
+
+	MailProgram "$Subject" $1
+	ha_pseudo_resource MailTo_${OCF_RESOURCE_INSTANCE} start
+}
+
+MailToStop () {
+	Subject="`SubjectLine $subject` Migrating resource away at `date` from $us"
+
+	MailProgram "$Subject" $1
+	ha_pseudo_resource MailTo_${OCF_RESOURCE_INSTANCE} stop
+}
+
+MailToStatus () {
+#	ocf_log warn "Don't stat/monitor me! MailTo is a pseudo resource agent, so the status reported may be incorrect"
+
+	if ha_pseudo_resource MailTo_${OCF_RESOURCE_INSTANCE} monitor
+	then
+		echo "running"
+		return $OCF_SUCCESS
+	else
+		echo "stopped"
+		return $OCF_NOT_RUNNING
+	fi
+}
+
+MailToValidateAll () {
+	if [ -z "$MAILCMD" ]; then
+		ocf_log err "MAILCMD not set: complain to the packager"
+		exit $OCF_ERR_INSTALLED
+	fi
+	check_binary "$MAILCMD"
+
+	return $OCF_SUCCESS
+}
+
+# 
+# See how we were called.
+#
+#	The order in which heartbeat provides arguments to resource
+#	scripts is broken.  It should be fixed.
+#
+
+if
+  ( [ $# -ne 1 ] )
+then
+  usage
+  exit $OCF_ERR_GENERIC
+fi
+
+case $1 in
+  meta-data)		meta_data
+			exit $OCF_SUCCESS
+			;;
+  status|monitor)	MailToStatus
+			exit $?
+			;;
+  usage)		usage
+			exit $OCF_SUCCESS
+			;;
+  *)			;;
+esac
+
+if 
+  [ -z "$OCF_RESKEY_email" ]
+then
+  ocf_log err "At least 1 Email address has to be given!"
+  exit $OCF_ERR_CONFIGURED
+fi
+
+email=$OCF_RESKEY_email
+subject=$OCF_RESKEY_subject
+
+MailToValidateAll
+
+case $1 in
+  start)		MailToStart
+			;;
+  stop)			MailToStop
+			;;
+  validate-all)		;;
+  *)			usage
+			exit $OCF_ERR_UNIMPLEMENTED
+			;;
+esac
+exit $?
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
new file mode 100644
index 0000000..bc95f89
--- /dev/null
+++ b/heartbeat/Makefile.am
@@ -0,0 +1,147 @@
+# Makefile.am for OCF RAs
+#
+# Author: Sun Jing Dong
+# Copyright (C) 2004 IBM
+#
+# 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		= $(ocf_SCRIPTS) $(ocfcommon_DATA) \
+			  $(common_DATA) $(hb_DATA) $(dtd_DATA) \
+			  README
+
+AM_CPPFLAGS		= -I$(top_srcdir)/include -I$(top_srcdir)/linux-ha
+
+halibdir		= $(libexecdir)/heartbeat
+
+ocfdir		        = $(OCF_RA_DIR_PREFIX)/heartbeat
+
+dtddir			= $(datadir)/$(PACKAGE_NAME)
+dtd_DATA		= ra-api-1.dtd
+
+if USE_IPV6ADDR_AGENT
+ocf_PROGRAMS           = IPv6addr
+else
+ocf_PROGRAMS           =
+endif
+
+if IPV6ADDR_COMPATIBLE
+halib_PROGRAMS         = send_ua
+else
+halib_PROGRAMS         =
+endif
+
+IPv6addr_SOURCES        = IPv6addr.c IPv6addr_utils.c
+send_ua_SOURCES         = send_ua.c IPv6addr_utils.c
+
+IPv6addr_LDADD          = -lplumb $(LIBNETLIBS)
+send_ua_LDADD           = $(LIBNETLIBS)
+
+ocf_SCRIPTS	     =  ClusterMon		\
+			CTDB			\
+			Dummy			\
+		        IPaddr			\
+		        IPaddr2			\
+			anything		\
+			AoEtarget		\
+			apache			\
+			asterisk		\
+			nginx			\
+			AudibleAlarm		\
+			conntrackd		\
+			db2			\
+			dhcpd		\
+			Delay			\
+			eDir88			\
+			EvmsSCC			\
+			Evmsd			\
+			ethmonitor		\
+			exportfs		\
+			Filesystem		\
+			fio			\
+			ids			\
+			iscsi			\
+			ICP			\
+			IPsrcaddr		\
+			iSCSITarget		\
+			iSCSILogicalUnit	\
+			iface-bridge		\
+			iface-vlan		\
+			jboss			\
+			LinuxSCSI		\
+			LVM			\
+			lxc			\
+			MailTo			\
+			ManageRAID		\
+			ManageVE		\
+			mysql			\
+			mysql-proxy		\
+			named			\
+			nfsserver		\
+			oracle			\
+			oralsnr			\
+			pingd			\
+			portblock		\
+			postfix			\
+			pound			\
+			pgsql			\
+			proftpd			\
+			Pure-FTPd		\
+			Raid1			\
+			Route			\
+			rsyncd			\
+			rsyslog			\
+			SAPDatabase		\
+			SAPInstance		\
+			SendArp			\
+			ServeRAID		\
+			slapd			\
+			SphinxSearchDaemon	\
+			Squid			\
+			Stateful		\
+			SysInfo			\
+			scsi2reservation	\
+			sfex			\
+			symlink			\
+			syslog-ng		\
+			tomcat			\
+			VIPArip			\
+			VirtualDomain		\
+			varnish			\
+			vmware			\
+			WAS			\
+			WAS6			\
+			WinPopup		\
+			Xen			\
+			Xinetd			\
+			zabbixserver
+
+ocfcommondir		= $(OCF_LIB_DIR_PREFIX)/heartbeat
+ocfcommon_DATA		= ocf-shellfuncs 	\
+			  ocf-binaries	 	\
+			  ocf-directories 	\
+			  ocf-returncodes 	\
+ 			  ocf-rarun		\
+			  apache-conf.sh 	\
+			  http-mon.sh    	\
+			  sapdb-nosha.sh	\
+			  sapdb.sh		\
+			  ora-common.sh		\
+			  findif.sh
+
+# Legacy locations
+hbdir			= $(sysconfdir)/ha.d
+hb_DATA			= shellfuncs
diff --git a/heartbeat/ManageRAID b/heartbeat/ManageRAID
new file mode 100755
index 0000000..fc43eb1
--- /dev/null
+++ b/heartbeat/ManageRAID
@@ -0,0 +1,384 @@
+#!/bin/bash
+#
+# Name     ManageRAID
+# Author   Matthias Dahl, m.dahl at designassembly.de
+# License  GPL version 2
+#
+# (c) 2006 The Design Assembly GmbH.
+#
+#
+# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+#
+# This resource agent is most likely function complete but not error free. Please
+# consider it BETA quality for the moment until it has proven itself stable...
+#
+# USE AT YOUR OWN RISK.
+#
+# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+#
+#
+# partly based on/inspired by original Heartbeat2 OCF resource agents
+#
+# Description
+#
+# Manages starting, mounting, unmounting, stopping and monitoring of RAID devices
+# which are preconfigured in /etc/conf.d/HB-ManageRAID.
+#
+# 
+# Created  11. Sep 2006
+# Updated  18. Sep 2006
+#
+# rev. 1.00.2
+#
+# Changelog
+#
+# 18/Sep/06 1.00.1 more cleanup
+# 12/Sep/06 1.00.1 add more functionality
+#                  add sanity check for config parameters
+#                  general cleanup all over the place
+# 11/Sep/06 1.00.0 it's alive... muahaha... ALIVE... :-)
+#
+#
+# TODO
+#
+#   - check if at least one disk out of PREFIX_LOCALDISKS is still active
+#     in RAID otherwise consider RAID broken and stop it.
+#
+#     The reason behind this: consider a RAID-1 which contains iSCSI devices
+#     shared over Ethernet which get dynamically added/removed to/from the RAID.
+#     Once all local disks have failed and only those iSCSI disks remain, the RAID
+#     should really stop to prevent bad performance and possible data loss.
+# 
+
+###
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+###
+
+# required utilities
+
+# required files/devices
+RAID_MDSTAT=/proc/mdstat
+
+#
+# check_file()
+#
+check_file ()
+{
+    if [[ ! -e $1 ]]; then
+        ocf_log err "setup problem: file $1 does not exist."
+        exit $OCF_ERR_GENERIC
+    fi
+}
+
+#
+# usage()
+#
+usage()
+{
+	cat <<-EOT
+	usage: $0 {start|stop|status|monitor|validate-all|usage|meta-data}
+	EOT
+}
+
+#
+# meta_data()
+#
+meta_data()
+{
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="ManageRAID">
+  <version>1.00.2</version>
+
+  <longdesc lang="en">
+    Manages starting, stopping and monitoring of RAID devices which
+    are preconfigured in /etc/conf.d/HB-ManageRAID.
+  </longdesc>
+
+  <shortdesc lang="en">Manages RAID devices</shortdesc>
+
+  <parameters>
+    <parameter name="raidname" unique="0" required="1">
+      <longdesc lang="en">
+        Name (case sensitive) of RAID to manage. (preconfigured in /etc/conf.d/HB-ManageRAID)
+      </longdesc>
+      <shortdesc lang="en">RAID name</shortdesc>
+      <content type="string" default="" />
+    </parameter>
+  </parameters>
+
+  <actions>
+    <action name="start" timeout="75" />
+    <action name="stop" timeout="75" />
+    <action name="status" depth="0" timeout="10" interval="10" />
+    <action name="monitor" depth="0" timeout="10" interval="10" />
+    <action name="validate-all" timeout="5" />
+    <action name="meta-data" timeout="5" />
+  </actions>
+</resource-agent>
+END
+}
+
+#
+# start_raid()
+#
+start_raid()
+{
+  declare -i retcode
+
+  status_raid
+  retcode=$?
+  if [[ $retcode == $OCF_SUCCESS ]]; then
+    return $OCF_SUCCESS
+  elif [[ $retcode != $OCF_NOT_RUNNING ]]; then
+    return $retcode
+  fi
+
+  for ldev in ${RAID_LOCALDISKS[@]}; do
+    if [[ ! -b $ldev ]]; then
+      ocf_log err "$ldev is not a (local) block device."
+      return $OCF_ERR_ARGS
+    fi
+  done
+
+  $MDADM -A $RAID_DEVPATH -a yes -u ${!RAID_UUID} ${RAID_LOCALDISKS[@]} &> /dev/null
+  if [[ $? != 0 ]]; then
+    ocf_log err "starting ${!RAID_DEV} with ${RAID_LOCALDISKS[@]} failed."
+    return $OCF_ERR_GENERIC
+  fi
+
+  $MOUNT -o ${!RAID_MOUNTOPTIONS} $RAID_DEVPATH ${!RAID_MOUNTPOINT} &> /dev/null
+  if [[ $? != 0 ]]; then
+    $MDADM -S $RAID_DEVPATH &> /dev/null
+    
+    if [[ $? != 0 ]]; then
+      ocf_log err "mounting ${!RAID_DEV} to ${!RAID_MOUNTPOINT} failed as well as stopping the RAID itself."
+    else
+      ocf_log err "mounting ${!RAID_DEV} to ${!RAID_MOUNTPOINT} failed. RAID stopped again."
+    fi
+
+    return $OCF_ERR_GENERIC
+  fi
+
+  return $OCF_SUCCESS
+}
+
+#
+# stop_raid()
+#
+stop_raid()
+{
+  status_raid
+  if [[ $? == $OCF_NOT_RUNNING ]]; then
+    return $OCF_SUCCESS
+  fi
+
+  $UMOUNT ${!RAID_MOUNTPOINT} &> /dev/null
+  if [[ $? != 0 ]]; then
+    ocf_log err "unmounting ${!RAID_MOUNTPOINT} failed. not stopping ${!RAID_DEV}!"
+    return $OCF_ERR_GENERIC
+  fi
+
+  $MDADM -S $RAID_DEVPATH &> /dev/null
+  if [[ $? != 0 ]]; then
+    ocf_log err "stopping RAID ${!RAID_DEV} failed."
+    return $OCF_ERR_GENERIC
+  fi
+
+  return $OCF_SUCCESS
+}
+
+#
+# status_raid()
+#
+status_raid()
+{ 
+  declare -i retcode_raidcheck
+  declare -i retcode_uuidcheck
+
+  $CAT $RAID_MDSTAT | $GREP -e "${!RAID_DEV}[\ ]*:[\ ]*active" &> /dev/null
+  if [[ $? != 0 ]]; then
+    return $OCF_NOT_RUNNING
+  fi
+ 
+  if [[ ! -e $RAID_DEVPATH ]]; then
+    return $OCF_ERR_GENERIC
+  fi
+
+  $MDADM --detail -t $RAID_DEVPATH &> /dev/null
+  retcode_raidcheck=$?
+  $MDADM --detail -t $RAID_DEVPATH | $GREP -qEe "^[\ ]*UUID[\ ]*:[\ ]*${!RAID_UUID}" &> /dev/null
+  retcode_uuidcheck=$?
+
+  if [[ $retcode_raidcheck > 3 ]]; then
+    ocf_log err "mdadm returned error code $retcode_raidcheck while checking ${!RAID_DEV}."
+    return $OCF_ERR_GENERIC
+  elif [[ $retcode_raidcheck == 3 ]]; then
+    ocf_log err "${!RAID_DEV} has failed."
+    return $OCF_ERR_GENERIC
+  elif [[ $retcode_raidcheck < 3 && $retcode_uuidcheck != 0  ]]; then
+    ocf_log err "active RAID ${!RAID_DEV} and configured UUID (!$RAID_UUID) do not match."
+    return $OCF_ERR_GENERIC
+  fi
+
+  $MOUNT | $GREP -e "$RAID_DEVPATH on ${!RAID_MOUNTPOINT}" &> /dev/null
+  if [[ $? != 0 ]]; then
+    ocf_log err "${!RAID_DEV} seems to be no longer mounted at ${!RAID_MOUNTPOINT}"
+    return $OCF_ERR_GENERIC
+  fi
+
+  return $OCF_SUCCESS
+}    
+
+#
+# validate_all_raid()
+#
+validate_all_raid()
+{
+  #
+  # since all parameters are checked every time ManageRAID is
+  # invoked, there not much more to check...
+  #
+  # status_raid should cover the rest.
+  # 
+  declare -i retcode
+
+  status_ve
+  retcode=$?
+
+  if [[ $retcode != $OCF_SUCCESS && $retcode != $OCF_NOT_RUNNING ]]; then
+    return $retcode
+  fi
+
+  return $OCF_SUCCESS
+}
+
+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
+
+## required configuration
+#
+[ -f /etc/conf.d/HB-ManageRAID ] || {
+	ocf_log err "/etc/conf.d/HB-ManageRAID missing"
+	exit $OCF_ERR_INSTALLED
+}
+. /etc/conf.d/HB-ManageRAID
+#
+##
+
+#
+# check relevant environment variables for sanity and security
+#
+
+declare -i retcode_test
+declare -i retcode_grep
+
+$TEST -z "$OCF_RESKEY_raidname"
+retcode_test=$?
+echo "$OCF_RESKEY_raidname" | $GREP -qEe "^[[:alnum:]\_]+$"
+retcode_grep=$?
+
+if [[ $retcode_test != 1 || $retcode_grep != 0 ]]; then
+  ocf_log err "OCF_RESKEY_raidname not set or invalid."
+  exit $OCF_ERR_ARGS
+fi
+
+RAID_UUID=${OCF_RESKEY_raidname}_UUID
+
+echo ${!RAID_UUID} | $GREP -qEe "^[[:alnum:]]{8}:[[:alnum:]]{8}:[[:alnum:]]{8}:[[:alnum:]]{8}$"
+if [[ $? != 0 ]]; then
+  ocf_log err "${OCF_RESKEY_raidname}_UUID is invalid."
+  exit $OCF_ERR_ARGS
+fi
+
+RAID_DEV=${OCF_RESKEY_raidname}_DEV
+
+echo ${!RAID_DEV} | $GREP -qEe "^md[0-9]+$"
+if [[ $? != 0 ]]; then
+  ocf_log err "${OCF_RESKEY_raidname}_DEV is invalid."
+  exit $OCF_ERR_ARGS
+fi
+
+RAID_DEVPATH=/dev/${!RAID_DEV/md/md\/}
+RAID_MOUNTPOINT=${OCF_RESKEY_raidname}_MOUNTPOINT
+
+echo ${!RAID_MOUNTPOINT} | $GREP -qEe "^[[:alnum:]\/\_\"\ ]+$"
+if [[ $? != 0 ]]; then
+  ocf_log err "${OCF_RESKEY_raidname}_MOUNTPOINT is invalid."
+  exit $OCF_ERR_ARGS
+fi
+
+RAID_MOUNTOPTIONS=${OCF_RESKEY_raidname}_MOUNTOPTIONS
+
+echo ${!RAID_MOUNTOPTIONS} | $GREP -qEe "^[[:alpha:]\,]+$"
+if [[ $? != 0 ]]; then
+  ocf_log err "${OCF_RESKEY_raidname}_MOUNTOPTIONS is invalid."
+  exit $OCF_ERR_ARGS
+fi
+
+RAID_LOCALDISKS=${OCF_RESKEY_raidname}_LOCALDISKS[@]
+RAID_LOCALDISKS=( "${!RAID_LOCALDISKS}" )
+
+if [[ ${#RAID_LOCALDISKS[@]} < 1 ]]; then
+  ocf_log err "you have to specify at least one local disk."
+  exit $OCF_ERR_ARGS
+fi
+
+#
+# check that all relevant utilities are available
+# 
+check_binary $MDADM
+check_binary $MOUNT
+check_binary $UMOUNT
+check_binary $GREP
+check_binary $CAT
+check_binary $TEST
+check_binary echo
+
+
+#
+# check that all relevant devices are available
+#
+check_file $RAID_MDSTAT 
+
+#
+# finally... let's see what we are ordered to do :-)
+#
+case "$1" in
+  start)
+	start_raid
+	;;
+  stop)
+	stop_raid
+	;;
+  status|monitor) 
+	status_raid
+	;;
+  validate-all)
+	validate_all_raid
+	;;
+  *)
+	usage
+	exit $OCF_ERR_UNIMPLEMENTED 
+	;;
+esac
+
+exit $?
+
diff --git a/heartbeat/ManageVE b/heartbeat/ManageVE
new file mode 100755
index 0000000..df0f670
--- /dev/null
+++ b/heartbeat/ManageVE
@@ -0,0 +1,313 @@
+#!/bin/bash
+#
+#	ManageVE OCF RA. Manages OpenVZ Virtual Environments (VEs)
+#
+#   (c) 2006-2010 Matthias Dahl, Florian Haas,
+#                 and Linux-HA contributors
+#
+# 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.
+#
+#
+# This OCF compliant resource agent manages OpenVZ VEs and thus requires
+# a proper OpenVZ installation including a recent vzctl util.
+#
+# rev. 1.00.4
+#
+# Changelog
+#
+# 21/Oct/10 1.00.4 implement migrate_from/migrate_to
+# 12/Sep/06 1.00.3 more cleanup
+# 12/Sep/06 1.00.2 fixed some logic in start_ve
+#                  general cleanup all over the place
+# 11/Sep/06 1.00.1 fixed some typos
+# 07/Sep/06 1.00.0 it's alive... muahaha... ALIVE... :-)
+# 
+
+###
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+###
+
+# required utilities
+VZCTL=/usr/sbin/vzctl
+
+#
+# usage()
+#
+usage()
+{
+	cat <<-EOF
+	usage: $0 {start|stop|status|monitor|migrate_from|migrate_to|validate-all|usage|meta-data}
+	EOF
+}
+
+#
+# meta_data()
+#
+meta_data()
+{
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="ManageVE">
+  <version>1.00.4</version>
+
+  <longdesc lang="en">
+    This OCF compliant resource agent manages OpenVZ VEs and thus requires
+    a proper OpenVZ installation including a recent vzctl util.
+  </longdesc>
+
+  <shortdesc lang="en">Manages an OpenVZ Virtual Environment (VE)</shortdesc>
+
+  <parameters>
+    <parameter name="veid" unique="0" required="1">
+      <longdesc lang="en">
+        OpenVZ ID of virtual environment (see output of vzlist -a for all assigned IDs)
+      </longdesc>
+      <shortdesc lang="en">OpenVZ ID of VE</shortdesc>
+      <content type="integer" default="" />
+    </parameter>
+  </parameters>
+
+  <actions>
+    <action name="start" timeout="75" />
+    <action name="stop" timeout="75" />
+    <action name="status" depth="0" timeout="10" interval="10" />
+    <action name="monitor" depth="0" timeout="10" interval="10" />
+    <action name="migrate_to" timeout="75" />
+    <action name="migrate_from" timeout="75" />
+    <action name="validate-all" timeout="5" />
+    <action name="meta-data" timeout="5" />
+  </actions>
+</resource-agent>
+END
+}
+
+#
+# start_ve()
+#
+# Starts a VE, or simply logs a message if the VE is already running.
+#
+start_ve()
+{
+  if status_ve; then
+	ocf_log info "VE $VEID already running."
+	return $OCF_SUCCESS
+  fi
+
+  ocf_run $VZCTL start $VEID || exit $OCF_ERR_GENERIC
+
+  return $OCF_SUCCESS
+}
+
+#
+# stop_ve()
+#
+# ATTENTION: The following code relies on vzctl's exit codes, especially:
+#
+#   0 : success
+#
+# In case any of those exit codes change, this function will need fixing.
+#
+stop_ve()
+{
+  status_ve
+  if [ $? -eq $OCF_NOT_RUNNING ]; then
+	ocf_log info "VE $VEID already stopped."
+	return $OCF_SUCCESS
+  fi
+
+  ocf_run $VZCTL stop $VEID || exit $OCF_ERR_GENERIC
+
+  return $OCF_SUCCESS
+}
+
+#
+# migrate_to_ve()
+#
+# In the process of a resource migration, checkpoints the VE. For this
+# to work, vzctl must obviously create the dump file in a place which
+# the migration target has access to (an NFS mount, a DRBD device,
+# etc.).
+#
+migrate_to_ve()
+{
+  if ! status_ve; then
+    ocf_log err "VE $VEID is not running, aborting"
+    exit $OCF_ERR_GENERIC
+  fi
+  ocf_run $VZCTL chkpnt $VEID || exit $OCF_ERR_GENERIC
+  return $OCF_SUCCESS
+}
+
+#
+# migrate_to_ve()
+#
+# In the process of a resource migration, restores the VE. For this to
+# work, vzctl must obviously have access to the dump file which was
+# created on the migration source (on an NFS mount, a DRBD device,
+# etc.).
+#
+migrate_from_ve()
+{
+  ocf_run $VZCTL restore $VEID || exit $OCF_ERR_GENERIC
+  return $OCF_SUCCESS
+}
+
+#
+# status_ve()
+#
+# ATTENTION: The following code relies on vzctl's status output. The fifth
+# column is interpreted as the VE status (either up or down).
+#
+# In case the output format should change, this function will need fixing.
+#
+status_ve()
+{ 
+  declare -i retcode
+
+  veexists=`$VZCTL status $VEID 2>/dev/null | $AWK '{print $3}'`
+  vestatus=`$VZCTL status $VEID 2>/dev/null | $AWK '{print $5}'`
+  retcode=$?
+
+  if [[ $retcode != 0 ]]; then
+    # log error only if expected to find running
+    if [ "$__OCF_ACTION" = "monitor" ] && ! ocf_is_probe; then
+      ocf_log err "vzctl status $VEID returned: $retcode"
+    fi
+    exit $OCF_ERR_GENERIC
+  fi
+
+  if [[ $veexists != "exist" ]]; then
+    ocf_log err "vzctl status $VEID returned: $VEID does not exist."
+    return $OCF_NOT_RUNNING
+  fi
+
+  case "$vestatus" in
+    running)
+        return $OCF_SUCCESS
+        ;;
+    down)
+	return $OCF_NOT_RUNNING
+        ;;
+    *)
+	ocf_log err "vzctl status $VEID, wrong output format. (5th column: $vestatus)"
+	exit $OCF_ERR_GENERIC
+        ;;
+  esac
+}    
+
+#
+# validate_all_ve()
+#
+# ATTENTION: The following code relies on vzctl's status output. The fifth
+# column is interpreted as the VE status (either up or down).
+#
+# In case the output format should change, this function will need fixing.
+#
+validate_all_ve()
+{
+  declare -i retcode
+
+  # VEID should be a valid VE
+  `status_ve`
+  retcode=$?
+
+  if [[ $retcode != $OCF_SUCCESS && $retcode != $OCF_NOT_RUNNING ]]; then
+    return $retcode
+  fi
+
+  return $OCF_SUCCESS
+}
+	
+
+if [[ $# != 1 ]]; then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+case "$1" in
+  meta-data)
+	meta_data
+	exit $OCF_SUCCESS
+	;;
+  usage) 
+	usage
+	exit $OCF_SUCCESS
+	;;
+  *)
+	;;
+esac
+
+#
+# check relevant environment variables for sanity and security
+#
+
+# empty string?
+`test -z "$OCF_RESKEY_veid"`
+
+declare -i veidtest1=$?
+
+# really a number?
+`echo "$OCF_RESKEY_veid" | egrep -q '^[[:digit:]]+$'`
+
+if [[ $veidtest1 != 1 || $? != 0 ]]; then
+  ocf_log err "OCF_RESKEY_veid not set or not a number."
+  exit $OCF_ERR_ARGS
+fi
+
+declare -i VEID=$OCF_RESKEY_veid
+
+#
+# check that all relevant utilities are available
+# 
+check_binary $VZCTL
+check_binary $AWK
+
+#
+# finally... let's see what we are ordered to do :-)
+#
+case "$1" in
+  start)
+	start_ve
+	;;
+  stop)
+	stop_ve
+	;;
+  status|monitor) 
+	status_ve
+	;;
+  migrate_to)
+    migrate_to_ve
+    ;;
+  migrate_from)
+    migrate_from_ve
+    ;;
+  validate-all)
+	validate_all_ve
+	;;
+  *)
+	usage
+	exit $OCF_ERR_UNIMPLEMENTED 
+	;;
+esac
+
+exit $?
+
diff --git a/heartbeat/Pure-FTPd b/heartbeat/Pure-FTPd
new file mode 100755
index 0000000..b5fe90e
--- /dev/null
+++ b/heartbeat/Pure-FTPd
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# Resource script for Pure-FTPd
+#
+# Description:  Manages Pure-FTPd as an OCF resource in
+#               an Active-Passive High Availability setup.
+#
+# Author:       Rajat Upadhyaya <urajat at novell.com> : Pure-FTPd script
+# Author:       Raoul Bhatia <r.bhatia at ipax.at>     : Minor Cleanup. Added Debian GNU/Linux Support
+# License:      GNU General Public License (GPL)
+#
+#
+#       usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+#
+#       The "start" arg starts Pure-FTPd.
+#
+#       The "stop" arg stops it.
+#
+# OCF parameters:
+#  OCF_RESKEY_script
+#  OCF_RESKEY_conffile
+#  OCF_RESKEY_daemon_type
+#  OCF_RESKEY_pidfile
+#
+##########################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+: ${OCF_RESKEY_script="/sbin/pure-config.pl"}
+script_basename=`basename $OCF_RESKEY_script`
+: ${OCF_RESKEY_conffile="/etc/pure-ftpd/pure-ftpd.conf"}
+: ${OCF_RESKEY_daemon_type=""}
+: ${OCF_RESKEY_pidfile="${HA_RSCTMP}/pure-ftpd-${OCF_RESOURCE_INSTANCE}.pid"}
+USAGE="Usage: $0 {start|stop|status|monitor|validate-all|meta-data}";
+
+##########################################################################
+
+usage() {
+    echo $USAGE >&2
+}
+
+meta_data() {
+    cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Pure-FTPd">
+<version>1.0</version>
+<longdesc lang="en">
+This script manages Pure-FTPd in an Active-Passive setup
+</longdesc>
+<shortdesc lang="en">Manages a Pure-FTPd FTP server instance</shortdesc>
+
+<parameters>
+
+<parameter name="script" unique="1" required="0">
+<longdesc lang="en">
+The full path to the Pure-FTPd startup script.
+For example, "/sbin/pure-config.pl"
+</longdesc>
+<shortdesc lang="en">Script name with full path</shortdesc>
+<content type="string" default="/sbin/pure-config.pl" />
+</parameter>
+
+<parameter name="conffile" unique="1" required="0">
+<longdesc lang="en">
+The Pure-FTPd configuration file name with full path.
+For example, "/etc/pure-ftpd/pure-ftpd.conf"
+</longdesc>
+<shortdesc lang="en">Configuration file name with full path</shortdesc>
+<content type="string" default="/etc/pure-ftpd/pure-ftpd.conf" />
+</parameter>
+
+<parameter name="daemon_type" unique="1" required="0">
+<longdesc lang="en">
+The Pure-FTPd daemon to be called by pure-ftpd-wrapper.
+Valid options are "" for pure-ftpd, "mysql" for pure-ftpd-mysql,
+"postgresql" for pure-ftpd-postgresql and "ldap" for pure-ftpd-ldap
+</longdesc>
+<shortdesc lang="en">Configuration file name with full path</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="pidfile" unique="0">
+<longdesc lang="en">PID file</longdesc>
+<shortdesc lang="en">PID file</shortdesc>
+<content type="string" default="${HA_RSCTMP}/pure-ftpd-${OCF_RESOURCE_INSTANCE}.pid" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" depth="0"  timeout="20s" interval="60s" />
+<action name="validate-all"  timeout="20s" />
+<action name="meta-data"  timeout="5s" />
+</actions>
+</resource-agent>
+END
+        exit $OCF_SUCCESS
+}
+
+isRunning()
+{
+        kill -s 0 "$1" > /dev/null
+}
+
+PureFTPd_status()
+{
+    if [ -f $OCF_RESKEY_pidfile ]
+    then
+    # Pure-FTPd is probably running
+        PID=`head -n 1 $OCF_RESKEY_pidfile`
+        if [ ! -z $PID ] ; then
+            isRunning "$PID" && [ `ps -p $PID | grep pure-ftpd | wc -l` -eq 1 ]
+            return $?
+        fi
+    fi
+
+    # Pure-FTPd is not running
+    false
+}
+
+PureFTPd_start()
+{
+    local pid_dir
+
+    #
+    # make a few checks and start Pure-FTPd
+    #
+    if ocf_is_root ; then : ; else
+        ocf_log err "You must be root."
+        exit $OCF_ERR_PERM
+    fi
+
+    # if Pure-FTPd is running return success
+
+    if PureFTPd_status ; then
+        exit $OCF_SUCCESS
+    fi
+
+    # check that the Pure-FTPd script exists and can be executed
+    if [ ! -x "$OCF_RESKEY_script" ]; then
+        ocf_log err "Pure-FTPd script '$OCF_RESKEY_script' does not exist or cannot be executed"
+        exit $OCF_ERR_GENERIC
+    fi
+
+    # make sure that the pid directory exists
+    pid_dir=`dirname $OCF_RESKEY_pidfile`
+    if [ ! -d $pid_dir ] ; then
+        ocf_log info "Creating PID directory '$pid_dir'."
+        mkdir -p $pid_dir
+    fi
+
+    # test for pure-ftpd-wrapper (e.g. Debian GNU/Linux Systems)
+    if [ "$script_basename" = "pure-ftpd-wrapper" ]; then
+        # pure-ftpd-wrapper expects STANDALONE_OR_INETD to be set to standalone
+        STANDALONE_OR_INETD=standalone $OCF_RESKEY_script $OCF_RESKEY_daemon_type
+    else
+        # check that the Pure-FTPd config file exist
+        if [ ! -f "$OCF_RESKEY_conffile" ]; then
+            ocf_log err "Pure_FTPd config file '$OCF_RESKEY_conffile' does not exist"
+            exit $OCF_ERR_GENERIC
+        fi
+
+        $OCF_RESKEY_script $OCF_RESKEY_conffile -g $OCF_RESKEY_pidfile
+    fi
+
+    if [ $? -ne 0 ]; then
+        ocf_log info "Pure-FTPd returned error" $?
+        exit $OCF_ERR_GENERIC
+    fi
+
+    exit $OCF_SUCCESS
+}
+
+
+PureFTPd_stop()
+{
+    if PureFTPd_status ; then
+        PID=`head -n 1 $OCF_RESKEY_pidfile`
+        if [ ! -z $PID ] ; then
+            kill $PID
+        fi
+    fi
+
+    exit $OCF_SUCCESS
+}
+
+PureFTPd_monitor()
+{
+    if PureFTPd_status ; then
+        return $OCF_SUCCESS
+    fi
+
+    return $OCF_NOT_RUNNING
+}
+
+PureFTPd_validate_all()
+{
+    return $OCF_SUCCESS
+}
+
+#
+# Main
+#
+
+if [ $# -ne 1 ]
+then
+    usage
+    exit $OCF_ERR_ARGS
+fi
+
+case $1 in
+    start)      PureFTPd_start
+                ;;
+
+    stop)       PureFTPd_stop
+                ;;
+
+    status)     if PureFTPd_status
+                then
+                    ocf_log info "Pure-FTPd is running"
+                    exit $OCF_SUCCESS
+                else
+                    ocf_log info "Pure-FTPd is stopped"
+                    exit $OCF_NOT_RUNNING
+                fi
+                ;;
+
+    monitor)    PureFTPd_monitor
+                exit $?
+                ;;
+
+    validate-all)   PureFTPd_validate_all
+                    exit $?
+                    ;;
+
+    meta-data)  meta_data
+                ;;
+
+    usage)      usage
+                exit $OCF_SUCCESS
+                ;;
+
+    *)          usage
+                exit $OCF_ERR_UNIMPLEMENTED
+                ;;
+esac
diff --git a/heartbeat/README b/heartbeat/README
new file mode 100644
index 0000000..aaaff3a
--- /dev/null
+++ b/heartbeat/README
@@ -0,0 +1,44 @@
+The OCF RA shared code directory
+
+If an RA is too big to be comfortably maintained, split it into
+several source files. Obviosuly, if two or more RAs share some
+code, move that code out to a file which can be shared.
+
+These files will be installed in $OCF_ROOT/lib/heartbeat with
+permissions 644.
+
+Naming practice
+
+Use names such as <RA>.sh or <RA>-check.sh or anything-else.sh
+where "anything-else" should be related to both the RA and the
+code it contains. By adding extension (.sh) it is going to be
+easier to notice that these files are not complete resource
+agents.
+
+For instance, oracle and oralsnr RA can both use code in
+ora-common.sh.
+
+Of course, if the RA is implemented in another programming
+language, use the appropriate extension.
+
+RA tracing
+
+RA tracing may be turned on by setting OCF_TRACE_RA. The trace
+output will be saved to OCF_TRACE_FILE, if set, or by default to
+
+  $HA_VARLIB/trace_ra/<type>/<id>.<action>.<timestamp>
+
+e.g. $HA_VARLIB/trace_ra/oracle/db.start.2012-11-27.08:37:08
+
+HA_VARLIB is typically set to /var/lib/heartbeat.
+
+OCF_TRACE_FILE can be set to a path or file descriptor:
+
+- FD (small integer [3-9]) in that case it is up to the callers
+  to capture output; the FD _must_ be open for writing
+
+- absolute path
+
+NB: FD 9 may be used for tracing with bash >= v4 in case
+OCF_TRACE_FILE is set to a path.
+
diff --git a/heartbeat/Raid1 b/heartbeat/Raid1
new file mode 100755
index 0000000..4460ca1
--- /dev/null
+++ b/heartbeat/Raid1
@@ -0,0 +1,556 @@
+#!/bin/sh
+#
+#
+# License:      GNU General Public License (GPL)
+# Support:      linux-ha at lists.linux-ha.org
+# 
+# Raid1
+#      Description: Manages a Linux software RAID device on a shared storage medium.
+#  Original Author: Eric Z. Ayers (eric.ayers at compgen.com)
+# Original Release: 25 Oct 2000
+#     RAID patches: http://people.redhat.com/mingo/raid-patches/
+# Word to the Wise: http://lwn.net/2000/0810/a/raid-faq.php3
+#  Sympathetic Ear: mailto:linux-raid at vger.kernel.org
+#
+# usage: $0 {start|stop|status|monitor|validate-all|usage|meta-data}
+#
+#
+# EXAMPLE config file /etc/raidtab.md0
+# This file must exist on both machines!
+#
+#  raiddev		    /dev/md0
+#  raid-level		    1
+#  nr-raid-disks	    2
+#  chunk-size		    64k
+#  persistent-superblock    1
+#  #nr-spare-disks	    0
+#    device	    /dev/sda1
+#    raid-disk     0
+#    device	    /dev/sdb1
+#    raid-disk     1
+#
+# EXAMPLE config file /etc/mdadm.conf (for more info:man mdadm.conf)
+#
+#  DEVICE /dev/sdb1 /dev/sdc1 
+#  ARRAY /dev/md0 UUID=4a865b55:ba27ef8d:29cd5701:6fb42799
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+usage() {
+	cat <<-EOT
+	usage: $0 {start|stop|status|monitor|validate-all|usage|meta-data}
+	EOT
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Raid1">
+<version>1.0</version>
+
+<longdesc lang="en">
+This resource agent manages Linux software RAID (MD) devices on
+a shared storage medium. It uses mdadm(8) to start, stop, and
+monitor the MD devices. Raidtools are supported, but deprecated.
+See https://raid.wiki.kernel.org/index.php/Linux_Raid for more
+information.
+</longdesc>
+<shortdesc lang="en">Manages Linux software RAID (MD) devices on shared storage</shortdesc>
+
+<parameters>
+<parameter name="raidconf" unique="0" required="1">
+<longdesc lang="en">
+The RAID configuration file, e.g. /etc/mdadm.conf.
+</longdesc>
+<shortdesc lang="en">RAID config file</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="raiddev" unique="0" required="1">
+<longdesc lang="en">
+One or more block devices to use, space separated. Alternatively,
+set to "auto" to manage all devices specified in raidconf.
+</longdesc>
+<shortdesc lang="en">block device</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="homehost" unique="0" required="0">
+<longdesc lang="en">
+The value for the homehost directive; this is an mdadm feature to
+protect RAIDs against being activated by accident. It is recommended to
+create RAIDs managed by the cluster with "homehost" set to a special
+value, so they are not accidentially auto-assembled by nodes not
+supposed to own them.
+</longdesc>
+<shortdesc lang="en">Homehost for mdadm</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="force_stop" unique="0" required="0">
+<longdesc lang="en">
+If processes or kernel threads are using the array, it cannot be
+stopped. We will try to stop processes, first by sending TERM and
+then, if that doesn't help in $PROC_CLEANUP_TIME seconds, using KILL.
+The lsof(8) program is required to get the list of array users.
+Of course, the kernel threads cannot be stopped this way.
+If the processes are critical for data integrity, then set this
+parameter to false. Note that in that case the stop operation
+will fail and the node will be fenced.
+</longdesc>
+<shortdesc lang="en">force stop processes using the array</shortdesc>
+<content type="boolean" default="true" />
+</parameter>
+
+<parameter name="udev" unique="0" required="0">
+<longdesc lang="en">
+Wait until udevd creates a device in the start operation. On a
+normally loaded host this should happen quickly, but you may be
+unlucky. If you are not using udev set this to "no".
+</longdesc>
+<shortdesc lang="en">udev</shortdesc>
+<content type="boolean" default="true" />
+</parameter>
+
+<parameter name="force_clones">
+<longdesc lang="en">
+Activating the same md RAID array on multiple nodes at the same time
+will result in data corruption and thus is forbidden by default.
+
+A safe example could be an array that is only named identically across
+all nodes, but is in fact distinct.
+
+Only set this to "true" if you know what you are doing!
+</longdesc>
+<shortdesc lang="en">force ability to run as a clone</shortdesc>
+<content type="boolean" default="false" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="20s" />
+<action name="stop" timeout="20s" />
+<action name="status" depth="0" timeout="20s" interval="10" />
+<action name="monitor" depth="0" timeout="20s" interval="10" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+udev_settle() {
+	if ocf_is_true $WAIT_FOR_UDEV; then
+		udevadm settle $*
+	fi
+}
+list_conf_arrays() {
+	test -f $RAIDCONF || {
+		ocf_log err "$RAIDCONF gone missing!"
+		exit $OCF_ERR_GENERIC
+	}
+	grep ^ARRAY $RAIDCONF | awk '{print $2}'
+}
+forall() {
+	local func=$1
+	local checkall=$2
+	local mddev rc=0
+	for mddev in $RAIDDEVS; do
+		$func $mddev
+		rc=$(($rc | $?))
+		[ "$checkall" = all ] && continue
+		[ $rc -ne 0 ] && return $rc
+	done
+	return $rc
+}
+are_arrays_stopped() {
+	local rc mddev
+	for mddev in $RAIDDEVS; do
+		raid1_monitor_one $mddev
+		rc=$?
+		[ $rc -ne $OCF_NOT_RUNNING ] && break
+	done
+	test $rc -eq $OCF_NOT_RUNNING
+}
+
+md_assemble() {
+	local mddev=$1
+	$MDADM --assemble $mddev --config=$RAIDCONF $MDADM_HOMEHOST
+	udev_settle --exit-if-exists=$mddev
+}
+#
+# START: Start up the RAID device
+#
+raid1_start() {
+	local rc
+	raid1_monitor
+	rc=$?
+	if [ $rc -eq $OCF_SUCCESS ]; then
+		# md already online, nothing to do.
+		return $OCF_SUCCESS
+	fi
+	if [ $rc -ne $OCF_NOT_RUNNING ]; then
+		# If the array is in a broken state, this agent doesn't
+		# know how to repair that.
+		ocf_log err "$RAIDDEVS in a broken state; cannot start (rc=$rc)"
+		return $OCF_ERR_GENERIC
+	fi
+
+	if [ $HAVE_RAIDTOOLS = "true" ]; then
+	    # Run raidstart to start up the RAID array
+	    $RAIDSTART --configfile $RAIDCONF $MDDEV
+	else
+		forall md_assemble all
+	fi
+
+	raid1_monitor
+	if [ $? -eq $OCF_SUCCESS ]; then
+	    return $OCF_SUCCESS
+	else
+	    ocf_log err "Couldn't start RAID for $RAIDDEVS"
+	    return $OCF_ERR_GENERIC
+	fi
+}
+
+#
+# STOP: stop the RAID device
+#
+mark_readonly() {
+	local mddev=$1
+	local rc
+	ocf_log info "Attempting to mark array $mddev readonly"
+	$MDADM --readonly $mddev --config=$RAIDCONF
+	rc=$?
+	if [ $rc -ne 0 ]; then
+		ocf_log err "Failed to set $mddev readonly (rc=$rc)"
+	fi
+	return $rc
+}
+mknod_raid1_stop() {
+	# first create a block device file, then try to stop the
+	# array
+	local rc n tmp_block_file
+	n=`echo $1 | sed 's/[^0-9]*//'`
+	if ! ocf_is_decimal "$n"; then
+		ocf_log warn "could not get the minor device number from $1"
+		return 1
+	fi
+	tmp_block_file="$HA_RSCTMP/${OCF_RESOURCE_INSTANCE}-`basename $1`"
+	rm -f $tmp_block_file
+	ocf_log info "block device file $1 missing, creating one in order to stop the array"
+	mknod $tmp_block_file b 9 $n
+	$MDADM --stop $tmp_block_file --config=$RAIDCONF --wait-clean -W
+	rc=$?
+	rm -f $tmp_block_file
+	return $rc
+}
+raid1_stop_one() {
+	ocf_log info "Stopping array $1"
+	if [ -b "$1" ]; then
+		$MDADM --stop $1 --config=$RAIDCONF --wait-clean -W &&
+			return
+	else
+		# newer mdadm releases can stop arrays when given the
+		# basename; try that first
+		$MDADM --stop `basename $1` --config=$RAIDCONF --wait-clean -W &&
+			return
+		# otherwise create a block device file
+		mknod_raid1_stop $1
+	fi
+}
+get_users_pids() {
+	local mddev=$1
+	local outp l
+	ocf_log debug "running lsof to list $mddev users..."
+	outp=`lsof $mddev | tail -n +2`
+	echo "$outp" | awk '{print $2}' | sort -u
+	echo "$outp" | while read l; do
+		ocf_log warn "$l"
+	done
+}
+stop_raid_users() {
+	local pids
+	pids=`forall get_users_pids all | sort -u`
+	if [ -z "$pids" ]; then
+		ocf_log warn "lsof reported no users holding arrays"
+		return 2
+	else
+		ocf_stop_processes TERM $PROC_CLEANUP_TIME $pids
+	fi
+}
+stop_arrays() {
+	if [ $HAVE_RAIDTOOLS = "true" ]; then
+		$RAIDSTOP --configfile $RAIDCONF $MDDEV
+	else
+		forall raid1_stop_one all
+	fi
+}
+showusers() {
+	local disk
+	for disk; do
+		if have_binary lsof; then
+			ocf_log info "running lsof to list $disk users..."
+			ocf_run -warn lsof $disk
+		fi
+		if [ -d /sys/block/$disk/holders ]; then
+			ocf_log info "ls -l /sys/block/$disk/holders"
+			ocf_run -warn ls -l /sys/block/$disk/holders
+		fi
+	done
+}
+raid1_stop() {
+	local rc
+	# See if the MD device is already cleanly stopped:
+	if are_arrays_stopped; then
+		return $OCF_SUCCESS
+	fi
+
+	# Turn off raid
+	if ! stop_arrays; then
+		if ocf_is_true $FORCESTOP; then
+			if have_binary lsof; then
+				stop_raid_users
+				case $? in
+				2) false;;
+				*) stop_arrays;;
+				esac
+			else
+				ocf_log warn "install lsof(8) to list users holding the disk"
+				false
+			fi
+		else
+			false
+		fi
+	fi
+	rc=$?
+
+	if [ $rc -ne 0 ]; then
+		ocf_log warn "Couldn't stop RAID for $RAIDDEVS (rc=$rc)"
+ 		showusers $RAIDDEVS
+		if [ $HAVE_RAIDTOOLS != "true" ]; then
+			forall mark_readonly all
+		fi
+		return $OCF_ERR_GENERIC
+	fi
+
+	if are_arrays_stopped; then
+		return $OCF_SUCCESS
+	fi
+
+	ocf_log err "RAID $RAIDDEVS still active after stop command!"
+	return $OCF_ERR_GENERIC
+}
+
+#
+# monitor: a less noisy status
+#
+raid1_monitor_one() {
+	local mddev=$1
+	local md=`echo $mddev | sed 's,/dev/,,'`
+	local rc
+	local TRY_READD=0
+	local pbsize
+	# check if the md device exists first
+	# but not if we are in the stop operation
+	# device existence is important only for the running arrays
+	if [ "$__OCF_ACTION" != "stop" -a ! -b $mddev ]; then
+		ocf_log info "$mddev is not a block device"
+		return $OCF_NOT_RUNNING
+	fi
+	if ! grep -e "^$md[ \t:]" /proc/mdstat >/dev/null ; then
+		ocf_log info "$md not found in /proc/mdstat"
+		return $OCF_NOT_RUNNING
+	fi
+	if [ $HAVE_RAIDTOOLS != "true" ]; then
+		$MDADM --detail --test $mddev >/dev/null 2>&1 ; rc=$?
+		case $rc in
+		0)	;;
+		1)	ocf_log warn "$mddev has at least one failed device."
+			TRY_READD=1
+			;;
+		2)	ocf_log err "$mddev has failed."
+			return $OCF_ERR_GENERIC
+			;;
+		4)	ocf_log err "mdadm failed on $mddev."
+			return $OCF_ERR_GENERIC
+			;;
+		*)	ocf_log err "mdadm returned an unknown result ($rc)."
+			return $OCF_ERR_GENERIC
+			;;
+		esac
+	fi
+	if [ "$__OCF_ACTION" = "monitor" -a "$OCF_RESKEY_CRM_meta_interval" != 0 \
+		-a $TRY_READD -eq 1 -a $OCF_CHECK_LEVEL -gt 0 ]; then
+		ocf_log info "Attempting recovery sequence to re-add devices on $mddev:"
+		$MDADM $mddev --fail detached 
+		$MDADM $mddev --remove failed 
+		$MDADM $mddev --re-add missing
+		# TODO: At this stage, there's nothing to actually do
+		# here. Either this worked or it did not.
+	fi
+
+	pbsize=`(blockdev --getpbsz $mddev || stat -c "%o" $mddev) 2>/dev/null`
+	if [ -z "$pbsize" ]; then
+		ocf_log warn "both blockdev and stat could not get the block size (will use 4k)"
+		pbsize=4096 # try with 4k
+	fi
+	if ! dd if=$mddev count=1 bs=$pbsize of=/dev/null \
+	     iflag=direct >/dev/null 2>&1 ; then
+		ocf_log err "$mddev: I/O error on read"
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+raid1_monitor() {
+	forall raid1_monitor_one
+}
+
+#
+# STATUS: is the raid device online or offline?
+#
+raid1_status() {
+	# See if the MD device is online
+	local rc
+	raid1_monitor
+	rc=$?
+	if [ $rc -ne $OCF_SUCCESS ]; then
+	    echo "stopped"
+	else
+	    echo "running"
+	fi
+	return $rc
+}
+
+raid1_validate_all() {
+    return $OCF_SUCCESS
+}
+
+PROC_CLEANUP_TIME=3
+
+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
+
+RAIDCONF="$OCF_RESKEY_raidconf"
+MDDEV="$OCF_RESKEY_raiddev"
+FORCESTOP="${OCF_RESKEY_force_stop:-1}"
+WAIT_FOR_UDEV="${OCF_RESKEY_udev:-1}"
+
+if [ -z "$RAIDCONF" ] ; then
+	ocf_log err "Please set OCF_RESKEY_raidconf!"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+if [ ! -r "$RAIDCONF" ] ; then
+	ocf_log err "Configuration file [$RAIDCONF] does not exist, or can not be opend!"
+	exit $OCF_ERR_INSTALLED
+fi
+
+if [ -z "$MDDEV" ] ; then
+	ocf_log err "Please set OCF_RESKEY_raiddev to the Raid device you want to control!"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+if ocf_is_clone && ! ocf_is_true "$OCF_RESKEY_force_clones"; then
+	ocf_log err "md RAID arrays are NOT safe to run as a clone!"
+	ocf_log err "Please read the comment on the force_clones parameter."
+	exit $OCF_ERR_CONFIGURED
+fi
+
+if ocf_is_true $WAIT_FOR_UDEV && ! have_binary udevadm; then
+	if [ "$__OCF_ACTION" = "start" ]; then
+		ocf_log warn "either install udevadm or set udev to false"
+		ocf_log info "setting udev to false!"
+	fi
+	WAIT_FOR_UDEV=0
+fi
+
+if ! ocf_is_true $WAIT_FOR_UDEV; then
+	export MDADM_NO_UDEV=1
+fi
+
+if ocf_is_true $FORCESTOP && ! have_binary lsof; then
+	ocf_log warn "Please install lsof(8), we may need it when stopping Raid device! Now continuing anyway ..."
+fi
+
+HAVE_RAIDTOOLS=false
+if have_binary $MDADM >/dev/null 2>&1 ; then
+  if [ -n "$OCF_RESKEY_homehost" ]; then
+  	MDADM_HOMEHOST="--homehost=${OCF_RESKEY_homehost}"
+  else
+  	MDADM_HOMEHOST=""
+  fi
+else
+  check_binary $RAIDSTART
+  HAVE_RAIDTOOLS=true
+fi
+
+if [ $HAVE_RAIDTOOLS = true ]; then
+	if [ "$MDDEV" = "auto" ]; then
+		ocf_log err "autoconf supported only with mdadm!"
+		exit $OCF_ERR_INSTALLED
+	elif [ `echo $MDDEV|wc -w` -gt 1 ]; then
+		ocf_log err "multiple devices supported only with mdadm!"
+		exit $OCF_ERR_INSTALLED
+	fi
+fi
+
+if [ "$MDDEV" = "auto" ]; then
+	RAIDDEVS=`list_conf_arrays`
+else
+	RAIDDEVS="$MDDEV"
+fi
+
+# At this stage,
+# [ $HAVE_RAIDTOOLS = false ] <=> we have $MDADM,
+# otherwise we have raidtools (raidstart and raidstop)
+
+# Look for how we are called 
+case "$1" in
+  start)
+	raid1_start
+	;;
+  stop)
+	raid1_stop
+	;;
+  status) 
+	raid1_status
+	;;
+  monitor) 
+	raid1_monitor
+	;;
+  validate-all)
+	raid1_validate_all
+	;;
+  *)
+	usage
+	exit $OCF_ERR_UNIMPLEMENTED 
+	;;
+esac
+
+exit $?
diff --git a/heartbeat/Route b/heartbeat/Route
new file mode 100755
index 0000000..9a49a26
--- /dev/null
+++ b/heartbeat/Route
@@ -0,0 +1,313 @@
+#!/bin/sh
+#
+#	Route OCF RA. Enables and disables network routes.
+#
+#   (c) 2008-2010 Florian Haas, Dejan Muhamedagic,
+#                 and Linux-HA contributors
+#
+# 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.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Route" version="0.1">
+<version>1.0</version>
+
+<longdesc lang="en">
+Enables and disables network routes.
+
+Supports host and net routes, routes via a gateway address,
+and routes using specific source addresses.
+
+This resource agent is useful if a node's routing table
+needs to be manipulated based on node role assignment.
+
+Consider the following example use case:
+
+  -  One cluster node serves as an IPsec tunnel endpoint.
+
+  -  All other nodes use the IPsec tunnel to reach hosts
+     in a specific remote network.
+
+Then, here is how you would implement this scheme making use
+of the Route resource agent:
+
+  -  Configure an ipsec LSB resource.
+
+  -  Configure a cloned Route OCF resource.
+
+  -  Create an order constraint to ensure 
+     that ipsec is started before Route.
+
+  -  Create a colocation constraint between the
+     ipsec and Route resources, to make sure no instance
+     of your cloned Route resource is started on the
+     tunnel endpoint itself.
+</longdesc>
+<shortdesc lang="en">Manages network routes</shortdesc>
+
+<parameters>
+
+<parameter name="destination" unique="1" required="1">
+<longdesc lang="en">
+The destination network (or host) to be configured for the route. 
+Specify the netmask suffix in CIDR notation (e.g. "/24").
+If no suffix is given, a host route will be created.
+Specify "0.0.0.0/0" or "default" if you want this resource to set 
+the system default route.
+</longdesc>
+<shortdesc lang="en">Destination network</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="device" unique="1">
+<longdesc lang="en">
+The outgoing network device to use for this route.
+</longdesc>
+<shortdesc lang="en">Outgoing network device</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="gateway" unique="1">
+<longdesc lang="en">
+The gateway IP address to use for this route.
+</longdesc>
+<shortdesc lang="en">Gateway IP address</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="source" unique="1">
+<longdesc lang="en">
+The source IP address to be configured for the route.
+</longdesc>
+<shortdesc lang="en">Source IP address</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="table" unique="0">
+<longdesc lang="en">
+The routing table to be configured for the route.
+</longdesc>
+<shortdesc lang="en">Routing table</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="20" />
+<action name="stop"         timeout="20" />
+<action name="monitor"      timeout="20" interval="10" 
+                            depth="0"/>
+<action name="reload"       timeout="20" />
+<action name="meta-data"    timeout="5" />
+<action name="validate-all" timeout="20" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+create_route_spec() {
+    # Creates a route specification for use by "ip route (add|del|show)"
+    route_spec="to ${OCF_RESKEY_destination}"
+    if [ -n "${OCF_RESKEY_device}" ]; then
+	route_spec="${route_spec} dev ${OCF_RESKEY_device}"
+    fi
+    if [ -n "${OCF_RESKEY_gateway}" ]; then
+	route_spec="${route_spec} via ${OCF_RESKEY_gateway}"
+    fi
+    if [ -n "${OCF_RESKEY_source}" ]; then
+	route_spec="${route_spec} src ${OCF_RESKEY_source}"
+    fi
+    if [ -n "${OCF_RESKEY_table}" ]; then
+	route_spec="${route_spec} table ${OCF_RESKEY_table}"
+    fi
+    echo "$route_spec"
+}
+
+route_usage() {
+	cat <<END
+usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+route_start() {
+    route_status
+    status=$?
+    if [ $status -eq $OCF_SUCCESS ]; then
+	ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : already started."
+	return $OCF_SUCCESS
+    fi
+    route_spec="$(create_route_spec)"
+    if ip route add $route_spec; then
+	ocf_log info "${OCF_RESOURCE_INSTANCE} Added network route: $route_spec"
+	return $OCF_SUCCESS
+    else
+	ocf_log error "${OCF_RESOURCE_INSTANCE} Failed to add network route: $route_spec"
+    fi
+    return $OCF_ERR_GENERIC
+}
+
+route_stop() {
+    route_status
+    status=$?
+    case $status in
+	$OCF_SUCCESS)
+	    route_spec="$(create_route_spec)"
+	    if ip route del $route_spec; then
+		ocf_log info "${OCF_RESOURCE_INSTANCE} Removed network route: $route_spec"
+		return $OCF_SUCCESS
+	    else
+		ocf_log error "${OCF_RESOURCE_INSTANCE} Failed to remove network route: $route_spec"
+	    fi
+	    ;;
+	$OCF_NOT_RUNNING)
+	    ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : already stopped."
+	    return $OCF_SUCCESS
+	    ;;
+    esac
+    return $OCF_ERR_GENERIC
+}
+
+route_status() {
+    show_output="$(ip $addr_family route show $(create_route_spec) 2>/dev/null)"
+    if [ $? -eq 0 ]; then
+	if [ -n "$show_output" ]; then
+	    # "ip route show" returned zero, and produced output on
+	    # stdout. That is what we expect.
+	    return $OCF_SUCCESS
+	else
+	    # "ip route show" returned zero, but produced no
+	    # output on stdout. Assume the route was cleanly
+	    # unconfigured.
+	    return $OCF_NOT_RUNNING
+	fi
+    else
+	# "ip route show" returned an error code. Assume something
+	# went wrong.
+	return $OCF_ERR_GENERIC
+    fi
+}
+
+route_validate() {
+    # If we're running as a clone, are the clone meta attrs OK?
+    if [ "${OCF_RESKEY_CRM_meta_clone}" ]; then
+	if [ "${OCF_RESKEY_CRM_meta_clone_node_max}" != 1 ]; then
+	    ocf_log error "Misconfigured clone parameters. Must set meta attribute \"clone_node_max\" to 1, got ${OCF_RESKEY_CRM_meta_clone_node_max}."
+	    return $OCF_ERR_ARGS
+	fi
+    fi
+    # Did we get a destination?
+    if [ -z "${OCF_RESKEY_destination}" ]; then
+	ocf_log error "Missing required parameter \"destination\"."
+	return $OCF_ERR_ARGS
+    fi
+    # Did we get either a device or a gateway address?
+    if [ -z "${OCF_RESKEY_device}" -a -z "${OCF_RESKEY_gateway}" ]; then
+	ocf_log error "Must specifiy either \"device\", or \"gateway\", or both."
+	return $OCF_ERR_ARGS
+    fi
+    # If a device has been configured, is it available on this system?
+    if [ -n "${OCF_RESKEY_device}" ]; then
+	if ! ip link show ${OCF_RESKEY_device} >/dev/null 2>&1; then
+	    ocf_log error "Network device ${OCF_RESKEY_device} appears not to be available on this system."
+	    # OCF_ERR_ARGS prevents the resource from running anywhere at all,
+	    # maybe another node has the interface?
+            # OCF_ERR_INSTALLED just prevents starting on this particular node.
+	    return $OCF_ERR_INSTALLED
+	fi
+    fi
+
+    # The following tests must return $OCF_ERR_INSTALLED, but only if
+    # the resource is actually running (i.e., not during probes)
+    if ! ocf_is_probe; then
+        # If a source address has been configured, is it available on
+        # this system?
+	if [ -n "${OCF_RESKEY_source}" ]; then
+	    if ! ip address show | grep -w ${OCF_RESKEY_source} >/dev/null 2>&1; then
+		ocf_log error "Source address ${OCF_RESKEY_source} appears not to be available on this system."
+	    # same reason as with _device:
+		return $OCF_ERR_INSTALLED
+	    fi
+	fi
+        # If a gateway address has been configured, is it reachable?
+	if [ -n "${OCF_RESKEY_gateway}" ]; then
+	    if ! ip route get ${OCF_RESKEY_gateway} >/dev/null 2>&1; then
+		ocf_log error "Gateway address ${OCF_RESKEY_gateway} is unreachable."
+	    # same reason as with _device:
+		return $OCF_ERR_INSTALLED
+	    fi
+	fi
+    fi
+    return $OCF_SUCCESS
+}
+
+# These two actions must always succeed
+case $__OCF_ACTION in
+meta-data)	meta_data
+		# OCF variables are not set when querying meta-data
+		exit 0
+		;;
+usage|help)	route_usage
+		exit $OCF_SUCCESS
+		;;
+esac
+
+# Don't do anything if the necessary utilities aren't present
+for binary in ip grep; do
+    check_binary $binary
+done
+
+route_validate || exit $?
+
+case $OCF_RESKEY_destination in
+*:*) addr_family="-6" ;;
+  *) addr_family="-4" ;;
+esac
+
+case $__OCF_ACTION in
+start)		route_start;;
+stop)		route_stop;;
+status|monitor)	route_status;;
+reload)		ocf_log info "Reloading..."
+	        route_start
+		;;
+validate-all)	;;
+*)		route_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION returned $rc"
+exit $rc
diff --git a/heartbeat/SAPDatabase b/heartbeat/SAPDatabase
new file mode 100755
index 0000000..3b77206
--- /dev/null
+++ b/heartbeat/SAPDatabase
@@ -0,0 +1,331 @@
+#!/bin/sh
+#
+# SAPDatabase
+#
+# Description:	Manages any type of SAP supported database instance
+#               as a High-Availability OCF compliant resource.
+#
+# Author:       Alexander Krauth, October 2006
+# Support:      linux at sap.com
+# License:      GNU General Public License (GPL)
+# Copyright:    (c) 2006, 2007, 2010, 2012 Alexander Krauth
+#
+# An example usage: 
+#      See usage() function below for more details...
+#
+# OCF instance parameters:
+#       OCF_RESKEY_SID
+#       OCF_RESKEY_DIR_EXECUTABLE      (optional, well known directories will be searched by default)
+#       OCF_RESKEY_DBTYPE              (mandatory, one of the following values: ORA,ADA,DB6,SYB,HDB)
+#       OCF_RESKEY_DBINSTANCE          (optional, Database instance name, if not equal to SID)
+#       OCF_RESKEY_STRICT_MONITORING   (optional, activate application level monitoring - with Oracle a failover will occur in case of an archiver stuck)
+#       OCF_RESKEY_AUTOMATIC_RECOVER   (optional, automatic startup recovery, default is false)
+#       OCF_RESKEY_MONITOR_SERVICES    (optional, default is to monitor all database services)
+#       OCF_RESKEY_PRE_START_USEREXIT  (optional, lists a script which can be executed before the resource is started)
+#       OCF_RESKEY_POST_START_USEREXIT (optional, lists a script which can be executed after the resource is started)
+#       OCF_RESKEY_PRE_STOP_USEREXIT   (optional, lists a script which can be executed before the resource is stopped)
+#       OCF_RESKEY_POST_STOP_USEREXIT  (optional, lists a script which can be executed after the resource is stopped)
+#     Deprecated parameters:
+#       OCF_RESKEY_NETSERVICENAME
+#       OCF_RESKEY_DBJ2EE_ONLY
+#       OCF_RESKEY_JAVA_HOME
+#       OCF_RESKEY_DIR_BOOTSTRAP
+#       OCF_RESKEY_DIR_SECSTORE
+#       OCF_RESKEY_DB_JARS
+#
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+SH=/bin/sh
+
+usage() {
+  methods=`sapdatabase_methods`
+  methods=`echo $methods | tr ' ' '|'`
+  cat <<-!
+	usage: $0 ($methods)
+
+	$0 manages a SAP database of any type as an HA resource.
+        Currently Oracle, MaxDB, DB/2 UDB, Sybase ASE and SAP HANA Database are supported.
+        ABAP databases as well as JAVA only databases are supported.
+
+	The 'start' operation starts the instance.
+	The 'stop' operation stops the instance.
+	The 'status' operation reports whether the instance is running
+	The 'monitor' operation reports whether the instance seems to be working
+	The 'recover' operation tries to recover the instance after a crash (instance will be stopped first!)
+	The 'validate-all' operation reports whether the parameters are valid
+	The 'methods' operation reports on the methods $0 supports
+
+	!
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="SAPDatabase">
+<version>2.06</version>
+
+<shortdesc lang="en">Manages a SAP database instance as an HA resource.</shortdesc>
+<longdesc lang="en">
+Resource script for SAP databases. It manages a SAP database of any type as an HA resource.
+
+The purpose of the resource agent is to start, stop and monitor the database instance of a SAP system. Together with the RDBMS system it will also control the related network service for the database. Like the Oracle Listener and the xserver of MaxDB.
+The resource agent expects a standard SAP installation of the database and therefore needs less parameters to configure.
+The resource agent supports the following databases:
+- Oracle 10.2 and 11.2
+- DB/2 UDB for Windows and Unix 9.x
+- SAP-DB / MaxDB 7.x
+- Sybase ASE 15.7
+- SAP HANA Database since 1.00 - with SAP node 1625203 (http://sdn.sap.com)
+
+In fact this resource agent does not run any database commands directly. It uses the SAP standard process SAPHostAgent to control the database.
+The SAPHostAgent must be installed on each cluster node locally. It will not work, if you try to run the SAPHostAgent also as a HA resource.
+Please follow SAP note 1031096 for the installation of SAPHostAgent.
+The required minimum version of SAPHostAgent is:
+Release: 7.20
+Patch Number: 90
+or compile time after: Dec 17 2011
+</longdesc>
+<parameters>
+ <parameter name="SID" unique="1" required="1">
+  <longdesc lang="en">The unique database system identifier. e.g. P01</longdesc>
+  <shortdesc lang="en">Database system ID</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DIR_EXECUTABLE" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find saphostexec and saphostctrl.
+Usually you can leave this empty. Then the default: /usr/sap/hostctrl/exe is used.
+  </longdesc>
+  <shortdesc lang="en">path of saphostexec and saphostctrl</shortdesc>
+  <content type="string" default="/usr/sap/hostctrl/exe" />
+ </parameter>
+ <parameter name="DBTYPE" unique="0" required="1">
+  <longdesc lang="en">The name of the database vendor you use. Set either: ADA, DB6, ORA, SYB, HDB</longdesc>
+  <shortdesc lang="en">database vendor</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DBINSTANCE" unique="1" required="0">
+  <longdesc lang="en">Must be used for special database implementations, when database instance name is not equal to the SID (e.g. Oracle DataGuard)</longdesc>
+  <shortdesc lang="en">Database instance name, if not equal to SID</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="NETSERVICENAME" unique="0" required="0">
+  <longdesc lang="en">Deprecated - do not use anymore. This parameter will be deleted in one of the next releases.</longdesc>
+  <shortdesc lang="en">deprecated - do not use anymore</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DBJ2EE_ONLY" unique="0" required="0">
+  <longdesc lang="en">Deprecated - do not use anymore. This parameter will be deleted in one of the next releases.</longdesc>
+  <shortdesc lang="en">deprecated - do not use anymore</shortdesc>
+  <content type="boolean" default=""/>
+ </parameter>
+ <parameter name="JAVA_HOME" unique="0" required="0">
+  <longdesc lang="en">Deprecated - do not use anymore. This parameter will be deleted in one of the next releases.</longdesc>
+  <shortdesc lang="en">deprecated - do not use anymore</shortdesc>
+  <content type="string" default=""/>
+ </parameter>
+ <parameter name="STRICT_MONITORING" unique="0" required="0">
+  <longdesc lang="en">This controls how the resource agent monitors the database. If set to true, it will use 'saphostctrl -function GetDatabaseStatus' to test the database state. If set to false, only operating system processes are monitored.</longdesc>
+  <shortdesc lang="en">Activates application level monitoring</shortdesc>
+  <content type="boolean" default="false"/>
+ </parameter>
+ <parameter name="AUTOMATIC_RECOVER" unique="0" required="0">
+  <longdesc lang="en">If you set this to true, 'saphostctrl -function StartDatabase' will always be called with the '-force' option.</longdesc>
+  <shortdesc lang="en">Enable or disable automatic startup recovery</shortdesc>
+  <content type="boolean" default="false"/>
+ </parameter>
+ <parameter name="MONITOR_SERVICES" unique="0" required="0">
+  <longdesc lang="en">Defines which services are monitored by the SAPDatabase resource agent, if STRICT_MONITORING is set to true. Service names must correspond with the output of the 'saphostctrl -function GetDatabaseStatus' command.</longdesc>
+  <shortdesc lang="en">Database services to monitor</shortdesc>
+  <content type="string" default="Instance|Database|Listener"/>
+ </parameter>
+ <parameter name="DIR_BOOTSTRAP" unique="0" required="0">
+  <longdesc lang="en">Deprecated - do not use anymore. This parameter will be deleted in one of the next releases.</longdesc>
+  <shortdesc lang="en">deprecated - do not use anymore</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DIR_SECSTORE" unique="0" required="0">
+  <longdesc lang="en">Deprecated - do not use anymore. This parameter will be deleted in one of the next releases.</longdesc>
+  <shortdesc lang="en">deprecated - do not use anymore</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DB_JARS" unique="0" required="0">
+  <longdesc lang="en">Deprecated - do not use anymore. This parameter will be deleted in one of the next releases.</longdesc>
+  <shortdesc lang="en">deprecated - do not use anymore</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="PRE_START_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed before this resource gets started.</longdesc>
+  <shortdesc lang="en">path to a pre-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="POST_START_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed after this resource got started.</longdesc>
+  <shortdesc lang="en">path to a post-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="PRE_STOP_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed before this resource gets stopped.</longdesc>
+  <shortdesc lang="en">path to a pre-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="POST_STOP_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed after this resource got stopped.</longdesc>
+  <shortdesc lang="en">path to a post-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="1800" />
+<action name="stop" timeout="1800" />
+<action name="status" timeout="60" />
+<action name="monitor" depth="0" timeout="60" interval="120" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+<action name="methods" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+
+#
+# methods: What methods/operations do we support?
+#
+sapdatabase_methods() {
+  cat <<-!
+	start
+	stop
+	status
+	monitor
+	recover
+	validate-all
+	methods
+	meta-data
+	usage
+	!
+}
+
+
+#
+# sapuserexit : Many SAP customers need some additional processes/tools to run their SAP systems.
+#               This specialties do not allow a totally generic SAP cluster resource agent.
+#               Someone should write a resource agent for each additional process you need, if it
+#               is required to monitor that process within the cluster manager. To enable
+#               you to extent this resource agent without developing a new one, this user exit
+#               was introduced.
+#
+sapuserexit() {
+  NAME="$1"
+  VALUE="$2"
+
+  if [ -n "$VALUE" ]
+  then
+    if have_binary "$VALUE"
+    then
+      ocf_log info "Calling userexit ${NAME} with customer script file ${VALUE}"
+      "$VALUE" >/dev/null 2>&1
+      ocf_log info "Exiting userexit ${NAME} with customer script file ${VALUE}, returncode: $?"
+    else
+      ocf_log warn "Attribute ${NAME} is set to ${VALUE}, but this file is not executable"
+    fi
+  fi
+  return $OCF_SUCCESS
+}
+
+
+#
+# saphostctrl_installed
+#
+saphostctrl_installed() {
+  OCF_RESKEY_DIR_EXECUTABLE_default="/usr/sap/hostctrl/exe"
+  : ${OCF_RESKEY_DIR_EXECUTABLE=${OCF_RESKEY_DIR_EXECUTABLE_default}}
+  SAPHOSTCTRL="${OCF_RESKEY_DIR_EXECUTABLE}/saphostctrl"
+  SAPHOSTEXEC="${OCF_RESKEY_DIR_EXECUTABLE}/saphostexec"
+  SAPHOSTSRV="${OCF_RESKEY_DIR_EXECUTABLE}/sapstartsrv"
+  SAPHOSTOSCOL="${OCF_RESKEY_DIR_EXECUTABLE}/saposcol"
+
+  have_binary $SAPHOSTCTRL && have_binary $SAPHOSTEXEC
+}
+
+
+#
+#	'main' starts here...
+#
+
+if
+  ( [ $# -ne 1 ] )
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+# These operations don't require OCF instance parameters to be set
+case "$1" in
+  meta-data)	meta_data
+		exit $OCF_SUCCESS;;
+
+  usage) 	usage
+		exit $OCF_SUCCESS;;
+
+  methods)	sapdatabase_methods
+		exit $?;;
+
+  *);;
+esac
+
+if  ! ocf_is_root 
+then
+  ocf_log err "$0 must be run as root"
+  exit $OCF_ERR_PERM
+fi
+
+# mandatory parameter check
+if  [ -z "$OCF_RESKEY_SID" ]; then
+  ocf_log err "Please set OCF_RESKEY_SID to the SAP system id!"
+  exit $OCF_ERR_ARGS
+fi
+SID=`echo "$OCF_RESKEY_SID"`
+
+if [ -z "$OCF_RESKEY_DBTYPE" ]; then
+  ocf_log err "Please set OCF_RESKEY_DBTYPE to the database vendor specific tag (ADA,DB6,ORA,SYB,HDB)!"
+  exit $OCF_ERR_ARGS
+fi
+DBTYPE=`echo "$OCF_RESKEY_DBTYPE" | tr '[:lower:]' '[:upper:]'`
+
+
+# source functions and initialize global variables
+if saphostctrl_installed; then
+                    . ${OCF_FUNCTIONS_DIR}/sapdb.sh
+else
+                    . ${OCF_FUNCTIONS_DIR}/sapdb-nosha.sh
+fi
+sapdatabase_init
+
+
+# we always want to fall to the faster status method in case of a probe by the cluster  
+ACTION=$1
+if ocf_is_probe 
+then
+  ACTION=status
+fi
+
+# What kind of method was invoked?
+case "$ACTION" in
+
+  start|stop|status|recover)   sapdatabase_$ACTION
+                               exit $?;;
+  monitor)                     sapdatabase_monitor $OCF_RESKEY_STRICT_MONITORING
+                               exit $?;;
+  validate-all)                sapdatabase_validate
+                               exit $?;;
+  *)		                   sapdatabase_methods
+                               exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/heartbeat/SAPInstance b/heartbeat/SAPInstance
new file mode 100755
index 0000000..da394f5
--- /dev/null
+++ b/heartbeat/SAPInstance
@@ -0,0 +1,942 @@
+#!/bin/sh
+#
+# SAPInstance
+#
+# Description:	Manages a single SAP Instance as a High-Availability
+#		resource. One SAP Instance is defined by one 
+#               SAP Instance-Profile. start/stop handels all services
+#               of the START-Profile, status and monitor care only
+#               about essential services.
+#
+# Author:       Alexander Krauth, June 2006
+# Support:      linux at sap.com
+# License:      GNU General Public License (GPL)
+# Copyright:    (c) 2006-2008 Alexander Krauth
+#
+# An example usage: 
+#      See usage() function below for more details...
+#
+# OCF instance parameters:
+#	OCF_RESKEY_InstanceName
+#	OCF_RESKEY_DIR_EXECUTABLE   (optional, well known directories will be searched by default)
+#	OCF_RESKEY_DIR_PROFILE      (optional, well known directories will be searched by default)
+#	OCF_RESKEY_START_PROFILE    (optional, well known directories will be searched by default)
+#	OCF_RESKEY_START_WAITTIME   (optional, to solve timing problems during J2EE-Addin start)
+#	OCF_RESKEY_AUTOMATIC_RECOVER    (optional, automatic startup recovery using cleanipc, default is false)
+#       OCF_RESKEY_MONITOR_SERVICES     (optional, default is to monitor critical services only)
+#       OCF_RESKEY_SHUTDOWN_METHOD      (optional, defaults to NORMAL, KILL: terminate the SAP instance with OS commands - faster, at your own risk)
+#       OCF_RESKEY_ERS_InstanceName     (optional, InstanceName of the ERS instance in a Master/Slave configuration)
+#       OCF_RESKEY_ERS_START_PROFILE    (optional, START_PROFILE of the ERS instance in a Master/Slave configuration)
+#	OCF_RESKEY_PRE_START_USEREXIT	(optional, lists a script which can be executed before the resource is started)
+#	OCF_RESKEY_POST_START_USEREXIT	(optional, lists a script which can be executed after the resource is started)
+#	OCF_RESKEY_PRE_STOP_USEREXIT	(optional, lists a script which can be executed before the resource is stopped)
+#	OCF_RESKEY_POST_STOP_USEREXIT	(optional, lists a script which can be executed after the resource is stopped)
+#
+#  TODO: - Option to shutdown sapstartsrv for non-active instances -> that means: do probes only with OS tools (sapinstance_status)
+#        - Option for better standalone enqueue server monitoring, using ensmon (test enque-deque)
+#        - Option for cleanup abandoned enqueue replication tables
+#
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+SH=/bin/sh
+
+sapinstance_usage() {
+  methods=`sapinstance_methods`
+  methods=`echo $methods | tr ' ' '|'`
+  cat <<-!
+	usage: $0 ($methods)
+
+	$0 manages a SAP Instance as an HA resource.
+
+	The 'start' operation starts the instance or the ERS instance in a Master/Slave configuration
+	The 'stop' operation stops the instance
+	The 'status' operation reports whether the instance is running
+	The 'monitor' operation reports whether the instance seems to be working
+        The 'promote' operation starts the primary instance in a Master/Slave configuration
+        The 'demote' operation stops the primary instance and starts the ERS instance
+        The 'notify' operation always returns SUCCESS
+	The 'validate-all' operation reports whether the parameters are valid
+	The 'methods' operation reports on the methods $0 supports
+
+	!
+}
+
+sapinstance_meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="SAPInstance">
+<version>2.14</version>
+
+<shortdesc lang="en">Manages a SAP instance as an HA resource.</shortdesc>
+<longdesc lang="en">
+Usually a SAP system consists of one database and at least one or more SAP instances (sometimes called application servers). One SAP Instance is defined by having exactly one instance profile. The instance profiles can usually be found in the directory /sapmnt/SID/profile. Each instance must be configured as it's own resource in the cluster configuration.
+The resource agent supports the following SAP versions:
+- SAP WebAS ABAP Release 6.20 - 7.30
+- SAP WebAS Java Release 6.40 - 7.30
+- SAP WebAS ABAP + Java Add-In Release 6.20 - 7.30 (Java is not monitored by the cluster in that case)
+When using a SAP Kernel 6.40 please check and implement the actions from the section "Manual postprocessing" from SAP note 995116 (http://sdn.sap.com).
+
+All operations of the SAPInstance resource agent are done by using the startup framework called SAP Management Console or sapstartsrv that was introduced with SAP kernel release 6.40. Find more information about the SAP Management Console in SAP note 1014480. Using this framework defines a clear interface for the Heartbeat cluster, how it sees the SAP system. The options for monitoring the SAP system are also much better than other methods like just watching the ps command for running pr [...]
+
+sapstartsrv knows 4 status colours:
+- GREEN   = everything is fine
+- YELLOW  = something is wrong, but the service is still working
+- RED     = the service does not work
+- GRAY    = the service has not been started
+
+The SAPInstance resource agent will interpret GREEN and YELLOW as OK. That means that minor problems will not be reported to the Heartbeat cluster. This prevents the cluster from doing an unwanted failover.
+The statuses RED and GRAY are reported as NOT_RUNNING to the cluster. Depending on the status the cluster expects from the resource, it will do a restart, failover or just nothing.
+</longdesc>
+<parameters>
+ <parameter name="InstanceName" unique="1" required="1">
+  <longdesc lang="en">The full qualified SAP instance name. e.g. P01_DVEBMGS00_sapp01ci. Usually this is the name of the SAP instance profile.</longdesc>
+  <shortdesc lang="en">Instance name: SID_INSTANCE_VIR-HOSTNAME</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DIR_EXECUTABLE" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find sapstartsrv and sapcontrol. Specify this parameter, if you have changed the SAP kernel directory location after the default SAP installation.</longdesc>
+  <shortdesc lang="en">Path of sapstartsrv and sapcontrol</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DIR_PROFILE" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find the SAP START profile. Specify this parameter, if you have changed the SAP profile directory location after the default SAP installation.</longdesc>
+  <shortdesc lang="en">Path of start profile</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="START_PROFILE" unique="1" required="0">
+  <longdesc lang="en">The name of the SAP START profile. Specify this parameter, if you have changed the name of the SAP START profile after the default SAP installation. As SAP release 7.10 does not have a START profile anymore, you need to specify the Instance Profile than.</longdesc>
+  <shortdesc lang="en">Start profile name</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="START_WAITTIME" unique="0" required="0">
+  <longdesc lang="en">After that time in seconds a monitor operation is executed by the resource agent. Does the monitor return SUCCESS, the start ishandled as SUCCESS. This is useful to resolve timing problems with e.g. the J2EE-Addin instance.Usually the resource agent waits until all services are started and the SAP Management Console reports a GREEN status. A double stack installation (ABAP + Java AddIn) consists of an ABAP dispatcher and aJAVA instance. Normally the start of the JAV [...]
+Actually the SAP MC reports a YELLOW status, if the JAVA instance of a double stack system fails. From the resource agent point of view YELLOW means:everything is OK. Setting START_WAITTIME to a lower value determines the resource agent to check the status of the instance during a start operation after that time. As it would wait normally for a GREEN status, now it reports SUCCESS to the cluster in case of a YELLOW status already after the specified time.
+
+That is only useful for double stack systems.
+  </longdesc>
+  <shortdesc lang="en">Check the successful start after that time (do not wait for J2EE-Addin)</shortdesc>
+  <content type="string" default="3600" />
+ </parameter>
+ <parameter name="AUTOMATIC_RECOVER" unique="0" required="0">
+  <longdesc lang="en">The SAPInstance resource agent tries to recover a failed start attempt automaticaly one time. This is done by killing runing instance processes, removing the kill.sap file and executing cleanipc. Sometimes a crashed SAP instance leaves some processes and/or shared memory segments behind. Setting this option to true will try to remove those leftovers during a start operation. That is to reduce manual work for the administrator.</longdesc>
+  <shortdesc lang="en">Enable or disable automatic startup recovery</shortdesc>
+  <content type="boolean" default="false"/>
+ </parameter>
+ <parameter name="MONITOR_SERVICES" unique="0" required="0">
+  <longdesc lang="en">Within a SAP instance there can be several services. Usually you will find the defined services in the START profile of the related instance (Attention: with SAP Release 7.10 the START profile content was moved to the instance profile). Not all of those services are worth to monitor by the cluster. For example you properly do not like to failover your SAP instance, if the central syslog collector daemon fails.
+Those services are monitored within the SAPInstance resource agent:
+
+- disp+work
+- msg_server
+- enserver
+- enrepserver
+- jcontrol
+- jstart
+
+That names match the strings used in the output of the command 'sapcontrol -nr [Instance-Nr] -function GetProcessList'.
+The default should fit most cases where you want to manage a SAP Instance from the cluster. You may change this with this parameter, if you like to monitor more/less or other services that sapstartsrv supports.
+You may specify multiple services seperated by a | (pipe) sign in this parameter: disp+work|msg_server|enserver
+  </longdesc>
+  <shortdesc lang="en">Services to monitor</shortdesc>
+  <content type="string" default="disp+work|msg_server|enserver|enrepserver|jcontrol|jstart"/>
+ </parameter>
+  <parameter name="SHUTDOWN_METHOD" unique="0" required="0">
+  <longdesc lang="en">Usual a SAP Instance is stopped by the command 'sapcontrol -nr InstanceNr -function Stop'. SHUTDOWN_METHOD=KILL means to kill the SAP Instance using OS commands. SAP processes of the instance are terminated with 'kill -9', shared memory is deleted with 'cleanipc' and the 'kill.sap' file will be deleted. That method is much faster than the gracefull stop, but the instance does not have the chance to say goodbye to other SAPinstances in the same system. USE AT YOUR OW [...]
+  <shortdesc lang="en">Shutdown graceful or kill a SAP instance by terminating the processes. (normal|KILL)</shortdesc>
+  <content type="string" default="normal"/>
+ </parameter>
+ <parameter name="ERS_InstanceName" unique="1" required="0">
+  <longdesc lang="en">Only used in a Master/Slave resource configuration:
+The full qualified SAP enqueue replication instance name. e.g. P01_ERS02_sapp01ers. Usually this is the name of the SAP instance profile.
+The enqueue replication instance must be installed, before you want to configure a master-slave cluster recource.
+
+The master-slave configuration in the cluster must use this properties:
+clone_max = 2
+clone_node_max = 1
+master_node_max = 1
+master_max = 1
+  </longdesc>
+  <shortdesc lang="en">Enqueue replication instance name: SID_INSTANCE_VIR-HOSTNAME</shortdesc>
+  <content type="string" default=""/>
+ </parameter>
+ <parameter name="ERS_START_PROFILE" unique="1" required="0">
+  <longdesc lang="en">Only used in a Master/Slave resource configuration:
+The parameter ERS_InstanceName must also be set in this configuration.
+The name of the SAP START profile. Specify this parameter, if you have changed the name of the SAP START profile after the default SAP installation. As SAP release 7.10 does not have a START profile anymore, you need to specify the Instance Profile than.
+  </longdesc>
+  <shortdesc lang="en">Enqueue replication start profile name</shortdesc>
+  <content type="string" default=""/>
+ </parameter>
+ <parameter name="PRE_START_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed before this resource gets started.</longdesc>
+  <shortdesc lang="en">Path to a pre-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="POST_START_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed after this resource got started.</longdesc>
+  <shortdesc lang="en">Path to a post-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="PRE_STOP_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed before this resource gets stopped.</longdesc>
+  <shortdesc lang="en">Path to a pre-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="POST_STOP_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed after this resource got stopped.</longdesc>
+  <shortdesc lang="en">Path to a post-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="180" />
+<action name="stop" timeout="240" />
+<action name="status" timeout="60" />
+<action name="monitor" depth="0" timeout="60" interval="120" />
+<action name="monitor" depth="0" timeout="60" interval="121" role="Slave" />
+<action name="monitor" depth="0" timeout="60" interval="119" role="Master" />
+<action name="promote" timeout="320" />
+<action name="demote" timeout="320" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+<action name="methods" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+
+#
+# methods: What methods/operations do we support?
+#
+sapinstance_methods() {
+  cat <<-!
+	start
+	stop
+	status
+	monitor
+        promote
+        demote
+        notify
+	validate-all
+	methods
+	meta-data
+	usage
+	!
+}
+
+
+
+#
+# is_clone : find out if we are configured to run in a Master/Slave configuration
+#
+is_clone() {
+  if [ -n "$OCF_RESKEY_CRM_meta_clone_max" ] \
+   && [ "$OCF_RESKEY_CRM_meta_clone_max" -gt 0 ]
+  then
+    if [ "$OCF_RESKEY_CRM_meta_clone_max" -ne 2 ] || \
+       [ "$OCF_RESKEY_CRM_meta_clone_node_max" -ne 1 ] || \
+       [ "$OCF_RESKEY_CRM_meta_master_node_max" -ne 1 ] || \
+       [ "$OCF_RESKEY_CRM_meta_master_max" -ne 1 ]
+    then
+            ocf_log err "Clone options misconfigured. (expect: clone_max=2,clone_node_max=1,master_node_max=1,master_max=1)"
+            exit $OCF_ERR_CONFIGURED
+    fi
+
+    if [ -z "$OCF_RESKEY_ERS_InstanceName" ]
+    then
+      ocf_log err "In a Master/Slave configuration the ERS_InstanceName parameter is mandatory."
+      exit $OCF_ERR_ARGS
+    fi
+  else
+    return 0
+  fi
+  return 1
+}
+
+
+#
+# abnormal_end : essential things are missing, but in the natur of a SAP installation - which can be very different
+#                from customer to customer - we cannot handle this always as an error
+#                This would be the case, if the software is installed on shared disks and not visible
+#                to all cluster nodes at all times.
+#
+abnormal_end() {
+  local err_msg=$1
+
+  ocf_is_probe && {
+    sapinstance_status
+    exit $?
+  }
+
+  if [ "$ACTION" = "stop" ]
+  then
+    cleanup_instance
+    exit $OCF_SUCCESS
+  fi
+
+  ocf_log err $err_msg
+  exit $OCF_ERR_CONFIGURED
+}
+
+#
+# sapinstance_init : Define global variables with default values, if optional parameters are not set
+#
+#
+sapinstance_init() {
+
+  local myInstanceName="$1"
+
+  SID=`echo "$myInstanceName" | cut -d_ -f1`
+  InstanceName=`echo "$myInstanceName" | cut -d_ -f2`
+  InstanceNr=`echo "$InstanceName" | sed 's/.*\([0-9][0-9]\)$/\1/'`
+  SAPVIRHOST=`echo "$myInstanceName" | cut -d_ -f3`
+
+  # optional OCF parameters, we try to guess which directories are correct
+  if  [ -z "$OCF_RESKEY_DIR_EXECUTABLE" ]
+  then
+    if have_binary /usr/sap/$SID/$InstanceName/exe/sapstartsrv && have_binary /usr/sap/$SID/$InstanceName/exe/sapcontrol
+    then
+      DIR_EXECUTABLE="/usr/sap/$SID/$InstanceName/exe"
+      SAPSTARTSRV="/usr/sap/$SID/$InstanceName/exe/sapstartsrv"
+      SAPCONTROL="/usr/sap/$SID/$InstanceName/exe/sapcontrol"
+    elif have_binary /usr/sap/$SID/SYS/exe/run/sapstartsrv && have_binary /usr/sap/$SID/SYS/exe/run/sapcontrol
+    then
+      DIR_EXECUTABLE="/usr/sap/$SID/SYS/exe/run"
+      SAPSTARTSRV="/usr/sap/$SID/SYS/exe/run/sapstartsrv"
+      SAPCONTROL="/usr/sap/$SID/SYS/exe/run/sapcontrol"
+    fi
+  else
+    if have_binary "$OCF_RESKEY_DIR_EXECUTABLE/sapstartsrv" && have_binary "$OCF_RESKEY_DIR_EXECUTABLE/sapcontrol"
+    then
+      DIR_EXECUTABLE="$OCF_RESKEY_DIR_EXECUTABLE"
+      SAPSTARTSRV="$OCF_RESKEY_DIR_EXECUTABLE/sapstartsrv"
+      SAPCONTROL="$OCF_RESKEY_DIR_EXECUTABLE/sapcontrol"
+    fi
+  fi
+
+  sidadm="`echo $SID | tr '[:upper:]' '[:lower:]'`adm"
+
+  [ -z "$DIR_EXECUTABLE" ] && abnormal_end "Cannot find sapstartsrv and sapcontrol executable, please set DIR_EXECUTABLE parameter!"
+
+  if [ -z "$OCF_RESKEY_DIR_PROFILE" ]
+  then
+    DIR_PROFILE="/usr/sap/$SID/SYS/profile"
+  else
+    DIR_PROFILE="$OCF_RESKEY_DIR_PROFILE"
+  fi
+
+  if [ "$myInstanceName" != "$OCF_RESKEY_InstanceName" ]
+  then
+    currentSTART_PROFILE=$OCF_RESKEY_ERS_START_PROFILE
+  else
+    currentSTART_PROFILE=$OCF_RESKEY_START_PROFILE
+  fi
+
+  if [ -z "$currentSTART_PROFILE" ]
+  then
+    SAPSTARTPROFILE="$DIR_PROFILE/START_${InstanceName}_${SAPVIRHOST}"
+  else
+    SAPSTARTPROFILE="$currentSTART_PROFILE"
+  fi
+
+  if [ -z "$OCF_RESKEY_START_WAITTIME" ]
+  then
+    export OCF_RESKEY_START_WAITTIME=3600
+  fi
+
+  if [ -z "$OCF_RESKEY_MONITOR_SERVICES" ]
+  then
+    export OCF_RESKEY_MONITOR_SERVICES="disp+work|msg_server|enserver|enrepserver|jcontrol|jstart"
+  fi
+
+  # as root user we need the library path to the SAP kernel to be able to call sapcontrol
+  if [ `echo $LD_LIBRARY_PATH | grep -c "^$DIR_EXECUTABLE\>"` -eq 0 ]; then
+    LD_LIBRARY_PATH=$DIR_EXECUTABLE${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH
+    export LD_LIBRARY_PATH
+  fi
+
+  return $OCF_SUCCESS
+}
+
+
+#
+# check_sapstartsrv : Before using sapcontrol we make sure that the sapstartsrv is running for the correct instance.
+#                     We cannot use sapinit and the /usr/sap/sapservices file in case of an enquerep instance,
+#                     because then we have two instances with the same instance number.
+#
+check_sapstartsrv() {
+  local restart=0
+  local runninginst=""
+  local chkrc=$OCF_SUCCESS
+  local output=""
+
+  if [ ! -S /tmp/.sapstream5${InstanceNr}13 ]; then
+    ocf_log warn "sapstartsrv is not running for instance $SID-$InstanceName (no UDS), it will be started now"
+    restart=1
+  else
+    output=`$SAPCONTROL -nr $InstanceNr -function ParameterValue INSTANCE_NAME -format script`
+    if [ $? -eq 0 ]
+    then
+      runninginst=`echo "$output" | grep '^0 : ' | cut -d' ' -f3`
+      if [ "$runninginst" != "$InstanceName" ]
+      then 
+        ocf_log warn "sapstartsrv is running for instance $runninginst, that service will be killed"
+        restart=1
+      else
+        output=`$SAPCONTROL -nr $InstanceNr -function AccessCheck Start`
+        if [ $? -ne 0 ]; then
+          ocf_log warn "FAILED : sapcontrol -nr $InstanceNr -function AccessCheck Start (`ls -ld1 /tmp/.sapstream5${InstanceNr}13`)"
+          ocf_log warn "sapstartsrv will be restarted to try to solve this situation, otherwise please check sapstsartsrv setup (SAP Note 927637)"
+          restart=1
+        fi
+      fi
+    else
+      ocf_log warn "sapstartsrv is not running for instance $SID-$InstanceName, it will be started now"
+      restart=1
+    fi
+  fi
+
+  if [ -z "$runninginst" ]; then runninginst=$InstanceName; fi
+
+  if [ $restart -eq 1 ]
+  then
+
+    if [ -d /usr/sap/$SID/SYS/profile/ ]
+    then
+      DIR_PROFILE="/usr/sap/$SID/SYS/profile"
+    else
+      abnormal_end "Expected /usr/sap/$SID/SYS/profile/ to be a directory, please set DIR_PROFILE parameter!"
+    fi
+
+    [ ! -r $SAPSTARTPROFILE ] && abnormal_end "Expected $SAPSTARTPROFILE to be the instance START profile, please set START_PROFILE parameter!"
+
+    pkill -9 -f "sapstartsrv.*$runninginst"
+
+    # removing the unix domain socket files as they might have wrong permissions
+    # or ownership - they will be recreated by sapstartsrv during next start
+    rm -f /tmp/.sapstream5${InstanceNr}13
+    rm -f /tmp/.sapstream5${InstanceNr}14
+
+    $SAPSTARTSRV pf=$SAPSTARTPROFILE -D -u $sidadm
+
+    # now make sure the daemon has been started and is able to respond
+    local srvrc=1
+    while [ $srvrc -eq 1 -a `pgrep -f "sapstartsrv.*$runninginst" | wc -l` -gt 0 ]
+    do
+      sleep 1
+      $SAPCONTROL -nr $InstanceNr -function GetProcessList > /dev/null 2>&1
+      srvrc=$?
+    done
+
+    if [ $srvrc -ne 1 ]
+    then
+      ocf_log info "sapstartsrv for instance $SID-$InstanceName was restarted !"
+      chkrc=$OCF_SUCCESS
+    else
+      ocf_log error "sapstartsrv for instance $SID-$InstanceName could not be started!"
+      chkrc=$OCF_ERR_GENERIC
+      ocf_is_probe && chkrc=$OCF_NOT_RUNNING
+    fi
+  fi
+
+  return $chkrc
+}
+
+
+#
+# sapuserexit : Many SAP customers need some additional processes/tools to run their SAP systems.
+#               This specialties do not allow a totally generic SAP cluster resource agent.
+#               Someone should write a resource agent for each additional process you need, if it
+#               is required to monitor that process within the cluster manager. To enable 
+#               you to extent this resource agent without developing a new one, this user exit
+#               was introduced.
+#
+sapuserexit() {
+  local NAME="$1"
+  local VALUE="$2"
+
+  if [ -n "$VALUE" ]
+  then
+    if have_binary "$VALUE"
+    then
+      ocf_log info "Calling userexit ${NAME} with customer script file ${VALUE}"
+      "$VALUE" >/dev/null 2>&1
+      ocf_log info "Exiting userexit ${NAME} with customer script file ${VALUE}, returncode: $?"
+    else
+      ocf_log warn "Attribute ${NAME} is set to ${VALUE}, but this file is not executable"
+    fi
+  fi
+  return 0
+}
+
+
+#
+# cleanup_instance : remove resources (processes and shared memory) from a crashed instance)
+#
+cleanup_instance() {
+  pkill -9 -f -U $sidadm $InstanceName
+  ocf_log info "Terminated instance using 'pkill -9 -f -U $sidadm $InstanceName'"
+
+  # it is necessary to call cleanipc as user sidadm if the system has 'vmcj/enable = ON' set - otherwise SHM-segments in /dev/shm/SAP_ES2* cannot beremoved
+  su - $sidadm -c "cleanipc $InstanceNr remove"
+  ocf_log info "Tried to remove shared memory resources using 'cleanipc $InstanceNr remove' as user $sidadm"
+
+  ocf_run rm -fv /usr/sap/$SID/$InstanceName/work/kill.sap
+  ocf_run rm -fv /usr/sap/$SID/$InstanceName/work/shutdown.sap
+  ocf_run rm -fv /usr/sap/$SID/$InstanceName/data/rslgcpid
+  ocf_run rm -fv /usr/sap/$SID/$InstanceName/data/rslgspid
+
+  return 0
+}
+
+#
+# sapinstance_start : Start the SAP instance
+#
+sapinstance_start() {
+
+  sapuserexit PRE_START_USEREXIT "$OCF_RESKEY_PRE_START_USEREXIT"
+
+  local rc=$OCF_NOT_RUNNING
+  local output=""
+  local loopcount=0
+
+  while [ $loopcount -lt 2 ]
+  do
+    loopcount=$(($loopcount + 1))
+
+    check_sapstartsrv
+    rc=$?
+    if [ $rc -eq $OCF_SUCCESS ]; then
+      output=`$SAPCONTROL -nr $InstanceNr -function Start`
+      rc=$?
+      ocf_log info "Starting SAP Instance $SID-$InstanceName: $output"
+    fi
+
+    if [ $rc -ne 0 ]
+    then
+      ocf_log err "SAP Instance $SID-$InstanceName start failed."
+      return $OCF_ERR_GENERIC
+    fi
+
+    local startrc=1
+    while [ $startrc -gt 0 ]
+    do
+      local waittime_start=`date +%s`
+      output=`$SAPCONTROL -nr $InstanceNr -function WaitforStarted $OCF_RESKEY_START_WAITTIME 10`
+      startrc=$?
+      local waittime_stop=`date +%s`
+
+      if [ $startrc -ne 0 ]
+      then
+        if [ $(($waittime_stop - $waittime_start)) -ge $OCF_RESKEY_START_WAITTIME ]
+        then
+          sapinstance_monitor NOLOG
+          if [ $? -eq $OCF_SUCCESS ]
+          then
+            output="START_WAITTIME ($OCF_RESKEY_START_WAITTIME) has elapsed, but instance monitor returned SUCCESS. Instance considered running."
+            startrc=0; loopcount=2
+          fi
+        else
+          if [ $loopcount -eq 1 ] && ocf_is_true $OCF_RESKEY_AUTOMATIC_RECOVER
+          then
+            ocf_log warn "SAP Instance $SID-$InstanceName start failed: $output"
+            ocf_log warn "Try to recover $SID-$InstanceName"
+            cleanup_instance
+          else
+            loopcount=2
+          fi
+          startrc=-1
+        fi
+      else
+        loopcount=2
+      fi
+    done
+  done
+
+  if [ $startrc -eq 0 ]
+  then
+    ocf_log info "SAP Instance $SID-$InstanceName started: $output"
+    rc=$OCF_SUCCESS
+    sapuserexit POST_START_USEREXIT "$OCF_RESKEY_POST_START_USEREXIT"
+  else
+    ocf_log err "SAP Instance $SID-$InstanceName start failed: $output"
+    rc=$OCF_NOT_RUNNING
+  fi
+
+  return $rc
+}
+
+
+#
+# sapinstance_recover: Try startup of failed instance by cleaning up resources
+#
+sapinstance_recover() {
+  cleanup_instance
+  sapinstance_start
+  return $?
+}
+
+
+#
+# sapinstance_stop: Stop the SAP instance
+#
+sapinstance_stop() {
+  local output=""
+  local rc
+
+  sapuserexit PRE_STOP_USEREXIT "$OCF_RESKEY_PRE_STOP_USEREXIT"
+
+  if [ "$OCF_RESKEY_SHUTDOWN_METHOD" = "KILL" ]
+  then
+    ocf_log info "Stopping SAP Instance $SID-$InstanceName with shutdown method KILL!"
+    cleanup_instance
+    return $OCF_SUCCESS
+  fi
+
+  check_sapstartsrv
+  rc=$?
+  if [ $rc -eq $OCF_SUCCESS ]; then
+    output=`$SAPCONTROL -nr $InstanceNr -function Stop`
+    rc=$?
+    ocf_log info "Stopping SAP Instance $SID-$InstanceName: $output"
+  fi
+
+  if [ $rc -eq 0 ]
+  then
+    output=`$SAPCONTROL -nr $InstanceNr -function WaitforStopped 3600 1`
+    if [ $? -eq 0 ]
+    then
+      ocf_log info "SAP Instance $SID-$InstanceName stopped: $output"
+      rc=$OCF_SUCCESS
+    else
+      ocf_log err "SAP Instance $SID-$InstanceName stop failed: $output"
+      rc=$OCF_ERR_GENERIC
+    fi
+  else
+    ocf_log err "SAP Instance $SID-$InstanceName stop failed: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+
+  sapuserexit POST_STOP_USEREXIT "$OCF_RESKEY_POST_STOP_USEREXIT"
+
+  return $rc
+}
+
+
+#
+# sapinstance_monitor: Can the given SAP instance do anything useful?
+#
+sapinstance_monitor() {
+  local MONLOG=$1
+  local rc
+
+  check_sapstartsrv
+  rc=$?
+
+  if [ $rc -eq $OCF_SUCCESS ]
+  then
+    local count=0
+    local SERVNO
+    local output
+
+    output=`$SAPCONTROL -nr $InstanceNr -function GetProcessList -format script`
+
+    # we have to parse the output, because the returncode doesn't tell anything about the instance status
+    for SERVNO in `echo "$output" | grep '^[0-9] ' | cut -d' ' -f1 | sort -u`
+    do
+      local COLOR=`echo "$output" | grep "^$SERVNO dispstatus: " | cut -d' ' -f3`
+      local SERVICE=`echo "$output" | grep "^$SERVNO name: " | cut -d' ' -f3`
+      local STATE=0
+      local SEARCH
+
+      case $COLOR in
+        GREEN|YELLOW)       STATE=$OCF_SUCCESS;;
+        *)                  STATE=$OCF_NOT_RUNNING;;
+      esac 
+
+      SEARCH=`echo "$OCF_RESKEY_MONITOR_SERVICES" | sed 's/\+/\\\+/g' | sed 's/\./\\\./g'`
+      if [ `echo "$SERVICE" | egrep -c "$SEARCH"` -eq 1 ]
+      then
+          if [ $STATE -eq $OCF_NOT_RUNNING ]
+          then
+            [ "$MONLOG" != "NOLOG" ] && ocf_log err "SAP instance service $SERVICE is not running with status $COLOR !"
+            rc=$STATE
+          fi
+          count=1
+      fi
+    done
+
+    if [ $count -eq 0 -a $rc -eq $OCF_SUCCESS ]
+    then
+      if ocf_is_probe
+      then
+        rc=$OCF_NOT_RUNNING
+      else
+        [ "$MONLOG" != "NOLOG" ] && ocf_log err "The SAP instance does not run any services which this RA could monitor!"
+        rc=$OCF_ERR_GENERIC
+      fi
+    fi
+  fi
+ 
+  return $rc
+}
+
+
+#
+# sapinstance_status: Lightweight check of SAP instance only with OS tools
+#
+sapinstance_status() {
+  local pid
+  local pids
+
+  [ ! -f "/usr/sap/$SID/$InstanceName/work/kill.sap" ] && return $OCF_NOT_RUNNING
+  pids=`grep '^kill -[0-9]' /usr/sap/$SID/$InstanceName/work/kill.sap | awk '{print $3}'`
+  for pid in $pids
+  do
+    [ `pgrep -f -U $sidadm $InstanceName | grep -c $pid` -gt 0 ] && return $OCF_SUCCESS
+  done
+  return $OCF_NOT_RUNNING
+}
+
+
+#
+# sapinstance_validate: Check the symantic of the input parameters 
+#
+sapinstance_validate() {
+  local rc=$OCF_SUCCESS
+  if [ `echo "$SID" | grep -c '^[A-Z][A-Z0-9][A-Z0-9]$'` -ne 1 ]
+  then
+    ocf_log err "Parsing instance profile name: '$SID' is not a valid system ID!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  if [ `echo "$InstanceName" | grep -c '^[A-Z].*[0-9][0-9]$'` -ne 1 ]
+  then
+    ocf_log err "Parsing instance profile name: '$InstanceName' is not a valid instance name!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  if [ `echo "$InstanceNr" | grep -c '^[0-9][0-9]$'` -ne 1 ]
+  then
+    ocf_log err "Parsing instance profile name: '$InstanceNr' is not a valid instance number!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  if [ `echo "$SAPVIRHOST" | grep -c '^[A-Za-z][A-Za-z0-9_-]*$'` -ne 1 ]
+  then
+    ocf_log err "Parsing instance profile name: '$SAPVIRHOST' is not a valid hostname!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  return $rc
+}
+
+
+#
+# sapinstance_start_clone
+#
+sapinstance_start_clone() {
+  sapinstance_init $OCF_RESKEY_ERS_InstanceName
+  ${HA_SBIN_DIR}/crm_master -v 50 -l reboot
+  sapinstance_start
+  return $?
+}
+
+
+#
+# sapinstance_stop_clone
+#
+sapinstance_stop_clone() {
+  sapinstance_init $OCF_RESKEY_ERS_InstanceName
+  ${HA_SBIN_DIR}/crm_master -v 0 -l reboot
+  sapinstance_stop
+  return $?
+}
+
+
+#
+# sapinstance_monitor_clone
+#
+sapinstance_monitor_clone() {
+  # first check with the status function (OS tools) if there could be something like a SAP instance running
+  # as we do not know here, if we are in master or slave state we do not want to start our monitoring
+  # agents (sapstartsrv) on the wrong host
+  local rc
+
+  sapinstance_init $OCF_RESKEY_InstanceName
+  if sapinstance_status; then
+    if sapinstance_monitor; then
+      ${HA_SBIN_DIR}/crm_master -Q -v 100 -l reboot
+      return $OCF_RUNNING_MASTER
+    fi
+    # by nature of the SAP enqueue server we have to make sure
+    # that we do a failover to the slave (enqueue replication server)
+    # in case the enqueue process has failed. We signal this to the
+    # cluster by setting our master preference to a lower value than the slave.
+    ${HA_SBIN_DIR}/crm_master -v 10 -l reboot
+    return $OCF_FAILED_MASTER
+  fi
+
+  sapinstance_init $OCF_RESKEY_ERS_InstanceName
+  sapinstance_status && sapinstance_monitor
+  rc=$?
+  if [ $rc -eq $OCF_SUCCESS ]; then
+    ${HA_SBIN_DIR}/crm_master -Q -v 100 -l reboot
+  fi
+  return $rc
+}
+
+
+#
+# sapinstance_promote_clone: In a Master/Slave configuration get Master by starting the SCS instance and stopping the ERS instance
+#                            The order is important here to behave correct from the application levels view
+#
+sapinstance_promote_clone() {
+  local rc
+
+  sapinstance_init $OCF_RESKEY_InstanceName
+  ocf_log info "Promoting $SID-$InstanceName to running Master."
+  sapinstance_start
+  rc=$?
+
+  if [ $rc -eq $OCF_SUCCESS ]; then
+    sapinstance_init $OCF_RESKEY_ERS_InstanceName
+    sapinstance_stop
+    rc=$?
+  fi
+
+  return $rc
+}
+
+
+#
+# sapinstance_demote_clone: In a Master/Slave configuration get Slave by stopping the SCS instance and starting the ERS instance
+#
+sapinstance_demote_clone() {
+  local rc
+
+  sapinstance_init $OCF_RESKEY_InstanceName
+  ocf_log info "Demoting $SID-$InstanceName to a slave."
+  sapinstance_stop
+  rc=$?
+
+  if [ $rc -eq $OCF_SUCCESS ]; then
+    sapinstance_init $OCF_RESKEY_ERS_InstanceName
+    sapinstance_start
+    rc=$?
+  fi
+
+  return $rc
+}
+
+
+#
+# sapinstance_notify: Handle master scoring - to make sure a slave gets the next master
+#
+sapinstance_notify() {
+  local n_type="$OCF_RESKEY_CRM_meta_notify_type"
+  local n_op="$OCF_RESKEY_CRM_meta_notify_operation"
+
+  if [ "${n_type}_${n_op}" = "post_promote" ]; then
+    # After promotion of one master in the cluster, we make sure that all clones reset their master
+    # value back to 100. This is because a failed monitor on a master might have degree one clone
+    # instance to score 10.
+    ${HA_SBIN_DIR}/crm_master -v 100 -l reboot
+  elif [ "${n_type}_${n_op}" = "pre_demote" ]; then
+    # if we are a slave and a demote event is anounced, make sure we have the highes wish to became master
+    # that is, when a slave resource was startet after the promote event of a already running master (e.g. node of slave was down)
+    # We also have to make sure to overrule the globaly set resource_stickiness or any fail-count factors => INFINITY
+    local n_uname="$OCF_RESKEY_CRM_meta_notify_demote_uname"
+    if [ ${n_uname} != ${NODENAME} ]; then
+      ${HA_SBIN_DIR}/crm_master -v INFINITY -l reboot
+    fi
+  fi
+}
+
+
+#
+#	'main' starts here...
+#
+
+## GLOBALS
+SID=""
+sidadm=""
+InstanceName=""
+InstanceNr=""
+SAPVIRHOST=""
+DIR_EXECUTABLE=""
+SAPSTARTSRV=""
+SAPCONTROL=""
+DIR_PROFILE=""
+SAPSTARTPROFILE=""
+CLONE=0
+NODENAME=$(ocf_local_nodename)
+
+
+if
+  ( [ $# -ne 1 ] )
+then
+  sapinstance_usage
+  exit $OCF_ERR_ARGS
+fi
+
+ACTION=$1
+if [ "$ACTION" = "status" ]; then
+  ACTION=monitor
+fi
+
+# These operations don't require OCF instance parameters to be set
+case "$ACTION" in
+  usage|methods)                sapinstance_$ACTION
+                                exit $OCF_SUCCESS;;
+  meta-data)                    sapinstance_meta_data
+                                exit $OCF_SUCCESS;;
+  notify)                       sapinstance_notify
+                                exit $OCF_SUCCESS;;
+  *);;
+esac
+
+if ! ocf_is_root
+then
+  ocf_log err "$0 must be run as root"
+  exit $OCF_ERR_PERM
+fi
+
+# parameter check
+if  [ -z "$OCF_RESKEY_InstanceName" ]
+then
+  ocf_log err "Please set OCF_RESKEY_InstanceName to the name to the SAP instance profile!"
+  exit $OCF_ERR_ARGS
+fi
+
+is_clone; CLONE=$?
+if [ ${CLONE} -eq 1 ]
+then
+  CLACT=_clone
+else
+  if [ "$ACTION" = "promote" -o "$ACTION" = "demote" ]
+  then
+    ocf_log err "$ACTION called in a non master/slave environment"
+    exit $OCF_ERR_ARGS
+  fi
+  sapinstance_init $OCF_RESKEY_InstanceName
+fi
+
+# What kind of method was invoked?
+case "$ACTION" in
+  start|stop|monitor|promote|demote)      sapinstance_$ACTION$CLACT
+                                          exit $?;;
+  validate-all)                           sapinstance_validate
+                                          exit $?;;
+  *)                                      sapinstance_methods
+                                          exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/heartbeat/SendArp b/heartbeat/SendArp
new file mode 100755
index 0000000..675070c
--- /dev/null
+++ b/heartbeat/SendArp
@@ -0,0 +1,267 @@
+#!/bin/sh
+#
+#
+#	Copyright (c) 2006, Huang Zhen <zhen.huang at gmail.com>
+#	Converting original heartbeat RA to OCF RA.
+#
+#	Copyright (C) 2004 Horms <horms at verge.net.au>
+#
+#       Based on IPaddr2: Copyright (C) 2003 Tuomo Soini <tis at foobar.fi>
+#
+# 	License:      GNU General Public License (GPL)
+# 	Support:      linux-ha at lists.linux-ha.org
+#
+#	This script send out gratuitous Arp for an IP address
+#
+#       It can be used _instead_ of the IPaddr2 or IPaddr resource
+#       to send gratuitous arp for an IP address on a given interface, 
+#       without adding the address to that interface. I.e. if for
+#       some reason you want to send gratuitous arp for addresses
+#       managed by IPaddr2 or IPaddr on an additional interface.
+#
+#	OCF parameters are as below:
+#		OCF_RESKEY_ip
+#		OCF_RESKEY_nic
+#
+#
+# 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.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+SENDARP=$HA_BIN/send_arp
+SENDARPPIDDIR=${HA_RSCTMP}
+
+BASEIP="$OCF_RESKEY_ip"
+INTERFACE="$OCF_RESKEY_nic"
+RESIDUAL=""
+SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$BASEIP"
+BACKGROUND=${OCF_RESKEY_background:-"yes"}
+
+# Set default values
+
+	: ${ARP_INTERVAL_MS=200}	# milliseconds between ARPs
+	: ${ARP_REPEAT=5}		# repeat count
+	: ${ARP_BACKGROUND=$BACKGROUND}	# no to run in foreground
+	: ${ARP_NETMASK=ffffffffffff}	# netmask for ARP
+
+#######################################################################
+
+sendarp_meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="SendArp" version="1.0">
+<version>1.0</version>
+
+<longdesc lang="en">
+This RA can be used _instead_ of the IPaddr2 or IPaddr RA to
+send gratuitous ARP for an IP address on a given interface, 
+without adding the address to that interface.  For example,
+if for some resaon you wanted to send gratuitous ARP for
+addresses managed by IPaddr2 or IPaddr on an additional
+interface.
+</longdesc>
+<shortdesc lang="en">Broadcasts unsolicited ARP announcements</shortdesc>
+
+<parameters>
+<parameter name="ip" unique="0" required="1">
+<longdesc lang="en">
+The IP address for sending ARP packet.
+</longdesc>
+<shortdesc lang="en">IP address</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="nic" unique="0" required="1">
+<longdesc lang="en">
+The NIC for sending ARP packet.
+</longdesc>
+<shortdesc lang="en">NIC</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="background" unique="0" required="0">
+<longdesc lang="en">
+Send ARPs in background. Set to false if you want to test if
+sending ARPs succeeded.
+</longdesc>
+<shortdesc lang="en">Send ARPs in background</shortdesc>
+<content type="boolean" default="true" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" depth="0"  timeout="20" interval="10" />
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="20s" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+sendarp_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+#
+#	Send gratuitous arp
+#
+sendarp_start() {
+    local rc
+
+    sendarp_validate
+    if [ $? = $OCF_ERR_CONFIGURED ]; then
+	return $OCF_ERR_CONFIGURED
+    fi
+    
+    sendarp_monitor
+    if [ $? = $OCF_SUCCESS ]; then
+	return $OCF_SUCCESS
+    fi
+    
+    [ -r ${HA_CONFDIR}/arp_config ] && . ${HA_CONFDIR}/arp_config
+    if [ -r "${HA_CONFDIR}/arp_config:${TARGET_INTERFACE}" ]; then
+	. "${HA_CONFDIR}/arp_config:${TARGET_INTERFACE}"
+    fi
+
+
+    ARGS="-i $ARP_INTERVAL_MS -r $ARP_REPEAT -p $SENDARPPIDFILE $INTERFACE $BASEIP auto $BASEIP $ARP_NETMASK"
+    ocf_log debug "$SENDARP $ARGS"
+
+    rc=$OCF_SUCCESS
+    if ocf_is_true $ARP_BACKGROUND; then
+	# not possible to check the status without wait! we can
+	# just log the outcome
+	# and wait-ing would be equal to not running in
+	# background
+	($SENDARP $ARGS ||
+	    ocf_log err "Could not send gratuitous arps") &
+    else
+	$SENDARP $ARGS || {
+	    ocf_log err "Could not send gratuitous arps"
+	    rc=$OCF_ERR_GENERIC
+	}
+    fi
+
+    if [ $rc -eq $OCF_SUCCESS ]; then
+	ha_pseudo_resource SendArp_${OCF_RESOURCE_INSTANCE} start
+    fi
+    return $rc
+}
+
+#
+#	Stop sending gratuitous arp
+#
+sendarp_stop() {
+    sendarp_monitor
+    if [ $? -eq $OCF_NOT_RUNNING ]; then
+	return $OCF_SUCCESS
+    fi
+ 
+    rc=$OCF_SUCCESS
+    
+    if
+	[ -f "$SENDARPPIDFILE" ]
+    then
+	kill `cat "$SENDARPPIDFILE"`
+	rc=$?
+	case $rc in
+	    0)
+		ocf_log info "killed previously running send_arp for $BASEIP"
+		rm -f "$SENDARPPIDFILE"
+		rc=$OCF_SUCCESS
+		;;
+	    *)
+		ocf_log warn "Could not kill previously running send_arp for $BASEIP"
+		rc=$OCF_ERR_GENERIC
+		;;
+	esac
+    fi
+
+    case $rc in
+	$OCF_SUCCESS)
+	    ocf_log info "SendArp for $BASEIP/$INTERFACE released"
+	    ha_pseudo_resource SendArp_${OCF_RESOURCE_INSTANCE} stop
+	    ;;
+	*)
+	    ocf_log warn "SendArp for $BASEIP/$INTERFACE NOT released"
+	    ;;
+    esac
+    return $rc
+}
+#
+sendarp_monitor() {
+    if [ -f "$SENDARPPIDFILE" ]; then
+    	return $OCF_SUCCESS
+    fi
+    ha_pseudo_resource SendArp_${OCF_RESOURCE_INSTANCE} monitor
+}
+
+sendarp_validate() {
+    if [ -z "$INTERFACE" -o -z "$BASEIP" -o -n "$RESIDUAL" ]
+    then
+        return $OCF_ERR_CONFIGURED
+    fi
+    return $OCF_SUCCESS
+}
+
+case $__OCF_ACTION in
+meta-data)	sendarp_meta_data
+		exit $OCF_SUCCESS
+		;;
+start)		sendarp_start
+		;;
+stop)		sendarp_stop
+		;;
+monitor)	sendarp_monitor
+		;;
+status)		sendarp_monitor
+		if [ $? = $OCF_SUCCESS ]; then
+			echo "running"
+			exit $OCF_SUCCESS;
+		else 
+			echo "stopped"
+			exit $OCF_NOT_RUNNING;
+    		fi
+    		;;
+validate-all)	sendarp_validate
+		;;
+usage|help)	sendarp_usage
+		exit $OCF_SUCCESS
+		;;
+*)		sendarp_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+
diff --git a/heartbeat/ServeRAID b/heartbeat/ServeRAID
new file mode 100755
index 0000000..4ab70fb
--- /dev/null
+++ b/heartbeat/ServeRAID
@@ -0,0 +1,419 @@
+#!/bin/sh
+#
+# 
+# ServeRAID
+#
+# Description:	Enables/Disables shared ServeRAID merge groups
+#
+# Author:	Alan Robertson, Renzo Alejandro Granados
+#
+# Support:	linux-ha at lists.linux-ha.org
+#
+# License:	GNU General Public License (GPL)
+#
+# Copyright:	(C) 2002-2005 International Business Machines
+#		(C) 2002 Renzo Alejandro Granados
+#
+# usage: ./ServeRAID (start|stop|status|monitor|validate-all|meta-data)
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_serveraid
+#                  (Adapter number of the ServeRAID adapter)
+#		OCF_RESKEY_mergegroup
+#                  (MergeGroup # of the logical drive under consideration)
+#
+# The ServeRAID clustering model is a bit odd, and its terminology needs
+# a little explanation
+#
+#	Logical Volume - a particular SCSI id {target id and LUN} on
+#		a particular controller.
+#
+#	Merge Group - when active on one side or the other of the ServeRAID
+#		configuration it corresponds with a logical drive.
+#		Merge group numbers are permanently assigned to a particular
+#		chunk of storage.  Shared merge groups are in the
+#		range of 1 to 8, and are largely arbitrary.
+#		Unshared merge groups start at 200.
+#		We can only deal with shared merge groups.  When a merge
+#		group is activated on one of the controllers, it becomes
+#		a logical volume on that system.  NOTE:  The order in
+#		which the Merge Groups are activated determines which
+#		SCSI Ids they become.  This makes for extra headaches
+#		for this script to deal with.  It also means that if
+#		you have more than one shared ServeRAID merge group on
+#		a particular controller, that the SCSI IDs will not
+#		be constant.  This requires mounting by uuid or label.
+#
+#	One of the ServerRAID controllers has to be configured with
+#	SCSI initiator ID 6, and the other with SCSI id 7.
+#
+#	At this time, the ServeRAID clustering solution only works with
+#	RAID 1 setups.  It does NOT support RAID 5.  This is a firmware
+#	bug in the ServeRAID where it doesn't fail over correctly
+#	if the RAID5 array is in a critical state...
+#
+#	Note that this script requires ServeRAID software version 6.10 or
+#	later.  This software is now available from IBM.
+#
+# An example usage in /etc/ha.d/haresources: 
+#       node1  10.0.0.170 ServeRAID::1::1
+#
+
+#	Older ServeRAID utility returns 1 when it succeeds (weird)
+#	BUT - the newly released version is more normal...
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+srsuccess=0
+SCSI="scsi "
+
+usage() {
+  cat <<-!
+	usage: $0 (start|stop|status|monitor|validate-all|meta-data)
+
+	You have to set the following environment virables before running $0 :
+		OCF_RESKEY_serveraid
+			(Adapter number of the ServeRAID adapter)
+		OCF_RESKEY_mergegroup
+			(MergeGroup # of the logical drive under consideration)
+
+	ServeRAID adapters are numbered starting from 1.
+
+	The shared merge group number is a number between 1 and 8 inclusive.
+	It indicates to the controller which logical disk to fail over.
+
+                node1  10.0.0.170 ServeRAID::1::1
+
+	PREREQUISITES:
+	You must configure your ServeRAID adapters for clustering for this
+	to work.
+
+	To do this, you must use the bootable "ServeRAID Support CD" and right
+	click your controller and pick "configure for clustering".  The Linux
+	version of the ServeRAID manager does not have the "configure for
+	clustering" option.
+
+	You will need at least version 6.10 (~July 2003 release) of the ipssend
+	command for this script to work.
+
+	!
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="ServeRAID">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for ServeRAID. It enables/disables shared ServeRAID merge groups.
+</longdesc>
+<shortdesc lang="en">Enables and disables shared ServeRAID merge groups</shortdesc>
+
+<parameters>
+<parameter name="serveraid" unique="0" required="1">
+<longdesc lang="en">
+The adapter number of the ServeRAID adapter.
+</longdesc>
+<shortdesc lang="en">serveraid</shortdesc>
+<content type="integer" default="" />
+</parameter>
+
+<parameter name="mergegroup" unique="0" required="1">
+<longdesc lang="en">
+The logical drive under consideration. 
+</longdesc>
+<shortdesc lang="en">mergegroup</shortdesc>
+<content type="integer" default="" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="40" />
+<action name="stop" timeout="40" />
+<action name="status" depth="0" timeout="20" interval="10" />
+<action name="monitor" depth="0" timeout="20" interval="10" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+<action name="methods" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+ServeRAID_methods() {
+  cat <<-!
+	start
+	stop
+	status
+	validate-all
+	methods
+	usage
+	meta-data
+	!
+}
+
+ServeRAIDSCSI="/proc/scsi/ips"
+
+ 
+IPS=ipssend
+proc_scsi=/proc/scsi/scsi
+
+
+parseinst() {
+  sr_adapter=error
+  sr_mergegroup=error
+  hostid=error
+  sr_logicaldrivenumber=error
+  if
+    [ $# -ne 2 ]
+  then
+    ocf_log err "Invalid ServeRAID instance: $*"
+    exit $OCF_ERR_ARGS
+  fi
+  PerlScript='next unless /^Host/; $_ .= <>.<>; print "$1 " if /SERVERAID/ and /Proces/ and /scsi(\d+)/'
+  # Get the list of host ids of the ServeRAID host adapters
+  hostlist=`$PERL -ne "${PerlScript}" <$proc_scsi`
+  # Figure the host id of the desired ServeRAID adapter
+  hostid=`echo $hostlist | cut -d' ' -f$1`
+  if
+    [ ! -f "$ServeRAIDSCSI/$hostid" ]
+  then
+    ocf_log err "No such ServeRAID adapter: $1"
+    exit $OCF_ERR_ARGS
+  fi
+    
+  case $2 in
+    [1-8]);;
+    *)	ocf_log err "Invalid Shared Merge Group Number: $2"
+	exit $OCF_ERR_ARGS;;
+  esac
+  sr_adapter=$1
+  sr_mergegroup=$2
+  CheckRaidLevel
+  return $?
+}
+
+SRLogicalDriveConfig() {
+  $IPS getconfig $sr_adapter ld
+}
+
+MergeGroupToSCSI_ID() {
+
+  PerlScript="while (<>) {
+	/logical drive number *([0-9]+)/i && (\$ld=\$1);
+	/part of merge group *: *$sr_mergegroup *\$/i && print \$ld - 1, \"\n\";
+  }"
+
+  ID=`SRLogicalDriveConfig | $PERL -e "$PerlScript"`
+  case $ID in
+    [0-9]*)	echo "$ID"; return 0;;
+    *)		return 1;;
+  esac
+}
+
+MergeGroupRaidLevel() {
+
+  PerlScript="while (<>) {
+	/RAID level *: *([0-9]+[A-Za-z]*)/i && (\$ld=\$1);
+	/part of merge group *: *$sr_mergegroup *\$/i && print \$ld, \"\n\";
+  }"
+
+  Level=`SRLogicalDriveConfig | $PERL -e "$PerlScript"`
+  case $Level in
+    ?*)	echo "$Level"; return 0;;
+    *)		return 1;;
+  esac
+}
+
+CheckRaidLevel() {
+  RAIDlevel=`MergeGroupRaidLevel`
+  case $RAIDlevel in
+    *5*)
+      ocf_log err "ServeRAID device $sr_adapter $sr_mergegroup is RAID level $RAIDlevel"
+      ocf_log err "This level of ServeRAID RAID is not supported for failover by the firmware."
+      exit $OCF_ERR_GENERIC;;
+  esac
+  return $OCF_SUCCESS
+}
+
+    
+	
+
+ReleaseSCSI() {
+  targetid=`MergeGroupToSCSI_ID`
+  echo "${SCSI}remove-single-device $hostid 0 $targetid 0" > $proc_scsi
+}
+
+AddSCSI() {
+  targetid=`MergeGroupToSCSI_ID`
+  echo "${SCSI}add-single-device $hostid 0 $targetid 0" > $proc_scsi
+}
+
+#
+# start: Enable the given ServeRAID device
+#
+ServeRAID_start() {
+  if
+     ServeRAID_status $serveraid $mergegroup
+  then
+     ocf_log debug "ServeRAID merge group $serveraid $mergegroup is running."
+     return $OCF_SUCCESS
+  else
+    if
+      #
+      # Normally we do a MERGE PARTNER, but if we still own the drive for
+      # some reason, then we'll need to do a MERGE OWN instead...
+      #
+      out=`$IPS MERGE $sr_adapter $sr_mergegroup PARTNER 2>&1`
+      if
+        [ $? -eq $srsuccess ]
+      then
+	ocf_log info "$out"
+      else
+        ocf_run $IPS MERGE $sr_adapter $sr_mergegroup OWN
+      fi
+    then
+      : OK All is well!
+      targetid=`MergeGroupToSCSI_ID`
+      sr_logicaldrivenumber=`expr $targetid + 1`
+      #run $IPS SYNCH $sr_adapter $sr_logicaldrivenumber &
+      # This version of the SYNCH command requires the 6.10 or later
+      # ServeRAID support CD.
+      # To avoid issues when called by lrmd, redirect stdout->stderr.
+      # Use () to create a subshell to make the redirection be synchronized.
+      ( ocf_run $IPS SYNCH $sr_adapter $sr_mergegroup & ) >&2
+      AddSCSI
+    else
+      return $OCF_ERR_GENERIC
+    fi
+  fi
+  if
+    ServeRAID_status "$@"
+  then
+    return $OCF_SUCCESS
+  else
+    ocf_log err "ServeRAID device $1 not active!"
+    exit $OCF_ERR_GENERIC
+  fi
+}
+
+
+#
+# stop: Disable the given ServeRAID device
+#
+ServeRAID_stop() {
+  parseinst "$@"
+  ReleaseSCSI
+  if
+    ocf_run $IPS UNMERGE $sr_adapter $sr_mergegroup
+  then
+    : UNMERGE $sr_adapter $sr_mergegroup worked
+  fi
+  if
+    ServeRAID_status "$@"
+  then
+    ocf_log err "ServeRAID device $@ is still active!"
+    return $OCF_ERR_GENERIC
+  else
+    return $OCF_SUCCESS
+  fi
+}
+
+
+#
+# status: is the given device now available?
+#
+ServeRAID_status() {
+  parseinst "$@"
+  #
+  # The output we're looking for
+  #	Part of merge group            : 2   
+  #
+  SRLogicalDriveConfig 		\
+  |	grep -i "part of merge group[ 	]*: *$sr_mergegroup *\$" >/dev/null
+}
+
+#
+# validate_all: are the OCF instance parameters valid?
+#
+ServeRAID_validate_all() {
+  check_binary $PERL
+
+# parseinst() will do all the work...
+  parseinst "$@"
+  return $?
+}
+
+if
+  ( [ $# -ne 1 ] )
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+# These operations don't require OCF instance parameters to be set
+case "$1" in
+  meta-data)
+	meta_data
+	exit $OCF_SUCCESS;;
+#
+# methods: What methods do we support?
+#
+  methods) 
+	ServeRAID_methods
+	exit $?;;
+  usage)
+	usage
+	exit $OCF_SUCCESS;;
+  *)
+	;;
+esac
+
+if 
+  ( [ -z "$OCF_RESKEY_serveraid" ] || [ -z "$OCF_RESKEY_mergegroup" ] )
+then
+  ocf_log err "You have to set the OCF_RESKEY_serveraid and OCF_RESKEY_mergegroup\n 
+        enviroment virables before running $0 !"
+#  usage
+  exit $OCF_ERR_GENERIC
+fi
+
+: Right Number of arguments..
+serveraid=$OCF_RESKEY_serveraid
+mergegroup=$OCF_RESKEY_mergegroup
+
+# Look for the start, stop, status, or methods calls...
+case "$1" in
+  stop)
+	ServeRAID_stop $serveraid $mergegroup
+	exit $?;;
+  start)
+	ServeRAID_start $serveraid $mergegroup
+	exit $?;;
+  status|monitor) 
+	if
+	  ServeRAID_status $serveraid $mergegroup
+	then
+	  ocf_log debug "ServeRAID merge group $serveraid $mergegroup is running."
+	  exit $OCF_SUCCESS
+	else
+	  ocf_log debug "ServeRAID merge group $serveraid $mergegroup is stopped."
+	  exit $OCF_NOT_RUNNING
+	fi
+	exit $?;;
+  validate-all)
+	ServeRAID_validate_all $serveraid $mergegroup
+	exit $?;;
+  *)
+    usage
+    exit $OCF_ERR_UNIMPLEMENTED;;
+
+esac
diff --git a/heartbeat/SphinxSearchDaemon b/heartbeat/SphinxSearchDaemon
new file mode 100755
index 0000000..f110928
--- /dev/null
+++ b/heartbeat/SphinxSearchDaemon
@@ -0,0 +1,223 @@
+#!/bin/sh
+#
+#
+#	Searchd OCF RA. 
+#	Manages the Sphinx search daemon
+#
+# Copyright (c) 2007 Christian Rishoj (christian at rishoj.net)
+#                    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.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="SphinxSearchDaemon" version="0.9">
+<version>1.0</version>
+
+<longdesc lang="en">
+This is a searchd Resource Agent. It manages the Sphinx Search Daemon.
+</longdesc>
+<shortdesc lang="en">Manages the Sphinx search daemon.</shortdesc>
+
+<parameters>
+
+<parameter name="config" required="0" unique="1">
+<longdesc lang="en">
+searchd configuration file
+</longdesc>
+<shortdesc lang="en">Configuration file</shortdesc>
+<content type="string" default="/etc/sphinx/sphinx.conf" />
+</parameter>
+
+<parameter name="searchd" required="0" unique="0">
+<longdesc lang="en">
+searchd binary
+</longdesc>
+<shortdesc lang="en">searchd binary</shortdesc>
+<content type="string" default="/usr/local/bin/searchd" />
+</parameter>
+
+<parameter name="search" required="0" unique="0">
+<longdesc lang="en">
+Search binary for functional testing in the monitor action.
+</longdesc>
+<shortdesc lang="en">search binary</shortdesc>
+<content type="string" default="/usr/local/bin/search" />
+</parameter>
+
+<parameter name="testQuery" required="0" unique="0">
+<longdesc lang="en">
+Test query for functional testing in the monitor action.
+The query does not need to match any documents in the index.
+The purpose is merely to test whether the search daemon is
+is able to query its indices and respond properly. 
+</longdesc>
+<shortdesc lang="en">test query</shortdesc>
+<content type="string" default="Heartbeat_Monitor_Query_Match_string" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="20s" />
+<action name="stop"         timeout="20s" />
+<action name="monitor"      timeout="20" interval="10" depth="0" />
+<action name="meta-data"    timeout="5" />
+<action name="validate-all"   timeout="20s" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+searchd_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+searchd_start() {
+    if ! searchd_validate ; then
+	return $OCF_ERR_GENERIC
+    fi 
+    if ! searchd_status ; then
+	$OCF_RESKEY_searchd --config $OCF_RESKEY_config
+	if [ $? != 0 ]; then 
+	    return $OCF_ERR_GENERIC
+	fi	    
+    fi
+    if searchd_check ; then
+	return $OCF_SUCCESS
+    else	
+	return $OCF_ERR_GENERIC
+    fi
+}
+
+searchd_stop() {
+    if ! searchd_validate ; then
+	return $OCF_ERR_GENERIC
+    fi 
+    if searchd_status ; then 
+	$OCF_RESKEY_searchd --config $OCF_RESKEY_config --stop
+	if [ $? = 0 ]; then
+	    return $OCF_SUCCESS
+	else	    
+	    return $OCF_ERR_GENERIC
+	fi
+    else
+	return $OCF_SUCCESS
+    fi
+}
+
+isRunning()
+{
+    kill -s 0 "$1" > /dev/null && [ `ps -p "$1" | grep searchd | wc -l` -eq 1 ]
+}
+
+searchd_status() {
+    pidfile=`grep -v "^#" "$OCF_RESKEY_config" | grep -w pid_file | awk -F "[ \t]*=[ \t]*" '{ print $2 }'`
+    if [ -f "$pidfile" ] ; then 
+	PID=`head -n 1 $pidfile`
+	if [ ! -z "$PID" ] ; then 
+	    isRunning "$PID" 
+	    if [ $? = 0 ] ; then
+		return 0
+	    fi
+	fi
+    fi
+    false
+}
+
+searchd_check() {
+    $OCF_RESKEY_search --config $OCF_RESKEY_config --noinfo "$OCF_RESKEY_testQuery" > /dev/null
+}
+
+searchd_monitor() {
+    if ! searchd_validate ; then
+	return $OCF_NOT_RUNNING
+    fi 
+    if searchd_status ; then 
+	if searchd_check ; then
+	    return $OCF_SUCCESS
+	else	    
+	    return $OCF_ERR_GENERIC
+	fi
+    else
+	return $OCF_NOT_RUNNING
+    fi
+}
+
+searchd_validate() {
+    if [ ! -x "$OCF_RESKEY_search" ]; then
+	ocf_log err "search binary '$OCF_RESKEY_search' does not exist or cannot be executed"
+	return $OCF_ERR_ARGS
+    fi
+
+    if [ ! -x "$OCF_RESKEY_searchd" ]; then
+	ocf_log err "searchd binary '$OCF_RESKEY_searchd' does not exist or cannot be executed"
+	return $OCF_ERR_ARGS
+    fi
+
+    if [ ! -f "$OCF_RESKEY_config" ]; then
+	ocf_log err "config file '$OCF_RESKEY_config' does not exist"
+	return $OCF_ERR_ARGS
+    fi
+
+    return $OCF_SUCCESS
+}
+
+: ${OCF_RESKEY_config=/etc/sphinx/sphinx.conf} 
+: ${OCF_RESKEY_search=/usr/local/bin/search}
+: ${OCF_RESKEY_searchd=/usr/local/bin/searchd}
+: ${OCF_RESKEY_testQuery=Heartbeat_Monitor_Query_Match_string} 
+
+case $__OCF_ACTION in
+meta-data)	meta_data
+		exit $OCF_SUCCESS
+		;;
+start)		searchd_start;;
+stop)		searchd_stop;;
+monitor)	searchd_monitor;;
+validate-all)	searchd_validate;;
+usage|help)	searchd_usage
+		exit $OCF_SUCCESS
+		;;
+*)		searchd_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
+
diff --git a/heartbeat/Squid b/heartbeat/Squid
new file mode 100755
index 0000000..28e2db5
--- /dev/null
+++ b/heartbeat/Squid
@@ -0,0 +1,446 @@
+#!/bin/bash
+#
+# Description:  Manages a Squid Server provided by NTT OSSC as an 
+#               OCF High-Availability resource under Heartbeat/LinuxHA control
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# Copyright (c) 2008 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+#
+#######################################################################
+# OCF parameters:
+#   OCF_RESKEY_squid_exe    : Executable file
+#   OCF_RESKEY_squid_conf   : Configuration file
+#   OCF_RESKEY_squid_pidfile: Process id file
+#   OCF_RESKEY_squid_port   : Port number
+#   OCF_RESKEY_debug_mode   : Debug mode
+#   OCF_RESKEY_debug_log    : Debug log file
+#   OCF_RESKEY_squid_stop_timeout:
+#                             Number of seconds to await to confirm a
+#                             normal stop method
+#
+#   OCF_RESKEY_squid_exe, OCF_RESKEY_squid_conf, OCF_RESKEY_squid_pidfile
+#   and OCF_RESKEY_squid_port must be specified. Each of the rests
+#   has its default value or refers OCF_RESKEY_squid_conf to make
+#   its value when no explicit value is given.
+###############################################################################
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+usage() 
+{
+	cat <<-!
+usage: $0 action
+
+action:
+        start       : start a new squid instance
+
+        stop        : stop the running squid instance
+
+        status      : return the status of squid, run or down
+
+        monitor     : return TRUE if the squid appears to be working.
+
+        meta-data   : show meta data message
+
+        validate-all: validate the instance parameters
+!
+	return $OCF_ERR_ARGS
+}
+
+metadata_squid()
+{
+    cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Squid">
+<version>1.0</version>
+
+<longdesc lang="en">
+The resource agent of Squid.
+This manages a Squid instance as an HA resource.
+</longdesc>
+<shortdesc lang="en">Manages a Squid proxy server instance</shortdesc>
+
+<parameters>
+
+<parameter name="squid_exe" required="1" unique="0">
+<longdesc lang="en">
+This is a required parameter. This parameter specifies squid's
+executable file.
+</longdesc>
+<shortdesc>Executable file</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="squid_conf" required="1" unique="1">
+<longdesc lang="en">
+This is a required parameter. This parameter specifies a configuration file
+for a squid instance managed by this RA.
+</longdesc>
+<shortdesc>Configuration file</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="squid_pidfile" required="1" unique="1">
+<longdesc lang="en">
+This is a required parameter. This parameter specifies a process id file
+for a squid instance managed by this RA.
+</longdesc>
+<shortdesc>Pidfile</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="squid_port" required="1" unique="1">
+<longdesc lang="en">
+This is a required parameter. This parameter specifies a port number
+for a squid instance managed by this RA. If plural ports are used,
+you must specifiy the only one of them.
+</longdesc>
+<shortdesc>Port number</shortdesc>
+<content type="integer" default=""/>
+</parameter>
+
+<parameter name="squid_stop_timeout" unique="0">
+<longdesc lang="en">
+On stop, a squid shutdown is invoked first. If the resource
+doesn't stop within this timeout, we resort to stopping
+processes by sending signals and finally KILLing them.
+</longdesc>
+<shortdesc>how long to wait for squid shutdown to stop the
+instance before resorting to kill</shortdesc>
+<content type="integer" default="10"/>
+</parameter>
+
+<parameter name="debug_mode" unique="0">
+<longdesc lang="en">
+This is an optional parameter.
+This RA runs in debug mode when this parameter includes 'x' or 'v'.
+If 'x' is included, both of STDOUT and STDERR redirect to the logfile
+specified by "debug_log", and then the builtin shell option 'x' is turned on.
+It is similar about 'v'.
+</longdesc>
+<shortdesc>Debug mode</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="debug_log" unique="0">
+<longdesc lang="en">
+This is an optional and omittable parameter.
+This parameter specifies a destination file for debug logs
+and works only if this RA run in debug mode.  Refer to "debug_mode"
+about debug mode. If no value is given but it's requied, it's made by the
+following rules: "/var/log/" as a directory part, the basename of
+the configuration file given by "syslog_ng_conf" as a basename part,
+".log" as a suffix.
+</longdesc>
+<shortdesc>A destination of the debug log</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="60s" />
+<action name="stop" timeout="120s" />
+<action name="status" timeout="60" />
+<action name="monitor" depth="0" timeout="30s" interval="10s" />
+<action name="meta-data" timeout="5s" />
+<action name="validate-all"  timeout="5"/>
+</actions>
+</resource-agent>
+END
+
+	return $OCF_SUCCESS
+}
+
+get_pids()
+{
+	SQUID_PIDS=( )
+
+	# Seek by pattern
+	SQUID_PIDS[0]=$(pgrep -f "$PROCESS_PATTERN")
+
+	# Seek by pidfile
+	SQUID_PIDS[1]=$(awk '1{print $1}' $SQUID_PIDFILE 2>/dev/null)
+
+	if [[ -n "${SQUID_PIDS[1]}" ]]; then
+		typeset exe
+		exe=$(ls -l "/proc/${SQUID_PIDS[1]}/exe")
+		if [[ $? = 0 ]]; then
+			exe=${exe##*-> }
+			if ! [[ "$exe" = $SQUID_EXE ]]; then
+				SQUID_PIDS[1]=""
+			fi
+		else
+			SQUID_PIDS[1]=""
+		fi
+	fi
+
+	# Seek by port
+	SQUID_PIDS[2]=$(
+		netstat -apn |
+		awk '/tcp.*:'$SQUID_PORT' .*LISTEN/ && $7~/^[1-9]/ {
+			sub("\\/.*", "", $7); print $7; exit}')
+}
+
+are_all_pids_found()
+{
+	if 
+		[[ -n "${SQUID_PIDS[0]}" ]] &&
+		[[ -n "${SQUID_PIDS[1]}" ]] &&
+		[[ -n "${SQUID_PIDS[2]}" ]]
+	then
+		return 0
+	else
+		return 1
+	fi
+}
+
+are_pids_sane()
+{
+	if [[ "${SQUID_PIDS[1]}" = "${SQUID_PIDS[2]}" ]]; then
+		return $OCF_SUCCESS
+	else
+		ocf_log err "$SQUID_NAME:Pid unmatch"
+		return $OCF_ERR_GENERIC
+	fi
+}
+
+is_squid_dead()
+{
+	if 
+		[[ -z "${SQUID_PIDS[0]}" ]] &&
+		[[ -z "${SQUID_PIDS[2]}" ]]
+	then
+		return 0
+	else
+		return 1
+	fi
+}
+
+monitor_squid()
+{
+	typeset trialcount=0
+
+	while true; do
+		get_pids
+
+		if are_all_pids_found; then
+			are_pids_sane
+			return $OCF_SUCCESS
+		fi
+
+		if is_squid_dead; then
+			return $OCF_NOT_RUNNING
+		fi
+
+		ocf_log info "$SQUID_NAME:Inconsistent processes:" \
+			"${SQUID_PIDS[0]},${SQUID_PIDS[1]},${SQUID_PIDS[2]}"
+		(( trialcount = trialcount + 1 ))
+		if (( trialcount > SQUID_CONFIRM_TRIALCOUNT )); then
+			ocf_log err "$SQUID_NAME:Inconsistency of processes remains unsolved"
+			return $OCF_ERR_GENERIC
+		fi
+		sleep 1
+	done
+}
+
+start_squid()
+{
+	typeset status
+
+	monitor_squid
+	status=$?
+
+	if [[ $status != $OCF_NOT_RUNNING ]]; then
+		return $status
+	fi
+
+	set -- "$SQUID_OPTS"
+	ocf_run $SQUID_EXE -f "$SQUID_CONF" "$@"
+	status=$?
+	if [[ $status != $OCF_SUCCESS ]]; then
+		return $OCF_ERR_GENERIC
+	fi
+
+	while true; do
+		get_pids
+		if are_all_pids_found && are_pids_sane; then
+			return $OCF_SUCCESS
+		fi
+		ocf_log info "$SQUID_NAME:Waiting for squid to be invoked"
+		sleep 1
+	done
+
+	return $OCF_ERR_GENERIC
+}
+
+stop_squid()
+{
+	typeset lapse_sec
+
+	if ocf_run $SQUID_EXE -f $SQUID_CONF -k shutdown; then
+		lapse_sec=0
+		while true; do
+			get_pids
+			if is_squid_dead; then
+				rm -f $SQUID_PIDFILE
+				return $OCF_SUCCESS
+			fi
+			(( lapse_sec = lapse_sec + 1 ))
+			if (( lapse_sec > SQUID_STOP_TIMEOUT )); then
+				break
+			fi
+			sleep 1
+			ocf_log info "$SQUID_NAME:$FUNCNAME:$LINENO: " \
+				"stop NORM $lapse_sec/$SQUID_STOP_TIMEOUT"
+		done
+	fi
+
+	while true; do
+		get_pids
+		ocf_log info "$SQUID_NAME:$FUNCNAME:$LINENO: " \
+			"try to stop by SIGKILL:${SQUID_PIDS[0]} ${SQUID_PIDS[2]}"
+		kill -KILL ${SQUID_PIDS[0]} ${SQUID_PIDS[2]}
+		sleep 1
+		if is_squid_dead; then
+			rm -f $SQUID_PIDFILE
+			return $OCF_SUCCESS
+		fi
+	done
+
+	return $OCF_ERR_GENERIC
+}
+
+status_squid()
+{
+	return $OCF_SUCCESS
+}
+
+
+validate_all_squid()
+{
+	ocf_log info "validate_all_squid[$SQUID_NAME]"
+	return $OCF_SUCCESS
+}
+
+: === Debug ${0##*/} $1 ===
+
+if [[ "$1" = "meta-data" ]]; then
+	metadata_squid
+	exit $?
+fi
+
+SQUID_CONF="${OCF_RESKEY_squid_conf}"
+if [[ -z "$SQUID_CONF" ]]; then
+	ocf_log err "SQUID_CONF is not defined"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+SQUID_NAME="${SQUID_CONF##*/}"
+SQUID_NAME="${SQUID_NAME%.*}"
+
+DEBUG_LOG="${OCF_RESKEY_debug_log-/var/log/squid_${SQUID_NAME}_debug}.log"
+
+DEBUG_MODE=""
+case $OCF_RESKEY_debug_mode in
+	*x*) DEBUG_MODE="${DEBUG_MODE}x";;
+esac
+case $OCF_RESKEY_debug_mode in
+	*v*) DEBUG_MODE="${DEBUG_MODE}v";;
+esac
+
+if [ -n "$DEBUG_MODE" ]; then
+	PS4='\d \t \h '"${1-unknown} "
+	export PS4
+	exec 1>>$DEBUG_LOG 2>&1
+	set -$DEBUG_MODE
+fi
+
+SQUID_EXE="${OCF_RESKEY_squid_exe}"
+if [[ -z "$SQUID_EXE" ]]; then
+	ocf_log err "SQUID_EXE is not defined"
+	exit $OCF_ERR_CONFIGURED
+fi
+if [[ ! -x "$SQUID_EXE" ]]; then
+	ocf_log err "$SQUID_EXE is not found"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+SQUID_PIDFILE="${OCF_RESKEY_squid_pidfile}"
+if [[ -z "$SQUID_PIDFILE" ]]; then
+	ocf_log err "SQUID_PIDFILE is not defined"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+SQUID_PORT="${OCF_RESKEY_squid_port}"
+if [[ -z "$SQUID_PORT" ]]; then
+	ocf_log err "SQUID_PORT is not defined"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+SQUID_OPTS="${OCF_RESKEY_squid_opts}"
+
+SQUID_PIDS=( )
+
+SQUID_CONFIRM_TRIALCOUNT="${OCF_RESKEY_squid_confirm_trialcount-3}"
+
+SQUID_STOP_TIMEOUT="${OCF_RESKEY_squid_stop_timeout-10}"
+SQUID_SUSPEND_TRIALCOUNT="${OCF_RESKEY_squid_suspend_trialcount-10}"
+
+PROCESS_PATTERN="$SQUID_EXE -f $SQUID_CONF"
+
+COMMAND=$1
+
+case "$COMMAND" in
+	start)
+		ocf_log debug  "[$SQUID_NAME] Enter squid start"
+		start_squid
+		func_status=$?
+		ocf_log debug  "[$SQUID_NAME] Leave squid start $func_status"
+		exit $func_status
+		;;
+	stop)
+		ocf_log debug  "[$SQUID_NAME] Enter squid stop"
+		stop_squid
+		func_status=$?
+		ocf_log debug  "[$SQUID_NAME] Leave squid stop $func_status"
+		exit $func_status
+		;;
+	status)
+		status_squid
+		exit $?
+		;;
+	monitor)
+		#ocf_log debug  "[$SQUID_NAME] Enter squid monitor"
+		monitor_squid
+		func_status=$?
+		#ocf_log debug  "[$SQUID_NAME] Leave squid monitor $func_status"
+		exit $func_status
+		;;
+	validate-all)
+		validate_all_squid
+		exit $?
+		;;
+	*)
+		usage
+		;;
+esac
+
+# vim: set sw=4 ts=4 :
+
diff --git a/heartbeat/Stateful b/heartbeat/Stateful
new file mode 100755
index 0000000..8ee42a0
--- /dev/null
+++ b/heartbeat/Stateful
@@ -0,0 +1,188 @@
+#!/bin/sh
+#
+#
+#	Example of a stateful OCF Resource Agent. 
+#
+# Copyright (c) 2006 Andrew Beekhof
+#
+# 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.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+CRM_MASTER="${HA_SBIN_DIR}/crm_master -l reboot"
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Stateful" version="1.0">
+<version>1.0</version>
+
+<longdesc lang="en">
+This is an example resource agent that impliments two states
+</longdesc>
+<shortdesc lang="en">Example stateful resource agent</shortdesc>
+
+<parameters>
+
+<parameter name="state" unique="1">
+<longdesc lang="en">
+Location to store the resource state in
+</longdesc>
+<shortdesc lang="en">State file</shortdesc>
+<content type="string" default="${HA_RSCTMP}/Stateful-{OCF_RESOURCE_INSTANCE}.state" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" depth="0"  timeout="20" interval="10"/>
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="20s" />
+</actions>
+</resource-agent>
+END
+	exit $OCF_SUCCESS
+}
+
+#######################################################################
+
+stateful_usage() {
+	cat <<END
+usage: $0 {start|stop|promote|demote|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+	exit $1
+}
+
+stateful_update() {
+	echo $1 > ${OCF_RESKEY_state}
+}
+
+stateful_check_state() {
+    target=$1
+    if [ -f ${OCF_RESKEY_state} ]; then
+	state=`cat ${OCF_RESKEY_state}`
+	if [ "x$target" = "x$state" ]; then
+	    return 0
+	fi
+
+    else
+	if [ "x$target" = "x" ]; then
+	    return 0
+	fi
+    fi
+
+    return 1
+}
+
+stateful_start() {
+    stateful_check_state master
+    if [ $? = 0 ]; then
+       	# CRM Error - Should never happen
+	return $OCF_RUNNING_MASTER
+    fi
+    stateful_update slave
+    $CRM_MASTER -v 5
+    return 0
+}
+
+stateful_demote() {
+    stateful_check_state 
+    if [ $? = 0 ]; then
+       	# CRM Error - Should never happen
+	return $OCF_NOT_RUNNING
+    fi
+    stateful_update slave
+    $CRM_MASTER -v 5
+    return 0
+}
+
+stateful_promote() {
+    stateful_check_state 
+    if [ $? = 0 ]; then
+	return $OCF_NOT_RUNNING
+    fi
+    stateful_update master
+    $CRM_MASTER -v 10
+    return 0
+}
+
+stateful_stop() {
+    $CRM_MASTER -D
+    stateful_check_state master
+    if [ $? = 0 ]; then
+       	# CRM Error - Should never happen
+	return $OCF_RUNNING_MASTER
+    fi
+    if [ -f ${OCF_RESKEY_state} ]; then
+	rm ${OCF_RESKEY_state}
+    fi
+    return 0
+}
+
+stateful_monitor() {
+    stateful_check_state "master"
+    if [ $? = 0 ]; then
+	return $OCF_RUNNING_MASTER
+    fi
+
+    stateful_check_state "slave"
+    if [ $? = 0 ]; then
+	return $OCF_SUCCESS
+    fi
+
+    if [ -f ${OCF_RESKEY_state} ]; then
+	echo "File '${OCF_RESKEY_state}' exists but contains unexpected contents"
+	cat ${OCF_RESKEY_state}
+	return $OCF_ERR_GENERIC
+    fi
+    return 7
+}
+
+stateful_validate() {
+	exit $OCF_SUCCESS
+}
+
+: ${OCF_RESKEY_state=${HA_RSCTMP}/Stateful-${OCF_RESOURCE_INSTANCE}.state}
+
+case $__OCF_ACTION in
+meta-data)	meta_data;;
+start)		stateful_start;;
+promote)	stateful_promote;;
+demote)		stateful_demote;;
+stop)		stateful_stop;;
+monitor)	stateful_monitor;;
+validate-all)	stateful_validate;;
+usage|help)	stateful_usage $OCF_SUCCESS;;
+*)		stateful_usage $OCF_ERR_UNIMPLEMENTED;;
+esac
+
+exit $?
+
diff --git a/heartbeat/SysInfo b/heartbeat/SysInfo
new file mode 100755
index 0000000..11df0e1
--- /dev/null
+++ b/heartbeat/SysInfo
@@ -0,0 +1,365 @@
+#!/bin/bash
+#
+#
+#	SysInfo OCF Resource Agent
+#	It records (in the CIB) various attributes of a node
+#
+# Copyright (c) 2004 SUSE LINUX AG, Lars Marowsky-Br�e
+#                    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.
+#
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="SysInfo">
+<version>1.0</version>
+
+<longdesc lang="en">
+This is a SysInfo Resource Agent.
+It records (in the CIB) various attributes of a node
+Sample Linux output:
+   arch:   i686
+   os:     Linux-2.4.26-gentoo-r14
+   free_swap:      1999
+   cpu_info:       Intel(R) Celeron(R) CPU 2.40GHz
+   cpu_speed:      4771.02
+   cpu_cores:      1
+   cpu_load:       0.00
+   ram_total:      513
+   ram_free:       117
+   root_free:      2.4
+
+Sample Darwin output:
+   arch:   i386
+   os:     Darwin-8.6.2
+   cpu_info:       Intel Core Duo
+   cpu_speed:      2.16
+   cpu_cores:      2
+   cpu_load:       0.18
+   ram_total:      2016
+   ram_free:       787
+   root_free:      13
+
+Units:
+   free_swap: Mb
+   ram_*:     Mb
+   root_free: Gb
+   cpu_speed (Linux): bogomips
+   cpu_speed (Darwin): Ghz
+
+</longdesc>
+<shortdesc lang="en">Records various node attributes in the CIB</shortdesc>
+
+<parameters>
+
+<parameter name="pidfile" unique="0">
+<longdesc lang="en">PID file</longdesc>
+<shortdesc lang="en">PID file</shortdesc>
+<content type="string" default="$OCF_RESKEY_pidfile" />
+</parameter>
+
+<parameter name="delay" unique="0">
+<longdesc lang="en">Interval to allow values to stabilize</longdesc>
+<shortdesc lang="en">Dampening Delay</shortdesc>
+<content type="string" default="0s" />
+</parameter>
+
+</parameters>
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" timeout="20s" interval="60s"/>
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="20s" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+UpdateStat() {
+    name=$1; shift
+    value="$*"
+    echo -e "$name:\t$value"
+    ${HA_SBIN_DIR}/attrd_updater ${OCF_RESKEY_delay} -S status -n $name -v "$value"
+}
+
+SysInfoStats() {
+
+    UpdateStat arch "`uname -m`"
+    UpdateStat os "`uname -s`-`uname -r`"
+
+    case `uname -s` in
+	"Darwin")
+	    mem=`top -l 1 | grep Mem: | awk '{print $10}'`
+	    mem_used=`top -l 1 | grep Mem: | awk '{print $8}'`
+	    mem=`SysInfo_mem_units $mem`
+	    mem_used=`SysInfo_mem_units $mem_used`
+	    mem_total=`expr $mem_used + $mem`
+	    cpu_type=`system_profiler SPHardwareDataType | grep "CPU Type:"`
+	    cpu_type=${cpu_type/*: /}
+	    cpu_speed=`system_profiler SPHardwareDataType | grep "CPU Speed:" | awk '{print $3}'`
+	    cpu_cores=`system_profiler SPHardwareDataType | grep "Number Of"`
+	    cpu_cores=${cpu_cores/*: /}
+	;;
+	"Linux")
+	    if [ -f /proc/cpuinfo ]; then
+		cpu_type=`grep "model name" /proc/cpuinfo | head -n 1`
+		cpu_type=${cpu_type/*: /}
+		cpu_speed=`grep "bogomips" /proc/cpuinfo | head -n 1`
+		cpu_speed=${cpu_speed/*: /}
+		cpu_cores=`grep "^processor" /proc/cpuinfo | wc -l`
+	    fi
+
+	    if [ -f /proc/meminfo ]; then
+	        # meminfo results are in kB
+		mem=`grep "SwapFree" /proc/meminfo | awk '{print $2"k"}'`
+		if [ ! -z $mem ]; then
+		    UpdateStat free_swap `SysInfo_mem_units $mem`
+		fi
+		mem=`grep "Inactive" /proc/meminfo | awk '{print $2"k"}'`
+		mem_total=`grep "MemTotal" /proc/meminfo | awk '{print $2"k"}'`
+	    else
+		mem=`top -n 1 | grep Mem: | awk '{print $7}'`
+	    fi
+	    ;;
+	*)
+    esac
+
+    if [ x != x"$cpu_type" ]; then
+	UpdateStat cpu_info "$cpu_type"
+    fi
+
+    if [ x != x"$cpu_speed" ]; then
+	UpdateStat cpu_speed "$cpu_speed"
+    fi
+
+    if [ x != x"$cpu_cores" ]; then
+	UpdateStat cpu_cores "$cpu_cores"
+    fi
+
+    loads=`uptime`
+    load15=`echo ${loads} | awk '{print $10}'`
+    UpdateStat cpu_load $load15
+
+    if [ ! -z "$mem" ]; then
+        # Massage the memory values
+ 	UpdateStat ram_total `SysInfo_mem_units $mem_total`
+	UpdateStat ram_free `SysInfo_mem_units $mem`
+    fi
+
+    # Portability notes:
+    #   o df:   -h flag not available on Solaris 8.  (OK on 9, 10, ...) #FIXME#
+    #   o tail: explicit "-n" not available in Solaris; instead simplify
+    #	  'tail -n <c>' to the equivalent 'tail -<c>'.
+    disk=`df -h / | tail -1 | awk '{print $4}'`
+    if [ x != x"$disk" ]; then
+        UpdateStat root_free `SysInfo_hdd_units $disk`
+    fi
+}
+
+SysInfo_mem_units() {
+    mem=$1
+
+    if [ -z $1 ]; then 
+	return
+    fi
+
+    memlen=`expr ${#mem} - 1`
+    memlen_alt=`expr ${#mem} - 2`    
+    if [ ${mem:$memlen:1} = "G" ]; then
+	mem="${mem:0:$memlen}"
+	if [ $mem != ${mem/./} ]; then
+	    mem_before=${mem/.*/}
+	    mem_after=${mem/*./}
+	    mem=$[mem_before*1024]
+	    if [ ${#mem_after} = 0 ]; then
+		:
+	    elif [ ${#mem_after} = 1 ]; then
+		mem=$[mem+100*$mem_after]
+	    elif [ ${#mem_after} = 2 ]; then
+		mem=$[mem+10*$mem_after]
+	    elif [ ${#mem_after} = 3 ]; then
+		mem=$[mem+$mem_after]
+	    else 
+		mem_after=${mem_after:0:3}
+		mem=$[mem+$mem_after]
+	    fi
+	fi
+    elif [ ${mem:$memlen:1} = "M" ]; then
+	mem=${mem/.*/}
+	mem="${mem:0:$memlen}"
+    elif [ ${mem:$memlen:1} = "k" ]; then
+	mem="${mem:0:$memlen}"
+	mem=${mem/.*/}
+	mem=`expr $mem / 1024`
+    elif [ ${mem:$memlen_alt:2} = "kB" ]; then
+	mem="${mem:0:$memlen_alt}"
+	mem=${mem/.*/}
+	mem=`expr $mem / 1024`
+    elif [ ${mem:$memlen_alt:2} = "Mb" ]; then
+	mem="${mem:0:$memlen_alt}"
+	mem=${mem/.*/}
+    elif [ ${mem:$memlen_alt:2} = "MB" ]; then
+	mem="${mem:0:$memlen_alt}"
+	mem=${mem/.*/}
+    fi
+
+    # Round to the next multiple of 50
+    memlen=`expr ${#mem} - 2`
+    mem_round="${mem:$memlen:2}"
+    if [ x$mem_round = x ]; then 
+	:
+    elif [ $mem_round = "00" ]; then 
+	:
+    else
+	mem_round=`echo $mem_round | sed 's/^0//'`
+	if [ $mem_round -lt "50" ]; then 
+	    mem=$[mem+50]
+	    mem=$[mem-$mem_round]
+
+	else 
+	    mem=$[mem+100]
+	    mem=$[mem-$mem_round]
+	fi
+    fi
+    echo $mem    
+}
+
+SysInfo_hdd_units() {
+    disk=$1
+    disklen=`expr ${#disk} - 1`
+    disklen_alt=`expr ${#disk} - 2`
+    if [ ${disk:$disklen:1} = "G" ]; then
+	disk="${disk:0:$disklen}"
+    elif [ ${disk:$disklen:1} = "M" ]; then
+	disk="${disk:0:$disklen}"
+	disk=${disk/.*/}
+	disk=`expr $disk / 1024`
+    elif [ ${disk:$disklen:1} = "k" ]; then
+	disk="${disk:0:$disklen}"
+	disk=${disk/.*/}
+	disk=`expr $disk / 1048576`
+    elif [ ${disk:$disklen_alt:2} = "kB" ]; then
+	disk="${disk:0:$disklen_alt}"
+	disk=${disk/.*/}
+	disk=`expr $disk / 1048576`
+    elif [ ${disk:$disklen_alt:2} = "Mb" ]; then
+	disk="${disk:0:$disklen_alt}"
+	disk=${disk/.*/}
+	disk=`expr $disk / 1024`
+    elif [ ${disk:$disklen_alt:2} = "MB" ]; then
+	disk="${disk:0:$disklen_alt}"
+	disk=${disk/.*/}
+	disk=`expr $disk / 1024`
+    fi
+    echo $disk    
+}
+
+SysInfo_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+SysInfo_start() {
+    echo $OCF_RESKEY_clone > $OCF_RESKEY_pidfile
+    SysInfoStats
+    exit $OCF_SUCCESS
+}
+
+SysInfo_stop() {
+    rm $OCF_RESKEY_pidfile
+    exit $OCF_SUCCESS
+}
+
+SysInfo_monitor() {
+    if [ -f $OCF_RESKEY_pidfile ]; then
+	clone=`cat $OCF_RESKEY_pidfile`
+    fi
+
+    if [ x$clone = x ]; then
+	rm $OCF_RESKEY_pidfile
+	exit $OCF_NOT_RUNNING
+
+    elif [ $clone = $OCF_RESKEY_clone ]; then
+	SysInfoStats
+	exit $OCF_SUCCESS
+
+    elif [ x$OCF_RESKEY_CRM_meta_globally_unique = xtrue  
+	    -o x$OCF_RESKEY_CRM_meta_globally_unique = xTrue
+	    -o x$OCF_RESKEY_CRM_meta_globally_unique = xyes
+	    -o x$OCF_RESKEY_CRM_meta_globally_unique = xYes
+	]; then
+	SysInfoStats
+	exit $OCF_SUCCESS
+    fi
+    exit $OCF_NOT_RUNNING
+}
+
+SysInfo_validate() {
+    return $OCF_SUCCESS
+}
+
+if [ $# -ne 1 ]; then
+    SysInfo_usage
+    exit $OCF_ERR_ARGS
+fi
+
+: ${OCF_RESKEY_pidfile:="$HA_RSCTMP/SysInfo-${OCF_RESOURCE_INSTANCE}"}
+: ${OCF_RESKEY_clone:="0"}
+if [ x != x${OCF_RESKEY_delay} ]; then
+    OCF_RESKEY_delay="-d ${OCF_RESKEY_delay}"
+fi
+
+case $__OCF_ACTION in
+meta-data)	meta_data
+		exit $OCF_SUCCESS
+		;;
+start)		SysInfo_start
+		;;
+stop)		SysInfo_stop
+		;;
+monitor)	SysInfo_monitor
+		;;
+validate-all)	SysInfo_validate
+		;;
+usage|help)	SysInfo_usage
+		exit $OCF_SUCCESS
+		;;
+*)		SysInfo_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+
+exit $?
diff --git a/heartbeat/VIPArip b/heartbeat/VIPArip
new file mode 100755
index 0000000..01c6c99
--- /dev/null
+++ b/heartbeat/VIPArip
@@ -0,0 +1,302 @@
+#!/bin/sh
+#
+# 	License:	GNU General Public License (GPL) 
+# 	Support:	linux-ha at lists.linux-ha.org
+#	Author: 	Huang Zhen <zhenhltc at cn.ibm.com>
+# 	Copyright (c) 	2006 International Business Machines
+#
+#	Virtual IP Address by RIP2 protocol.
+#	This script manages IP alias in different subnet with quagga/ripd.
+#	It can add an IP alias, or remove one.
+#	
+#	The quagga package should be installed to run this RA
+#
+#	usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+#
+#	The "start" arg adds an IP alias.
+#	Surprisingly, the "stop" arg removes one. :-)
+#
+#       OCF parameters are as below
+#       OCF_RESKEY_ip	The IP address in different subnet
+#       OCF_RESKEY_nic	The nic for broadcast the route information
+#
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+RIPDCONF=$HA_RSCTMP/VIPArip-ripd.conf
+ZEBRA=/usr/sbin/zebra
+RIPD=/usr/sbin/ripd
+USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}";
+
+#######################################################################
+
+meta_data() {
+cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="VIPArip">
+<version>1.0</version>
+
+<longdesc lang="en">
+Virtual IP Address by RIP2 protocol.
+This script manages IP alias in different subnet with quagga/ripd.
+It can add an IP alias, or remove one.
+</longdesc>
+<shortdesc lang="en">Manages a virtual IP address through RIP2</shortdesc>
+
+<parameters>
+
+<parameter name="ip" unique="1" required="1">
+<longdesc lang="en">
+The IPv4 address in different subnet, for example "192.168.1.1".
+</longdesc>
+<shortdesc lang="en">The IP address in different subnet</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="nic" unique="0">
+<longdesc lang="en">
+The nic for broadcast the route information.
+The ripd uses this nic to broadcast the route informaton to others
+</longdesc>
+<shortdesc lang="en">The nic for broadcast the route information</shortdesc>
+<content type="string" default="eth0"/>
+</parameter>
+
+<parameter name="zebra_binary" unique="0">
+<longdesc lang="en">
+Absolute path to the zebra binary.
+</longdesc>
+<shortdesc lang="en">zebra binary</shortdesc>
+<content type="string" default="$ZEBRA"/>
+</parameter>
+
+<parameter name="ripd_binary" unique="0">
+<longdesc lang="en">
+Absolute path to the ripd binary.
+</longdesc>
+<shortdesc lang="en">ripd binary</shortdesc>
+<content type="string" default="$RIPD"/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" depth="0"  timeout="20s" interval="5s" />
+<action name="validate-all"  timeout="20s" />
+<action name="meta-data"  timeout="5s" />
+</actions>
+</resource-agent>
+END
+exit $OCF_SUCCESS
+}
+
+usage() {
+  echo $USAGE >&2
+}
+
+new_config_file() {
+	echo new_config_file $1 $2 $3
+	cat >$RIPDCONF <<END
+hostname ripd
+password zebra
+debug rip events
+debug rip packet
+debug rip zebra
+log file /var/log/quagga/quagga.log
+router rip
+!nic_tag
+ no passive-interface $2
+ network $2
+ distribute-list private out $2
+ distribute-list private in $2
+!metric_tag
+ redistribute connected metric $3
+!ip_tag
+access-list private permit $1/32
+access-list private deny any
+END
+}
+check_params() {
+	if [ x"$OCF_RESKEY_ip" = x ]
+	then
+		ocf_log err "ip is a required parameter"
+		exit $OCF_ERR_CONFIGURED
+	fi
+}
+set_metric() {
+	echo set_metric $1
+	sed "s/redistribute connected metric .*/redistribute connected metric $1/g" $RIPDCONF > $RIPDCONF.tmp
+	cp $RIPDCONF.tmp $RIPDCONF
+}
+
+add_ip() {
+	echo add_ip $1
+	sed "s/ip_tag/ip_tag\naccess-list private permit $1\/32/g" $RIPDCONF > $RIPDCONF.tmp
+	cp $RIPDCONF.tmp $RIPDCONF
+}
+
+del_ip() {
+	echo del_ip $1
+	sed "/$1/d" $RIPDCONF > $RIPDCONF.tmp
+	cp $RIPDCONF.tmp $RIPDCONF
+	if $GREP "access-list private permit" $RIPDCONF>/dev/null 
+	then
+		echo some other IP is running
+		reload_config
+	else
+		stop_quagga
+		echo remove $RIPDCONF
+		rm $RIPDCONF
+	fi
+	
+}
+
+add_nic() {
+	echo add_nic $1
+	if $GREP "network $1" $RIPDCONF >/dev/null 
+	then
+		echo the nic is already in the config file
+	else
+		sed "s/nic_tag/nic_tag\n no passive-interface $1\n network $1\n distribute-list private out $1\n distribute-list private in $1/g" $RIPDCONF > $RIPDCONF.tmp
+		cp $RIPDCONF.tmp $RIPDCONF
+	fi
+}
+
+reload_config() {
+	echo reload_config
+	echo $RIPDCONF:
+	cat $RIPDCONF
+	echo killall -SIGHUP ripd
+	killall -SIGHUP ripd
+}
+
+start_quagga() {
+	echo start_quagga
+	echo $RIPDCONF:
+	cat $RIPDCONF
+	echo $ZEBRA -d
+	$ZEBRA -d
+	echo $RIPD -d -f $RIPDCONF
+	$RIPD -d -f $RIPDCONF
+}
+
+stop_quagga() {
+	echo stop_quagga
+	echo $RIPDCONF:
+	cat $RIPDCONF
+	echo killall -SIGTERM ripd
+	killall -SIGTERM ripd
+	echo killall -SIGTERM zebra
+	killall -SIGTERM zebra
+}
+
+start_rip_ip() {
+	echo start_rip_ip
+	check_params	
+
+	if [ x"$OCF_RESKEY_nic" = x ]
+	then
+		echo OCF_RESKEY_nic is null, set to eth0
+		OCF_RESKEY_nic="eth0"
+	fi
+	
+	status_rip_ip
+	case $? in
+	$OCF_SUCCESS)
+		ocf_log info "already running"
+		exit $OCF_SUCCESS
+		;;
+	$OCF_NOT_RUNNING)
+		;;
+	*)
+		ocf_log info "state undefined, stopping first"
+		stop_rip_ip
+		;;
+	esac
+
+	$IP2UTIL addr add $OCF_RESKEY_ip/32 dev lo          
+	if [ -f "$RIPDCONF" ]
+	then
+		# there is a config file, add new data(IP,nic,metric) 
+		# to the existing config file.
+		add_ip $OCF_RESKEY_ip
+		add_nic $OCF_RESKEY_nic
+		set_metric 1
+		reload_config
+		echo sleep 3
+		sleep 3
+		set_metric 3
+		reload_config
+	else
+		new_config_file $OCF_RESKEY_ip $OCF_RESKEY_nic 1
+		start_quagga
+		echo sleep 3
+		sleep 3
+		set_metric 3
+		reload_config
+	fi
+	return $OCF_SUCCESS
+}
+
+stop_rip_ip() {
+	echo stop_rip_ip
+	check_params
+	status_rip_ip
+	if [ $? = $OCF_NOT_RUNNING ]
+	then
+		exit $OCF_SUCCESS
+	fi
+	$IP2UTIL addr del $OCF_RESKEY_ip dev lo
+	echo sleep 2
+	sleep 2
+	del_ip	$OCF_RESKEY_ip
+	return $OCF_SUCCESS
+}
+
+status_rip_ip() {
+	check_params
+	if $IP2UTIL addr | $GREP $OCF_RESKEY_ip >/dev/null 
+	then
+		if $GREP $OCF_RESKEY_ip $RIPDCONF >/dev/null 
+		then
+			if pidof ripd >/dev/null
+			then
+				return $OCF_SUCCESS
+			fi
+		fi
+		return $OCF_ERR_GENERIC
+	fi
+	return $OCF_NOT_RUNNING
+}
+
+if
+  [ $# -ne 1 ]
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+[ x != x"$OCF_RESKEY_zebra_binary" ] &&
+	ZEBRA=$OCF_RESKEY_zebra_binary
+[ x != x"$OCF_RESKEY_ripd_binary" ] &&
+	RIPD=$OCF_RESKEY_ripd_binary
+
+case $1 in
+  start)	start_rip_ip;;
+  stop)		stop_rip_ip;;
+  status)	status_rip_ip;;
+  monitor)	status_rip_ip;;
+  validate-all)	check_binary $IP2UTIL
+		exit $OCF_SUCCESS;;
+  meta-data)	meta_data;;
+  usage)	usage; exit $OCF_SUCCESS;;
+  *)		usage
+ 		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
new file mode 100755
index 0000000..b159c2c
--- /dev/null
+++ b/heartbeat/VirtualDomain
@@ -0,0 +1,638 @@
+#!/bin/sh
+#
+# Support:	  linux-ha at 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_autoset_utilization_cpu_default="true"
+OCF_RESKEY_autoset_utilization_hv_memory_default="true"
+OCF_RESKEY_migrateport_default=$(( 49152 + $(ocf_maybe_random) % 64 ))
+
+: ${OCF_RESKEY_force_stop=${OCF_RESKEY_force_stop_default}}
+: ${OCF_RESKEY_autoset_utilization_cpu=${OCF_RESKEY_autoset_utilization_cpu_default}}
+: ${OCF_RESKEY_autoset_utilization_hv_memory=${OCF_RESKEY_autoset_utilization_hv_memory_default}}
+: ${OCF_RESKEY_migrateport=${OCF_RESKEY_migrateport_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.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.
+Determine the system's default uri by running 'virsh --quiet uri'.
+</longdesc>
+<shortdesc lang="en">Hypervisor URI</shortdesc>
+<content type="string"/>
+</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>
+
+<parameter name="autoset_utilization_cpu" unique="0" required="0">
+<longdesc lang="en">
+If set true, the agent will detect the number of domainU's vCPUs from virsh, and put it 
+into the CPU utilization of the resource when the monitor is executed.
+</longdesc>
+<shortdesc lang="en">Enable auto-setting the CPU utilization of the resource</shortdesc>
+<content type="boolean" default="true" />
+</parameter>
+
+<parameter name="autoset_utilization_hv_memory" unique="0" required="0">
+<longdesc lang="en">
+If set true, the agent will detect the number of *Max memory* from virsh, and put it 
+into the hv_memory utilization of the resource when the monitor is executed.
+</longdesc>
+<shortdesc lang="en">Enable auto-setting the hv_memory utilization of the resource</shortdesc>
+<content type="boolean" default="true" />
+</parameter>
+
+<parameter name="migrateport" unique="0" required="0">
+<longdesc lang="en">
+This port will be used in the qemu migrateuri. If unset, the port will be a random highport.
+</longdesc>
+<shortdesc lang="en">Port for migrateuri</shortdesc>
+<content type="integer" />
+</parameter>
+
+<parameter name="snapshot">
+<longdesc lang="en">
+Path to the snapshot directory where the virtual machine image will be stored.  When this 
+parameter is set, the virtual machine's RAM state will be saved to a file in the snapshot
+directory when stopped.  If on start a state file is present for the domain, the domain
+will be restored to the same state it was in right before it stopped last.  This option
+is incompatible with the 'force_stop' option. 
+</longdesc>
+<shortdesc lang="en">
+Restore state on start/stop
+</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_util_attr() {
+	local attr=$1 val=$2
+	local cval outp
+
+	cval=$(crm_resource -Q -r $OCF_RESOURCE_INSTANCE -z -g $attr 2>/dev/null)
+	if [ "$cval" != "$val" ]; then
+	   outp=`crm_resource -r $OCF_RESOURCE_INSTANCE -z -p $attr -v $val 2>&1` ||
+	   ocf_log warn "crm_resource failed to set utilization attribute $attr: $outp"
+	fi
+}
+
+update_utilization() {
+	local dom_cpu dom_mem
+
+	if ocf_is_true "$OCF_RESKEY_autoset_utilization_cpu"; then
+	   dom_cpu=$(LANG=C virsh $VIRSH_OPTIONS dominfo ${DOMAIN_NAME} | awk '/CPU\(s\)/{print $2}')
+	   test -n "$dom_cpu" && set_util_attr cpu $dom_cpu
+	fi
+	if ocf_is_true "$OCF_RESKEY_autoset_utilization_hv_memory"; then
+	   dom_mem=$(LANG=C virsh $VIRSH_OPTIONS dominfo ${DOMAIN_NAME} | awk '/Max memory/{printf("%d", $3/1024)}')
+	   test -n "$dom_mem" && set_util_attr hv_memory "$dom_mem"
+	fi
+}
+
+# attempt to check domain status outside of libvirt using the emulator process
+pid_status()
+{
+	local rc=$OCF_ERR_GENERIC
+	local emulator
+
+	emulator=$(basename $(egrep '[[:space:]]*<emulator>.*</emulator>[[:space:]]*$' ${OCF_RESKEY_config} | sed -e 's/[[:space:]]*<emulator>\(.*\)<\/emulator>[[:space:]]*$/\1/'))
+
+	case "$emulator" in
+		qemu-kvm|qemu-system-*)
+			ps awx | grep -E "[q]emu-(kvm|system).*-name $DOMAIN_NAME " > /dev/null 2>&1
+			if [ $? -eq 0 ]; then
+				# domain exists and is running
+				ocf_log debug "Virtual domain $DOMAIN_NAME is currently running."
+				rc=$OCF_SUCCESS
+			else 
+				# domain pid does not exist on local machine
+				ocf_log debug "Virtual domain $DOMAIN_NAME is currently not running."
+				rc=$OCF_NOT_RUNNING
+			fi
+			;;
+		# This can be expanded to check for additional emulators
+		*)
+			;;
+	esac
+
+	return $rc
+}
+
+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 2>&1|tr 'A-Z' 'a-z')
+		case "$status" in
+			*"error:"*"domain not found"*|"shut off")
+				# shut off: domain is defined, but not started, will not happen if
+				#   domain is created but not defined
+				# Domain not found: domain is not defined and thus not started
+				ocf_log debug "Virtual domain $DOMAIN_NAME is currently $status."
+				rc=$OCF_NOT_RUNNING
+				;;
+			running|paused|idle|blocked|"in shutdown")
+				# 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
+				# in shutdown: the domain is in process of shutting down, but has not completely shutdown or crashed.
+				ocf_log debug "Virtual domain $DOMAIN_NAME is currently $status."
+				rc=$OCF_SUCCESS
+				;;
+			""|*"failed to "*"connect to the hypervisor"*|"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;
+				elif [ "$__OCF_ACTION" = "monitor" ]; then
+					pid_status
+					rc=$?
+					if [ $rc -ne $OCF_ERR_GENERIC ]; then
+						# we've successfully determined the domains status outside of libvirt
+						return $rc
+					fi
+
+				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
+}
+
+verify_undefined() {
+	for dom in `virsh --connect=${OCF_RESKEY_hypervisor} list --all --name`; do
+		if [ "$dom" = "$DOMAIN_NAME" ]; then
+			virsh $VIRSH_OPTIONS undefine $DOMAIN_NAME > /dev/null 2>&1
+			return
+		fi
+	done
+}
+
+VirtualDomain_Start() {
+	local snapshotimage
+
+	if VirtualDomain_Status; then
+		ocf_log info "Virtual domain $DOMAIN_NAME already running."
+		return $OCF_SUCCESS
+	fi
+
+	snapshotimage="$OCF_RESKEY_snapshot/${DOMAIN_NAME}.state"
+	if [ -n "$OCF_RESKEY_snapshot" -a -f "$snapshotimage" ]; then
+		virsh restore $snapshotimage
+		if [ $? -eq 0 ]; then
+			rm -f $snapshotimage
+			return $OCF_SUCCESS
+		fi
+		ocf_log error "Failed to restore ${DOMAIN_NAME} from state file in ${OCF_RESKEY_snapshot} directory."
+		return $OCF_ERR_GENERIC
+	fi
+
+	# Make sure domain is undefined before creating.
+	# The 'create' command guarantees that the domain will be
+	# undefined on shutdown, but requires the domain to be undefined.
+	# if a user defines the domain
+	# outside of this agent, we have to ensure that the domain
+	# is restored to an 'undefined' state before creating.
+	verify_undefined
+
+	virsh $VIRSH_OPTIONS create ${OCF_RESKEY_config}
+	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
+}
+
+force_stop()
+{
+	local out ex
+	local status=0
+
+	ocf_log info "Issuing forced shutdown (destroy) request for domain ${DOMAIN_NAME}."
+	out=$(virsh $VIRSH_OPTIONS destroy ${DOMAIN_NAME} 2>&1|tr 'A-Z' 'a-z')
+	ex=$?
+	echo >&2 "$out"
+	case $ex$out in
+		*"error:"*"domain is not running"*|*"error:"*"domain not found"*)
+			: ;; # 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_Stop() {
+	local i
+	local status
+	local shutdown_timeout
+	local needshutdown=1
+
+	VirtualDomain_Status
+	status=$?
+
+	case $status in
+		$OCF_SUCCESS)
+			if ocf_is_true $OCF_RESKEY_force_stop; then
+				# if force stop, don't bother attempting graceful shutdown.
+				force_stop
+				return $?
+			fi
+
+			ocf_log info "Issuing graceful shutdown request for domain ${DOMAIN_NAME}."
+
+			if [ -n "$OCF_RESKEY_snapshot" ]; then
+				virsh save $DOMAIN_NAME "$OCF_RESKEY_snapshot/${DOMAIN_NAME}.state"
+				if [ $? -eq 0 ]; then
+					needshutdown=0
+				else
+					ocf_log error "Failed to save snapshot state of ${DOMAIN_NAME} on stop"
+				fi
+			fi
+
+			# issue the shutdown if save state didn't shutdown for us
+			if [ $needshutdown -eq 1 ]; then
+				# Issue a graceful shutdown request
+				virsh $VIRSH_OPTIONS shutdown ${DOMAIN_NAME}
+			fi
+
+			# 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.
+						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
+			;;
+		$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.
+	force_stop
+}
+
+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.
+					migrateuri="tcp:${migrate_target}:${OCF_RESKEY_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} ${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} ${migrateuri} failed: $rc"
+			return $OCF_ERR_GENERIC
+		else
+			ocf_log info "$DOMAIN_NAME: live migration to ${target_node} succeeded."
+			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
+
+	update_utilization
+
+	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
+
+	if ocf_is_true $OCF_RESKEY_force_stop; then
+		if [ -n "$OCF_RESKEY_snapshot" ]; then
+			ocf_log error "The 'force_stop' and 'snapshot' options can not be used together."
+			return $OCF_ERR_CONFIGURED
+		fi
+	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."
+		elif [ "$__OCF_ACTION" = "stop" ]; then
+			ocf_log info "Configuration file $OCF_RESKEY_config not readable, resource considered stopped."
+		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
+
+# Grab the virsh uri default, but only if hypervisor isn't set
+: ${OCF_RESKEY_hypervisor=$(virsh --quiet uri)}
+
+# Set options to be passed to virsh:
+VIRSH_OPTIONS="--connect=${OCF_RESKEY_hypervisor} --quiet"
+
+# 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, 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 [ ! -r $OCF_RESKEY_config ]; then
+	ocf_is_probe && exit $OCF_NOT_RUNNING
+	[ "$__OCF_ACTION" = "stop" ] && exit $OCF_SUCCESS
+fi
+
+# Retrieve the domain name from the xml file.
+DOMAIN_NAME=`egrep '[[:space:]]*<name>.*</name>[[:space:]]*$' ${OCF_RESKEY_config} | sed -e 's/[[:space:]]*<name>\(.*\)<\/name>[[:space:]]*$/\1/' 2>/dev/null`
+if [ -z $DOMAIN_NAME ]; then
+	ocf_log err "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/heartbeat/WAS b/heartbeat/WAS
new file mode 100755
index 0000000..a46cdd9
--- /dev/null
+++ b/heartbeat/WAS
@@ -0,0 +1,572 @@
+#!/bin/sh
+#
+# 
+# WAS
+#
+# Description:	Manages a Websphere Application Server as an HA resource
+#
+#
+# Author:	Alan Robertson
+# Support:	linux-ha at lists.linux-ha.org
+# License:	GNU General Public License (GPL)
+# Copyright:	(C) 2002 - 2005 International Business Machines, Inc.
+#
+#
+# An example usage in /etc/ha.d/haresources: 
+#       node1  10.0.0.170 WAS::/opt/WebSphere/ApplicationServer/config/server-cfg.xml
+#
+# See usage() function below for more details...
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_config
+#		  (WAS-configuration file, used for the single server edition of WAS)
+#		OCF_RESKEY_port
+#		  (WAS-<snoop>-port-number, used for the advanced edition of WAS)
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+WASDIR=/opt/WebSphere/AppServer
+if
+  [ ! -d $WASDIR ]
+then
+  WASDIR=/usr/WebSphere/AppServer
+fi
+STARTTIME=300	#	5 minutes
+DEFAULT_WASPORTS="9080"
+#
+#
+WASBIN=$WASDIR/bin
+DEFAULT=$WASDIR/config/server-cfg.xml
+
+#
+#	Print usage message
+#
+usage() {
+  methods=`WAS_methods | grep -v methods`
+  methods=`echo $methods | tr ' ' '|'`
+  cat <<-END
+	usage: $0 ($methods)
+
+	For the single server edition of WAS, you have to set the following
+	enviroment virable:
+		OCF_RESKEY_config
+			(WAS-configuration file)
+
+	For the advanced edition of WAS, you have to set the following
+	enviroment virable:
+		OCF_RESKEY_port
+			(WAS-<snoop>-port-number)
+
+	$0 manages a Websphere Application Server (WAS) as an HA resource
+
+	The 'start' operation starts WAS.
+	The 'stop' operation stops WAS.
+	The 'status' operation reports whether WAS is running
+	The 'monitor' operation reports whether the WAS seems to be working
+		(httpd also needs to be working for this case)
+	The 'validate-all' operation reports whether the OCF instance parameter (OCF_RESKEY_config or OCF_RESKEY_port) is valid
+	The 'methods' operation reports on the methods $0 supports
+
+	This is known to work with the Single Server edition of Websphere,
+	and is believed to work with the Advanced edition too.
+	Since the Advanced Edition has no configuration file (it's in a the
+	database) you need to give a port number instead of a
+	configuration file for this config parameter.
+
+	The default configuration file for the single server edition is:
+	$DEFAULT
+
+	The default snoop-port for the advanced edition is: $DEFAULT_WASPORTS
+
+	The start and stop operations must be run as root.
+
+	The status operation will report a pid of "-" for the
+	WAS root process using unless it is run as root.
+
+	If you don't have xmllint on your system, parsing of WAS
+	configuration files is very primitive.
+	In this case, the port specification we need from the XML
+	config file has to be on the same line as the
+	first part of the <transports/> tag.
+
+	We run servlet/snoop on the first transport port listed in
+	the config file for the "monitor" operation.
+
+	END
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="WAS">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for WAS. It manages a Websphere Application Server (WAS) as 
+an HA resource.
+</longdesc>
+<shortdesc lang="en">Manages a WebSphere Application Server instance</shortdesc>
+
+<parameters>
+<parameter name="config" unique="0" required="0">
+<longdesc lang="en">
+The WAS-configuration file.
+</longdesc>
+<shortdesc lang="en">configration file</shortdesc>
+<content type="string" default="$DEFAULT" />
+</parameter>
+
+<parameter name="port" unique="0">
+<longdesc lang="en">
+The WAS-(snoop)-port-number.
+</longdesc>
+<shortdesc lang="en">port</shortdesc>
+<content type="integer" default="$DEFAULT_WASPORTS" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="300" />
+<action name="stop" timeout="300" />
+<action name="status" depth="0" timeout="30" interval="10" />
+<action name="monitor" depth="0" timeout="30" interval="10" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+<action name="methods" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+#
+#	Reformat the XML document in a sort of canonical form
+#	if we can.  If we don't have xmllint, we just cat it out
+#	and hope for the best ;-)
+#
+xmlcat() {
+  if
+    [ "X$XMLcat" = X ]
+  then
+    XMLcat=`which xmllint 2>/dev/null`
+    if
+      [ "X${XMLcat}" = X  -o ! -x "${XMLcat}" ]
+    then
+      XMLcat=cat
+    else
+      XMLcat="$XMLcat --recover --format"
+    fi
+  fi
+  for j in "$@"
+  do
+    ${XMLcat} "$j"
+  done
+}
+
+#
+#This is a bit skanky, but it works anyway...
+#
+#<transports xmi:type="applicationserver:HTTPTransport" xmi:id="HttpTransport_1" hostname="*" port="9080"/>
+#<transports xmi:type="applicationserver:HTTPTransport" xmi:id="HttpTransport_2" hostname="*" port="9443" sslEnabled="true"/>
+#<transports xmi:type="applicationserver:HTTPTransport" xmi:id="HttpTransport_3" hostname="*" port="9090" external="false"/>
+#
+# It's not really skanky if we can find xmllint on the system, because it
+# reformats tags so they are all on one line, which is all we we need...
+#
+
+#
+# Get the numbers of the ports WAS should be listening on...
+#
+# If we don't have xmllint around, then the applicationserver and the
+# port= specification have to be on the same line in the XML config file.
+#
+GetWASPorts() {
+  case $1 in
+    [0-9]*)	echo "$1" | tr ',' '\012';;
+    *)	
+	xmlcat $1 | grep -i 'transports.*applicationserver:HTTPTransport' |
+	grep port= 				|
+	sed -e 's%.*port= *"* *%%'		\
+		-e 's%[^0-9][^0-9]*.*$%%'
+	# Delete up to port=, throw away optional quote and optional
+	#	white space.
+	# Throw away everything after the first non-digit.
+	# This should leave us the port number all by itself...
+  esac
+}
+
+#
+#	We assume that the first port listed in the <transports/>
+#	is the one we should run servlet/snoop on.
+#
+GetWASSnoopPort() {
+	GetWASPorts "$@" | head -n1
+}
+
+#
+#	Return information on the processname/id for the WAS ports
+#
+#	pid/java	is the expected output.  Several lines, one per port...
+#
+#
+WASPortInfo() {
+  pat=""
+  once=yes
+  PortCount=0
+  for j in $*
+  do
+    case $pat in
+      "")	pat="$j";;
+      *)	pat="$pat|$j";;
+    esac
+    PortCount=`expr $PortCount + 1`
+  done
+  netstat -ltnp  2>/dev/null| egrep -i "($pat) .*LISTEN" | sed 's%.*LISTEN *%%'
+}
+
+#
+#	Return the number of WAS ports which are open
+#
+CheckWASPortsInUse() {
+  count=`WASPortInfo "$@" | wc -l`
+  echo $count
+}
+
+#
+#	Return the pid(s) of the processes that have WAS ports open
+#
+WASPIDs() {
+  WASPortInfo "$@" | sort -u | cut -f1 -d/
+}
+
+#
+#	The version of ps that returns all processes and their (long) args
+#	It's only used by WAS_procs, which isn't used for anything ;-)
+#
+ps_long() {
+  ps axww
+}
+
+
+#
+#	The total set of WAS processes (single server only)
+#
+WAS_procs() {
+  ps_long | grep -i "config=$1"  | grep -i java | cut -d' ' -f1
+}
+
+
+
+#
+# methods: What methods/operations do we support?
+#
+WAS_methods() {
+  cat <<-!
+	start
+	stop
+	status
+	methods
+	validate-all
+	meta-data
+	usage
+	!
+  if
+    have_binary $WGET
+  then
+    echo monitor
+  fi
+}
+
+#
+#	Return WAS status (silently)
+#
+WAS_status() {
+  WASPorts=`GetWASPorts $1`
+  PortsInUse=`CheckWASPortsInUse $WASPorts`
+  case $PortsInUse in
+    0)	false;;
+    *)	true;;
+  esac
+}
+
+#
+#	Report on WAS status to stdout...
+#
+WAS_report_status() {
+  WASPorts=`GetWASPorts $1`
+  PortCount=`echo $WASPorts | wc -w`
+  PortCount=`echo $PortCount`
+  PortsInUse=`CheckWASPortsInUse $WASPorts`
+  case $PortsInUse in
+    0)	ocf_log debug "WAS: server $1 is stopped."; return $OCF_NOT_RUNNING;;
+    *)
+	pids=`WASPIDs $WASPorts`
+	if
+	  [ $PortsInUse -ge $PortCount ]
+	then
+    	  ocf_log debug "WAS: server $1 is running (pid" $pids "et al)."
+	else
+    	  ocf_log debug "WAS: server $1 is running (pid $pids et al) but not listening on all ports."
+        fi
+	return $OCF_SUCCESS;;
+  esac
+}
+
+#
+#	Monitor WAS - does it really seem to be working?
+#
+#	For this we invoke the snoop applet via wget.
+#
+#	This is actually faster than WAS_status above...
+#
+WAS_monitor() {
+  trap '[ -z "$tmpfile" ] || rmtempfile "$tmpfile"' 0
+  tmpfile=`maketempfile` || return 1
+  SnoopPort=`GetWASSnoopPort $1`
+  output=`$WGET -nv -O$tmpfile  http://localhost:$SnoopPort/servlet/snoop 2>&1`
+  rc=$?
+  if
+    [ $rc -eq 0 ]
+  then
+    if
+      grep -i 'user-agent.*Wget' $tmpfile >/dev/null
+    then
+      : OK
+    else
+      ocf_log "err" "WAS: $1: no user-agent from snoop application"
+      rc=$OCF_ERR_GENERIC
+    fi
+  else
+    ocf_log "err" "WAS: $1: wget failure: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+  return $rc
+}
+
+#
+#	Start WAS instance
+#
+WAS_start() {
+# Launch Arguments:
+#
+#      -configFile      <configFile>
+#      -nodeName        <nodeName>
+#      -serverName      <serverName>
+#      -oltEnabled
+#      -oltHost         <hostname>
+#      -oltPort         <port>
+#      -debugEnabled
+#      -jdwpPort        <port>
+#      -debugSource     <sourcePath>
+#      -serverTrace     <traceString>
+#      -serverTraceFile <traceFile>
+#      -script          [<scriptFile>]
+#      -platform        <platformName>
+#      -noExecute
+#      -help
+  if
+    [ -x $WASBIN/startServer.sh ]
+  then
+    cmd="$WASBIN/startServer.sh -configFile $1"
+  else
+    cmd="$WASBIN/startupServer.sh"
+  fi
+    
+  if
+    ocf_run $cmd
+  then
+    if
+      WAS_wait_4_start $STARTTIME "$@"
+    then
+      #true
+      return $OCF_SUCCESS
+    else
+      ocf_log "err" "WAS server $1 did not start correctly"
+      return $OCF_ERR_GENERIC
+    fi
+  else
+    #false
+    return $OCF_ERR_GENERIC
+  fi
+}
+
+#
+#	Wait for WAS to actually start up.
+#
+#	It seems to take between 30 and 60 seconds for it to
+#	start up on a trivial WAS instance.
+#
+WAS_wait_4_start() {
+  max=$1
+  retries=0
+  shift
+  while
+    [ $retries -lt $max ]
+  do
+    if
+      WAS_status "$@"
+    then
+      return $OCF_SUCCESS
+    else
+      sleep 1
+    fi
+    retries=`expr $retries + 1`
+  done
+  WAS_status "$@"
+}
+  
+
+#
+#	Shut down WAS
+#
+WAS_stop() {
+  # They don't return good return codes...
+  # And, they seem to allow anyone to stop WAS (!)
+  if
+    [ -x $WASBIN/stopServer.sh ]
+  then
+    ocf_run $WASBIN/stopServer.sh -configFile $1
+  else
+    WASPorts=`GetWASPorts $1`
+    kill `WASPIDs $WASPorts`
+  fi
+  if
+    WAS_status $1
+  then
+    ocf_log "err" "WAS: $1 did not stop correctly"
+    #false
+    return $OCF_ERR_GENERIC
+  else
+    #true
+    return $OCF_SUCCESS
+  fi
+}
+
+#
+#	Check if the port is valid
+#
+CheckPort() {
+  ocf_is_decimal "$1" && [ $1 -gt 0 ]
+}
+
+WAS_validate_all() {
+  if [ -x $WASBIN/startServer.sh ]; then
+  # $arg should be config file
+	if [ ! -f "$arg" ]; then
+	    ocf_log err "Configuration file [$arg] does not exist"
+	    exit $OCF_ERR_ARGS
+	fi
+
+  # $arg should specify a valid port number at the very least
+	local WASPorts=`GetWASPorts $arg`
+	if [ -z "$WASPorts" ]; then
+	    ocf_log err "No port number specified in configuration file [$arg]"
+	    exit $OCF_ERR_CONFIGURED
+	fi
+
+	local port
+	local have_valid_port=false
+	for port in $WASPorts; do
+	    if CheckPort $port; then
+		have_valid_port=true
+		break
+	    fi
+	done
+	if [ "false" = "$have_valid_port" ]; then
+	    ocf_log err "No valid port number specified in configuration file [$arg]"
+	    exit $OCF_ERR_CONFIGURED
+	fi
+	   
+  elif [ -x $WASBIN/startupServer.sh ]; then
+  # $arg should be port number
+	if CheckPort "$arg"; then 
+	    ocf_log err "Port number is required but [$arg] is not valid port number"
+	    exit $OCF_ERR_ARGS
+	fi
+  else
+  # Do not know hot to validate_all
+	ocf_log warn "Do not know how to validate-all, assuming validation OK"
+	return $OCF_SUCCESS
+  fi
+}
+#
+#	'main' starts here...
+#
+
+if
+  ( [ $# -ne 1 ] )
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+#
+#	Supply default configuration parameter(s)
+#
+
+if
+  ( [ -z $OCF_RESKEY_config ] && [ -z $OCF_RESKEY_port ] )
+then
+  if
+    [ -f $DEFAULT ]
+  then
+    arg=$DEFAULT
+  else
+    arg=$DEFAULT_WASPORTS
+  fi
+elif
+  [ ! -z $OCF_RESKEY_config ]  
+then
+  arg=$OCF_RESKEY_config
+else
+  arg=$OCF_RESKEY_port
+fi
+
+if
+  [ ! -f $arg ]
+then
+  case $arg in
+    [0-9]*)	;;	# ignore port numbers...
+    *)		ocf_log "err" "WAS configuration file $arg does not exist!"
+  		usage
+  		exit $OCF_ERR_ARGS;;
+  esac
+fi
+  
+
+# What kind of method was invoked?
+case "$1" in
+
+  meta-data)	meta_data
+		exit $OCF_SUCCESS;;
+
+  start)	WAS_start $arg
+		exit $?;;
+
+  stop)		WAS_stop $arg
+		exit $?;;
+
+  status)	WAS_report_status $arg
+		exit $?;;
+
+  monitor)	WAS_monitor $arg
+		exit $?;;
+
+  validate-all)	WAS_validate_all $arg
+		exit $?;;
+
+  methods)	WAS_methods
+		exit $?;;
+
+  usage)	usage
+		exit $OCF_SUCCESS;;
+
+  *)		usage
+		exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/heartbeat/WAS6 b/heartbeat/WAS6
new file mode 100755
index 0000000..560ae60
--- /dev/null
+++ b/heartbeat/WAS6
@@ -0,0 +1,546 @@
+#!/bin/sh
+# WAS6 
+#
+# Description:  Manages a Websphere Application Server as an HA resource
+#
+#
+# Author:       Ru Xiang Min
+# Support:      linux-ha at lists.linux-ha.org
+# License:      GNU General Public License (GPL)
+# Copyright:    (C) 2006 International Business Machines China, Ltd., Inc.
+#
+#
+# An example usage in /etc/ha.d/haresources:
+#       node1  10.0.0.170 WAS::/opt/IBM/WebSphere/AppServer/profiles/default/config/cells/Node01Cell/nodes/Node01/serverindex.xml
+#
+# See usage() function below for more details...
+#
+#         OCF parameters are as below:
+#               OCF_RESKEY_profile
+#                 (WAS profile name, used for the single server edition of WAS6)
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+WAS_DIR=/opt/IBM/WebSphere/AppServer
+if
+  [ ! -d $WAS_DIR ]
+then
+  WAS_DIR=/usr/IBM/WebSphere/AppServer
+fi
+STARTTIME=300   #       5 minutes
+DEFAULT_WASPORTS="9080"
+#
+#
+WAS_BIN=$WAS_DIR/bin
+DEFAULT=default
+#
+#       Print usage message
+#
+usage() {
+  methods=`WAS_methods | grep -v methods`
+  methods=`echo $methods | tr ' ' '|'`
+  cat <<-END
+        usage: $0 ($methods)
+
+        For the single server edition of WAS6, you have to set the following
+        enviroment virable:
+                OCF_RESKEY_profile
+                        (WAS profile name)
+
+
+        $0 manages a Websphere Application Server 6(WAS6) as an HA resource
+
+        The 'start' operation starts WAS6.
+        The 'stop' operation stops WAS6.
+        The 'status' operation reports whether WAS6 is running
+        The 'monitor' operation reports whether the WAS6 seems to be working
+                (httpd also needs to be working for this case)
+        The 'validate-all' operation reports whether the OCF instance parameter (OCF_RESKEY_profileName ) is valid
+        The 'methods' operation reports on the methods $0 supports
+
+        This is known to work with the Single Server edition of Websphere.
+
+        The default profile name for the single server edition is:
+        $DEFAULT
+
+        The start and stop operations must be run as root.
+
+        The status operation will report a pid of "-" for the
+        WAS root process using unless it is run as root.
+
+        If you don't have xmllint on your system, parsing of WAS
+        configuration files is very primitive.
+
+        We run servlet/snoop on the seventh transport port listed in
+        the config file for the "monitor" operation.
+
+	END
+}
+
+meta_data() {
+        cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="WAS6">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for WAS6. It manages a Websphere Application Server (WAS6) as
+an HA resource.
+</longdesc>
+<shortdesc lang="en">Manages a WebSphere Application Server 6 instance</shortdesc>
+
+<parameters>
+<parameter name="profile" unique="0" required="0">
+<longdesc lang="en">
+The WAS profile name.
+</longdesc>
+<shortdesc lang="en">profile name</shortdesc>
+<content type="string" default="$DEFAULT" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="300" />
+<action name="stop" timeout="300" />
+<action name="status" depth="0" timeout="30" interval="10" />
+<action name="monitor" depth="0" timeout="30" interval="10" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+<action name="methods" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+#
+#       Reformat the XML document in a sort of canonical form
+#       if we can.  If we don't have xmllint, we just cat it out
+#       and hope for the best ;-)
+#
+xmlcat() {
+  if
+    [ "X$XMLcat" = X ]
+  then
+    XMLcat=`which xmllint 2>/dev/null`
+    if
+      [ "X${XMLcat}" = X  -o ! -x "${XMLcat}" ]
+    then
+      XMLcat=cat
+    else
+      XMLcat="$XMLcat --recover --format"
+    fi
+  fi
+  for j in "$@"
+  do
+    ${XMLcat} "$j"
+  done
+}
+
+#
+#This is a bit skanky, but it works anyway...
+#
+# It's not really skanky if we can find xmllint on the system, because it
+# reformats tags so they are all on one line, which is all we we need...
+#
+#
+# Get the numbers of the ports WAS should be listening on...
+#
+# If we don't have xmllint around, then the applicationserver and the
+# port= specification have to be on the same line in the XML config file.
+#
+GetWASPorts() {
+  case $1 in
+    [0-9]*)     echo "$1" | tr ',' '\012';;
+    *)
+        xmlcat ${WAS_DIR}/profiles/${WAS_PROFILE_NAME}/config/cells/${WAS_CELL}/nodes/${WAS_NODE}/serverindex.xml | 
+        grep port=                              |
+        sed -e 's%.*port= *"* *%%'              \
+                -e 's%[^0-9][^0-9]*.*$%%'
+        # Delete up to port=, throw away optional quote and optional
+        #       white space.
+        # Throw away everything after the first non-digit.
+        # This should leave us the port number all by itself...
+  esac
+}
+
+#
+#       We assume that the seventh port listed in the serverindex.xml
+#       is the one we should run servlet/snoop on.
+#
+GetWASSnoopPort() {
+        GetWASPorts "$@" | sed -n '7p' 
+}
+
+#
+#       Return information on the processname/id for the WAS ports
+#
+#       pid/java        is the expected output.  Several lines, one per port...
+#
+#
+WASPortInfo() {
+  pat=""
+  once=yes
+  PortCount=0
+  for j in $*
+  do
+    case $pat in
+      "")       pat="$j";;
+      *)        pat="$pat|$j";;
+    esac
+    PortCount=`expr $PortCount + 1`
+  done
+  netstat -ltnp  2>/dev/null| egrep -i "($pat) .*LISTEN" | sed 's%.*LISTEN *%%'
+}
+
+#
+#       Return the number of WAS ports which are open
+#
+CheckWASPortsInUse() {
+  count=`WASPortInfo "$@" | wc -l`
+  echo $count
+}
+
+#
+#       Return the pid(s) of the processes that have WAS ports open
+#
+WASPIDs() {
+  WASPortInfo "$@" | sort -u | cut -f1 -d/
+}
+
+#
+#       The version of ps that returns all processes and their (long) args
+#       It's only used by WAS_procs, which isn't used for anything ;-)
+#
+ps_long() {
+  ps axww
+}
+
+
+#
+#       The total set of WAS processes (single server only)
+#
+WAS_procs() {
+  ps_long | grep -i "config=$1"  | grep -i java | cut -d' ' -f1
+}
+
+
+
+#
+# methods: What methods/operations do we support?
+#
+WAS_methods() {
+  cat <<-!
+        start
+        stop
+        status
+        methods
+        validate-all
+        meta-data
+        usage
+	!
+  if
+    have_binary $WGET
+  then
+    echo "	monitor"
+  fi
+}
+
+#
+#       Return WAS status (silently)
+#
+WAS_status() {
+  WASPorts=`GetWASPorts $1`
+  PortsInUse=`CheckWASPortsInUse $WASPorts`
+  case $PortsInUse in
+    0)  false;;
+    *)  true;;
+  esac
+}
+
+#
+#       Report on WAS status to stdout...
+#
+WAS_report_status() {
+  WASPorts=`GetWASPorts $1`
+  PortCount=`echo $WASPorts | wc -w`
+  PortCount=`echo $PortCount`
+  PortsInUse=`CheckWASPortsInUse $WASPorts`
+  case $PortsInUse in
+    0)  ocf_log debug "WAS: server $1 is stopped."; return $OCF_NOT_RUNNING;;
+    *)
+        pids=`WASPIDs $WASPorts`
+        if
+          [ $PortsInUse -ge $PortCount ]
+        then
+          ocf_log debug "WAS: server $1 is running (pid" $pids "et al)."
+        else
+          ocf_log debug "WAS: server $1 is running (pid $pids et al) but not listening on all ports."
+        fi
+        return $OCF_SUCCESS;;
+  esac
+}
+
+#
+#       Monitor WAS - does it really seem to be working?
+#
+#       For this we invoke the snoop applet via wget.
+#
+#       This is actually faster than WAS_status above...
+#
+WAS_monitor() {
+  trap '[ -z "$tmpfile" || rmtempfile "$tmpfile"' 0
+  tmpfile=`maketempfile` || exit 1
+  SnoopPort=`GetWASSnoopPort $1`
+  output=`$WGET -nv -O$tmpfile  http://localhost:$SnoopPort/snoop 2>&1`
+  rc=$?
+  if
+    [ $rc -eq 0 ]
+  then
+    if
+      grep -i 'user-agent.*Wget' $tmpfile >/dev/null
+    then
+      : OK
+    else
+      ocf_log "err" "WAS: $1: no user-agent from snoop application"
+      rc=$OCF_ERR_GENERIC
+    fi
+  else
+    ocf_log "err" "WAS: $1: wget failure: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+  return $rc
+}
+
+#
+#       Start WAS instance
+#
+WAS_start() {
+# Launch Arguments:
+#     -nowait
+#     -quiet
+#     -logfile <filename>
+#     -replacelog
+#     -trace
+#     -script [<script filename >] [-background]
+#     -timeout <seconds>
+#     -statusport <portnumber>
+#     -profileName <profile>
+#     -help
+  if
+    [ -x $WAS_BIN/startServer.sh ]
+  then
+    cmd="$WAS_BIN/startServer.sh server1  -profileName $1"
+  fi
+
+  if
+    ocf_run $cmd
+  then
+    if
+      WAS_wait_4_start $STARTTIME "$@"
+    then
+      #true
+      return $OCF_SUCCESS
+    else
+      ocf_log "err" "WAS server $1 did not start correctly"
+      return $OCF_ERR_GENERIC
+    fi
+  else
+    #false
+    if 
+       WAS_wait_4_start $STARTTIME "$@"
+    then
+       #true
+       return $OCF_SUCCESS
+    else
+       ocf_log "err" "WAS server $1 did not start correctly"
+       return $OCF_ERR_GENERIC
+    fi
+  fi
+}
+
+#
+#       Wait for WAS to actually start up.
+#
+#       It seems to take between 30 and 60 seconds for it to
+#       start up on a trivial WAS instance.
+#
+WAS_wait_4_start() {
+  max=$1
+  retries=0
+  shift
+  while
+    [ $retries -lt $max ]
+  do
+    if
+      WAS_status "$@"
+    then
+      return $OCF_SUCCESS
+    else
+      sleep 1
+    fi
+    retries=`expr $retries + 1`
+  done
+  WAS_status "$@"
+}
+
+
+#
+#       Shut down WAS
+#
+WAS_stop() {
+  # They don't return good return codes...
+  # And, they seem to allow anyone to stop WAS (!)
+  if
+    [ -x $WAS_BIN/stopServer.sh ]
+  then
+    ocf_run $WAS_BIN/stopServer.sh server1 -profileName $1
+  else
+    WASPorts=`GetWASPorts $1`
+    kill `WASPIDs $WASPorts`
+  fi
+  if
+    WAS_status $1
+  then
+    ocf_log "err" "WAS: $1 did not stop correctly"
+    #false
+    return $OCF_ERR_GENERIC
+  else
+    #true
+    return $OCF_SUCCESS
+  fi
+}
+
+#
+#       Check if the port is valid
+#
+CheckPort() {
+  ocf_is_decimal "$1" && [ $1 -gt 0 ]
+}
+
+WAS_validate_all() {
+  if [ -x $WAS_BIN/startServer.sh ]; then
+  # $arg should be profile name 
+        if [ ! -f ${WAS_DIR}/profiles/${arg}/config/cells/${WAS_CELL}/nodes/${WAS_NODE}/serverindex.xml ]; then
+            ocf_log err "profile [$arg] does not exist"
+            exit $OCF_ERR_ARGS
+        fi
+
+  # $arg should specify a valid port number at the very least
+        local WASPorts=`GetWASPorts $arg`
+        if [ -z "$WASPorts" ]; then
+            ocf_log err "No port number specified in configuration file of profile [$arg]"
+            exit $OCF_ERR_CONFIGURED
+        fi
+
+        local port
+        local have_valid_port=false
+        for port in $WASPorts; do
+            if CheckPort $port; then
+                have_valid_port=true
+                break
+            fi
+        done
+        if [ "false" = "$have_valid_port" ]; then
+            ocf_log err "No valid port number specified in configuration file of profile [$arg]"
+            exit $OCF_ERR_CONFIGURED
+        fi
+
+  elif [ -x $WAS_BIN/startupServer.sh ]; then
+  # $arg should be port number
+        if CheckPort "$arg"; then
+            ocf_log err "Port number is required but [$arg] is not valid port number"
+            exit $OCF_ERR_ARGS
+        fi
+  else
+  # Do not know hot to validate_all
+        ocf_log warn "Do not know how to validate-all, assuming validation OK"
+        return $OCF_SUCCESS
+  fi
+}
+#
+#       'main' starts here...
+#
+
+if
+  ( [ $# -ne 1 ] )
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+# These operations don't require OCF instance parameters to be set
+case "$1" in
+
+  meta-data)    meta_data
+                exit $OCF_SUCCESS;;
+
+  usage)        usage
+                exit $OCF_SUCCESS;;
+
+  methods)      WAS_methods
+                exit $?;;
+  *);;
+esac
+
+
+#
+#       Supply default configuration parameter(s)
+#
+
+if
+   [ -z $OCF_RESKEY_profile ] 
+then
+    arg=$DEFAULT
+else
+    arg=$OCF_RESKEY_profile
+fi
+
+if
+   [ ! -d ${WAS_DIR}/profiles/$arg ]
+then
+    ocf_log "err" "WAS profile $arg does not exist!"
+    usage
+    exit $OCF_ERR_ARGS
+fi
+
+WAS_PROFILE_NAME=$arg
+if [ "${WAS_PROFILE_NAME:=}" != "" ]; then
+    WAS_PROFILE_FSDB_SCRIPT=${WAS_DIR}/properties/fsdb/${WAS_PROFILE_NAME}.sh
+fi
+
+if [ "${WAS_PROFILE_FSDB_SCRIPT:=}" != "" ] && [ -f ${WAS_PROFILE_FSDB_SCRIPT} ]; then
+    . ${WAS_PROFILE_FSDB_SCRIPT}
+fi
+
+if [ "${WAS_USER_SCRIPT:=}" != "" ]; then
+    . ${WAS_USER_SCRIPT}
+fi
+
+# What kind of method was invoked?
+case "$1" in
+
+  start)        WAS_start $arg
+                exit $?;;
+
+  stop)         WAS_stop $arg
+                exit $?;;
+
+  status)       WAS_report_status $arg
+                exit $?;;
+
+  monitor)      WAS_monitor $arg
+                exit $?;;
+
+  validate-all) WAS_validate_all $arg
+                exit $?;;
+
+  *)            usage
+                exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/heartbeat/WinPopup b/heartbeat/WinPopup
new file mode 100755
index 0000000..0d3f00e
--- /dev/null
+++ b/heartbeat/WinPopup
@@ -0,0 +1,231 @@
+#!/bin/sh
+#
+# Resource script for sending WinPopups using smbclient
+# derived from Alan Robertson's MailTo script
+#
+# Author: Sandro Poppi <spoppi at gmx.de>
+#
+# Description: sends WinPopups to a sysadmin's workstation
+#	       whenever a takeover occurs.
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_hostfile
+#		
+#	where "hostfile" is a file containing the IPs/Workstation names
+#	one by line to be sent WinPopups
+#
+# License:  GNU General Public License (GPL)
+
+WINPOPUPFILE=${HA_VARRUN}/WinPopup
+#######################################################################
+# Initialization:
+
+# Source function library.
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+us=`uname -n`
+
+usage() {
+  echo "Usage: $0 {start|stop|status|monitor|validate-all|meta-data}"
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="WinPopup">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for WinPopup. It sends WinPopups message to a 
+sysadmin's workstation whenever a takeover occurs.
+</longdesc>
+<shortdesc lang="en">Sends an SMB notification message to selected hosts</shortdesc>
+
+<parameters>
+<parameter name="hostfile" unique="0" required="1">
+<longdesc lang="en">
+The file containing the hosts to send WinPopup messages to.
+</longdesc>
+<shortdesc lang="en">Host file</shortdesc>
+<content type="string" default="" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="30" />
+<action name="stop" timeout="30" />
+<action name="status" depth="0" timeout="10" interval="10" />
+<action name="monitor" depth="0" timeout="10" interval="10" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+sendWinPopup() {
+  # if workstation file exists and is not zero
+  if [ -s "$hostfile" ] ; then
+    subject=$1
+    shift
+
+    for i in `cat $hostfile` ; do
+      echo "$subject $*" | smbclient -M $i >/dev/null 2>&1
+    done
+  else
+    ocf_log err "Workstation file $hostfile missing or corrupt!"
+    return $OCF_ERR_ARGS
+  fi
+
+  return $?
+}
+
+SubjectLine() {
+  case $1 in
+    ??*)	echo $1;;
+    *)		echo "Resource Group";;
+  esac
+}
+
+
+WinPopupStart() {
+
+	Subject="`SubjectLine $2` Takeover in progress on $us"
+ 
+	if sendWinPopup "$Subject" $1; then
+		touch $WINPOPUPFILE
+		return $?
+	else
+		return $?
+	fi
+
+}
+
+WinPopupStop () {
+	Subject="`SubjectLine $2` Reestablishing original master connection in progress on $us"
+
+	if sendWinPopup "$Subject" $1; then
+		rm -f $WINPOPUPFILE
+		return $?
+	else
+		return $?
+	fi
+
+}
+
+WinPopupStatus () {
+	ocf_log warn "Don't stat/monitor me! WinPopup is a pseudo resource agent, so the status reported may be incorrect"
+	if [ -f $WINPOPUPFILE ]; then
+		echo "running"
+		return $OCF_SUCCESS
+	else
+		echo "stopped"
+		return $OCF_NOT_RUNNING
+	fi
+}
+
+# A not reliable IP address checking function, which only picks up those _obvious_ violations...
+#
+# It accepts IPv4 address in dotted quad notation, for example "192.168.1.1"
+#
+# 100% confidence whenever it reports "negative", 
+# but may get false "positive" answer. 
+# 
+CheckIP() {
+  ip="$1"
+  case $ip in
+    *[!0-9.]*) #got invalid char
+	false;;
+    .*|*.) #begin or end by ".", which is invalid
+	false;;
+    *..*) #consecutive ".", which is invalid
+	false;;
+    *.*.*.*.*) #four decimal dots, which is too many
+	false;;
+    *.*.*.*) #exactly three decimal dots, candidate, evaluate each field
+	local IFS=.
+	set -- $ip
+	if
+	    ( [ $1 -le 254 ] && [ $2 -le 254 ] && [ $3 -le 254 ] && [ $4 -le 254 ] )
+	then
+	    true
+	fi	   
+	;;
+    *) #less than three decimal dots
+	false;;
+  esac
+  return $? # This return is unnecessary, this comment too :)
+}
+
+WinPopupValidateAll () {
+  if [ ! -s "$hostfile" ] ; then
+    ocf_log err "Workstation file $hostfile missing or corrupt!"
+    return $OCF_ERR_ARGS
+  fi
+
+  # What kind of hostfiles are valid? 
+  # We stick to the definition that, a hostfile is valid if and only if it 
+  # contains at least one valid host to send WinPopup message to.
+
+#  have_valid_host=no
+  for host in `cat $hostfile`; do
+	nmblookup $host 2>&1 | grep -q "failed to find name $host\>"
+	if [ $? -ne 0 ]; then
+#	  have_valid_host=yes
+	  return $OCF_SUCCESS
+	fi
+	# $host is not a netbios name, an IP address maybe?
+	if CheckIP "$host"; then
+#	  have_valid_host=yes
+	  return $OCF_SUCCESS
+	fi
+  done
+
+  ocf_log err "Workstation file $hostfile contains no valid host!"
+  return $OCF_ERR_CONFIGURED
+}
+
+if
+  ( [ $# -ne 1 ] )
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+# See how the environment virables were set.
+hostfile=${OCF_RESKEY_hostfile:-hosts}
+
+case "$1" in
+  meta-data)
+	meta_data
+	exit $OCF_SUCCESS
+	;;
+  start)
+	WinPopupStart
+	;;
+  stop)
+	WinPopupStop
+	;;
+
+	#	Not quite sure what to do with this one...
+  status|monitor)
+	WinPopupStatus
+	;;
+  validate-all)
+	WinPopupValidateAll
+	;;
+  usage)
+	usage
+	exit $OCF_SUCCESS
+	;;
+  *)
+        usage
+	exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+
+exit $?
diff --git a/heartbeat/Xen b/heartbeat/Xen
new file mode 100755
index 0000000..cbc7c37
--- /dev/null
+++ b/heartbeat/Xen
@@ -0,0 +1,535 @@
+#!/bin/sh
+#
+#
+# Support:      linux-ha at lists.linux-ha.org
+# License:      GNU General Public License (GPL)
+#
+#	Resource Agent for the Xen Hypervisor.
+#	Manages Xen virtual machine instances by
+#	mapping cluster resource start and stop,  
+#	to Xen create and shutdown, respectively.
+#
+#	usage: $0  {start|stop|status|monitor|meta-data}
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_xmfile
+#			Absolute path to the Xen control file,
+#			for this virtual machine.
+#		OCF_RESKEY_allow_mem_management
+#			Change memory usage on start/stop/migration
+#			of virtual machine
+#		OCF_RESKEY_reserved_Dom0_memory
+#			minimum memory reserved for domain 0
+#		OCF_RESKEY_monitor_scripts
+#			scripts to monitor services within the
+#			virtual domain
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+
+usage() {
+  cat <<-!
+	usage: $0 {start|stop|status|monitor|meta-data|validate-all}
+	!
+}
+
+
+: ${OCF_RESKEY_xmfile=/etc/xen/vm/MyDomU}
+: ${OCF_RESKEY_shutdown_acpi=0}
+: ${OCF_RESKEY_allow_mem_management=0}
+: ${OCF_RESKEY_reserved_Dom0_memory=512}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Xen">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource Agent for the Xen Hypervisor.
+Manages Xen virtual machine instances by mapping cluster resource
+start and stop,  to Xen create and shutdown, respectively.
+
+A note on names
+
+We will try to extract the name from the config file (the xmfile
+attribute). If you use a simple assignment statement, then you
+should be fine. Otherwise, if there's some python acrobacy
+involved such as dynamically assigning names depending on other
+variables, and we will try to detect this, then please set the
+name attribute. You should also do that if there is any chance of
+a pathological situation where a config file might be missing,
+for example if it resides on a shared storage. If all fails, we
+finally fall back to the instance id to preserve backward
+compatibility.
+
+Para-virtualized guests can also be migrated by enabling the
+meta_attribute allow-migrate.
+
+</longdesc>
+<shortdesc lang="en">Manages Xen unprivileged domains (DomUs)</shortdesc>
+
+<parameters>
+
+<parameter name="xmfile" unique="0" required="1">
+<longdesc lang="en">
+Absolute path to the Xen control file,
+for this virtual machine.
+</longdesc>
+<shortdesc lang="en">Xen control file</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="name" unique="0" required="0">
+<longdesc lang="en">
+Name of the virtual machine.
+</longdesc>
+<shortdesc lang="en">Xen DomU name</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="shutdown_timeout">
+<longdesc lang="en">
+The Xen agent will first try an orderly shutdown using xm shutdown.
+Should this not succeed within this timeout, the agent will escalate to
+xm destroy, forcibly killing the node.
+
+If this is not set, it will default to two-third of the stop action
+timeout.
+
+Setting this value to 0 forces an immediate destroy.
+
+</longdesc>
+<shortdesc lang="en">Shutdown escalation timeout</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="shutdown_acpi" unique="0" required="0">
+<longdesc lang="en">
+Handle shutdown by simulating an ACPI power button event.
+Enable this to allow graceful shutdown for HVM domains
+without installed PV drivers.
+</longdesc>
+<shortdesc lang="en">Simulate power button event on shutdown</shortdesc>
+<content type="boolean" default="0" />
+</parameter>
+<parameter name="allow_mem_management" unique="0" required="0">
+<longdesc lang="en">
+This parameter enables dynamic adjustment of memory for start 
+and stop actions used for Dom0 and the DomUs. The default is
+to not adjust memory dynamically.
+</longdesc>
+<shortdesc lang="en">Use dynamic memory management</shortdesc>
+<content type="boolean" default="0" />
+</parameter>
+
+<parameter name="node_ip_attribute">
+<longdesc lang="en">
+In case of a live migration, the system will default to using the IP
+address associated with the hostname via DNS or /etc/hosts.
+
+This parameter allows you to specify a node attribute that will be
+queried instead for the target node, overriding the IP address. This
+allows you to use a dedicated network for live migration traffic to a
+specific node.
+
+Warning: make very sure the IP address does point to the right node. Or
+else the live migration will end up somewhere else, greatly confusing
+the cluster and causing havoc.
+</longdesc>
+<shortdesc lang="en">Node attribute containing target IP address</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="reserved_Dom0_memory" unique="0" required="0">
+<longdesc lang="en">
+In case memory management is used, this parameter
+defines the minimum amount of memory to be reserved
+for the dom0. The default minimum memory is 512MB.
+</longdesc>
+<shortdesc lang="en">Minimum Dom0 memory</shortdesc>
+<content type="string" default="512" />
+</parameter>
+<parameter name="monitor_scripts" unique="0" required="0">
+<longdesc lang="en">
+To additionally monitor services within the unprivileged domain,
+add this parameter with a list of scripts to monitor.
+</longdesc>
+<shortdesc lang="en">list of space separated monitor scripts</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="60" />
+<action name="stop" timeout="40" />
+<action name="migrate_from" timeout="120" />
+<action name="migrate_to" timeout="120" />
+<action name="monitor" depth="0" timeout="30" interval="10" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+Xen_Status() {
+  if have_binary xen-list; then
+     xen-list $1 2>/dev/null | grep -qs "State.*[-r][-b][-p]--" 2>/dev/null
+     if [ $? -ne 0 ]; then
+     	return $OCF_NOT_RUNNING
+     else
+     	return $OCF_SUCCESS
+     fi
+  fi
+  STATUS=`xm list --long $1 2>/dev/null | grep status 2>/dev/null`
+  if [ "X${STATUS}" != "X" ]; then
+    # we have Xen 3.0.4 or higher
+    STATUS_NOSPACES=`echo "$STATUS" | awk '{ print $1,$2}'`
+    if [ "$STATUS_NOSPACES" = "(status 2)" -o "$STATUS_NOSPACES" = "(status 1)" ]; then
+      return $OCF_SUCCESS
+    else 
+      return $OCF_NOT_RUNNING
+    fi
+  else
+    # we have Xen 3.0.3 or lower
+    STATUS=`xm list --long $1 2>/dev/null | grep state 2>/dev/null`
+    echo "${STATUS}" | grep -qs "[-r][-b][-p]---"
+    if [ $? -ne 0 ]; then
+      return $OCF_NOT_RUNNING
+    else
+      return $OCF_SUCCESS
+    fi
+    
+  fi
+}
+
+# If the guest is rebooting, it may completely disappear from the
+# list of defined guests, thus xm/xen-list would return with not
+# running; apparently, this period lasts only for a second or
+# two
+# If a status returns not running, then test status
+# again for 5 times (perhaps it'll show up)
+Xen_Status_with_Retry() {
+  local rc cnt=5
+
+  Xen_Status $1
+  rc=$?
+  while [ $rc -eq $OCF_NOT_RUNNING -a $cnt -gt 0 ]; do
+	case "$__OCF_ACTION" in
+	stop)
+	  ocf_log debug "domain $1 reported as not running, waiting $cnt seconds ..."
+	  ;;
+	monitor)
+	  ocf_log warn "domain $1 reported as not running, but it is expected to be running! Retrying for $cnt seconds ..."
+	  ;;
+	*) : not reachable
+		;;
+	esac
+	sleep 1
+	Xen_Status $1
+	rc=$?
+	let cnt=$((cnt-1))
+  done
+  return $rc
+}
+
+Xen_Adjust_Memory() {
+    if ocf_is_true "${OCF_RESKEY_allow_mem_management}"; then
+      CNTNEW=$1
+      RUNNING=`Xen_List_running`
+      RUNCNT=`Xen_Count_running`
+      MAXMEM=`Xen_Total_Memory`
+      if [ ${RUNCNT} -eq 0 -a ${CNTNEW} -eq 0 ]; then
+	RUNCNT=1
+      fi
+      #NEWMEM=`echo "(${MAXMEM}-${OCF_RESKEY_reserved_Dom0_memory})/(${RUNCNT}+${CNTNEW})"|bc`
+      NEWMEM=$(( (${MAXMEM} - ${OCF_RESKEY_reserved_Dom0_memory}) / (${RUNCNT} + ${CNTNEW} ) ))
+      # do not rely on ballooning add dom0_mem=512 instead to force memory for dom0
+      #xm mem-set Domain-0 ${OCF_RESKEY_reserved_Dom0_memory}
+      for DOM in ${RUNNING}; do
+        xm mem-set ${DOM} ${NEWMEM} 
+      done
+      ocf_log info "Adjusted memory to: $NEWMEM, for the following $RUNCNT domains: $RUNNING"
+    fi
+}
+
+Xen_List_all() {
+	xm list | grep -v -e "Name" -e "Domain-0" | awk '{print $1}'
+}
+Xen_List_running() {
+	ALL_DOMS=`Xen_List_all`
+	for DOM in ${ALL_DOMS}; do
+		if Xen_Status $DOM; then
+			echo "${DOM} "
+		fi
+	done
+}
+Xen_Count_running() {
+	Xen_List_running | wc -w
+}
+
+Xen_Monitor() {
+  if ocf_is_probe; then
+	Xen_Status ${DOMAIN_NAME}
+  else
+	Xen_Status_with_Retry ${DOMAIN_NAME}
+  fi
+  if [ $? -eq ${OCF_NOT_RUNNING} ]; then
+	ocf_is_probe ||
+	  ocf_log err "Xen domain $DOMAIN_NAME stopped"
+	return ${OCF_NOT_RUNNING}
+  fi
+  if [ "X${OCF_RESKEY_monitor_scripts}" = "X" ]; then
+	return ${OCF_SUCCESS}
+  fi
+  for SCRIPT in ${OCF_RESKEY_monitor_scripts}; do
+	$SCRIPT
+	if [ $? -ne 0 ]; then
+		return ${OCF_ERR_GENERIC}
+	fi
+  done
+  return ${OCF_SUCCESS}
+}
+
+Xen_Total_Memory() {
+	xm info | grep "^total_memory" | awk '{print $3}'
+}
+
+Xen_Start() {
+  if Xen_Status ${DOMAIN_NAME}; then
+    ocf_log info "Xen domain $DOMAIN_NAME already running."
+    return $OCF_SUCCESS
+  fi
+
+  if [ ! -f "${OCF_RESKEY_xmfile}" ]; then
+    ocf_log err "Config file ${OCF_RESKEY_xmfile} for $DOMAIN_NAME does not exist."
+    return $OCF_ERR_INSTALLED
+  fi
+
+  if ocf_is_true "${OCF_RESKEY_allow_mem_management}"; then
+    Xen_Adjust_Memory 1
+    ocf_log info "New memory for virtual domains: ${NEWMEM}"
+    sed -i -e "/^memory=/ s/^memory=.*/memory=${NEWMEM}/" ${OCF_RESKEY_xmfile}
+    xm mem-set ${DOMAIN_NAME} ${NEWMEM} 
+  fi
+
+  xm create ${OCF_RESKEY_xmfile} name=$DOMAIN_NAME
+  rc=$?
+  if [ $rc -ne 0 ]; then
+    return $OCF_ERR_GENERIC
+  else 
+    if ocf_is_true "${OCF_RESKEY_allow_mem_management}"; then
+      xm mem-set ${DOMAIN_NAME} ${NEWMEM}
+    fi
+  fi
+  while sleep 1; do
+    Xen_Monitor && return $OCF_SUCCESS
+  done
+}
+
+xen_domain_stop() {
+    local dom=$1
+    local timeout
+
+    if [ -n "$OCF_RESKEY_shutdown_timeout" ]; then
+      timeout=$OCF_RESKEY_shutdown_timeout
+    elif [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
+      # Allow 2/3 of the action timeout for the orderly shutdown
+      # (The origin unit is ms, hence the conversion)
+      timeout=$((OCF_RESKEY_CRM_meta_timeout/1500))
+    else
+      timeout=60
+    fi
+
+    if [ "$timeout" -gt 0 ]; then
+      ocf_log info "Xen domain $dom will be stopped (timeout: ${timeout}s)"
+      if ocf_is_true "${OCF_RESKEY_shutdown_acpi}"; then
+        xm trigger $dom power
+      else
+        xm shutdown $dom
+      fi
+          
+      while Xen_Status $dom && [ "$timeout" -gt 0 ]; do
+        ocf_log debug "$dom still not stopped. Waiting..."
+        timeout=$((timeout-1))
+        sleep 1
+      done
+    fi
+    
+    if [ "$timeout" -eq 0 ]; then
+      while Xen_Status $dom; do
+        ocf_log warn "Xen domain $dom will be destroyed!"
+	$xenkill $dom
+        sleep 1
+      done
+      # Note: This does not give up. stop isn't allowed to to fail.
+      # If xm destroy fails, stop will eventually timeout.
+      # This is the correct behaviour.
+    fi
+
+    ocf_log info "Xen domain $dom stopped."
+}
+
+Xen_Stop() {
+  local vm
+  if Xen_Status_with_Retry ${DOMAIN_NAME}; then
+    vm=${DOMAIN_NAME}
+  elif Xen_Status migrating-${DOMAIN_NAME}; then
+    ocf_log info "Xen domain $DOMAIN_NAME is migrating" 
+    vm="migrating-${DOMAIN_NAME}"
+  else
+    ocf_log info "Xen domain $DOMAIN_NAME already stopped." 
+  fi
+
+  if [ "$vm" ]; then
+    xen_domain_stop $vm
+  else
+  # It is supposed to be gone, but there have been situations where xm
+  # list / xen-list showed it as stopped but it was still instantiated.
+  # Nuke it once more to make sure:
+    $xenkill ${DOMAIN_NAME}
+  fi
+
+  Xen_Adjust_Memory 0
+  return $OCF_SUCCESS
+}
+
+Xen_Migrate_To() {
+  target_node="$OCF_RESKEY_CRM_meta_migrate_target"
+  target_attr="$OCF_RESKEY_node_ip_attribute"
+  target_addr="$target_node"
+ 
+  if Xen_Status ${DOMAIN_NAME}; then
+    ocf_log info "$DOMAIN_NAME: Starting xm migrate to $target_node"
+    
+    if [ -n "$target_attr" ]; then
+	  nodevalue=`crm_attribute --type nodes --node-uname $target_node --attr-name $target_attr --get-value -q`
+	  if [ -n "${nodevalue}" -a "${nodevalue}" != "(null)" ]; then
+	  	target_addr="$nodevalue"
+		ocf_log info "$DOMAIN_NAME: $target_node is using address $target_addr"
+	  fi
+    fi
+
+    xm migrate --live $DOMAIN_NAME $target_addr
+
+    rc=$?
+    if [ $rc -ne 0 ]; then
+      ocf_log err "$DOMAIN_NAME: xm migrate to $target_node failed: $rc"
+      return $OCF_ERR_GENERIC
+    else 
+      Xen_Adjust_Memory 0
+      ocf_log info "$DOMAIN_NAME: xm migrate to $target_node succeeded."
+      return $OCF_SUCCESS
+    fi
+  else
+    ocf_log err "$DOMAIN_NAME: migrate_to: Not active locally!"
+    return $OCF_ERR_GENERIC
+  fi
+}
+
+Xen_Migrate_From() {
+  if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
+      # Allow 2/3 of the action timeout for status to stabilize
+      # (The origin unit is ms, hence the conversion)
+      timeout=$((OCF_RESKEY_CRM_meta_timeout/1500))
+  else
+      timeout=10		# should be plenty
+  fi
+
+  while ! Xen_Status ${DOMAIN_NAME} && [ $timeout -gt 0 ]; do
+    ocf_log debug "$DOMAIN_NAME: Not yet active locally, waiting (timeout: ${timeout}s)"
+    timeout=$((timeout-1))
+    sleep 1
+  done
+
+  if Xen_Status ${DOMAIN_NAME}; then
+    Xen_Adjust_Memory 0
+    ocf_log info "$DOMAIN_NAME: Active locally, migration successful"
+    return $OCF_SUCCESS
+  else
+    ocf_log err "$DOMAIN_NAME: Not active locally, migration failed!"
+    return $OCF_ERR_GENERIC
+  fi
+}
+
+Xen_Validate_All() {
+  return $OCF_SUCCESS
+}
+
+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
+
+# the name business:
+#
+# 1. use the name attribute, or
+# 2. find the name in the config file (if it exists) and use that
+# unless it contains funny characters such as '%' or space, or
+# 3. use the OCF_RESOURCE_INSTANCE
+
+if [ x"${OCF_RESKEY_name}" != x ]; then
+	DOMAIN_NAME="${OCF_RESKEY_name}"
+else
+	if [ -f "${OCF_RESKEY_xmfile}" ]; then
+		DOMAIN_NAME=`awk '$1~/^name(=|$)/{print}' ${OCF_RESKEY_xmfile} | sed 's/.*=[[:space:]]*//' | tr -d "[\"']"`
+		if echo "$DOMAIN_NAME" | grep -qs '[%[:space:]]'; then
+			DOMAIN_NAME=""
+		fi
+	fi
+	DOMAIN_NAME=${DOMAIN_NAME:-${OCF_RESOURCE_INSTANCE}}
+fi
+
+for binary in xm sed awk; do
+    check_binary $binary
+done
+
+if have_binary xen-destroy ; then
+  xenkill="xen-destroy"
+else
+  xenkill="xm destroy"
+fi
+
+if [ -n "$OCF_RESKEY_shutdown_timeout" ]; then
+	ocf_is_decimal "$OCF_RESKEY_shutdown_timeout" || {
+		ocf_log err "shutdown_timeout must be a number" 
+		exit $OCF_ERR_CONFIGURED
+	}
+fi
+
+case $1 in
+  start)		Xen_Start
+			;;
+  stop)			Xen_Stop
+			;;
+  migrate_to)		Xen_Migrate_To
+			;;
+  migrate_from)		Xen_Migrate_From
+			;;
+  monitor)		Xen_Monitor
+			;;
+  status)		Xen_Status ${DOMAIN_NAME}
+			;;
+  validate-all)		Xen_Validate_All
+			;;
+  *)			usage
+			exit $OCF_ERR_UNIMPLEMENTED
+			;;
+esac
+exit $?
+# vim:sw=2:ts=4:
diff --git a/heartbeat/Xinetd b/heartbeat/Xinetd
new file mode 100755
index 0000000..ee2c4fa
--- /dev/null
+++ b/heartbeat/Xinetd
@@ -0,0 +1,240 @@
+#!/bin/sh
+#
+# Startup/shutdown script for services managed by xinetd.
+#
+#	Copyright (C) 2003 Charlie Brooks
+#	Copyright (C) 2011 Ulrich Windl
+#
+# WARNING:	Tested ONLY on SLES11 SP1 at this time.
+#
+# Author:	Charlie Brooks <ha at HBCS.Org>
+# Description:	given parameters of a service name and start|stop|status,
+#		will enable, disable or report on a specified xinetd service
+# Config:	all services must have a descriptor file in /etc/xinetd.d
+# Support:	linux-ha at lists.linux-ha.org
+# License:	GNU General Public License (GPL)
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_service
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+service=$OCF_RESKEY_service
+SVCDEF=/etc/xinetd.d/$service
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="Xinetd">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for Xinetd. It starts/stops services managed
+by xinetd by enabling or disabling them in the configuration file.
+
+The xinetd daemon itself must be running: we are not going to start or
+stop it ourselves.
+
+All services should have a line saying either "disable=yes" or "disable=no".
+The script just changes those settings before reloading xinetd.
+
+Important: in case the services managed by the cluster are the
+only ones enabled, you should specify the -stayalive option for
+xinetd or it will exit on Heartbeat stop. Alternatively, you may
+enable some internal service such as echo.
+</longdesc>
+<shortdesc lang="en">Manages a service of Xinetd</shortdesc>
+
+<parameters>
+<parameter name="service" unique="0" required="1">
+<longdesc lang="en">
+The name of the service managed by xinetd. 
+</longdesc>
+<shortdesc lang="en">service name</shortdesc>
+<content type="string" default="" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="20s" />
+<action name="stop" timeout="20s" />
+<action name="restart" timeout="20s" />
+<action name="status" depth="0" timeout="10" interval="10" />
+<action name="monitor" depth="0" timeout="10" interval="10" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+get_xinetd_pid() {
+    ps -e -o pid,comm | $AWK '$2 == "xinetd" { print $1 }'
+}
+
+# force xinetd to reload the service descriptions
+hup_inetd () {
+    # don't rely on the pid file, but lookup xinetd in the list of
+    # processes
+    local pid
+    pid=`get_xinetd_pid`
+    if [ "$pid" ]; then
+	if kill -s HUP $pid; then
+            ocf_log info "asked xinetd to reload by sending SIGHUP to process $pid!"
+	else
+            ocf_log err "could not send SIGHUP to process $pid!"
+            exit $OCF_ERR_GENERIC
+	fi
+    else
+	ocf_log err "xinetd process not found!"
+	exit $OCF_ERR_GENERIC
+    fi
+}
+
+# check "disable = X", printing X
+check_service()
+{
+    ocf_log "info" "checking \"disable\" in $1"
+    local result=$(sed -nre 's/^[ 	]*disable[ 	]*=[ 	]*([^ 	]+)[# 	]*/\1/p' $1)
+    echo "$result"
+}
+
+# change "disable = X" to desired value
+change_service()
+{
+    ocf_log "info" "setting \"disable = $1\" in $2"
+    if ! sed -i -re 's/^([ 	]*disable[ 	]*=[ 	]*)([^ 	]+)([# 	]*)/\1'"$1"'\3/' $2
+    then
+	ocf_log "err" "could not edit $2"
+	return 1
+    fi
+    return 0
+}
+
+xup_status () {
+    local disabled="$(check_service $SVCDEF)"
+    if [ "${disabled:=no}" = no ]; then
+	echo running
+	return $OCF_SUCCESS
+    elif [ "$disabled" = yes ]; then
+	echo stopped
+	return $OCF_NOT_RUNNING
+    else
+	echo unknown
+	return $OCF_ERR_CONFIGURED
+    fi
+}
+
+xup_start () {
+    if [ "running" = "`xup_status`" ]; then
+	ocf_log info "service $service already started"
+	exit $OCF_SUCCESS
+    fi
+    ocf_log "info" "enabling in $SVCDEF"
+    if change_service "no" $SVCDEF; then
+        hup_inetd 
+    fi
+}
+
+xup_stop () {
+    if [ "stopped" = "`xup_status`" ]; then
+	ocf_log info "service $service already stopped"
+	exit $OCF_SUCCESS
+    fi
+    ocf_log "info" "disabling in $SVCDEF"
+    if change_service "yes" $SVCDEF; then
+        hup_inetd 
+    fi
+}
+
+xup_usage () {
+    echo "Usage: $0 {start|stop|restart|status|monitor|validate-all|meta-data}"
+    return 0
+}
+
+xup_validate_all () {
+    if [ ! -f "$SVCDEF" ]; then
+        ocf_log err "service $service missing $SVCDEF"
+	return $OCF_ERR_INSTALLED
+    fi
+    return $OCF_SUCCESS
+}
+
+if [ $# -ne 1 ]; then
+    xup_usage
+    exit $OCF_ERR_ARGS
+fi
+
+# These operations do not require OCF instance parameters to be set
+case "$1" in
+    meta-data)
+	meta_data
+	exit $OCF_SUCCESS
+	;;
+    usage)
+	xup_usage
+	exit $OCF_SUCCESS
+	;;
+esac
+
+if [ -z "$OCF_RESKEY_service" ]; then
+    ocf_log err "please define \"service\" parameter"
+    if [ "$1" = "start" ]; then 
+	exit $OCF_ERR_CONFIGURED
+    else
+	exit $OCF_NOT_RUNNING
+    fi
+fi
+
+# Is xinetd running at all
+if [ -z "`get_xinetd_pid`" ]; then
+    ocf_log err "xinetd not running, we manage just xinetd services, not the daemon itself"
+    case "$1" in
+    stop) exit $OCF_SUCCESS;;
+    start|monitor|status) exit $OCF_ERR_INSTALLED;;
+    esac
+fi
+
+# Make sure the OCF_RESKEY_service is a valid xinetd service name
+if [ ! -f $SVCDEF ]; then
+    ocf_log err "service definition $SVCDEF not found!"
+    if [ "$1" = "start" ]; then 
+	exit $OCF_ERR_INSTALLED
+    else
+	exit $OCF_NOT_RUNNING
+    fi
+fi
+
+# See how we were called.
+case "$1" in
+    start)
+	xup_start
+	;;
+    stop)
+	xup_stop
+	;;
+    restart)
+	$0 stop
+	$0 start
+	;;
+    status)
+	xup_status
+	;;
+    monitor)
+	xup_status > /dev/null
+	;;
+    validate-all)
+	xup_validate_all
+	;;
+    *)
+	xup_usage
+	exit $OCF_ERR_UNIMPLEMENTED
+esac
+exit $?
diff --git a/heartbeat/anything b/heartbeat/anything
new file mode 100755
index 0000000..f7debf9
--- /dev/null
+++ b/heartbeat/anything
@@ -0,0 +1,316 @@
+#!/bin/sh
+#
+#       OCF Resource Agent compliant resource script.
+#
+# Copyright (c) 2009 IN-telegence GmbH & Co. KG, Dominik Klein
+#                    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.
+
+# OCF instance parameters
+#       OCF_RESKEY_binfile
+#       OCF_RESKEY_cmdline_options
+#	OCF_RESKEY_workdir
+#	OCF_RESKEY_pidfile
+#       OCF_RESKEY_logfile
+#       OCF_RESKEY_errlogfile
+#       OCF_RESKEY_user
+#       OCF_RESKEY_monitor_hook
+#       OCF_RESKEY_stop_timeout
+#
+# This RA starts $binfile with $cmdline_options as $user in $workdir and writes a $pidfile from that. 
+# If you want it to, it logs:
+# - stdout to $logfile, stderr to $errlogfile or 
+# - stdout and stderr to $logfile
+# - or to will be captured by lrmd if these options are omitted.
+# Monitoring is done through $pidfile or your custom $monitor_hook script. 
+# The RA expects the program to keep running "daemon-like" and
+# not just quit and exit. So this is NOT (yet - feel free to
+# enhance) a way to just run a single one-shot command which just
+# does something and then exits.
+
+# Initialization:
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+getpid() {
+        grep -o '[0-9]*' $1
+}
+
+anything_status() {
+	if test -f "$pidfile"
+	then
+		if pid=`getpid $pidfile` && [ "$pid" ] && kill -s 0 $pid
+		then
+			return $OCF_SUCCESS
+		else
+			# pidfile w/o process means the process died
+			return $OCF_ERR_GENERIC
+		fi
+	else
+		return $OCF_NOT_RUNNING
+	fi
+}
+
+anything_start() {
+	if ! anything_status
+	then
+		if [ -n "$logfile" -a -n "$errlogfile" ]
+		then
+			# We have logfile and errlogfile, so redirect STDOUT und STDERR to different files
+			cmd="su - $user -c \"cd $workdir; nohup $binfile $cmdline_options >> $logfile 2>> $errlogfile & \"'echo \$!' "
+		else if [ -n "$logfile" ]
+			then
+				# We only have logfile so redirect STDOUT and STDERR to the same file
+				cmd="su - $user -c \"cd $workdir; nohup $binfile $cmdline_options >> $logfile 2>&1 & \"'echo \$!' "
+			else
+				# We have neither logfile nor errlogfile, so we're not going to redirect anything
+				cmd="su - $user -c \"cd $workdir; nohup $binfile $cmdline_options & \"'echo \$!'"
+			fi
+		fi
+		ocf_log debug "Starting $process: $cmd"
+		# Execute the command as created above
+		eval $cmd > $pidfile
+		if anything_status
+		then
+			ocf_log debug "$process: $cmd started successfully"
+			return $OCF_SUCCESS
+		else 
+			ocf_log err "$process: $cmd could not be started"
+			return $OCF_ERR_GENERIC
+		fi
+	else
+		# If already running, consider start successful
+		ocf_log debug "$process: $cmd is already running"
+		return $OCF_SUCCESS
+	fi
+}
+
+anything_stop() {
+	local rc=$OCF_SUCCESS
+
+        if [ -n "$OCF_RESKEY_stop_timeout" ]
+        then
+                stop_timeout=$OCF_RESKEY_stop_timeout
+        elif [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
+                # Allow 2/3 of the action timeout for the orderly shutdown
+                # (The origin unit is ms, hence the conversion)
+                stop_timeout=$((OCF_RESKEY_CRM_meta_timeout/1500))
+        else
+                stop_timeout=10
+        fi
+	if anything_status
+	then
+                pid=`getpid $pidfile`
+                kill $pid
+                i=0
+                while [ $i -lt $stop_timeout ]
+                do
+                        if ! anything_status
+                        then
+                        	rm -f $pidfile
+                                return $OCF_SUCCESS
+                        fi
+                        sleep 1 
+                        i=$((i+1))
+                done
+                ocf_log warn "Stop with SIGTERM failed/timed out, now sending SIGKILL."
+                kill -s 9 $pid
+                if ! anything_status
+                then
+                        ocf_log warn "SIGKILL did the job."
+                        rc=$OCF_SUCCESS
+                else
+                        ocf_log err "Failed to stop - even with SIGKILL."
+                        rc=$OCF_ERR_GENERIC
+                fi
+	fi
+	rm -f $pidfile 
+	return $rc
+}
+
+anything_monitor() {
+	anything_status
+	ret=$?
+	if [ $ret -eq $OCF_SUCCESS ]
+	then
+		if [ -n "$OCF_RESKEY_monitor_hook" ]; then
+			eval "$OCF_RESKEY_monitor_hook"
+                        if [ $? -ne $OCF_SUCCESS ]; then
+                                return ${OCF_ERR_GENERIC}
+                        fi
+			return $OCF_SUCCESS
+		else
+			true
+		fi
+	else
+		return $ret
+	fi
+}
+
+# FIXME: Attributes special meaning to the resource id
+process="$OCF_RESOURCE_INSTANCE"
+binfile="$OCF_RESKEY_binfile"
+cmdline_options="$OCF_RESKEY_cmdline_options"
+workdir="$OCF_RESKEY_workdir"
+pidfile="$OCF_RESKEY_pidfile"
+[ -z "$pidfile" ] && pidfile=${HA_VARRUN}/anything_${process}.pid
+logfile="$OCF_RESKEY_logfile"
+errlogfile="$OCF_RESKEY_errlogfile"
+user="$OCF_RESKEY_user"
+[ -z "$user" ] && user=root
+
+anything_validate() {
+	if ! su - $user -c "test -x $binfile"
+	then
+		ocf_log err "binfile $binfile does not exist or is not executable by $user."
+		exit $OCF_ERR_INSTALLED
+	fi
+	if ! getent passwd $user >/dev/null 2>&1
+	then
+		ocf_log err "user $user does not exist."
+		exit $OCF_ERR_INSTALLED
+	fi
+	for logfilename in "$logfile" "$errlogfile"
+	do
+		if [ -n "$logfilename" ]; then
+			mkdir -p `dirname $logfilename` || {
+				ocf_log err "cannot create $(dirname $logfilename)"
+				exit $OCF_ERR_INSTALLED
+			}
+		fi
+	done
+	[ "x$workdir" != x -a ! -d "$workdir" ] && {
+		ocf_log err "working directory $workdir doesn't exist"
+		exit $OCF_ERR_INSTALLED
+	}
+	return $OCF_SUCCESS
+}
+
+anything_meta() {
+cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="anything">
+<version>1.0</version>
+<longdesc lang="en">
+This is a generic OCF RA to manage almost anything.
+</longdesc>
+<shortdesc lang="en">Manages an arbitrary service</shortdesc>
+
+<parameters>
+<parameter name="binfile" required="1" unique="1">
+<longdesc lang="en">
+The full name of the binary to be executed. This is expected to keep running with the same pid and not just do something and exit.
+</longdesc>
+<shortdesc lang="en">Full path name of the binary to be executed</shortdesc>
+<content type="string" default=""/>
+</parameter>
+<parameter name="cmdline_options" required="0">
+<longdesc lang="en">
+Command line options to pass to the binary
+</longdesc>
+<shortdesc lang="en">Command line options</shortdesc>
+<content type="string" />
+</parameter>
+<parameter name="workdir" required="0" unique="0">
+<longdesc lang="en">
+The path from where the binfile will be executed.
+</longdesc>
+<shortdesc lang="en">Full path name of the work directory</shortdesc>
+<content type="string" default=""/>
+</parameter>
+<parameter name="pidfile">
+<longdesc lang="en">
+File to read/write the PID from/to.
+</longdesc>
+<shortdesc lang="en">File to write STDOUT to</shortdesc>
+<content type="string" default="${HA_VARRUN}/anything_${process}.pid"/>
+</parameter>
+<parameter name="logfile" required="0">
+<longdesc lang="en">
+File to write STDOUT to
+</longdesc>
+<shortdesc lang="en">File to write STDOUT to</shortdesc>
+<content type="string" />
+</parameter>
+<parameter name="errlogfile" required="0">
+<longdesc lang="en">
+File to write STDERR to
+</longdesc>
+<shortdesc lang="en">File to write STDERR to</shortdesc>
+<content type="string" />
+</parameter>
+<parameter name="user" required="0">
+<longdesc lang="en">
+User to run the command as
+</longdesc>
+<shortdesc lang="en">User to run the command as</shortdesc>
+<content type="string" default="root"/>
+</parameter>
+<parameter name="monitor_hook">
+<longdesc lang="en">
+Command to run in monitor operation
+</longdesc>
+<shortdesc lang="en">Command to run in monitor operation</shortdesc>
+<content type="string"/>
+</parameter>
+<parameter name="stop_timeout">
+<longdesc lang="en">
+In the stop operation: Seconds to wait for kill -TERM to succeed
+before sending kill -SIGKILL. Defaults to 2/3 of the stop operation timeout.
+</longdesc>
+<shortdesc lang="en">Seconds to wait after having sent SIGTERM before sending SIGKILL in stop operation</shortdesc>
+<content type="string" default=""/>
+</parameter>
+</parameters>
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" depth="0"  timeout="20s" interval="10" />
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="5" />
+</actions>
+</resource-agent>
+END
+exit 0
+}
+
+case "$1" in
+	meta-data|metadata|meta_data)
+		anything_meta
+	;;
+	start)
+		anything_start
+	;;
+	stop)
+		anything_stop
+	;;
+	monitor)
+		anything_monitor
+	;;
+	validate-all)
+		anything_validate
+	;;
+	*)
+		ocf_log err "$0 was called with unsupported arguments: $*"
+		exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
diff --git a/heartbeat/apache b/heartbeat/apache
new file mode 100755
index 0000000..d72c534
--- /dev/null
+++ b/heartbeat/apache
@@ -0,0 +1,651 @@
+#!/bin/sh
+#
+#	High-Availability Apache/IBMhttp control script
+# 
+# apache (aka IBMhttpd)
+#
+# Description:	starts/stops apache web servers.
+#
+# Author:	Alan Robertson
+#		Sun Jiang Dong
+#
+# Support:	linux-ha at lists.linux-ha.org
+#
+# License:	GNU General Public License (GPL)
+#
+# Copyright:	(C) 2002-2005 International Business Machines
+#
+#
+# An example usage in /etc/ha.d/haresources: 
+#	 node1 10.0.0.170 apache::/opt/IBMHTTPServer/conf/httpd.conf
+#	 node1 10.0.0.170 IBMhttpd
+#
+# Our parsing of the Apache config files is very rudimentary.
+# It'll work with lots of different configurations - but not every
+# possible configuration.
+#
+# Patches are being accepted ;-)
+#
+# OCF parameters:
+#  OCF_RESKEY_configfile
+#  OCF_RESKEY_httpd
+#  OCF_RESKEY_port
+#  OCF_RESKEY_statusurl
+#  OCF_RESKEY_options
+#  OCF_RESKEY_testregex
+#  OCF_RESKEY_client
+#  OCF_RESKEY_testurl
+#  OCF_RESKEY_testregex10
+#  OCF_RESKEY_testconffile
+#  OCF_RESKEY_testname
+#  OCF_RESKEY_envfiles
+
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+. ${OCF_FUNCTIONS_DIR}/apache-conf.sh
+. ${OCF_FUNCTIONS_DIR}/http-mon.sh
+HA_VARRUNDIR=${HA_VARRUN}
+
+#######################################################################
+#
+#	Configuration options - usually you don't need to change these
+#
+#######################################################################
+#
+IBMHTTPD=/opt/IBMHTTPServer/bin/httpd
+HTTPDLIST="/sbin/httpd2 /usr/sbin/httpd2 /usr/sbin/apache2 /sbin/httpd /usr/sbin/httpd /usr/sbin/apache $IBMHTTPD"
+MPM=/usr/share/apache2/find_mpm
+if [ -x $MPM ]; then
+	HTTPDLIST="$HTTPDLIST `$MPM 2>/dev/null`"
+fi
+
+LOCALHOST="http://localhost"
+HTTPDOPTS="-DSTATUS"
+DEFAULT_IBMCONFIG=/opt/IBMHTTPServer/conf/httpd.conf
+DEFAULT_SUSECONFIG="/etc/apache2/httpd.conf"
+DEFAULT_RHELCONFIG="/etc/httpd/conf/httpd.conf"
+#
+# You can also set
+#	HTTPD
+#	PORT
+#	STATUSURL
+#	CONFIGFILE
+# in this section if what we're doing doesn't work for you...
+#
+#	End of Configuration options
+#######################################################################
+
+CMD=`basename $0`
+
+#	The config-file-pathname is the pathname to the configuration
+#	file for this web server. Various appropriate defaults are
+#	assumed if no config file is specified. If this command is
+#	invoked as *IBM*, then the default config file name is
+#	$DEFAULT_IBMCONFIG, otherwise the default config file
+#	will be either $DEFAULT_RHELCONFIG or $DEFAULT_SUSECONFIG depending
+#	on which is detected.
+usage() {
+cat <<-!
+usage: $0 action
+
+action:
+	start	start the web server
+
+	stop	stop the web server
+
+	status	return the status of web server, run or down
+
+	monitor	return TRUE if the web server appears to be working.
+		For this to be supported you must configure mod_status
+		and give it a server-status URL. You have to have 
+		installed either curl or wget for this to work.
+
+	meta-data	show meta data message
+
+	validate-all	validate the instance parameters
+	!
+}
+
+get_pid() {
+	if [ -f $PidFile ]; then
+		cat $PidFile
+	else
+		false
+	fi
+}
+#
+# return TRUE if a process with given PID is running
+#
+ProcessRunning() {
+	local pid=$1
+
+	# Use /proc if it looks like it's here...
+	if [ -d /proc -a -d /proc/1 ]; then
+		[ -d /proc/$pid ]
+	else
+		# This assumes we're running as root...
+		kill -s 0 "$pid" >/dev/null 2>&1
+	fi
+}
+silent_status() {
+	local pid
+
+	pid=`get_pid`
+	if [ -n "$pid" ]; then
+		ProcessRunning $pid
+	else
+		: No pid file
+		false
+	fi
+}
+
+# May be useful to add other distros in future
+validate_default_config() {
+	if [ -e /etc/SuSE-release ]; then
+		validate_default_suse_config
+	else
+		return 0
+	fi
+}
+
+# When using the default /etc/apache2/httpd.conf on SUSE, the file
+# /etc/apache2/sysconfig.d/include.conf is required to be present,
+# but this is only generated if you run the apache init script
+# (with contents derived from /etc/sysconfig/apache2).  So, here,
+# if we're using the default system config file and it requires
+# that include, we run "/etc/init.d/apache2 configtest" to ensure
+# the relevant config is generated and valid.  We're also taking
+# this opportunity to enable mod_status if it's not present.
+validate_default_suse_config() {
+	if [ "$CONFIGFILE" = "$DEFAULT_SUSECONFIG" ] && \
+		grep -Eq '^Include[[:space:]]+/etc/apache2/sysconfig.d/include.conf' "$CONFIGFILE"
+	then
+		[ -x "/usr/sbin/a2enmod" ] && ocf_run -q /usr/sbin/a2enmod status
+		ocf_run -q /etc/init.d/apache2 configtest
+		return
+	else
+		return 0
+	fi
+}
+
+apache_start() {
+	if
+		silent_status
+	then
+		ocf_log info "$CMD already running (pid `get_pid`)"
+		return $OCF_SUCCESS
+	fi
+
+	validate_default_config || return $OCF_ERR_CONFIGURED
+	# https://bugs.launchpad.net/ubuntu/+source/apache2/+bug/603211
+	[ -d /var/run/apache2 ] || mkdir /var/run/apache2
+
+	if [ -z $PIDFILE_DIRECTIVE ]; then
+		ocf_run $HTTPD $HTTPDOPTS $OPTIONS -f $CONFIGFILE
+	else
+		ocf_run $HTTPD $HTTPDOPTS $OPTIONS -f $CONFIGFILE -c "PidFile $PidFile"
+	fi
+
+	tries=0
+	while : # wait until the user set timeout
+	do
+		apache_monitor
+		ec=$?
+		if [ $ec -eq $OCF_NOT_RUNNING ]
+		then
+			tries=`expr $tries + 1`
+			ocf_log info "waiting for apache $CONFIGFILE to come up"
+			sleep 1
+		else
+			break
+		fi
+	done
+
+	if [ $ec -ne 0 ] && silent_status; then
+		apache_stop
+	fi
+	return $ec
+}
+
+signal_children()
+{
+	for sig in SIGTERM SIGHUP SIGKILL ; do
+		if pgrep -f $HTTPD.*$CONFIGFILE >/dev/null ; then
+			pkill -$sig -f $HTTPD.*$CONFIGFILE >/dev/null
+			ocf_log info "signal $sig sent to apache children"
+			sleep 1
+		else
+			break
+		fi
+	done
+}
+
+graceful_stop()
+{
+	local tries=10
+	local pid=$1
+
+	# Try graceful stop for half timeout period if timeout period is present
+	if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
+		tries=$((($OCF_RESKEY_CRM_meta_timeout/1000) / 2))
+	fi
+
+	ocf_log info "Attempting graceful stop of apache PID $pid"
+	kill -WINCH $pid >/dev/null
+	while
+		ProcessRunning $pid &&
+		[ $tries -gt 0 ]
+	do
+		sleep 1
+		tries=`expr $tries - 1`
+	done
+
+	if [ $tries -eq 0 ]; then
+		# graceful stop didn't work, process still up.
+		return 1
+	fi
+
+	return 0
+}
+
+kill_stop()
+{
+	local tries=0
+	local pid=$1
+
+	ocf_log info "Killing apache PID $pid"
+	while
+		ProcessRunning $pid &&
+		[ $tries -lt 10 ]
+	do
+		if [ $tries -ne 0 ]; then
+			# don't sleep on the first try
+			sleep 1
+		fi
+		kill $pid >/dev/null 
+		tries=`expr $tries + 1`
+	done
+}
+
+apache_stop() {
+	local ret=$OCF_SUCCESS
+	local pid
+
+	if ! silent_status; then
+		ocf_log info "$CMD is not running."
+		signal_children
+		return $ret
+	fi
+
+	pid=`get_pid`
+	graceful_stop $pid
+	if [ $? -ne 0 ]; then
+		kill_stop $pid
+
+		if ProcessRunning $pid; then
+			ocf_log info "$CMD still running ($pid). Killing pid failed."
+			ret=$OCF_ERR_GENERIC
+		fi
+	fi
+
+	if [ $ret -eq 0 ]; then
+		ocf_log info "$CMD stopped."
+	fi
+
+	signal_children
+	return $ret
+}
+
+apache_monitor_10() {
+	if [ "$TESTCONFFILE" ]; then
+		readtestconf < $TESTCONFFILE
+	else
+		test_url="$TESTURL"
+		test_regex="$TESTREGEX10"
+	fi
+
+	whattorun=`gethttpclient`
+	fixtesturl
+	is_testconf_sane ||
+		return $OCF_ERR_CONFIGURED
+
+	if $whattorun "$test_url" | grep -Ei "$test_regex" > /dev/null
+	then
+		return $OCF_SUCCESS
+	else
+		if ! ocf_is_probe; then
+			ocf_log err "Failed to access httpd status page."
+		fi
+		return $OCF_ERR_GENERIC
+	fi
+}
+
+# If the user has not provided any basic monitoring 
+# information, allow the agent to verify the server is
+# healthy and capable of processing requests by requesting
+# the http header of website's index 
+attempt_index_monitor_request() {
+	local indexpage=""
+	
+	if [ -n "$OCF_RESKEY_testregex" ]; then
+		return 1;
+	fi
+	if [ -n "$OCF_RESKEY_testregex10" ]; then
+		return 1;
+	fi
+	if [ -n "$OCF_RESKEY_testurl" ]; then
+		return 1;
+	fi
+	if [ -n "$OCF_RESKEY_statusurl" ]; then
+		return 1;
+	fi
+	if [ -n "$OCF_RESKEY_testconffile" ]; then
+		return 1;
+	fi
+
+	indexpage=$(buildlocalurl)
+
+	request_url_header $indexpage
+	if [ $? -ne 0 ]; then
+		return $OCF_ERR_GENERIC
+	fi
+	ocf_log info "Successfully retrieved http header at $indexpage" 
+	return 0
+}
+
+apache_monitor_basic() {
+	if ${ourhttpclient}_func "$STATUSURL" | grep -Ei "$TESTREGEX" > /dev/null
+	then
+		return $OCF_SUCCESS
+	fi
+
+	attempt_index_monitor_request
+	if [ $? -eq 0 ]; then
+		return $OCF_SUCCESS
+	fi
+
+	if ! ocf_is_probe; then
+		ocf_log err "Failed to access httpd status page."
+	fi
+	return $OCF_ERR_GENERIC
+}
+apache_monitor() {
+	silent_status
+	if [ $? -ne 0 ]; then
+		ocf_log info "$CMD not running"
+		return $OCF_NOT_RUNNING
+	fi
+
+	ourhttpclient=`findhttpclient`  # we'll need one
+	if [ -z "$ourhttpclient" ]; then
+		ocf_log err "could not find a http client; make sure that either wget or curl is available"
+		return $OCF_ERR_INSTALLED
+	fi
+
+	case `ocf_check_level 10` in
+		0) apache_monitor_basic;;
+		10) apache_monitor_10;;
+	esac
+}
+
+detect_default_config()
+{
+	if [ -f $DEFAULT_SUSECONFIG ]; then
+		echo $DEFAULT_SUSECONFIG
+	else
+		echo $DEFAULT_RHELCONFIG
+	fi
+}
+
+
+apache_meta_data(){
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="apache">
+<version>1.0</version>
+
+<longdesc lang="en">
+This is the resource agent for the Apache Web server.
+This resource agent operates both version 1.x and version 2.x Apache
+servers.
+
+The start operation ends with a loop in which monitor is
+repeatedly called to make sure that the server started and that
+it is operational. Hence, if the monitor operation does not
+succeed within the start operation timeout, the apache resource
+will end with an error status.
+
+The monitor operation by default loads the server status page
+which depends on the mod_status module and the corresponding
+configuration file (usually /etc/apache2/mod_status.conf).
+Make sure that the server status page works and that the access
+is allowed *only* from localhost (address 127.0.0.1).
+See the statusurl and testregex attributes for more details.
+
+See also http://httpd.apache.org/
+</longdesc>
+<shortdesc lang="en">Manages an Apache Web server instance</shortdesc>
+
+<parameters>
+<parameter name="configfile" required="0" unique="1">
+<longdesc lang="en">
+The full pathname of the Apache configuration file.
+This file is parsed to provide defaults for various other
+resource agent parameters.
+</longdesc>
+<shortdesc lang="en">configuration file path</shortdesc>
+<content type="string" default="$(detect_default_config)" />
+</parameter>
+
+<parameter name="httpd">
+<longdesc lang="en">
+The full pathname of the httpd binary (optional).
+</longdesc>
+<shortdesc lang="en">httpd binary path</shortdesc>
+<content type="string" default="/usr/sbin/httpd" />
+</parameter>
+
+<parameter name="port" >
+<longdesc lang="en">
+A port number that we can probe for status information
+using the statusurl.
+This will default to the port number found in the
+configuration file, or 80, if none can be found
+in the configuration file.
+
+</longdesc>
+<shortdesc lang="en">httpd port</shortdesc>
+<content type="integer" />
+</parameter>
+
+<parameter name="statusurl">
+<longdesc lang="en">
+The URL to monitor (the apache server status page by default).
+If left unspecified, it will be inferred from
+the apache configuration file.
+
+If you set this, make sure that it succeeds *only* from the
+localhost (127.0.0.1). Otherwise, it may happen that the cluster
+complains about the resource being active on multiple nodes.
+</longdesc>
+<shortdesc lang="en">url name</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="testregex">
+<longdesc lang="en">
+Regular expression to match in the output of statusurl.
+Case insensitive.
+</longdesc>
+<shortdesc lang="en">monitor regular expression</shortdesc>
+<content type="string" default="exists, but impossible to show in a human readable format (try grep testregex)"/>
+</parameter>
+
+<parameter name="client">
+<longdesc lang="en">
+Client to use to query to Apache. If not specified, the RA will
+try to find one on the system. Currently, wget and curl are
+supported. For example, you can set this parameter to "curl" if
+you prefer that to wget.
+</longdesc>
+<shortdesc lang="en">http client</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="testurl">
+<longdesc lang="en">
+URL to test. If it does not start with "http", then it's
+considered to be relative to the Listen address.
+</longdesc>
+<shortdesc lang="en">test url</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="testregex10">
+<longdesc lang="en">
+Regular expression to match in the output of testurl.
+Case insensitive.
+</longdesc>
+<shortdesc lang="en">extended monitor regular expression</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="testconffile">
+<longdesc lang="en">
+A file which contains test configuration. Could be useful if
+you have to check more than one web application or in case sensitive
+info should be passed as arguments (passwords). Furthermore,
+using a config file is the only way to specify certain
+parameters.
+
+Please see README.webapps for examples and file description.
+</longdesc>
+<shortdesc lang="en">test configuration file</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="testname">
+<longdesc lang="en">
+Name of the test within the test configuration file.
+</longdesc>
+<shortdesc lang="en">test name</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="options">
+<longdesc lang="en">
+Extra options to apply when starting apache. See man httpd(8).
+</longdesc>
+<shortdesc lang="en">command line options</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="envfiles">
+<longdesc lang="en">
+Files (one or more) which contain extra environment variables.
+If you want to prevent script from reading the default file, set
+this parameter to empty string.
+</longdesc>
+<shortdesc lang="en">environment settings files</shortdesc>
+<content type="string" default="/etc/apache2/envvars"/>
+</parameter>
+
+<parameter name="use_ipv6">
+<longdesc lang="en">
+We will try to detect if the URL (for monitor) is IPv6, but if
+that doesn't work set this to true to enforce IPv6.
+</longdesc>
+<shortdesc lang="en">use ipv6 with http clients</shortdesc>
+<content type="boolean" default="false"/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="40s" />
+<action name="stop"    timeout="60s" />
+<action name="status"  timeout="30s" />
+<action name="monitor" depth="0"  timeout="20s" interval="10" />
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="5" />
+</actions>
+</resource-agent>
+END
+	return $OCF_SUCCESS
+}
+
+apache_validate_all() {
+	if [ -z "$HTTPD" ]; then
+		ocf_log err "apache httpd program not found"
+		return $OCF_ERR_INSTALLED
+	fi
+	if [ ! -x "$HTTPD" ]; then
+		ocf_log err "HTTPD $HTTPD not found or is not an executable!"
+		return $OCF_ERR_INSTALLED
+	fi
+	if [ ! -f $CONFIGFILE ]; then
+		ocf_log err "Configuration file $CONFIGFILE not found!"
+		return $OCF_ERR_INSTALLED
+	fi
+	return $OCF_SUCCESS
+}
+
+find_httpd_prog() {
+	case $0 in
+		*IBM*)
+			HTTPD=$IBMHTTPD
+			DefaultConfig=$DEFAULT_IBMCONFIG;;
+		*)	
+			HTTPD=
+			for h in $HTTPDLIST
+			do
+				if [ -f $h -a -x $h ]; then
+					HTTPD=$h
+					break
+				fi
+			done
+
+			# Let the user know that the $HTTPD used is not the one (s)he specified via $OCF_RESKEY_httpd
+			if [ "X$OCF_RESKEY_httpd" != X -a "X$HTTPD" != X ]; then
+				ocf_log info "Using $HTTPD as HTTPD"
+			fi
+			DefaultConfig=$(detect_default_config)
+			;;
+	esac
+}
+
+apache_getconfig() {
+	# these variables are global
+	HTTPD="$OCF_RESKEY_httpd"
+	PORT="$OCF_RESKEY_port"
+	STATUSURL="$OCF_RESKEY_statusurl"
+	CONFIGFILE="$OCF_RESKEY_configfile"
+	OPTIONS="$OCF_RESKEY_options"
+	CLIENT=${OCF_RESKEY_client}
+	TESTREGEX=${OCF_RESKEY_testregex:-'</ *html *>'}
+	TESTURL="$OCF_RESKEY_testurl"
+	TESTREGEX10=${OCF_RESKEY_testregex10}
+	TESTCONFFILE="$OCF_RESKEY_testconffile"
+	TESTNAME="$OCF_RESKEY_testname"
+	: ${OCF_RESKEY_envfiles="/etc/apache2/envvars"}
+	source_envfiles $OCF_RESKEY_envfiles
+
+	if [ "X$HTTPD" = X -o ! -f "$HTTPD" -o ! -x "$HTTPD" ]; then
+		find_httpd_prog
+	fi
+
+	CONFIGFILE=${CONFIGFILE:-$DefaultConfig}
+	if [ -n "$HTTPD" ]; then
+		httpd_basename=`basename $HTTPD`
+		case $httpd_basename in
+			*-*)	httpd_basename=`echo "$httpd_basename" | sed -e 's%\-.*%%'`;;
+		esac
+	fi
+	GetParams $CONFIGFILE
+}
+
+OCF_REQUIRED_PARAMS=""
+OCF_REQUIRED_BINARIES=""
+ocf_rarun $*
diff --git a/heartbeat/apache-conf.sh b/heartbeat/apache-conf.sh
new file mode 100644
index 0000000..dc3426f
--- /dev/null
+++ b/heartbeat/apache-conf.sh
@@ -0,0 +1,194 @@
+#
+# Common apache code
+# (sourced by apache)
+#
+# Author:	Alan Robertson
+#		Sun Jiang Dong
+#
+# Support:	linux-ha at lists.linux-ha.org
+#
+# License:	GNU General Public License (GPL)
+#
+# Copyright:	(C) 2002-2005 International Business Machines
+#
+
+source_envfiles() {
+	for f; do
+		[ -f "$f" -a -r "$f" ] &&
+			. "$f"
+	done
+}
+
+apachecat() {
+	awk '
+	function procline() {
+		split($0,a);
+		if( a[1]~/^[Ii]nclude$/ ) {
+			procinclude(a[2]);
+		} else {
+			if( a[1]=="ServerRoot" ) {
+				rootdir=a[2];
+				gsub("\"","",rootdir);
+			}
+			print;
+		}
+	}
+	function printfile(infile, a) {
+		while( (getline<infile) > 0 ) {
+			procline();
+		}
+		close(infile);
+	}
+	function allfiles(dir, cmd,f) {
+		cmd="find -L "dir" -type f";
+		while( ( cmd | getline f ) > 0 ) {
+			printfile(f);
+		}
+		close(cmd);
+	}
+	function listfiles(pattern, cmd,f) {
+		cmd="ls "pattern" 2>/dev/null";
+		while( ( cmd | getline f ) > 0 ) {
+			printfile(f);
+		}
+		close(cmd);
+	}
+	function procinclude(spec) {
+		if( rootdir!="" && spec!~/^\// ) {
+			spec=rootdir"/"spec;
+		}
+		if( isdir(spec) ) {
+			allfiles(spec); # read all files in a directory (and subdirs)
+		} else {
+			listfiles(spec); # there could be jokers
+		}
+	}
+	function isdir(s) {
+		return !system("test -d \""s"\"");
+	}
+	{ procline(); }
+	' $1 |
+	sed 's/#.*//;s/[[:blank:]]*$//;s/^[[:blank:]]*//' |
+	grep -v '^$'
+}
+
+#
+# set parameters (as shell vars) from our apache config file
+#
+get_apache_params() {
+	configfile=$1
+	shift 1
+	vars=`echo $@ | sed 's/ /,/g'`
+
+	eval `
+	apachecat $configfile | awk -v vars="$vars" '
+	BEGIN{
+		split(vars,v,",");
+		for( i in v )
+			vl[i]=tolower(v[i]);
+	}
+	{
+		for( i in v )
+			if( tolower($1)==vl[i] ) {
+			print v[i]"="$2
+			delete vl[i]
+			break
+		}
+	}
+	'`
+}
+
+#
+# Return the location(s) that are handled by the given handler
+#
+FindLocationForHandler() {
+	PerlScript='while (<>) {
+		/<Location "?([^ >"]+)/i && ($loc=$1);
+		'"/SetHandler +$2"'/i && print "$loc\n"; 
+	}'
+	apachecat $1 | perl -e "$PerlScript"
+}
+
+#
+# Check if the port is valid
+#
+CheckPort() {
+	ocf_is_decimal "$1" && [ $1 -gt 0 ]
+}
+
+buildlocalurl() {
+	[ "x$Listen" != "x" ] &&
+	echo "http://${Listen}" ||
+	echo "${LOCALHOST}:${PORT}"
+}
+# the test url may need a local prefix (as specified in the
+# apache Listen directive)
+fixtesturl() {
+	echo $test_url | grep -qs "^http" && return
+	test_url="`buildlocalurl`$test_url"
+}
+#
+# Get all the parameters we need from the Apache config file
+#
+GetParams() {
+	ConfigFile=$1
+	if [ ! -f $ConfigFile ]; then
+		return $OCF_ERR_INSTALLED
+	fi
+	get_apache_params $ConfigFile ServerRoot PidFile Port Listen
+	case $PidFile in
+		/*) ;;
+		[[:alnum:]]*) PidFile=$ServerRoot/$PidFile;;
+		*)
+			# If the PidFile is not set in the config, set
+			# a default location.
+			PidFile=$HA_VARRUNDIR/${httpd_basename}.pid
+			# Force the daemon to use this location by using
+			# the -c option, which adds the PidFile directive
+			# as if it was in the configuration file to begin with.
+			PIDFILE_DIRECTIVE="true"
+			;;
+	esac
+
+	for p in "$PORT" "$Port" 80; do
+		if CheckPort "$p"; then
+			PORT="$p"
+			break
+		fi
+	done
+ 
+	echo $Listen | grep ':' >/dev/null || # Listen could be just port spec
+		Listen="localhost:$Listen"
+
+	#
+	# It's difficult to figure out whether the server supports
+	# the status operation.
+	# (we start our server with -DSTATUS - just in case :-))
+	#
+	# Typically (but not necessarily) the status URL is /server-status
+	#
+	# For us to think status will work, we have to have the following things:
+	#
+	# - The server-status handler has to be mapped to some URL somewhere
+	#
+	# We assume that:
+	#
+	# - the "main" web server at $PORT will also support it if we can find it
+	#   somewhere in the file
+	# - it will be supported at the same URL as the one we find in the file
+	#
+	# If this doesn't work for you, then set the statusurl attribute.
+	#
+	if
+		 [ "X$STATUSURL" = "X" ]
+	then
+		StatusURL=`FindLocationForHandler $1 server-status | tail -1`
+		STATUSURL="`buildlocalurl`$StatusURL"
+	fi
+
+	if ! test "$PidFile"; then
+		return $OCF_ERR_INSTALLED
+	else
+		return $OCF_SUCCESS
+	fi
+}
diff --git a/heartbeat/asterisk b/heartbeat/asterisk
new file mode 100755
index 0000000..cc78ba1
--- /dev/null
+++ b/heartbeat/asterisk
@@ -0,0 +1,479 @@
+#!/bin/sh
+#
+#
+# Asterisk
+#
+# Description:  Manages an Asterisk PBX as an HA resource
+#
+# Authors:      Martin Gerhard Loschwitz
+#               Florian Haas
+#
+# Support:      linux-ha at lists.linux-ha.org
+# License:      GNU General Public License (GPL)
+#
+# (c) 2011      hastexo Professional Services GmbH
+#
+# This resource agent is losely derived from the MySQL resource
+# agent, which itself is made available to the public under the
+# following copyright:
+# 
+# (c) 2002-2005 International Business Machines, Inc.
+#     2005-2010 Linux-HA contributors
+#
+# See usage() function below for more details ...
+#
+# OCF instance parameters:
+#   OCF_RESKEY_binary
+#   OCF_RESKEY_canary_binary
+#   OCF_RESKEY_config
+#   OCF_RESKEY_user
+#   OCF_RESKEY_group
+#   OCF_RESKEY_additional_parameters
+#   OCF_RESKEY_realtime
+#   OCF_RESKEY_maxfiles
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+# Fill in some defaults if no values are specified
+HOSTOS=`uname`
+if [ "X${HOSTOS}" = "XOpenBSD" ]; then
+    OCF_RESKEY_user_default="_asterisk"
+    OCF_RESKEY_group_default="_asterisk"
+else
+    OCF_RESKEY_user_default="asterisk"
+    OCF_RESKEY_group_default="asterisk"
+fi
+OCF_RESKEY_binary_default="asterisk"
+OCF_RESKEY_canary_binary_default="astcanary"
+OCF_RESKEY_config_default="/etc/asterisk/asterisk.conf"
+OCF_RESKEY_additional_parameters_default="-g -vvv"
+OCF_RESKEY_realtime_default="false"
+OCF_RESKEY_maxfiles_default="8192"
+
+: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
+: ${OCF_RESKEY_canary_binary=${OCF_RESKEY_canary_binary_default}}
+: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
+: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}}
+: ${OCF_RESKEY_group=${OCF_RESKEY_group_default}}
+: ${OCF_RESKEY_additional_parameters=${OCF_RESKEY_additional_parameters_default}}
+: ${OCF_RESKEY_realtime=${OCF_RESKEY_realtime_default}}
+: ${OCF_RESKEY_maxfiles=${OCF_RESKEY_maxfiles_default}}
+
+#######################################################################
+
+usage() {
+    cat <<UEND
+        usage: $0 (start|stop|validate-all|meta-data|status|monitor)
+
+        $0 manages an Asterisk PBX as an HA resource.
+
+        The 'start' operation starts the database.
+        The 'stop' operation stops the database.
+        The 'validate-all' operation reports whether the parameters are valid
+        The 'meta-data' operation reports this RA's meta-data information
+        The 'status' operation reports whether the database is running
+        The 'monitor' operation reports whether the database seems to be working
+
+UEND
+}
+
+meta_data() {
+    cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="asterisk">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource agent for the Asterisk PBX. 
+May manage an Asterisk PBX telephony system or a clone set that 
+forms an Asterisk distributed device setup.
+</longdesc>
+<shortdesc lang="en">Manages an Asterisk PBX</shortdesc>
+<parameters>
+
+<parameter name="binary" unique="0" required="0">
+<longdesc lang="en">
+Location of the Asterisk PBX server binary
+</longdesc>
+<shortdesc lang="en">Asterisk PBX server binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_binary_default}" />
+</parameter>
+
+<parameter name="canary_binary" unique="0" required="0">
+<longdesc lang="en">
+Location of the Asterisk PBX Canary server binary
+</longdesc>
+<shortdesc lang="en">Asterisk PBX Canary server binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_canary_binary_default}" />
+</parameter>
+
+<parameter name="config" unique="0" required="0">
+<longdesc lang="en">
+The Asterisk PBX configuration file
+</longdesc>
+<shortdesc lang="en">Asterisk PBX config</shortdesc>
+<content type="string" default="${OCF_RESKEY_config_default}" />
+</parameter>
+
+<parameter name="user" unique="0" required="0">
+<longdesc lang="en">
+User running Asterisk PBX daemon
+</longdesc>
+<shortdesc lang="en">Asterisk PBX user</shortdesc>
+<content type="string" default="${OCF_RESKEY_user_default}" />
+</parameter>
+
+<parameter name="group" unique="0" required="0">
+<longdesc lang="en">
+Group running Asterisk PBX daemon (for logfile and directory permissions)
+</longdesc>
+<shortdesc lang="en">Asterisk PBX group</shortdesc>
+<content type="string" default="${OCF_RESKEY_group_default}" />
+</parameter>
+
+<parameter name="additional_parameters" unique="0" required="0">
+<longdesc lang="en">
+Additional parameters which are passed to the Asterisk PBX on 
+startup (e.g. -L <load> or -M <value>). 
+</longdesc>
+<shortdesc lang="en">Additional parameters to pass to the Asterisk PBX</shortdesc>
+<content type="string" default="${OCF_RESKEY_additional_parameters_default}" />
+</parameter>
+
+<parameter name="realtime" unique="0" required="0">
+<longdesc lang="en">
+Determines whether the Asterisk PBX daemon will be run with
+realtime priority or not.
+</longdesc>
+<shortdesc lang="en">Asterisk PBX realtime priority</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_realtime_default}" />
+</parameter>
+
+<parameter name="maxfiles" unique="0" required="0">
+<longdesc lang="en">
+Determines how many files the Asterisk PBX is allowed to open at
+a time. Helps to fix the 'Too many open files' error message.
+</longdesc>
+<shortdesc lang="en">Asterisk PBX allowed MAXFILES</shortdesc>
+<content type="integer" default="${OCF_RESKEY_maxfiles_default}" />
+</parameter>
+
+<parameter name="monitor_sipuri" unique="0" required="0">
+<longdesc lang="en">
+A SIP URI to check when monitoring. During monitor, the agent will
+attempt to do a SIP OPTIONS request against this URI.
+Requires the sipsak utility to be present and executable.
+If unset, the agent does no SIP URI monitoring.
+</longdesc>
+<shortdesc lang="en">SIP URI to check when monitoring</shortdesc>
+<content type="string" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="20" />
+<action name="stop" timeout="20" />
+<action name="status" timeout="20" />
+<action name="monitor" timeout="30" interval="20" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+# Convenience functions
+
+asterisk_rx() {
+    # if $HOME is set, asterisk -rx writes a .asterisk_history there
+    (
+        unset HOME
+        ocf_run $OCF_RESKEY_binary -r -s $ASTRUNDIR/asterisk.ctl -x "$1"
+    )
+}
+
+#######################################################################
+# Functions invoked by resource manager actions
+
+asterisk_validate() {
+    local rc
+
+    check_binary $OCF_RESKEY_binary
+    check_binary pgrep
+
+    if [ -n "$OCF_RESKEY_monitor_sipuri" ]; then
+        check_binary sipsak
+    fi
+
+    # A config file on shared storage that is not available
+    # during probes is OK.
+    if [ ! -f $OCF_RESKEY_config ]; then
+        if ! ocf_is_probe; then
+            ocf_log err "Config $OCF_RESKEY_config doesn't exist"
+            return $OCF_ERR_INSTALLED
+        fi
+        ocf_log_warn "Config $OCF_RESKEY_config not available during a probe"
+    fi
+
+    getent passwd $OCF_RESKEY_user >/dev/null 2>&1
+    rc=$?
+    if [ $rc -ne 0 ]; then
+        ocf_log err "User $OCF_RESKEY_user doesn't exist"
+        return $OCF_ERR_INSTALLED
+    fi
+
+    getent group $OCF_RESKEY_group >/dev/null 2>&1
+    rc=$?
+    if [ $rc -ne 0 ]; then
+        ocf_log err "Group $OCF_RESKEY_group doesn't exist"
+        return $OCF_ERR_INSTALLED
+    fi
+
+    true
+}
+
+asterisk_status() {
+    local pid
+    local rc
+
+    if [ ! -f $ASTRUNDIR/asterisk.pid ]; then
+        ocf_log info "Asterisk PBX is not running"
+        return $OCF_NOT_RUNNING
+    fi
+
+    pid=`cat $ASTRUNDIR/asterisk.pid`
+    ocf_run kill -s 0 $pid
+    rc=$?
+
+    if [ $rc -eq 0 ]; then
+        if ocf_is_true "$OCF_RESKEY_realtime"; then
+            astcanary_pid=`pgrep -d " " -f "astcanary $ASTRUNDIR/alt.asterisk.canary.tweet.tweet.tweet"`
+            if [ ! "$astcanary_pid" ]; then
+		ocf_log err "Asterisk PBX is running but astcanary is not although it should"
+		return $OCF_ERR_GENERIC
+            fi
+        else
+            return $OCF_SUCCESS
+        fi
+    else
+        ocf_log info "Asterisk PBX not running: removing old PID file"
+        rm -f $ASTRUNDIR/asterisk.pid
+        return $OCF_NOT_RUNNING
+    fi
+}
+
+asterisk_monitor() {
+    local rc
+
+    asterisk_status
+    rc=$?
+
+    # If status returned an error, return that immediately
+    if [ $rc -ne $OCF_SUCCESS ]; then
+        return $rc
+    fi
+
+    # Check whether connecting to asterisk is possible
+    asterisk_rx 'core show channels count'
+    rc=$?
+
+    if [ $rc -ne 0 ]; then
+      ocf_log err "Failed to connect to the Asterisk PBX"
+      return $OCF_ERR_GENERIC
+    fi
+
+    # Optionally check the monitor URI with sipsak
+    # The return values:
+    # 0 means that a 200 was received.
+    # 1 means something else then 1xx or 2xx was received.
+    # 2 will be returned on local errors like non resolvable names
+    #   or wrong options combination.
+    # 3 will be returned on remote errors like socket errors
+    #   (e.g. icmp error), redirects without a contact header or
+    #   simply no answer (timeout).
+    #   This can also happen if sipsak is run too early after asterisk
+    #   start.
+    if [ -n "$OCF_RESKEY_monitor_sipuri" ]; then
+        ocf_run sipsak -s "$OCF_RESKEY_monitor_sipuri"
+        rc=$?
+        case "$rc" in
+          1|2) return $OCF_ERR_GENERIC;;
+          3)   return $OCF_NOT_RUNNING;;
+        esac
+    fi
+
+    ocf_log debug "Asterisk PBX monitor succeeded"
+    return $OCF_SUCCESS
+}
+
+asterisk_start() {
+    local asterisk_extra_params
+    local dir
+    local rc
+
+    asterisk_status
+    rc=$?
+    if [ $rc -eq $OCF_SUCCESS ]; then
+        ocf_log info "Asterisk PBX already running"
+        return $OCF_SUCCESS
+    fi
+
+    # If Asterisk is not already running, make sure there is no
+    # old astcanary instance when the new asterisk starts. To
+    # achieve this, kill old astcanary instances belonging to
+    # this $ASTRUNDIR.
+
+    # Find out PIDs of running astcanaries
+    astcanary_pid=`pgrep -d " " -f "astcanary $ASTRUNDIR/alt.asterisk.canary.tweet.tweet.tweet"`
+
+    # If there are astcanaries running that belong to $ASTRUNDIR,
+    # kill them.
+    if [ "$astcanary_pid" ]; then
+      for i in $astcanary_pid; do ocf_run kill -s KILL $astcanary_pid; done
+    fi
+
+    for dir in $ASTRUNDIR $ASTLOGDIR $ASTLOGDIR/cdr-csv $ASTLOGDIR/cdr-custom; do
+        if [ ! -d "$dir" ]; then
+            ocf_run install -d -o $OCF_RESKEY_user -g $OCF_RESKEY_group $dir \
+                || exit $OCF_ERR_GENERIC
+        fi
+        # Regardless of whether we just created the directory or it
+        # already existed, check whether it is writable by the configured
+        # user
+        if ! su -s /bin/sh - $OCF_RESKEY_user -c "test -w $dir"; then
+            ocf_log err "Directory $dir is not writable by $OCF_RESKEY_user"
+            exit $OCF_ERR_PERM
+        fi
+    done
+
+    # set MAXFILES
+    ulimit -n $OCF_RESKEY_maxfiles
+
+    # Determine whether Asterisk PBX is supposed to run in Realtime mode
+    # or not and make asterisk daemonize automatically
+    if ocf_is_true "$OCF_RESKEY_realtime"; then
+      asterisk_extra_params="-F -p"
+    else
+      asterisk_extra_params="-F"
+    fi
+
+    ocf_run ${OCF_RESKEY_binary} -G $OCF_RESKEY_group -U $OCF_RESKEY_user \
+                -C $OCF_RESKEY_config \
+                $OCF_RESKEY_additional_parameters \
+                $asterisk_extra_params
+    rc=$?
+    if [ $rc -ne 0 ]; then
+        ocf_log err "Asterisk PBX start command failed: $rc"
+        exit $OCF_ERR_GENERIC
+    fi
+
+    # Spin waiting for the server to come up.
+    # Let the CRM/LRM time us out if required
+    while true; do
+        asterisk_monitor
+        rc=$?
+        [ $rc -eq $OCF_SUCCESS ] && break
+        if [ $rc -ne $OCF_NOT_RUNNING ]; then
+            ocf_log err "Asterisk PBX start failed"
+            exit $OCF_ERR_GENERIC
+        fi
+        sleep 2
+    done
+
+    ocf_log info "Asterisk PBX started"
+    return $OCF_SUCCESS
+}
+
+asterisk_stop() {
+    local pid
+    local astcanary_pid
+    local rc
+
+    asterisk_status
+    rc=$?
+    if [ $rc -eq $OCF_NOT_RUNNING ]; then
+        ocf_log info "Asterisk PBX already stopped"
+        return $OCF_SUCCESS
+    fi
+
+    pid=`cat $ASTRUNDIR/asterisk.pid`
+    ocf_run kill -s TERM $pid
+    rc=$?
+    if [ $rc -ne 0 ]; then
+        ocf_log err "Asterisk PBX couldn't be stopped"
+        exit $OCF_ERR_GENERIC
+    fi
+
+    # stop waiting
+    shutdown_timeout=15
+    if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
+        shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5))
+    fi
+    count=0
+    while [ $count -lt $shutdown_timeout ]; do
+        asterisk_status
+        rc=$?
+        if [ $rc -eq $OCF_NOT_RUNNING ]; then
+            break
+        fi
+        count=`expr $count + 1`
+        sleep 1
+        ocf_log debug "Asterisk PBX still hasn't stopped yet. Waiting ..."
+    done
+
+    asterisk_status
+    rc=$?
+    if [ $rc -ne $OCF_NOT_RUNNING ]; then
+        # SIGTERM didn't help either, try SIGKILL
+        ocf_log info "Asterisk PBX failed to stop after ${shutdown_timeout}s using SIGTERM. Trying SIGKILL ..."
+        ocf_run kill -s KILL $pid
+    fi
+
+    # After killing asterisk, stop astcanary
+    if ocf_is_true "$OCF_RESKEY_realtime"; then
+      astcanary_pid=`pgrep -d " " -f "astcanary $ASTRUNDIR/alt.asterisk.canary.tweet.tweet.tweet"`
+      if [ "$astcanary_pid" ]; then
+        for i in $astcanary_pid; do ocf_run kill -s KILL $astcanary_pid; done
+      fi
+    fi
+
+    ocf_log info "Asterisk PBX stopped"
+    return $OCF_SUCCESS
+}
+
+#######################################################################
+
+case "$1" in
+  meta-data)    meta_data
+                exit $OCF_SUCCESS;;
+  usage|help)   usage
+                exit $OCF_SUCCESS;;
+esac
+
+
+# Anything except meta-data and help must pass validation
+asterisk_validate || exit $?
+
+# Now that validate has passed and we can be sure to be able to read
+# the config file, set convenience variables
+ASTRUNDIR=`grep astrundir $OCF_RESKEY_config | awk '/^astrundir/ {print $3}'`
+ASTLOGDIR=`grep astlogdir $OCF_RESKEY_config | awk '/^astlogdir/ {print $3}'`
+
+# What kind of method was invoked?
+case "$1" in
+  start)        asterisk_start;;
+  stop)         asterisk_stop;;
+  status)       asterisk_status;;
+  monitor)      asterisk_monitor;;
+  validate-all) ;;
+  *)            usage
+                exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/heartbeat/conntrackd b/heartbeat/conntrackd
new file mode 100755
index 0000000..32eab6b
--- /dev/null
+++ b/heartbeat/conntrackd
@@ -0,0 +1,335 @@
+#!/bin/bash
+#
+#
+#       An OCF RA for conntrackd
+#	http://conntrack-tools.netfilter.org/
+#
+# Copyright (c) 2011 Dominik Klein
+#
+# 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.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+OCF_RESKEY_binary_default=conntrackd
+OCF_RESKEY_config_default=/etc/conntrackd/conntrackd.conf
+
+# For users of versions prior to 1.2:
+# Map renamed parameter "conntrackd" to "binary" if in use
+: ${OCF_RESKEY_binary=${OCF_RESKEY_conntrackd-${OCF_RESKEY_binary_default}}}
+: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="conntrackd">
+<version>1.2</version>
+
+<longdesc lang="en">
+Master/Slave OCF Resource Agent for conntrackd
+</longdesc>
+
+<shortdesc lang="en">This resource agent manages conntrackd</shortdesc>
+
+<parameters>
+<parameter name="binary">
+<longdesc lang="en">Name of the conntrackd executable.
+If conntrackd is installed and available in the default PATH, it is sufficient to configure the name of the binary
+For example "my-conntrackd-binary-version-0.9.14"
+If conntrackd is installed somewhere else, you may also give a full path
+For example "/packages/conntrackd-0.9.14/sbin/conntrackd"
+</longdesc>
+<shortdesc lang="en">Name of the conntrackd executable</shortdesc>
+<content type="string" default="$OCF_RESKEY_binary_default"/>
+</parameter>
+
+<parameter name="config">
+<longdesc lang="en">Full path to the conntrackd.conf file.
+For example "/packages/conntrackd-0.9.14/etc/conntrackd/conntrackd.conf"</longdesc>
+<shortdesc lang="en">Path to conntrackd.conf</shortdesc>
+<content type="string" default="$OCF_RESKEY_config_default"/>
+</parameter>
+</parameters>
+
+<actions>
+<action name="start"   timeout="30" />
+<action name="promote"	 timeout="30" />
+<action name="demote"	timeout="30" />
+<action name="notify"	timeout="30" />
+<action name="stop"    timeout="30" />
+<action name="monitor" timeout="20" interval="20" role="Slave" />
+<action name="monitor" timeout="20" interval="10" role="Master" />
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="30" />
+</actions>
+</resource-agent>
+END
+}
+
+meta_expect()
+{
+        local what=$1 whatvar=OCF_RESKEY_CRM_meta_${1//-/_} op=$2 expect=$3
+        local val=${!whatvar}
+        if [[ -n $val ]]; then
+                # [, not [[, or it won't work ;)
+                [ $val $op $expect ] && return
+        fi
+        ocf_log err "meta parameter misconfigured, expected $what $op $expect, but found ${val:-unset}."
+        exit $OCF_ERR_CONFIGURED
+}
+
+conntrackd_is_master() {
+	# You can't query conntrackd whether it is master or slave. It can be both at the same time. 
+	# This RA creates a statefile during promote and enforces master-max=1 and clone-node-max=1
+	ha_pseudo_resource $statefile monitor
+}
+
+conntrackd_set_master_score() {
+	${HA_SBIN_DIR}/crm_master -Q -l reboot -v $1
+}
+
+conntrackd_monitor() {
+	rc=$OCF_NOT_RUNNING
+	# It does not write a PID file, so check the socket exists after
+	# extracting its path from the configuration file
+	local conntrack_socket=$(awk '/^[ \t]*UNIX[ \t]*{/,/^[ \t]*}/ { if ($1 == "Path") { print $2 } }' $OCF_RESKEY_config)
+	[ -S "$conntrack_socket" ] && rc=$OCF_SUCCESS
+	if [ "$rc" -eq "$OCF_SUCCESS" ]; then
+		# conntrackd is running 
+		# now see if it acceppts queries
+		if ! $OCF_RESKEY_binary -C $OCF_RESKEY_config -s > /dev/null 2>&1; then
+			rc=$OCF_ERR_GENERIC
+			ocf_log err "conntrackd is running but not responding to queries"
+		fi
+		if conntrackd_is_master; then
+			rc=$OCF_RUNNING_MASTER
+			# Restore master setting on probes
+	                if [ $OCF_RESKEY_CRM_meta_interval -eq 0 ]; then
+				conntrackd_set_master_score $master_score
+			fi
+		else
+			# Restore master setting on probes
+	                if [ $OCF_RESKEY_CRM_meta_interval -eq 0 ]; then
+				conntrackd_set_master_score $slave_score
+			fi
+		fi
+	fi
+	return $rc
+}
+
+conntrackd_start() {
+        rc=$OCF_ERR_GENERIC
+
+        # Keep trying to start the resource;
+        # wait for the CRM to time us out if this fails
+	while :; do
+		conntrackd_monitor
+		status=$?
+		case "$status" in 
+		$OCF_SUCCESS)
+			conntrackd_set_master_score $slave_score
+			# -n = request resync from the others
+			if ! $OCF_RESKEY_binary -C $OCF_RESKEY_config -n; then
+				ocf_log err "$OCF_RESKEY_binary -C $OCF_RESKEY_config -n failed during start."
+				rc=$OCF_ERR_GENERIC
+			else
+				rc=$OCF_SUCCESS
+			fi
+			break
+			;;
+		$OCF_NOT_RUNNING)
+			ocf_log info "Starting conntrackd"
+			$OCF_RESKEY_binary -C $OCF_RESKEY_config -d
+			;;
+		$OCF_RUNNING_MASTER)
+			ocf_log warn "conntrackd already in master mode, demoting."
+			ha_pseudo_resource $statefile stop
+			;;
+		$OCF_ERR_GENERIC)
+			ocf_log err "conntrackd start failed"
+			rc=$OCF_ERR_GENERIC
+			break
+			;;
+		esac
+	done
+	return $rc
+}
+
+conntrackd_stop() {
+        rc=$OCF_ERR_GENERIC
+
+        # Keep trying to bring down the resource;
+        # wait for the CRM to time us out if this fails
+        while :; do
+                conntrackd_monitor
+                status=$?
+                case "$status" in
+                $OCF_SUCCESS|$OCF_ERR_GENERIC)
+			ocf_log info "Stopping conntrackd"
+                        $OCF_RESKEY_binary -C $OCF_RESKEY_config -k
+                        ;;
+                $OCF_NOT_RUNNING)
+                        rc=$OCF_SUCCESS
+                        break
+                        ;;
+                $OCF_RUNNING_MASTER)
+                        ocf_log warn "conntrackd still master"
+			;;
+                esac
+        done
+        return $rc
+
+}
+
+conntrackd_validate_all() {
+	check_binary "$OCF_RESKEY_binary"
+	if ! [ -e "$OCF_RESKEY_config" ]; then
+		ocf_log err "Config FILE $OCF_RESKEY_config does not exist"
+		return $OCF_ERR_INSTALLED
+	fi
+        meta_expect master-node-max = 1
+        meta_expect master-max = 1
+        meta_expect clone-node-max = 1
+	
+	return $OCF_SUCCESS
+}
+
+conntrackd_promote() {
+	rc=$OCF_SUCCESS
+	if ! conntrackd_is_master; then
+		# -c = Commit the external cache to the kernel
+		# -f = Flush internal and external cache
+		# -R = resync with the kernel table
+		# -B = send a bulk update on the line
+		for parm in c f R B; do
+			if ! $OCF_RESKEY_binary -C $OCF_RESKEY_config -$parm; then
+				ocf_log err "$OCF_RESKEY_binary -C $OCF_RESKEY_config -$parm failed during promote."
+				rc=$OCF_ERR_GENERIC
+				break
+			fi
+		done
+		ha_pseudo_resource $statefile start
+		conntrackd_set_master_score $master_score
+	fi
+	return $rc
+}
+
+conntrackd_demote() {
+	rc=$OCF_SUCCESS
+	if conntrackd_is_master; then
+		# -t = shorten kernel timers to remove zombies
+		# -n = request a resync from the others
+		for parm in t n; do
+			if ! $OCF_RESKEY_binary -C $OCF_RESKEY_config -$parm; then
+                        	ocf_log err "$OCF_RESKEY_binary -C $OCF_RESKEY_config -$parm failed during demote."
+                        	rc=$OCF_ERR_GENERIC
+                        	break
+                	fi
+        	done
+		ha_pseudo_resource $statefile stop
+		conntrackd_set_master_score $slave_score
+	fi
+	return $rc
+}
+
+conntrackd_notify() {
+	hostname=$(hostname)
+	# OCF_RESKEY_CRM_meta_notify_master_uname is a whitespace separated list of master hostnames
+	for master in $OCF_RESKEY_CRM_meta_notify_master_uname; do
+		# if we are the master and an instance was just started on another node:
+		# send a bulk update to allow failback
+		if [ "$hostname" = "$master" -a "$OCF_RESKEY_CRM_meta_notify_type" = "post" -a "$OCF_RESKEY_CRM_meta_notify_operation" = "start" -a "$OCF_RESKEY_CRM_meta_notify_start_uname" != "$hostname" ]; then
+			ocf_log info "Sending bulk update in post start to peers to allow failback"
+			$OCF_RESKEY_binary -C $OCF_RESKEY_config -B
+		fi
+	done
+	for tobepromoted in $OCF_RESKEY_CRM_meta_notify_promote_uname; do
+		# if there is a promote action to be executed on another node:
+		# send a bulk update to allow failback
+		if [ "$hostname" != "$tobepromoted" -a "$OCF_RESKEY_CRM_meta_notify_type" = "pre" -a "$OCF_RESKEY_CRM_meta_notify_operation" = "promote" ]; then
+			ocf_log info "Sending bulk update in pre promote to peers to allow failback"
+			$OCF_RESKEY_binary -C $OCF_RESKEY_config -B
+		fi
+	done
+}
+
+conntrackd_usage() {
+        cat <<EOF
+usage: $0 {start|stop|promote|demote|monitor|validate-all|meta-data}
+Expects to have a fully populated OCF RA-compliant environment set.
+EOF
+}
+
+statefile=conntrackd.${OCF_RESOURCE_INSTANCE}.master
+
+master_score=1000
+slave_score=100
+
+if [ $# -ne 1 ]; then
+	conntrackd_usage
+	exit $OCF_ERR_ARGS
+fi
+
+case $__OCF_ACTION in
+meta-data)
+	meta_data
+	exit $OCF_SUCCESS
+	;;
+usage)
+	conntrackd_usage
+	exit $OCF_SUCCESS
+esac
+
+# Everything except usage and meta-data must pass the validate test
+conntrackd_validate_all || exit
+
+case $__OCF_ACTION in
+start)
+	conntrackd_start
+	;;
+stop)
+	conntrackd_stop
+	;;
+promote)
+	conntrackd_promote
+	;;
+demote)
+	conntrackd_demote
+	;;
+status|monitor)
+	conntrackd_monitor
+	;;
+notify)
+	conntrackd_notify
+	;;
+validate-all)
+	;;
+*)
+	conntrackd_usage
+	exit $OCF_ERR_UNIMPLEMENTED
+esac
+# exit code is the exit code (return code) of the last command (shell function)
diff --git a/heartbeat/db2 b/heartbeat/db2
new file mode 100755
index 0000000..f9db2f8
--- /dev/null
+++ b/heartbeat/db2
@@ -0,0 +1,864 @@
+#!/bin/sh
+#
+# db2
+#
+# Resource agent that manages a DB2 LUW database in Standard role 
+# or HADR configuration in master/slave configuration.
+# Multi partition is supported as well.
+#
+# Copyright (c) 2011 Holger Teutsch <holger.teutsch at web.de>
+#
+# This agent incoporates code of a previous release created by
+# Alan Robertson and the community.
+#
+# 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.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+
+db2_usage() {
+    echo "db2 start|stop|monitor|promote|demote|notify|validate-all|meta-data"
+}
+
+db2_meta_data() {
+cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="db2">
+<version>1.0</version>
+<longdesc lang="en">
+Resource Agent that manages an IBM DB2 LUW databases in Standard role as primitive or in HADR roles in master/slave configuration. Multiple partitions are supported.
+
+Standard mode:
+
+An instance including all or selected databases is made highly available.
+Configure each partition as a separate primitive resource.
+
+HADR mode:
+
+A single database in HADR configuration is made highly available by automating takeover operations.
+Configure a master / slave resource with notifications enabled and an
+additional monitoring operation with role "Master".
+
+In case of HADR be very deliberate in specifying intervals/timeouts. The detection of a failure including promote must complete within HADR_PEER_WINDOW.
+
+In addition to honoring requirements for crash recovery etc. for your specific database use the following relations as guidance:
+
+"monitor interval" < HADR_PEER_WINDOW - (appr 30 sec)
+
+"promote timeout" < HADR_PEER_WINDOW + (appr 20 sec)
+
+For further information and examples consult http://www.linux-ha.org/wiki/db2_(resource_agent)
+</longdesc>
+<shortdesc lang="en">Resource Agent that manages an IBM DB2 LUW databases in Standard role as primitive or in HADR roles as master/slave configuration. Multiple partitions are supported.</shortdesc>
+
+<parameters>
+<parameter name="instance" unique="1" required="1">
+<longdesc lang="en">
+The instance of the database(s).
+</longdesc>
+<shortdesc lang="en">instance</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="dblist" unique="0" required="0">
+<longdesc lang="en">
+List of databases to be managed, e.g "db1 db2".
+Defaults to all databases in the instance. Specify one db for HADR mode.
+</longdesc>
+<shortdesc lang="en">List of databases to be managed</shortdesc>
+<content type="string"/>
+</parameter>
+<parameter name="admin" unique="0" required="0">
+<longdesc lang="en">
+DEPRECATED: The admin user of the instance.
+</longdesc>
+<shortdesc lang="en">DEPRECATED: admin</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="dbpartitionnum" unique="0" required="0">
+<longdesc lang="en">
+The number of the partion (DBPARTITIONNUM) to be managed.
+</longdesc>
+<shortdesc lang="en">database partition number (DBPARTITIONNUM)</shortdesc>
+<content type="string" default="0" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="120"/>
+<action name="stop" timeout="120"/>
+<action name="promote" timeout="120"/>
+<action name="demote" timeout="120"/>
+<action name="notify" timeout="10"/>
+<action name="monitor" depth="0" timeout="60" interval="20"/>
+<action name="monitor" depth="0" timeout="60" role="Master" interval="22"/>
+<action name="validate-all" timeout="5"/>
+<action name="meta-data" timeout="5"/>
+</actions>
+</resource-agent>
+END
+}
+
+#
+# validate
+# .. and set global variables
+#
+# exit on error
+#
+db2_validate() {
+    local db2home db2sql db2instance
+
+    # check required instance vars
+    if [ -z "$OCF_RESKEY_instance" ]
+    then
+        ocf_log err "DB2 required parameter instance is not set!"
+        return $OCF_ERR_CONFIGURED
+    fi
+
+    instance=$OCF_RESKEY_instance
+    if [ -n "$OCF_RESKEY_admin" ]
+    then
+        ocf_log warn "DB2 deprecated parameter admin is set, using $OCF_RESKEY_admin as instance."
+        instance=$OCF_RESKEY_admin
+    fi
+
+    db2node=${OCF_RESKEY_dbpartitionnum:-0}
+
+    db2home=$(sh -c "echo ~$instance")
+    db2sql=$db2home/sqllib
+    db2profile=$db2sql/db2profile
+    db2bin=$db2sql/bin
+
+    STATE_FILE=${HA_RSCTMP}/db2-${OCF_RESOURCE_INSTANCE}.state
+
+    #	Let's make sure a few important things are there...
+    if ! [ -d "$db2sql" -a  -d "$db2bin" -a -f "$db2profile" -a \
+           -x "$db2profile" -a -x "$db2bin/db2" ]
+    then
+        ocf_is_probe && exit $OCF_NOT_RUNNING
+        ocf_log err "DB2 required directories and/or files not found"
+        exit $OCF_ERR_INSTALLED
+    fi
+
+    db2instance=$(runasdb2 'echo $DB2INSTANCE')
+    if [ "$db2instance" != "$instance" ]
+    then
+        ocf_is_probe && exit $OCF_NOT_RUNNING
+        ocf_log err "DB2 parameter instance \"$instance\" != DB2INSTANCE \"$db2instance\""
+        exit $OCF_ERR_CONFIGURED
+    fi
+
+    # enough checking for stop to succeed
+    [ $__OCF_ACTION = stop ] && return $OCF_SUCCESS
+
+    dblist=$OCF_RESKEY_dblist
+    if [ -n "$dblist" ]
+    then
+        # support , as separator as well
+        dblist=$(echo "$dblist" | sed -e 's/[,]/ /g')
+    else
+        if ! dblist=$(db2_dblist)
+        then
+            ocf_log err "DB2 $instance($db2node): cannot retrieve db directory"
+            exit $OCF_ERR_INSTALLED
+        fi
+    fi
+
+    # check requirements for the HADR case
+    if ocf_is_ms
+    then
+        set -- $dblist
+        if [ $# != 1 ]
+        then
+            ocf_log err "DB2 resource $OCF_RESOURCE_INSTANCE must have exactly one name in dblist"
+            exit $OCF_ERR_CONFIGURED
+        fi
+
+        if [ $db2node != 0 ]
+        then
+            ocf_log err "DB2 resource $OCF_RESOURCE_INSTANCE must have dbpartitionnum=0"
+            exit $OCF_ERR_CONFIGURED
+        fi
+    fi
+
+    return $OCF_SUCCESS
+}
+
+
+#
+# Run the given command as db2 instance user
+#
+runasdb2() {
+    su $instance -c ". $db2profile; $*"
+}
+
+#
+# Run a command as the DB2 admin, and log the output
+#
+logasdb2() {
+    local output rc
+
+    output=$(runasdb2 $*)
+    rc=$?
+    if [ $rc -eq 0 ]
+    then
+        ocf_log info "$output"
+    else
+        ocf_log err "$output"
+    fi
+    return $rc
+}
+
+
+#
+# maintain the fal (first active log) attribute
+# db2_fal_attrib DB {set val|get}
+#
+db2_fal_attrib() {
+    local db=$1
+    local attr val rc id node member me
+
+    attr=db2hadr_${instance}_${db}_fal
+
+    case "$2" in
+        set)
+        me=$(uname -n)
+
+        # loop over all member nodes and set attribute
+        crm_node -l |
+        while read id node member
+        do
+            [ "$member" = member -a "$node" != "$me" ] || continue
+            crm_attribute -t nodes -l reboot --node=$node -n $attr -v "$3"
+            rc=$?
+            ocf_log info "DB2 instance $instance($db2node/$db: setting attrib for FAL to $FIRST_ACTIVE_LOG @ $node"
+            [ $rc != 0 ] && break
+        done
+        ;;
+
+        get)
+        crm_attribute -t nodes -l reboot -n $attr -G -Q 2>&1
+        rc=$?
+        if [ $rc != 0 ]
+        then
+            ocf_log warn "DB2 instance $instance($db2node/$db: can't retrieve attribute $attr, are you sure notifications are enabled ?"
+        fi
+        ;;
+
+        *)
+        exit $OCF_ERR_CONFIGURED
+    esac
+
+    return $rc
+}
+
+#
+# unfortunately a first connect after a crash may need several minutes
+# for some internal cleanup stuff in DB2.
+# We run a connect in background so other connects (i.e. monitoring!) may proceed.
+#
+db2_run_connect() {
+    local db=$1
+
+    logasdb2 "db2 connect to $db; db2 terminate"
+}
+
+#
+# get some data from the database config
+# sets HADR_ROLE HADR_TIMEOUT HADR_PEER_WINDOW
+#
+db2_get_cfg() {
+    local db=$1
+
+    local output hadr_vars
+
+    output=$(runasdb2 db2 get db cfg for $db)
+    [ $? != 0 ] && return $OCF_ERR_GENERIC
+
+    hadr_vars=$(echo "$output" |
+        awk '/HADR database role/ {printf "HADR_ROLE='%s'; ", $NF;}
+            /HADR_TIMEOUT/ {printf "HADR_TIMEOUT='%s'; ", $NF;}
+            /First active log file/ {printf "FIRST_ACTIVE_LOG='%s'\n", $NF;}
+            /HADR_PEER_WINDOW/ {printf "HADR_PEER_WINDOW='%s'\n", $NF;}')
+
+
+    # sets HADR_ROLE HADR_TIMEOUT HADR_PEER_WINDOW 
+    eval $hadr_vars
+
+    # HADR_PEER_WINDOW comes with V9 and is checked later
+    if [ -z "$HADR_ROLE" -o -z "$HADR_TIMEOUT" ]
+    then
+        ocf_log error "DB2 cfg values invalid for $instance($db2node)/$db: $hadr_vars"
+        return $OCF_ERR_GENERIC
+    fi
+
+    return $OCF_SUCCESS
+}
+
+#
+# return the list of databases in the instance
+#
+db2_dblist() {
+    local output
+
+    output=$(runasdb2 db2 list database directory) || return $OCF_ERR_GENERIC
+    
+    echo "$output" | grep -i 'Database name.*=' | sed 's%.*= *%%'
+}
+
+#
+# Delayed check of the compatibility of DB2 instance and pacemaker
+# config.
+# Logically this belongs to validate but certain parameters can only
+# be retrieved once the instance is started.
+#
+db2_check_config_compatibility() {
+    local db=$1
+    local is_ms
+
+    ocf_is_ms
+    is_ms=$?
+
+    case "$HADR_ROLE/$is_ms" in
+        STANDARD/0)
+        ocf_log err "DB2 database $instance/$db is not in a HADR configuration but I am a M/S resource"
+        exit $OCF_ERR_INSTALLED
+        ;;
+
+        STANDARD/1)
+        # OK
+        ;;
+
+        */0)
+        if [ -z "$HADR_PEER_WINDOW" ]
+        then
+            ocf_log err "DB2 database $instance: release to old, need HADR_PEER_WINDOW (>=V9)"
+            exit $OCF_ERR_INSTALLED
+        fi
+        ;;
+
+        */1)
+        ocf_log err "DB2 database $instance/$db is in a HADR configuration but I must be a M/S resource"
+    esac
+
+}
+
+#
+# Start instance and DB.
+# Standard mode is through "db2 activate" in order to start in previous
+# mode (Standy/Primary).
+# If the database is a primary AND we can determine that the running master
+# has a higher "first active log" we conclude that we come up after a crash
+# an the previous Standby is now Primary.
+# The db is then started as Standby.
+#
+# Other cases: danger of split brain, log error and do nothing.
+#
+db2_start() {
+    local output start_cmd db
+
+    if output=$(runasdb2 db2start dbpartitionnum $db2node)
+    then
+        ocf_log info "DB2 instance $instance($db2node) started: $output"
+    else
+        case $output in
+            *SQL1026N*)
+            ocf_log info "DB2 instance $instance($db2node) already running: $output"
+            ;;
+
+            *)
+            ocf_log err "$output"
+            return $OCF_ERR_GENERIC
+        esac
+    fi
+
+    if ! db2_instance_status
+    then
+        ocf_log err "DB2 instance $instance($db2node) is not active!"
+        return $OCF_ERR_GENERIC
+    fi
+
+    [ $db2node = 0 ] || return $OCF_SUCCESS
+    # activate DB only on node 0
+
+    for db in $dblist
+    do
+        # sets HADR_ROLE HADR_TIMEOUT HADR_PEER_WINDOW FIRST_ACTIVE_LOG
+        db2_get_cfg $db || return $?
+
+        # Better late than never: can only check this when the instance is already up
+        db2_check_config_compatibility $db
+
+        start_cmd="db2 activate db $db"
+
+        if [ $HADR_ROLE = PRIMARY ]
+        then
+            local master_fal
+
+            # communicate our FAL to other nodes the might start concurrently
+            db2_fal_attrib $db set $FIRST_ACTIVE_LOG
+
+            if master_fal=$(db2_fal_attrib $db get) && [ "$master_fal" '>' $FIRST_ACTIVE_LOG ]
+            then
+                ocf_log info "DB2 database $instance($db2node)/$db is Primary and outdated, starting as secondary"
+                start_cmd="db2 start hadr on db $db as standby"
+                HADR_ROLE=STANDBY
+            fi
+        fi
+
+        if output=$(runasdb2 $start_cmd)
+        then
+            ocf_log info "DB2 database $instance($db2node)/$db started/activated"
+            [ $HADR_ROLE != STANDBY ] && db2_run_connect $db &
+        else
+            case $output in
+                SQL1490W*|SQL1494W*|SQL1497W*|SQL1777N*)
+                ocf_log info "DB2 database $instance($db2node)/$db already activated: $output"
+                ;;
+
+                SQL1768N*"Reason code = \"7\""*)
+                ocf_log err "DB2 database $instance($db2node)/$db is a Primary and the Standby is down"
+                ocf_log err "Possible split brain ! Manual intervention required."
+                ocf_log err "If this DB is outdated use \"db2 start hadr on db $db as standby\""
+                ocf_log err "If this DB is the surviving primary use \"db2 start hadr on db $db as primary by force\""
+
+                # might be the Standby is not yet there
+                # might be a timing problem because "First active log" is delayed
+                #    on the next start attempt we might succeed when FAL was advanced
+                # might be manual intervention is required
+                # ... so let pacemaker give it another try and we will succeed then
+                return $OCF_ERR_GENERIC
+                ;;
+
+                *)
+                ocf_log err "DB2 database $instance($db2node)/$db didn't start: $output"
+                return $OCF_ERR_GENERIC
+            esac
+        fi
+    done
+
+    # come here with success
+    # Even if we are a db2 Primary pacemaker requires start to end up in slave mode
+    echo SLAVE > $STATE_FILE
+    return $OCF_SUCCESS
+}
+
+#
+# helper function to be spawned
+# so we can detect a hang of the db2stop command
+#
+db2_stop_bg() {
+    local rc output
+
+    rc=$OCF_SUCCESS
+
+    if output=$(runasdb2 db2stop force dbpartitionnum $db2node)
+    then
+        ocf_log info "DB2 instance $instance($db2node) stopped: $output"
+    else
+        case $output in
+            *SQL1032N*)
+            #SQL1032N  No start database manager command was issued
+            ocf_log info "$output"
+            ;;
+
+            *)
+            ocf_log err "DB2 instance $instance($db2node) stop failed: $output"
+            rc=$OCF_ERR_GENERIC
+        esac
+    fi
+
+    return $rc
+}
+
+#
+# Stop the given db2 database instance
+#
+db2_stop() {
+    local stop_timeout grace_timeout stop_bg_pid i must_kill
+
+    # remove master score
+    crm_master -D -l reboot
+
+    # be very early here in order to avoid stale data
+    rm -f $STATE_FILE
+
+    if ! db2_instance_status
+    then
+        ocf_log info "DB2 instance $instance already stopped"
+        return $OCF_SUCCESS
+    fi
+
+    stop_timeout=${OCF_RESKEY_CRM_meta_timeout:-20000}
+
+    # grace_time is 4/5 (unit is ms)
+    grace_timeout=$((stop_timeout/1250))
+
+    # start db2stop in background as this may hang
+    db2_stop_bg &
+    stop_bg_pid=$!
+
+    # wait for grace_timeout
+    i=0
+    while [ $i -lt $grace_timeout ]
+    do
+        kill -0 $stop_bg_pid 2>/dev/null || break;
+        sleep 1
+        i=$((i+1))
+    done
+
+    # collect exit status but don't hang
+    if kill -0 $stop_bg_pid 2>/dev/null
+    then
+        stoprc=1
+        kill -9 $stop_bg_pid 2>/dev/null
+    else
+        wait $stop_bg_pid
+        stoprc=$?
+    fi
+
+    must_kill=0
+
+    if [ $stoprc -ne 0 ]
+    then
+        ocf_log warn "DB2 instance $instance($db2node): db2stop failed, using db2nkill"
+        must_kill=1
+    elif ! db2_instance_dead
+    then
+        ocf_log warn "DB2 instance $instance($db2node): db2stop indicated success but there a still processes, using db2nkill"
+        must_kill=1
+    fi
+
+    if [ $must_kill -eq 1 ]
+    then
+        # db2nkill kills *all* partions on the node
+        if [ -x $db2bin/db2nkill ]
+        then
+            logasdb2 $db2bin/db2nkill $db2node
+        elif [ -x $db2bin/db2_kill ]
+        then
+            logasdb2 $db2bin/db2_kill
+        fi
+
+        # loop forever (or lrmd kills us due to timeout) until the
+        # instance is dead
+        while ! db2_instance_dead
+        do
+            ocf_log info "DB2 instance $instance($db2node): waiting for processes to exit"
+            sleep 1
+        done
+
+        ocf_log info "DB2 instance $instance($db2node) is now dead"
+    fi
+
+    return $OCF_SUCCESS
+}
+
+#
+# check whether `enough´ processes for a healthy instance are up
+# 
+db2_instance_status() {
+    local pscount
+
+    pscount=$(runasdb2 $db2bin/db2nps $db2node | cut -c9- |  grep ' db2[^ ]' | wc -l)
+    test $pscount -ge 4
+}
+
+#
+# is the given db2 instance dead?
+# 
+db2_instance_dead() {
+    local pscount
+
+    pscount=$(runasdb2 $db2bin/db2nps $db2node | cut -c9- |  grep ' db2[^ ]' | wc -l)
+    test $pscount -eq 0
+}
+
+#
+# return the status of the db as "Role/Status"
+# e.g. Primary/Peer, Standby/RemoteCatchupPending
+#
+# If not in HADR configuration return "Standard/Standalone"
+#
+db2_hadr_status() {
+    local db=$1
+    local output
+
+    output=$(runasdb2 db2pd -hadr -db $db)
+    if [ $? != 0 ]
+    then
+        echo "Down/Off"
+        return 1 
+    fi
+
+    echo "$output" |
+    awk '/^HADR is not active/ {print "Standard/Standalone"; exit; }
+         /^Role *State */ {getline; printf "%s/%s\n", $1, $2; exit; }'
+}
+
+#
+# Monitor the db
+# And as side effect set crm_master / FAL attribute
+#
+db2_monitor() {
+    local CMD output hadr db
+
+    if ! db2_instance_status
+    then
+        # instance is dead remove master score
+        crm_master -D -l reboot
+        exit $OCF_NOT_RUNNING
+    fi
+
+    [ $db2node = 0 ] || return 0
+    # monitoring only for partition 0
+
+    for db in $dblist
+    do
+        hadr=$(db2_hadr_status $db) || return $OCF_ERR_GENERIC
+        ocf_log debug "Monitor: DB2 database $instance($db2node)/$db has HADR status $hadr"
+
+        # set master preference accordingly
+        case "$hadr" in
+            Primary/*|Standard/*)
+            # perform  a basic health check
+            CMD="if db2 connect to $db;
+            then 
+                db2 select \* from sysibm.sysversions ; rc=\$?;
+                db2 terminate;
+            else
+                rc=\$?;
+            fi;
+            exit \$rc"
+
+            if ! output=$(runasdb2 $CMD)
+            then
+                case "$output" in
+                    SQL1776N*)
+                    # can't connect/select on standby, may be spurious turing takeover
+                    ;;
+
+                    *)
+                    ocf_log err "DB2 database $instance($db2node)/$db is not working"
+                    ocf_log err "DB2 message: $output"
+
+                    # dead primary, remove master score
+                    crm_master -D -l reboot
+                    return $OCF_ERR_GENERIC
+                esac
+            fi
+
+            ocf_log debug "DB2 database $instance($db2node)/$db appears to be working"
+            ocf_is_ms && crm_master -v 10000 -l reboot
+            ;;
+
+            Standby/*Peer)
+            crm_master -v 8000 -l reboot
+            ;;
+
+            Standby/*)
+            ocf_log warn "DB2 database $instance($db2node)/$db in status $hadr can never be promoted"
+            crm_master -D -l reboot
+            ;;
+
+            *)
+            return $OCF_ERR_GENERIC
+        esac
+    done
+
+    # everything OK, return if running as slave
+    grep MASTER $STATE_FILE >/dev/null 2>&1 || return $OCF_SUCCESS
+
+    return $OCF_RUNNING_MASTER
+}
+
+#
+# Promote db to Primary
+#
+db2_promote() {
+    # validate ensured that dblist contains only one entry
+    local db=$dblist
+    local i hadr output force
+
+    # we run this twice as after a crash of the other node
+    # within HADR_TIMEOUT the status may be still reported as Peer
+    # although a connection no longer exists
+
+    for i in 1 2
+    do
+        hadr=$(db2_hadr_status $db) || return $OCF_ERR_GENERIC
+        ocf_log info "DB2 database $instance($db2node)/$db has HADR status $hadr and will be promoted"
+
+        case "$hadr" in
+            Standard/Standalone)
+            # this case only to keep ocf-tester happy
+            return $OCF_SUCCESS
+            ;;
+
+            Primary/Peer)
+            # nothing to do, only update pacemaker's view
+            echo MASTER > $STATE_FILE
+            return $OCF_SUCCESS
+            ;;
+
+            Standby/Peer)
+            # must take over 
+            ;;
+
+            Standby/DisconnectedPeer)
+            # must take over forced 
+            force="by force peer window only"
+            ;;
+
+            *)
+            return $OCF_ERR_GENERIC
+        esac
+
+        if output=$(runasdb2 db2 takeover hadr on db $db $force)
+        then
+            # update pacemaker's view
+            echo MASTER > $STATE_FILE
+
+            # turn the log so we rapidly get a new FAL
+            logasdb2 "db2 archive log for db $db"
+            return $OCF_SUCCESS
+        fi
+
+        case "$output" in
+            SQL1770N*"Reason code = \"7\""*)
+            # expected, HADR_TIMEOUT is now expired
+            # go for the second try
+            continue
+            ;;
+
+            *)
+            ocf_log err "DB2 database $instance($db2node)/$db promote failed: $output"
+            return $OCF_ERR_GENERIC
+        esac
+    done
+
+    return $OCF_ERR_GENERIC
+}
+
+#
+# Demote db to standby
+#
+db2_demote() {
+    # validate ensured that dblist contains only one entry
+    local db=$dblist
+    local hadr
+    
+    # house keeping, set pacemaker's view to slave
+    echo SLAVE > $STATE_FILE
+
+    hadr=$(db2_hadr_status $dblist) || return $OCF_ERR_GENERIC
+    ocf_log info "DB2 database $instance($db2node)/$db has HADR status $hadr and will be demoted"
+
+    db2_monitor
+    return $?
+}
+
+#
+# handle pre start notification
+# We record our first active log on the other nodes.
+# If two primaries come up after a crash they can safely determine who is
+# the outdated one.
+#
+db2_notify() {
+    local node
+
+    # only interested in pre-start
+    [  $OCF_RESKEY_CRM_meta_notify_type = pre \
+    -a $OCF_RESKEY_CRM_meta_notify_operation = start ] || return $OCF_SUCESS
+
+    # gets FIRST_ACTIVE_LOG
+    db2_get_cfg $dblist || return $?
+
+    db2_fal_attrib $dblist set $FIRST_ACTIVE_LOG || return $OCF_ERR_GENERIC
+    exit $OCF_SUCCESS
+}
+
+########
+# Main #
+########
+case "$__OCF_ACTION" in
+    meta-data)
+    db2_meta_data
+    exit $OCF_SUCCESS
+    ;;
+
+    usage)
+    db2_usage
+    exit $OCF_SUCCESS
+    ;;
+
+    start)
+    db2_validate
+    db2_start || exit $?
+    db2_monitor
+    exit $?
+    ;;
+
+    stop)
+    db2_validate
+    db2_stop
+    exit $?
+    ;;
+
+    promote)
+    db2_validate
+    db2_promote
+    exit $?
+    ;;
+
+    demote)
+    db2_validate
+    db2_demote
+    exit $?
+    ;;
+
+    notify)
+    db2_validate
+    db2_notify
+    exit $?
+    ;;
+
+    monitor)	
+    db2_validate
+    db2_monitor
+    exit $?
+    ;;
+
+    validate-all)
+    db2_validate
+    exit $?
+    ;;
+
+    *)
+    db2_usage
+    exit $OCF_ERR_UNIMPLEMENTED
+esac
diff --git a/heartbeat/dhcpd b/heartbeat/dhcpd
new file mode 100755
index 0000000..835a788
--- /dev/null
+++ b/heartbeat/dhcpd
@@ -0,0 +1,545 @@
+#!/bin/sh
+#
+#   Resource Agent for managing dhcpd resources.
+#
+#   License:      GNU General Public License (GPL)
+#   (c) 2011-2012 Chris Bowlby,
+#
+# A fair amount of this script has been pulled from the official 0dhcpd 
+# init script. Those portions have been integrated into this script to
+# ensure consistent behavior between the resource agent and the
+# original script. The copyrights and original authors are credited
+# as follows:
+#
+# Copyright (c) 1996, 1997, 1998 S.u.S.E. GmbH
+# Copyright (c) 1998, 1999, 2000, 2001 SuSE GmbH
+# Copyright (c) 2002, 2003 SuSE Linux AG
+# Copyright (c) 2004-2008 SUSE LINUX Products GmbH, Nuernberg, Germany.
+#
+# Author(s) : Rolf Haberrecker <rolf at suse.de>, 1997-1999
+#             Peter Poeml <poeml at suse.de>, 2000-2006
+#             Marius Tomaschewski <mt at suse.de>, 2006-2010
+#
+#                 and Linux-HA contributors
+
+# Initialization:
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+OCF_RESKEY_binary_default="dhcpd"
+OCF_RESKEY_pid_default="/var/run/dhcpd.pid"
+OCF_RESKEY_user_default=dhcpd
+OCF_RESKEY_group_default=nogroup
+OCF_RESKEY_config_default=""
+OCF_RESKEY_chrooted_default="true"
+OCF_RESKEY_chrooted_path_default="/var/lib/dhcp"
+OCF_RESKEY_leases_default="/db/dhcpd.leases"
+OCF_RESKEY_interface_default=""
+OCF_RESKEY_includes_default=""
+
+: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
+: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
+: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}}
+: ${OCF_RESKEY_group=${OCF_RESKEY_group_default}}
+: ${OCF_RESKEY_chrooted=${OCF_RESKEY_chrooted_default}}
+: ${OCF_RESKEY_chrooted_path=${OCF_RESKEY_chrooted_path_default}}
+: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
+: ${OCF_RESKEY_leases=${OCF_RESKEY_leases_default}}
+: ${OCF_RESKEY_interface=${OCF_RESKEY_interface_default}}
+: ${OCF_RESKEY_includes=${OCF_RESKEY_includes_default}}
+
+# To enable support for different versions of dhcp, we need
+# to know what version we are being run against.
+DHCP_VERSION_MAJOR=`$OCF_RESKEY_binary --version 2>&1 | awk -F- '{print $3}' | awk -F.  '{print $1}' | sed s/^[a-zA-Z]//g`
+
+# These files are always copied by default to ensure the chroot environment works.
+DEFAULT_FILE_LIST="/etc/gai.conf /etc/nsswitch.conf /etc/resolv.conf /etc/host.conf /etc/hosts /etc/localtime /dev/urandom"
+
+usage() {
+    cat <<EOF
+        usage: $0 start|stop|monitor|meta-data|validate-all
+
+        $0 manages the dhcp (dhcpd) server as an HA resource.
+
+        The 'start' operation starts the dhcpd server.
+        The 'stop' operation stops the dhcpd server.
+        The 'monitor' operation reports whether the dhcpd service is running.
+        The 'validate-all' operation reports whether the parameters are valid.
+EOF
+  return $OCF_SUCCESS
+}
+
+dhcpd_meta_data()  {
+        cat <<EOF
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="dhcpd" version="0.1">
+  <version>0.1</version>
+  <longdesc lang="en">
+Manage an ISC DHCP server service in a chroot environment.
+  </longdesc>
+  <shortdesc lang="en">Chrooted ISC DHCP server resource agent.</shortdesc>
+  <parameters>
+    <parameter name="config" unique="1" required="1">
+      <longdesc lang="en">
+	The absolute path to the DHCP server configuration file.
+      </longdesc>
+      <shortdesc lang="en">Configuration file</shortdesc>
+      <content type="string" default="$OCF_RESKEY_config_default"/>
+    </parameter>
+    <parameter name="chrooted" unique="1" required="0">
+      <longdesc lang="en">
+	Configure the dhcpd service to run in a chrooted or non-chrooted
+	mode.
+      </longdesc>
+      <shortdesc lang="en">Enable chroot mode</shortdesc>
+      <content type="boolean" default="$OCF_RESKEY_chrooted_default"/>
+    </parameter>
+    <parameter name="chrooted_path" unique="1" required="0">
+      <longdesc lang="en">
+	The absolute path of the chrooted DHCP environment.
+      </longdesc>
+      <shortdesc lang="en">The chrooted path</shortdesc>
+      <content type="string" default="$OCF_RESKEY_chrooted_path_default"/>
+    </parameter>
+    <parameter name="binary" unique="0" required="0">
+      <longdesc lang="en">
+	The binary for the DHCP server process. An absolute path
+	definition is not required, but can be used to override
+	environment path.
+      </longdesc>
+      <shortdesc lang="en">dhcpd binary</shortdesc>
+      <content type="string" default="$OCF_RESKEY_binary_default"/>
+    </parameter>
+    <parameter name="user" unique="0" required="0">
+      <longdesc lang="en">
+	The system user the DHCP server process will run as when
+	it is chrooted.
+      </longdesc>
+      <shortdesc lang="en">dhcpd owner</shortdesc>
+      <content type="string" default="$OCF_RESKEY_user_default"/>
+    </parameter>
+    <parameter name="group" unique="0" required="0">
+      <longdesc lang="en">
+	The system group the DHCP server process will run as when
+	it is chrooted.
+      </longdesc>
+      <shortdesc lang="en">dhcpd group owner</shortdesc>
+      <content type="string" default="$OCF_RESKEY_group_default"/>
+    </parameter>
+    <parameter name="interface" unique="0" required="0">
+      <longdesc lang="en">
+	The network interface(s) the DHCP server process will
+	bind to. A blank value will bind the process to all
+	interfaces.
+      </longdesc>
+      <shortdesc lang="en">Network Interface</shortdesc>
+      <content type="string" default="$OCF_RESKEY_interface_default"/>
+    </parameter>
+    <parameter name="includes" unique="0" required="0">
+      <longdesc lang="en">
+	This parameter provides a means to copy include files
+	into the chrooted environment. If a dhcpd.conf file
+	contains a line similar to this:
+
+		include "/etc/named.keys";
+
+	Then an admin also has to tell the dhcpd RA that this
+	file should be pulled into the chrooted environment. This
+	is a space delimited list.
+      </longdesc>
+      <shortdesc lang="en">Include files</shortdesc>
+      <content type="string" default="$OCF_RESKEY_includes_default"/>
+    </parameter>
+    <parameter name="leases" unique="0" required="0">
+      <longdesc lang="en">
+	The leases database file, relative to chrooted_path.
+      </longdesc>
+      <shortdesc lang="en">Leases file</shortdesc>
+      <content type="string" default="$OCF_RESKEY_leases_default"/>
+    </parameter>
+    <parameter name="pid" unique="0" required="0">
+      <longdesc lang="en">
+	The path and filename of the PID file. It is relative
+	to chrooted_path.
+      </longdesc>
+      <shortdesc lang="en">PID file</shortdesc>
+      <content type="string" default="$OCF_RESKEY_pid_default"/>
+    </parameter>
+  </parameters>
+  <actions>
+    <action name="start"        timeout="20" />
+    <action name="stop"         timeout="20" />
+    <action name="monitor"      timeout="20" interval="10" depth="0" />
+    <action name="meta-data"    timeout="5" />
+    <action name="validate-all"   timeout="20" />
+  </actions>
+</resource-agent>
+EOF
+}
+
+# Validate most critical parameters
+dhcpd_validate_all() {
+    check_binary $OCF_RESKEY_binary
+
+
+    if ! ocf_is_probe; then
+	# Test for the appropriate configuration files depending on if
+	# chroot mode is enabled.
+	if ocf_is_true $OCF_RESKEY_chrooted ; then
+	    if ! test -e "$OCF_RESKEY_chrooted_path"; then
+		ocf_log err "Path $OCF_RESKEY_chrooted_path does not exist."
+		return $OCF_ERR_INSTALLED
+	    fi
+
+	    if test -n "$OCF_RESKEY_chrooted_path/$OCF_RESKEY_config" -a ! -r "$OCF_RESKEY_chrooted_path/$OCF_RESKEY_config"; then
+		ocf_log err "Configuration file $OCF_RESKEY_chrooted_path/$OCF_RESKEY_config doesn't exist"
+		return $OCF_ERR_INSTALLED
+	    fi
+	else
+	    if test -n "$OCF_RESKEY_config" -a ! -r "$OCF_RESKEY_config"; then
+		ocf_log err "Configuration file $OCF_RESKEY_config doesn't exist"
+		return $OCF_ERR_INSTALLED
+	    fi
+	fi
+
+    fi 
+
+    if ! getent passwd $OCF_RESKEY_user >/dev/null 2>&1; then
+        ocf_log err "User $OCF_RESKEY_user doesn't exist"
+        return $OCF_ERR_INSTALLED
+    fi
+
+    return $OCF_SUCCESS
+}
+
+# dhcpd_monitor. Send a request to dhcpd and check response.
+dhcpd_monitor() {
+    # Assume chrooted mode is being used, but if not update the PIDF
+    # variable to point to the non-chrooted PID file.
+    PIDF="$OCF_RESKEY_chrooted_path/$OCF_RESKEY_pid"
+
+    if ! ocf_is_true $OCF_RESKEY_chrooted ; then
+	PIDF=`dirname $OCF_RESKEY_pid`/dhcpd/`basename $OCF_RESKEY_pid`
+    fi
+
+    ocf_pidfile_status $PIDF >/dev/null 2>&1 || return $OCF_NOT_RUNNING
+
+    return $OCF_SUCCESS
+}
+
+# Initialize Chroot
+dhcpd_initialize_chroot() {
+    # If we are running the initialization for the first time, we need to make
+    # the new chrooted folder, in case we are not using the same default.
+    if ! [ -d $OCF_RESKEY_chrooted_path ] ; then
+	ocf_log info "Initializing $OCF_RESKEY_chrooted_path for use."
+    fi
+
+    # Make sure all sub-paths are created if something went wrong during
+    # a partial run.
+    for i in db dev etc lib64 var/run; do
+	mkdir -p $OCF_RESKEY_chrooted_path/$i
+    done
+
+    # If we are running version 4 of the dhcp server, we need to mount a proc partition.
+    if [ $DHCP_VERSION_MAJOR -ge 4 ] ; then
+	mkdir -p $OCF_RESKEY_chrooted_path/proc
+
+	if ! [ -e $OCF_RESKEY_chrooted_path/proc/net/dev ] ; then
+	    mount -t proc -o ro proc $OCF_RESKEY_chrooted_path/proc > /dev/null 2>&1
+	fi
+    fi
+
+    # If the folder to store the PID file does not exist, make it.
+    if ! [ -d "$OCF_RESKEY_chrooted_path`dirname $OCF_RESKEY_pid`" ] ; then
+	mkdir -p "$OCF_RESKEY_chrooted_path`dirname $OCF_RESKEY_pid`"
+    fi
+
+    # Ensure all permissions are in place if the folder was re-created.
+    chown -R $OCF_RESKEY_user:$OCF_RESKEY_group $OCF_RESKEY_chrooted_path/`dirname $OCF_RESKEY_leases`
+    chown -R $OCF_RESKEY_user:$OCF_RESKEY_group "$OCF_RESKEY_chrooted_path/`dirname $OCF_RESKEY_pid`"
+
+    ## If there is no conf file, we can't initialize the chrooted 
+    ## environment, return with "program not configured"
+    if ! [ -f $OCF_RESKEY_config ] ; then
+	ocf_log err "dhcpd has not been configured."
+	return $OCF_ERR_CONFIGURED
+    fi
+
+    # If the leases file does not exist, create it, as this is a fresh install.
+    if [ ! -e $OCF_RESKEY_chrooted_path/$OCF_RESKEY_leases ]; then
+	touch $OCF_RESKEY_chrooted_path/$OCF_RESKEY_leases
+    fi
+
+    # Remove the random device.
+    test -e "$OCF_RESKEY_chrooted_path/dev/urandom" &&
+	rm -f $OCF_RESKEY_chrooted_path/dev/urandom
+
+    # Test for the existance of the defined include files, and append
+    # them to the list of files to be copied.
+    for i in $OCF_RESKEY_includes ; do
+	if [ -e $i ] ; then
+	    DEFAULT_FILE_LIST="$DEFAULT_FILE_LIST $i"
+	else
+	    ocf_log err "include file $i does not exist"
+	    return $OCF_ERR_INSTALLED
+	fi
+    done
+
+    # Ensure all "modified" non-chrooted configuration files are copied into the chrooted environment.
+    for i in $OCF_RESKEY_config $DEFAULT_FILE_LIST; do
+	# First, lets make sure the directory exists within the chrooted environment.
+	if test -d "$i" ; then
+	    mkdir -p $OCF_RESKEY_chrooted_path/$i
+	elif test -e "$i" ; then
+	    mkdir -p "`dirname $OCF_RESKEY_chrooted_path/$i`"
+	fi
+
+	# Next, we copy the configuration file into place.
+	cp -aL "$i" "$OCF_RESKEY_chrooted_path/${i%/*}/" > /dev/null 2>&1 ||
+	    { ocf_log err "could not copy $i to chroot jail"; return $OCF_ERR_GENERIC; }
+    done
+
+    libdir=$(basename $(echo /var/lib/dhcp/lib*))
+    if test -x /usr/bin/ldd ; then
+	get_ldd_deps()
+	{
+	    ldd_wl="\/$libdir\/lib"
+	    ldd_bl="\/$libdir\/libc\."
+	    /usr/bin/ldd "$1" | while read a b c d ; do
+		[ -n "$c" ] || continue
+		[[ $c =~ $ldd_wl ]] || continue
+		[[ $c =~ $ldd_bl ]] && continue
+		echo $c
+	    done
+	}
+    else
+	get_ldd_deps() { :; }
+    fi
+    cplibs=`for i in /$libdir/libresolv.so.* /$libdir/libnss_*.so.* /$libdir/libpthread.so.0 /$libdir/libdl.so.2
+    do
+	if [ -s "$i" ] ; then
+	    echo "$i"
+	    get_ldd_deps "$i"
+	fi
+    done | sort -u`
+    for i in $cplibs ; do
+	if [ -s "$i" ]; then
+	    cp -pL "$i" "/var/lib/dhcp/$libdir/" ||
+		{ ocf_log err "could not copy $i to chroot jail"; return $OCF_ERR_GENERIC; }
+	fi
+    done
+
+   return $OCF_SUCCESS
+}
+
+# Initialize a non-chroot environment
+dhcpd_initialize() {
+    ## If there is no conf file, we can't start a dhcp service.
+    if ! [ -f $OCF_RESKEY_config ] ; then
+	ocf_log err "dhcpd has not been configured."
+	return $OCF_ERR_CONFIGURED
+    fi
+
+    # As with the standard DHCP init script, we can still use the
+    # chrooted default path for storing the leases file. This behavior
+    # is consistent with the existing /etc/init.d/dhcpd script.
+    if ! [ -d $OCF_RESKEY_chrooted_path ] ; then
+	ocf_log info "Initializing $OCF_RESKEY_chrooted_path for use."
+    fi
+    
+    # If the leases file does not exist, create it, as this is a fresh install.
+    if [ ! -e $OCF_RESKEY_chrooted_path/$OCF_RESKEY_leases ]; then
+	touch $OCF_RESKEY_chrooted_path/$OCF_RESKEY_leases
+    fi
+
+    # if the PID storage path does not exist, make it, and setup the permissions.
+
+    # NOTE: This part of the script has a potential security flaw, in that if someone
+    # puts in /var/run as the path, it will change ownership to the dhcpd user
+    # and group. However, all that would do is allow that user to view the contents
+    # of the files, which they can do now anyway. If this becomes an issue, I can work
+    # in some changes.
+
+    # We need to append "dhcpd" to the path for the PID file storage folder, because
+    # if /var/run is used, that folders permissions can not be changed, otherwise it affects
+    # more then just one application.
+    if ! [ -d `dirname $OCF_RESKEY_pid`/dhcpd ] ; then
+	mkdir -p `dirname $OCF_RESKEY_pid`/dhcpd
+
+        if [ -n "$OCF_RESKEY_user" -a "x$OCF_RESKEY_user" != "xroot" ] ; then
+	    chown $OCF_RESKEY_user `dirname $OCF_RESKEY_pid`/dhcpd
+        fi
+    
+        if [ -n "$OCF_RESKEY_group" -a "x$OCF_RESKEY_group" != "xwheel" ] ; then
+	    chgrp $OCF_RESKEY_group `dirname $OCF_RESKEY_pid`/dhcpd
+        fi
+    fi
+
+    return $OCF_SUCCESS
+}
+
+# Start
+dhcpd_start() {
+    # Lets make sure we are not already running.
+    if dhcpd_monitor; then
+		ocf_log info "dhcpd already running"
+		return $OCF_SUCCESS
+	fi
+
+    # Only initialize the chrooted path(s) if chroot mode is enabled.
+    if ocf_is_true $OCF_RESKEY_chrooted ; then
+	dhcpd_initialize_chroot ||
+	    { ocf_log err "Could not fully initialize the chroot environment." ; return $OCF_ERR_INSTALLED; }
+    else
+	dhcpd_initialize ||
+	    { ocf_log err "Could not fully initialize the runtime environment." ; return $OCF_ERR_INSTALLED; }
+    fi
+
+    dhcpd_validate_all || exit
+
+    # Define an empty string variable, to ensure it exists when needed.
+    DHCPD_ARGS=""
+
+    # To ensure consistent behavior with the standard DHCPD init script, 
+    # use the chrooted default path for storing a leases file, when not in
+    # a chrooted enviroment.
+    if ocf_is_true $OCF_RESKEY_chrooted ; then
+	DHCPD_ARGS="$DHCPD_ARGS -chroot $OCF_RESKEY_chrooted_path -lf $OCF_RESKEY_leases"
+    else
+	DHCPD_ARGS="$DHCPD_ARGS -lf $OCF_RESKEY_chrooted_path/$OCF_RESKEY_leases"
+    fi
+
+    if [ -n "$OCF_RESKEY_user" ]; then
+	DHCPD_ARGS="$DHCPD_ARGS -user $OCF_RESKEY_user"
+    fi
+
+    if [ -n "$OCF_RESKEY_group" ]; then
+	DHCPD_ARGS="$DHCPD_ARGS -group $OCF_RESKEY_group"
+    fi
+
+    # If there is a pid file containing a pid, the machine might have crashed. pid files in
+    # /var/run are always cleaned up at boot time, but this is not the case for the pid file in
+    # the chroot jail. Therefore, an old pid file may exist. This is only a problem if it
+    # incidentally contains the pid of a running process. If this process is not a 'dhcpd',
+    # we remove the pid. (dhcpd itself only checks whether the pid is alive or not.)
+
+    PIDF="$OCF_RESKEY_chrooted_path/$OCF_RESKEY_pid"
+
+    if ocf_is_true $OCF_RESKEY_chrooted ; then
+	ocf_log info "Starting dhcpd [chroot] service."
+	DHCPD_ARGS="$DHCPD_ARGS -pf $OCF_RESKEY_pid"
+    else
+	ocf_log info "Starting dhcpd [non-chroot] service."
+	PIDF=`dirname $OCF_RESKEY_pid`/dhcpd/`basename $OCF_RESKEY_pid`
+	DHCPD_ARGS="$DHCPD_ARGS -pf $PIDF"
+    fi
+
+    test -e "$PIDF" && rm -f $PIDF
+
+    ocf_run $OCF_RESKEY_binary -cf $OCF_RESKEY_config $DHCPD_ARGS $OCF_RESKEY_interface ||
+	return $OCF_ERR_INSTALLED
+
+    while ! dhcpd_monitor; do
+		sleep .1
+		ocf_log info "waiting for dhcpd to start"
+		return $OCF_SUCCESS
+	done
+
+    if ocf_is_true $OCF_RESKEY_chrooted ; then
+	ocf_log info "dhcpd [chrooted] has started."
+    else
+	ocf_log info "dhcpd [non-chrooted] has started."
+    fi
+
+    return $OCF_SUCCESS
+}
+
+# Stop
+dhcpd_stop () {
+    local timeout
+    local timewait
+    local rc
+
+    dhcpd_monitor
+    rc=$?
+
+    case "$rc" in
+	"$OCF_SUCCESS")
+	    # Currently running, and is expected behaviour.
+	    ;;
+	"$OCF_NOT_RUNNING")
+	    # Currently not running, therefore nothing to do.
+		ocf_log info "dhcpd already stopped"
+	    return $OCF_SUCCESS
+	    ;;
+    esac
+
+    PIDF="$OCF_RESKEY_chrooted_path/$OCF_RESKEY_pid"
+
+    if ! ocf_is_true $OCF_RESKEY_chrooted ; then
+	PIDF=`dirname $OCF_RESKEY_pid`/dhcpd/`basename $OCF_RESKEY_pid`
+    fi
+
+    kill `cat $PIDF`
+
+    # Allow 2/3 of the action timeout for the orderly shutdown
+    # (The origin unit is ms, hence the conversion)
+    timewait=$((OCF_RESKEY_CRM_meta_timeout/1500))
+
+    sleep 0.1; timeout=0 # Sleep here for .1 sec to let dhcpd finish.
+    while dhcpd_monitor ; do
+        if [ $timeout -ge $timewait ]; then
+            break
+        else
+            sleep 1
+            timeout=`expr $timeout + 1`
+        fi
+    done
+
+    #If still up
+    if dhcpd_monitor 2>&1; then
+        ocf_log err "dhcpd is still up! Trying kill -s KILL"
+
+	kill -s SIGKILL `cat $PIDF`
+    fi
+
+    # If we are running a dhcp server v4 or higher, unmount the proc partition.
+    if [ $DHCP_VERSION_MAJOR -ge 4 ] ; then
+	# We only want to unmount proc in a chrooted environment, else we could
+	# cause other issues.
+	if ocf_is_true $OCF_RESKEY_chrooted ; then
+	    umount $OCF_RESKEY_chrooted_path/proc > /dev/null 2>&1
+	fi
+    fi
+
+    rm -f $PIDF
+
+    ocf_log info "dhcpd stopped"
+    return $OCF_SUCCESS
+}
+
+# Make sure meta-data and usage always succeed
+case $__OCF_ACTION in
+meta-data)      dhcpd_meta_data
+                exit $OCF_SUCCESS
+                ;;
+validate-all)   dhcpd_validate_all
+		exit $OCF_SUCCESS
+		;;
+usage|help)     dhcpd_usage
+                exit $OCF_SUCCESS
+                ;;
+esac
+
+# Translate each action into the appropriate function call
+case $__OCF_ACTION in
+start)          dhcpd_start;;
+stop)           dhcpd_stop;;
+monitor)        dhcpd_monitor;;
+*)              dhcpd_usage
+                exit $OCF_ERR_UNIMPLEMENTED
+                ;;
+esac
diff --git a/heartbeat/eDir88 b/heartbeat/eDir88
new file mode 100755
index 0000000..31b1a06
--- /dev/null
+++ b/heartbeat/eDir88
@@ -0,0 +1,460 @@
+#!/bin/bash
+#
+#      eDirectory Resource Agent (RA) for Heartbeat.
+#      This script is only compatible with eDirectory 8.8 and later
+#
+# Copyright (c) 2007 Novell Inc, Yan Fitterer
+#                    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.
+#
+#
+# OCF parameters:
+#  OCF_RESKEY_eDir_config_file      - full filename to instance configuration file
+#  OCF_RESKEY_eDir_monitor_ldap     - Should we monitor LDAP (0/1 - 1 is true)
+#  OCF_RESKEY_eDir_monitor_idm      - Should we monitor IDM (0/1 - 1 is true)
+#  OCF_RESKEY_eDir_jvm_initial_heap - Value of the DHOST_INITIAL_HEAP java env var
+#  OCF_RESKEY_eDir_jvm_max_heap     - Value of the DHOST_MAX_HEAP java env var
+#  OCF_RESKEY_eDir_jvm_options      - Value of the DHOST_OPTIONS java env var
+###############################################################################
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+test -f /opt/novell/eDirectory/bin/ndspath &&
+	. /opt/novell/eDirectory/bin/ndspath 2>/dev/null >/dev/null
+
+#######################################################################
+
+usage() {
+    ME=$(basename "$0")
+    cat <<-EOFA
+
+usage: $ME start|stop|status|monitor|validate-all
+
+$ME manages an eDirectory instance as an HA resource.
+
+The 'start' operation starts the instance.
+The 'stop' operation stops the instance.
+The 'status' operation reports if the instance is running.
+The 'monitor' operation reports if the instance is running, and runs additional checks.
+The 'validate-all' operation checks the validity of the arguments (environment variables).
+EOFA
+}
+
+eDir_meta_data() {
+cat <<-EOFB
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="eDir88" version="0.17">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for managing an eDirectory instance. Manages a single instance
+of eDirectory as an HA resource. The "multiple instances" feature or
+eDirectory has been added in version 8.8. This script will not work for any
+version of eDirectory prior to 8.8. This RA can be used to load multiple
+eDirectory instances on the same host.
+
+It is very strongly recommended to put eDir configuration files (as per the
+eDir_config_file parameter) on local storage on each node. This is necessary for
+this RA to be able to handle situations where the shared storage has become
+unavailable. If the eDir configuration file is not available, this RA will fail,
+and heartbeat will be unable to manage the resource. Side effects include
+STONITH actions, unmanageable resources, etc...
+
+Setting a high action timeout value is _very_ _strongly_ recommended. eDir
+with IDM can take in excess of 10 minutes to start. If heartbeat times out
+before eDir has had a chance to start properly, mayhem _WILL ENSUE_.
+
+The LDAP module seems to be one of the very last to start. So this script will
+take even longer to start on installations with IDM and LDAP if the monitoring
+of IDM and/or LDAP is enabled, as the start command will wait for IDM and LDAP
+to be available.
+</longdesc>
+<shortdesc lang="en">Manages a Novell eDirectory directory server</shortdesc>
+<parameters>
+<parameter name="eDir_config_file" unique="1" required="0">
+<longdesc lang="en">
+Path to configuration file for eDirectory instance.
+</longdesc>
+<shortdesc lang="en">eDir config file</shortdesc>
+<content type="string" default="/etc/opt/novell/eDirectory/conf/nds.conf" />
+</parameter>
+<parameter name="eDir_monitor_ldap" required="0">
+<longdesc lang="en">
+Should we monitor if LDAP is running for the eDirectory instance?
+</longdesc>
+<shortdesc lang="en">eDir monitor ldap</shortdesc>
+<content type="boolean" default="0" />
+</parameter>
+<parameter name="eDir_monitor_idm" required="0">
+<longdesc lang="en">
+Should we monitor if IDM is running for the eDirectory instance?
+</longdesc>
+<shortdesc lang="en">eDir monitor IDM</shortdesc>
+<content type="boolean" default="0" />
+</parameter>
+<parameter name="eDir_jvm_initial_heap" required="0">
+<longdesc lang="en">
+Value for the DHOST_INITIAL_HEAP java environment variable. If unset, java defaults will be used.
+</longdesc>
+<shortdesc lang="en">DHOST_INITIAL_HEAP value</shortdesc>
+<content type="integer" default="" />
+</parameter>
+<parameter name="eDir_jvm_max_heap" required="0">
+<longdesc lang="en">
+Value for the DHOST_MAX_HEAP java environment variable. If unset, java defaults will be used.
+</longdesc>
+<shortdesc lang="en">DHOST_MAX_HEAP value</shortdesc>
+<content type="integer" default="" />
+</parameter>
+<parameter name="eDir_jvm_options" required="0">
+<longdesc lang="en">
+Value for the DHOST_OPTIONS java environment variable. If unset, original values will be used.
+</longdesc>
+<shortdesc lang="en">DHOST_OPTIONS value</shortdesc>
+<content type="string" default="" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="600" />
+<action name="stop" timeout="600" />
+<action name="monitor" timeout="60" interval="30" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+</actions>
+</resource-agent>
+EOFB
+return $OCF_SUCCESS
+}
+
+#
+# eDir_start: Start eDirectory instance
+#
+
+eDir_start() {
+    if eDir_status ; then
+        ocf_log info "eDirectory is already running ($NDSCONF)."
+        return $OCF_SUCCESS
+    fi
+
+    # Start eDirectory instance
+    if [ -n "$OCF_RESKEY_eDir_jvm_initial_heap" ]; then
+        DHOST_JVM_INITIAL_HEAP=$OCF_RESKEY_eDir_jvm_initial_heap
+        export DHOST_JVM_INITIAL_HEAP
+    fi
+    if [ -n "$OCF_RESKEY_eDir_jvm_max_heap" ]; then
+        DHOST_JVM_MAX_HEAP=$OCF_RESKEY_eDir_jvm_max_heap
+        export DHOST_JVM_MAX_HEAP
+    fi
+    if [ -n "$OCF_RESKEY_eDir_jvm_options" ]; then
+        DHOST_JVM_OPTIONS=$OCF_RESKEY_eDir_jvm_options
+        export DHOST_JVM_OPTIONS
+    fi
+
+    $NDSMANAGE start --config-file "$NDSCONF" > /dev/null 2>&1
+    if [ $? -eq 0 ]; then
+        ocf_log info "eDir start command sent for $NDSCONF."
+    else
+        echo "ERROR: Can't start eDirectory for $NDSCONF."
+        return $OCF_ERR_GENERIC
+    fi
+
+    CNT=0
+    while ! eDir_monitor ; do
+        # Apparently, LDAP will only start after all other services
+        # Startup time can be in excess of 10 minutes.
+        # Leave a very long heartbeat timeout on the start action
+        # We're relying on heartbeat to bail us out...
+        let CNT=$CNT+1
+        ocf_log info "eDirectory start waiting for ${CNT}th retry for $NDSCONF."
+        sleep 10
+    done
+
+    ocf_log info "eDirectory start verified for $NDSCONF."
+
+    return $OCF_SUCCESS
+}
+
+#
+# eDir_stop: Stop eDirectory instance
+#            This action is written in such a way that even when run
+#            on a node were things are broken (no binaries, no config
+#            etc...) it will try to stop any running ndsd processes
+#            and report success if none are running.
+#
+
+eDir_stop() {
+    if ! eDir_status ; then
+        return $OCF_SUCCESS
+    fi
+
+    $NDSMANAGE stop --config-file "$NDSCONF" >/dev/null 2>&1
+    if eDir_status ; then
+            # eDir failed to stop.
+        ocf_log err "eDirectory instance failed to stop for $NDSCONF"
+        return $OCF_ERR_GENERIC
+    else
+        ocf_log info "eDirectory stop verified for $NDSCONF."
+        return $OCF_SUCCESS
+    fi
+}
+
+#
+# eDir_status: is eDirectory instance up ?
+#
+
+eDir_status() {
+    if [ ! -r "$NDSCONF" ] ; then
+        ocf_log err "Config file missing ($NDSCONF)."
+        exit $OCF_ERR_GENERIC
+    fi
+
+    # Find how many ndsd processes have open listening sockets
+    # with the IP of this eDir instance
+    IFACE=$(grep -i "n4u.server.interfaces" $NDSCONF | cut -f2 -d= | tr '@' ':')
+    if [ -z "$IFACE" ] ; then
+        ocf_log err "Cannot retrieve interfaces from $NDSCONF. eDirectory may not be correctly configured."
+        exit $OCF_ERR_GENERIC
+    fi
+
+    # In case of multiple IP's split into an array
+    # and check all of them
+    IFS=', ' read -a IFACE2 <<< "$IFACE"
+    ocf_log debug "Found ${#IFACE2[@]} interfaces from $NDSCONF."
+
+    counter=${#IFACE2[@]}
+
+    for IFACE in ${IFACE2[@]}
+    do
+        ocf_log debug "Checking ndsd instance for $IFACE"
+        NDSD_SOCKS=$(netstat -ntlp | grep -ce "$IFACE.*ndsd")
+
+	if [ "$NDSD_SOCKS" -eq 1 ] ; then
+	   let counter=counter-1
+	   ocf_log debug "Found ndsd instance for $IFACE"
+	elif [ "$NDSD_SOCKS" -gt 1 ] ; then
+            ocf_log err "More than 1 ndsd listening socket matched. Likely misconfiguration of eDirectory."
+            exit $OCF_ERR_GENERIC
+	fi
+    done
+
+    if [ $counter -eq 0 ] ; then
+        # Correct ndsd instance is definitely running
+        ocf_log debug "All ndsd instances found."
+        return 0;
+    elif [ $counter -lt ${#IFACE2[@]} ]; then
+        ocf_log err "Only some ndsd listening sockets matched, something is very wrong."
+        exit $OCF_ERR_GENERIC
+    fi
+
+    # No listening socket. Make sure we don't have the process running...
+    PIDDIR=$(grep -i "n4u.server.vardir" "$NDSCONF" | cut -f2 -d=)
+    if [ -z "$PIDDIR" ] ; then
+        ocf_log err "Cannot get vardir from nds config ($NDSCONF). Probable eDir configuration error."
+        exit $OCF_ERR_GENERIC
+    fi
+    NDSD_PID=$(cat $PIDDIR/ndsd.pid 2>/dev/null)
+    if [ -z "$NDSD_PID" ] ; then
+        # PID file unavailable or empty.
+        # This will happen if the PIDDIR is not available
+        # on this node at this time.
+        return 1
+    fi
+
+    RC=$(ps -p "$NDSD_PID" | grep -c ndsd)
+    if [ "$RC" -gt 0 ] ; then
+        # process found but no listening socket. ndsd likely not operational
+        ocf_log err "ndsd process found, but no listening socket. Something's gone wrong ($NDSCONF)"
+        exit $OCF_ERR_GENERIC
+    fi
+
+    ocf_log debug "ndsd instance is not running, but no other error detected."
+    return 1
+}
+
+
+#
+# eDir_monitor: Do more in-depth checks to ensure that eDirectory is fully functional
+#               LDAP and IDM checks are only done if reqested.
+#
+#
+
+eDir_monitor() {
+    if ! eDir_status ; then
+        ocf_log info "eDirectory instance is down ($NDSCONF)"
+        return $OCF_NOT_RUNNING
+    fi
+
+    # We know the right ndsd is running locally, check health
+    $NDSSTAT --config-file "$NDSCONF" >/dev/null 2>&1
+    if [ $? -ne 0 ] ; then
+        return 1
+    fi
+
+    # Monitor IDM first, as it will start before LDAP
+    if [ $MONITOR_IDM -eq 1 ]; then
+        RET=$($NDSTRACE --config-file "$NDSCONF" -c modules | egrep -i '^vrdim.*Running' | awk '{print $1}')
+        if [ "$RET" !=  "vrdim" ]; then
+            ocf_log err "eDirectory IDM engine isn't running ($NDSCONF)."
+            return $OCF_ERR_GENERIC
+        fi
+    fi
+    if [ $MONITOR_LDAP -eq 1 ] ; then
+        $NDSNLDAP -c --config-file "$NDSCONF" >/dev/null 2>&1
+        if [ $? -ne 0 ]; then
+            ocf_log err "eDirectory LDAP server isn't running ($NDSCONF)."
+            return $OCF_ERR_GENERIC
+        fi
+    fi
+
+    ocf_log debug "eDirectory monitor success ($NDSCONF)"
+    return $OCF_SUCCESS
+}
+
+#
+# eDir_validate: Validate environment
+#
+
+eDir_validate() {
+
+    declare rc=$OCF_SUCCESS
+
+    # Script must be run as root
+    if ! ocf_is_root ; then
+        ocf_log err "$0 must be run as root"
+        rc=$OCF_ERR_GENERIC
+    fi
+
+    # ndsmanage must be available and runnable
+    check_binary $NDSMANAGE
+
+    # ndsstat must be available and runnable
+    check_binary $NDSSTAT
+
+    # Config file must be readable
+    if [ ! -r "$NDSCONF" ] ; then
+        ocf_log err "eDirectory configuration file [$NDSCONF] is not readable"
+        rc=$OCF_ERR_ARGS
+    fi
+
+    # monitor_ldap must be unambiguously resolvable to a truth value
+    MONITOR_LDAP=$(echo "$MONITOR_LDAP" | tr [A-Z] [a-z])
+    case "$MONITOR_LDAP" in
+        yes|true|1)
+            MONITOR_LDAP=1;;
+        no|false|0)
+            MONITOR_LDAP=0;;
+        *)
+            ocf_log err "Configuration parameter eDir_monitor_ldap has invalid value [$MONITOR_LDAP]"
+            rc=$OCF_ERR_ARGS;;
+    esac
+
+    # monitor_idm must be unambiguously resolvable to a truth value
+    MONITOR_IDM=$(echo "$MONITOR_IDM" | tr [A-Z] [a-z])
+    case "$MONITOR_IDM" in
+        yes|true|1)
+            MONITOR_IDM=1;;
+        no|false|0)
+            MONITOR_IDM=0;;
+        *)
+            ocf_log err "Configuration parameter eDir_monitor_idm has invalid value [$MONITOR_IDM]"
+            rc=$OCF_ERR_ARGS;;
+    esac
+
+    # eDir_jvm_initial_heap must be blank or numeric
+    if [ -n "$OCF_RESKEY_eDir_jvm_initial_heap" ] ; then
+        if ! ocf_is_decimal "$OCF_RESKEY_eDir_jvm_initial_heap" ; then
+            ocf_log err "Configuration parameter eDir_jvm_initial_heap has invalid" \
+                        "value [$OCF_RESKEY_eDir_jvm_initial_heap]"
+            rc=$OCF_ERR_ARGS
+        fi
+    fi
+
+    # eDir_jvm_max_heap must be blank or numeric
+    if [ -n "$OCF_RESKEY_eDir_jvm_max_heap" ] ; then
+        if ! ocf_is_decimal "$OCF_RESKEY_eDir_jvm_max_heap" ; then
+            ocf_log err "Configuration parameter eDir_jvm_max_heap has invalid" \
+                         "value [$OCF_RESKEY_eDir_jvm_max_heap]"
+            rc=$OCF_ERR_ARGS
+        fi
+    fi
+    if [ $rc -ne $OCF_SUCCESS ] ; then
+        ocf_log err "Invalid environment"
+    fi
+    return $rc
+}
+
+#
+# Start of main logic
+#
+
+ocf_log debug "$0 started with arguments \"$@\""
+
+NDSBASE=/opt/novell/eDirectory
+NDSNLDAP=$NDSBASE/sbin/nldap
+NDSMANAGE=$NDSBASE/bin/ndsmanage
+NDSSTAT=$NDSBASE/bin/ndsstat
+NDSTRACE=$NDSBASE/bin/ndstrace
+NDSCONF=${OCF_RESKEY_eDir_config_file:-/etc/opt/novell/eDirectory/conf/nds.conf}
+MONITOR_LDAP=${OCF_RESKEY_eDir_monitor_ldap:-0}
+MONITOR_IDM=${OCF_RESKEY_eDir_monitor_idm:-0}
+
+
+# What kind of method was invoked?
+case "$1" in
+    validate-all) eDir_validate;   exit $?;;
+    meta-data)    eDir_meta_data;  exit $OCF_SUCCESS;;
+    status)       if eDir_status ; then
+                      ocf_log info "eDirectory instance is up ($NDSCONF)"
+                      exit $OCF_SUCCESS
+                  else
+                      ocf_log info "eDirectory instance is down ($NDSCONF)"
+                      exit $OCF_NOT_RUNNING
+                  fi;;
+    start)        : skip;;
+    stop)         : skip;;
+    monitor)      : skip;;
+    usage)        usage; exit $OCF_SUCCESS;;
+    *)            ocf_log err "Invalid argument [$1]"
+                  usage; exit $OCF_ERR_ARGS;;
+esac
+
+# From now on we must have a valid environment to continue.
+# stop goes in the list above as it should ideally be able to
+# clean up after a start that failed due to bad args
+
+eDir_validate
+RC=$?
+if [ $RC -ne $OCF_SUCCESS ]; then
+    exit $RC
+fi
+
+case "$1" in
+    start)      eDir_start;;
+    stop)       eDir_stop;;
+    monitor)    eDir_monitor;;
+esac
+
+exit $?
diff --git a/heartbeat/ethmonitor b/heartbeat/ethmonitor
new file mode 100755
index 0000000..b85d7fc
--- /dev/null
+++ b/heartbeat/ethmonitor
@@ -0,0 +1,454 @@
+#!/bin/sh
+#
+#       OCF Resource Agent compliant script.
+#       Monitor the vitality of a local network interface.
+#
+# 	Based on the work by Robert Euhus and Lars Marowsky-Br�e.
+#
+#	Transfered from Ipaddr2 into ethmonitor by Alexander Krauth
+#
+# Copyright (c) 2011 Robert Euhus, Alexander Krauth, Lars Marowsky-Br�e
+#                    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.
+#
+#     OCF parameters are as below
+#
+#	OCF_RESKEY_interface
+#	OCF_RESKEY_multiplicator
+#	OCF_RESKEY_name
+#       OCF_RESKEY_repeat_count
+#	OCF_RESKEY_repeat_interval
+#	OCF_RESKEY_pktcnt_timeout
+#	OCF_RESKEY_arping_count
+#	OCF_RESKEY_arping_timeout
+#	OCF_RESKEY_arping_cache_entries
+#
+#   TODO: Check against IPv6
+#
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="ethmonitor">
+<version>1.2</version>
+
+<longdesc lang="en">
+Monitor the vitality of a local network interface.
+
+You may set up this RA as a clone resource to monitor the network interfaces on different nodes, with the same interface name.
+This is not related to the IP address or the network on which a interface is configured.
+You may use this RA to move resources away from a node, which has a faulty interface or prevent moving resources to such a node.
+This gives you independend control of the resources, without involving cluster intercommunication. But it requires your nodes to have more than one network interface.
+
+The resource configuration requires a monitor operation, because the monitor does the main part of the work.
+In addition to the resource configuration, you need to configure some location constraints, based on a CIB attribute value.
+The name of the attribute value is configured in the 'name' option of this RA.
+
+Example constraint configuration:
+location loc_connected_node my_resource_grp \
+        rule $id="rule_loc_connected_node" -INF: ethmonitor eq 0
+
+The ethmonitor works in 3 different modes to test the interface vitality.
+1. call ip to see if the link status is up (if link is down -> error)
+2. call ip and watch the RX counter (if packages come around in a certain time -> success)
+3. call arping to check whether any of the IPs found in the local ARP cache answers an ARP REQUEST (one answer -> success)
+4. return error
+</longdesc>
+<shortdesc lang="en">Monitors network interfaces</shortdesc>
+
+<parameters>
+<parameter name="interface" unique="1" required="1">
+<longdesc lang="en">
+The name of the network interface which should be monitored (e.g. eth0).
+</longdesc>
+<shortdesc lang="en">Network interface name</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="name" unique="1">
+<longdesc lang="en">
+The name of the CIB attribute to set.  This is the name to be used in the constraints. Defaults to "ethmonitor-'interface_name'".
+</longdesc>
+<shortdesc lang="en">Attribute name</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="multiplier" unique="0" >
+<longdesc lang="en">
+Multiplier for the value of the CIB attriobute specified in parameter name. 
+</longdesc>
+<shortdesc lang="en">Multiplier for result variable</shortdesc>
+<content type="integer" default="1"/>
+</parameter>
+
+<parameter name="repeat_count">
+<longdesc lang="en">
+Specify how often the interface will be monitored, before the status is set to failed. You need to set the timeout of the monitoring operation to at least repeat_count * repeat_interval
+</longdesc>
+<shortdesc lang="en">Monitor repeat count</shortdesc>
+<content type="integer" default="5"/>
+</parameter>
+
+<parameter name="repeat_interval">
+<longdesc lang="en">
+Specify how long to wait in seconds between the repeat_counts.
+</longdesc>
+<shortdesc lang="en">Monitor repeat interval in seconds</shortdesc>
+<content type="integer" default="10"/>
+</parameter>
+
+<parameter name="pktcnt_timeout">
+<longdesc lang="en">
+Timeout for the RX packet counter. Stop listening for packet counter changes after the given number of seconds.
+</longdesc>
+<shortdesc lang="en">packet counter timeout</shortdesc>
+<content type="integer" default="5"/>
+</parameter>
+
+<parameter name="arping_count">
+<longdesc lang="en">
+Number of ARP REQUEST packets to send for every IP.
+Usually one ARP REQUEST (arping) is send
+</longdesc>
+<shortdesc lang="en">Number of arpings per IP</shortdesc>
+<content type="integer" default="1"/>
+</parameter>
+
+<parameter name="arping_timeout">
+<longdesc lang="en">
+Time in seconds to wait for ARP REQUESTs (all packets of arping_count).
+This is to limit the time for arp requests, to be able to send requests to more than one node, without running in the monitor operation timeout.
+</longdesc>
+<shortdesc lang="en">Timeout for arpings per IP</shortdesc>
+<content type="integer" default="1"/>
+</parameter>
+
+<parameter name="arping_cache_entries">
+<longdesc lang="en">
+Maximum number of IPs from ARP cache list to check for ARP REQUEST (arping) answers. Newest entries are tried first.
+</longdesc>
+<shortdesc lang="en">Number of ARP cache entries to try</shortdesc>
+<content type="integer" default="5"/>
+</parameter>
+
+</parameters>
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="status" depth="0"  timeout="20s" interval="10s" />
+<action name="monitor" depth="0"  timeout="20s" interval="10s" />
+<action name="meta-data"  timeout="5s" />
+<action name="validate-all"  timeout="20s" />
+</actions>
+</resource-agent>
+END
+
+	exit $OCF_SUCCESS
+}
+
+#
+#	Return true, if the interface exists
+#
+is_interface() {
+	#
+	# List interfaces but exclude FreeS/WAN ipsecN virtual interfaces
+	#
+	local iface=`$IP2UTIL -o -f inet addr show | grep " $1 " \
+		| cut -d ' ' -f2 | sort -u | grep -v '^ipsec[0-9][0-9]*$'`
+        [ "$iface" != "" ]
+}
+
+if_init() {
+	local rc
+
+	if [ X"$OCF_RESKEY_interface" = "X" ]; then
+		ocf_log err "Interface name (the interface parameter) is mandatory"
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	NIC="$OCF_RESKEY_interface"
+
+	if is_interface $NIC
+	then
+	  case "$NIC" in
+	    *:*) ocf_log err "Do not specify a virtual interface : $OCF_RESKEY_interface"
+	         exit $OCF_ERR_CONFIGURED;;
+	    *)  ;;
+	  esac
+	else
+	  case $__OCF_ACTION in
+	    validate-all) ocf_log err "Interface $NIC does not exist"
+                            exit $OCF_ERR_CONFIGURED;;
+	    *)   	    ocf_log warn "Interface $NIC does not exist"
+                            ## It might be a bond interface which is temporarily not available, therefore we want to continue here
+	                    ;;
+	  esac
+	fi
+
+	: ${OCF_RESKEY_multiplier:="1"}
+	if ! ocf_is_decimal "$OCF_RESKEY_multiplier"; then
+		ocf_log err "Invalid OCF_RESKEY_multiplier [$OCF_RESKEY_multiplier]"
+		exit $OCF_ERR_CONFIGURED
+	fi
+	
+	ATTRNAME=${OCF_RESKEY_name:-"ethmonitor-$NIC"}
+	
+        REP_COUNT=${OCF_RESKEY_repeat_count:-5}
+	if ! ocf_is_decimal "$REP_COUNT" -o [ $REP_COUNT -lt 1 ]; then
+		ocf_log err "Invalid OCF_RESKEY_repeat_count [$REP_COUNT]"
+		exit $OCF_ERR_CONFIGURED
+        fi
+	REP_INTERVAL_S=${OCF_RESKEY_repeat_interval:-10}
+	if ! ocf_is_decimal "$REP_INTERVAL_S"; then
+		ocf_log err "Invalid OCF_RESKEY_repeat_interval [$REP_INTERVAL_S]"
+		exit $OCF_ERR_CONFIGURED
+	fi
+	: ${OCF_RESKEY_pktcnt_timeout:="5"}
+	if ! ocf_is_decimal "$OCF_RESKEY_pktcnt_timeout"; then
+		ocf_log err "Invalid OCF_RESKEY_pktcnt_timeout [$OCF_RESKEY_pktcnt_timeout]"
+		exit $OCF_ERR_CONFIGURED
+	fi
+	: ${OCF_RESKEY_arping_count:="1"}
+	if ! ocf_is_decimal "$OCF_RESKEY_arping_count"; then
+		ocf_log err "Invalid OCF_RESKEY_arping_count [$OCF_RESKEY_arping_count]"
+		exit $OCF_ERR_CONFIGURED
+	fi
+	: ${OCF_RESKEY_arping_timeout:="1"}
+	if ! ocf_is_decimal "$OCF_RESKEY_arping_timeout"; then
+		ocf_log err "Invalid OCF_RESKEY_arping_timeout [$OCF_RESKEY_arping_count]"
+		exit $OCF_ERR_CONFIGURED
+	fi
+	: ${OCF_RESKEY_arping_cache_entries:="5"}
+	if ! ocf_is_decimal "$OCF_RESKEY_arping_cache_entries"; then
+		ocf_log err "Invalid OCF_RESKEY_arping_cache_entries [$OCF_RESKEY_arping_cache_entries]"
+		exit $OCF_ERR_CONFIGURED
+	fi
+  return $OCF_SUCCESS
+}
+
+# get the link status on $NIC
+# asks ip about running (up) interfaces, returns the number of matching interface names that are up
+get_link_status () {
+	$IP2UTIL -o link show up dev "$NIC" | grep -v 'NO-CARRIER' | grep -c "$NIC"
+}
+
+# returns the number of received rx packets on $NIC
+get_rx_packets () {
+	ocf_log debug "$IP2UTIL -o -s link show dev $NIC"
+	$IP2UTIL -o -s link show dev "$NIC" \
+		| sed 's/.* RX: [^0-9]*[0-9]* *\([0-9]*\) .*/\1/'
+		# the first number after RX: ist the # of bytes ,
+		# the second is the # of packets received
+}
+
+# watch for packet counter changes for max. OCF_RESKEY_pktcnt_timeout seconds
+# returns immedeately with return code 0 if any packets were received
+# otherwise 1 is returned
+watch_pkt_counter () {
+	local RX_PACKETS_NEW
+	local RX_PACKETS_OLD
+	RX_PACKETS_OLD="`get_rx_packets`"
+	for n in `seq $(( $OCF_RESKEY_pktcnt_timeout * 10 ))`; do
+		sleep 0.1
+		RX_PACKETS_NEW="`get_rx_packets`"
+		ocf_log debug "RX_PACKETS_OLD: $RX_PACKETS_OLD    RX_PACKETS_NEW: $RX_PACKETS_NEW"
+		if [ "$RX_PACKETS_OLD" -ne "$RX_PACKETS_NEW" ]; then
+			ocf_log debug "we received some packets."
+			return 0
+		fi
+	done
+	return 1
+}
+
+# returns list of cached ARP entries for $NIC
+# sorted by age ("last confirmed")
+# max. OCF_RESKEY_arping_cache_entries entries
+get_arp_list () {
+	$IP2UTIL -s neighbour show dev $NIC \
+		| sort -t/ -k2,2n | cut -d' ' -f1 \
+		| head -n $OCF_RESKEY_arping_cache_entries
+		# the "used" entries in `ip -s neighbour show` are:
+		# "last used"/"last confirmed"/"last updated"
+}
+
+# arping the IP given as argument $1 on $NIC
+# until OCF_RESKEY_arping_count answers are received
+do_arping () {
+	# TODO: add the source IP
+	# TODO: check for diffenrent arping versions out there
+	arping -q -c $OCF_RESKEY_arping_count -w $OCF_RESKEY_arping_timeout -I $NIC $1
+	# return with the exit code of the arping command 
+	return $?
+}
+
+#
+# 	Check the interface depending on the level given as parameter: $OCF_RESKEY_check_level
+#
+# 09: check for nonempty ARP cache
+# 10: watch for packet counter changes
+#
+# 19: check arping_ip_list
+# 20: check arping ARP cache entries
+# 
+# 30:  watch for packet counter changes in promiscios mode
+# 
+# If unsuccessfull in levels 18 and above,
+# the tests for higher check levels are run.
+#
+if_check () {
+	# always check link status first
+	link_status="`get_link_status`"
+	ocf_log debug "link_status: $link_status (1=up, 0=down)"
+        [ $link_status -eq 0 ] && return $OCF_NOT_RUNNING
+
+	# watch for packet counter changes
+	ocf_log debug "watch for packet counter changes" 
+	watch_pkt_counter && return $OCF_SUCCESS
+
+	# check arping ARP cache entries
+	ocf_log debug "check arping ARP cache entries" 
+	for ip in `get_arp_list`; do
+		do_arping $ip && return $OCF_SUCCESS
+	done
+
+	# watch for packet counter changes in promiscios mode
+#	ocf_log debug "watch for packet counter changes in promiscios mode" 
+	# be sure switch off promiscios mode in any case
+	# TODO: check first, wether promisc is already on and leave it untouched.
+#	trap "$IP2UTIL link set dev $NIC promisc off; exit" INT TERM EXIT
+#		$IP2UTIL link set dev $NIC promisc on
+#		watch_pkt_counter && return $OCF_SUCCESS
+#		$IP2UTIL link set dev $NIC promisc off
+#	trap - INT TERM EXIT
+
+	# looks like it's not working (for whatever reason)
+	return $OCF_NOT_RUNNING
+}
+
+#######################################################################
+
+if_usage() {
+	cat <<END
+usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+set_cib_value() {
+    local score=`expr $1 \* $OCF_RESKEY_multiplier`
+    attrd_updater -n $ATTRNAME -v $score -q
+    local rc=$?
+    case $rc in
+        0) ocf_log debug "attrd_updater: Updated $ATTRNAME = $score" ;;
+        *) ocf_log warn "attrd_updater: Could not update $ATTRNAME = $score: rc=$rc";;
+    esac
+    return $rc
+}
+
+if_monitor() {
+    ha_pseudo_resource $OCF_RESOURCE_INSTANCE monitor
+    local pseudo_status=$?
+    if [ $pseudo_status -ne $OCF_SUCCESS ]; then
+      exit $pseudo_status
+    fi
+    
+    local mon_rc=$OCF_NOT_RUNNING
+    local attr_rc=$OCF_NOT_RUNNING
+    local runs=0
+    local start_time
+    local end_time
+    local sleep_time
+    while [ $mon_rc -ne $OCF_SUCCESS -a $REP_COUNT -gt 0 ]
+    do
+      start_time=`date +%s%N`
+      if_check
+      mon_rc=$?
+      REP_COUNT=$(( $REP_COUNT - 1 ))
+      if [ $mon_rc -ne $OCF_SUCCESS -a $REP_COUNT -gt 0 ]; then
+        ocf_log warn "Monitoring of $OCF_RESOURCE_INSTANCE failed, $REP_COUNT retries left."
+	end_time=`date +%s%N`
+	sleep_time=`echo "scale=9; ( $start_time + ( $REP_INTERVAL_S * 1000000000 ) - $end_time ) / 1000000000" | bc -q 2> /dev/null`
+        sleep $sleep_time 2> /dev/null
+        runs=$(($runs + 1))
+      fi
+
+      if [ $mon_rc -eq $OCF_SUCCESS -a $runs -ne 0 ]; then
+        ocf_log info "Monitoring of $OCF_RESOURCE_INSTANCE recovered from error"
+      fi
+    done
+    
+    ocf_log debug "Monitoring return code: $mon_rc"
+    if [ $mon_rc -eq $OCF_SUCCESS ]; then
+      set_cib_value 1
+      attr_rc=$?
+    else
+      ocf_log err "Monitoring of $OCF_RESOURCE_INSTANCE failed."
+      set_cib_value 0
+      attr_rc=$?
+    fi
+
+    ## The resource should not fail, if the interface is down. It should fail, if the update of the CIB variable has errors.
+    ## To react on the interface failure you must use constraints based on the CIB variable value, not on the resource itself.
+    exit $attr_rc
+}
+
+if_validate() {
+    check_binary $IP2UTIL
+    check_binary arping
+    if_init
+}
+
+case $__OCF_ACTION in
+meta-data)	meta_data
+		;;
+usage|help)	if_usage
+		exit $OCF_SUCCESS
+		;;
+esac
+
+if_validate
+
+case $__OCF_ACTION in
+start)		ha_pseudo_resource $OCF_RESOURCE_INSTANCE start
+		exit $?
+		;;
+stop)		attrd_updater -D -n $ATTRNAME
+                ha_pseudo_resource $OCF_RESOURCE_INSTANCE stop
+		exit $?
+		;;
+monitor|status)	if_monitor
+		exit $?
+		;;
+validate-all)	exit $?
+                ;;
+*)		if_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
diff --git a/heartbeat/exportfs b/heartbeat/exportfs
new file mode 100755
index 0000000..0c6d092
--- /dev/null
+++ b/heartbeat/exportfs
@@ -0,0 +1,350 @@
+#!/bin/sh
+# exportfs
+#
+# Description: Manages nfs exported file system.
+#
+#   (c) 2010 Ben Timby, Florian Haas, Dejan Muhamedagic,
+#            and Linux-HA contributors
+#
+# License: GNU General Public License v2 (GPLv2) and later
+
+#######################################################################
+# Initialization:
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+OCF_RESKEY_unlock_on_stop_default=0
+OCF_RESKEY_wait_for_leasetime_on_stop_default=0
+OCF_RESKEY_rmtab_backup_default=".rmtab"
+
+: ${OCF_RESKEY_unlock_on_stop=${OCF_RESKEY_unlock_on_stop_default}}
+: ${OCF_RESKEY_wait_for_leasetime_on_stop=${OCF_RESKEY_wait_for_leasetime_on_stop_default}}
+: ${OCF_RESKEY_rmtab_backup=${OCF_RESKEY_rmtab_backup_default}}
+#######################################################################
+
+exportfs_meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="exportfs">
+<version>1.0</version>
+
+<longdesc lang="en">
+Exportfs uses the exportfs command to add/remove nfs exports.
+It does NOT manage the nfs server daemon.
+It depends on Linux specific NFS implementation details,
+so is considered not portable to other platforms yet.
+</longdesc>
+
+<shortdesc lang="en">
+Manages NFS exports
+</shortdesc>
+
+<parameters>
+
+<parameter name="clientspec" unique="0" required="1">
+<longdesc lang="en">
+The client specification allowing remote machines to mount the directory
+over NFS.
+</longdesc>
+<shortdesc lang="en">
+Client ACL.
+</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="options" unique="0" required="0">
+<longdesc lang="en">
+The options to pass to exportfs for the exported directory.
+</longdesc>
+<shortdesc lang="en">
+Export options.
+</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="directory" unique="0" required="1">
+<longdesc lang="en">
+The directory which you wish to export using NFS.
+</longdesc>
+<shortdesc lang="en">
+The directory to export.
+</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="fsid" unique="1" required="1">
+<longdesc lang="en">
+The fsid option to pass to exportfs. This can be a unique positive
+integer, a UUID, or the special string "root" which is functionally
+identical to numeric fsid of 0.
+0 (root) identifies the export as the root of an NFSv4
+pseudofilesystem -- avoid this setting unless you understand its
+special status.
+This value will override any fsid provided via the options parameter.
+</longdesc>
+<shortdesc lang="en">
+Unique fsid within cluster.
+</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="unlock_on_stop">
+<longdesc lang="en">
+Relinquish NFS locks associated with this filesystem when the resource
+stops. Enabling this parameter is highly recommended unless the path exported
+by this ${__SCRIPT_NAME} resource is also exported by a different resource.
+</longdesc>
+<shortdesc lang="en">
+Unlock filesystem on stop?
+</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_unlock_on_stop_default}" />
+</parameter>
+
+<parameter name="wait_for_leasetime_on_stop">
+<longdesc lang="en">
+When stopping (unexporting), wait out the NFSv4 lease time.
+Only after all leases have expired does the NFS kernel server
+relinquish all server-side handles on the exported filesystem.
+If this ${__SCRIPT_NAME} resource manages an export that resides
+on a mount point designed to fail over along with the NFS export
+itself, then enabling this parameter will ensure such failover
+is working properly. Note that when this parameter is set, your
+stop timeout MUST accommodate for the wait period. This parameter
+is safe to disable if none of your NFS clients are using NFS
+version 4 or later.
+</longdesc>
+<shortdesc lang="en">
+Ride out the NFSv4 lease time on resource stop?
+</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_wait_for_leasetime_on_stop_default}" />
+</parameter>
+
+<parameter name="rmtab_backup">
+<longdesc lang="en">
+Back up those entries from the NFS rmtab that apply to the exported
+directory, to the specified backup file. The filename is interpreted
+as relative to the exported directory. This backup is required if
+clients are connecting to the export via NFSv3 over TCP. Note that a
+configured monitor operation is required for this functionality.
+
+To disable rmtab backups, set this parameter to the special
+string "none".
+</longdesc>
+<shortdesc lang="en">
+Location of the rmtab backup, relative to directory.
+</shortdesc>
+<content type="string" default="${OCF_RESKEY_rmtab_backup_default}" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start"   timeout="40" />
+<action name="stop"    timeout="10" />
+<action name="monitor" depth="0"  timeout="20" interval="10" />
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="30" />
+</actions>
+</resource-agent>
+END
+
+return $OCF_SUCCESS
+}
+
+exportfs_methods() {
+  cat <<-!
+	start
+	stop
+	status
+	monitor
+	validate-all
+	methods
+	meta-data
+	usage
+	!
+}
+
+backup_rmtab() {
+	local rmtab_backup
+	if [ ${OCF_RESKEY_rmtab_backup} != "none" ]; then
+		rmtab_backup="${OCF_RESKEY_directory}/${OCF_RESKEY_rmtab_backup}"
+		grep ":${OCF_RESKEY_directory}:" /var/lib/nfs/rmtab > ${rmtab_backup}
+	fi
+}
+
+restore_rmtab() {
+	local rmtab_backup
+	if [ ${OCF_RESKEY_rmtab_backup} != "none" ]; then
+	rmtab_backup="${OCF_RESKEY_directory}/${OCF_RESKEY_rmtab_backup}"
+	if [ -r ${rmtab_backup} ]; then
+		local tmpf=`mktemp`
+		sort -u ${rmtab_backup} /var/lib/nfs/rmtab > $tmpf &&
+		install -o root -m 644 $tmpf /var/lib/nfs/rmtab
+		rm -f $tmpf
+		ocf_log debug "Restored `wc -l ${rmtab_backup}` rmtab entries from ${rmtab_backup}."
+	else
+		ocf_log warn "rmtab backup ${rmtab_backup} not found or not readable."
+	fi
+	fi
+}
+
+exportfs_usage() {
+	cat <<END
+		usage: $0 {start|stop|monitor|status|validate-all|meta-data}
+END
+}
+
+is_exported() {
+	local dir=$1
+	local spec=$2
+	exportfs |
+		sed -e '$! N; s/\n[[:space:]]\+/ /; t; s/[[:space:]]\+\([^[:space:]]\+\)\(\n\|$\)/ \1\2/g; P;D;' |
+		grep -q -x -F "$dir $spec"
+}
+
+exportfs_monitor ()
+{
+	local rc
+	# exportfs output wraps lines for long export directory names.
+	# We unwrap here with sed.
+	# We then do a literal match on the full line (grep -x -F)
+	is_exported "${OCF_RESKEY_directory}" "${OCF_RESKEY_clientspec}"
+	rc=$?
+
+	# on some platforms, exportfs may print "<world>" instead of
+	# "*"
+	if [ $rc -eq 1 -a "${OCF_RESKEY_clientspec}" = "*" ]; then
+		is_exported "${OCF_RESKEY_directory}" "<world>"
+		rc=$?
+	fi
+
+#Adapt grep status code to OCF return code
+	case $rc in
+	0)
+		ocf_log info "Directory ${OCF_RESKEY_directory} is exported to ${OCF_RESKEY_clientspec} (started)."
+		# Backup the rmtab to ensure smooth NFS-over-TCP failover
+		backup_rmtab
+		return $OCF_SUCCESS
+		;;
+	1)
+		ocf_log info "Directory ${OCF_RESKEY_directory} is not exported to ${OCF_RESKEY_clientspec} (stopped)."
+		return $OCF_NOT_RUNNING;;
+	*)
+		ocf_log err "Unable to determine export status for ${OCF_RESKEY_directory}."
+		return $OCF_ERR_GENERIC;;
+	esac
+}
+
+exportfs_start ()
+{
+	if exportfs_monitor; then
+		ocf_log debug "${OCF_RESKEY_directory} already exported"
+		return $OCF_SUCCESS
+	fi
+		
+	ocf_log info "Exporting file system ..."
+
+	if [ ${OCF_RESKEY_options} ]; then
+		OPTIONS="${OCF_RESKEY_options}"
+		OPTPREFIX=','
+	fi
+	if [ `echo ${OPTIONS} | grep fsid` ]; then
+		#replace fsid provided in options list with one provided in fsid param.
+		OPTIONS=`echo ${OPTIONS} | sed "s/fsid=[0-9]\+/fsid=${OCF_RESKEY_fsid}/g"`
+	else
+		#tack the fsid option onto our options list.
+		OPTIONS="${OPTIONS}${OPTPREFIX}fsid=${OCF_RESKEY_fsid}"
+	fi
+	OPTIONS="-o ${OPTIONS}"
+
+	ocf_run exportfs -v ${OPTIONS} ${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory} || exit $OCF_ERR_GENERIC
+
+	# Restore the rmtab to ensure smooth NFS-over-TCP failover
+	restore_rmtab
+
+	ocf_log info "File system exported"
+	return $OCF_SUCCESS
+}
+
+unlock_fs() {
+	local unlockfile
+	unlockfile=/proc/fs/nfsd/unlock_filesystem
+	if [ -w ${unlockfile} ]; then
+		echo "${OCF_RESKEY_directory}" > ${unlockfile}
+		ocf_log info "Unlocked NFS export ${OCF_RESKEY_directory}"
+	else
+		ocf_log warn "Unable to unlock NFS export ${OCF_RESKEY_directory}, ${unlockfile} not found or not writable"
+	fi
+}
+wait_for_leasetime() {
+	local leasetimefile
+	local sleeptime
+	leasetimefile=/proc/fs/nfsd/nfsv4leasetime
+	if [ -r ${leasetimefile} ]; then
+		sleeptime=$((`cat ${leasetimefile}`+2))
+		ocf_log info "Sleeping ${sleeptime} seconds to accommodate for NFSv4 lease expiry"
+		sleep ${sleeptime}s
+	else
+		ocf_log warn "Unable to read NFSv4 lease time from ${leasetimefile}, file not found or not readable"
+	fi
+}
+cleanup_export_cache() {
+	# see if the cache is blocking unexport
+	local contentfile=/proc/net/rpc/nfsd.export/content
+	local fsid_re="fsid=$OCF_RESKEY_fsid,"
+	local i=1
+	while :; do
+		fgrep -q "$fsid_re" $contentfile ||
+			break
+		ocf_log info "Cleanup export cache ... (try $i)"
+		ocf_run exportfs -f
+		sleep 0.5
+		let i=$i+1
+	done
+}
+exportfs_stop ()
+{
+	exportfs_monitor
+	if [ $? -eq $OCF_NOT_RUNNING ]; then
+		ocf_log debug "${OCF_RESKEY_directory} not exported"
+		return $OCF_SUCCESS
+	fi
+
+	ocf_log info "Un-exporting file system ..."
+
+	# Backup the rmtab to ensure smooth NFS-over-TCP failover
+	backup_rmtab
+
+	ocf_run exportfs -v -u ${OCF_RESKEY_clientspec}:${OCF_RESKEY_directory}
+	rc=$?
+
+	if ocf_is_true ${OCF_RESKEY_unlock_on_stop}; then
+		unlock_fs
+	fi
+
+	if ocf_is_true ${OCF_RESKEY_wait_for_leasetime_on_stop}; then
+		wait_for_leasetime
+	fi
+
+	if [ $rc -eq 0 ]; then
+		cleanup_export_cache
+		ocf_log info "Un-exported file system"
+		return $OCF_SUCCESS
+	else
+		ocf_log err "Failed to un-export file system"
+		exit $OCF_ERR_GENERIC
+	fi
+}
+
+exportfs_validate_all ()
+{
+	if [ ! -d $OCF_RESKEY_directory ]; then
+		ocf_log err "$OCF_RESKEY_directory does not exist or is not a directory"
+		return $OCF_ERR_INSTALLED
+	fi
+}
+
+OCF_REQUIRED_PARAMS="directory fsid clientspec"
+OCF_REQUIRED_BINARIES="exportfs"
+ocf_rarun $*
diff --git a/heartbeat/findif.sh b/heartbeat/findif.sh
new file mode 100644
index 0000000..fd92d9b
--- /dev/null
+++ b/heartbeat/findif.sh
@@ -0,0 +1,180 @@
+#!/bin/sh
+ipcheck_ipv4() {
+  local r1_to_255="([1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"
+  local r0_to_255="([0-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"
+  local r_ipv4="^$r1_to_255\.$r0_to_255\.$r0_to_255\.$r0_to_255$"
+  echo "$1" | grep -q -Ee "$r_ipv4"
+}
+ipcheck_ipv6() {
+  ! echo "$1" | grep -qs "[^0-9:a-fA-F]"
+}
+ifcheck() {
+  local ifname="$1"
+  $IP2UTIL link show dev $ifname 2>&1 >/dev/null
+}
+prefixcheck() {
+  local prefix=$1
+  local prefix_length=${#prefix}
+  local prefix_check=$2
+
+  if [ $prefix_length -gt 3 -o $prefix_length -eq 0 ] ; then
+    return 1
+  fi
+  echo "$prefix" | grep -qs "[^0-9]"
+  if [ $? = 0 ] ; then
+    return 1
+  fi
+  if [ $prefix -lt 1 -o $prefix -gt $prefix_check ] ; then
+    return 1
+  fi
+  return 0
+}
+getnetworkinfo()
+{
+  local line netinfo
+  ip -o -f inet route list match $OCF_RESKEY_ip table local scope host | (while read line;
+  do
+    netinfo=`echo $line | awk '{print $2}'`
+    case $netinfo in
+    */*)
+      set -- $line
+      break
+      ;;
+    esac
+  done
+  echo $line)
+}
+
+findif_check_params()
+{
+  local family="$1"
+  local match="$OCF_RESKEY_ip"
+  local nic="$OCF_RESKEY_nic"
+  local netmask="$OCF_RESKEY_cidr_netmask"
+  local brdcast="$OCF_RESKEY_broadcast"
+  local errmsg
+
+  # Do a sanity check only on start and validate-all
+  # to avoid returning OCF_ERR_CONFIGURED from the monitor operation.
+  case $__OCF_ACTION in
+      start|validate-all)	true;;
+      *)			return $OCF_SUCCESS;;
+  esac
+
+  if [ -n "$nic" ] ; then
+    errmsg=`ifcheck $nic`
+    if [ $? -ne 0 ] ; then
+      ocf_log err "Invalid interface name [$nic]: $errmsg"
+      return $OCF_ERR_CONFIGURED
+    fi
+  fi
+
+  if [ "$family" = "inet6" ] ; then
+    ipcheck_ipv6 $match
+    if [ $? = 1 ] ; then
+      ocf_log err "IP address [$match] not valid."
+      return $OCF_ERR_CONFIGURED
+    fi
+    if [ -z "$nic" ] ; then
+      echo $match | grep -qis '^fe80::'
+      if [ $? = 0 ] ; then
+        ocf_log err "'nic' parameter is mandatory for a link local address [$match]."
+        return $OCF_ERR_CONFIGURED
+      fi
+    fi
+    if [ -n "$netmask" ] ; then
+      prefixcheck $netmask 128
+      if [ $? = 1 ] ; then
+        ocf_log err "Invalid netmask specification [$netmask]."
+        return $OCF_ERR_CONFIGURED
+      fi
+    fi
+  else
+    # family = inet
+    ipcheck_ipv4 $match
+    if [ $? = 1 ] ; then
+      ocf_log err "IP address [$match] not valid."
+      return $OCF_ERR_CONFIGURED
+    fi
+    if [ -n "$netmask" ] ; then
+      prefixcheck $netmask 32
+      if [ $? = 1 ] ; then
+        ocf_log err "Invalid netmask specification [$netmask]."
+        return $OCF_ERR_CONFIGURED
+      fi
+    fi
+    if [ -n "$brdcast" ] ; then
+      ipcheck_ipv4 $brdcast
+      if [ $? = 1 ] ; then
+        ocf_log err "Invalid broadcast address [$brdcast]."
+        return $OCF_ERR_CONFIGURED
+      fi
+    fi
+  fi
+  return $OCF_SUCCESS
+}
+
+findif()
+{
+  local match="$OCF_RESKEY_ip"
+  local family
+  local scope
+  local nic="$OCF_RESKEY_nic"
+  local netmask="$OCF_RESKEY_cidr_netmask"
+  local brdcast="$OCF_RESKEY_broadcast"
+
+  echo $match | grep -qs ":"
+  if [ $? = 0 ] ; then
+    family="inet6"
+  else
+    family="inet"
+    scope="scope link"
+  fi
+  findif_check_params $family || return $?
+
+  if [ -n "$netmask" ] ; then
+      match=$match/$netmask
+  fi
+  if [ -n "$nic" ] ; then
+    # NIC supports more than two.
+    set -- `ip -o -f $family route list match $match $scope | grep "dev $nic"`
+  else
+    set -- `ip -o -f $family route list match $match $scope`
+  fi
+  if [ $# = 0 ] ; then
+    case $OCF_RESKEY_ip in
+    127.*)
+      set -- `getnetworkinfo`
+      shift;;
+    esac
+  fi
+  if [ -z "$nic" -o -z "$netmask" ] ; then
+    if [ $# = 0 ] ; then
+      ocf_log err "Unable to find nic or netmask."
+      return $OCF_ERR_GENERIC
+    fi
+    case $1 in
+    */*) : OK ;;
+    *)
+      ocf_log err "Unable to find cidr_netmask."
+      return $OCF_ERR_GENERIC ;;
+    esac
+  fi
+  [ -z "$nic" ] && nic=$3
+  [ -z "$netmask" ] && netmask=${1#*/}
+  if [ $family = "inet" ] ; then
+    if [ -z "$brdcast" ] ; then
+      if [ -n "$7" ] ; then
+        set -- `ip -o -f $family addr show | grep $7`
+        [ "$5" = brd ] && brdcast=$6
+      fi
+    fi
+  else
+    if [ -z "$OCF_RESKEY_nic" -a "$netmask" != "${1#*/}" ] ; then
+      ocf_log err "Unable to find nic, or netmask mismatch."
+      return $OCF_ERR_GENERIC
+    fi
+  fi
+  echo "$nic netmask $netmask broadcast $brdcast"
+  return $OCF_SUCCESS
+}
diff --git a/heartbeat/fio b/heartbeat/fio
new file mode 100755
index 0000000..6d2371f
--- /dev/null
+++ b/heartbeat/fio
@@ -0,0 +1,172 @@
+#!/bin/bash
+#
+#	fio RA
+#
+# Copyright (c) 2010 SUSE Linux Products GmbH, Lars Marowsky-Brée
+#                    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.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="fio" version="0.9">
+<version>1.0</version>
+
+<longdesc lang="en">
+fio is a generic I/O load generator. This RA allows start/stop of fio
+instances to simulate load on a cluster without configuring complex
+services.
+</longdesc>
+<shortdesc lang="en">fio IO load generator</shortdesc>
+
+<parameters>
+<parameter name="args">
+<longdesc lang="en">
+Arguments to the fio client. Minimally, this should be a (list of) job
+descriptions to run.
+</longdesc>
+<shortdesc lang="en">fio arguments</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="60" />
+<action name="stop"         timeout="60" />
+<action name="monitor"      timeout="60" interval="10" />
+<action name="meta-data"    timeout="5" />
+<action name="validate-all"   timeout="20" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+fio_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+END
+}
+
+fio_start() {
+	fio_monitor ; rc=$?
+	if [ $rc = $OCF_SUCCESS ]; then
+		ocf_log info "fio already running."
+		exit $OCF_SUCCESS
+	fi
+	if [ $rc != $OCF_NOT_RUNNING ]; then
+		ocf_log info "fio apparently dead; cleaning up before restart"
+		fio_stop
+	fi
+	fio $OCF_RESKEY_args >/dev/null 2>&1 </dev/null &
+	fio_pid=`jobs -p`
+	echo $fio_pid >${fio_state_file}
+	ocf_log info "fio started as pid=$fio_pid"
+	exit $OCF_SUCCESS
+}
+
+fio_stop() {
+	for sig in SIGINT SIGTERM SIGKILL ; do
+		fio_monitor ; rc=$?
+		case $rc in
+		$OCF_NOT_RUNNING)
+			ocf_log info "fio already stopped."
+			exit $OCF_SUCCESS
+			;;
+		$OCF_ERR_GENERIC)
+			rm $fio_state_file
+			ocf_log info "fio stopped and cleaned up."
+			exit $OCF_SUCCESS
+			;;
+		$OCF_SUCCESS)
+			if [ -n "$fio_pid" ]; then
+				ocf_log info "Sending $sig to fio (pid=$fio_pid)"
+				kill -$sig $fio_pid
+				sleep 3
+				continue
+			fi
+			ocf_log err "Internal logic failure in fio RA."
+			;;
+		*)	ocf_log err "Internal logic failure in fio RA."
+			;;
+		esac
+	done
+	ocf_log err "fio did not stop! Perhaps hung on IO?"
+	exit $OCF_ERR_GENERIC
+}
+
+fio_monitor() {
+	fio_state_file="${HA_RSCTMP}/fio-${OCF_RESOURCE_INSTANCE}.state"
+	if [ ! -e $fio_state_file ]; then
+		return $OCF_NOT_RUNNING
+	fi
+	fio_pid=`cat $fio_state_file`
+	
+	if [ -z "$fio_pid" ]; then
+		ocf_log err "State file found, but empty. Assuming stopped."
+		return $OCF_NOT_RUNNING
+	fi
+
+	ps=`ps h -o comm $fio_pid 2>&1`
+	if [ "$ps" != "fio" ]; then
+		fio_pid=""
+		return $OCF_ERR_GENERIC
+	fi
+	return $OCF_SUCCESS
+}
+
+fio_validate() {
+	return $OCF_SUCCESS
+}
+
+case $__OCF_ACTION in
+	meta-data)	meta_data
+			exit $OCF_SUCCESS
+			;;
+	validate-all)	fio_validate;;
+	usage|help)	fio_usage
+			exit $OCF_SUCCESS
+			;;
+esac
+
+ocf_is_probe || check_binary fio
+
+case $__OCF_ACTION in
+	start)		fio_start;;
+	stop)		fio_stop;;
+	monitor)	fio_monitor;;
+	*)		fio_usage
+			exit $OCF_ERR_UNIMPLEMENTED
+			;;
+esac
+
diff --git a/heartbeat/http-mon.sh b/heartbeat/http-mon.sh
new file mode 100644
index 0000000..46a4820
--- /dev/null
+++ b/heartbeat/http-mon.sh
@@ -0,0 +1,140 @@
+#
+# General http monitor code
+# (sourced by apache and httpmon)
+#
+# Author:	Alan Robertson
+#		Sun Jiang Dong
+#
+# Support:	linux-ha at lists.linux-ha.org
+#
+# License:	GNU General Public License (GPL)
+#
+# Copyright:	(C) 2002-2005 International Business Machines
+#
+
+# default options for http clients
+# NB: We _always_ test a local resource, so it should be
+# safe to connect from the local interface.
+bind_address="127.0.0.1"
+curl_ipv6_opts=""
+if ocf_is_true "$OCF_RESKEY_use_ipv6" || echo "$STATUSURL" | grep -qs "::"; then
+	bind_address="::1"
+	curl_ipv6_opts="-g"
+fi
+WGETOPTS="-O- -q -L --no-proxy --bind-address=$bind_address"
+CURLOPTS="-o - -Ss -L --interface lo $curl_ipv6_opts"
+
+request_url_header() {
+	which curl >/dev/null 2>&1
+	if [ $? -eq 0 ]; then
+		curl -IL --connect-timeout 5 --interface lo $curl_ipv6_opts "$1" > /dev/null 2>&1
+		return $?
+	fi
+
+	which wget >/dev/null 2>&1
+	if [ $? -eq 0 ]; then
+		local header=$(wget --server-response --spider --timeout=5 --tries=2 "$1" 2>&1)
+		if [ $? -eq 0 ]; then
+			return $OCF_SUCCESS
+		fi
+
+		# a 4xx error is still a server response.
+		echo "$header" | grep "HTTP/1.1 4.. " > /dev/null 2>&1
+		return $?
+	fi
+	return $OCF_ERR_GENERIC
+}
+
+#
+# run the http client
+#
+curl_func() {
+	cl_opts="$CURLOPTS $test_httpclient_opts"
+	if [ x != "x$test_user" ]; then
+		echo "-u $test_user:$test_password" |
+			curl -K - $cl_opts "$1"
+	else
+		curl $cl_opts "$1"
+	fi
+}
+wget_func() {
+	auth=""
+	cl_opts="$WGETOPTS $test_httpclient_opts"
+	[ x != "x$test_user" ] &&
+		auth="--http-user=$test_user --http-passwd=$test_password"
+	wget $auth $cl_opts "$1"
+}
+#
+# rely on whatever the user provided
+userdefined() {
+	$test_httpclient $test_httpclient_opts "$1"
+}
+
+#
+# find a good http client
+#
+findhttpclient() {
+	# prefer wget (for historical reasons)
+	if [ "x$CLIENT" != x ] && which "$CLIENT" >/dev/null 2>&1; then
+		echo "$CLIENT"
+	elif which wget >/dev/null 2>&1; then
+		echo "wget"
+	elif which curl >/dev/null 2>&1; then
+		echo "curl"
+	else
+		return 1
+	fi
+}
+gethttpclient() {
+	[ -z "$test_httpclient" ] &&
+		test_httpclient=$ourhttpclient
+	case "$test_httpclient" in
+		curl|wget) echo ${test_httpclient}_func;;  #these are supported
+		*) echo userdefined;;
+	esac
+}
+
+# test configuration good?
+is_testconf_sane() {
+	if [ "x$test_regex" = x -o "x$test_url" = x ]; then
+		ocf_log err "test regular expression or test url empty"
+		return 1
+	fi
+	if [ "x$test_user$test_password" != x -a \( "x$test_user" = x -o "x$test_password" = x \) ]; then
+		ocf_log err "bad user authentication for extended test"
+		return 1
+	fi
+	return 0
+}
+#
+# read the test definition from the config
+#
+readtestconf() {
+	test_name="$1" # we look for this one or the first one if empty
+	lcnt=0
+	readdef=""
+	test_url="" test_regex=""
+	test_user="" test_password=""
+	test_httpclient="" test_httpclient_opts=""
+
+	while read key value; do
+		lcnt=$((lcnt+1))
+		if [ "$readdef" ]; then
+			case "$key" in
+			"url") test_url="$value" ;;
+			"user") test_user="$value" ;;
+			"password") test_password="$value" ;;
+			"client") test_httpclient="$value" ;;
+			"client_opts") test_httpclient_opts="$value" ;;
+			"match") test_regex="$value" ;;
+			"end") break ;;
+			"#"*|"") ;;
+			*) ocf_log err "$lcnt: $key: unknown keyword"; return 1 ;;
+			esac
+		else
+			[ "$key" = "test" ] &&
+				[ -z "$test_name" -o "$test_name" = "$value" ] &&
+				readdef=1
+		fi
+	done
+}
diff --git a/heartbeat/iSCSILogicalUnit b/heartbeat/iSCSILogicalUnit
new file mode 100755
index 0000000..0ab4722
--- /dev/null
+++ b/heartbeat/iSCSILogicalUnit
@@ -0,0 +1,580 @@
+#!/bin/bash
+#
+#
+#   iSCSILogicalUnit OCF RA. Exports and manages iSCSI Logical Units.
+#
+#   (c) 2013	LINBIT, Lars Ellenberg
+#   (c) 2009-2010 Florian Haas, Dejan Muhamedagic,
+#                 and Linux-HA contributors
+#				  
+#
+# 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.
+#
+
+#######################################################################
+# Initialization:
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+# Set a default implementation based on software installed
+if have_binary ietadm; then
+    OCF_RESKEY_implementation_default="iet"
+elif have_binary tgtadm; then
+    OCF_RESKEY_implementation_default="tgt"
+elif have_binary lio_node; then
+    OCF_RESKEY_implementation_default="lio"
+fi
+: ${OCF_RESKEY_implementation=${OCF_RESKEY_implementation_default}}
+
+# Use a default SCSI ID and SCSI SN that is unique across the cluster,
+# and persistent in the event of resource migration.
+# SCSI IDs are limited to 24 bytes, but only 16 bytes are known to be
+# supported by all iSCSI implementations this RA cares about. Thus,
+# for a default, use the first 16 characters of
+# $OCF_RESOURCE_INSTANCE.
+OCF_RESKEY_scsi_id_default="${OCF_RESOURCE_INSTANCE:0:16}"
+: ${OCF_RESKEY_scsi_id=${OCF_RESKEY_scsi_id_default}}
+# To have a reasonably unique default SCSI SN, use the first 8 bytes
+# of an MD5 hash of of $OCF_RESOURCE_INSTANCE
+sn=`echo -n "${OCF_RESOURCE_INSTANCE}" | openssl md5 | sed -e 's/(stdin)= //'`
+OCF_RESKEY_scsi_sn_default=${sn:0:8}
+: ${OCF_RESKEY_scsi_sn=${OCF_RESKEY_scsi_sn_default}}
+# set 0 as a default value for lio iblock device number
+OCF_RESKEY_lio_iblock_default=0
+OCF_RESKEY_lio_iblock=${OCF_RESKEY_lio_iblock:-$OCF_RESKEY_lio_iblock_default}
+
+## tgt specifics
+# tgt has "backing store type" and "backing store open flags",
+# as well as device-type.
+#
+# suggestions how to make this generic accross all supported implementations?
+# how should they be named, how should they be mapped to implementation specifics?
+#
+# OCF_RESKEY_tgt_bstype
+# OCF_RESKEY_tgt_bsoflags
+# OCF_RESKEY_tgt_device_type
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="iSCSILogicalUnit" version="0.9">
+<version>0.9</version>
+
+<longdesc lang="en">
+Manages iSCSI Logical Unit. An iSCSI Logical unit is a subdivision of 
+an SCSI Target, exported via a daemon that speaks the iSCSI protocol.
+</longdesc>
+<shortdesc lang="en">Manages iSCSI Logical Units (LUs)</shortdesc>
+
+<parameters>
+<parameter name="implementation" required="0" unique="0">
+<longdesc lang="en">
+The iSCSI target daemon implementation. Must be one of "iet", "tgt",
+or "lio".  If unspecified, an implementation is selected based on the
+availability of management utilities, with "iet" being tried first,
+then "tgt", then "lio".
+</longdesc>
+<shortdesc lang="en">iSCSI target daemon implementation</shortdesc>
+<content type="string" default="${OCF_RESKEY_implementation_default}"/>
+</parameter>
+
+<parameter name="target_iqn" required="1" unique="0">
+<longdesc lang="en">
+The iSCSI Qualified Name (IQN) that this Logical Unit belongs to.
+</longdesc>
+<shortdesc lang="en">iSCSI target IQN</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="lun" required="1" unique="0">
+<longdesc lang="en">
+The Logical Unit number (LUN) exposed to initiators.
+</longdesc>
+<shortdesc lang="en">Logical Unit number (LUN)</shortdesc>
+<content type="integer" />
+</parameter>
+
+<parameter name="path" required="1" unique="0">
+<longdesc lang="en">
+The path to the block device exposed. Some implementations allow this
+to be a regular file, too.
+</longdesc>
+<shortdesc lang="en">Block device (or file) path</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="scsi_id" required="0" unique="1">
+<longdesc lang="en">
+The SCSI ID to be configured for this Logical Unit. The default
+is the resource name, truncated to 24 bytes.
+</longdesc>
+<shortdesc lang="en">SCSI ID</shortdesc>
+<content type="string" default="${OCF_RESKEY_scsi_id_default}"/>
+</parameter>
+
+<parameter name="scsi_sn" required="0" unique="1">
+<longdesc lang="en">
+The SCSI serial number to be configured for this Logical Unit.
+The default is a hash of the resource name, truncated to 8 bytes.
+</longdesc>
+<shortdesc lang="en">SCSI serial number</shortdesc>
+<content type="string" default="${OCF_RESKEY_scsi_sn_default}"/>
+</parameter>
+
+<parameter name="vendor_id" required="0" unique="0">
+<longdesc lang="en">
+The SCSI vendor ID to be configured for this Logical Unit.
+</longdesc>
+<shortdesc lang="en">SCSI vendor ID</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="product_id" required="0" unique="0">
+<longdesc lang="en">
+The SCSI product ID to be configured for this Logical Unit.
+</longdesc>
+<shortdesc lang="en">SCSI product ID</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="tgt_bstype" required="0" unique="0">
+<longdesc lang="en">
+TGT specific backing store type. If you want to use aio,
+make sure your tgtadm is built against libaio.
+See tgtadm(8).
+</longdesc>
+<shortdesc lang="en">TGT backing store type</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="tgt_bsoflags" required="0" unique="0">
+<longdesc lang="en">
+TGT specific backing store open flags (direct|sync).
+See tgtadm(8).
+</longdesc>
+<shortdesc lang="en">TGT backing store open flags</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="tgt_device_type" required="0" unique="0">
+<longdesc lang="en">
+TGT specific device type.
+See tgtadm(8).
+</longdesc>
+<shortdesc lang="en">TGT device type</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="additional_parameters" required="0" unique="0">
+<longdesc lang="en">
+Additional LU parameters. A space-separated list of "name=value" pairs
+which will be passed through to the iSCSI daemon's management
+interface. The supported parameters are implementation
+dependent. Neither the name nor the value may contain whitespace.
+</longdesc>
+<shortdesc lang="en">List of iSCSI LU parameters</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="allowed_initiators" required="0" unique="0">
+<longdesc lang="en">
+Allowed initiators. A space-separated list of initiators allowed to
+connect to this lun. Initiators may be listed in any syntax
+the target implementation allows. If this parameter is empty or
+not set, access to this lun will not be allowed from any initiator,
+if target is not in demo mode.
+
+This parameter is only necessary when using LIO.
+</longdesc>
+<shortdesc lang="en">List of iSCSI initiators allowed to connect
+to this lun.</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="lio_iblock" required="0" unique="0">
+<longdesc lang="en">
+LIO iblock device name, a number starting from 0.
+
+Using distinct values here avoids a warning in LIO "LEGACY: SHARED HBA";
+and it is necessary when using multiple LUNs started at the same time
+(eg. on node failover) to prevent a race condition in tcm_core on mkdir()
+in /sys/kernel/config/target/core/.
+</longdesc>
+<shortdesc lang="en">LIO iblock device number</shortdesc>
+<content type="integer" default="0"/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="10" />
+<action name="stop"         timeout="10" />
+<action name="status"       timeout="10" interval="10" depth="0" />
+<action name="monitor"      timeout="10" interval="10" depth="0" />
+<action name="meta-data"    timeout="5" />
+<action name="validate-all"   timeout="10" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+iSCSILogicalUnit_usage() {
+	cat <<END
+usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+iSCSILogicalUnit_start() {
+    iSCSILogicalUnit_monitor
+    if [ $? =  $OCF_SUCCESS ]; then
+	return $OCF_SUCCESS
+    fi
+
+    local params
+
+    case $OCF_RESKEY_implementation in
+	iet)
+	    params="Path=${OCF_RESKEY_path}"
+	    # use blockio if path points to a block device, fileio
+	    # otherwise.
+	    if [ -b "${OCF_RESKEY_path}" ]; then
+		params="${params} Type=blockio"
+	    else
+		params="${params} Type=fileio"
+	    fi
+	    # in IET, we have to set LU parameters on creation
+	    if [ -n "${OCF_RESKEY_scsi_id}" ]; then
+		params="${params} ScsiId=${OCF_RESKEY_scsi_id}"
+	    fi
+	    if [ -n "${OCF_RESKEY_scsi_sn}" ]; then
+		params="${params} ScsiSN=${OCF_RESKEY_scsi_sn}"
+	    fi
+	    params="${params} ${OCF_RESKEY_additional_parameters}"
+	    ocf_run ietadm --op new \
+		--tid=${TID} \
+		--lun=${OCF_RESKEY_lun} \
+		--params ${params// /,} || exit $OCF_ERR_GENERIC
+	    ;;
+	tgt)
+	    # tgt requires that we create the LU first, then set LU
+	    # parameters
+	    params=""
+	    local var
+            local envar
+	    for var in scsi_id scsi_sn vendor_id product_id; do
+		envar="OCF_RESKEY_${var}"
+		if [ -n "${!envar}" ]; then
+		    params="${params} ${var}=${!envar}"
+		fi
+	    done
+	    params="${params} ${OCF_RESKEY_additional_parameters}"
+
+	    # cleanup: tgt (as of tgtadm version 1.0.24) does not like an explicit "bsoflags=direct"
+	    # when used with "bstype=aio" (which always uses O_DIRECT)
+	    [[ $OCF_RESKEY_tgt_bstype/$OCF_RESKEY_tgt_bsoflags = "aio/direct" ]] && OCF_RESKEY_tgt_bsoflags=""
+
+	    tgt_args=""
+	    [[ $OCF_RESKEY_tgt_bstype ]]	&& tgt_args="$tgt_args --bstype=$OCF_RESKEY_tgt_bstype"
+	    [[ $OCF_RESKEY_tgt_bsoflags ]]	&& tgt_args="$tgt_args --bsoflags=$OCF_RESKEY_tgt_bsoflags"
+	    [[ $OCF_RESKEY_tgt_device_type ]]	&& tgt_args="$tgt_args --device-type=$OCF_RESKEY_tgt_device_type"
+
+	    ocf_run tgtadm --lld iscsi --op new --mode logicalunit \
+		--tid=${TID} \
+		--lun=${OCF_RESKEY_lun} \
+		$tgt_args \
+	    	--backing-store ${OCF_RESKEY_path} || exit $OCF_ERR_GENERIC
+	    if [ -z "$params" ]; then
+		return $OCF_SUCCESS
+	    else
+		ocf_run tgtadm --lld iscsi --op update --mode logicalunit \
+		    --tid=${TID} \
+		    --lun=${OCF_RESKEY_lun} \
+		    --params ${params// /,} || exit $OCF_ERR_GENERIC
+	    fi
+	    ;;
+	lio)
+	    # For lio, we first have to create a target device, then
+	    # add it to the Target Portal Group as an LU.
+	    ocf_run tcm_node --createdev=iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESOURCE_INSTANCE} \
+		${OCF_RESKEY_path} || exit $OCF_ERR_GENERIC
+	    if [ -n "${OCF_RESKEY_scsi_sn}" ]; then
+		ocf_run tcm_node --setunitserial=iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESOURCE_INSTANCE} \
+		    ${OCF_RESKEY_scsi_sn} || exit $OCF_ERR_GENERIC
+	    fi
+	    ocf_run lio_node --addlun=${OCF_RESKEY_target_iqn} 1 ${OCF_RESKEY_lun} \
+		${OCF_RESOURCE_INSTANCE} iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESOURCE_INSTANCE} || exit $OCF_ERR_GENERIC
+
+           if [ -n "${OCF_RESKEY_allowed_initiators}" ]; then
+               for initiator in ${OCF_RESKEY_allowed_initiators}; do
+                       ocf_run lio_node --addlunacl=${OCF_RESKEY_target_iqn} 1 \
+                       ${initiator} ${OCF_RESKEY_lun} ${OCF_RESKEY_lun} || exit $OCF_ERR_GENERIC
+               done
+           fi
+	    ;;
+    esac
+
+    return $OCF_SUCCESS
+}
+
+iSCSILogicalUnit_stop() {
+    iSCSILogicalUnit_monitor
+    if [ $? =  $OCF_SUCCESS ]; then
+	case $OCF_RESKEY_implementation in
+	    iet)
+		# IET allows us to remove LUs while they are in use
+		ocf_run ietadm --op delete \
+		    --tid=${TID} \
+		    --lun=${OCF_RESKEY_lun} || exit $OCF_ERR_GENERIC
+		;;
+	    tgt)
+		# tgt will fail to remove an LU while it is in use,
+		# but at the same time does not allow us to
+		# selectively shut down a connection that is using a
+		# specific LU. Thus, we need to loop here until tgtd
+		# decides that the LU is no longer in use, or we get
+		# timed out by the LRM.
+		while ! ocf_run -warn tgtadm --lld iscsi --op delete --mode logicalunit \
+		    --tid ${TID} \
+		    --lun=${OCF_RESKEY_lun}; do
+		    sleep 1
+		done
+		;;
+	    lio)
+               if [ -n "${OCF_RESKEY_allowed_initiators}" ]; then
+                       for initiator in ${OCF_RESKEY_allowed_initiators}; do
+                               ocf_run lio_node --dellunacl=${OCF_RESKEY_target_iqn} 1 \
+                               ${initiator} ${OCF_RESKEY_lun} || exit $OCF_ERR_GENERIC
+                       done
+               fi
+		ocf_run lio_node --dellun=${OCF_RESKEY_target_iqn} 1 ${OCF_RESKEY_lun} || exit $OCF_ERR_GENERIC
+		ocf_run tcm_node --freedev=iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESOURCE_INSTANCE} || exit $OCF_ERR_GENERIC
+	esac
+    fi
+    
+    return $OCF_SUCCESS
+}
+
+iSCSILogicalUnit_monitor() {
+    case $OCF_RESKEY_implementation in
+	iet)
+ 	    # Figure out and set the target ID
+	    TID=`sed -ne "s/tid:\([[:digit:]]\+\) name:${OCF_RESKEY_target_iqn}$/\1/p" < /proc/net/iet/volume`
+	    if [ -z "${TID}" ]; then
+		# Our target is not configured, thus we're not
+		# running.
+		return $OCF_NOT_RUNNING
+	    fi
+	    # FIXME: this looks for a matching LUN and path, but does
+	    # not actually test for the correct target ID.
+	    grep -E -q "[[:space:]]+lun:${OCF_RESKEY_lun}.*path:${OCF_RESKEY_path}$" /proc/net/iet/volume && return $OCF_SUCCESS
+	    ;;
+	tgt)
+	    # Figure out and set the target ID
+	    TID=`tgtadm --lld iscsi --op show --mode target \
+		| sed -ne "s/^Target \([[:digit:]]\+\): ${OCF_RESKEY_target_iqn}$/\1/p"`
+	    if [ -z "$TID" ]; then
+		# Our target is not configured, thus we're not
+		# running.
+		return $OCF_NOT_RUNNING
+	    fi
+	    # This only looks for the backing store, but does not test
+	    # for the correct target ID and LUN.
+	    tgtadm --lld iscsi --op show --mode target \
+		| grep -E -q "[[:space:]]+Backing store.*: ${OCF_RESKEY_path}$" && return $OCF_SUCCESS
+	    ;;
+	lio)
+	    configfs_path="/sys/kernel/config/target/iscsi/${OCF_RESKEY_target_iqn}/tpgt_1/lun/lun_${OCF_RESKEY_lun}/${OCF_RESOURCE_INSTANCE}/udev_path"
+	    [ -e ${configfs_path} ] && [ `cat ${configfs_path}` = "${OCF_RESKEY_path}" ] && return $OCF_SUCCESS
+	    ;;
+    esac
+    
+    return $OCF_NOT_RUNNING
+}
+
+iSCSILogicalUnit_validate() {
+    # Do we have all required variables?
+    for var in target_iqn lun path; do
+	param="OCF_RESKEY_${var}"
+	if [ -z "${!param}" ]; then
+	    ocf_log error "Missing resource parameter \"$var\"!"
+	    exit $OCF_ERR_CONFIGURED
+	fi
+    done
+
+    # Is the configured implementation supported?
+    case "$OCF_RESKEY_implementation" in
+	"iet"|"tgt"|"lio")
+	    ;;
+	"")
+	    # The user didn't specify an implementation, and we were
+	    # unable to determine one from installed binaries (in
+	    # other words: no binaries for any supported
+	    # implementation could be found)
+	    ocf_log error "Undefined iSCSI target implementation"
+	    exit $OCF_ERR_INSTALLED
+	    ;;
+	*)
+	    ocf_log error "Unsupported iSCSI target implementation \"$OCF_RESKEY_implementation\"!"
+	    exit $OCF_ERR_CONFIGURED
+	    ;;
+    esac
+
+    # Do we have a valid LUN?
+    case $OCF_RESKEY_implementation in
+	iet)
+	    # IET allows LUN 0 and up
+	    [ $OCF_RESKEY_lun -ge 0 ]
+	    case $? in
+		0)
+	            # OK
+		    ;;
+		1)
+		    ocf_log err "Invalid LUN $OCF_RESKEY_lun (must be a non-negative integer)."
+		    exit $OCF_ERR_CONFIGURED
+		    ;;
+		*)
+		    ocf_log err "Invalid LUN $OCF_RESKEY_lun (must be an integer)."
+		    exit $OCF_ERR_CONFIGURED
+		    ;;
+	    esac
+	    ;;
+	tgt)
+	    # tgt reserves LUN 0 for its own purposes
+	    [ $OCF_RESKEY_lun -ge 1 ]
+	    case $? in
+		0)
+	            # OK
+		    ;;
+		1)
+		    ocf_log err "Invalid LUN $OCF_RESKEY_lun (must be greater than 0)."
+		    exit $OCF_ERR_CONFIGURED
+		    ;;
+		*)
+		    ocf_log err "Invalid LUN $OCF_RESKEY_lun (must be an integer)."
+		    exit $OCF_ERR_CONFIGURED
+		    ;;
+	    esac
+	    ;;
+    esac
+
+    # Do we have any configuration parameters that the current
+    # implementation does not support?
+    local unsupported_params
+    local var
+    local envar
+    case $OCF_RESKEY_implementation in
+	iet)
+	    # IET does not support setting the vendor and product ID
+	    # (it always uses "IET" and "VIRTUAL-DISK")
+	    unsupported_params="vendor_id product_id allowed_initiators lio_iblock tgt_bstype tgt_bsoflags tgt_device_type"
+	    ;;
+	tgt)
+	    unsupported_params="allowed_initiators lio_iblock"
+	    ;;
+	lio)
+	    unsupported_params="scsi_id vendor_id product_id tgt_bstype tgt_bsoflags tgt_device_type"
+	    ;;
+    esac
+    for var in ${unsupported_params}; do
+	envar=OCF_RESKEY_${var}
+	defvar=OCF_RESKEY_${var}_default
+	if [ -n "${!envar}" ]; then
+	    if  [[ "${!envar}" != "${!defvar}" ]];then 
+	        case "$__OCF_ACTION" in
+                    start|validate-all)
+                      ocf_log warn "Configuration parameter \"${var}\"" \
+                       "is not supported by the iSCSI implementation" \
+                       "and will be ignored." ;;
+	        esac
+	    fi
+	fi
+    done
+
+    if ! ocf_is_probe; then
+    # Do we have all required binaries?
+	case $OCF_RESKEY_implementation in
+	    iet)
+		check_binary ietadm
+		;;
+	    tgt)
+		check_binary tgtadm
+		;;
+	    lio)
+		check_binary tcm_node
+		check_binary lio_node
+		;;
+	esac
+
+        # Is the required kernel functionality available?
+	case $OCF_RESKEY_implementation in
+	    iet)
+		[ -d /proc/net/iet ]
+		if [ $? -ne 0 ]; then
+		    ocf_log err "/proc/net/iet does not exist or is not a directory -- check if required modules are loaded."
+		    exit $OCF_ERR_INSTALLED
+		fi
+		;;
+	    tgt)
+	        # tgt is userland only
+		;;
+	esac
+    fi
+
+    return $OCF_SUCCESS
+}
+
+
+case $1 in
+  meta-data)
+	meta_data
+	exit $OCF_SUCCESS
+	;;
+  usage|help)
+	iSCSILogicalUnit_usage
+	exit $OCF_SUCCESS
+	;;
+esac
+
+# Everything except usage and meta-data must pass the validate test
+iSCSILogicalUnit_validate
+
+case $__OCF_ACTION in
+start)		iSCSILogicalUnit_start;;
+stop)		iSCSILogicalUnit_stop;;
+monitor|status)	iSCSILogicalUnit_monitor;;
+reload)		ocf_log err "Reloading..."
+	        iSCSILogicalUnit_start
+		;;
+validate-all)	;;
+*)		iSCSILogicalUnit_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
diff --git a/heartbeat/iSCSITarget b/heartbeat/iSCSITarget
new file mode 100755
index 0000000..a988fb2
--- /dev/null
+++ b/heartbeat/iSCSITarget
@@ -0,0 +1,597 @@
+#!/bin/bash
+#
+#
+# 	iSCSITarget OCF RA. Exports and manages iSCSI targets.
+#
+#   (c) 2009-2010 Florian Haas, Dejan Muhamedagic,
+#                 and Linux-HA contributors
+#
+# 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.
+#
+
+#######################################################################
+# Initialization:
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+# Set a default implementation based on software installed
+if have_binary ietadm; then
+    OCF_RESKEY_implementation_default="iet"
+elif have_binary tgtadm; then
+    OCF_RESKEY_implementation_default="tgt"
+elif have_binary lio_node; then
+    OCF_RESKEY_implementation_default="lio"
+fi
+: ${OCF_RESKEY_implementation=${OCF_RESKEY_implementation_default}}
+
+# Listen on 0.0.0.0:3260 by default
+OCF_RESKEY_portals_default="0.0.0.0:3260"
+: ${OCF_RESKEY_portals=${OCF_RESKEY_portals_default}}
+
+# Lockfile, used for selecting a target ID
+LOCKFILE=${HA_RSCTMP}/iSCSITarget-${OCF_RESKEY_implementation}.lock
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="iSCSITarget" version="0.9">
+<version>0.9</version>
+
+<longdesc lang="en">
+Manages iSCSI targets. An iSCSI target is a collection of SCSI Logical
+Units (LUs) exported via a daemon that speaks the iSCSI protocol.
+</longdesc>
+<shortdesc lang="en">iSCSI target export agent</shortdesc>
+
+<parameters>
+<parameter name="implementation" required="0" unique="0">
+<longdesc lang="en">
+The iSCSI target daemon implementation. Must be one of "iet", "tgt",
+or "lio".  If unspecified, an implementation is selected based on the
+availability of management utilities, with "iet" being tried first,
+then "tgt", then "lio".
+</longdesc>
+<shortdesc lang="en">Specifies the iSCSI target implementation
+("iet", "tgt" or "lio").</shortdesc>
+<content type="string" default="${OCF_RESKEY_implementation_default}"/>
+</parameter>
+
+<parameter name="iqn" required="1" unique="1">
+<longdesc lang="en">
+The target iSCSI Qualified Name (IQN). Should follow the conventional
+"iqn.yyyy-mm.<reversed domain name>[:identifier]" syntax.
+</longdesc>
+<shortdesc lang="en">iSCSI target IQN</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="tid" required="0" unique="1">
+<longdesc lang="en">
+The iSCSI target ID. Required for tgt.
+</longdesc>
+<shortdesc lang="en">iSCSI target ID</shortdesc>
+<content type="integer" />
+</parameter>
+
+<parameter name="portals" required="0" unique="0">
+<longdesc lang="en">
+iSCSI network portal addresses. Not supported by all
+implementations. If unset, the default is to create one portal that
+listens on ${OCF_RESKEY_portal_default}.
+</longdesc>
+<shortdesc lang="en">iSCSI portal addresses</shortdesc>
+<content type="string" default="${OCF_RESKEY_portals_default}"/>
+</parameter>
+
+<parameter name="allowed_initiators" required="0" unique="0">
+<longdesc lang="en">
+Allowed initiators. A space-separated list of initiators allowed to
+connect to this target. Initiators may be listed in any syntax
+the target implementation allows. If this parameter is empty or
+not set, access to this target will be allowed from any initiator.
+</longdesc>
+<shortdesc lang="en">List of iSCSI initiators allowed to connect
+to this target</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="incoming_username" required="0" unique="1">
+<longdesc lang="en">
+A username used for incoming initiator authentication. If unspecified,
+allowed initiators will be able to log in without authentication.
+This is a unique parameter, as it not allowed to re-use a single
+username across multiple target instances.
+</longdesc>
+<shortdesc lang="en">Incoming account username</shortdesc>
+<content type="string"/>
+</parameter>
+
+<parameter name="incoming_password" required="0" unique="0">
+<longdesc lang="en">
+A password used for incoming initiator authentication.
+</longdesc>
+<shortdesc lang="en">Incoming account password</shortdesc>
+<content type="string"/>
+</parameter>
+
+<parameter name="additional_parameters" required="0" unique="0">
+<longdesc lang="en">
+Additional target parameters. A space-separated list of "name=value"
+pairs which will be passed through to the iSCSI daemon's management
+interface. The supported parameters are implementation
+dependent. Neither the name nor the value may contain whitespace.
+</longdesc>
+<shortdesc lang="en">List of iSCSI target parameters</shortdesc>
+<content type="string" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="10" />
+<action name="stop"         timeout="10" />
+<action name="status"       timeout="10" interval="10" depth="0" />
+<action name="monitor"      timeout="10" interval="10" depth="0" />
+<action name="meta-data"    timeout="5" />
+<action name="validate-all"   timeout="10" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+iSCSITarget_usage() {
+	cat <<END
+usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+iSCSITarget_start() {
+    iSCSITarget_monitor
+    if [ $? =  $OCF_SUCCESS ]; then
+	return $OCF_SUCCESS
+    fi
+
+    local param
+    local name
+    local value
+    local initiator
+    local portal
+
+    case $OCF_RESKEY_implementation in
+	iet)
+	    local lasttid
+	    local tid
+	    if [ "${OCF_RESKEY_tid}" ]; then
+		tid="${OCF_RESKEY_tid}"
+	    else
+    	        # Figure out the last used target ID, add 1 to get the new
+	        # target ID.
+		ocf_take_lock $LOCKFILE
+		ocf_release_lock_on_exit $LOCKFILE
+		lasttid=`sed -ne "s/tid:\([[:digit:]]\+\) name:.*/\1/p" < /proc/net/iet/volume | sort -n | tail -n1`
+		[ -z "${lasttid}" ] && lasttid=0
+		tid=$((++lasttid))
+	    fi
+	    # Create the target.
+	    ocf_run ietadm --op new \
+		--tid=${tid} \
+		--params Name=${OCF_RESKEY_iqn} || exit $OCF_ERR_GENERIC
+	    # Set additional parameters.
+	    for param in ${OCF_RESKEY_additional_parameters}; do
+		name=${param%=*}
+		value=${param#*=}
+		ocf_run ietadm --op update \
+		    --tid=${tid} \
+		    --params ${name}=${value} || exit $OCF_ERR_GENERIC
+	    done
+	    # Legacy versions of IET allow targets by default, current
+	    # versions deny. To be safe we manage both the .allow and
+	    # .deny files.
+	    if [ -n "${OCF_RESKEY_allowed_initiators}" ]; then
+		echo "${OCF_RESKEY_iqn} ALL" >> /etc/initiators.deny
+		echo "${OCF_RESKEY_iqn} ${OCF_RESKEY_allowed_initiators// /,}" >> /etc/initiators.allow
+	    else
+		echo "${OCF_RESKEY_iqn} ALL" >> /etc/initiators.allow
+	    fi
+	    # In iet, adding a new user and assigning it to a target
+	    # is one operation.
+	    if [ -n "${OCF_RESKEY_incoming_username}" ]; then
+		ocf_run ietadm --op new --user \
+		    --tid=${tid} \
+		    --params=IncomingUser=${OCF_RESKEY_incoming_username},Password=${OCF_RESKEY_incoming_password} \
+		    || exit $OCF_ERR_GENERIC
+	    fi
+	    ;;
+	tgt)
+	    local tid
+	    tid="${OCF_RESKEY_tid}"
+	    # Create the target.
+	    ocf_run tgtadm --lld iscsi --op new --mode target \
+		--tid=${tid} \
+		--targetname ${OCF_RESKEY_iqn} || exit $OCF_ERR_GENERIC
+	    # Set parameters.
+	    for param in ${OCF_RESKEY_additional_parameters}; do
+		name=${param%=*}
+		value=${param#*=}
+		ocf_run tgtadm --lld iscsi --op update --mode target \
+		    --tid=${tid} \
+		    --name=${name} --value=${value} || exit $OCF_ERR_GENERIC
+	    done
+	    # For tgt, we always have to add access per initiator;
+	    # access to targets is denied by default. If
+	    # "allowed_initiators" is unset, we must use the special
+	    # keyword ALL.
+	    for initiator in ${OCF_RESKEY_allowed_initiators=ALL}; do
+		ocf_run tgtadm --lld iscsi --op bind --mode target \
+		    --tid=${tid} \
+		    --initiator-address=${initiator} || exit $OCF_ERR_GENERIC
+	    done
+	    # In tgt, we must first create a user account, then assign
+	    # it to a target using the "bind" operation.
+	    if [ -n "${OCF_RESKEY_incoming_username}" ]; then
+		ocf_run tgtadm --lld iscsi --mode account --op new \
+		    --user=${OCF_RESKEY_incoming_username} \
+		    --password=${OCF_RESKEY_incoming_password} || exit $OCF_ERR_GENERIC
+		ocf_run tgtadm --lld iscsi --mode account --op bind \
+		    --tid=${tid} \
+		    --user=${OCF_RESKEY_incoming_username} || exit $OCF_ERR_GENERIC
+	    fi
+	    ;;
+	lio)
+	    # lio distinguishes between targets and target portal
+	    # groups (TPGs). We will always create one TPG, with the
+	    # number 1. In lio, creating a network portal
+	    # automatically creates the corresponding target if it
+	    # doesn't already exist.
+	    for portal in ${OCF_RESKEY_portals}; do
+		ocf_run lio_node --addnp ${OCF_RESKEY_iqn} 1 \
+		    ${portal} || exit $OCF_ERR_GENERIC
+	    done
+	    # in lio, we can set target parameters by manipulating
+	    # the appropriate configfs entries
+	    for param in ${OCF_RESKEY_additional_parameters}; do
+		name=${param%=*}
+		value=${param#*=}
+		configfs_path="/sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_1/param/${name}"
+		if [ -e ${configfs_path} ]; then
+		    echo ${value} > ${configfs_path} || exit $OCF_ERR_GENERIC
+		else
+		    ocf_log warn "Unsupported iSCSI target parameter ${name}: will be ignored."
+		fi
+	    done
+	    # lio does per-initiator filtering by default. To disable
+	    # this, we need to switch the target to "permissive mode".
+	    if [ -n "${OCF_RESKEY_allowed_initiators}" ]; then
+		for initiator in ${OCF_RESKEY_allowed_initiators}; do
+		    ocf_run lio_node --addnodeacl ${OCF_RESKEY_iqn} 1 \
+			${initiator} || exit $OCF_ERR_GENERIC
+		done
+	    else
+		ocf_run lio_node --permissive ${OCF_RESKEY_iqn} 1 || exit $OCF_ERR_GENERIC
+		# permissive mode enables read-only access by default,
+		# so we need to change that to RW to be in line with
+		# the other implementations.
+		echo 0 > "/sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_1/attrib/demo_mode_write_protect"
+		if [ `cat /sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_1/attrib/demo_mode_write_protect` -ne 0 ]; then
+		    ocf_log err "Failed to disable write protection for target ${OCF_RESKEY_iqn}."
+		    exit $OCF_ERR_GENERIC
+		fi
+	    fi
+	    # TODO: add CHAP authentication support when it gets added
+	    # back into LIO
+	    ocf_run lio_node --disableauth ${OCF_RESKEY_iqn} 1 || exit $OCF_ERR_GENERIC
+	    # Finally, we need to enable the target to allow
+	    # initiators to connect
+	    ocf_run lio_node --enabletpg=${OCF_RESKEY_iqn} 1 || exit $OCF_ERR_GENERIC
+	    ;;
+    esac
+
+    return $OCF_SUCCESS
+}
+
+iSCSITarget_stop() {
+    iSCSITarget_monitor
+    if [ $? =  $OCF_SUCCESS ]; then
+	local tid
+	case $OCF_RESKEY_implementation in
+	    iet)
+		# Figure out the target ID
+		tid=`sed -ne "s/tid:\([[:digit:]]\+\) name:${OCF_RESKEY_iqn}/\1/p" < /proc/net/iet/volume`
+		if [ -z "${tid}" ]; then
+		    ocf_log err "Failed to retrieve target ID for IQN ${OCF_RESKEY_iqn}"
+		    exit $OCF_ERR_GENERIC
+		fi
+		# Close existing connections. There is no other way to
+		# do this in IET than to parse the contents of
+		# /proc/net/iet/session.
+		set -- $(sed -ne '/^tid:'${tid}' /,/^tid/ {
+                          /^[[:space:]]*sid:\([0-9]\+\)/ {
+                             s/^[[:space:]]*sid:\([0-9]*\).*/--sid=\1/; h;
+                          };
+                          /^[[:space:]]*cid:\([0-9]\+\)/ { 
+                              s/^[[:space:]]*cid:\([0-9]*\).*/--cid=\1/; G; p; 
+                          }; 
+                      }' < /proc/net/iet/session)
+		while [[ -n $2 ]]; do
+                    # $2 $1 looks like "--sid=X --cid=Y"
+		    ocf_run ietadm --op delete \
+			     --tid=${tid} $2 $1
+		    shift 2
+		done
+   	        # In iet, unassigning a user from a target and
+		# deleting the user account is one operation.
+		if [ -n "${OCF_RESKEY_incoming_username}" ]; then
+		    ocf_run ietadm --op delete --user \
+			--tid=${tid} \
+			--params=IncomingUser=${OCF_RESKEY_incoming_username} \
+			|| exit $OCF_ERR_GENERIC
+		fi
+		# Loop on delete. Keep trying until we time out, if
+		# necessary.
+		while true; do
+		    if ietadm --op delete --tid=${tid}; then
+			ocf_log debug "Removed target ${OCF_RESKEY_iqn}."
+			break
+		    else
+			ocf_log warn "Failed to remove target ${OCF_RESKEY_iqn}, retrying."
+			sleep 1
+		    fi
+		done
+		# Avoid stale /etc/initiators.{allow,deny} entries
+		# for this target
+		if [ -e /etc/initiators.deny ]; then
+		    ocf_run sed -e "/^${OCF_RESKEY_iqn}[[:space:]]/d" \
+			-i /etc/initiators.deny
+		fi
+		if [ -e /etc/initiators.allow ]; then
+		    ocf_run sed -e "/^${OCF_RESKEY_iqn}[[:space:]]/d" \
+			-i /etc/initiators.allow
+		fi
+		;;
+	    tgt)
+		tid="${OCF_RESKEY_tid}"
+		# Close existing connections. There is no other way to
+		# do this in tgt than to parse the output of "tgtadm --op
+		# show".
+		set -- $(tgtadm --lld iscsi --op show --mode target \
+		    | sed -ne '/^Target '${tid}':/,/^Target/ {
+                          /^[[:space:]]*I_T nexus: \([0-9]\+\)/ {
+                             s/^.*: \([0-9]*\).*/--sid=\1/; h;
+                          };
+                          /^[[:space:]]*Connection: \([0-9]\+\)/ { 
+                              s/^.*: \([0-9]*\).*/--cid=\1/; G; p; 
+                          }; 
+                          /^[[:space:]]*LUN information:/ q; 
+                      }')
+		while [[ -n $2 ]]; do
+                    # $2 $1 looks like "--sid=X --cid=Y"
+		    ocf_run tgtadm --lld iscsi --op delete --mode connection \
+			--tid=${tid} $2 $1
+		    shift 2
+		done
+	        # In tgt, we must first unbind the user account from
+		# the target, then remove the account itself.
+		if [ -n "${OCF_RESKEY_incoming_username}" ]; then
+		    ocf_run tgtadm --lld iscsi --mode account --op unbind \
+			--tid=${tid} \
+			--user=${OCF_RESKEY_incoming_username} || exit $OCF_ERR_GENERIC
+		    ocf_run tgtadm --lld iscsi --mode account --op delete \
+			--user=${OCF_RESKEY_incoming_username} || exit $OCF_ERR_GENERIC
+		fi
+		# Loop on delete. Keep trying until we time out, if
+		# necessary.
+		while true; do
+		    if tgtadm --lld iscsi --op delete --mode target --tid=${tid}; then
+			ocf_log debug "Removed target ${OCF_RESKEY_iqn}."
+			break
+		    else
+			ocf_log warn "Failed to remove target ${OCF_RESKEY_iqn}, retrying."
+			sleep 1
+		    fi
+		done
+		# In tgt, we don't have to worry about our ACL
+		# entries. They are automatically removed upon target
+		# deletion.
+		;;
+	    lio)
+		# In lio, removing a target automatically removes all
+		# associated TPGs, network portals, and LUNs.
+		ocf_run lio_node --deliqn ${OCF_RESKEY_iqn} || exit $OCF_ERR_GENERIC
+		;;
+	esac
+    fi
+
+    return $OCF_SUCCESS
+}
+
+iSCSITarget_monitor() {
+    case $OCF_RESKEY_implementation in
+	iet)
+	    grep -Eq "tid:[0-9]+ name:${OCF_RESKEY_iqn}" /proc/net/iet/volume && return $OCF_SUCCESS
+	    ;;
+	tgt)
+	    tgtadm --lld iscsi --op show --mode target \
+		| grep -Eq "Target [0-9]+: ${OCF_RESKEY_iqn}" && return $OCF_SUCCESS
+	    ;;
+	lio)
+	    # if we have no configfs entry for the target, it's
+	    # definitely stopped
+	    [ -d /sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn} ] || return $OCF_NOT_RUNNING
+	    # if the target is there, but its TPG is not enabled, then
+	    # we also consider it stopped
+	    [ `cat /sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_1/enable` -eq 1 ] || return $OCF_NOT_RUNNING
+	    return $OCF_SUCCESS
+	    ;;
+    esac
+    
+    return $OCF_NOT_RUNNING
+}
+
+iSCSITarget_validate() {
+    # Do we have all required variables?
+    local required_vars
+    case $OCF_RESKEY_implementation in
+	iet)
+	    required_vars="iqn"
+	    ;;
+	tgt)
+	    required_vars="iqn tid"
+	    ;;
+    esac
+    for var in ${required_vars}; do
+	param="OCF_RESKEY_${var}"
+	if [ -z "${!param}" ]; then
+	    ocf_log error "Missing resource parameter \"$var\"!"
+	    exit $OCF_ERR_CONFIGURED
+	fi
+    done
+
+    # Is the configured implementation supported?
+    case "$OCF_RESKEY_implementation" in
+	"iet"|"tgt"|"lio")
+	    ;;
+	"")
+	    # The user didn't specify an implementation, and we were
+	    # unable to determine one from installed binaries (in
+	    # other words: no binaries for any supported
+	    # implementation could be found)
+	    ocf_log error "Undefined iSCSI target implementation"
+	    exit $OCF_ERR_INSTALLED
+	    ;;
+	*)
+	    ocf_log error "Unsupported iSCSI target implementation \"$OCF_RESKEY_implementation\"!"
+	    exit $OCF_ERR_CONFIGURED
+	    ;;
+    esac
+
+    # Do we have any configuration parameters that the current
+    # implementation does not support?
+    local unsupported_params
+    local var
+    local envar
+    case $OCF_RESKEY_implementation in
+	iet|tgt)
+	    # IET and tgt do not support binding a target portal to a
+	    # specific IP address.
+	    unsupported_params="portals"
+	    ;;
+	lio)
+	    # TODO: Remove incoming_username and incoming_password
+	    # from this check when LIO 3.0 gets CHAP authentication
+	    unsupported_params="tid incoming_username incoming_password"
+	    ;;
+    esac
+    for var in ${unsupported_params}; do
+	envar=OCF_RESKEY_${var}
+	defvar=OCF_RESKEY_${var}_default
+	if [ -n "${!envar}" ]; then
+            if  [[ "${!envar}" != "${!defvar}" ]];then
+                    case "$__OCF_ACTION" in
+                        start|validate-all)
+                          ocf_log warn "Configuration parameter \"${var}\"" \
+                            "is not supported by the iSCSI implementation" \
+                            "and will be ignored." ;;
+                    esac
+            fi
+	fi
+    done
+
+    if ! ocf_is_probe; then
+        # Do we have all required binaries?
+	case $OCF_RESKEY_implementation in
+	    iet)
+		check_binary ietadm
+		;;
+	    tgt)
+		check_binary tgtadm
+		;;
+	    lio)
+		check_binary tcm_node
+		check_binary lio_node
+		;;
+	esac
+
+        # Is the required kernel functionality available?
+	case $OCF_RESKEY_implementation in
+	    iet)
+		[ -d /proc/net/iet ]
+		if [ $? -ne 0 ]; then
+		    ocf_log err "/proc/net/iet does not exist or is not a directory -- check if required modules are loaded."
+		    exit $OCF_ERR_INSTALLED
+		fi
+		;;
+	    tgt)
+	        # tgt is userland only
+		;;
+	    lio)
+	        # lio needs configfs to be mounted
+		if ! grep -Eq "^.*/sys/kernel/config[[:space:]]+configfs" /proc/mounts; then
+		    ocf_log err "configfs not mounted at /sys/kernel/config -- check if required modules are loaded."
+		    exit $OCF_ERR_INSTALLED
+		fi
+	        # check for configfs entries created by target_core_mod
+		if [ ! -d /sys/kernel/config/target ]; then
+		    ocf_log err "/sys/kernel/config/target does not exist or is not a directory -- check if required modules are loaded."
+		    exit $OCF_ERR_INSTALLED
+		fi
+		;;
+	esac
+    fi
+
+    return $OCF_SUCCESS
+}
+
+
+case $1 in
+  meta-data)
+	meta_data
+	exit $OCF_SUCCESS
+	;;
+  usage|help)
+	iSCSITarget_usage
+	exit $OCF_SUCCESS
+	;;
+esac
+
+# Everything except usage and meta-data must pass the validate test
+iSCSITarget_validate
+
+case $__OCF_ACTION in
+start)		iSCSITarget_start;;
+stop)		iSCSITarget_stop;;
+monitor|status)	iSCSITarget_monitor;;
+reload)		ocf_log err "Reloading..."
+	        iSCSITarget_start
+		;;
+validate-all)	;;
+*)		iSCSITarget_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
diff --git a/heartbeat/ids b/heartbeat/ids
new file mode 100755
index 0000000..740f450
--- /dev/null
+++ b/heartbeat/ids
@@ -0,0 +1,738 @@
+#!/bin/sh
+#
+#
+# ids
+#
+# Description:
+#
+# OCF resource agent that manages an 
+# IBM Informix Dynamic Server (IDS) instance 
+# as an High-Availability resource.
+####
+#
+# Author:			Lars D. Forseth, <lars.forseth at de.ibm.com> or <lars at forseth.de>
+# Created:			May 25th 2007
+# Last Modified:	July 30th 2007
+# Support:			linux-ha at lists.linux-ha.org
+# License:			GNU General Public License (GPL), Version 2 or later
+# Copyright:		(c) 2002 - 2007 International Business Machines, Inc.
+#
+# This code is inspired by the db2 OCF resource agent 
+# written by Alan Robertson, <alanr at unix.sh>
+####
+#
+# 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 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.
+####
+#
+# Example usage as it would appear in /etc/ha.d/haresources:
+#		node1 192.168.0.1 ids::/informix::ids1::onconfig.ids1
+#
+#
+# --> Note that passing dbname and sqltestquery in heartbeat version 1 style is not supported!
+#
+# See usage() function below for more details...
+####
+#
+# OCF instance parameters:
+#   OCF_RESKEY_informixdir
+#	OCF_RESKEY_informixserver 
+#	OCF_RESKEY_onconfig
+#	OCF_RESKEY_dbname
+#	OCF_RESKEY_sqltestquery
+####
+
+
+#
+# Include general OCF functions and variables (such as OCF return codes).
+#
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+
+#
+# Function that displays the usage of this script.
+#
+ids_usage() {
+	methods=`ids_methods`
+	methods=`echo $methods | tr ' ' '|'`
+
+	echo "
+	usage: $0 ($methods)
+
+	$0 manages an IBM Informix Dynamic Server (IDS) instance as an High-Availability resource.
+
+	The 'start' operation starts the database.
+	The 'stop' operation stops the database.
+	The 'status' operation reports whether the database is running
+	The 'monitor' operation reports whether the database seems to be working
+	The 'validate-all' operation reports whether the parameters are valid
+	The 'methods' operation lists the methods $0 supports
+	The 'usage' operation displays this text
+	The 'meta-data' operation returns the meta-data (in XML) of this resource script
+    "
+}
+
+
+#
+# Function that displays the possible methods this script supports.
+#
+ids_methods() {
+	echo " 
+	start
+	stop
+	status
+	monitor
+	validate-all
+	methods
+	usage
+	meta-data
+	"
+}
+
+
+#
+# Function that displays the meta-data of this OCF resource agent.
+#
+ids_meta_data() {
+    cat <<-!
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="ids">
+<version>1.0</version>
+
+
+<longdesc lang="en">
+OCF resource agent to manage an IBM Informix Dynamic Server (IDS) instance as an High-Availability resource.
+</longdesc>
+<shortdesc lang="en">Manages an Informix Dynamic Server (IDS) instance</shortdesc>
+
+
+<parameters>
+
+<parameter name="informixdir" required="0">
+<longdesc lang="en">
+The value the environment variable INFORMIXDIR has after a typical installation of IDS.
+Or in other words: the path (without trailing '/') where IDS was installed to.
+If this parameter is unspecified the script will try to get the value from the shell environment.
+</longdesc>
+<shortdesc lang="en">
+INFORMIXDIR environment variable
+</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="informixserver" required="0">
+<longdesc lang="en">
+The value the environment variable INFORMIXSERVER has after a typical installation of IDS.
+Or in other words: the name of the IDS server instance to manage.
+If this parameter is unspecified the script will try to get the value from the shell environment.
+</longdesc>
+<shortdesc lang="en">
+INFORMIXSERVER environment variable
+</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="onconfig" required="0">
+<longdesc lang="en">
+The value the environment variable ONCONFIG has after a typical installation of IDS.
+Or in other words: the name of the configuration file for the IDS instance specified in INFORMIXSERVER. 
+The specified configuration file will be searched at '$INFORMIXDIR/etc/$ONCONFIG'.
+If this parameter is unspecified the script will try to get the value from the shell environment.
+</longdesc>
+<shortdesc lang="en">
+ONCONFIG environment variable
+</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="dbname" required="0">
+<longdesc lang="en">
+This parameter defines which database to use in order to monitor the IDS instance.
+If this parameter is unspecified the script will use the 'sysmaster' database as a default.
+</longdesc>
+<shortdesc lang="en">
+database to use for monitoring, defaults to 'sysmaster'
+</shortdesc>
+<content type="string" default="sysmaster" />
+</parameter>
+
+<parameter name="sqltestquery" required="0">
+<longdesc lang="en">
+SQL test query to run on the database specified by the parameter 'dbname' 
+in order to monitor the IDS instance and determine if it's functional or not.
+If this parameter is unspecified the script will use 'SELECT COUNT(*) FROM systables;' as a default.
+</longdesc>
+<shortdesc lang="en">
+SQL test query to use for monitoring, defaults to 'SELECT COUNT(*) FROM systables;'
+</shortdesc>
+<content type="string" default="SELECT COUNT(*) FROM systables;" />
+</parameter>
+
+</parameters>
+
+
+<actions>
+<action name="start" timeout="120" />
+<action name="stop" timeout="120" />
+<action name="status" timeout="60" />
+<action name="monitor" depth="0" timeout="30" interval="10" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+<action name="methods" timeout="5" />
+<action name="usage" timeout="5" />
+</actions>
+
+
+</resource-agent>
+!
+}
+
+
+#
+# Function that either forwards log messages to the ocf_log function
+# provided by heartbeat or simply prints them to standard out via echo.
+# This is determined by setting the variable "idslogger" to "echo" or "ocf".
+# The default for "idslogger" is "ocf".
+#
+ids_log() {
+
+	# Where should the passed log messages be passed to,
+	# to the standard output via the echo command ("echo")
+	# or to the ocf_log function provided by heartbeat ("ocf") ?
+	# Default is "ocf".
+	idslogger="ocf"
+
+	# When the variable "idsdebug" is not set to "true"
+	# this function (ids_log) will not print any info message
+	# that has been forwarded to it!
+	# This is done in order to spare if-statements within the 
+	# other functions in this script and to centralize the decision
+	# whether to have a chatty resource script or not... ;)
+	# Nevertheless, error messages will always be printed!
+	idsdebug=false
+
+	# Only continue if the two expected parameters 
+	# are not empty and "idsdebug" is set to "true"
+	# or the message is of type "error".
+	if [ $# -eq 2 -a -n "$1" -a -n "$2" ]; then
+		if [ "$idsdebug" = "true" -o "$1" = "error" ]; then
+			case $idslogger in
+				# Print messages to stdout via echo command.
+				echo)
+					echo "`date +'%b %d %H:%M:%S'`: [$1] $2";;
+				# Pass messages to ocf_log function.
+				ocf|*)
+					ocf_log "$1" "$2";;
+			esac
+		fi
+	fi		
+}
+
+
+#
+# Function that prints the current values of important environment variables
+# needed by the script and the IDS instance itself. The just mentioned variables are:
+# - INFORMIXDIR
+# - INFORMIXSERVER
+# - ONCONFIG
+# - PATH
+# - LD_LIBRARY_PATH
+#
+ids_debug() {
+	ids_log info "called ids_debug"	
+
+	ids_log info "INFORMIXDIR=$INFORMIXDIR"
+	ids_log info "OCF_RESKEY_informixdir=$OCF_RESKEY_informixdir"
+	
+	ids_log info "INFORMIXSERVER=$INFORMIXSERVER"
+	ids_log info "OCF_RESKEY_informixserver=$OCF_RESKEY_informixserver"
+	
+	ids_log info "ONCONFIG=$ONCONFIG"
+	ids_log info "OCF_RESKEY_onconfig=$OCF_RESKEY_onconfig"
+	
+	ids_log info "PATH=$PATH"
+	ids_log info "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
+	
+	ids_log info "dbname=$OCF_RESKEY_dbname"
+	ids_log info "sqltestquery=$OCF_RESKEY_sqltestquery"
+
+	ids_log info "this script is run as user: `id`"
+	ids_log info "...in the current working directory: `pwd`"
+}
+
+
+#
+# Function that validates if the passed parameters are valid and sets them if valid. 
+# If the first three parameters have not been passed, 
+# this function checks whether they have been already set in the parent's shell environment.
+# The variables that are checked and set (only the capitalized ones are set) are:
+# - INFORMIXDIR
+# - INFORMIXSERVER
+# - ONCONFIG
+# - PATH
+# - LD_LIBRARY_PATH
+# - dbname
+# - sqltestquery
+#
+ids_validate() {
+	
+	ids_log info "called ids_validate"
+	rc=$OCF_SUCCESS
+
+	# Check if INFORMIX, INFORMIXSERVER and ONCONFIG 
+	# have been passed or set and validate them.
+	
+	# OCF vars not passed, vars empty - set and export them to the shell environment.
+	if [ -n "$OCF_RESKEY_informixdir" -a -n "$OCF_RESKEY_informixserver" -a -n "$OCF_RESKEY_onconfig" ]; then
+		ids_log info "ids_validate: passed vars not empty"
+		
+		INFORMIXDIR=$OCF_RESKEY_informixdir
+		export INFORMIXDIR
+
+		INFORMIXSERVER=$OCF_RESKEY_informixserver
+		export INFORMIXSERVER
+
+		ONCONFIG=$OCF_RESKEY_onconfig
+		export ONCONFIG
+	fi
+
+	# Check if INFORMIXDIR is non-empty and a directory (and if there was an error so far).
+	if [ $rc -eq $OCF_SUCCESS -a -n "$INFORMIXDIR" -a -d "$INFORMIXDIR" ]; then
+		ids_log info "ids_validate: INFORMIXDIR is valid: $INFORMIXDIR"
+		rc=$OCF_SUCCESS
+	else
+		ids_log error "ids_validate: INFORMIXDIR is invalid: $INFORMIXDIR"
+		rc=$OCF_ERR_ARGS
+	fi
+
+	# Check if INFORMIXSERVER is non-empty (and if there was an error so far).
+	if [ $rc -eq $OCF_SUCCESS -a -n "$INFORMIXSERVER" ]; then
+		ids_log info "ids_validate: INFORMIXSERVER is valid: $INFORMIXSERVER"
+		rc=$OCF_SUCCESS
+	else
+		ids_log error "ids_validate: INFORMIXSERVER is invalid: $INFORMIXSERVER"
+		rc=$OCF_ERR_ARGS
+	fi
+
+	# Check if ONCONFIG is non-empty and a non-empty file (and if there was an error so far).
+	if [ $rc -eq $OCF_SUCCESS -a -n "$ONCONFIG" -a -s "$INFORMIXDIR/etc/$ONCONFIG" ]; then
+		ids_log info "ids_validate: ONCONFIG is a non-empty file in: \$INFORMIXDIR/etc/\$ONCONFIG where ONCONFIG=$ONCONFIG"
+		rc=$OCF_SUCCESS
+	else 
+		if [ -z "$ONCONFIG" -a -s "$INFORMIXDIR/etc/onconfig" ]; then
+			ONCONFIG="onconfig" 
+			export ONCONFIG
+			ids_log info "ids_validate: ONCONFIG is a non-empty file in: \$INFORMIXDIR/etc/\$ONCONFIG where ONCONFIG=$ONCONFIG"
+			rc=$OCF_SUCCESS
+		else
+			if [ -z "$ONCONFIG" -a -s "$INFORMIXDIR/etc/onconfig.std" ]; then
+				ONCONFIG="onconfig.std"
+            	export ONCONFIG
+				ids_log info "ids_validate: ONCONFIG is a non-empty file in: \$INFORMIXDIR/etc/\$ONCONFIG where ONCONFIG=$ONCONFIG"
+            	rc=$OCF_SUCCESS				
+			else
+				ids_log error "ids_validate: ONCONFIG is invalid, searched for it in: \$INFORMIXDIR/etc/\$ONCONFIG where ONCONFIG=$ONCONFIG"
+				rc=$OCF_ERR_ARGS
+			fi
+		fi
+	fi
+
+	# Check if the commands oninit, onstat, onmode and dbaccess	exist in INFORMIXDIR/bin/
+	# and whether they are executable (do this only if there wasn't an error so far).
+	if [ $rc -eq $OCF_SUCCESS -a -x "$INFORMIXDIR/bin/oninit" -a -x "$INFORMIXDIR/bin/onstat" -a -x "$INFORMIXDIR/bin/onmode" -a -x "$INFORMIXDIR/bin/dbaccess" ]; then
+		ids_log info "ids_validate: oninit, onstat and dbaccess exist and are executable in: \$INFORMIXDIR/bin/"
+		rc=$OCF_SUCCESS
+	else
+		ids_log error "ids_validate: oninit, onstat or dbacces don't exist or they are not executable in: \$INFORMIXDIR/bin/"
+		rc=$OCF_ERR_PERM
+	fi
+
+	# Extend PATH and LD_LIBRARY_PATH as needed for the IDS instance to run properly
+	# BUT: only do this if it hasn't been done before! Otherwise PATH and LD_LIBRARY_PATH will
+	# keep on growing every time heartbeat calls the IDS resource agent script! ;)
+	echo $PATH | grep $INFORMIXDIR > /dev/null 2>&1
+	inpath=$?
+	
+	if [ $rc -eq $OCF_SUCCESS -a $inpath -ne 0 ]; then 
+		PATH="${INFORMIXDIR}/bin":${PATH}
+		export PATH
+		ids_log info "ids_validate: PATH did not contain INFORMIXDIR, added \$INFORMIXDIR/bin"
+	else
+		ids_log info "ids_validate: INFORMIXDIR already in PATH, where PATH=$PATH"
+	fi
+
+	echo $LD_LIBRARY_PATH | grep $INFORMIXDIR > /dev/null 2>&1
+	inldlibpath=$?
+
+	if [ $rc -eq $OCF_SUCCESS -a $inldlibpath -ne 0 ]; then
+		LD_LIBRARY_PATH="${INFORMIXDIR}/lib:${INFORMIXDIR}/lib/esql"
+		export LD_LIBRARY_PATH
+		ids_log info "ids_validate: LD_LIBRARY_PATH did not contain INFORMIXDIR, added \$INFORMIXDIR/lib and \$INFORMIXDIR/lib/esql, added them"
+	else
+		ids_log info "ids_validate: INFORMIXDIR already in LD_LIBRARY_PATH, where LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
+	fi
+	
+	# Check if dbname is empty (and if there was an error so far)
+	# if it is empty, assign default.
+	if [ $rc -eq $OCF_SUCCESS -a -n "$OCF_RESKEY_dbname" ]; then
+		ids_log info "ids_validate: dbname is valid: $OCF_RESKEY_dbname"
+		rc=$OCF_SUCCESS
+	else
+		ids_log info "ids_validate: dbname is invalid: $OCF_RESKEY_dbname"
+		ids_log info "ids_validate: using 'sysmaster' as default..."
+		OCF_RESKEY_dbname="sysmaster"
+		export OCF_RESKEY_dbname
+		rc=$OCF_SUCCESS
+	fi
+
+	# Check if sqltestquery is empty (and if there was an error so far)
+	# if it is empty, assign default.
+	if [ $rc -eq $OCF_SUCCESS -a -n "$OCF_RESKEY_sqltestquery" ]; then
+		ids_log info "ids_validate: sqltestquery is valid: $OCF_RESKEY_sqltestquery"
+		rc=$OCF_SUCCESS
+	else
+		ids_log info "ids_validate: sqltestquery is invalid: $OCF_RESKEY_sqltestquery"
+		ids_log info "ids_validate: using 'SELECT COUNT(*) FROM systables;' as default..."
+        OCF_RESKEY_sqltestquery="SELECT COUNT(*) FROM systables;"
+        export OCF_RESKEY_sqltestquery
+        rc=$OCF_SUCCESS
+	fi
+
+	# Return exit status code.
+	return $rc
+}
+
+
+#
+# Function that start the IDS instance and reports any error that
+# may occur while starting.
+#
+ids_start() {
+
+	ids_log info "called ids_start"
+	
+	# Get current status of IDS instance.
+	ids_status
+	stat=$?
+
+	case $stat in
+		
+		# IDS instance already running - exit with success.
+		$OCF_SUCCESS)
+			ids_log info "ids_start: IDS instance already running: $stat"
+			rc=$OCF_SUCCESS;;
+	
+		# IDS instance in undefined state - exit with error.
+		$OCF_ERR_GENERIC)
+			ids_log error "ids_start: IDS instance in undefined state: $stat"
+			ids_debug
+			rc=$OCF_ERR_GENERIC;;	
+
+		# IDS instance not running - try to start it.
+		$OCF_NOT_RUNNING)
+			ids_log info "ids_start: executing 'oninit' now..."	
+			oninit
+			stat=$?
+			ids_log info "ids_start: done executing 'oninit': $stat"
+			
+			# The oninit command terminated successfully - check new state of IDS instance.
+			if [ $stat -eq 0 ]; then
+				# Initialize stat with failure exit status code.
+				stat=$OCF_ERR_GENERIC
+				# Endless loop that waits until IDS is completely online.
+				# If IDS takes too long to achieve this or even hangs, 
+				# the timeout settings of heartbeat will cancel the starting 
+				# of the IDS resource and therefore terminate the loop.
+				while [ $stat -ne $OCF_SUCCESS ]; do
+					ids_status
+					stat=$?
+				done
+				# IDS is running now - success.
+				ids_log info "ids_start: IDS instance successfully started: $stat"
+				rc=$OCF_SUCCESS
+			# The oninit command terminated with an error - starting the IDS resource failed!
+			else
+				ids_log error "ids_start: starting IDS instance failed: $stat"
+				ids_debug
+				rc=$OCF_ERR_GENERIC			
+			fi
+			;;
+
+		# Unexpected state - return OCF_ERR_UNIMPLEMENTED error.
+		*) 
+			ids_log error "ids_start: unexpected state returned from ids_status: $stat"
+			ids_debug
+			rc=$OCF_ERR_UNIMPLEMENTED;;				
+
+	esac
+
+	# Return exit status code.
+	return $rc
+}
+
+
+#
+# Function that stops the IDS instance and reports any error that
+# may occur while stopping.
+#
+ids_stop() {
+	
+	ids_log info "caled ids_stop"
+
+	ids_status
+	stat=$?
+
+	case $stat in
+
+        # IDS instance is not running - success stopping it.
+        $OCF_NOT_RUNNING)
+			ids_log info "ids_stop: IDS instance is not running: $stat"
+            rc=$OCF_SUCCESS;;
+
+        # IDS instance is in an undefined state - exit with error.
+        $OCF_ERR_GENERIC)
+			ids_log error "ids_stop: IDS instance in undefined state: $stat"
+			ids_debug
+            rc=$OCF_ERR_GENERIC;;
+
+        # IDS instance is running - try to stop it.
+        $OCF_SUCCESS)
+			ids_log info "ids_stop: running 'onmode -kuy' now..."
+			onmode -kuy
+			stat=$?
+			ids_log info "ids_stop: done running 'onmode -kuy' now: $stat"
+
+			# The onmode command terminated successfully - check new state of the IDS instance.
+			if [ $stat -eq 0 ]; then
+				ids_status
+                stat=$?
+                # New state is: not running - success.
+                if [ $stat -eq $OCF_NOT_RUNNING ]; then
+					ids_log info "ids_stop: IDS instance successfully stopped: $stat"
+                    rc=$OCF_SUCCESS
+                # New state is: running or even undefined - failure!
+                else
+					ids_log error "ids_stop: stopping IDS instance failed: $stat"
+                    ids_debug
+                    rc=$OCF_ERR_GENERIC
+                fi
+				
+ 			# The onmode command terminated with an error - stopping the IDS resource failed!
+            else
+				ids_log error "ids_stop: stopping IDS instance (by executing 'onmode -kuy') failed: $stat"
+                ids_debug
+                rc=$OCF_ERR_GENERIC
+            fi
+            ;;
+
+		# Unexpected state - return OCF_ERR_UNIMPLEMENTED error.
+        *)
+			ids_log error "ids_stop: unexpected state returned from ids_status: $stat"
+			ids_debug
+            rc=$OCF_ERR_UNIMPLEMENTED;;
+		
+	esac
+
+	# Return exit status code indicating whether IDS was successfully stopped or not.
+	return $rc
+}
+
+
+#
+# Function that determines the current status/state of the IDS instance,
+# meaning whether it is running (the case when output of "onstat -" contains "On-Line"),
+# not running (the case when output of "onstat -" contains "shared memory not initialized")
+# or in an undefined state (the case output of "onstat -" contains "Quiescent", "Single-User", or other).
+# If the IDS instance is declared running the exit status code will indicate succes, otherwise failure of course.
+#
+ids_status() {
+	
+	ids_log info "called ids_status"
+
+	# Get current status from the onstat tool and store it.
+	stat=`onstat -`
+	
+	case $stat in
+		
+		# IDS instance is running.
+		*"On-Line"*)
+			ids_log info "ids_status: IDS instance running: $stat"
+			rc=$OCF_SUCCESS;;
+
+		# IDS instance is not running.
+		*"shared memory not initialized"*)
+			ids_log info "ids_status: IDS instance not running: $stat"
+			rc=$OCF_NOT_RUNNING;;
+
+		# IDS instance is in an undefined state!
+		*)
+			ids_log error "ids_status: IDS instance status undefined: $stat"
+			rc=$OCF_ERR_GENERIC;;
+	esac
+	
+	# Return exit status code (ergo current status of the IDS instance) to caller
+	return $rc
+}
+
+
+#
+# Function that monitors the current status _and_ funtionality of the IDS instance.
+# First the state of the instance is determined. If it is running, a sql test query is
+# executed on the database. If the sql test query executes sucessfully, the instance's
+# status is rechecked and if it is still running, the script terminates with an exit
+# status code indicating success. If any of the above described steps fails, 
+# the script terminates with an error.
+#
+ids_monitor() {
+	
+	ids_log info "called ids_monitor" 
+
+	ids_status
+	stat=$?
+
+	case $stat in
+
+        # IDS instance is not running - monitoring failed.
+        $OCF_NOT_RUNNING)
+			ids_log info "ids_monitor: IDS instance is not running: $stat"
+            rc=$OCF_NOT_RUNNING;;
+
+        # IDS instance in an undefined state - exit with error.
+        $OCF_ERR_GENERIC)
+			ids_log error "ids_monitor: IDS instance in undefined state: $stat"
+			ids_debug
+            rc=$OCF_ERR_GENERIC;;
+
+        # IDS instance is running - try to execute the sql test query and recheck state.
+        $OCF_SUCCESS)
+			ids_log info "ids_monitor: IDS instance is running (before executing sql test query)"
+			ids_log info "ids_monitor: running sql test query now..."
+			echo $OCF_RESKEY_sqltestquery | dbaccess $OCF_RESKEY_dbname - > /dev/null 2>&1
+			stat=$?
+			ids_log info "ids_monitor: done running sql test query now: $stat"
+
+			# The sql test query terminated successfully - check the new state of the IDS instance.
+			if [ $stat -eq 0 ]; then
+				ids_status
+                stat=$?
+                # New state is: running - success.
+                if [ $stat -eq $OCF_SUCCESS ]; then
+					ids_log info "ids_monitor: successfully ran sql test query on IDS instance: $stat"
+                    rc=$OCF_SUCCESS
+                # New state is: not running or even undefined - failure!
+                else
+					ids_log error "ids_monitor: running sql test query on IDS instance failed: $stat"
+                    ids_debug
+                    rc=$OCF_ERR_GENERIC
+                fi
+				
+ 			# The sql test query terminated with an error - exit with error!
+            else
+				ids_log error "ids_monitor: running sql test query on IDS instance failed: $stat"
+                ids_debug
+                rc=$OCF_ERR_GENERIC
+            fi
+            ;;
+
+		# Unexpected state - return OCF_ERR_UNIMPLEMENTED error!
+        *)
+			ids_log error "ids_monitor: unexpected state returned from ids_status: $stat"
+			ids_debug
+            rc=$OCF_ERR_UNIMPLEMENTED;;
+		
+	esac
+
+	# Return exit status code indicating whether IDS is running and functional or not.
+	return $rc
+}
+
+
+
+
+###
+#
+# M A I N   S E C T I O N
+#
+###
+
+case "$1" in
+	usage)
+		ids_usage
+		exit $?;;
+	meta-data)
+		ids_meta_data
+		exit $?;;
+esac
+
+# Validate configuration (parameters and such) 
+# passed to this script and only process the method parameter
+# if the configuration is valid! Otherwise exit with OCF_ERR_ARGS error code.
+
+# Only check configuration when given method is not "validate-all",
+# as in case of "validate-all" the configuration will be checked anyway! ;)
+if [ "$1" != "validate-all" ]; then
+	ids_validate
+	valid=$?
+	ids_log info "main section: validated ids RA configuration, result: $valid"
+	
+	# Configuration invalid - terminate with error message.
+	if [ $valid -ne $OCF_SUCCESS ]; then
+		ids_log error "main section: terminating script due to invalid configuration"
+		ids_debug
+		exit $OCF_ERR_ARGS
+	fi
+fi
+
+# Configuration valid or method equals to "validate-all" - react depending on called method.
+case "$1" in
+
+	start)	
+		ids_start
+		exit $?;;
+
+	stop)	
+		ids_stop
+		exit $?;;
+
+	status)	
+		ids_status
+		exit $?;;
+
+	monitor)	
+		ids_monitor
+		exit $?;;
+
+	validate-all)
+		ids_validate
+		exit $?;;
+
+	methods)
+		ids_methods
+		exit $?;;
+
+	*)
+		ids_log error "mainsection: no or invalid command supplied: $1"
+		exit $OCF_ERR_UNIMPLEMENTED;;
+
+esac
+###############################################################################
diff --git a/heartbeat/iface-bridge b/heartbeat/iface-bridge
new file mode 100755
index 0000000..e1dfecb
--- /dev/null
+++ b/heartbeat/iface-bridge
@@ -0,0 +1,843 @@
+#!/bin/sh
+#
+#       OCF Resource Agent compliant iface-bridge script.
+#
+#       Implements network Bridge interface management
+#
+# Copyright (C) 2013 Red Hat, Inc.  All rights reserved.
+# Author: Fabio M. Di Nitto <fdinitto at redhat.com>
+#
+# 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.
+#
+#
+
+# TODO:
+#       * Eventually improve bridge_check to verify all runtime
+#         parameters. Is it really necessary?
+#       * consider add support for advanced multicast timers tuning
+#         sethashel       <bridge> <int>   set hash elasticity                   default 4
+#         sethashmax      <bridge> <int>   set hash max                          default 512
+#         setmclmc        <bridge> <int>   set multicast last member count       default 2, ?
+#         setmcsqc        <bridge> <int>   set multicast startup query count     default 2, ?
+#         setmclmi        <bridge> <time>  set multicast last member interval    default HZ
+#         setmcmi         <bridge> <time>  set multicast membership interval     default 260 * HZ
+#         setmcqpi        <bridge> <time>  set multicast querier interval        default 255 * HZ
+#         setmcqi         <bridge> <time>  set multicast query interval          detault 125 * HZ
+#         setmcqri        <bridge> <time>  set multicast query response interval default 10 * HZ
+#         setmcqri        <bridge> <time>  set multicast startup query interval  default 125 * hZ / 4
+#
+#
+#	OCF parameters are as below
+#	OCF_RESKEY_bridge_name
+#       OCF_RESKEY_bridge_slaves
+#       OCF_RESKEY_bridge_ageing
+#       OCF_RESKEY_port_hairpin
+#       OCF_RESKEY_stp
+#       OCF_RESKEY_stp_bridgeprio
+#       OCF_RESKEY_stp_fd
+#       OCF_RESKEY_stp_maxage
+#       OCF_RESKEY_stp_hello
+#       OCF_RESKEY_stp_pathcost
+#       OCF_RESKEY_stp_portprio
+#       OCF_RESKEY_multicast_router
+#       OCF_RESKEY_multicast_snooping
+#       OCF_RESKEY_multicast_querier
+#       OCF_RESKEY_multicast_port_router
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+OCF_RESKEY_stp_default=false
+OCF_RESKEY_stp_fd_default=0
+OCF_RESKEY_multicast_router_default=1
+OCF_RESKEY_multicast_snooping_default=1
+OCF_RESKEY_multicast_querier_default=0
+
+: ${OCF_RESKEY_stp=${OCF_RESKEY_stp_default}}
+: ${OCF_RESKEY_stp_fd=${OCF_RESKEY_stp_fd_default}}
+: ${OCF_RESKEY_multicast_router=${OCF_RESKEY_multicast_router_default}}
+: ${OCF_RESKEY_multicast_snooping=${OCF_RESKEY_multicast_snooping_default}}
+: ${OCF_RESKEY_multicast_querier=${OCF_RESKEY_multicast_querier_default}}
+
+# binaries
+: ${BRCTL:=brctl}
+
+#######################################################################
+
+bridge_usage() {
+	cat <<END
+usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+bridge_meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="iface-bridge">
+  <version>1.0</version>
+
+  <longdesc lang="en">
+    This resource manages Bridge network interfaces.
+    It can add, remove, configure bridges and spanning-tree.
+  </longdesc>
+
+  <shortdesc lang="en">
+    Manages Bridge network interfaces.
+  </shortdesc>
+
+  <parameters>
+    <parameter name="bridge_name" unique="1" required="1">
+      <longdesc lang="en">
+        Define the name of the bridge (max 15 charaters).
+      </longdesc>
+      <shortdesc lang="en">
+        Name of the bridge
+      </shortdesc>
+      <content type="string"/>
+    </parameter>
+
+    <parameter name="bridge_slaves" unique="1">
+      <longdesc lang="en">
+        Define the list of interfaces, space separated, to add to the bridge.
+        The list can be empty.
+      </longdesc>
+      <shortdesc lang="en">
+        Network interface
+      </shortdesc>
+      <content type="string"/>
+    </parameter>
+
+    <parameter name="bridge_ageing" unique="0">
+      <longdesc lang="en">
+        Set the ethernet (MAC) address ageing time in seconds.
+      </longdesc>
+      <shortdesc lang="en">
+        MAC ageing in seconds.
+      </shortdesc>
+      <content type="integer"/>
+    </parameter>
+
+    <parameter name="port_hairpin" unique="0">
+      <longdesc lang="en">
+        Set hairpin forwarding mode.
+        A list of ports that should have hairpin enabled
+        can be specified using the following
+        Example: eth0 eth1
+      </longdesc>
+      <shortdesc lang="en">
+        Set hairpin forwarding mode.
+      </shortdesc>
+      <content type="string"/>
+    </parameter>
+
+    <parameter name="stp" unique="0">
+      <longdesc lang="en">
+        Enable or disable Spanning Tree Protocol on the bridge.
+      </longdesc>
+      <shortdesc lang="en">
+        Spanning Tree Protocol
+      </shortdesc>
+      <content type="boolean" default="${OCF_RESKEY_stp_default}"/>
+    </parameter>
+
+    <parameter name="stp_bridgeprio" unique="0">
+      <longdesc lang="en">
+        Set the bridge's priority to defined value. The priority value is a
+        number between  0  and 65535), and has no dimension. Lower priority values are
+        preferred. The bridge with the lowest priority will be elected as root bridge.
+      </longdesc>
+      <shortdesc lang="en">
+        Set the bridge's priority.
+      </shortdesc>
+      <content type="integer"/>
+    </parameter>
+
+    <parameter name="stp_fd" unique="0">
+      <longdesc lang="en">
+        Set the bridge forward delay (in seconds).
+      </longdesc>
+      <shortdesc lang="en">
+        Set the bridge forward delay.
+      </shortdesc>
+      <content type="integer" default="${OCF_RESKEY_stp_fd_default}"/>
+    </parameter>
+
+    <parameter name="stp_maxage" unique="0">
+      <longdesc lang="en">
+        Set the bridge maximum message age (in seconds).
+      </longdesc>
+      <shortdesc lang="en">
+        Set the bridge maximum message age.
+      </shortdesc>
+      <content type="integer"/>
+    </parameter>
+
+    <parameter name="stp_hello" unique="0">
+      <longdesc lang="en">
+        Set the bridge hello time (in seconds).
+      </longdesc>
+      <shortdesc lang="en">
+        Set the bridge hello time.
+      </shortdesc>
+      <content type="integer"/>
+    </parameter>
+
+    <parameter name="stp_pathcost" unique="0">
+      <longdesc lang="en">
+        Set the port cost. This is a dimensionless metric.
+        A list of port/cost can be specified using the following
+        format: slave cost slave cost.
+        Example: eth0 100 eth1 1000
+      </longdesc>
+      <shortdesc lang="en">
+        Set the port cost.
+      </shortdesc>
+      <content type="string"/>
+    </parameter>
+
+    <parameter name="stp_portprio" unique="0">
+      <longdesc lang="en">
+        Set the port priority. This is a number between 0 and 63.
+        $BRCTL man page reports a value between 0 and 255, but
+        tests show a limit of 63 on a live system.
+        This metric is used in the designated port and root port
+        selection algorithms.
+        A list of port/priority can be specified using the following
+        format: slave cost slave cost.
+        Example: eth0 10 eth1 60
+      </longdesc>
+      <shortdesc lang="en">
+        Set the port priority.
+      </shortdesc>
+      <content type="string"/>
+    </parameter>
+
+    <parameter name="multicast_router" unique="0">
+      <longdesc lang="en">
+        Enable or disable multicast routing on the bridge.
+      </longdesc>
+      <shortdesc lang="en">
+        Enable or disable multicast routing.
+      </shortdesc>
+      <content type="boolean" default="${OCF_RESKEY_multicast_router_default}"/>
+    </parameter>
+
+    <parameter name="multicast_snooping" unique="0">
+      <longdesc lang="en">
+        Enable or disable multicast snooping on the bridge.
+      </longdesc>
+      <shortdesc lang="en">
+        Enable or disable multicast snooping.
+      </shortdesc>
+      <content type="boolean" default="${OCF_RESKEY_multicast_snooping_default}"/>
+    </parameter>
+
+    <parameter name="multicast_port_router" unique="0">
+      <longdesc lang="en">
+        Enable or disable a port from the multicast router.
+        Kernel enables all port by default.
+        A list of port can be specified using the following
+        format: slave 0|1 slave 0|1.
+        Example: eth0 1 eth1 0
+      </longdesc>
+      <shortdesc lang="en">
+        Enable or disable a port from the multicast router.
+      </shortdesc>
+      <content type="string"/>
+    </parameter>
+  </parameters>
+
+  <actions>
+    <action name="start"        timeout="30s" />
+    <action name="stop"         timeout="20s" />
+    <action name="status"       timeout="20s" depth="0" interval="10s" />
+    <action name="monitor"      timeout="20s" depth="0" interval="10s" />
+    <action name="meta-data"    timeout="5s" />
+    <action name="validate-all" timeout="20s" />
+  </actions>
+</resource-agent>
+END
+}
+
+# commodity function
+# split_string eth0 100 eth1 1000 eth2 100
+# eth0 100
+# eth1 1000
+# eth2 100
+
+split_string() {
+	while [ -n "$1" ]; do
+		echo $1 $2
+		shift && shift
+	done
+}
+
+# check if the interface is admin up/down
+
+iface_is_up() {
+	if ! $IP2UTIL -o link show $1 | \
+	    sed -e 's#.*<##g' -e 's#>.*##' -e 's#LOWER_UP##g' | \
+	    grep -q UP; then
+		return 1
+	fi
+	return 0
+}
+
+# check if the slaves have link layer up/down
+# see kernel network documentation on meaning of LOWER_UP flag
+# for more in depth explanation on how it works
+# NOTE: this check is not reliable in virt environment
+# since interfaces are always LOWER_UP. There is no way
+# from the guest to know if the host has disconnected somehow
+
+iface_lower_is_up() {
+	if ! $IP2UTIL -o link show $1 | \
+	    grep -q LOWER_UP; then
+		return 1
+	fi
+	return 0
+}
+
+# wrapup function to check if any interface defined in
+# option lists is a slave
+
+iface_is_slave() {
+	for slave in $OCF_RESKEY_bridge_slaves; do
+		if [ "$1" = "$slave" ]; then
+			return 0
+		fi	
+	done
+	return 1
+}
+
+bridge_validate() {
+	check_binary $BRCTL
+	check_binary $IP2UTIL
+
+	if [ -z "$OCF_RESKEY_bridge_name" ]; then
+		ocf_log err "Invalid OCF_RESKEY_bridge_name: value cannot be empty"
+		return 1
+	fi
+
+	# the echo .. is the equivalent of strlen in bash
+	#
+	# /usr/include/linux/if.h:#define IFNAMSIZ        16
+	# needs to include 0 byte end string
+
+	if [ "${#OCF_RESKEY_bridge_name}" -gt 15 ]; then
+		ocf_log err "Invalid OCF_RESKEY_bridge_name: name is too long"
+		return 1
+	fi
+
+	if [ ! -d "/sys/class/net" ]; then
+		ocf_log err "Unable to find sysfs network class in /sys"
+		return 1
+	fi
+
+	for slave in $OCF_RESKEY_bridge_slaves; do
+		if [ ! -e "/sys/class/net/$slave" ]; then
+			ocf_log err "Invalid OCF_RESKEY_bridge_slaves: $slave does not exists"
+			return 1
+		fi
+	done
+
+	# check if declared harpin ports are slaves
+	for hairpin in $OCF_RESKEY_port_hairpin; do
+		if ! iface_is_slave $hairpin; then
+			ocf_log err "Invalid OCF_RESKEY_port_hairpin: $hairpin is not listed in OCF_RESKEY_bridge_slaves"
+			return 1
+		fi
+	done
+
+	if [ -n "$OCF_RESKEY_bridge_ageing" ]; then
+		if ! ocf_is_decimal "$OCF_RESKEY_bridge_ageing"; then
+			ocf_log err "Invalid OCF_RESKEY_bridge_ageing: must be a decimal value (0 or greater)"
+			return 1
+		fi
+	fi
+
+	# OCF_RESKEY_stp_fd needs special handling as it can be 0 or greater
+	# but only when configured before OCF_RESKEY_stp.
+	# if enabled after OCF_RESKEY_stp with stp=true the value range is
+	# different. It is not clear from the man page or brctl documentation
+	# what the range is ahead of time.
+	if [ -n "$OCF_RESKEY_stp_fd" ]; then
+		if ! ocf_is_decimal "$OCF_RESKEY_stp_fd" || \
+		   [ "$OCF_RESKEY_stp_fd" -lt 0 ]; then
+			ocf_log err "Invalid OCF_RESKEY_stp_fd: must be a decimal value (0 or greater)"
+			return 1
+		fi
+	fi
+
+	if ocf_is_true "$OCF_RESKEY_stp"; then
+
+		if [ -n "$OCF_RESKEY_stp_bridgeprio" ]; then
+			if ! ocf_is_decimal "$OCF_RESKEY_stp_bridgeprio" || \
+			   [ "$OCF_RESKEY_stp_bridgeprio" -gt 65535 ]; then
+				ocf_log err "Invalid OCF_RESKEY_stp_bridgeprio: must be a decimal value between 0 and 65535 included"
+				return 1
+			fi
+		fi
+
+		if [ -n "$OCF_RESKEY_stp_hello" ]; then
+			if ! ocf_is_decimal "$OCF_RESKEY_stp_hello"; then
+				ocf_log err "Invalid OCF_RESKEY_stp_hello: must be a decimal value (0 or greater)"
+				return 1
+			fi
+		fi
+
+		if [ -n "$OCF_RESKEY_stp_maxage" ]; then
+			if ! ocf_is_decimal "$OCF_RESKEY_stp_maxage"; then
+				ocf_log err "Invalid OCF_RESKEY_stp_maxage: must be a decimal value (0 or greater)"
+				return 1
+			fi
+		fi
+
+		if [ -n "$OCF_RESKEY_stp_pathcost" ]; then
+			split_string $OCF_RESKEY_stp_pathcost | { while read iface cost; do
+					if ! iface_is_slave $iface; then
+						ocf_log err "Invalid OCF_RESKEY_stp_pathcost: $iface is not listed in OCF_RESKEY_bridge_slaves"
+						return 1
+					fi
+
+					if ! ocf_is_decimal $cost; then
+						ocf_log err "Invalid OCF_RESKEY_stp_pathcost: cost must be a decimal value (0 or great)"
+						return 1
+					fi
+				done
+			}
+		fi
+
+		if [ -n "$OCF_RESKEY_stp_portprio" ]; then
+			split_string $OCF_RESKEY_stp_portprio | { while read iface prio; do
+					if ! iface_is_slave $iface; then
+						ocf_log err "Invalid OCF_RESKEY_stp_portprio: $iface is not listed in OCF_RESKEY_bridge_slaves"
+						return 1
+					fi
+
+					if ! ocf_is_decimal $prio || \
+					   [ "$prio" -gt "63" ]; then
+						ocf_log err "Invalid OCF_RESKEY_stp_portprio: priority must be a decimal value between 0 and 63 included"
+						return 1
+					fi
+				done
+			}
+		fi
+
+	fi
+
+	if [ -n "$OCF_RESKEY_multicast_port_router" ]; then
+		split_string $OCF_RESKEY_multicast_port_router | { while read iface mcport; do
+				if ! iface_is_slave $iface; then
+					ocf_log err "Invalid OCF_RESKEY_multicast_port_router: $iface is not listed in OCF_RESKEY_bridge_slaves"
+					return 1
+				fi
+
+				if ! ocf_is_decimal $mcport || \
+				   [ "$mcport" -gt "1" ]; then
+					ocf_log err "Invalid OCF_RESKEY_multicast_port_router: valuer must be 0 (disabled) or 1 (enabled)"
+					return 1
+				fi
+			done
+		}
+	fi
+
+	return 0
+}
+
+bridge_check() {
+	if [ -e "/sys/class/net/$OCF_RESKEY_bridge_name" ]; then
+		if [ ! -e "$HA_RSCTMP/iface-bridge.$OCF_RESKEY_bridge_name" ]; then
+			return $OCF_ERR_GENERIC
+		fi
+	else
+		if [ -e "$HA_RSCTMP/iface-bridge.$OCF_RESKEY_bridge_name" ]; then
+			error="$(rm -f "$HA_RSCTMP/iface-bridge.$OCF_RESKEY_bridge_name" 2>&1)"
+			if [ "$?" != "0" ]; then
+				ocf_log err "Unable to remove stale lock file for bridge $OCF_RESKEY_bridge_name: $error"
+				return $OCF_ERR_GENERIC
+			fi
+		fi
+		return $OCF_NOT_RUNNING
+	fi
+
+	# we check if all slaves are still part of the bridge
+	for slave in $OCF_RESKEY_bridge_slaves; do
+		if [ ! -e "/sys/class/net/$OCF_RESKEY_bridge_name/brif/$slave" ]; then
+			ocf_log err "Interface $slave is not part of the bridge $OCF_RESKEY_bridge_name"
+			return $OCF_ERR_GENERIC
+		fi
+		if ! iface_is_up $slave; then
+			ocf_log err "Interface $slave of the bridge $OCF_RESKEY_bridge_name is administratively down"
+			return $OCF_ERR_GENERIC
+		fi
+	done
+
+	# check if bridge is still "UP"
+	# is there a cleaner way?
+
+	if ! iface_is_up $OCF_RESKEY_bridge_name; then
+		ocf_log err "Bridge $OCF_RESKEY_bridge_name is administratively down"
+		return $OCF_ERR_GENERIC
+	fi
+
+	if ! iface_lower_is_up $OCF_RESKEY_bridge_name; then
+		ocf_log err "Bridge $OCF_RESKEY_bridge_name has no active link-layer slaves"
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+# we need a simpler stop version to clean after us if start fails
+# without involving any error checking
+# rolling back in case of failure is otherwise complex
+
+bridge_force_stop() {
+	$IP2UTIL link set dev "$OCF_RESKEY_bridge_name" down 2>&1
+	for slave in $OCF_RESKEY_bridge_slaves; do
+		$IP2UTIL link set dev "$slave" down 2>&1
+	done
+	$BRCTL delbr "$OCF_RESKEY_bridge_name" 2>&1
+	rm -f "$HA_RSCTMP/iface-bridge.$OCF_RESKEY_bridge_name" 2>&1
+}
+
+bridge_start() {
+	# check if the bridge already exists
+	bridge_check
+	ret=$?
+	if [ "$ret" != "$OCF_NOT_RUNNING" ]; then
+		return $ret
+	fi
+
+	# create the bridge
+	error="$($BRCTL addbr "$OCF_RESKEY_bridge_name" 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to create bridge $OCF_RESKEY_bridge_name: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	# add slaves if configured
+	for slave in $OCF_RESKEY_bridge_slaves; do
+		error="$($BRCTL addif "$OCF_RESKEY_bridge_name" "$slave" 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to add interface $slave to bridge $OCF_RESKEY_bridge_name: $error"
+			return $OCF_ERR_GENERIC
+		fi
+	done
+
+	# set haripin forward mode
+	for hairpin in $OCF_RESKEY_port_hairpin; do
+		error="$($BRCTL hairpin "$OCF_RESKEY_bridge_name" "$hairpin" on 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to set hairpin on for interface $hairpin to bridge $OCF_RESKEY_bridge_name: $error"
+			return $OCF_ERR_GENERIC
+		fi
+	done
+
+	# set bridge ageing
+	if [ -n "$OCF_RESKEY_bridge_ageing" ]; then
+		error="$($BRCTL setageing "$OCF_RESKEY_bridge_name" "$OCF_RESKEY_bridge_ageing" 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to set bridge $OCF_RESKEY_bridge_name ageing to $OCF_RESKEY_bridge_ageing: $error"
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+
+	# OCF_RESKEY_stp_fd needs special handling as it can be 0 or greater
+	# but only when configured before OCF_RESKEY_stp.
+	# if enabled after OCF_RESKEY_stp with stp=true the value range is
+	# different. It is not clear from the man page or brctl documentation
+	# what the range is ahead of time.
+	if [ -n "$OCF_RESKEY_stp_fd" ]; then
+		error="$($BRCTL setfd "$OCF_RESKEY_bridge_name" "$OCF_RESKEY_stp_fd" 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to set bridge forward delay $OCF_RESKEY_stp_fd on bridge $OCF_RESKEY_bridge_name : $error"
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+
+	# enable/disable spanning tree protocol
+	if ocf_is_true "$OCF_RESKEY_stp"; then
+		error="$($BRCTL stp "$OCF_RESKEY_bridge_name" on 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to enable STP on bridge $OCF_RESKEY_bridge_name : $error"
+			return $OCF_ERR_GENERIC
+		fi
+
+		# set bridge priority
+		if [ -n "$OCF_RESKEY_stp_bridgeprio" ]; then
+			error="$($BRCTL setbridgeprio "$OCF_RESKEY_bridge_name" "$OCF_RESKEY_stp_bridgeprio" 2>&1)"
+			if [ "$?" != "0" ]; then
+				ocf_log err "Unable to set bridge priority $OCF_RESKEY_stp_bridgeprio on bridge $OCF_RESKEY_bridge_name : $error"
+				return $OCF_ERR_GENERIC
+			fi
+		fi
+
+		# set hello timer
+		if [ -n "$OCF_RESKEY_stp_hello" ]; then
+			error="$($BRCTL sethello "$OCF_RESKEY_bridge_name" "$OCF_RESKEY_stp_hello" 2>&1)"
+			if [ "$?" != "0" ]; then
+				ocf_log err "Unable to set bridge hello timer $OCF_RESKEY_stp_hello on bridge $OCF_RESKEY_bridge_name : $error"
+				return $OCF_ERR_GENERIC
+			fi
+		fi
+
+
+		# set max age
+		if [ -n "$OCF_RESKEY_stp_maxage" ]; then
+			error="$($BRCTL setmaxage "$OCF_RESKEY_bridge_name" "$OCF_RESKEY_stp_maxage" 2>&1)"
+			if [ "$?" != "0" ]; then
+				ocf_log err "Unable to set bridge max age $OCF_RESKEY_stp_maxage on bridge $OCF_RESKEY_bridge_name : $error"
+				return $OCF_ERR_GENERIC
+			fi
+		fi
+
+		# set path cost per port
+		if [ -n "$OCF_RESKEY_stp_pathcost" ]; then
+			split_string $OCF_RESKEY_stp_pathcost | { while read iface cost; do
+				error="$($BRCTL setpathcost "$OCF_RESKEY_bridge_name" "$iface" "$cost" 2>&1)"
+				if [ "$?" != "0" ]; then
+					ocf_log err "Unable to set pathcost $cost for interface $iface on bridge $OCF_RESKEY_bridge_name : $error"
+					return $OCF_ERR_GENERIC
+				fi
+				done
+			}
+		fi
+
+		# set port priority per port
+		if [ -n "$OCF_RESKEY_stp_portprio" ]; then
+			split_string $OCF_RESKEY_stp_portprio | { while read iface prio; do
+				error="$($BRCTL setportprio "$OCF_RESKEY_bridge_name" "$iface" "$prio" 2>&1)"
+				if [ "$?" != "0" ]; then
+					ocf_log err "Unable to set portprio $prio for interface $iface on bridge $OCF_RESKEY_bridge_name : $error"
+					return $OCF_ERR_GENERIC
+				fi
+				done
+			}
+		fi
+	else
+		# stp off is default via brctl/kernel interface but it
+		# is best to force it since we don't know if default
+		# has changed across kernel releases
+		error="$($BRCTL stp "$OCF_RESKEY_bridge_name" off 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to disable STP on bridge $OCF_RESKEY_bridge_name : $error"
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+
+	# set slaves up
+	for slave in $OCF_RESKEY_bridge_slaves; do
+		error="$($IP2UTIL link set dev "$slave" up 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to set slave $slave for bridge $OCF_RESKEY_bridge_name up: $error"
+			return $OCF_ERR_GENERIC
+		fi
+	done
+
+	# set the bridge up
+	error="$($IP2UTIL link set dev "$OCF_RESKEY_bridge_name" up 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to set bridge $OCF_RESKEY_bridge_name up: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	# multicast operations can only be executed after the bridge is up
+	# and configured.
+
+	# enable/disable multicast router
+	if ocf_is_true "$OCF_RESKEY_multicast_router"; then
+		mcrouter=1
+	else
+		mcrouter=0
+	fi
+	if [ -e "/sys/class/net/$OCF_RESKEY_bridge_name/bridge/multicast_router" ]; then
+		error="$(echo $mcrouter > /sys/class/net/$OCF_RESKEY_bridge_name/bridge/multicast_router 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to set OCF_RESKEY_multicast_router for bridge $OCF_RESKEY_bridge_name: $error"
+			return $OCF_ERR_GENERIC
+		fi
+	else
+		ocf_log warn "Unable to set multicast router on bridge $OCF_RESKEY_bridge_name because kernel does not support it"
+	fi
+
+	# enable/disable multicast snoopint
+	if ocf_is_true "$OCF_RESKEY_multicast_snooping"; then
+		mcsnooping=1
+	else
+		mcsnooping=0
+	fi
+	if [ -e "/sys/class/net/$OCF_RESKEY_bridge_name/bridge/multicast_snooping" ]; then
+		error="$(echo $mcsnooping > /sys/class/net/$OCF_RESKEY_bridge_name/bridge/multicast_snooping 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to set OCF_RESKEY_multicast_snooping for bridge $OCF_RESKEY_bridge_name: $error"
+			return $OCF_ERR_GENERIC
+		fi
+	else
+		ocf_log warn "Unable to set multicast snooping on bridge $OCF_RESKEY_bridge_name because kernel does not support it"
+	fi
+
+	# enable/disable multicast querier
+	if ocf_is_true "$OCF_RESKEY_multicast_querier"; then
+		mcquerier=1
+	else
+		mcquerier=0
+	fi
+	if [ -e "/sys/class/net/$OCF_RESKEY_bridge_name/bridge/multicast_querier" ]; then
+		error="$(echo $mcquerier > /sys/class/net/$OCF_RESKEY_bridge_name/bridge/multicast_querier 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to set OCF_RESKEY_multicast_querier for bridge $OCF_RESKEY_bridge_name: $error"
+			return $OCF_ERR_GENERIC
+		fi
+	else
+		ocf_log warn "Unable to set multicast querier on bridge $OCF_RESKEY_bridge_name because kernel does not support it"
+	fi
+
+	# set multicast router per port
+	if [ -n "$OCF_RESKEY_multicast_port_router" ]; then
+		split_string $OCF_RESKEY_multicast_port_router | { while read iface mcport; do
+			if [ -e "/sys/class/net/$iface/brport/multicast_router" ]; then
+				error="$(echo $mcport > /sys/class/net/$iface/brport/multicast_router 2>&1)"
+				if [ "$?" != "0" ]; then
+					ocf_log err "Unable to set OCF_RESKEY_multicast_port_router $mcport for interface $iface on bridge $OCF_RESKEY_bridge_name : $error"
+					return $OCF_ERR_GENERIC
+				fi
+			else
+				ocf_log warn "Unable to set multicast port router on bridge $OCF_RESKEY_bridge_name because kernel does not support it"
+			fi
+			done
+		}
+	fi
+
+	error="$(touch "$HA_RSCTMP/iface-bridge.$OCF_RESKEY_bridge_name")"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to write lock file for bridge $OCF_RESKEY_bridge_name: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+bridge_stop() {
+	bridge_check
+	ret=$?
+	if [ "$ret" = "$OCF_NOT_RUNNING" ]; then
+		return $OCF_SUCCESS
+	fi
+	if [ "$ret" != "$OCF_SUCCESS" ]; then
+		return $ret
+	fi
+
+	# set bridge down
+	error="$($IP2UTIL link set dev "$OCF_RESKEY_bridge_name" down 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to set bridge $OCF_RESKEY_bridge_name down: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	# set slaves down
+	for slave in $OCF_RESKEY_bridge_slaves; do
+		error="$($IP2UTIL link set dev "$slave" down 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to set slave $slave for bridge $OCF_RESKEY_bridge_name down: $error"
+			return $OCF_ERR_GENERIC
+		fi
+	done
+
+	# delete bridge
+	error="$($BRCTL delbr "$OCF_RESKEY_bridge_name" 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to delete bridge $OCF_RESKEY_bridge_name: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	error="$(rm -f "$HA_RSCTMP/iface-bridge.$OCF_RESKEY_bridge_name" 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to remove lock file for bridge $OCF_RESKEY_bridge_name: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+case $__OCF_ACTION in
+	meta-data)
+		bridge_meta_data
+		exit $OCF_SUCCESS
+	;;
+	usage|help)
+		bridge_usage
+		exit $OCF_SUCCESS
+	;;
+esac
+
+if [ ! -d "$HA_RSCTMP" ]; then
+	ocf_log debug "$HA_RSCTMP not found, we are probably being executed manually"
+	mkdir -p "$HA_RSCTMP"
+fi
+
+if [ -n "$__OCF_ACTION" ] && ! bridge_validate; then
+	exit $OCF_ERR_CONFIGURED
+fi
+
+case $__OCF_ACTION in
+	start|stop)
+		if ! ocf_is_root; then
+			ocf_log err "You must be root for $__OCF_ACTION operation."
+			exit $OCF_ERR_PERM
+		fi
+	;;
+esac
+
+case $__OCF_ACTION in
+	start)
+		bridge_start
+		ret=$?
+		if [ "$ret" != "$OCF_SUCCESS" ]; then
+			bridge_force_stop
+		fi
+		exit $ret
+	;;
+	stop)
+		bridge_stop
+		exit $?
+	;;
+	status|monitor)
+		bridge_check
+		exit $?
+	;;
+	validate-all)
+		# bridge_validate above does the trick
+	;;
+	*)
+		bridge_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+# vi:sw=4:ts=8:
diff --git a/heartbeat/iface-vlan b/heartbeat/iface-vlan
new file mode 100755
index 0000000..bc8583c
--- /dev/null
+++ b/heartbeat/iface-vlan
@@ -0,0 +1,475 @@
+#!/bin/sh
+#
+#       OCF Resource Agent compliant iface-vlan script.
+#
+#       Implements network VLAN interface management
+#
+# Copyright (C) 2013 Red Hat, Inc.  All rights reserved.
+# Author: Fabio M. Di Nitto <fdinitto at redhat.com>
+#
+# 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.
+#
+#
+
+# TODO:
+#
+#	OCF parameters are as below
+#       OCF_RESKEY_vlan_interface
+#       OCF_RESKEY_vlan_id
+#	OCF_RESKEY_vlan_name
+#       OCF_RESKEY_vlan_reorder_hdr
+#       OCF_RESKEY_vlan_gvrp
+#       OCF_RESKEY_vlan_mvrp
+#       OCF_RESKEY_vlan_loose_binding
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+OCF_RESKEY_vlan_reorder_hdr_default=1
+OCF_RESKEY_vlan_gvrp_default=0
+OCF_RESKEY_vlan_mvrp_default=0
+OCF_RESKEY_vlan_loose_binding_default=0
+OCF_RESKEY_vlan_name_default=${OCF_RESKEY_vlan_interface}.${OCF_RESKEY_vlan_id}
+
+: ${OCF_RESKEY_vlan_name=${OCF_RESKEY_vlan_name_default}}
+: ${OCF_RESKEY_vlan_reorder_hdr=${OCF_RESKEY_vlan_reorder_hdr_default}}
+: ${OCF_RESKEY_vlan_gvrp=${OCF_RESKEY_vlan_gvrp_default}}
+
+# don't set defaults for mvrp or loose binding since both
+# are rather new kernel features and they might not be supported
+#: ${OCF_RESKEY_vlan_mvrp=${OCF_RESKEY_vlan_mvrp_default}}
+#: ${OCF_RESKEY_vlan_loose_binding=${OCF_RESKEY_vlan_loose_binding_default}}
+
+#######################################################################
+
+vlan_usage() {
+	cat <<END
+usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+vlan_meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="iface-vlan">
+  <version>1.0</version>
+
+  <longdesc lang="en">
+    This resource manages VLAN network interfaces.
+    It can add, remove, configure VLANs.
+  </longdesc>
+
+  <shortdesc lang="en">
+    Manages VLAN network interfaces.
+  </shortdesc>
+
+  <parameters>
+    <parameter name="vlan_interface" unique="1" required="1">
+      <longdesc lang="en">
+        Define the interface where VLAN should be attached.
+      </longdesc>
+      <shortdesc lang="en">
+        Network interface.
+      </shortdesc>
+      <content type="string"/>
+    </parameter>
+
+    <parameter name="vlan_id" unique="1" required="1">
+      <longdesc lang="en">
+        Define the VLAN ID. It has to be a value between 0 and 4094.
+      </longdesc>
+      <shortdesc lang="en">
+        Define the VLAN ID.
+      </shortdesc>
+      <content type="integer"/>
+    </parameter>
+
+    <parameter name="vlan_name" unique="1">
+      <longdesc lang="en">
+        Define the name of the VLAN interface (max 15 charaters).
+      </longdesc>
+      <shortdesc lang="en">
+        Name of the VLAN.
+      </shortdesc>
+      <content type="string" default="vlan_interface.vlan.id" />
+    </parameter>
+
+    <parameter name="vlan_reorder_hdr" unique="0">
+      <longdesc lang="en">
+        Enable or disable header reordering.
+      </longdesc>
+      <shortdesc lang="en">
+        Enable or disable header reordering.
+      </shortdesc>
+      <content type="boolean" default="${OCF_RESKEY_vlan_reorder_hdr_default}"/>
+    </parameter>
+
+    <parameter name="vlan_gvrp" unique="0">
+      <longdesc lang="en">
+        Enable or disable GARP VLAN registration protocol.
+      </longdesc>
+      <shortdesc lang="en">
+        Enable or disable gvrp.
+      </shortdesc>
+      <content type="boolean" default="${OCF_RESKEY_vlan_gvrp_default}"/>
+    </parameter>
+
+    <parameter name="vlan_mvrp" unique="0">
+      <longdesc lang="en">
+        Enable or disable Multiple VLAN Registration Protocol.
+        Please note that most distributions do not ship a version of iproute2
+        that supports mvrp yet, even if the kernel has support for it.
+        Check output of $IPADDR2 link add type vlan --help in the FLAG
+        section to verify if mvrp support is available.
+      </longdesc>
+      <shortdesc lang="en">
+        Enable or disable mvrp.
+      </shortdesc>
+      <content type="boolean" default="${OCF_RESKEY_vlan_mvrp_default}"/>
+    </parameter>
+
+    <parameter name="vlan_loose_binding" unique="0">
+      <longdesc lang="en">
+        Enable or disable VLAN loose bind. By default the VLAN interface
+        admin status (UP/DOWN) follows the underneath inteface status.
+        Enabling loose bind allows the VLAN to disconnect from the
+        interface status. Be very careful that enabling loose binding
+        could invalidate this agent monitor operations.
+        Please note that most distributions do not ship a version of iproute2
+        that supports loose_binding yet, even if the kernel has support for it.
+        Check output of $IPADDR2 link add type vlan --help in the FLAG
+        section to verify if loose_binding support is available.
+      </longdesc>
+      <shortdesc lang="en">
+        Enable or disable loose binding.
+      </shortdesc>
+      <content type="boolean" default="${OCF_RESKEY_vlan_loose_binding_default}"/>
+    </parameter>
+  </parameters>
+
+  <actions>
+    <action name="start"        timeout="30s" />
+    <action name="stop"         timeout="20s" />
+    <action name="status"       timeout="20s" depth="0" interval="10s" />
+    <action name="monitor"      timeout="20s" depth="0" interval="10s" />
+    <action name="meta-data"    timeout="5s" />
+    <action name="validate-all" timeout="20s" />
+  </actions>
+</resource-agent>
+END
+}
+
+# check if the interface is admin up/down
+
+iface_is_up() {
+	if ! $IP2UTIL -o link show $1 | \
+	    sed -e 's#.*<##g' -e 's#>.*##' -e 's#LOWER_UP##g' | \
+	    grep -q UP; then
+		return 1
+	fi
+	return 0
+}
+
+# check if the slaves have link layer up/down
+# see kernel network documentation on meaning of LOWER_UP flag
+# for more in depth explanation on how it works
+# NOTE: this check is not reliable in virt environment
+# since interfaces are always LOWER_UP. There is no way
+# from the guest to know if the host has disconnected somehow
+
+iface_lower_is_up() {
+	if ! $IP2UTIL -o link show $1 | \
+	    grep -q LOWER_UP; then
+		return 1
+	fi
+	return 0
+}
+
+vlan_validate() {
+	check_binary $IP2UTIL
+
+	if [ -z "$OCF_RESKEY_vlan_interface" ]; then
+		ocf_log err "Invalid OCF_RESKEY_vlan_interface: value cannot be empty"
+		return 1
+	fi
+
+	# the echo .. is the equivalent of strlen in bash
+	#
+	# /usr/include/linux/if.h:#define IFNAMSIZ        16
+	# needs to include 0 byte end string
+
+	if [ "${#OCF_RESKEY_vlan_interface}" -gt 15 ]; then
+		ocf_log err "Invalid OCF_RESKEY_vlan_interface: name is too long"
+		return 1
+	fi
+
+	if [ ! -d "/sys/class/net" ]; then
+		ocf_log err "Unable to find sysfs network class in /sys"
+		return 1
+	fi
+
+	if [ ! -e "/sys/class/net/$OCF_RESKEY_vlan_interface" ]; then
+		ocf_log err "Invalid OCF_RESKEY_vlan_interface: $OCF_RESKEY_vlan_interface does not exists"
+		return 1
+	fi
+
+	if [ -z "$OCF_RESKEY_vlan_id" ]; then
+		ocf_log err "Invalid OCF_RESKEY_vlan_id: value cannot be empty"
+		return 1
+	fi
+	if ! ocf_is_decimal "$OCF_RESKEY_vlan_id" || \
+	   [ "$OCF_RESKEY_vlan_id" -gt "4094" ]; then
+		ocf_log err "Invalid OCF_RESKEY_vlan_id: must be a decimal value (0 to 4094 included)"
+		return 1
+	fi
+
+	if [ "${#OCF_RESKEY_vlan_name}" -gt 15 ]; then
+		ocf_log err "Invalid OCF_RESKEY_vlan_name: name is too long"
+		return 1
+	fi
+
+	return 0
+}
+
+vlan_check() {
+	if [ -e "/sys/class/net/$OCF_RESKEY_vlan_name" ]; then
+		if [ ! -e "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" ]; then
+			return $OCF_ERR_GENERIC
+		fi
+	else
+		if [ -e "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" ]; then
+			error="$(rm -f "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" 2>&1)"
+			if [ "$?" != "0" ]; then
+				ocf_log err "Unable to remove stale lock file for vlan $OCF_RESKEY_vlan_name: $error"
+				return $OCF_ERR_GENERIC
+			fi
+		fi
+		return $OCF_NOT_RUNNING
+	fi
+
+	if ! iface_is_up $OCF_RESKEY_vlan_interface; then
+		if ocf_is_true "$OCF_RESKEY_vlan_loose_binding"; then
+			ocf_log warn "Interface $OCF_RESKEY_vlan_interface is administratively down"
+		else
+			ocf_log err "Interface $OCF_RESKEY_vlan_interface is administratively down"
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+
+	if ! iface_is_up $OCF_RESKEY_vlan_name; then
+		ocf_log err "VLAN $OCF_RESKEY_vlan_name is administratively down"
+		return $OCF_ERR_GENERIC
+	fi
+
+	if ! iface_lower_is_up $OCF_RESKEY_vlan_name; then
+		ocf_log err "VLAN $OCF_RESKEY_vlan_name has no active link-layer"
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+# we need a simpler stop version to clean after us if start fails
+# without involving any error checking
+# rolling back in case of failure is otherwise complex
+
+vlan_force_stop() {
+	$IP2UTIL link delete "$OCF_RESKEY_vlan_name" >/dev/null 2>&1
+	rm -f "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" 2>&1
+}
+
+vlan_start() {
+	# check if the vlan already exists
+	vlan_check
+	ret=$?
+	if [ "$ret" != "$OCF_NOT_RUNNING" ]; then
+		return $ret
+	fi
+
+	# make sure kernel module is loaded
+	if [ ! -e /proc/net/vlan ]; then
+		error="$(modprobe 8021q 2>&1)"
+		if [ "$?" != "0" ]; then
+			ocf_log err "Unable to load kernel 8021q driver: $error"
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+
+	# generate options
+	VLANOPTS=""
+
+	if [ -n "$OCF_RESKEY_vlan_reorder_hdr" ]; then
+		if ocf_is_true "$OCF_RESKEY_vlan_reorder_hdr"; then
+			VLANOPTS="reorder_hdr on"
+		else
+			VLANOPTS="reorder_hdr off"
+		fi
+	fi
+
+	if [ -n "$OCF_RESKEY_vlan_gvrp" ]; then
+		if ocf_is_true "$OCF_RESKEY_vlan_gvrp"; then
+			VLANOPTS="$VLANOPTS gvrp on"
+		else
+			VLANOPTS="$VLANOPTS gvrp off"
+		fi
+	fi
+
+	if [ -n "$OCF_RESKEY_vlan_mvrp" ]; then
+		if ocf_is_true "$OCF_RESKEY_vlan_mvrp"; then
+			VLANOPTS="$VLANOPTS mvrp on"
+		else
+			VLANOPTS="$VLANOPTS mvrp off"
+		fi
+	fi
+
+	if [ -n "$OCF_RESKEY_vlan_loose_binding" ]; then
+		if ocf_is_true "$OCF_RESKEY_vlan_loose_binding"; then
+			VLANOPTS="$VLANOPTS loose_binding on"
+		else
+			VLANOPTS="$VLANOPTS loose_binding off"
+		fi
+	fi
+
+	# create the VLAN
+	error="$($IP2UTIL link add link "$OCF_RESKEY_vlan_interface" name "$OCF_RESKEY_vlan_name" type vlan id "$OCF_RESKEY_vlan_id" $VLANOPTS 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to create VLAN $OCF_RESKEY_vlan_name: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	# set the interface up
+	error="$($IP2UTIL link set dev "$OCF_RESKEY_vlan_interface" up 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to set VLAN $OCF_RESKEY_vlan_interface up: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	# set the vlan up
+	error="$($IP2UTIL link set dev "$OCF_RESKEY_vlan_name" up 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to set VLAN $OCF_RESKEY_vlan_name up: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	error="$(touch "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to create lock file for VLAN $OCF_RESKEY_vlan_name: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+vlan_stop() {
+	vlan_check
+	ret=$?
+	if [ "$ret" = "$OCF_NOT_RUNNING" ]; then
+		return $OCF_SUCCESS
+	fi
+	if [ "$ret" != "$OCF_SUCCESS" ]; then
+		return $ret
+	fi
+
+	# set vlan down
+	error="$($IP2UTIL link set dev "$OCF_RESKEY_vlan_name" down 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to set VLAN $OCF_RESKEY_vlan_name down: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	# delete vlan
+	error="$($IP2UTIL link delete "$OCF_RESKEY_vlan_name" 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to delete VLAN $OCF_RESKEY_vlan_name: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	error="$(rm -f "$HA_RSCTMP/iface-vlan.$OCF_RESKEY_vlan_name" 2>&1)"
+	if [ "$?" != "0" ]; then
+		ocf_log err "Unable to remove lock file for VLAN $OCF_RESKEY_vlan_name: $error"
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+case $__OCF_ACTION in
+	meta-data)
+		vlan_meta_data
+		exit $OCF_SUCCESS
+	;;
+	usage|help)
+		vlan_usage
+		exit $OCF_SUCCESS
+	;;
+esac
+
+if [ ! -d "$HA_RSCTMP" ]; then
+	ocf_log debug "$HA_RSCTMP not found, we are probably being executed manually"
+	mkdir -p "$HA_RSCTMP"
+fi
+
+if [ -n "$__OCF_ACTION" ] && ! vlan_validate; then
+	exit $OCF_ERR_CONFIGURED
+fi
+
+case $__OCF_ACTION in
+	start|stop)
+		if ! ocf_is_root; then
+			ocf_log err "You must be root for $__OCF_ACTION operation."
+			exit $OCF_ERR_PERM
+		fi
+	;;
+esac
+
+case $__OCF_ACTION in
+	start)
+		vlan_start
+		ret=$?
+		if [ "$ret" != "$OCF_SUCCESS" ]; then
+			vlan_force_stop
+		fi
+		exit $ret
+	;;
+	stop)
+		vlan_stop
+		exit $?
+	;;
+	status|monitor)
+		vlan_check
+		exit $?
+	;;
+	validate-all)
+		# vlan_validate above does the trick
+	;;
+	*)
+		vlan_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+# vi:sw=4:ts=8:
diff --git a/heartbeat/iscsi b/heartbeat/iscsi
new file mode 100755
index 0000000..de3f4c0
--- /dev/null
+++ b/heartbeat/iscsi
@@ -0,0 +1,503 @@
+#!/bin/sh
+#
+# iSCSI OCF resource agent
+# Description: manage iSCSI disks (add/remove) using open-iscsi
+#
+# Copyright Dejan Muhamedagic <dejan at suse.de>
+# (C) 2007 Novell Inc. 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.
+#
+# See usage() and meta_data() below for more details...
+#
+# OCF instance parameters:
+#	OCF_RESKEY_portal: the iSCSI portal address or host name (required)
+#	OCF_RESKEY_target: the iSCSI target (required)
+#	OCF_RESKEY_iscsiadm: iscsiadm program path (optional)
+#	OCF_RESKEY_discovery_type: discovery type (optional; default: sendtargets)
+#	OCF_RESKEY_try_recovery: wait for iSCSI recovery in monitor (optional; default: false)
+#
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+OCF_RESKEY_udev_default="yes"
+OCF_RESKEY_iscsiadm_default="iscsiadm"
+OCF_RESKEY_discovery_type_default="sendtargets"
+OCF_RESKEY_try_recovery_default="false"
+
+: ${OCF_RESKEY_udev=${OCF_RESKEY_udev_default}}
+: ${OCF_RESKEY_iscsiadm=${OCF_RESKEY_iscsiadm_default}}
+: ${OCF_RESKEY_discovery_type=${OCF_RESKEY_discovery_type_default}}
+
+usage() {
+  methods=`iscsi_methods`
+  methods=`echo $methods | tr ' ' '|'`
+  cat <<EOF
+	usage: $0 {$methods}
+
+	$0 manages an iSCSI target
+
+	The 'start' operation starts (adds) the iSCSI target.
+	The 'stop' operation stops (removes) the iSCSI target.
+	The 'status' operation reports whether the iSCSI target is connected
+	The 'monitor' operation reports whether the iSCSI target is connected
+	The 'validate-all' operation reports whether the parameters are valid
+	The 'methods' operation reports on the methods $0 supports
+
+EOF
+}
+
+meta_data() {
+	cat <<EOF
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="iscsi">
+<version>1.0</version>
+
+<longdesc lang="en">
+OCF Resource Agent for iSCSI. Add (start) or remove (stop) iSCSI
+targets.
+</longdesc>
+<shortdesc lang="en">Manages a local iSCSI initiator and its connections to iSCSI targets</shortdesc>
+
+<parameters>
+
+<parameter name="portal" unique="0" required="1">
+<longdesc lang="en">
+The iSCSI portal address in the form: {ip_address|hostname}[":"port]
+</longdesc>
+<shortdesc lang="en">Portal address</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="target" unique="1" required="1">
+<longdesc lang="en">
+The iSCSI target IQN.
+</longdesc>
+<shortdesc lang="en">Target IQN</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="discovery_type" unique="0" required="0">
+<longdesc lang="en">
+Target discovery type. Check the open-iscsi documentation for
+supported discovery types.
+</longdesc>
+<shortdesc lang="en">Target discovery type</shortdesc>
+<content type="string" default="${OCF_RESKEY_discovery_type_default}" />
+</parameter>
+
+<parameter name="iscsiadm" unique="0" required="0">
+<longdesc lang="en">
+open-iscsi administration utility binary.
+</longdesc>
+<shortdesc lang="en">iscsiadm binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_iscsiadm_default}" />
+</parameter>
+
+<parameter name="udev" unique="0" required="0">
+<longdesc lang="en">
+If the next resource depends on the udev creating a device then
+we wait until it is finished. On a normally loaded host this
+should be done quickly, but you may be unlucky. If you are not
+using udev set this to "no", otherwise we will spin in a loop
+until a timeout occurs.
+</longdesc>
+<shortdesc lang="en">udev</shortdesc>
+<content type="string" default="${OCF_RESKEY_udev_default}" />
+</parameter>
+
+<parameter name="try_recovery" unique="0" required="0">
+<longdesc lang="en">
+If the iSCSI session exists but is currently inactive/broken,
+which is most probably due to network problems, the iSCSI layer
+will try to recover. If this parameter is set to true, we'll wait
+for the recovery to succeed. In that case the monitor operation
+can only time out so you should set the monitor op timeout
+attribute appropriately.
+</longdesc>
+<shortdesc lang="en">On error wait for iSCSI recovery in monitor</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_try_recovery_default}" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="120" />
+<action name="stop" timeout="120" />
+<action name="status" timeout="30" />
+<action name="monitor" depth="0" timeout="30" interval="120" />
+<action name="validate-all" timeout="5" />
+<action name="methods" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+EOF
+}
+
+iscsi_methods() {
+  cat <<EOF
+	start
+	stop
+	status
+	monitor
+	validate-all
+	methods
+	meta-data
+	usage
+EOF
+}
+
+#
+# open-iscsi interface
+#
+
+is_iscsid_running() {
+	ps -e -o cmd | grep -qs '[i]scsid'
+}
+open_iscsi_setup() {
+	discovery=open_iscsi_discovery
+	add_disk=open_iscsi_add
+	remove_disk=open_iscsi_remove
+	disk_status=open_iscsi_status
+	iscsiadm=${OCF_RESKEY_iscsiadm}
+
+	have_binary ${iscsiadm} ||
+		return 3
+	if is_iscsid_running; then
+		return 0
+	elif grep -qs '^iscsid.startup' /etc/iscsi/iscsid.conf; then
+		# apparently on RedHat (perhaps elsewhere?), there is a
+		# kind of iscsid autostart once root invokes some
+		# open_iscsi command; the iscsid.startup hook should take
+		# care of it; reported by m.richardson at ed.ac.uk (see also
+		# the discussion at the linux-ha-dev ML)
+		return 1
+	else
+		ocf_log err "iscsid not running; please start open-iscsi utilities"
+		return 2
+	fi
+}
+
+#
+# discovery return codes:
+#   0: ok (variable portal set)
+#   1: target not found
+#   2: target found but can't connect it unambigously
+#   3: iscsiadm returned error
+#
+# open-iscsi >= "2.0-872" changed discovery semantics
+# see http://www.mail-archive.com/open-iscsi@googlegroups.com/msg04883.html
+# there's a new discoverydb command which should be used instead discovery
+ 
+open_iscsi_discovery() {
+	local output
+	local discovery_variant="discovery"
+	local options=""
+	local cmd
+	local version=`$iscsiadm --version | awk '{print $3}'`
+
+	ocf_version_cmp "$version" "2.0-871"
+	if [ $? -eq 2 ]; then # newer than 2.0-871?
+		discovery_variant="discoverydb"
+		[ "$discovery_type" = "sendtargets" ] &&
+			options="-D"
+	fi
+	cmd="$iscsiadm -m $discovery_variant -p $OCF_RESKEY_portal -t $discovery_type $options"
+	output=`$cmd`
+	if [ $? -ne 0 -o x = "x$output" ]; then
+		[ x != "x$output" ] && {
+			ocf_log err "$cmd FAILED"
+			echo "$output"
+		}
+		return 3
+	fi
+	PORTAL=`echo "$output" |
+		awk -v target="$OCF_RESKEY_target" '
+		$NF==target{
+			if( NF==3 ) portal=$2; # sles compat mode
+			else portal=$1;
+			sub(",.*","",portal);
+			print portal;
+		}'`
+
+	case `echo "$PORTAL" | wc -w` in
+	0) #target not found
+		echo "$output"
+		ocf_log err "target $OCF_RESKEY_target not found at portal $OCF_RESKEY_portal"
+		return 1
+	;;
+	1) #we're ok
+		return 0
+	;;
+	*) # handle multihome hosts reporting multiple portals
+		for p in $PORTAL; do
+			if [ "$OCF_RESKEY_portal" = "$p" ]; then
+				PORTAL="$OCF_RESKEY_portal"
+				return 0
+			fi
+		done
+		echo "$output"
+		ocf_log err "sorry, can't handle multihomed hosts unless you specify the portal exactly"
+		return 2
+	;;
+	esac
+}
+open_iscsi_add() {
+	$iscsiadm -m node -p $1 -T $2 -l
+}
+open_iscsi_get_session_id() {
+	local target="$1"
+	$iscsiadm -m session 2>/dev/null | grep "$target$" |
+		awk '{print $2}' | tr -d '[]'
+}
+open_iscsi_remove() {
+	local target="$1"
+	local session_id
+	session_id=`open_iscsi_get_session_id "$target"`
+	if [ "$session_id" ]; then
+		$iscsiadm -m session -r $session_id -u
+	else
+		ocf_log err "cannot find session id for target $target"
+		return 1
+	fi
+}
+open_iscsi_status() {
+	local target="$1"
+	local session_id conn_state outp
+	local prev_state
+	local recov
+
+	recov=${2:-$OCF_RESKEY_try_recovery}
+	session_id=`open_iscsi_get_session_id "$target"`
+	prev_state=""
+	[ -z "$session_id" ] &&
+		return 1
+	while :; do
+		outp=`$iscsiadm -m session -r $session_id -P 1` ||
+			return 2
+		conn_state=`echo "$outp" | sed -n '/Connection State/s/.*: //p'`
+		# some drivers don't return connection state, in that case
+		# we'll assume that we're still connected
+		case "$conn_state" in
+			"LOGGED IN")
+				[ -n "$msg_logged" ] &&
+					ocf_log info "connection state $conn_state. Session restored."
+				return 0;;
+			"Unknown"|"") # this is also probably OK
+				[ -n "$msg_logged" ] &&
+					ocf_log info "connection state $conn_state. Session restored."
+				return 0;;
+			*) # failed
+				if [ "$__OCF_ACTION" != stop ] && ! ocf_is_probe && ocf_is_true $recov; then
+					if [ "$conn_state" != "$prev_state" ]; then
+						ocf_log warning "connection state $conn_state, waiting for recovery..."
+						prev_state="$conn_state"
+					fi
+					sleep 1
+				else
+					ocf_log err "iscsiadm output: $outp"
+					return 2
+				fi
+			;;
+		esac
+	done
+}
+
+disk_discovery() {
+	$discovery  # discover and setup the real portal string (address)
+	case $? in
+	0) ;;
+	1|2) exit $OCF_ERR_GENERIC ;;
+	3) if ! is_iscsid_running; then
+			[ $setup_rc -eq 1 ] &&
+				ocf_log warning "iscsid.startup probably not correctly set in /etc/iscsi/iscsid.conf"
+			exit $OCF_ERR_INSTALLED
+	   fi
+	   exit $OCF_ERR_GENERIC
+	;;
+	esac
+}
+
+#
+# NB: this is udev specific!
+#
+wait_for_udev() {
+	dev=/dev/disk/by-path/ip-$PORTAL-iscsi-$OCF_RESKEY_target
+	while :; do
+		ls $dev* >/dev/null 2>&1 && break
+		ocf_log warning "waiting for udev to create $dev" 
+		sleep 1
+	done
+}
+iscsi_status() {
+	$disk_status $OCF_RESKEY_target $*
+	case $? in
+		0) return $OCF_SUCCESS;;
+		1) return $OCF_NOT_RUNNING;;
+		2) return $OCF_ERR_GENERIC;;
+	esac
+}
+iscsi_start() {
+	iscsi_status
+	case $? in
+	$OCF_SUCCESS)
+		ocf_log info "iscsi $PORTAL $OCF_RESKEY_target already running"
+		return $OCF_SUCCESS
+	;;
+	$OCF_NOT_RUNNING)
+		$add_disk $PORTAL $OCF_RESKEY_target ||
+			return $OCF_ERR_GENERIC
+		case "$OCF_RESKEY_udev" in
+		[Yy]es) wait_for_udev ||
+			return $OCF_ERR_GENERIC
+		;;
+		*) ;;
+		esac
+	;;
+	*) # the session exists, but it's broken
+		ocf_log warning "iscsi $PORTAL $OCF_RESKEY_target in failed state"
+	;;
+	esac
+	iscsi_status 1 # enforce wait
+	if [ $? -eq $OCF_SUCCESS ]; then
+		return $OCF_SUCCESS
+	else
+		return $OCF_ERR_GENERIC
+	fi
+}
+iscsi_stop() {
+	iscsi_status
+	if [ $? -ne $OCF_NOT_RUNNING ] ; then
+		$remove_disk $OCF_RESKEY_target ||
+			return $OCF_ERR_GENERIC
+		iscsi_status
+		if [ $? -ne $OCF_NOT_RUNNING ] ; then
+			return $OCF_ERR_GENERIC
+		else
+			return $OCF_SUCCESS
+		fi
+	else
+		ocf_log info "iscsi $OCF_RESKEY_target already stopped"
+		return $OCF_SUCCESS
+	fi
+}
+
+iscsi_monitor() {
+	if $disk_status $OCF_RESKEY_target; then
+		return $OCF_SUCCESS
+	else
+		return $OCF_NOT_RUNNING
+	fi
+}
+
+#
+#	'main' starts here...
+#
+
+if [ $# -ne 1 ]; then
+	usage
+	exit $OCF_ERR_ARGS
+fi
+
+# These operations don't require OCF instance parameters to be set
+case "$1" in
+	meta-data)	meta_data
+		exit $OCF_SUCCESS;;
+	usage) usage
+		exit $OCF_SUCCESS;;
+	methods) iscsi_methods
+		exit $OCF_SUCCESS;;
+esac
+
+if [ x = "x$OCF_RESKEY_target" ]; then
+	ocf_log err "target parameter not set"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+if [ x = "x$OCF_RESKEY_portal" ]; then
+	ocf_log err "portal parameter not set"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+case `uname` in
+Linux) setup=open_iscsi_setup
+;;
+*) ocf_log info "platform `uname` may not be supported"
+	setup=open_iscsi_setup
+;;
+esac
+
+LSB_STATUS_STOPPED=3
+$setup
+setup_rc=$?
+if [ $setup_rc -gt 1 ]; then
+	ocf_log info "iscsi initiator utilities not installed or not setup"
+	case "$1" in
+		stop) exit $OCF_SUCCESS;;
+		monitor) exit $OCF_NOT_RUNNING;;
+		status) exit $LSB_STATUS_STOPPED;;
+		*) exit $OCF_ERR_INSTALLED;;
+	esac
+fi
+
+if [ `id -u` != 0 ]; then
+	ocf_log err "$0 must be run as root"
+	exit $OCF_ERR_PERM
+fi
+
+# which method was invoked?
+case "$1" in
+	start)
+		discovery_type=${OCF_RESKEY_discovery_type}
+		disk_discovery
+		iscsi_start
+	;;
+	stop)	iscsi_stop
+	;;
+	status)	iscsi_status
+		rc=$?
+		case $rc in
+		$OCF_SUCCESS)
+		  echo iscsi target $OCF_RESKEY_target running
+		;;
+		$OCF_NOT_RUNNING)
+		  echo iscsi target $OCF_RESKEY_target stopped
+		;;
+		*)
+		  echo iscsi target $OCF_RESKEY_target failed
+		;;
+		esac
+		exit $rc
+		;;
+	monitor)	iscsi_status
+	;;
+	validate-all)	# everything already validated
+		# just exit successfully here.
+		exit $OCF_SUCCESS;;
+	*)		iscsi_methods
+		exit $OCF_ERR_UNIMPLEMENTED;;
+esac
+
+#
+# vim:tabstop=4:shiftwidth=4:textwidth=0:wrapmargin=0
diff --git a/heartbeat/jboss b/heartbeat/jboss
new file mode 100755
index 0000000..48a51ca
--- /dev/null
+++ b/heartbeat/jboss
@@ -0,0 +1,658 @@
+#!/bin/sh
+#
+# Description:  Manages a Jboss Server as an OCF High-Availability
+#               resource under Heartbeat/LinuxHA control
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA  
+# 02110-1301, USA.
+#
+# Copyright (c) 2009 Bauer Systems KG / Stefan Schluppeck
+#
+#######################################################################
+# OCF parameters:
+#   OCF_RESKEY_resource_name - The name of the resource. Default is ${OCF_RESOURCE_INSTANCE}
+#   OCF_RESKEY_jboss_version - The version of JBoss. Default is 5.
+# why not let the RA log through lrmd?
+# 2009/09/09 Nakahira:
+# jboss_console is used to record output of the "run.sh".
+# The log of "Run.sh" should not be output to ha-log because it is so annoying.
+#   OCF_RESKEY_console - A destination of the log of jboss run and shutdown script. Default is /var/log/${OCF_RESKEY_resource_name}.log
+#   OCF_RESKEY_shutdown_timeout - Time-out at the time of the stop. Default is 5
+#   OCF_RESKEY_kill_timeout - The re-try number of times awaiting a stop. Default is 10
+#   OCF_RESKEY_user - A user name to start a JBoss. Default is root
+#   OCF_RESKEY_statusurl - URL for state confirmation. Default is ${OCF_RESKEY_statusurl_default}
+#   OCF_RESKEY_java_home - Home directory of the Java. Default is ${JAVA_HOME}
+#   OCF_RESKEY_java_opts - Options for Java.
+#   OCF_RESKEY_jboss_home - Home directory of Jboss. Default is None
+# is it possible to devise this string from options? I'm afraid
+# that allowing users to set this could be error prone.
+# 2009/09/09 Nakahira:
+# It is difficult to set it automatically because jboss_pstring
+# greatly depends on the environment. At any rate, system architect
+# should note that pstring doesn't influence other processes.
+#   OCF_RESKEY_jboss_base_dir - Base directory of JBoss. Default is ${OCF_RESKEY_jboss_base_dir_default}
+#   OCF_RESKEY_pstring - String Jboss will found in procceslist. Default is ${OCF_RESKEY_pstring_default}
+#   OCF_RESKEY_run_command - JBoss start command. Default is "${OCF_RESKEY_run_command_default}"
+#   OCF_RESKEY_run_opts - Options for jboss to run. Default is ${OCF_RESKEY_run_opts_default}
+#   OCF_RESKEY_shutdown_opts - Options for jboss to shutdonw. Default is "-s 127.0.0.1:1099"
+#   OCF_RESKEY_rotate_consolelog - Control console log logrotation flag. Default is false.
+#   OCF_RESKEY_rotate_value - console log logrotation value. Default is 86400 span(seconds).
+#   OCF_RESKEY_rotate_logsuffix - Control console log logrotation suffix. Default is .%F.
+###############################################################################
+
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+usage()
+{
+    cat <<-!
+usage: $0 action
+
+action:
+        start   start jboss
+
+        stop    stop the jboss
+
+        status  return the status of jboss, run or down
+
+        monitor  return TRUE if the jboss appears to be working.
+                 You have to have installed $WGETNAME for this to work.
+
+        meta-data       show meta data message
+
+        validate-all    validate the instance parameters
+!
+    return $OCF_ERR_ARGS
+}
+
+isrunning_jboss()
+{
+    local rc
+    if [ -z "$1" ];then
+        ocf_run -q -err wget -t 1 -O /dev/null $STATUSURL
+    else
+        # Retry message for restraint
+        wget -t 1 -O /dev/null $STATUSURL 2>/dev/null
+    fi
+    rc=$?
+    if [ $rc -eq 0 ]; then
+        return $OCF_SUCCESS
+    fi
+    # JBoss service error
+    return $OCF_ERR_GENERIC
+}
+
+monitor_rotatelogs()
+{
+    pgrep -f "$ROTATELOGS.*$CONSOLE$ROTATELOG_SUFFIX" > /dev/null 2>&1
+    if [ $? -ne 0 ]; then
+        ocf_log warn "A rotatelogs command for $CONSOLE is not running. Restarting it."
+        start_rotatelogs
+        if [ $? -eq 0 ]; then
+            ocf_log info "Restart rotatelogs process succeeded."
+        else
+            ocf_log warn "Restart rotatelogs process failed."
+        fi
+    fi
+}
+
+monitor_jboss()
+{
+    if ! pgrep -f "$PSTRING" > /dev/null; then
+        return $OCF_NOT_RUNNING
+    fi
+    isrunning_jboss $1
+    rc=$?
+    if [ $rc -ne $OCF_SUCCESS ]; then
+        return $rc
+    fi
+    if ocf_is_true $ROTATELOG_FLG; then
+       # Monitor rotatelogs process and restart it if it is stopped.
+       # And never consider rotatelogs process failure to be a monitor failure
+       # as long as JBoss process works fine.
+       monitor_rotatelogs
+    fi
+    return $OCF_SUCCESS
+}
+
+start_rotatelogs()
+{
+    su - -s /bin/sh $JBOSS_USER \
+        -c "$ROTATELOGS -l \"$CONSOLE$ROTATELOG_SUFFIX\" $ROTATEVALUE" \
+        < "$CONSOLE" > /dev/null 2>&1 &
+}
+
+rotate_console()
+{
+    # Check $CONSOLE$ROTATELOG_SUFFIX is writable or not.
+    CURRENT_ROTATELOG_SUFFIX=`date +"$ROTATELOG_SUFFIX"`
+    su - -s /bin/sh $JBOSS_USER \
+        -c "touch \"$CONSOLE$CURRENT_ROTATELOG_SUFFIX\"" > /dev/null 2>&1
+    if [ $? -ne 0 ]; then
+        ocf_log err "$CONSOLE$CURRENT_ROTATELOG_SUFFIX is not writable."
+        return $OCF_ERR_GENERIC
+    fi
+
+    # Clean up and set permissions on required files
+    if [ -p "$CONSOLE" ]; then
+        rm -rf "$CONSOLE"
+    elif [ -e "$CONSOLE" ]; then
+        DATE=`date +"%F-%H%M%S"`
+        ocf_log warn "$CONSOLE already exists. It is saved as $CONSOLE-$DATE"
+        mv "$CONSOLE" "$CONSOLE-$DATE"
+    fi
+    mkfifo -m700 "$CONSOLE"
+    chown --dereference "$JBOSS_USER" "$CONSOLE" || true
+
+    start_rotatelogs
+}
+
+start_jboss()
+{
+    monitor_jboss start
+    if [ $? -eq $OCF_SUCCESS ]; then
+        ocf_log info "JBoss already running."
+        return $OCF_SUCCESS
+    fi
+
+    if ocf_is_true $ROTATELOG_FLG; then
+        rotate_console
+        if [ $? -eq 0 ]; then
+            ocf_log debug "Rotate console log succeeded."
+        else
+            ocf_log err "Rotate console log failed. Avoid starting jboss without console log rotation."
+            return $OCF_ERR_GENERIC
+        fi
+    fi
+
+    ocf_log info "Starting JBoss[$RESOURCE_NAME]"
+    if [ "$JBOSS_USER" = root ]; then
+        "$RUN_COMMAND" $RUN_OPTS \
+            >> "$CONSOLE" 2>&1 &
+    else
+        su - -s /bin/sh "$JBOSS_USER" \
+            -c "export JAVA_HOME=\"${JAVA_HOME}\"; \
+                export JAVA_OPTS=\"${JAVA_OPTS}\"; \
+                export JBOSS_HOME=\"${JBOSS_HOME}\"; \
+                export JBOSS_BASE_DIR=\"${JBOSS_BASE_DIR}\"; \
+                \"$RUN_COMMAND\" $RUN_OPTS" \
+            >> "$CONSOLE" 2>&1 &
+    fi
+
+    while true; do
+        monitor_jboss start
+        if [ $? -eq $OCF_SUCCESS ]; then
+            break
+        fi
+        ocf_log info "start_jboss[$RESOURCE_NAME]: retry monitor_jboss"
+        sleep 3
+    done
+
+    ocf_log info "JBoss[$RESOURCE_NAME] is started."
+    return $OCF_SUCCESS
+}
+
+output_thread_dump()
+{
+    ocf_log info "stop_jboss[$RESOURCE_NAME]: output a JVM thread dump to $CONSOLE"
+    pkill -QUIT -f "$PSTRING"
+}
+
+# arg1 : timeout
+# arg2 : send specified signal
+wait_process_exit()
+{
+    local lapse_sec=0
+    local timeout=$1
+    local signal=$2
+
+    while pgrep -f "$PSTRING" > /dev/null; do
+        sleep 1
+        lapse_sec=`expr $lapse_sec + 1`
+        if [ -n "$signal" ]; then
+            ocf_log info "stop_jboss[$RESOURCE_NAME]: kill jboss by SIG$signal ($lapse_sec/$timeout)"
+            pkill -$signal -f "$PSTRING"
+        else
+            ocf_log info "stop_jboss[$RESOURCE_NAME]: stop NORM $lapse_sec/$timeout"
+        fi
+        if [ "$timeout" -ne 0 -a $lapse_sec -ge $timeout ]; then
+            return 1
+        fi
+    done
+    return 0
+}
+
+stop_jboss5()
+{
+    if [ "$JBOSS_USER" = root ]; then
+        "$JBOSS_HOME/bin/shutdown.sh" $SHUTDOWN_OPTS -S \
+            >> "$CONSOLE" 2>&1 &
+    else
+        su - -s /bin/sh "$JBOSS_USER" \
+            -c "export JAVA_HOME=\"${JAVA_HOME}\"; \
+                export JBOSS_HOME=\"${JBOSS_HOME}\"; \
+                \"$JBOSS_HOME/bin/shutdown.sh\" $SHUTDOWN_OPTS -S" \
+            >> "$CONSOLE" 2>&1 &
+    fi
+    if ! wait_process_exit $SHUTDOWN_TIMEOUT; then
+        output_thread_dump
+        if ! wait_process_exit $KILL_TIMEOUT TERM; then
+            return 1
+        fi
+    fi
+    return 0
+}
+
+stop_jboss6()
+{
+    pkill -TERM -f "$PSTRING"
+
+    if ! wait_process_exit $SHUTDOWN_TIMEOUT; then
+        output_thread_dump
+        return 1
+    fi
+    return 0
+}
+
+stop_jboss()
+{
+    local rc
+
+    if ! pgrep -f "$PSTRING" > /dev/null; then
+        ocf_log info "JBoss[$RESOURCE_NAME] is already stopped."
+    else
+        ocf_log info "Stopping JBoss[$RESOURCE_NAME]"
+        # JBoss5 : shutdonw.sh -> SIGQUIT(output thread dump) -> SIGTERM
+        #   If the JBoss process hangs, JBoss RA waits $SHUTDOWN_TIMEOUT
+        #   seconds and tries kill TERM and QUIT for $KILL_TIMEOUT seconds.
+        # JBoss6 : SIGTERM -> SIGQUIT(output thread dump)
+        #   If the JBoss process hangs, JBoss RA waits $SHUTDOWN_TIMEOUT
+        #   seconds and tries kill QUIT.
+        if [ "$JBOSS_VERSION" -le 5 ]; then
+            stop_jboss5
+            rc=$?
+        else
+            stop_jboss6
+            rc=$?
+        fi
+        if [ $rc -ne 0 ]; then
+            # JBoss5
+            #   The stop timeout of RA should be
+            #   longer than $SHUTDOWN_TIMEOUT + $KILL_TIMEOUT.
+            # JBoss6
+            #   The stop timeout of RA should be longer than $SHUTDOWN_TIMEOUT.
+            wait_process_exit 0 KILL
+        fi
+        ocf_log info "JBoss[$RESOURCE_NAME] is stopped."
+    fi
+
+    if ocf_is_true $ROTATELOG_FLG; then
+        rm -f "${CONSOLE}"
+    fi
+
+    return $OCF_SUCCESS
+}
+
+status_jboss()
+{
+    if ! pgrep -f "$PSTRING" > /dev/null; then
+        echo "JBoss process[$RESOURCE_NAME] is not running."
+        return $OCF_NOT_RUNNING
+    fi
+
+    if isrunning_jboss; then
+        echo "JBoss[$RESOURCE_NAME] is running."
+        return $OCF_SUCCESS
+    else
+        echo "JBoss process[$RESOURCE_NAME] is running."
+        echo "But, we can not access JBoss web service."
+        return $OCF_NOT_RUNNING
+    fi
+}
+
+
+metadata_jboss()
+{
+    cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="jboss">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for Jboss. It manages a Jboss instance as an HA resource.
+</longdesc>
+<shortdesc lang="en">Manages a JBoss application server instance</shortdesc>
+
+<parameters>
+
+<parameter name="jboss_version" unique="0" required="0">
+<longdesc lang="en">
+The version of JBoss. Default is 5.
+The usage of JBoss was greatly changed as of JBoss 6.
+Specify "6" when you use JBoss 6.
+</longdesc>
+<shortdesc>The version of JBoss</shortdesc>
+<content type="integer" default="5" />
+</parameter>
+
+<parameter name="resource_name" unique="1" required="0">
+<longdesc lang="en">
+The name of the resource. Defaults to the name of the resource
+instance.
+</longdesc>
+<shortdesc>The name of the resource</shortdesc>
+<content type="string" default="${OCF_RESOURCE_INSTANCE}" />
+</parameter>
+
+<parameter name="console" unique="1" required="0">
+<longdesc lang="en">
+A destination of the log of jboss run and shutdown script.
+</longdesc>
+<shortdesc>jboss log path</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="shutdown_timeout" unique="0" required="0">
+<longdesc lang="en">
+Timeout for jboss bin/shutdown.sh. We wait for this timeout to
+expire, then send the TERM and QUIT signals. Finally, the KILL
+signal is used to terminate the jboss process. You should set the
+timeout for the stop operation to a value bigger than the sum of
+the timeout parameters. See also kill_timeout.
+</longdesc>
+<shortdesc>shutdown timeout</shortdesc>
+<content type="integer" default="5" />
+</parameter>
+
+<parameter name="kill_timeout" unique="0" required="0">
+<longdesc lang="en">
+If bin/shutdown.sh doesn't stop the jboss process, then we send
+it TERM and QUIT signals, intermittently and once a second. After
+this timeout expires, if the process is still live, we use the
+KILL signal. See also shutdown_timeout.
+</longdesc>
+<shortdesc>stop by signal timeout</shortdesc>
+<content type="integer" default="10" />
+</parameter>
+
+<parameter name="user" unique="0" required="0">
+<longdesc lang="en">
+A user name to start a JBoss.
+</longdesc>
+<shortdesc>A user name to start a resource.</shortdesc>
+<content type="string" default="root"/>
+</parameter>
+
+<parameter name="statusurl" unique="0" required="0">
+<longdesc lang="en">
+URL to test in the monitor operation.
+</longdesc>
+<shortdesc>URL to test in the monitor operation.</shortdesc>
+<content type="string" default="${OCF_RESKEY_statusurl_default}" />
+</parameter>
+
+<parameter name="java_home" unique="0" required="0">
+<longdesc lang="en">
+Home directory of Java. Defaults to the environment variable
+JAVA_HOME. If it is not set, then define this parameter.
+</longdesc>
+<shortdesc>Home directory of Java.</shortdesc>
+<content type="string" default="$JAVA_HOME"/>
+</parameter>
+
+<parameter name="java_opts" unique="0" required="0">
+<longdesc lang="en">
+Java options.
+</longdesc>
+<shortdesc>Java options.</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="jboss_home" unique="0" required="1">
+<longdesc lang="en">
+Home directory of Jboss.
+</longdesc>
+<shortdesc>Home directory of Jboss.</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="jboss_base_dir" unique="0" required="0">
+<longdesc lang="en">
+Base directory of JBoss. This parameter is not used in JBoss5.
+</longdesc>
+<shortdesc>Base directory of JBoss.</shortdesc>
+<content type="string" default="${OCF_RESKEY_jboss_base_dir_default}" />
+</parameter>
+
+<parameter name="pstring" unique="0" required="0">
+<longdesc lang="en">
+With this string heartbeat matches for the right process to kill.
+</longdesc>
+<shortdesc>pkill/pgrep search string</shortdesc>
+<content type="string" default="${OCF_RESKEY_pstring_default}" />
+</parameter>
+
+<parameter name="run_command" unique="0" required="0">
+<longdesc lang="en">
+JBoss start command.
+</longdesc>
+<shortdesc>JBoss start command.</shortdesc>
+<content type="string" default="${OCF_RESKEY_run_command_default}" />
+</parameter>
+
+<parameter name="run_opts" unique="0" required="0">
+<longdesc lang="en">
+Start options to start Jboss with, defaults are from the Jboss-Doku.
+</longdesc>
+<shortdesc>options for jboss run.sh</shortdesc>
+<content type="string" default="${OCF_RESKEY_run_opts_default}" />
+</parameter>
+
+<parameter name="shutdown_opts" unique="0" required="0">
+<longdesc lang="en">
+Stop options to stop Jboss with.
+</longdesc>
+<shortdesc>options for jboss shutdown.sh</shortdesc>
+<content type="string" default="-s 127.0.0.1:1099" />
+</parameter>
+
+<parameter name="rotate_consolelog" unique="0">
+<longdesc lang="en">
+Rotate console log flag.
+</longdesc>
+<shortdesc>Rotate console log flag</shortdesc>
+<content type="boolean" default="false" />
+</parameter>
+
+<parameter name="rotate_value" unique="0">
+<longdesc lang="en">
+Console log rotation value (default is 86400 seconds).
+</longdesc>
+<shortdesc>Console log rotation value (default is 86400 seconds)</shortdesc>
+<content type="integer" default="86400" />
+</parameter>
+
+<parameter name="rotate_logsuffix" unique="0">
+<longdesc lang="en">
+Rotate console log suffix.
+</longdesc>
+<shortdesc>Rotate console log suffix</shortdesc>
+<content type="integer" default=".%F" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="60s" />
+<action name="stop" timeout="120s" />
+<action name="status" timeout="30s" />
+<action name="monitor" depth="0" timeout="30s" interval="10s" />
+<action name="meta-data" timeout="5s" />
+<action name="validate-all"  timeout="5"/>
+</actions>
+</resource-agent>
+END
+    return $OCF_SUCCESS
+}
+
+validate_all_jboss()
+{
+    if [ ! -d "$JAVA_HOME" ]; then
+        ocf_log err "JAVA_HOME does not exist."
+        return $OCF_ERR_INSTALLED
+    fi
+
+    if [ ! -d "$JBOSS_HOME" ]; then
+        ocf_log err "JBOSS_HOME does not exist."
+        return $OCF_ERR_INSTALLED
+    fi
+
+    if [ "$JBOSS_VERSION" -gt 5 ]; then
+        if [ ! -d "$JBOSS_BASE_DIR" ]; then
+            ocf_log err "JBOSS_BASE_DIR does not exist."
+            return $OCF_ERR_INSTALLED
+        fi
+    fi
+
+    if [ ! -x "$JAVA" ]; then
+        ocf_log err "java command does not exist."
+        return $OCF_ERR_INSTALLED
+    fi
+
+    if ocf_is_true $ROTATELOG_FLG; then
+        if [ ! -x "$ROTATELOGS" ]; then
+            ocf_log err "rotatelogs command does not exist."
+            return $OCF_ERR_INSTALLED
+        fi
+    fi
+
+    return $OCF_SUCCESS
+}
+
+COMMAND=$1
+JBOSS_VERSION="${OCF_RESKEY_jboss_version-5}"
+if ! ocf_is_decimal $JBOSS_VERSION; then
+    ocf_log err "Invalid parameter value: jboss_version [$JBOSS_VERSION]"
+    return $OCF_ERR_ARGS
+fi
+# Setting of the default value
+if [ "$JBOSS_VERSION" -le 5 ]; then
+    OCF_RESKEY_statusurl_default="http://127.0.0.1:8080"
+    OCF_RESKEY_pstring_default="java -Dprogram.name=run.sh"
+    OCF_RESKEY_run_command_default="${OCF_RESKEY_jboss_home}/bin/run.sh"
+    OCF_RESKEY_run_opts_default="-c default"
+else
+    OCF_RESKEY_jboss_base_dir_default="${OCF_RESKEY_jboss_home}/standalone"
+    JBOSS_BASE_DIR="${OCF_RESKEY_jboss_base_dir-${OCF_RESKEY_jboss_base_dir_default}}"
+    OCF_RESKEY_statusurl_default="http://127.0.0.1:9990"
+    OCF_RESKEY_pstring_default="java.*-Djboss.server.base.dir=${JBOSS_BASE_DIR}( .*)?$"
+    OCF_RESKEY_run_command_default="${OCF_RESKEY_jboss_home}/bin/standalone.sh"
+    OCF_RESKEY_run_opts_default=""
+fi
+RESOURCE_NAME="${OCF_RESKEY_resource_name-${OCF_RESOURCE_INSTANCE}}"
+CONSOLE="${OCF_RESKEY_console-/var/log/${RESOURCE_NAME}.log}"
+SHUTDOWN_TIMEOUT="${OCF_RESKEY_shutdown_timeout-5}"
+KILL_TIMEOUT="${OCF_RESKEY_kill_timeout-10}"
+JBOSS_USER="${OCF_RESKEY_user-root}"
+STATUSURL="${OCF_RESKEY_statusurl-${OCF_RESKEY_statusurl_default}}"
+PSTRING="${OCF_RESKEY_pstring-${OCF_RESKEY_pstring_default}}"
+RUN_OPTS="${OCF_RESKEY_run_opts-${OCF_RESKEY_run_opts_default}}"
+SHUTDOWN_OPTS="${OCF_RESKEY_shutdown_opts--s 127.0.0.1:1099}"
+ROTATELOG_FLG="${OCF_RESKEY_rotate_consolelog-false}"
+ROTATEVALUE="${OCF_RESKEY_rotate_value-86400}"
+ROTATELOG_SUFFIX="${OCF_RESKEY_rotate_logsuffix-.%F}"
+
+if [ $# -ne 1 ]; then
+    usage
+    exit $OCF_ERR_ARGS
+fi
+
+if [ "$COMMAND" = "meta-data" ]; then
+    metadata_jboss
+    exit $OCF_SUCCESS
+fi
+if [ "$COMMAND" = "help" -o "$COMMAND" = "usage" ]; then
+    usage
+    exit $OCF_SUCCESS
+fi
+
+# test if these two are set and if directories exist and if the
+# required scripts/binaries exist; use OCF_ERR_INSTALLED
+JAVA_HOME="${OCF_RESKEY_java_home-${JAVA_HOME}}"
+JAVA_OPTS="${OCF_RESKEY_java_opts}"
+JBOSS_HOME="${OCF_RESKEY_jboss_home}"
+RUN_COMMAND="${OCF_RESKEY_run_command-${OCF_RESKEY_run_command_default}}"
+
+LSB_STATUS_STOPPED=3
+
+export JAVA_HOME JAVA_OPTS JBOSS_HOME JBOSS_BASE_DIR
+
+JAVA=${JAVA_HOME}/bin/java
+
+ROTATELOGS=""
+if ocf_is_true $ROTATELOG_FLG; then
+    # Look for rotatelogs/rotatelogs2
+    if [ -x /usr/sbin/rotatelogs ]; then
+        ROTATELOGS=/usr/sbin/rotatelogs
+    elif [ -x /usr/sbin/rotatelogs2 ]; then
+        ROTATELOGS=/usr/sbin/rotatelogs2
+    fi
+fi
+
+validate_all_jboss
+rc=$?
+
+[ "$COMMAND" = "validate-all" ] && exit $rc
+
+if [ $rc -ne 0 ]; then
+    case $COMMAND in
+        stop)       exit    $OCF_SUCCESS;;
+        monitor)    exit    $OCF_NOT_RUNNING;;
+        status)     exit    $LSB_STATUS_STOPPED;;
+        *)          exit    $rc;;
+    esac
+fi
+
+case "$COMMAND" in
+    start)
+        start_jboss
+        func_status=$?
+        exit $func_status
+        ;;
+    stop)
+        stop_jboss
+        func_status=$?
+        exit $func_status
+        ;;
+    status)
+        status_jboss
+        exit $?
+        ;;
+    monitor)
+        monitor_jboss
+        func_status=$?
+        exit $func_status
+        ;;
+    validate-all)
+        validate_all_jboss
+        exit $?
+        ;;
+    *)
+        usage
+        exit $OCF_ERR_UNIMPLEMENTED;;
+esac
+
diff --git a/heartbeat/lxc b/heartbeat/lxc
new file mode 100755
index 0000000..53a80df
--- /dev/null
+++ b/heartbeat/lxc
@@ -0,0 +1,323 @@
+#!/bin/bash
+# Should now conform to guidelines: http://www.linux-ha.org/doc/dev-guides/ra-dev-guide.html
+#
+#	LXC (Linux Containers) OCF RA. 
+#	Used to cluster enable the start, stop and monitoring of a LXC container.
+#
+# Copyright (c) 2011 AkurIT.com.au, Darren Thompson
+#                    All Rights Reserved.
+#
+# Without limiting the rights of the original copyright holders
+# This resource is licensed under GPL version 2
+#
+# 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.
+
+# OCF instance parameters
+#       OCF_RESKEY_container
+#       OCF_RESKEY_config
+#       OCF_RESKEY_log
+#	OCF_RESKEY_use_screen
+
+# Initialization:
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+OCF_RESKEY_log_default="${HA_RSCTMP}/${OCF_RESOURCE_INSTANCE}.log"
+OCF_RESKEY_use_screen_default="false"
+
+: ${OCF_RESKEY_log=${OCF_RESKEY_log_default}}
+: ${OCF_RESKEY_use_screen=${OCF_RESKEY_use_screen_default}}
+
+
+# Set default TRANS_RES_STATE (temporary file to "flag" if resource was stated but not stopped)
+TRANS_RES_STATE="${HA_RSCTMP}/${OCF_RESOURCE_INSTANCE}.state"
+
+meta_data() {
+cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="lxc" version="0.1">
+<version>0.1</version>
+<longdesc lang="en">Allows LXC containers to be managed by the cluster.
+If the container is running "init" it will also perform an orderly shutdown.
+It is 'assumed' that the 'init' system will do an orderly shudown if presented with a 'kill -PWR' signal.
+On a 'sysvinit' this would require the container to have an inittab file containing "p0::powerfail:/sbin/init 0"
+I have absolutly no idea how this is done with 'upstart' or 'systemd', YMMV if your container is using one of them.</longdesc>
+<shortdesc lang="en">Manages LXC containers</shortdesc>
+
+<parameters>
+<parameter name="container" required="1" unique="1">
+<longdesc lang="en">The unique name for this 'Container Instance' e.g. 'test1'.</longdesc>
+<shortdesc lang="en">Container Name</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="config" required="1" unique="0">
+<longdesc lang="en">Absolute path to the file holding the specific configuration for this container e.g. '/etc/lxc/test1/config'.</longdesc>
+<shortdesc lang="en">The LXC config file.</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="log" required="0" unique="0">
+<longdesc lang="en">Absolute path to the container log file</longdesc>
+<shortdesc lang="en">Container log file</shortdesc>
+<content type="string" default="${OCF_RESKEY_log_default}"/>
+</parameter>
+
+<parameter name="use_screen" required="0" unique="0">
+<longdesc lang="en">Provides the option of capturing the 'root console' from the container and showing it on a separate screen. 
+To see the screen output run 'screen -r {container name}'
+The default value is set to 'false', change to 'true' to activate this option</longdesc>
+<shortdesc lang="en">Use 'screen' for container 'root console' output</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_use_screen_default}"/>
+</parameter>
+
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="10" />
+<action name="stop"         timeout="30" />
+<action name="monitor"      timeout="20" interval="60" depth="0"/>
+<action name="validate-all" timeout="20" />
+<action name="meta-data"    timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+
+LXC_usage() {
+	cat <<END
+	usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+	Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+cgroup_mounted() {
+# test cgroup_mounted, mount if required
+	# Various possible overrides to cgroup mount point.
+	# If kernel supplies cgroup mount point, prefer it.
+	CGROUP_MOUNT_POINT=/var/run/lxc/cgroup
+	CGROUP_MOUNT_NAME=lxc
+	CGROUP_MOUNTED=false
+	[[ -d /sys/fs/cgroup ]] && CGROUP_MOUNT_POINT=/sys/fs/cgroup CGROUP_MOUNT_NAME=cgroup
+	# If cgroup already mounted, use it no matter where it is.
+	# If multiple cgroup mounts, prefer the one named lxc if any.
+	eval `awk 'BEGIN{P="";N=""}END{print("cgmp="P" cgmn="N)}($3=="cgroup"){N=$1;P=$2;if($1="lxc")exit}' /proc/mounts`
+	[[ "$cgmn" && "$cgmp" && -d "$cgmp" ]] && CGROUP_MOUNT_POINT=$cgmp CGROUP_MOUNT_NAME=$cgmn CGROUP_MOUNTED=true
+	$CGROUP_MOUNTED || {
+		[[ -d $CGROUP_MOUNT_POINT ]] || ocf_run mkdir -p $CGROUP_MOUNT_POINT
+		ocf_run mount -t cgroup $CGROUP_MOUNT_NAME $CGROUP_MOUNT_POINT
+	}
+	echo 1 >${CGROUP_MOUNT_POINT}/notify_on_release
+	return 0
+}
+
+LXC_start() {
+	# put this here as it's so long it gets messy later!!!
+	if ocf_is_true $OCF_RESKEY_use_screen; then
+		STARTCMD="screen -dmS ${OCF_RESKEY_container} lxc-start -f ${OCF_RESKEY_config} -n ${OCF_RESKEY_container} -o ${OCF_RESKEY_log}"
+	else
+		STARTCMD="lxc-start -f ${OCF_RESKEY_config} -n ${OCF_RESKEY_container} -o ${OCF_RESKEY_log} -d"
+	fi
+
+	LXC_status
+	if [ $? -eq $OCF_SUCCESS ]; then
+		ocf_log debug "Resource $OCF_RESOURCE_INSTANCE is already running"
+		ocf_run touch "${TRANS_RES_STATE}" || exit $OCF_ERR_GENERIC
+		return $OCF_SUCCESS
+	fi
+
+	cgroup_mounted
+	if [ $? -ne 0 ]; then
+		ocf_log err "Unable to find cgroup mount"
+		exit $OCF_ERR_GENERIC
+	fi
+
+	ocf_log info "Starting" ${OCF_RESKEY_container}
+	ocf_run ${STARTCMD} || exit $OCF_ERR_GENERIC
+
+	# Spin on status, wait for the cluster manager to time us out if
+	# we fail
+	while ! LXC_status; do
+		ocf_log info "Container ${OCF_RESKEY_container} has not started, waiting"
+		sleep 1
+	done
+
+	ocf_run touch "${TRANS_RES_STATE}" || exit $OCF_ERR_GENERIC
+	return $OCF_SUCCESS
+}
+
+
+
+LXC_stop() {
+	local shutdown_timeout
+	local now
+	LXC_status
+	if [ $? -eq $OCF_NOT_RUNNING ]; then
+		ocf_log debug "Resource $OCF_RESOURCE_INSTANCE is already stopped"
+		ocf_run rm -f $TRANS_RES_STATE
+		return $OCF_SUCCESS
+	fi
+
+	cgroup_mounted
+	if [ $? -ne 0 ]; then
+		ocf_log err "Unable to find cgroup mount"
+		exit $OCF_ERR_GENERIC
+	fi
+
+	# If the container is running "init" and is able to perform and orderly shutdown, then it should be done.
+	# It is 'assumed' that the 'init' system will do an orderly shudown if presented with a 'kill -PWR' signal.
+	# On a 'sysvinit' this would require the container to have an inittab file containing "p0::powerfail:/sbin/init 0"
+	typeset -i PID=0
+	# This should work for traditional 'sysvinit' and 'upstart'
+	lxc-ps --name "${OCF_RESKEY_container}" -- -C init -o pid,comm |while read CN PID CMD ;do
+		[ $PID -gt 1 ] || continue
+		[ "$CMD" = "init" ] || continue
+		ocf_log info "Sending \"OS shut down\" instruction to" ${OCF_RESKEY_container} "as it was found to be using \"sysV init\" or \"upstart\""
+		kill -PWR $PID
+	done
+	# This should work for containers using 'systemd' instead of 'init'
+	lxc-ps --name "${OCF_RESKEY_container}" -- -C systemd -o pid,comm |while read CN PID CMD ;do
+		[ $PID -gt 1 ] || continue
+		[ "$CMD" = "systemd" ] || continue
+		ocf_log info "Sending \"OS shut down\" instruction to" ${OCF_RESKEY_container} "as it was found to be using \"systemd\""
+		kill -PWR $PID
+	done
+	# The "shutdown_timeout" we use here is the operation
+	# timeout specified in the CIB, minus 5 seconds
+	now=$(date +%s)
+	shutdown_timeout=$(( $now + ($OCF_RESKEY_CRM_meta_timeout/1000) -5 ))
+	# Loop on status until we reach $shutdown_timeout
+	while [ $now -lt $shutdown_timeout ]; do
+	    LXC_status
+	    status=$?
+	    case $status in
+		"$OCF_NOT_RUNNING")
+		    ocf_run rm -f $TRANS_RES_STATE
+		    return $OCF_SUCCESS
+		    ;;
+		"$OCF_SUCCESS")
+		    # Container 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
+
+	# If the container is still running, it will be stopped now. regardless of state!
+	ocf_run lxc-stop -n ${OCF_RESKEY_container} || exit $OCF_ERR_GENERIC
+	ocf_log info "Container" ${OCF_RESKEY_container} "stopped"
+	ocf_run rm -f $TRANS_RES_STATE
+
+	return $OCF_SUCCESS
+}
+
+LXC_status() {
+	# run lxc-info with -s option for LXC-0.7.5 or later
+	local lxc_info_opt="-s"
+	ocf_version_cmp "`lxc-version | cut -d' ' -f 3`" 0.7.5 && lxc_info_opt=""
+	S=`lxc-info $lxc_info_opt -n ${OCF_RESKEY_container}`
+	ocf_log debug "State of ${OCF_RESKEY_container}: $S"
+	if [[ "${S##* }" = "RUNNING" ]] ; then 
+		return $OCF_SUCCESS
+	fi
+	return $OCF_NOT_RUNNING
+}
+
+LXC_monitor() {
+	LXC_status && return $OCF_SUCCESS
+	if [ -f $TRANS_RES_STATE ]; then
+		ocf_log err "${OCF_RESKEY_container} is not running, but state file ${TRANS_RES_STATE} exists."
+		exit $OCF_ERR_GENERIC
+	fi
+	return $OCF_NOT_RUNNING
+}
+
+
+LXC_validate() {
+	# Quick check that all required attributes are set
+	if [ -z "${OCF_RESKEY_container}" ]; then
+		ocf_log err "LXC container name not set!"
+		exit $OCF_ERR_CONFIGURED
+	fi
+	if [ -z "${OCF_RESKEY_config}" ]; then
+		ocf_log err "LXC configuration filename name not set!"
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	# Tests that apply only to non-probes
+	if ! ocf_is_probe; then
+		if ! [ -f "${OCF_RESKEY_config}" ]; then
+			ocf_log err "LXC configuration file \"${OCF_RESKEY_config}\" missing or not found!"
+			exit $OCF_ERR_INSTALLED
+		fi
+
+		if ocf_is_true $OCF_RESKEY_use_screen; then
+			check_binary screen
+		fi
+
+	    check_binary lxc-start
+	    check_binary lxc-stop
+	    check_binary lxc-ps
+	    check_binary lxc-info
+	fi
+	return $OCF_SUCCESS
+}
+
+if [ $# -ne 1 ]; then
+  LXC_usage
+  exit $OCF_ERR_ARGS
+fi
+
+case $__OCF_ACTION in
+    meta-data)	meta_data
+	exit $OCF_SUCCESS
+	;;
+    usage|help)	LXC_usage
+	exit $OCF_SUCCESS
+	;;
+esac
+
+# Everything except usage and meta-data must pass the validate test
+LXC_validate
+
+case $__OCF_ACTION in
+start)		LXC_start;;
+stop)		LXC_stop;;
+status)	LXC_status;;
+monitor)	LXC_monitor;;
+validate-all)	;;
+*)		LXC_usage
+		ocf_log err "$0 was called with unsupported arguments: $*"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
diff --git a/heartbeat/mysql b/heartbeat/mysql
new file mode 100755
index 0000000..5e332a1
--- /dev/null
+++ b/heartbeat/mysql
@@ -0,0 +1,1274 @@
+#!/bin/sh
+#
+#
+# MySQL
+#
+# Description:  Manages a MySQL database as Linux-HA resource
+#
+# Authors:  Alan Robertson:               DB2 Script
+#           Jakub Janczak:                rewrite as MySQL
+#           Andrew Beekhof:               cleanup and import
+#           Sebastian Reitenbach:         add OpenBSD defaults, more cleanup
+#           Narayan Newton:               add Gentoo/Debian defaults
+#           Marian Marinov, Florian Haas: add replication capability
+#           Yves Trudeau, Baron Schwartz: add VIP support and improve replication
+#
+# Support:  linux-ha at lists.linux-ha.org
+# License:  GNU General Public License (GPL)
+#
+# (c) 2002-2005 International Business Machines, Inc.
+#     2005-2010 Linux-HA contributors
+#
+# An example usage in /etc/ha.d/haresources:
+#       node1  10.0.0.170 mysql
+#
+# See usage() function below for more details...
+#
+# OCF instance parameters:
+#   OCF_RESKEY_binary
+#   OCF_RESKEY_client_binary
+#   OCF_RESKEY_config
+#   OCF_RESKEY_datadir
+#   OCF_RESKEY_user
+#   OCF_RESKEY_group
+#   OCF_RESKEY_test_table
+#   OCF_RESKEY_test_user
+#   OCF_RESKEY_test_passwd
+#   OCF_RESKEY_enable_creation
+#   OCF_RESKEY_additional_parameters
+#   OCF_RESKEY_log
+#   OCF_RESKEY_pid
+#   OCF_RESKEY_socket
+#   OCF_RESKEY_replication_user
+#   OCF_RESKEY_replication_passwd
+#   OCF_RESKEY_replication_port
+#   OCF_RESKEY_max_slave_lag
+#   OCF_RESKEY_evict_outdated_slaves
+#   OCF_RESKEY_reader_attribute
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+# Attempt to detect a default binary
+OCF_RESKEY_binary_default=$(which mysqld_safe 2> /dev/null)
+if [ "$OCF_RESKEY_binary_default" = "" ]; then
+	OCF_RESKEY_binary_default=$(which safe_mysqld 2> /dev/null)
+fi
+
+# Fill in some defaults if no values are specified
+HOSTOS=`uname`
+if [ "X${HOSTOS}" = "XOpenBSD" ];then
+	if [ "$OCF_RESKEY_binary_default" = "" ]; then
+		OCF_RESKEY_binary_default="/usr/local/bin/mysqld_safe"
+	fi
+	OCF_RESKEY_config_default="/etc/my.cnf"
+	OCF_RESKEY_datadir_default="/var/mysql"
+	OCF_RESKEY_user_default="_mysql"
+	OCF_RESKEY_group_default="_mysql"
+	OCF_RESKEY_log_default="/var/log/mysqld.log"
+	OCF_RESKEY_pid_default="/var/mysql/mysqld.pid"
+	OCF_RESKEY_socket_default="/var/run/mysql/mysql.sock"
+else
+	if [ "$OCF_RESKEY_binary_default" = "" ]; then
+		OCF_RESKEY_binary_default="/usr/bin/safe_mysqld"
+	fi
+	OCF_RESKEY_config_default="/etc/my.cnf"
+	OCF_RESKEY_datadir_default="/var/lib/mysql"
+	OCF_RESKEY_user_default="mysql"
+	OCF_RESKEY_group_default="mysql"
+	OCF_RESKEY_log_default="/var/log/mysqld.log"
+	OCF_RESKEY_pid_default="/var/run/mysql/mysqld.pid"
+	OCF_RESKEY_socket_default="/var/lib/mysql/mysql.sock"
+fi
+OCF_RESKEY_client_binary_default="mysql"
+OCF_RESKEY_test_user_default="root"
+OCF_RESKEY_test_table_default="mysql.user"
+OCF_RESKEY_test_passwd_default=""
+OCF_RESKEY_enable_creation_default=0
+OCF_RESKEY_additional_parameters_default=""
+OCF_RESKEY_replication_port_default="3306"
+OCF_RESKEY_max_slave_lag_default="3600"
+OCF_RESKEY_evict_outdated_slaves_default="false"
+OCF_RESKEY_reader_attribute_default="readable"
+
+: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
+MYSQL_BINDIR=`dirname ${OCF_RESKEY_binary}`
+
+: ${OCF_RESKEY_client_binary=${OCF_RESKEY_client_binary_default}}
+
+: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
+: ${OCF_RESKEY_datadir=${OCF_RESKEY_datadir_default}}
+
+: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}}
+: ${OCF_RESKEY_group=${OCF_RESKEY_group_default}}
+
+: ${OCF_RESKEY_log=${OCF_RESKEY_log_default}}
+: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
+: ${OCF_RESKEY_socket=${OCF_RESKEY_socket_default}}
+
+: ${OCF_RESKEY_test_user=${OCF_RESKEY_test_user_default}}
+: ${OCF_RESKEY_test_table=${OCF_RESKEY_test_table_default}}
+: ${OCF_RESKEY_test_passwd=${OCF_RESKEY_test_passwd_default}}
+
+: ${OCF_RESKEY_enable_creation=${OCF_RESKEY_enable_creation_default}}
+: ${OCF_RESKEY_additional_parameters=${OCF_RESKEY_additional_parameters_default}}
+
+: ${OCF_RESKEY_replication_user=${OCF_RESKEY_replication_user_default}}
+: ${OCF_RESKEY_replication_passwd=${OCF_RESKEY_replication_passwd_default}}
+: ${OCF_RESKEY_replication_port=${OCF_RESKEY_replication_port_default}}
+
+: ${OCF_RESKEY_max_slave_lag=${OCF_RESKEY_max_slave_lag_default}}
+: ${OCF_RESKEY_evict_outdated_slaves=${OCF_RESKEY_evict_outdated_slaves_default}}
+
+: ${OCF_RESKEY_reader_attribute=${OCF_RESKEY_reader_attribute_default}}
+
+#######################################################################
+# Convenience variables
+
+MYSQL=$OCF_RESKEY_client_binary
+MYSQL_OPTIONS_LOCAL="-S $OCF_RESKEY_socket --connect_timeout=10"
+MYSQL_OPTIONS_REPL="$MYSQL_OPTIONS_LOCAL --user=$OCF_RESKEY_replication_user --password=$OCF_RESKEY_replication_passwd"
+MYSQL_OPTIONS_TEST="$MYSQL_OPTIONS_LOCAL --user=$OCF_RESKEY_test_user --password=$OCF_RESKEY_test_passwd"
+MYSQL_TOO_MANY_CONN_ERR=1040
+
+CRM_MASTER="${HA_SBIN_DIR}/crm_master -l reboot "
+NODENAME=$(ocf_local_nodename)
+CRM_ATTR="${HA_SBIN_DIR}/crm_attribute -N $NODENAME "
+INSTANCE_ATTR_NAME=`echo ${OCF_RESOURCE_INSTANCE}| awk -F : '{print $1}'`
+CRM_ATTR_REPL_INFO="${HA_SBIN_DIR}/crm_attribute --type crm_config --name ${INSTANCE_ATTR_NAME}_REPL_INFO -s mysql_replication"
+
+#######################################################################
+
+usage() {
+  cat <<UEND
+usage: $0 (start|stop|validate-all|meta-data|monitor|promote|demote|notify)
+
+$0 manages a MySQL Database as an HA resource.
+
+The 'start' operation starts the database.
+The 'stop' operation stops the database.
+The 'status' operation reports whether the database is running
+The 'monitor' operation reports whether the database seems to be working
+The 'promote' operation makes this mysql server run as master
+The 'demote' operation makes this mysql server run as slave
+The 'validate-all' operation reports whether the parameters are valid
+
+UEND
+}
+
+meta_data() {
+   cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="mysql">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for MySQL.
+May manage a standalone MySQL database, a clone set with externally
+managed replication, or a complete master/slave replication setup.
+
+While managing replication, the default behavior is to use uname -n 
+values in the change master to command.  Other IPs can be specified 
+manually by adding a node attribute \${INSTANCE_ATTR_NAME}_mysql_master_IP
+giving the IP to use for replication.  For example, if the mysql primitive 
+you are using is p_mysql, the attribute to set will be 
+p_mysql_mysql_master_IP.
+</longdesc>
+<shortdesc lang="en">Manages a MySQL database instance</shortdesc>
+<parameters>
+
+<parameter name="binary" unique="0" required="0">
+<longdesc lang="en">
+Location of the MySQL server binary
+</longdesc>
+<shortdesc lang="en">MySQL server binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_binary_default}" />
+</parameter>
+
+<parameter name="client_binary" unique="0" required="0">
+<longdesc lang="en">
+Location of the MySQL client binary
+</longdesc>
+<shortdesc lang="en">MySQL client binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_client_binary_default}" />
+</parameter>
+
+<parameter name="config" unique="0" required="0">
+<longdesc lang="en">
+Configuration file
+</longdesc>
+<shortdesc lang="en">MySQL config</shortdesc>
+<content type="string" default="${OCF_RESKEY_config_default}" />
+</parameter>
+
+<parameter name="datadir" unique="0" required="0">
+<longdesc lang="en">
+Directory containing databases
+</longdesc>
+<shortdesc lang="en">MySQL datadir</shortdesc>
+<content type="string" default="${OCF_RESKEY_datadir_default}" />
+</parameter>
+
+<parameter name="user" unique="0" required="0">
+<longdesc lang="en">
+User running MySQL daemon
+</longdesc>
+<shortdesc lang="en">MySQL user</shortdesc>
+<content type="string" default="${OCF_RESKEY_user_default}" />
+</parameter>
+
+<parameter name="group" unique="0" required="0">
+<longdesc lang="en">
+Group running MySQL daemon (for logfile and directory permissions)
+</longdesc>
+<shortdesc lang="en">MySQL group</shortdesc>
+<content type="string" default="${OCF_RESKEY_group_default}"/>
+</parameter>
+
+<parameter name="log" unique="0" required="0">
+<longdesc lang="en">
+The logfile to be used for mysqld.
+</longdesc>
+<shortdesc lang="en">MySQL log file</shortdesc>
+<content type="string" default="${OCF_RESKEY_log_default}"/>
+</parameter>
+
+<parameter name="pid" unique="0" required="0">
+<longdesc lang="en">
+The pidfile to be used for mysqld.
+</longdesc>
+<shortdesc lang="en">MySQL pid file</shortdesc>
+<content type="string" default="${OCF_RESKEY_pid_default}"/>
+</parameter>
+
+<parameter name="socket" unique="0" required="0">
+<longdesc lang="en">
+The socket to be used for mysqld.
+</longdesc>
+<shortdesc lang="en">MySQL socket</shortdesc>
+<content type="string" default="${OCF_RESKEY_socket_default}"/>
+</parameter>
+
+<parameter name="test_table" unique="0" required="0">
+<longdesc lang="en">
+Table to be tested in monitor statement (in database.table notation)
+</longdesc>
+<shortdesc lang="en">MySQL test table</shortdesc>
+<content type="string" default="${OCF_RESKEY_test_table_default}" />
+</parameter>
+
+<parameter name="test_user" unique="0" required="0">
+<longdesc lang="en">
+MySQL test user, must have select privilege on test_table
+</longdesc>
+<shortdesc lang="en">MySQL test user</shortdesc>
+<content type="string" default="${OCF_RESKEY_test_user_default}" />
+</parameter>
+
+<parameter name="test_passwd" unique="0" required="0">
+<longdesc lang="en">
+MySQL test user password
+</longdesc>
+<shortdesc lang="en">MySQL test user password</shortdesc>
+<content type="string" default="${OCF_RESKEY_test_passwd_default}" />
+</parameter>
+
+<parameter name="enable_creation" unique="0" required="0">
+<longdesc lang="en">
+If the MySQL database does not exist, it will be created
+</longdesc>
+<shortdesc lang="en">Create the database if it does not exist</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_enable_creation_default}"/>
+</parameter>
+
+<parameter name="additional_parameters" unique="0" required="0">
+<longdesc lang="en">
+Additional parameters which are passed to the mysqld on startup.
+(e.g. --skip-external-locking or --skip-grant-tables)
+</longdesc>
+<shortdesc lang="en">Additional parameters to pass to mysqld</shortdesc>
+<content type="string" default="${OCF_RESKEY_additional_parameters_default}"/>
+</parameter>
+
+<parameter name="replication_user" unique="0" required="0">
+<longdesc lang="en">
+MySQL replication user. This user is used for starting and stopping
+MySQL replication, for setting and resetting the master host, and for
+setting and unsetting read-only mode. Because of that, this user must
+have SUPER, REPLICATION SLAVE, REPLICATION CLIENT, and PROCESS
+privileges on all nodes within the cluster. Mandatory if you define
+a master-slave resource.
+</longdesc>
+<shortdesc lang="en">MySQL replication user</shortdesc>
+<content type="string" default="${OCF_RESKEY_replication_user_default}" />
+</parameter>
+
+<parameter name="replication_passwd" unique="0" required="0">
+<longdesc lang="en">
+MySQL replication password. Used for replication client and slave.
+Mandatory if you define a master-slave resource.
+</longdesc>
+<shortdesc lang="en">MySQL replication user password</shortdesc>
+<content type="string" default="${OCF_RESKEY_replication_passwd_default}" />
+</parameter>
+
+<parameter name="replication_port" unique="0" required="0">
+<longdesc lang="en">
+The port on which the Master MySQL instance is listening.
+</longdesc>
+<shortdesc lang="en">MySQL replication port</shortdesc>
+<content type="string" default="${OCF_RESKEY_replication_port_default}" />
+</parameter>
+
+<parameter name="max_slave_lag" unique="0" required="0">
+<longdesc lang="en">
+The maximum number of seconds a replication slave is allowed to lag
+behind its master. Do not set this to zero. What the cluster manager
+does in case a slave exceeds this maximum lag is determined by the
+evict_outdated_slaves parameter.
+</longdesc>
+<shortdesc lang="en">Maximum time (seconds) a MySQL slave is allowed
+to lag behind a master</shortdesc>
+<content type="integer" default="${OCF_RESKEY_max_slave_lag_default}"/>
+</parameter>
+
+<parameter name="evict_outdated_slaves" unique="0" required="0">
+<longdesc lang="en">
+If set to true, any slave which is more than max_slave_lag seconds
+behind the master has its MySQL instance shut down. If this parameter
+is set to false in a primitive or clone resource, it is simply
+ignored. If set to false in a master/slave resource, then exceeding
+the maximum slave lag will merely push down the master preference so
+the lagging slave is never promoted to the new master.
+</longdesc>
+<shortdesc lang="en">Determines whether to shut down badly lagging
+slaves</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_evict_outdated_slaves_default}" />
+</parameter>
+
+<parameter name="reader_attribute" unique="1" required="0">
+<longdesc lang="en">
+An attribute that the RA can manage to specify whether a node
+can be read from. This node attribute will be 1 if it's fine to
+read from the node, and 0 otherwise (for example, when a slave
+has lagged too far behind the master).
+
+A typical example for the use of this attribute would be to tie
+a set of IP addresses to MySQL slaves that can be read from.
+
+This parameter is only meaningful in master/slave set configurations.
+</longdesc>
+<shortdesc lang="en">Sets the node attribute that determines
+whether a node is usable for clients to read from.</shortdesc>
+<content type="string" default="${OCF_RESKEY_reader_attribute_default}" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="120" />
+<action name="stop" timeout="120" />
+<action name="status" timeout="60" />
+<action name="monitor" depth="0" timeout="30" interval="20" />
+<action name="monitor" role="Master" depth="0" timeout="30" interval="10" />
+<action name="monitor" role="Slave" depth="0" timeout="30" interval="30" />
+<action name="promote" timeout="120" />
+<action name="demote" timeout="120" />
+<action name="notify" timeout="90" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+# Convenience functions
+
+set_read_only() {
+    # Sets or unsets read-only mode. Accepts one boolean as its
+    # optional argument. If invoked without any arguments, defaults to
+    # enabling read only mode. Should only be set in master/slave
+    # setups.
+    # Returns $OCF_SUCCESS if the operation succeeds, or
+    # $OCF_ERR_GENERIC if it fails.
+    local ro_val
+    if ocf_is_true $1; then
+        ro_val="on"
+    else
+        ro_val="off"
+    fi
+    ocf_run $MYSQL $MYSQL_OPTIONS_REPL \
+        -e "SET GLOBAL read_only=${ro_val}"
+}
+
+get_read_only() {
+    # Check if read-only is set
+    local read_only_state
+
+    read_only_state=`$MYSQL $MYSQL_OPTIONS_REPL \
+        -e "SHOW VARIABLES" | grep read_only | awk '{print $2}'`
+
+    if [ "$read_only_state" = "ON" ]; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+is_slave() {
+    # Determine whether the machine is currently running as a MySQL
+    # slave, as determined per SHOW SLAVE STATUS. Returns 1 if SHOW
+    # SLAVE STATUS creates an empty result set, 0 otherwise.
+    local rc
+    local tmpfile
+
+    # Check whether this machine should be slave
+    if ! ocf_is_ms || ! get_read_only; then
+        return 1
+    fi
+   
+    get_slave_info
+    rc=$?
+
+    if [ $rc -eq 0 ]; then
+       # show slave status is not empty
+       # Is there a master_log_file defined?  (master_log_file is deleted 
+       # by reset slave
+       if [ "$master_log_file" ]; then
+          return 0
+       else
+          return 1
+       fi
+    else
+       # "SHOW SLAVE STATUS" returns an empty set if instance is not a
+       # replication slave
+       return 1
+    fi
+    
+}
+
+parse_slave_info() {
+    # Extracts field $1 from result of "SHOW SLAVE STATUS\G" from file $2
+    sed -ne "s/^.* $1: \(.*\)$/\1/p" < $2
+}
+
+get_slave_info() {
+    # Warning: this sets $tmpfile and LEAVE this file! You must delete it after use!
+    local mysql_options
+            
+    if [ "$master_log_file" -a "$master_host" ]; then
+        # variables are already defined, get_slave_info has been run before
+        return $OCF_SUCCESS
+    else
+        tmpfile=`mktemp ${HA_RSCTMP}/check_slave.${OCF_RESOURCE_INSTANCE}.XXXXXX`
+
+        $MYSQL $MYSQL_OPTIONS_REPL \
+        -e 'SHOW SLAVE STATUS\G' > $tmpfile
+
+        if [ -s $tmpfile ]; then
+            master_host=`parse_slave_info Master_Host $tmpfile`
+            master_user=`parse_slave_info Master_User $tmpfile`
+            master_port=`parse_slave_info Master_Port $tmpfile`
+            master_log_file=`parse_slave_info Master_Log_File $tmpfile`
+            master_log_pos=`parse_slave_info Read_Master_Log_Pos $tmpfile`
+            slave_sql=`parse_slave_info Slave_SQL_Running $tmpfile`
+            slave_io=`parse_slave_info Slave_IO_Running $tmpfile`
+            last_errno=`parse_slave_info Last_Errno $tmpfile`
+            secs_behind=`parse_slave_info Seconds_Behind_Master $tmpfile`
+            ocf_log debug "MySQL instance running as a replication slave"
+        else
+            # Instance produced an empty "SHOW SLAVE STATUS" output --
+            # instance is not a slave
+            ocf_log err "check_slave invoked on an instance that is not a replication slave."
+            return $OCF_ERR_GENERIC
+        fi
+
+        return $OCF_SUCCESS
+    fi
+}
+
+check_slave() {
+    # Checks slave status
+    local rc new_master
+
+    get_slave_info
+    rc=$?
+
+    if [ $rc -eq 0 ]; then
+        # Did we receive an error other than max_connections?
+        if [ $last_errno -ne 0 -a $last_errno -ne "$MYSQL_TOO_MANY_CONN_ERR" ]; then
+            # Whoa. Replication ran into an error. This slave has
+            # diverged from its master. Make sure this resource
+            # doesn't restart in place.
+            ocf_log err "MySQL instance configured for replication, but replication has failed."
+            ocf_log err "See $tmpfile for details"
+
+            # Just pull the reader VIP away, killing MySQL here would be pretty evil
+            # on a loaded server
+
+            set_reader_attr 0
+            exit $OCF_SUCCESS
+
+        fi
+
+        # If we got max_connections, let's remove the vip
+        if [ $last_errno -eq "$MYSQL_TOO_MANY_CONN_ERR" ]; then
+            set_reader_attr 0
+            exit $OCF_SUCCESS
+        fi
+
+        if [ "$slave_io" != 'Yes' ]; then
+            # Not necessarily a bad thing. The master may have
+            # temporarily shut down, and the slave may just be
+            # reconnecting. A warning can't hurt, though.
+            ocf_log warn "MySQL Slave IO threads currently not running."
+
+            # Sanity check, are we at least on the right master
+            new_master=`$CRM_ATTR_REPL_INFO --query  -q | cut -d'|' -f1`
+
+            if [ "$master_host" != "$new_master" ]; then
+               # Not pointing to the right master, not good, removing the VIPs
+               set_reader_attr 0
+
+               exit $OCF_SUCCESS
+            fi
+
+        fi
+
+        if [ "$slave_sql" != 'Yes' ]; then
+            # We don't have a replication SQL thread running. Not a
+            # good thing. Try to recoved by restarting the SQL thread
+            # and remove reader vip.  Prevent MySQL restart.
+            ocf_log err "MySQL Slave SQL threads currently not running."
+            ocf_log err "See $tmpfile for details"
+
+            # Remove reader vip
+            set_reader_attr 0
+
+            # try to restart slave
+            ocf_run $MYSQL $MYSQL_OPTIONS_REPL \
+                -e "START SLAVE"
+
+            # Return success to prevent a restart
+            exit $OCF_SUCCESS
+        fi
+
+        if ocf_is_true $OCF_RESKEY_evict_outdated_slaves; then
+            # We're supposed to bail out if we lag too far
+            # behind. Let's check our lag.
+            if [ $secs_behind -gt $OCF_RESKEY_max_slave_lag ]; then
+                ocf_log err "MySQL Slave is $secs_behind seconds behind master (allowed maximum: $OCF_RESKEY_max_slave_lag)."
+                ocf_log err "See $tmpfile for details"
+
+                # Remove reader vip
+                set_reader_attr 0
+
+                exit $OCF_ERR_INSTALLED
+            fi
+            elif ocf_is_ms; then
+            # Even if we're not set to evict lagging slaves, we can
+            # still use the seconds behind master value to set our
+            # master preference.
+            local master_pref
+            master_pref=$((${OCF_RESKEY_max_slave_lag}-${secs_behind}))
+            if [ $master_pref -lt 0 ]; then
+                # Sanitize a below-zero preference to just zero
+                master_pref=0
+            fi
+            $CRM_MASTER -v $master_pref
+        fi
+
+        # is the slave ok to have a VIP on it
+        if [ $secs_behind -gt $OCF_RESKEY_max_slave_lag ]; then
+            set_reader_attr 0
+        else
+            set_reader_attr 1
+        fi
+
+        ocf_log debug "MySQL instance running as a replication slave"
+        rm -f $tmpfile
+    else
+        # Instance produced an empty "SHOW SLAVE STATUS" output --
+        # instance is not a slave
+        # TODO: Needs to handle when get_slave_info will return too many connections error
+        rm -f $tmpfile
+        ocf_log err "check_slave invoked on an instance that is not a replication slave."
+        exit $OCF_ERR_GENERIC
+    fi
+}
+
+set_master() {
+    local new_master master_log_file master_log_pos
+    local master_params
+
+    new_master=`$CRM_ATTR_REPL_INFO --query  -q | cut -d'|' -f1`
+
+    # Keep replication position
+    get_slave_info
+
+    if [ "$master_log_file" -a "$new_master" = "$master_host" ]; then
+        #	master_params=", MASTER_LOG_FILE='$master_log_file', \
+        #	    MASTER_LOG_POS=$master_log_pos"
+        ocf_log info "Kept master pos for $master_host : $master_log_file:$master_log_pos"
+        rm -f $tmpfile
+        return
+    else
+        master_log_file=`$CRM_ATTR_REPL_INFO --query  -q | cut -d'|' -f2`
+        master_log_pos=`$CRM_ATTR_REPL_INFO --query  -q | cut -d'|' -f3`
+        if [ -n "$master_log_file" -a -n "$master_log_pos" ]; then
+            master_params=", MASTER_LOG_FILE='$master_log_file', \
+            MASTER_LOG_POS=$master_log_pos"
+            ocf_log info "Restored master pos for $new_master : $master_log_file:$master_log_pos"
+        fi
+    fi
+
+    # Informs the MySQL server of the master to replicate
+    # from. Accepts one mandatory argument which must contain the host
+    # name of the new master host. The master must either be unchanged
+    # from the laste master the slave replicated from, or freshly
+    # reset with RESET MASTER.
+
+    ocf_run $MYSQL $MYSQL_OPTIONS_REPL \
+        -e "CHANGE MASTER TO MASTER_HOST='$new_master', \
+        MASTER_USER='$OCF_RESKEY_replication_user', \
+        MASTER_PASSWORD='$OCF_RESKEY_replication_passwd' $master_params"
+    rm -f $tmpfile
+}
+
+unset_master(){
+    # Instructs the MySQL server to stop replicating from a master
+    # host.
+
+    # If we're currently not configured to be replicating from any
+    # host, then there's nothing to do. But we do log a warning as
+    # no-one but the CRM should be touching the MySQL master/slave
+    # configuration.
+    if ! is_slave; then
+        ocf_log warn "Attempted to unset the replication master on an instance that is not configured as a replication slave"
+        return $OCF_SUCCESS
+    fi
+
+    local tmpfile
+    tmpfile=`mktemp ${HA_RSCTMP}/unset_master.${OCF_RESOURCE_INSTANCE}.XXXXXX`
+
+    # At this point, the master is read only so there should not be much binlogs to transfer
+    # Let's wait for the last bits
+    while true; do
+        $MYSQL $MYSQL_OPTIONS_REPL \
+        -e 'SHOW PROCESSLIST\G' > $tmpfile
+        if grep -i 'Waiting for master to send event' $tmpfile >/dev/null; then
+            ocf_log info "MySQL slave has finished reading master binary log"
+            break
+        fi
+        if grep -i 'Reconnecting after a failed master event read' $tmpfile >/dev/null; then
+            ocf_log info "Master is down, no more binary logs to come"
+            break
+        fi
+        if grep -i 'Connecting to master' $tmpfile >/dev/null; then
+            ocf_log info "Master is down, no more binary logs to come"
+            break
+        fi
+        if ! grep 'system user' $tmpfile >/dev/null; then
+            ocf_log info "Slave is not running - not waiting to finish"
+            break
+        fi
+
+        sleep 1
+    done
+
+    # Now, stop the slave I/O thread and wait for relay log
+    # processing to complete
+    ocf_run $MYSQL $MYSQL_OPTIONS_REPL \
+        -e "STOP SLAVE IO_THREAD"
+    if [ $? -gt 0 ]; then
+        ocf_log err "Error stopping slave IO thread"
+        exit $OCF_ERR_GENERIC
+    fi
+
+    while true; do
+        $MYSQL $MYSQL_OPTIONS_REPL \
+            -e 'SHOW PROCESSLIST\G' > $tmpfile
+        if grep -i 'Has read all relay log' $tmpfile >/dev/null; then
+            ocf_log info "MySQL slave has finished processing relay log"
+            break
+        fi
+        if ! grep -q 'system user' $tmpfile; then
+            ocf_log info "Slave not runnig - not waiting to finish"
+            break
+        fi
+        ocf_log info "Waiting for MySQL slave to finish processing relay log"
+        sleep 1
+    done
+    rm -f $tmpfile
+
+    # Now, stop all slave activity and unset the master host
+    ocf_run $MYSQL $MYSQL_OPTIONS_REPL \
+        -e "STOP SLAVE"
+    if [ $? -gt 0 ]; then
+        ocf_log err "Error stopping rest slave threads"
+        exit $OCF_ERR_GENERIC
+    fi
+
+    ocf_run $MYSQL $MYSQL_OPTIONS_REPL \
+        -e "RESET SLAVE /*!50516 ALL */;"
+    if [ $? -gt 0 ]; then
+        ocf_log err "Failed to reset slave"
+        exit $OCF_ERR_GENERIC
+    fi
+}
+
+# Start replication as slave
+start_slave() {
+
+    ocf_run $MYSQL $MYSQL_OPTIONS_REPL \
+        -e "START SLAVE"
+}
+
+# Set the attribute controlling the readers VIP
+set_reader_attr() {
+    local curr_attr_value
+
+    curr_attr_value=$(get_reader_attr)
+
+    if [ "$curr_attr_value" -ne "$1" ]; then
+        $CRM_ATTR -l reboot --name ${OCF_RESKEY_reader_attribute} -v $1
+    fi
+
+}
+
+# get the attribute controlling the readers VIP
+get_reader_attr() {
+    local attr_value
+    local rc
+
+    attr_value=`$CRM_ATTR -l reboot --name ${OCF_RESKEY_reader_attribute} --query -q`
+    rc=$?
+    if [ "$rc" -eq "0" ]; then
+        echo $attr_value
+    else
+        echo -1
+    fi
+
+}
+
+# Stores data for MASTER STATUS from MySQL
+update_data_master_status() {
+
+   master_status_file="${HA_RSCTMP}/master_status.${OCF_RESOURCE_INSTANCE}"
+
+   $MYSQL $MYSQL_OPTIONS_REPL -e "SHOW MASTER STATUS\G" > $master_status_file
+}
+
+
+# Returns the specified value from the stored copy of SHOW MASTER STATUS.
+# should be call after update_data_master_status for tmpfile
+# Arguments:
+#  $1 The value to get.
+get_master_status() {
+   awk -v var="$1" '$1 == var ":" {print substr($0, index($0, ":") + 2)}' "$master_status_file"
+}
+
+
+# Determines what IP address is attached to the current host.  The output of the
+# crm_attribute command looks like this:
+# scope=nodes  name=IP value=10.2.2.161
+# If the ${INSTANCE_ATTR_NAME}_MYSQL_MASTER_IP node attribute is not defined, fallback is to uname -n
+# The ${INSTANCE_ATTR_NAME}_MYSQL_MASTER_IP is the IP address that will be used for the 
+# change master to command.
+get_local_ip() {
+   local IP
+   IP=`$CRM_ATTR -l forever -n ${INSTANCE_ATTR_NAME}_mysql_master_IP -q -G`
+   if [ ! $? -eq 0 ]; then
+      uname -n
+   else
+      echo $IP
+   fi
+}
+
+#######################################################################
+
+# Functions invoked by resource manager actions
+
+mysql_validate() {
+    check_binary $OCF_RESKEY_binary
+    check_binary  $OCF_RESKEY_client_binary
+
+    if [ ! -f $OCF_RESKEY_config ]; then
+        ocf_log err "Config $OCF_RESKEY_config doesn't exist";
+        return $OCF_ERR_INSTALLED;
+    fi
+
+    if [ ! -d $OCF_RESKEY_datadir ]; then
+        ocf_log err "Datadir $OCF_RESKEY_datadir doesn't exist";
+        return $OCF_ERR_INSTALLED;
+    fi
+
+    getent passwd $OCF_RESKEY_user >/dev/null 2>&1
+    if [ ! $? -eq 0 ]; then
+        ocf_log err "User $OCF_RESKEY_user doesn't exit";
+        return $OCF_ERR_INSTALLED;
+    fi
+
+    getent group $OCF_RESKEY_group >/dev/null 2>&1
+    if [ ! $? -eq 0 ]; then
+        ocf_log err "Group $OCF_RESKEY_group doesn't exist";
+        return $OCF_ERR_INSTALLED;
+    fi
+
+    true
+}
+
+mysql_status() {
+    if [ ! -e $OCF_RESKEY_pid ]; then
+        ocf_log $1 "MySQL is not running"
+        return $OCF_NOT_RUNNING;
+    fi
+
+    pid=`cat $OCF_RESKEY_pid`;
+    if [ -d /proc -a -d /proc/1 ]; then
+        [ "u$pid" != "u" -a -d /proc/$pid ]
+    else
+        kill -s 0 $pid >/dev/null 2>&1
+    fi
+
+    if [ $? -eq 0 ]; then
+        return $OCF_SUCCESS;
+    else
+        ocf_log $1 "MySQL not running: removing old PID file"
+        rm -f $OCF_RESKEY_pid
+        return $OCF_NOT_RUNNING;
+    fi
+}
+
+mysql_monitor() {
+    local rc
+    local status_loglevel="err"
+
+    # Set loglevel to info during probe
+    if ocf_is_probe; then
+        status_loglevel="info"
+    fi
+ 
+    mysql_status $status_loglevel
+
+    rc=$?
+
+    # TODO: check max connections error
+
+    # If status returned an error, return that immediately
+    if [ $rc -ne $OCF_SUCCESS ]; then
+        return $rc
+    fi
+
+
+    if [ $OCF_CHECK_LEVEL -gt 0 -a -n "$OCF_RESKEY_test_table" ]; then
+        # Check if this instance is configured as a slave, and if so
+        # check slave status
+        if is_slave; then
+            check_slave
+        fi
+
+        # Check for test table
+        ocf_run -q $MYSQL $MYSQL_OPTIONS_TEST \
+            -e "SELECT COUNT(*) FROM $OCF_RESKEY_test_table"
+        rc=$?
+
+        if [ $rc -ne 0 ]; then
+            ocf_log err "Failed to select from $test_table";
+            return $OCF_ERR_GENERIC;
+        fi
+    fi
+
+    if ocf_is_ms && ! get_read_only; then
+        ocf_log debug "MySQL monitor succeeded (master)";
+        return $OCF_RUNNING_MASTER
+    else
+        ocf_log debug "MySQL monitor succeeded";
+        return $OCF_SUCCESS
+    fi
+}
+
+mysql_start() {
+    local rc pid
+
+    if ocf_is_ms; then
+        # Initialize the ReaderVIP attribute, monitor will enable it
+        set_reader_attr 0
+    fi
+
+    mysql_status info
+    if [ $? = $OCF_SUCCESS ]; then
+        ocf_log info "MySQL already running"
+        return $OCF_SUCCESS
+    fi
+
+    touch $OCF_RESKEY_log
+    chown $OCF_RESKEY_user:$OCF_RESKEY_group $OCF_RESKEY_log
+    chmod 0640 $OCF_RESKEY_log
+    [ -x /sbin/restorecon ] && /sbin/restorecon $OCF_RESKEY_log
+
+    if ocf_is_true "$OCF_RESKEY_enable_creation" && [ ! -d $OCF_RESKEY_datadir/mysql ] ; then
+        ocf_log info "Initializing MySQL database: "
+        $MYSQL_BINDIR/mysql_install_db --datadir=$OCF_RESKEY_datadir
+        rc=$?
+        if [ $rc -ne 0 ] ; then
+            ocf_log err "Initialization failed: $rc";
+            exit $OCF_ERR_GENERIC
+        fi
+        chown -R $OCF_RESKEY_user:$OCF_RESKEY_group $OCF_RESKEY_datadir
+    fi
+
+    pid_dir=`dirname $OCF_RESKEY_pid`
+    if [ ! -d $pid_dir ] ; then
+        ocf_log info "Creating PID dir: $pid_dir"
+        mkdir -p $pid_dir
+        chown $OCF_RESKEY_user:$OCF_RESKEY_group $pid_dir
+    fi
+
+    socket_dir=`dirname $OCF_RESKEY_socket`
+    if [ ! -d $socket_dir ] ; then
+        ocf_log info "Creating socket dir: $socket_dir"
+        mkdir -p $socket_dir
+        chown $OCF_RESKEY_user:$OCF_RESKEY_group $socket_dir
+    fi
+
+    # Regardless of whether we just created the directory or it
+    # already existed, check whether it is writable by the configured
+    # user
+    for dir in $pid_dir $socket_dir; do
+        if ! su -s /bin/sh - $OCF_RESKEY_user -c "test -w $dir"; then
+            ocf_log err "Directory $dir is not writable by $OCF_RESKEY_user"
+            exit $OCF_ERR_PERM;
+        fi
+    done
+
+    # Uncomment to perform permission clensing
+    # - not convinced this should be enabled by default
+    #
+    #chmod 0755 $OCF_RESKEY_datadir
+    #chown -R $OCF_RESKEY_user $OCF_RESKEY_datadir
+    #chgrp -R $OCF_RESKEY_group $OCF_RESKEY_datadir
+    mysql_extra_params=
+    if ocf_is_ms; then
+        mysql_extra_params="--skip-slave-start"
+    fi
+
+    ${OCF_RESKEY_binary} --defaults-file=$OCF_RESKEY_config \
+    --pid-file=$OCF_RESKEY_pid \
+    --socket=$OCF_RESKEY_socket \
+    --datadir=$OCF_RESKEY_datadir \
+    --log-error=$OCF_RESKEY_log \
+    --user=$OCF_RESKEY_user $OCF_RESKEY_additional_parameters \
+    $mysql_extra_params >/dev/null 2>&1 &
+    pid=$!
+
+    # Spin waiting for the server to come up.
+    # Let the CRM/LRM time us out if required.
+    start_wait=1
+    while [ $start_wait = 1 ]; do
+        if ! ps $pid > /dev/null 2>&1; then
+            wait $pid
+            ocf_log err "MySQL server failed to start (rc=$?), please check your installation"
+            return $OCF_ERR_GENERIC
+        fi
+        mysql_status info
+        rc=$?
+        if [ $rc = $OCF_SUCCESS ]; then
+            start_wait=0
+        elif [ $rc != $OCF_NOT_RUNNING ]; then
+            ocf_log info "MySQL start failed: $rc"
+            return $rc
+        fi
+        sleep 2
+    done
+
+    if ocf_is_ms; then
+        # We're configured as a stateful resource. We must start as
+        # slave by default. At this point we don't know if the CRM has
+        # already promoted a master. So, we simply start in read only
+        # mode.
+        set_read_only on
+
+        # Now, let's see whether there is a master. We might be a new
+        # node that is just joining the cluster, and the CRM may have
+        # promoted a master before.
+        master_host=`echo $OCF_RESKEY_CRM_meta_notify_master_uname|tr -d " "`
+        if [ "$master_host" -a "$master_host" != ${NODENAME} ]; then
+            ocf_log info "Changing MySQL configuration to replicate from $master_host."
+            set_master
+            start_slave
+            if [ $? -ne 0 ]; then
+                ocf_log err "Failed to start slave"
+                return $OCF_ERR_GENERIC
+            fi
+        else
+            ocf_log info "No MySQL master present - clearing replication state"
+            unset_master
+        fi
+
+        # We also need to set a master preference, otherwise Pacemaker
+        # won't ever promote us in the absence of any explicit
+        # preference set by the administrator. We choose a low
+        # greater-than-zero preference.
+        $CRM_MASTER -v 1
+
+    fi
+
+    # Initial monitor action
+    if [ -n "$OCF_RESKEY_test_table" -a -n "$OCF_RESKEY_test_user" -a -n "$OCF_RESKEY_test_passwd" ]; then
+        OCF_CHECK_LEVEL=10
+    fi
+    mysql_monitor
+    rc=$?
+    if [ $rc != $OCF_SUCCESS -a $rc != $OCF_RUNNING_MASTER ]; then
+        ocf_log err "Failed initial monitor action"
+        return $rc
+    fi
+
+    ocf_log info "MySQL started"
+    return $OCF_SUCCESS
+}
+
+mysql_stop() {
+
+    if ocf_is_ms; then
+        # clear preference for becoming master
+        $CRM_MASTER -D
+
+        # Remove VIP capability
+        set_reader_attr 0
+    fi
+
+    if [ ! -f $OCF_RESKEY_pid ]; then
+        ocf_log info "MySQL is not running"
+        return $OCF_SUCCESS
+    fi
+
+    pid=`cat $OCF_RESKEY_pid 2> /dev/null `
+    /bin/kill $pid > /dev/null
+    rc=$?
+    if [ $rc != 0 ]; then
+        ocf_log err "MySQL couldn't be stopped"
+        return $OCF_ERR_GENERIC
+    fi
+    # stop waiting
+    shutdown_timeout=15
+    if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
+        shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5))
+    fi
+    count=0
+    while [ $count -lt $shutdown_timeout ]
+    do
+        mysql_status info
+        rc=$?
+        if [ $rc = $OCF_NOT_RUNNING ]; then
+            break
+        fi
+        count=`expr $count + 1`
+        sleep 1
+        ocf_log debug "MySQL still hasn't stopped yet. Waiting..."
+    done
+
+    mysql_status info
+    if [ $? != $OCF_NOT_RUNNING ]; then
+        ocf_log info "MySQL failed to stop after ${shutdown_timeout}s using SIGTERM. Trying SIGKILL..."
+        /bin/kill -KILL $pid > /dev/null
+    fi
+
+    ocf_log info "MySQL stopped";
+    rm -f /var/lock/subsys/mysqld
+    rm -f $OCF_RESKEY_socket
+    return $OCF_SUCCESS
+}
+
+mysql_promote() {
+    local master_info
+
+    if ( ! mysql_status err ); then
+        return $OCF_NOT_RUNNING
+    fi
+    ocf_run $MYSQL $MYSQL_OPTIONS_REPL \
+        -e "STOP SLAVE"
+
+    # Set Master Info in CIB, cluster level attribute
+    update_data_master_status
+    master_info="$(get_local_ip)|$(get_master_status File)|$(get_master_status Position)"
+    ${CRM_ATTR_REPL_INFO} -v "$master_info"
+    rm -f $tmpfile
+
+    set_read_only off || return $OCF_ERR_GENERIC
+
+    # Existing master gets a higher-than-default master preference, so
+    # the cluster manager does not shuffle the master role around
+    # unnecessarily
+    $CRM_MASTER -v $((${OCF_RESKEY_max_slave_lag}+1))
+
+    # A master can accept reads
+    set_reader_attr 1
+
+    return $OCF_SUCCESS
+}
+
+mysql_demote() {
+    if ! mysql_status err; then
+        return $OCF_NOT_RUNNING
+    fi
+
+    # Return master preference to default, so the cluster manager gets
+    # a chance to select a new master
+    $CRM_MASTER -v 1
+}
+
+mysql_notify() {
+    # If not configured as a Stateful resource, we make no sense of
+    # notifications.
+    if ! ocf_is_ms; then
+        ocf_log info "This agent makes no use of notifications unless running in master/slave mode."
+        return $OCF_SUCCESS
+    fi
+
+    local type_op
+    type_op="${OCF_RESKEY_CRM_meta_notify_type}-${OCF_RESKEY_CRM_meta_notify_operation}"
+
+    ocf_log debug "Received $type_op notification."
+
+    case "$type_op" in
+        'pre-promote')
+            # Nothing to do now here, new replication info not yet published
+
+        ;;
+        'post-promote')
+            # The master has completed its promotion. Now is a good
+            # time to check whether our replication slave is working
+            # correctly.
+            master_host=`echo $OCF_RESKEY_CRM_meta_notify_promote_uname|tr -d " "`
+            if [ "$master_host" = ${NODENAME} ]; then
+                ocf_log info "This will be the new master, ignoring post-promote notification."
+            else
+                ocf_log info "Resetting replication"
+                unset_master
+                if [ $? -ne 0 ]; then
+                    return $OCF_ERR_GENERIC
+                fi
+
+                ocf_log info "Changing MySQL configuration to replicate from $master_host"
+                set_master
+                if [ $? -ne 0 ]; then
+                    return $OCF_ERR_GENERIC
+                fi
+
+                start_slave
+                if [ $? -ne 0 ]; then
+                    ocf_log err "Failed to start slave"
+                    return $OCF_ERR_GENERIC
+                fi
+            fi
+            return $OCF_SUCCESS
+        ;;
+        'pre-demote')
+            demote_host=`echo $OCF_RESKEY_CRM_meta_notify_demote_uname|tr -d " "`
+            if [ $demote_host = ${NODENAME} ]; then
+                ocf_log info "post-demote notification for $demote_host"
+                set_read_only on
+                if [ $? -ne 0 ]; then
+                    ocf_log err "Failed to set read-only";
+                    return $OCF_ERR_GENERIC;
+                fi
+
+                # Must kill all existing user threads because they are still Read/write
+                # in order for the slaves to complete the read of binlogs
+                local tmpfile
+                tmpfile=`mktemp ${HA_RSCTMP}/threads.${OCF_RESOURCE_INSTANCE}.XXXXXX`
+                $MYSQL $MYSQL_OPTIONS_REPL \
+                -e "SHOW PROCESSLIST" > $tmpfile
+
+                for thread in `awk '$0 !~ /Binlog Dump|system user|event_scheduler|SHOW PROCESSLIST/ && $0 ~ /^[0-9]/ {print $1}' $tmpfile`
+                do
+                    ocf_run $MYSQL $MYSQL_OPTIONS_REPL \
+                        -e "KILL ${thread}"
+                done
+            else
+               ocf_log info "Ignoring post-demote notification execpt for my own demotion."
+            fi
+            return $OCF_SUCCESS
+        ;;
+        'post-demote')
+            demote_host=`echo $OCF_RESKEY_CRM_meta_notify_demote_uname|tr -d " "`
+            if [ $demote_host = ${NODENAME} ]; then
+                ocf_log info "Ignoring post-demote notification for my own demotion."
+                return $OCF_SUCCESS
+            fi
+            ocf_log info "post-demote notification for $demote_host."
+            # The former master has just been gracefully demoted.
+            unset_master
+        ;;
+        *)
+            return $OCF_SUCCESS
+        ;;
+    esac
+}
+
+#######################################################################
+
+
+##########################################################################
+# If DEBUG_LOG is set, make this resource agent easy to debug: set up the
+# debug log and direct all output to it.  Otherwise, redirect to /dev/null.
+# The log directory must be a directory owned by root, with permissions 0700,
+# and the log must be writable and not a symlink.
+##########################################################################
+DEBUG_LOG="/tmp/mysql.ocf.ra.debug/log"
+if [ "${DEBUG_LOG}" -a -w "${DEBUG_LOG}" -a ! -L "${DEBUG_LOG}" ]; then
+    DEBUG_LOG_DIR="${DEBUG_LOG%/*}"
+    if [ -d "${DEBUG_LOG_DIR}" ]; then
+        exec 9>>"$DEBUG_LOG"
+        exec 2>&9
+        date >&9
+        echo "$*" >&9
+        env | grep OCF_ | sort >&9
+        set -x
+    else
+        exec 9>/dev/null
+    fi
+fi
+
+case "$1" in
+  meta-data)    meta_data
+        exit $OCF_SUCCESS;;
+  usage|help)   usage
+        exit $OCF_SUCCESS;;
+esac
+
+mysql_validate
+rc=$?
+LSB_STATUS_STOPPED=3
+if [ $rc -ne 0 ]; then
+    case "$1" in
+        stop) exit $OCF_SUCCESS;;
+        monitor) exit $OCF_NOT_RUNNING;;
+        status) exit $LSB_STATUS_STOPPED;;
+        *) exit $rc;;
+    esac
+fi
+
+# What kind of method was invoked?
+case "$1" in
+  start)    mysql_start;;
+  stop)     mysql_stop;;
+  status)   mysql_status err;;
+  monitor)  mysql_monitor;;
+  promote)  mysql_promote;;
+  demote)   mysql_demote;;
+  notify)   mysql_notify;;
+  validate-all) exit $OCF_SUCCESS;;
+
+ *)     usage
+        exit $OCF_ERR_UNIMPLEMENTED;;
+esac
+
+# vi:sw=4:ts=4:et:
diff --git a/heartbeat/mysql-proxy b/heartbeat/mysql-proxy
new file mode 100755
index 0000000..024e97e
--- /dev/null
+++ b/heartbeat/mysql-proxy
@@ -0,0 +1,719 @@
+#!/bin/sh
+#
+# Resource script for MySQL Proxy
+#
+# Description:  Manages MySQL Proxy as an OCF resource in
+#               an high-availability setup.
+#
+#               Tested with MySQL Proxy 0.8.1 and 0.8.3 on Debian 6.0.
+#
+#               Based on the mysql and Pure-Ftpd OCF resource agents.
+#
+# Author:       Raoul Bhatia <r.bhatia at ipax.at> : Original Author
+# License:      GNU General Public License (GPL)
+#
+#
+#       usage: $0 {start|stop|reload|status|monitor|validate-all|meta-data}
+#
+#       The "start" arg starts a MySQL Proxy instance
+#
+#       The "stop" arg stops it.
+#
+# TODO
+# * add in-depth monitoring by querying the mysql-proxy admin port
+#
+# Test via
+# (note: this did not work with MySQL Proxy 0.8.1 and ocf-tester from resource-agents 3.9.2 on Debian 6.0)
+#
+# * /usr/sbin/ocf-tester -n mp -o binary="/usr/sbin/mysql-proxy" -o defaults_file="" -o parameters="--proxy-skip-profiling" \
+#       -o admin_address="127.0.0.1:4041" -o admin_username="root" -o admin_password="la" -o admin_lua_script="/usr/lib/mysql-proxy/lua/admin.lua" \
+#       -o proxy_backend_addresses="192.168.100.200:42006" -o proxy_address="/var/run/mysqld/mysqld.sock" /usr/lib/ocf/resource.d/heartbeat/mysql-proxy
+#
+#
+# OCF parameters:
+#  OCF_RESKEY_binary
+#  OCF_RESKEY_client_binary
+#  OCF_RESKEY_defaults_file
+#  OCF_RESKEY_proxy_backend_addresses
+#  OCF_RESKEY_proxy_read_only_backend_addresses
+#  OCF_RESKEY_proxy_address
+#  OCF_RESKEY_log_level
+#  OCF_RESKEY_keepalive
+#  OCF_RESKEY_plugins
+#  OCF_RESKEY_admin_address
+#  OCF_RESKEY_admin_username
+#  OCF_RESKEY_admin_password
+#  OCF_RESKEY_admin_lua_script
+#  OCF_RESKEY_test_table
+#  OCF_RESKEY_test_user
+#  OCF_RESKEY_test_passwd
+#  OCF_RESKEY_parameters
+#  OCF_RESKEY_pidfile
+#
+##########################################################################
+
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+: ${OCF_RESKEY_binary="/usr/sbin/mysql-proxy"}
+: ${OCF_RESKEY_client_binary="mysql"}
+: ${OCF_RESKEY_defaults_file=""}
+: ${OCF_RESKEY_proxy_backend_addresses="127.0.0.1:3306"}
+: ${OCF_RESKEY_proxy_read_only_backend_addresses=""}
+: ${OCF_RESKEY_proxy_address=":4040"}
+: ${OCF_RESKEY_log_level=""}
+: ${OCF_RESKEY_keepalive=""}
+: ${OCF_RESKEY_plugins=""}
+: ${OCF_RESKEY_admin_address="127.0.0.1:4041"}
+: ${OCF_RESKEY_admin_username=""}
+: ${OCF_RESKEY_admin_password=""}
+: ${OCF_RESKEY_admin_lua_script=""}
+: ${OCF_RESKEY_test_table="mysql.user"}
+: ${OCF_RESKEY_test_user=""}
+: ${OCF_RESKEY_test_passwd=""}
+: ${OCF_RESKEY_parameters=""}
+: ${OCF_RESKEY_pidfile="${HA_RSCTMP}/mysql-proxy-${OCF_RESOURCE_INSTANCE}.pid"}
+USAGE="Usage: $0 {start|stop|reload|status|monitor|validate-all|meta-data}"
+
+##########################################################################
+
+usage() {
+    echo $USAGE >&2
+}
+
+meta_data() {
+        cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="mysql-proxy">
+<version>0.1</version>
+<longdesc lang="en">
+This script manages MySQL Proxy as an OCF resource in a high-availability setup.
+
+The default monitor operation will verify that mysql-proxy is running.
+
+The level 10 monitor operation is left out intentionally for possible future enhancements in conjunction with the admin plugin.
+
+The level 20 monitor operation will perform a SELECT on a given table to verify that the connection to a back-end server is actually working.
+
+Tested with MySQL Proxy 0.8.1 and 0.8.3 on Debian 6.0.
+</longdesc>
+<shortdesc lang="en">Manages a MySQL Proxy instance</shortdesc>
+
+<parameters>
+
+<parameter name="binary" unique="0" required="0">
+<longdesc lang="en">
+Full path to the MySQL Proxy binary.
+For example, "/usr/sbin/mysql-proxy".
+</longdesc>
+<shortdesc lang="en">Full path to MySQL Proxy binary</shortdesc>
+<content type="string" default="/usr/sbin/mysql-proxy" />
+</parameter>
+
+<parameter name="client_binary" unique="0" required="0">
+<longdesc lang="en">
+Location of the MySQL client binary.
+</longdesc>
+<shortdesc lang="en">MySQL client binary</shortdesc>
+<content type="string" default="mysql" />
+</parameter>
+
+<parameter name="defaults_file" unique="0" required="0">
+<longdesc lang="en">
+Full path to a MySQL Proxy configuration file.
+For example, "/etc/mysql-proxy.conf".
+</longdesc>
+<shortdesc lang="en">Full path to configuration file</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="proxy_backend_addresses" unique="0" required="0">
+<longdesc lang="en">
+Address:port of the remote back-end servers (default: 127.0.0.1:3306).
+</longdesc>
+<shortdesc lang="en">MySQL Proxy back-end servers</shortdesc>
+<content type="string" default="127.0.0.1:3306" />
+</parameter>
+
+<parameter name="proxy_read_only_backend_addresses" unique="0" required="0">
+<longdesc lang="en">
+Address:port of the remote (read only) slave-server (default: ).
+</longdesc>
+<shortdesc lang="en">MySql Proxy read only back-end servers</shortdesc>
+<content type="string" default="127.0.0.1:3306" />
+</parameter>
+
+<parameter name="proxy_address" unique="0" required="0">
+<longdesc lang="en">
+Listening address:port of the proxy server (default: :4040).
+You can also specify a socket like "/tmp/mysql-proxy.sock".
+</longdesc>
+<shortdesc lang="en">MySQL Proxy listening address</shortdesc>
+<content type="string" default=":4040" />
+</parameter>
+
+<parameter name="log_level" unique="0" required="0">
+<longdesc lang="en">
+Log all messages of level (error|warning|info|message|debug|) or higher.
+An empty value disables logging.
+</longdesc>
+<shortdesc lang="en">MySQL Proxy log level.</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="keepalive" unique="0" required="0">
+<longdesc lang="en">
+Try to restart the proxy if it crashed (default: ).
+Valid values: true or false. An empty value equals "false".
+</longdesc>
+<shortdesc lang="en">Use keepalive option</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="plugins" unique="0" required="0">
+<longdesc lang="en">
+Whitespace separated list of plugins to load (default: ).
+Note: The admin plugin will be auto-loaded in case you specify an admin_* parameter.
+</longdesc>
+<shortdesc lang="en">MySQL Proxy plugins</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="admin_address" unique="0" required="0">
+<longdesc lang="en">
+Listening address:port of the admin plugin (default: 127.0.0.1:4041).
+Note: The admin plugin will be auto-loaded in case you specify an admin_* parameter.
+</longdesc>
+<shortdesc lang="en">MySQL Proxy admin plugin listening address</shortdesc>
+<content type="string" default="127.0.0.1:4041" />
+</parameter>
+
+<parameter name="admin_username" unique="0" required="0">
+<longdesc lang="en">
+Username for the admin plugin (default: ).
+Required since MySQL Proxy 0.8.1, if the admin plugin is loaded.
+Note: The admin plugin will be auto-loaded in case you specify an admin_* parameter.
+</longdesc>
+<shortdesc lang="en">MySQL Proxy admin plugin username</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="admin_password" unique="0" required="0">
+<longdesc lang="en">
+Password for the admin plugin (default: ).
+Required since MySQL Proxy 0.8.1, if the admin plugin is loaded.
+Note: The admin plugin will be auto-loaded in case you specify an admin_* parameter.
+</longdesc>
+<shortdesc lang="en">MySQL Proxy admin plugin password</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="admin_lua_script" unique="0" required="0">
+<longdesc lang="en">
+Script to execute by the admin plugin.
+Required since MySQL Proxy 0.8.1, if the admin plugin is loaded.
+Note: The admin plugin will be auto-loaded in case you specify an admin_* parameter.
+</longdesc>
+<shortdesc lang="en">MySQL Proxy admin plugin lua script</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="test_table" unique="0" required="0">
+<longdesc lang="en">
+Table to be tested in monitor statement (in database.table notation)
+</longdesc>
+<shortdesc lang="en">MySQL test table</shortdesc>
+<content type="string" default="mysql.user" />
+</parameter>
+
+<parameter name="test_user" unique="0" required="0">
+<longdesc lang="en">
+MySQL test user
+</longdesc>
+<shortdesc lang="en">MySQL test user</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="test_passwd" unique="0" required="0">
+<longdesc lang="en">
+MySQL test user password
+</longdesc>
+<shortdesc lang="en">MySQL test user password</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="parameters" unique="0" required="0">
+<longdesc lang="en">
+The MySQL Proxy daemon may be called with additional parameters.
+Specify any of them here.
+</longdesc>
+<shortdesc lang="en">MySQL Proxy additional parameters</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="pidfile" unique="1" required="0">
+<longdesc lang="en">PID file</longdesc>
+<shortdesc lang="en">PID file</shortdesc>
+<content type="string" default="${HA_RSCTMP}/mysql-proxy-${OCF_RESOURCE_INSTANCE}.pid" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="30s" />
+<action name="stop"    timeout="30s" />
+<action name="reload"  timeout="30s" />
+<action name="monitor" depth="0"  timeout="20s" interval="60s" />
+<action name="validate-all"  timeout="30s" />
+<action name="meta-data"  timeout="5s" />
+</actions>
+</resource-agent>
+END
+}
+
+isRunning()
+{
+    kill -s 0 "$1" 2>/dev/null
+}
+
+mysqlproxy_status()
+{
+    local PID
+
+    if [ -f "${pidfile}" ]; then
+    # MySQL Proxy is probably running
+        PID=`head -n 1 "${pidfile}"`
+        if [ ! -z "$PID" ] ; then
+            isRunning "$PID"
+            return $?
+        fi
+    fi
+
+    # MySQL Proxy is not running
+    false
+}
+
+mysqlproxy_start()
+{
+    local PARAM_PREFIX OPTIONS
+    local p pa pba proba
+    local pid_dir socket_dir
+
+    # if MySQL Proxy is running return success
+    if mysqlproxy_status ; then
+        ocf_log info "MySQL Proxy already running."
+        return $OCF_SUCCESS
+    fi
+
+    PARAM_PREFIX=''
+
+    # MySQL Proxy plugins to load
+    # @TODO check if the plugins are actually available?
+    if ocf_is_true $plugin_support; then
+        for p in $plugins; do
+            PARAM_PREFIX="$PARAM_PREFIX --plugins=$p"
+        done
+    fi
+
+    # check if the MySQL Proxy defaults-file exist
+    if [ -f "$defaults_file" ]; then
+        PARAM_PREFIX="$PARAM_PREFIX --defaults-file=$defaults_file"
+    fi
+
+    # set log-level
+    if [ ! -z "$log_level" ]; then
+        PARAM_PREFIX="$PARAM_PREFIX --log-level=$log_level"
+    fi
+
+    # set keepalive
+    if [ "$keepalive" = "true" ]; then
+        PARAM_PREFIX="$PARAM_PREFIX --keepalive"
+    fi
+
+    # honor admin_* options
+    if [ ! -z "$admin_username" ]; then
+        PARAM_PREFIX="$PARAM_PREFIX --admin-username=$admin_username"
+    fi
+    if [ ! -z "$admin_password" ]; then
+        PARAM_PREFIX="$PARAM_PREFIX --admin-password=$admin_password"
+    fi
+    if [ ! -z "$admin_lua_script" ]; then
+        PARAM_PREFIX="$PARAM_PREFIX --admin-lua-script=$admin_lua_script"
+    fi
+
+    # make sure that the pid directory exists
+    pid_dir=`dirname $pidfile`
+    if [ ! -d $pid_dir ] ; then
+        ocf_log info "Creating PID directory '$pid_dir'."
+        mkdir -p $pid_dir
+        #chown $OCF_RESKEY_user:$OCF_RESKEY_group $pid_dir # c/p from mysql ra; currently not needed
+    fi
+
+    # split multiple proxy-address options.
+    # currently unsupported but let us hope for the future ;)
+    for pa in $proxy_address; do
+        [ -z "$pa" ] && continue
+        OPTIONS=" $OPTIONS --proxy-address=$pa"
+
+        # if $pa contains a slash, we are dealing with a socket
+        # make sure that the socket directory exists
+        if echo "$pa" | grep -q '/' ; then
+            socket_dir=`dirname $pa`
+            if [ ! -d $socket_dir ] ; then
+                ocf_log info "Creating socket directory '$socket_dir'."
+                mkdir -p $socket_dir
+                #chown $OCF_RESKEY_user:$OCF_RESKEY_group $socket_dir # c/p from mysql ra; currently not needed
+            fi
+        fi
+    done
+
+    # split multiple proxy-backend-addresses options.
+    for pba in $proxy_backend_addresses; do
+        [ -z "$pba" ] && continue
+        OPTIONS=" $OPTIONS --proxy-backend-addresses=$pba"
+    done
+
+    # split multiple proxy-backend-addresses options.
+    for proba in $proxy_read_only_backend_addresses; do
+        [ -z "$proba" ] && continue
+        OPTIONS=" $OPTIONS --proxy-read-only-backend-addresses=$proba"
+    done
+
+    # build $OPTIONS and add admin-address and pidfile
+    OPTIONS="$PARAM_PREFIX $OPTIONS --admin-address=$admin_address --pid-file=${pidfile}"
+
+    # add additional parameters
+    if [ -n "$parameters" ]; then
+        OPTIONS="$OPTIONS $parameters"
+    fi
+
+    # start MySQL Proxy
+    #start-stop-daemon --start --quiet --pidfile $pidfile --make-pidfile --name mysql-proxy --startas $binary -b -- $OPTIONS
+    $binary --daemon $OPTIONS
+    ret=$?
+
+    if [ $ret -ne 0 ]; then
+        ocf_log err "MySQL Proxy returned error: " $ret
+        return $OCF_ERR_GENERIC
+    fi
+
+    # @TODO add an initial monitoring action?
+
+    return $OCF_SUCCESS
+}
+
+
+mysqlproxy_stop()
+{
+    local ret
+    local pa
+
+    if mysqlproxy_status ; then
+        #start-stop-daemon --stop --quiet --retry 3 --exec $binary --pidfile $pidfile
+        /bin/kill `cat "${pidfile}"`
+        ret=$?
+
+        if [ $ret -ne 0 ]; then
+            ocf_log err "MySQL Proxy returned an error while stopping: " $ret
+            return $OCF_ERR_GENERIC
+        fi
+
+        # grant some time for shutdown and recheck
+        sleep 1
+        if mysqlproxy_status ; then
+            ocf_log err "MySQL Proxy failed to stop."
+            return $OCF_ERR_GENERIC
+        fi
+
+        # remove dangling socketfile, if specified
+        for pa in $proxy_address; do
+            if [ -S "$pa" ]; then
+                ocf_log info "Removing dangling socket file '$pa'."
+                rm -f "$pa"
+            fi
+        done
+
+        # remove dangling pidfile
+        if [ -f "${pidfile}" ]; then
+            ocf_log info "Removing dangling pidfile '${pidfile}'."
+            rm -f "${pidfile}"
+        fi
+    fi
+
+    return $OCF_SUCCESS
+}
+
+mysqlproxy_reload()
+{
+    # @TODO check if pidfile is empty
+    # PID=`head -n 1 "${pidfile}"`
+    #    if [ ! -z "$PID" ] ; then
+
+    if mysqlproxy_status; then
+        ocf_log info "Reloading MySQL Proxy."
+        kill -s HUP `cat ${pidfile}`
+    fi
+}
+
+mysqlproxy_monitor()
+{
+    local rc
+
+    if [ "${OCF_RESKEY_CRM_meta_interval:-0}" -eq "0" ]; then
+        # in case of probe, monitor operation is surely treated as
+        # under suspension. This will call start operation.
+        # (c/p from ocf:heartbeat:sfex)
+        mysqlproxy_validate_all
+        rc=$?
+        [ $rc -ne 0 ] && return $rc
+    fi
+
+    if ! mysqlproxy_status ; then
+        return $OCF_NOT_RUNNING
+    fi
+
+    if [ $OCF_CHECK_LEVEL -eq 20 ]; then
+        mysqlproxy_monitor_20
+        rc=$?
+        [ $rc -ne 0 ] && return $rc
+    fi
+
+    return $OCF_SUCCESS
+}
+
+mysqlproxy_monitor_20()
+{
+    local rc
+    local mysql_options pa
+    local mysql_server_parameter mysql_server_host mysql_server_port
+
+    if [ -z "$OCF_RESKEY_test_table" -o -z "$OCF_RESKEY_test_user" -a -z "$OCF_RESKEY_test_passwd" ]; then
+        ocf_log warn "Missing proper configuration for OCF_CHECK_LEVEL=20 (test_table=[$OCF_RESKEY_test_table] test_user=[$OCF_RESKEY_test_user] test_password=[$OCF_RESKEY_test_passwd]). Not running in-depth monitoring."
+        return $OCF_SUCCESS
+    fi
+
+    mysql_options="--connect_timeout=10 --user=$OCF_RESKEY_test_user --password=$OCF_RESKEY_test_passwd"
+
+    # cycle each address
+    for pa in $proxy_address; do
+        # build correct connect parameter
+        if [ -S "$pa" ]; then
+            # we need to monitor a mysql socket
+            mysql_server_parameter="--socket=$pa"
+        else
+            # we need to monitor a host address
+            mysql_server_parameter=""
+
+            # split host:port
+            # @TODO correctly handle IPv6 address
+            # @TODO correctly handle 0.0.0.0 address
+            mysql_server_host=`echo $pa | cut -d : -f 1`
+            mysql_server_port=`echo $pa | cut -d : -f 2`
+
+            if [ -n $mysql_server_host ]; then
+                mysql_server_parameter="$mysql_server_parameter --host=$mysql_server_host"
+            fi
+            if [ -n $mysql_server_port ]; then
+                mysql_server_parameter="$mysql_server_parameter --port=$mysql_server_port"
+            fi
+        fi
+
+        # Check for test table
+        ocf_run $mysql $mysql_server_parameter $mysql_options \
+            -e "SELECT COUNT(*) FROM $OCF_RESKEY_test_table"
+        rc=$?
+
+        if [ $rc -ne 0 ]; then
+            ocf_log err "Failed to select from $OCF_RESKEY_test_table: " $rc
+            return $OCF_ERR_GENERIC
+        fi
+    done
+
+    return $OCF_SUCCESS
+}
+
+mysqlproxy_validate_all()
+{
+    # local variables
+    local config_error=0
+
+    # check that the MySQL Proxy binary exists and can be executed
+    check_binary $binary
+
+    # check MySQL client binary only if in-depth monitoring is requested
+    # do not break backwards compatibility otherwise
+    if [ $OCF_CHECK_LEVEL -gt 0 ]; then
+        check_binary $mysql
+    fi
+
+    # check for valid log-level
+    echo $log_level | egrep -q "^(error|warning|info|message|debug|)$"
+    if [ $? -ne 0 ]; then
+        ocf_log err "MySQL Proxy log level '$log_level' not in valid range error|warning|info|message|debug"
+        return $OCF_ERR_CONFIGURED
+    fi
+
+
+    # if we're running MySQL Proxy > 0.8.1 and there is any admin parameter set,
+    # explicitly load the admin (and the proxy) plugin.
+    # (version 0.8.2 does not load the admin plugin by default anymore)
+    ocf_version_cmp "$version" "0.8.1"
+    ret=$?
+    if [ $ret -eq 2 ]; then
+        # simple check: concat all parameters and check if the string has non-zero length
+        if [ -n "$admin_username$admin_password$admin_lua_script$admin_address" ]; then
+            plugins="proxy admin"
+            has_plugin_admin=1
+        else
+            has_plugin_admin=0
+        fi
+    fi
+
+
+    # check for required admin_* parameters for 0.8.1 and 0.8.2 (with admin module)
+    # translated: if (version == 0.8.1 or (version > 0.8.1 and has_plugin_admin))
+    if [ $ret -eq 1 -o \( $ret -eq 2 -a $has_plugin_admin -eq 1 \) ]; then
+        if [ -z "$admin_username" ]; then
+            ocf_log err "Missing required parameter \"admin_username\""
+            config_error=1
+        fi
+        if [ -z "$admin_password" ]; then
+            ocf_log err "Missing required parameter \"admin_password\""
+            config_error=1
+        fi
+        if [ -z "$admin_lua_script" ]; then
+            ocf_log err "Missing required parameter \"admin_lua_script\""
+            config_error=1
+        fi
+
+        # check if the admin_lua_script, if specified, exists
+        if [ -n "$admin_lua_script" -a ! -e "$admin_lua_script" ]; then
+            ocf_log err "MySQL Proxy admin lua script '$admin_lua_script' does not exist or is not readable."
+        fi
+    fi
+
+    # issue a warning during start if the user wants to load a plugin
+    # but this version of MySQL Proxy does not support the plugin architecture.
+    if [ -n "$plugins" ] && ocf_is_false "$plugin_support" && [ $__OCF_ACTION = 'start' ]; then
+        ocf_log warn "You are running MySQL Proxy version '$version'. This version does not support the plugin architecture. Please use version 0.7.0 or later to load the plugins '$plugins'."
+    fi
+
+    # exit in case we have found relevant config errors
+    if [ $config_error -eq 1 ]; then
+        exit $OCF_ERR_CONFIGURED
+    fi
+
+    return $OCF_SUCCESS
+}
+
+#
+# Main
+#
+
+if [ $# -ne 1 ]; then
+    usage
+    exit $OCF_ERR_ARGS
+fi
+
+pidfile=$OCF_RESKEY_pidfile
+binary=$OCF_RESKEY_binary
+defaults_file=$OCF_RESKEY_defaults_file
+proxy_backend_addresses=$OCF_RESKEY_proxy_backend_addresses
+proxy_read_only_backend_addresses=$OCF_RESKEY_proxy_read_only_backend_addresses
+admin_address=$OCF_RESKEY_admin_address
+admin_username=$OCF_RESKEY_admin_username
+admin_password=$OCF_RESKEY_admin_password
+admin_lua_script=$OCF_RESKEY_admin_lua_script
+proxy_address=$OCF_RESKEY_proxy_address
+log_level=$OCF_RESKEY_log_level
+keepalive=$OCF_RESKEY_keepalive
+plugins=`echo $OCF_RESKEY_plugins | tr "[:space:]" "\n" | sort -u`
+mysql=$OCF_RESKEY_client_binary
+parameters=$OCF_RESKEY_parameters
+plugin_support=false
+has_plugin_admin=0 # 0 because this simplifies the if statements
+
+# debugging stuff
+#echo OCF_RESKEY_binary=$OCF_RESKEY_binary >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_defaults_file=$OCF_RESKEY_defaults_file >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_proxy_backend_addresses=$OCF_RESKEY_proxy_backend_addresses >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_proxy_read_only_backend_addresses=$OCF_RESKEY_proxy_read_only_backend_addresses >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_proxy_address=$OCF_RESKEY_proxy_address >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_log_level=$OCF_RESKEY_log_level >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_keepalive=$OCF_RESKEY_keepalive >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_admin_address=$OCF_RESKEY_admin_address >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_admin_username=$OCF_RESKEY_admin_username >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_admin_password=$OCF_RESKEY_admin_password >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_admin_lua_script=$OCF_RESKEY_admin_lua_script >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_parameters=$OCF_RESKEY_parameters >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+#echo OCF_RESKEY_pidfile=$OCF_RESKEY_pidfile >> /tmp/prox_conf_$OCF_RESOURCE_INSTANCE
+
+
+# handle some parameters before performing any additional checks
+case $1 in
+    meta-data)  meta_data
+                exit $?
+                ;;
+
+    usage)      usage
+                exit $OCF_SUCCESS
+                ;;
+esac
+
+
+# determine MySQL Proxy version
+check_binary $binary
+version=`$binary --version | grep ^mysql-proxy | awk '{print $NF}'`
+
+# version 0.7.0 (and later) support the plugin architecture and load the admin plugin by default
+# version 0.8.1 loads admin plugin by default and requires the admin parameters to be set
+# version 0.8.2 does not load the admin plugin by default anymore
+ocf_version_cmp "$version" "0.7.0"
+ret=$?
+if [ $ret -eq 1 -o $ret -eq 2 ]; then
+    plugin_support=true
+    has_plugin_admin=1
+fi
+
+
+# perform action
+case $1 in
+    start)      mysqlproxy_validate_all &&
+                mysqlproxy_start
+                exit $?
+                ;;
+
+    stop)       mysqlproxy_validate_all &&
+                mysqlproxy_stop
+                exit $?
+                ;;
+
+    reload)     mysqlproxy_reload
+                exit $?
+                ;;
+
+    status)     if mysqlproxy_status; then
+                    ocf_log info "MySQL Proxy is running."
+                    exit $OCF_SUCCESS
+                else
+                    ocf_log info "MySQL Proxy is stopped."
+                    exit $OCF_NOT_RUNNING
+                fi
+                ;;
+
+    monitor)    mysqlproxy_monitor
+                exit $?
+                ;;
+
+    validate-all)   mysqlproxy_validate_all
+                    exit $?
+                    ;;
+
+
+    *)          usage
+                exit $OCF_ERR_UNIMPLEMENTED
+                ;;
+esac
diff --git a/heartbeat/named b/heartbeat/named
new file mode 100755
index 0000000..ede22df
--- /dev/null
+++ b/heartbeat/named
@@ -0,0 +1,489 @@
+#!/bin/sh
+#
+# Description:  Manages a named (Bind) server as an OCF High-Availability
+#               resource
+#
+# Authors:      Serge Dubrouski (sergeyfd at gmail.com) 
+#
+# Copyright:    2011 Serge Dubrouski <sergeyfd at gmail.com>
+#                         
+# License:      GNU General Public License (GPL)
+#
+###############################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#Defaults
+OCF_RESKEY_named_default="/usr/sbin/named"
+OCF_RESKEY_rndc_default="/usr/sbin/rndc"
+OCF_RESKEY_host_default="/usr/bin/host"
+OCF_RESKEY_named_user_default=named
+OCF_RESKEY_named_config_default=""
+OCF_RESKEY_named_pidfile_default="/var/run/named/named.pid"
+OCF_RESKEY_named_rootdir_default=""
+OCF_RESKEY_named_options_default=""
+OCF_RESKEY_named_keytab_file_default=""
+OCF_RESKEY_monitor_request_default="localhost"
+OCF_RESKEY_monitor_response_default="127.0.0.1"
+OCF_RESKEY_monitor_ip_default="127.0.0.1"
+
+: ${OCF_RESKEY_named=${OCF_RESKEY_named_default}}
+: ${OCF_RESKEY_rndc=${OCF_RESKEY_rndc_default}}
+: ${OCF_RESKEY_host=${OCF_RESKEY_host_default}}
+: ${OCF_RESKEY_named_user=${OCF_RESKEY_named_user_default}}
+: ${OCF_RESKEY_named_config=${OCF_RESKEY_named_config_default}}
+: ${OCF_RESKEY_named_pidfile=${OCF_RESKEY_named_pidfile_default}}
+: ${OCF_RESKEY_named_rootdir=${OCF_RESKEY_named_rootdir_default}}
+: ${OCF_RESKEY_named_options=${OCF_RESKEY_named_options_default}}
+: ${OCF_RESKEY_named_keytab_file=${OCF_RESKEY_named_keytab_file_default}}
+: ${OCF_RESKEY_monitor_request=${OCF_RESKEY_monitor_request_default}}
+: ${OCF_RESKEY_monitor_response=${OCF_RESKEY_monitor_response_default}}
+: ${OCF_RESKEY_monitor_ip=${OCF_RESKEY_monitor_ip_default}}
+
+usage() {
+    cat <<EOF
+        usage: $0 start|stop|reload|status|monitor|meta-data|validate-all|methods
+
+        $0 manages named (Bind) server as an HA resource.
+
+        The 'start' operation starts named server.
+        The 'stop' operation stops  named server.
+        The 'reload' operation reload named configuration.
+        The 'status' operation reports whether named is up.
+        The 'monitor' operation reports whether named is running.
+        The 'validate-all' operation reports whether parameters are valid.
+        The 'methods' operation reports on the methods $0 supports.
+EOF
+  return $OCF_ERR_ARGS
+}
+
+named_meta_data() {
+        cat <<EOF
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="named">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for named (Bind) server. It manages named as an HA resource.
+</longdesc>
+<shortdesc lang="en">Manages a named server</shortdesc>
+
+<parameters>
+<parameter name="named" unique="0" required="0">
+<longdesc lang="en">
+Path to the named command.
+</longdesc>
+<shortdesc lang="en">named</shortdesc>
+<content type="string" default="${OCF_RESKEY_named_default}" />
+</parameter>
+
+<parameter name="rndc" unique="0" required="0">
+<longdesc lang="en">
+Path to the rndc command.
+</longdesc>
+<shortdesc lang="en">rndc</shortdesc>
+<content type="string" default="${OCF_RESKEY_rndc_default}" />
+</parameter>
+
+<parameter name="host" unique="0" required="0">
+<longdesc lang="en">
+Path to the host command.
+</longdesc>
+<shortdesc lang="en">host</shortdesc>
+<content type="string" default="${OCF_RESKEY_host_default}" />
+</parameter>
+
+<parameter name="named_user" unique="0" required="0">
+<longdesc lang="en">
+User that should own named process.
+</longdesc>
+<shortdesc lang="en">named_user</shortdesc>
+<content type="string" default="${OCF_RESKEY_named_user_default}" />
+</parameter>
+
+<parameter name="named_config" unique="1" required="0">
+<longdesc lang="en">
+Configuration file for named.
+</longdesc>
+<shortdesc lang="en">named_config</shortdesc>
+<content type="string" default="${OCF_RESKEY_named_config_default}" />
+</parameter>
+
+<parameter name="named_pidfile" unique="1" required="0">
+<longdesc lang="en">
+PIDFILE file for named.
+</longdesc>
+<shortdesc lang="en">named_pidfile</shortdesc>
+<content type="string" default="${OCF_RESKEY_named_pidfile_default}" />
+</parameter>
+
+<parameter name="named_rootdir" unique="1" required="0">
+<longdesc lang="en">
+Directory that named should use for chroot if any.
+</longdesc>
+<shortdesc lang="en">named_rootdir</shortdesc>
+<content type="string" default="${OCF_RESKEY_named_rootdir_default}" />
+</parameter>
+
+<parameter name="named_options" unique="0" required="0">
+<longdesc lang="en">
+Options for named process if any.
+</longdesc>
+<shortdesc lang="en">named_options</shortdesc>
+<content type="string" default="${OCF_RESKEY_named_options_default}" />
+</parameter>
+
+<parameter name="named_keytab_file" unique="0" required="0">
+<longdesc lang="en">
+named service keytab file (for GSS-TSIG).
+</longdesc>
+<shortdesc lang="en">named_keytab_file</shortdesc>
+<content type="string" default="${OCF_RESKEY_named_keytab_file_default}" />
+</parameter>
+
+<parameter name="monitor_request" unique="0" required="0">
+<longdesc lang="en">
+Request that shall be sent to named for monitoring. Usually an A record in DNS.
+</longdesc>
+<shortdesc lang="en">monitor_request</shortdesc>
+<content type="string" default="${OCF_RESKEY_monitor_request_default}" />
+</parameter>
+
+<parameter name="monitor_response" unique="0" required="0">
+<longdesc lang="en">
+Expected response from named server.
+</longdesc>
+<shortdesc lang="en">monitor_response</shortdesc>
+<content type="string" default="${OCF_RESKEY_monitor_response_default}" />
+</parameter>
+
+<parameter name="monitor_ip" unique="0" required="0">
+<longdesc lang="en">
+IP Address where named listens.
+</longdesc>
+<shortdesc lang="en">monitor_ip</shortdesc>
+<content type="string" default="${OCF_RESKEY_monitor_ip_default}" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="60" />
+<action name="stop" timeout="60" />
+<action name="reload" timeout="60" />
+<action name="status" timeout="10" />
+<action name="monitor" depth="0" timeout="30" interval="30"/>
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+<action name="methods" timeout="5" />
+</actions>
+</resource-agent>
+
+EOF
+}
+
+#
+# methods: What methods/operations do we support?
+#
+
+named_methods() {
+  cat <<EOF
+        start
+        stop
+        status
+        monitor
+        methods 
+        meta-data
+        validate-all
+EOF
+}
+
+# Validate most critical parameters
+named_validate_all() {
+    check_binary $OCF_RESKEY_named
+    check_binary $OCF_RESKEY_rndc
+    check_binary $OCF_RESKEY_host
+
+    if [ -n "$OCF_RESKEY_named_config" -a \
+        ! -r "${OCF_RESKEY_named_rootdir}/${OCF_RESKEY_named_config}" ]; then
+        if ocf_is_probe; then
+           ocf_log info "Configuration file ${OCF_RESKEY_named_rootdir}/${OCF_RESKEY_named_config} not readable during probe."
+        else
+           ocf_log err "Configuration file ${OCF_RESKEY_named_rootdir}/${OCF_RESKEY_named_config} doesn't exist"
+           return $OCF_ERR_INSTALLED
+        fi
+    fi
+
+    getent passwd $OCF_RESKEY_named_user >/dev/null 2>&1
+    if [ ! $? -eq 0 ]; then
+        ocf_log err "User $OCF_RESKEY_named_user doesn't exist";
+        return $OCF_ERR_INSTALLED;
+    fi
+
+    if [ -z "$OCF_RESKEY_monitor_request" -o \
+         -z "$OCF_RESKEY_monitor_response" -o \
+         -z "$OCF_RESKEY_monitor_ip" ]; then
+        ocf_log err "None of monitor_request, monitor_response, and monitor_ip can be empty"
+        return $OCF_ERR_CONFIGURED
+    fi                            
+         
+    return $OCF_SUCCESS
+}
+
+##
+# Attempt to generate a /etc/rndc.key if one is not present
+##
+rndc_key_generator()
+{
+    local rndc_options="-a -r /dev/urandom -u $OCF_RESKEY_named_user"
+
+    if [ -s /etc/rndc.key ]; then
+        # file already exists
+        return
+    fi
+
+    if ! have_binary "rndc-confgen"; then
+        # can't autogen key... Report this, but not as a warning or error.
+        # It is possible that the user configured the key in named.conf
+        ocf_log info "rndc-confgen tool not present, unable to autogen /etc/rndc.key."
+        return
+    fi 
+
+    if [ -n "$OCF_RESKEY_rootdir" ]; then
+        rndc_options="$rndc_options -t $OCF_RESKEY_rootdir"
+    fi
+
+    rndc-confgen $rndc_options > /dev/null 2>&1;
+    if [ $? -eq 0 ]; then
+        if have_binary "restorecon"; then
+            restorecon /etc/rndc.key
+        fi
+    else
+        ocf_log info "failed to auto-generate /etc/rndc.key file."
+    fi
+}
+
+#
+# named_getpid. Get pid of named process with a given parameters.
+#
+
+named_getpid () {
+    local pattern="$OCF_RESKEY_named"
+
+    if [ -n "$OCF_RESKEY_named_rootdir" -a "x${OCF_RESKEY_named_rootdir}" != "x/" ]; then
+       pattern="$pattern.*-t $OCF_RESKEY_named_rootdir"
+    fi
+
+    if [ -n "$OCF_RESKEY_named_config" ]; then
+       pattern="$pattern.*-c $OCF_RESKEY_named_config"
+    fi
+
+    pid=`pgrep -f "$pattern"`
+    echo $pid
+}
+
+#
+# named_status. Simple check of the status of named process by pidfile.
+#
+
+named_status () {
+    ocf_pidfile_status ${OCF_RESKEY_named_pidfile} >/dev/null 2>&1
+}
+
+#
+# named_monitor. Send a request to named and check response.
+#
+
+named_monitor() {
+    local output
+
+    if ! named_status
+    then
+        ocf_log info "named is down"
+        return $OCF_NOT_RUNNING
+    fi
+   
+    output=`$OCF_RESKEY_host $OCF_RESKEY_monitor_request $OCF_RESKEY_monitor_ip`
+
+    if [ $? -ne 0 ] || ! echo $output | grep -q '.* has .*address '"$OCF_RESKEY_monitor_response" 
+    then
+       ocf_log err "named didn't answer properly for $OCF_RESKEY_monitor_request."
+       ocf_log err "Expected: $OCF_RESKEY_monitor_response."
+       ocf_log err "Got: $output"
+       return $OCF_ERR_GENERIC
+    fi
+    
+    return $OCF_SUCCESS
+}
+
+#
+# Reload
+#
+
+named_reload() {
+    $OCF_RESKEY_rndc reload >/dev/null || return $OCF_ERR_GENERIC
+    
+    return $OCF_SUCCESS
+}
+    
+#
+# Start
+#
+
+named_start() {    
+    local root_dir_opt
+    local pid
+    
+    root_dir_opt=""
+    named_status && return $OCF_SUCCESS
+    
+    # Remove pidfile if exists    
+    rm -f ${OCF_RESKEY_named_pidfile}
+    
+    if [ -n "${OCF_RESKEY_named_rootdir}" -a "x${OCF_RESKEY_named_rootdir}" != "x/" ]
+    then
+        root_dir_opt="-t ${OCF_RESKEY_named_rootdir}"
+        [ -s /etc/localtime ] && cp -fp /etc/localtime ${OCF_RESKEY_named_rootdir}/etc/localtime
+    fi
+
+    if [ -n "$OCF_RESKEY_named_config" ]; then
+        OCF_RESKEY_named_options="-c $OCF_RESKEY_named_config $OCF_RESKEY_named_options"
+    fi
+
+    rndc_key_generator
+
+    if ! ${OCF_RESKEY_named} -u ${OCF_RESKEY_named_user} $root_dir_opt ${OCF_RESKEY_named_options}
+    then
+        ocf_log err "named failed to start."
+        return $OCF_ERR_GENERIC
+    fi
+    
+    
+    pid=`named_getpid`
+    
+    if [ -n "$pid" ]; then
+        if [ ! -e ${OCF_RESKEY_named_pidfile} ]; then
+            echo $pid > ${OCF_RESKEY_named_pidfile}
+        fi
+    else
+        ocf_log err "named failed to start. Probably error in configuration."
+        return $OCF_ERR_GENERIC
+    fi
+        
+    while :
+    do
+        named_monitor && break
+        sleep 1
+        ocf_log debug "named hasn't started yet."
+    done
+    ocf_log info "named has started."
+    
+    return $OCF_SUCCESS
+}
+    
+#
+# Stop
+# 
+
+named_stop () {
+    local timeout
+    local timewait
+    
+    named_status || return $OCF_SUCCESS
+    
+    $OCF_RESKEY_rndc stop >/dev/null
+    if [ $? -ne 0 ]; then
+        ocf_log info "rndc stop failed. Killing named."
+        kill `cat ${OCF_RESKEY_named_pidfile}`
+    fi
+ 
+    if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
+      # Allow 2/3 of the action timeout for the orderly shutdown
+      # (The origin unit is ms, hence the conversion)
+      timewait=$((OCF_RESKEY_CRM_meta_timeout/1500))
+    else
+      timewait=20
+    fi
+
+    sleep 1; timeout=0 # Sleep here for 1 sec to let rndc finish.
+    while named_status ; do
+        if [ $timeout -ge $timewait ]; then    
+            break
+        else
+            sleep 1
+            timeout=`expr $timeout + 1`
+            ocf_log debug "named appears to hung, waiting ..."
+        fi
+    done
+    
+    #If still up    
+    if named_status 2>&1; then
+        ocf_log err "named is still up! Killing"
+        kill -9 `cat ${OCF_RESKEY_named_pidfile}`
+    fi
+    
+    rm -f ${OCF_RESKEY_named_pidfile}
+    return $OCF_SUCCESS
+}
+
+
+# Main part
+
+if [ $# -ne 1 ]; then 
+    usage 
+    exit $OCF_ERR_GENERIC
+fi
+
+case "$1" in
+    methods)    named_methods
+                exit $?;;
+
+    meta-data)  named_meta_data
+                exit $OCF_SUCCESS;;
+esac
+
+named_validate_all
+rc=$?
+
+[ "$1" = "validate-all" ] && exit $rc
+
+if [ $rc -ne 0 ]
+then
+    case "$1" in
+        stop)    exit $OCF_SUCCESS;;
+        monitor) exit $OCF_NOT_RUNNING;;
+        status)  exit $OCF_NOT_RUNNING;;
+        *)       exit $rc;;
+    esac
+fi
+
+if [ `id -u` -ne 0 ]; then
+    ocf_log err "$0 must be run as root"
+    exit $OCF_ERR_GENERIC
+fi
+
+case "$1" in
+    status)     if named_status
+                then
+                    ocf_log info "named is up"
+                    exit $OCF_SUCCESS
+                else
+                    ocf_log info "named is down"
+                    exit $OCF_NOT_RUNNING
+                fi;;
+
+    monitor)    named_monitor
+                exit $?;;
+
+    start)      named_start
+                exit $?;;
+
+    stop)       named_stop
+                exit $?;;
+    reload)     named_reload
+                exit $?;;
+    *)
+                exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
new file mode 100755
index 0000000..fdb0831
--- /dev/null
+++ b/heartbeat/nfsserver
@@ -0,0 +1,489 @@
+#!/bin/sh
+# nfsserver
+#
+# Description: Manages nfs server as OCF resource
+# by hxinwei at gmail.com
+# License: GNU General Public License v2 (GPLv2) and later
+
+if [ -n "$OCF_DEBUG_LIBRARY" ]; then
+    . $OCF_DEBUG_LIBRARY
+else
+    : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+fi
+
+DEFAULT_INIT_SCRIPT="/etc/init.d/nfsserver"
+DEFAULT_NOTIFY_CMD=`which sm-notify`
+DEFAULT_NOTIFY_CMD=${DEFAULT_NOTIFY_CMD:-"/sbin/sm-notify"}
+DEFAULT_NOTIFY_FOREGROUND="false"
+DEFAULT_RPCPIPEFS_DIR="/var/lib/nfs/rpc_pipefs"
+EXEC_MODE=0
+SELINUX_ENABLED=-1
+STATD_PATH="/var/lib/nfs"
+STATD_DIR=""
+
+nfsserver_meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="nfsserver">
+<version>1.0</version>
+
+<longdesc lang="en">
+Nfsserver helps to manage the Linux nfs server as a failover-able resource in Linux-HA.
+It depends on Linux specific NFS implementation details, so is considered not portable to other platforms yet.
+</longdesc>
+
+<shortdesc lang="en">Manages an NFS server</shortdesc>
+
+<parameters>
+
+<parameter name="nfs_init_script" unique="0" required="0">
+<longdesc lang="en">
+The default init script shipped with the Linux distro.
+The nfsserver resource agent offloads the start/stop/monitor 
+work to the init script because the procedure to start/stop/monitor 
+nfsserver varies on different Linux distro. In the event that this
+option is not set, this agent will attempt to use an init script at 
+this location, ${DEFAULT_INIT_SCRIPT}, or detect a systemd unit-file 
+to use in the event that no init script is detected.
+</longdesc>
+<shortdesc lang="en">
+Init script for nfsserver
+</shortdesc>
+<content type="string" default="auto detected" />
+</parameter>
+
+<parameter name="nfs_notify_cmd" unique="0" required="0">
+<longdesc lang="en">
+The tool to send out NSM reboot notification; it should be either sm-notify or rpc.statd.
+Failover of nfsserver can be considered as rebooting to different machines.
+The nfsserver resource agent use this command to notify all clients about the occurrence of failover.
+</longdesc>
+<shortdesc lang="en">
+The tool to send out notification.
+</shortdesc>
+<content type="string" default="$DEFAULT_NOTIFY_CMD" />
+</parameter>
+
+<parameter name="nfs_notify_foreground" unique="0" required="0">
+<longdesc lang="en">
+Keeps the notify tool attached to its controlling terminal and running in the foreground.
+</longdesc>
+<shortdesc lang="en">
+Keeps the notify tool running in the foreground.
+</shortdesc>
+<content type="boolean" default="$DEFAULT_NOTIFY_FOREGROUND" />
+</parameter>
+
+<parameter name="nfs_smnotify_retry_time" unique="0" required="0">
+<longdesc lang="en">
+Specifies the length of sm-notify retry time, in minutes, to continue retrying notifications to unresponsive hosts.  
+If this option is not specified, sm-notify attempts to send notifications for 15 minutes. Specifying a value of 0 
+causes sm-notify to continue sending notifications to unresponsive peers until it is manually killed.
+</longdesc>
+<shortdesc lang="en">
+Specifies the length of sm-notify retry time (minutes).
+</shortdesc>
+<content type="integer" default="" />
+</parameter>
+
+<parameter name="nfs_shared_infodir" unique="0" required="1">
+<longdesc lang="en">
+The nfsserver resource agent will save nfs related information in this specific directory.
+And this directory must be able to fail-over before nfsserver itself.
+</longdesc>
+<shortdesc lang="en">
+Directory to store nfs server related information.
+</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="nfs_ip" unique="0" required="1">
+<longdesc lang="en">
+Comma separated list of floating IP addresses used to access the nfs service
+</longdesc>
+<shortdesc lang="en">
+IP addresses.
+</shortdesc>
+<content type="string"/>
+</parameter>
+
+<parameter name="rpcpipefs_dir" unique="0" required="0">
+<longdesc lang="en">
+The mount point for the sunrpc file system. Default is $DEFAULT_RPCPIPEFS_DIR. 
+This script will mount (bind) nfs_shared_infodir on /var/lib/nfs/ (cannot be changed),
+and this script will mount the sunrpc file system on $DEFAULT_RPCPIPEFS_DIR (default, can be changed by this parameter).
+If you want to move only rpc_pipefs/ (e.g. to keep rpc_pipefs/ local) from default, please set this value.
+</longdesc>
+<shortdesc lang="en">
+The mount point for the sunrpc file system.
+</shortdesc>
+<content type="string" default="$DEFAULT_RPCPIPEFS_DIR" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="40" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" depth="0"  timeout="20s" interval="10" />
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="30" />
+</actions>
+</resource-agent>
+END
+
+return $OCF_SUCCESS
+}
+
+nfsserver_usage() {
+	cat <<END
+		usage: $0 {start|stop|monitor|status|validate-all|meta-data}
+END
+}
+
+if [ $# -ne 1 ]; then
+	nfsserver_usage
+	exit $OCF_ERR_ARGS
+fi
+
+case $__OCF_ACTION in
+	meta-data)  nfsserver_meta_data
+		exit $OCF_SUCCESS
+		;;
+	usage|help) nfsserver_usage
+		exit $OCF_SUCCESS
+		;;
+	*)
+		;;	
+esac
+
+fp="$OCF_RESKEY_nfs_shared_infodir"
+: ${OCF_RESKEY_nfs_notify_cmd="$DEFAULT_NOTIFY_CMD"}
+: ${OCF_RESKEY_nfs_notify_foreground="$DEFAULT_NOTIFY_FOREGROUND"}
+
+if [ -z ${OCF_RESKEY_rpcpipefs_dir} ]; then
+	rpcpipefs_make_dir=$fp/rpc_pipefs
+	rpcpipefs_umount_dir=${DEFAULT_RPCPIPEFS_DIR}
+else
+	rpcpipefs_make_dir=${OCF_RESKEY_rpcpipefs_dir}
+	rpcpipefs_umount_dir=${OCF_RESKEY_rpcpipefs_dir}
+fi
+
+# Use statd folder if it exists
+if [ -d "/var/lib/nfs/statd" ]; then
+	STATD_DIR="statd"
+	STATD_PATH="/var/lib/nfs/statd"
+fi
+
+# SELinux information. We are taking the permissions from
+# the current statd dir and applying it to the HA one that is
+# being mounted in its place.
+which restorecon > /dev/null 2>&1 && selinuxenabled
+SELINUX_ENABLED=$?
+if [ $SELINUX_ENABLED -eq 0 ]; then
+	export SELINUX_LABEL="$(ls -ldZ $STATD_PATH | cut -f4 -d' ')"
+fi
+
+##
+# EXEC_MODE values
+# 1  user init script or default init script
+# 2  systemd
+#
+# On error, this function will terminate the process
+# with error code $OCF_ERR_INSTALLED
+##
+set_exec_mode()
+{
+
+	##
+	# If EXEC_MODE is already set, we don't need to run this function again.
+	## 
+	if [ $EXEC_MODE -ne 0 ]; then
+		return 0;
+	fi
+
+	##
+	# If the user defined an init script, It must exist for us to continue
+	##
+	if [ -n "$OCF_RESKEY_nfs_init_script" ]; then
+		# check_binary will exit the process if init script does not exist
+		check_binary ${OCF_RESKEY_nfs_init_script}
+		EXEC_MODE=1
+		return 0
+	fi
+
+	##
+	# Check to see if the default init script exists, if so we'll use that.
+	##
+	if which $DEFAULT_INIT_SCRIPT > /dev/null 2>&1; then
+		OCF_RESKEY_nfs_init_script=$DEFAULT_INIT_SCRIPT
+		EXEC_MODE=1
+		return 0
+	fi
+
+	##
+	# Last of all, attempt systemd.
+	##
+	if which systemctl > /dev/null 2>&1; then
+		if systemctl list-unit-files | grep nfs-server > /dev/null && systemctl list-unit-files | grep nfs-lock > /dev/null; then
+			EXEC_MODE=2
+			return 0
+		fi
+	fi
+
+	ocf_log err "No init script or systemd unit file detected for nfs server"
+	exit $OCF_ERR_INSTALLED
+}
+
+nfs_systemd_exec()
+{
+	local cmd=$1
+	local server_res
+	local lock_res
+
+	if [ "$cmd" = "stop" ]; then
+		systemctl $cmd nfs-server.service
+		server_res=$?
+		systemctl $cmd nfs-lock.service
+		lock_res=$?
+	else
+		systemctl $cmd nfs-lock.service
+		lock_res=$?
+		systemctl $cmd nfs-server.service
+		server_res=$?
+	fi
+
+	if [ $lock_res -ne $server_res ]; then
+		# If one is running and the other isn't, or for whatever other reason
+		# the return code's aren't the same, this is bad.
+		ocf_log err "Systemd services nfs-lock and nfs-server are not in the same state after attempting $cmd command"
+		return $OCF_ERR_GENERIC
+	fi
+	return $server_res
+}
+
+##
+# wrapper for init script and systemd calls.
+##
+nfs_exec()
+{
+	local cmd=$1
+	set_exec_mode
+
+	case $EXEC_MODE in 
+		1) ${OCF_RESKEY_nfs_init_script} $cmd;;
+		2) nfs_systemd_exec $cmd;;
+	esac
+}
+
+nfsserver_monitor ()
+{
+	fn=`mktemp`
+	nfs_exec status > $fn 2>&1 
+	rc=$?
+	ocf_log debug `cat $fn`
+	rm -f $fn
+
+#Adapte LSB status code to OCF return code
+	if [ $rc -eq 0 ]; then
+		return $OCF_SUCCESS
+	elif [ $rc -eq 3 ]; then
+		return $OCF_NOT_RUNNING
+	else
+		return $OCF_ERR_GENERIC
+	fi
+}
+
+prepare_directory ()
+{
+	[ -d "$fp" ] || mkdir -p $fp
+	[ -d "$rpcpipefs_make_dir" ] || mkdir -p $rpcpipefs_make_dir
+	[ -d "$fp/v4recovery" ] || mkdir -p $fp/v4recovery
+
+	[ -d "$fp/$STATD_DIR" ] || mkdir -p "$fp/$STATD_DIR"
+	[ -d "$fp/$STATD_DIR/sm" ] || mkdir -p "$fp/$STATD_DIR/sm"
+	[ -d "$fp/$STATD_DIR/sm.ha" ] || mkdir -p "$fp/$STATD_DIR/sm.ha"
+	[ -d "$fp/$STATD_DIR/sm.bak" ] || mkdir -p "$fp/$STATD_DIR/sm.bak"
+	[ -n "`id -u rpcuser`" -a "`id -g rpcuser`" ] && chown -R rpcuser.rpcuser "$fp/$STATD_DIR"
+
+	[ -f "$fp/etab" ] || touch "$fp/etab"
+	[ -f "$fp/xtab" ] || touch "$fp/xtab"
+	[ -f "$fp/rmtab" ] || touch "$fp/rmtab"
+
+	[ $SELINUX_ENABLED -eq 0 ] && chcon -R "$SELINUX_LABEL" "$fp"
+}
+
+is_bound ()
+{
+	if mount | grep -q "on $1 type"; then
+		return 0
+	fi
+
+	return 1
+}
+
+bind_tree ()
+{
+	if is_bound /var/lib/nfs; then
+		ocf_log debug "$fp is already bound to /var/lib/nfs"
+		return 0
+	fi
+	mount --bind $fp /var/lib/nfs
+	[ $SELINUX_ENABLED -eq 0 ] && restorecon /var/lib/nfs
+}
+
+unbind_tree ()
+{
+	if `mount | grep -q " on $rpcpipefs_umount_dir"`; then
+		umount -t rpc_pipefs $rpcpipefs_umount_dir
+	fi
+	if is_bound /var/lib/nfs; then
+		umount /var/lib/nfs
+	fi
+}
+
+nfsserver_start ()
+{
+	if nfsserver_monitor; then
+		ocf_log debug "NFS server is already started"
+		return $OCF_SUCCESS
+	fi
+
+	prepare_directory
+	bind_tree
+
+	rm -rf $STATD_PATH/sm.ha/* > /dev/null 2>&1
+	cp -rf $STATD_PATH/sm $STATD_PATH/sm.bak /var/lib/nfs/state $STATD_PATH/sm.ha > /dev/null 2>&1
+
+	ocf_log info "Starting NFS server ..."
+
+	fn=`mktemp`
+	nfs_exec start > $fn 2>&1
+	rc=$?
+	ocf_log debug `cat $fn`
+	rm -f $fn
+
+	if [ $rc -ne 0 ]; then
+		ocf_log err "Failed to start NFS server"
+		return $rc
+	fi	
+
+	#Notify the nfs server has been moved or rebooted
+	#The init script do that already, but with the hostname, which may be ignored by client
+	#we have to do it again with the nfs_ip 
+	local opts
+
+	case ${OCF_RESKEY_nfs_notify_cmd##*/} in 
+	sm-notify)
+		# run in foreground, if requested
+		if ocf_is_true "$OCF_RESKEY_nfs_notify_foreground"; then
+			opts="-d"
+		fi
+
+		if [ -n "$OCF_RESKEY_nfs_smnotify_retry_time" ]; then
+			opts="$opts -m $OCF_RESKEY_nfs_smnotify_retry_time"
+		fi
+
+		opts="$opts -f -v"
+		;;
+
+	rpc.statd)
+		if ocf_is_true "$OCF_RESKEY_nfs_notify_foreground"; then
+			opts="-F"
+		fi
+		opts="$opts -n"
+		;;
+
+	esac
+
+	rm -rf $STATD_PATH/sm.ha.save > /dev/null 2>&1
+	cp -rf $STATD_PATH/sm.ha $STATD_PATH/sm.ha.save > /dev/null 2>&1
+	for ip in `echo ${OCF_RESKEY_nfs_ip} | sed 's/,/ /g'`; do
+	  ${OCF_RESKEY_nfs_notify_cmd} $opts $ip -P $STATD_PATH/sm.ha
+	  rm -rf $STATD_PATH/sm.ha > /dev/null 2>&1
+	  cp -rf $STATD_PATH/sm.ha.save $STATD_PATH/sm.ha > /dev/null 2>&1
+	done
+
+
+	ocf_log info "NFS server started"
+	return $OCF_SUCCESS
+}
+
+nfsserver_stop ()
+{
+	ocf_log info "Stopping NFS server ..."
+
+	fn=`mktemp`
+	nfs_exec stop > $fn 2>&1
+	rc=$?
+	ocf_log debug `cat $fn`
+	rm -f $fn
+
+	if [ $rc -eq 0 ]; then
+		unbind_tree 
+		ocf_log info "NFS server stopped"
+		return $OCF_SUCCESS
+	fi
+	ocf_log err "Failed to stop NFS server"
+	return $rc
+}
+
+nfsserver_validate ()
+{
+	##
+	# set_exec_mode will exit if nfs server is not installed
+	##
+	set_exec_mode
+	check_binary ${OCF_RESKEY_nfs_notify_cmd}
+
+	if [ x = x"${OCF_RESKEY_nfs_ip}" ]; then
+		ocf_log err "nfs_ip not set"
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	if [ x = "x$OCF_RESKEY_nfs_shared_infodir" ]; then
+		ocf_log err "nfs_shared_infodir not set"
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	if [ -n "$OCF_RESKEY_nfs_smnotify_retry_time" ]; then
+		if ! ocf_is_decimal "$OCF_RESKEY_nfs_smnotify_retry_time"; then
+			ocf_log err "Invalid nfs_smnotify_retry_time [$OCF_RESKEY_nfs_smnotify_retry_time]"
+			exit $OCF_ERR_CONFIGURED
+		fi
+	fi
+
+	case ${OCF_RESKEY_nfs_notify_cmd##*/} in
+	sm-notify|rpc.statd) ;;
+	*)
+		ocf_log err "Invalid nfs_notify_cmd [$OCF_RESKEY_nfs_notify_cmd]"
+		exit $OCF_ERR_CONFIGURED
+		;;
+	esac
+
+	return $OCF_SUCCESS
+}
+
+if [ -n "$OCF_RESKEY_CRM_meta_clone" ]; then
+	ocf_log err "THIS RA DO NOT SUPPORT CLONE MODE!"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+nfsserver_validate
+
+case $__OCF_ACTION in
+	start)      nfsserver_start
+		;;
+	stop)       nfsserver_stop
+		;;
+	monitor)    nfsserver_monitor
+		;;
+	validate-all)   exit $OCF_SUCCESS
+		;;
+	*)      nfsserver_usage
+	exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+
diff --git a/heartbeat/nginx b/heartbeat/nginx
new file mode 100755
index 0000000..65fd8f2
--- /dev/null
+++ b/heartbeat/nginx
@@ -0,0 +1,947 @@
+#!/bin/sh
+#
+#	High-Availability nginx OCF resource agent
+# 
+# nginx
+#
+# Description:	starts/stops nginx servers.
+#
+# Author:	Alan Robertson
+#		Dejan Muhamedagic
+#		This code is based significantly on the apache resource agent
+#
+# Support:	linux-ha at lists.linux-ha.org
+#
+# License:	GNU General Public License (GPL)
+#
+# Copyright:	(C) 2002-2010 International Business Machines
+#
+#
+# Our parsing of the nginx config files is very rudimentary.
+# It'll work with lots of different configurations - but not every
+# possible configuration.
+#
+# Patches are being accepted ;-)
+#
+# OCF parameters:
+#  OCF_RESKEY_configfile
+#  OCF_RESKEY_nginx
+#  OCF_RESKEY_port
+#  OCF_RESKEY_options
+#  OCF_RESKEY_status10regex
+#  OCF_RESKEY_status10url
+#  OCF_RESKEY_client
+#  OCF_RESKEY_testurl
+#  OCF_RESKEY_test20regex
+#  OCF_RESKEY_test20conffile
+#  OCF_RESKEY_test20name
+#  OCF_RESKEY_external_monitor30_cmd
+#
+#
+#	TO DO:
+#		More extensive tests of extended monitor actions
+#		Look at the --with-http_stub_status_module for validating
+#			the configuration?  (or is that automatically done?)
+#			Checking could certainly result in better error
+#			messages.
+#		Allow for the fact that the config file and so on might all be
+#			on shared disks - this affects the validate-all option.
+
+
+: ${OCF_FUNCTIONS_DIR=$OCF_ROOT/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+HA_VARRUNDIR=${HA_VARRUN}
+
+#######################################################################
+#
+#	Configuration options - usually you don't need to change these
+#
+#######################################################################
+#
+NGINXDLIST="/usr/sbin/nginx /usr/local/sbin/nginx"
+
+# default options for http clients
+# NB: We _always_ test a local resource, so it should be
+# safe to connect from the local interface.
+WGETOPTS="-O- -q -L --no-proxy --bind-address=127.0.0.1"
+CURLOPTS="-o - -Ss -L --interface lo"
+
+LOCALHOST="http://localhost"
+NGINXDOPTS=""
+#
+#
+#	End of Configuration options
+#######################################################################
+
+CMD=`basename $0`
+
+#	The config-file-pathname is the pathname to the configuration
+#	file for this web server.  Various appropriate defaults are
+#	assumed if no config file is specified.
+usage() {
+  cat <<-!
+usage: $0 action
+
+action:
+	start	start nginx
+
+	stop	stop nginx
+
+	reload	reload the nginx configuration
+
+	status	return the status of web server, running or stopped
+
+	monitor  return TRUE if the web server appears to be working.
+                For this to be supported you must configure mod_status
+		and give it a server-status URL - or configure what URL
+		you wish to be monitored.  You have to have installed
+		either curl or wget for this to work.
+
+	meta-data	show meta data message
+
+	validate-all	validate the instance parameters
+	!
+  exit $1
+}
+
+#
+# run the http client
+#
+curl_func() {
+	cl_opts="$CURLOPTS $test_httpclient_opts"
+	if
+	  [ x != "x$test_user" ]
+        then
+	  echo "-u $test_user:$test_password" |
+	  curl -K - $cl_opts "$1"
+	else
+	  curl $cl_opts "$1"
+	fi
+}
+wget_func() {
+	auth=""
+	cl_opts="$WGETOPTS $test_httpclient_opts"
+	[ x != "x$test_user" ] &&
+		auth="--http-user=$test_user --http-passwd=$test_password"
+	wget $auth $cl_opts "$1"
+}
+#
+# rely on whatever the user provided
+userdefined() {
+	$test_httpclient $test_httpclient_opts "$1"
+}
+
+#
+# find a good http client
+#
+findhttpclient() {
+	# prefer curl if present...
+	if
+          [ "x$CLIENT" != x ]
+        then
+		echo "$CLIENT"
+	elif
+          which curl >/dev/null 2>&1
+        then
+		echo "curl"
+	elif
+          which wget >/dev/null 2>&1
+        then
+		echo "wget"
+	else
+		return 1
+	fi
+}
+gethttpclient() {
+	[ -z "$test_httpclient" ] &&
+		test_httpclient=$ourhttpclient
+	case "$test_httpclient" in
+		curl|wget) echo ${test_httpclient}_func;;  #these are supported
+		*) echo userdefined;;
+	esac
+}
+
+# test configuration good?
+is_testconf_sane() {
+	if
+          [ "x$test_regex" = x -o "x$test_url" = x ]
+        then
+	  ocf_log err "test regular expression or test url empty"
+	  return 1
+	fi
+	if
+          [ "x$test_user$test_password" != x -a \( "x$test_user" = x -o "x$test_password" = x \) ]
+        then
+	  ocf_log err "bad user authentication for extended test"
+	  return 1
+	fi
+	return 0
+}
+#
+# read the test definition from the config
+#
+readtestconf() {
+  test_name="$1" # we look for this one or the first one if empty
+  lcnt=0
+  readdef=""
+  test_url="" test_regex=""
+  test_user="" test_password=""
+  test_httpclient="" test_httpclient_opts=""
+
+  while
+    read key value
+  do
+    lcnt=$((lcnt+1))
+    if
+      [ "$readdef" ]
+    then
+      case "$key" in
+		"url") test_url="$value" ;;
+		"user") test_user="$value" ;;
+		"password") test_password="$value" ;;
+		"client") test_httpclient="$value" ;;
+		"client_opts") test_httpclient_opts="$value" ;;
+		"match") test_regex="$value" ;;
+		"end") break ;;
+		"#"*|"") ;;
+		*) ocf_log err "$lcnt: $key: unknown keyword"; return 1 ;;
+      esac
+    else
+      [ "$key" = "test" ] &&
+      [ -z "$test_name" -o "$test_name" = "$value" ] &&
+      readdef=1
+    fi
+  done
+}
+
+nginxcat() {
+  awk '
+	function procline() {
+		split($0,a);
+		if( a[1]~/^[Ii]nclude$/ ) {
+			procinclude(a[2]);
+		} else {
+			if( a[1]=="root" ) {
+				rootdir=a[2];
+				gsub("\"","",rootdir);
+			}
+			print;
+		}
+	}
+	function printfile(infile, a) {
+		while( (getline<infile) > 0 ) {
+			procline();
+		}
+		close(infile);
+	}
+	function allfiles(dir, cmd,f) {
+		cmd="find -L "dir" -type f";
+		while( ( cmd | getline f ) > 0 ) {
+			printfile(f);
+		}
+		close(cmd);
+	}
+	function listfiles(pattern, cmd,f) {
+		cmd="ls "pattern" 2>/dev/null";
+		while( ( cmd | getline f ) > 0 ) {
+			printfile(f);
+		}
+		close(cmd);
+	}
+	function procinclude(spec) {
+		if( rootdir!="" && spec!~/^\// ) {
+			spec=rootdir"/"spec;
+		}
+		if( isdir(spec) ) {
+			allfiles(spec); # read all files in a directory (and subdirs)
+		} else {
+			listfiles(spec); # there could be jokers
+		}
+	}
+	function isdir(s) {
+		return !system("test -d \""s"\"");
+	}
+	{ procline(); }
+	' $1 |
+  sed 's/#.*//;s/[[:blank:]]*$//;s/^[[:blank:]]*//' |
+  grep -v '^$'
+}
+
+#
+# set parameters (as shell vars) from our nginx config file
+#
+get_nginx_params() {
+  configfile=$1
+  shift 1
+  vars=`echo $@ | sed 's/ /,/g'`
+
+  eval `
+  nginxcat $configfile | awk -v vars="$vars" '
+  BEGIN{
+    split(vars,v,",");
+    for( i in v )
+  	  vl[i]=tolower(v[i]);
+  }
+  {
+	  for( i in v )
+	  	if( tolower($1)==vl[i] ) {
+			print v[i]"="$2
+			delete vl[i]
+			break
+		}
+  }
+  '`
+}
+
+#
+#	Return the location(s) that are handled by the given handler
+#
+FindLocationForHandler() {
+  PerlScript='while (<>) {
+	/^\s*location\s+([^ \s{]+)\s*{/i && ($loc=$1);
+	/^\s*stub_status\s+on\s*;$2/i && print "$loc\n"; 
+  }'
+  nginxcat $1 | perl -e "$PerlScript"
+}
+
+#
+#	Check if the port is valid
+#
+CheckPort() {
+  lclport="$1"
+  case "$lclport" in
+    *:[0-9]*)	lclport=`echo "$lclport" | sed 's%^[^:][^:]*:%%'`
+  esac
+  ocf_is_decimal "$lclport" && [ $lclport -gt 0 -a $lclport -lt 65537 ]
+}
+
+buildlocalurl() {
+  [ "x$listen" != "x" ] &&
+	echo "http://${listen}" ||
+	echo "${LOCALHOST}:${PORT}"
+}
+#
+#	Get all the parameters we need from the Nginx config file
+#
+GetParams() {
+  ConfigFile=$1
+  DEFAULT_PID=`echo "$NGINX_CONFIGURATION" | sed -e 's%.*--pid-path=%%' -e 's% *--.*%%'`
+  if
+    [ ! -f $ConfigFile ]
+  then
+    return 1
+  fi
+
+  get_nginx_params $ConfigFile root pid listen
+  PidFile="$pid"
+  case $PidFile in
+    "")	PidFile=$DEFAULT_PID	;;
+    *)				;;
+  esac
+
+  for p in "$PORT" "$listen" 80
+  do
+    if
+      CheckPort "$p"
+    then
+      PORT="$p"
+      break
+    fi
+  done
+ 
+  echo $listen | grep ':' >/dev/null ||  # Listen could be just port spec
+	  listen="localhost:$listen"
+
+  #
+  # It's difficult to figure out whether the server supports
+  # the status operation.
+  # (we start our server with -DSTATUS - just in case :-))
+  #
+  # Typically (but not necessarily) the status URL is /nginx_status
+  #
+  # For us to think status will work, we have to have the following things:
+  #
+  # - The server-status handler has to be mapped to some URL somewhere
+  #
+  # We assume that:
+  #
+  # - the "main" web server at $PORT will also support it if we can find it
+  #	somewhere in the file
+  # - it will be supported at the same URL as the one we find in the file
+  #
+  # If this doesn't work for you, then set the status10url attribute.
+  #
+  if
+     [ "X$STATUSURL" = "X" ]
+  then
+      StatusURL=`FindLocationForHandler $1 nginx_status | tail -1`
+      STATUSURL="`buildlocalurl`$StatusURL"
+  fi
+  test ! -z "$PidFile"
+}
+
+#
+# return TRUE if a process with given PID is running
+#
+ProcessRunning() {
+    NginxPID=$1
+    # Use /proc if it looks like it's here...
+    if
+      [ -d /proc -a -d /proc/1 ]
+    then
+       [ -d /proc/$NginxPID ]
+    else
+      #  This assumes we're running as root...
+      kill -0 "$NginxPID" >/dev/null 2>&1
+    fi
+}
+
+
+silent_status() {
+  if
+    [ -f $PidFile  -a  -s $PidFile ]  && ocf_is_decimal "`cat $PidFile`"
+  then
+    ProcessRunning `cat $PidFile`
+  else
+    : No pid file
+    false
+  fi
+}
+
+start_nginx() {
+  if
+    silent_status
+  then
+    ocf_log info "$CMD already running (pid $NginxPID)"
+    return $OCF_SUCCESS
+  fi
+  if 
+    ocf_run $NGINXD -t -c $CONFIGFILE
+  then
+    : Configuration file $CONFIGFILE looks OK
+  else
+    return $OCF_ERR_CONFIGURED
+  fi
+  NGINX_VERSION=`$NGINXD -v 2>&1`
+  ocf_log info "Starting $NGINXD - $NGINX_VERSION"
+  ocf_log info "$NGINXD build configuration: $NGINX_CONFIGURATION"
+  if 
+    ocf_run $NGINXD $NGINXDOPTS $OPTIONS -c $CONFIGFILE
+  then
+    : $NGINXD started without errors!
+  else
+    return $OCF_ERR_GENERIC
+  fi
+  tries=0
+  # This looks like a potential infinite loop - but it's not in practice
+  # The LRM will time us out and kill us if nginx never starts working.
+  while
+    monitor_nginx
+    ec=$?
+    if
+      [ $ec -eq $OCF_NOT_RUNNING ]
+    then
+      tries=`expr $tries + 1`
+      ocf_log info "Waiting for $NGINXD -c $CONFIGFILE to come up (try $tries)"
+      true
+    else
+      false
+    fi
+  do
+    sleep 1
+  done
+  return $ec
+}
+
+stop_nginx() {
+  if
+    silent_status
+  then
+    if
+      kill $NginxPID
+    then
+      tries=0
+      while
+        ProcessRunning $NginxPID && [ $tries -lt 10 ]
+      do
+        sleep 1
+        kill $NginxPID >/dev/null 
+        ocf_log info "Killing nginx PID $NginxPID"
+        tries=`expr $tries + 1`
+      done
+    else
+      ocf_log warn "Killing nginx PID $NginxPID FAILED."
+    fi
+    if
+      ProcessRunning $NginxPID
+    then
+      ocf_log info "$CMD still running ($NginxPID)."
+      false
+    else
+      ocf_log info "$CMD stopped."
+    fi
+  else
+    ocf_log info "$CMD is not running."
+  fi
+
+  #
+  #	I'm not convinced this is a wonderful idea (AlanR)
+  #
+  for sig in SIGTERM SIGHUP SIGKILL
+  do
+    if
+      pgrep -f "$NGINXD.*$CONFIGFILE" >/dev/null
+    then
+      pkill -$sig -f $NGINXD.*$CONFIGFILE >/dev/null
+      ocf_log info "nginxd children were signalled ($sig)"
+      sleep 1
+    else
+      break
+    fi
+  done
+}
+
+reload_nginx() {
+  if
+    silent_status
+  then
+    if
+      kill -1 $NginxPID
+    then
+      : $NGINX reload signal to $NginxPID succeeded
+      return $OCF_SUCCESS
+    fi
+    return $OCF_ERR_GENERIC
+  fi
+  start_nginx
+}
+
+status_nginx() {
+  silent_status
+  rc=$?
+  if
+    [ $rc -eq 0 ]
+  then
+    ocf_log info "$CMD is running (pid $NginxPID)."
+    return $OCF_SUCCESS
+  else
+    ocf_log info "$CMD is stopped."
+    return $OCF_NOT_RUNNING
+  fi
+}
+
+fixtesturl() {
+	echo $test_url | grep -qs "^http" && return
+	test_url="`buildlocalurl`$test_url"
+}
+
+monitor_nginx_external() {
+  if
+    [ -z "$EXTMONITOR" ]
+  then
+    ocf_log err "$External level 30 Monitor Command not configured."
+    return $OCF_ERR_CONFIGURED
+  fi
+  extbase=`echo $EXTMONITOR | sed 's% .*%%'`
+  if
+    case "$extbase" in
+      /*)	test -f "$extbase" -a -x "$extbase";;
+      *)	which "$extbase" >/dev/null 2>&1
+    esac
+  then
+    : OK - $extbase seems to be there...
+  else
+    ocf_log err "$External monitor command [$extbase] is not installed."
+    return $OCF_ERR_CONFIGURED
+  fi
+  if
+    $extbase
+  then
+    : OK - $extbase succeeded
+  else
+    ocf_log err "$extbase reported failure [rc=$?]"
+    return $OCF_NOT_RUNNING
+  fi
+  return $OCF_SUCCESS
+}
+
+
+monitor_nginx_extended() {
+  if
+    [ -f "$TESTCONFFILE" -a -r "$TESTCONFFILE" ]
+  then
+    readtestconf < $TESTCONFFILE
+  else
+    test_url="$TESTURL"
+    test_regex="$TESTREGEX20"
+  fi
+  whattorun=`gethttpclient`
+  fixtesturl
+  is_testconf_sane || return $OCF_ERR_CONFIGURED
+  $whattorun "$test_url" | grep -Ei "$test_regex" > /dev/null
+}
+
+monitor_nginx_basic() {
+  if
+    [ -z "$STATUSURL" ]
+  then
+    ocf_log err "status10url parameter empty"
+    return $OCF_ERR_CONFIGURED
+  elif
+    [ -z "$ourhttpclient" ]
+  then
+    ocf_log err "could not find a http client; make sure that either wget or curl is available"
+	return $OCF_ERR_CONFIGURED
+  fi
+  ${ourhttpclient}_func "$STATUSURL" | grep -Ei "$TESTREGEX" > /dev/null
+}
+
+monitor_nginx() {
+  silent_status
+  if
+    [ $? -ne 0 ]
+  then
+    ocf_log info "$CMD not running"
+    return $OCF_NOT_RUNNING
+  fi
+  if
+    [ -z "$OCF_CHECK_LEVEL" ] || [ "$OCF_CHECK_LEVEL" -lt 10  ]
+  then
+    return 0
+  fi
+  ourhttpclient=`findhttpclient`  # we'll need one
+  if
+    [ "$OCF_CHECK_LEVEL" -lt 20 ]
+  then
+    monitor_nginx_basic
+  elif
+    [ "$OCF_CHECK_LEVEL" -lt 30 ]
+  then
+    monitor_nginx_extended
+  else
+    monitor_nginx_external
+  fi
+}
+
+metadata_nginx(){
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="nginx">
+<version>1.0</version>
+
+<longdesc lang="en">
+This is the resource agent for the Nginx web/proxy server.
+This resource agent does not monitor POP or IMAP servers, as
+we don't know how to determine meaningful status for them.
+
+The start operation ends with a loop in which monitor is
+repeatedly called to make sure that the server started and that
+it is operational. Hence, if the monitor operation does not
+succeed within the start operation timeout, the nginx resource
+will end with an error status.
+
+The default monitor operation will verify that nginx is running.
+
+The level 10 monitor operation by default will try and fetch the /nginx_status
+page - which is commented out in sample nginx configurations.
+Make sure that the /nginx_status page works and that the access
+is restricted to localhost (address 127.0.0.1) plus whatever
+places _outside the cluster_ you want to monitor the server from.
+See the status10url and status10regex attributes for more details.
+
+The level 20 monitor operation will perform a more complex set of tests
+from a configuration file.
+
+The level 30 monitor operation will run an external command to perform
+an arbitrary monitoring operation.
+
+</longdesc>
+<shortdesc lang="en">Manages an Nginx web/proxy server instance</shortdesc>
+
+<parameters>
+
+<parameter name="configfile" required="0" unique="1">
+<longdesc lang="en">
+The full pathname of the Nginx configuration file.
+This file is parsed to provide defaults for various other
+resource agent parameters.
+</longdesc>
+<shortdesc lang="en">configuration file path</shortdesc>
+<content type="string"/>
+</parameter>
+
+<parameter name="httpd">
+<longdesc lang="en">
+The full pathname of the httpd binary (optional).
+</longdesc>
+<shortdesc lang="en">httpd binary path</shortdesc>
+<content type="string" default="/usr/sbin/httpd" />
+</parameter>
+
+<parameter name="port" >
+<longdesc lang="en">
+A port number that we can probe for status information
+using the statusurl.
+This will default to the port number found in the
+configuration file, or 80, if none can be found
+in the configuration file.
+
+</longdesc>
+<shortdesc lang="en">httpd port</shortdesc>
+<content type="integer" />
+</parameter>
+
+<parameter name="status10url">
+<longdesc lang="en">
+The URL to monitor (the nginx server status page by default) when given a level 10 monitor operation.
+If left unspecified, it will be inferred from
+the nginx configuration file, or defaulted to /nginx_status.
+
+If you set this, make sure that it succeeds *only* from the
+localhost (127.0.0.1) and no other cluster nodes.
+Otherwise, the cluster software may complain
+about it being active on multiple nodes.
+</longdesc>
+<shortdesc lang="en">url name</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="status10regex">
+<longdesc lang="en">
+Regular expression to match in the output of status10url.
+Case insensitive.
+</longdesc>
+<shortdesc lang="en">monitor regular expression</shortdesc>
+<content type="string" default="Reading: [0-9]+ Writing: [0-9]+ Waiting: [0-9]+"/>
+</parameter>
+
+<parameter name="testclient">
+<longdesc lang="en">
+Client to use to query to Nginx for level 10 and level 20 tests.
+If not specified, the RA will try to find one on the system.
+Currently, wget and curl are supported, with curl being preferred.
+For example, you can set this paramter to "wget" if you prefer that to curl.
+</longdesc>
+<shortdesc lang="en">http client</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="testurl">
+<longdesc lang="en">
+URL to test. If it does not start with "http", then it's
+considered to be relative to the document root address.
+</longdesc>
+<shortdesc lang="en">Level 10 monitor url</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="test20regex">
+<longdesc lang="en">
+Regular expression to match in the output of testurl.
+Case insensitive.
+</longdesc>
+<shortdesc lang="en">Level 20 monitor regular expression</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="testconffile">
+<longdesc lang="en">
+A file which contains a more complex test configuration. Could be useful if
+you have to check more than one web application or in case sensitive
+info should be passed as arguments (passwords). Furthermore,
+using a config file is the only way to specify certain parameters.
+
+Please see README.webapps for examples and file description.
+</longdesc>
+<shortdesc lang="en">Level 20 test configuration file</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="test20name">
+<longdesc lang="en">
+Name of the test within the test configuration file.
+</longdesc>
+<shortdesc lang="en">Level 20 test name</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="external_monitor30_cmd">
+<longdesc lang="en">
+Command string to run which implements level 30 monitoring.
+</longdesc>
+<shortdesc lang="en">Level 30 test string</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="options">
+<longdesc lang="en">
+Extra options to apply when starting nginx.
+</longdesc>
+<shortdesc lang="en">nginx start options</shortdesc>
+<content type="string" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="40s" />
+<action name="stop"    timeout="60s" />
+<action name="reload"  timeout="40s" />
+<action name="status"  timeout="30s" />
+<action name="monitor" timeout="30s" depth="0" interval="10s" />
+<action name="monitor" timeout="30s" depth="10" interval="30s" />
+<action name="monitor" timeout="45s" depth="20" />
+<action name="monitor" timeout="60s" depth="30" />
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="5" />
+</actions>
+</resource-agent>
+END
+
+  exit $OCF_SUCCESS
+}
+
+validate_all_nginx() {
+  if
+    CheckPort $PORT
+    # We are sure to succeed here, since we forced $PORT to be valid in GetParams()
+  then
+    : OK
+  else
+    ocf_log err "Port number $PORT is invalid!"
+    exit $OCF_ERR_ARGS
+  fi
+
+  if
+    [ -z $STATUSURL ]
+  then
+    : OK to be empty
+  else
+    case $STATUSURL in
+      http://*/*) ;;
+      *) ocf_log err "Invalid STATUSURL $STATUSURL"
+         exit $OCF_ERR_ARGS ;;
+    esac
+  fi
+  if
+    [ ! -x $NGINXD ]
+  then
+    ocf_log err "NGINXD $NGINXD not found or is not an executable!"
+    exit $OCF_ERR_ARGS
+  fi
+  if
+    [ ! -f $CONFIGFILE ]
+  then
+    # We are sure to succeed here, since we have parsed $CONFIGFILE before getting here
+    ocf_log err "Configuration file $CONFIGFILE not found!"
+    exit $OCF_ERR_CONFIGURED
+  fi
+  if
+    ocf_run $NGINXD -t -c $CONFIGFILE
+  then
+    : Cool $NGINXD likes $CONFIGFILE
+  else
+    ocf_log err "$NGINXD -t -c $CONFIGFILE reported a configuration error."
+    return $OCF_ERR_CONFIGURED
+  fi
+  return $OCF_SUCCESS
+}
+
+if
+  [ $# -eq 1 ]
+then
+  COMMAND=$1
+  NGINXD="$OCF_RESKEY_httpd"
+  PORT="$OCF_RESKEY_port"
+  STATUSURL="$OCF_RESKEY_status10url"
+  CONFIGFILE="$OCF_RESKEY_configfile"
+  OPTIONS="$OCF_RESKEY_options"
+  CLIENT=${OCF_RESKEY_client}
+  TESTREGEX=${OCF_RESKEY_status10regex:-'Reading: [0-9]+ Writing: [0-9]+ Waiting: [0-9]+'}
+  TESTURL="$OCF_RESKEY_status10url"
+  TESTREGEX20=${OCF_RESKEY_test20regex}
+  TESTCONFFILE="$OCF_RESKEY_test20conffile"
+  TESTNAME="$OCF_RESKEY_test20name"
+  EXTMONITOR="$OCF_RESKEY_external_monitor30_cmd"
+else
+  usage $OCF_ERR_ARGS
+fi
+
+LSB_STATUS_STOPPED=3
+if
+  [ "X$NGINXD" = X -o ! -f "$NGINXD" -o ! -x "$NGINXD" ]
+then
+  NGINXD=
+  for h in $NGINXDLIST
+  do
+    if
+      [ -f "$h" -a -x "$h" ]
+    then
+      NGINXD="$h"
+      break
+    fi
+  done
+# It is possible that we still do not have a valid httpd at this stage
+  if
+    [ -z "$NGINXD" ]
+  then
+    case $COMMAND in
+	    stop)	exit $OCF_SUCCESS;;
+	    monitor)	exit $OCF_NOT_RUNNING;;
+            status)	exit $LSB_STATUS_STOPPED;;
+  	    meta-data)	metadata_nginx;;
+    esac
+    ocf_log err "nginx binary not found! Please verify you've installed it"
+    exit $OCF_ERR_INSTALLED
+  fi
+  # Let the user know that the $NGINXD used is the one (s)he specified via $OCF_RESKEY_httpd
+  if
+    [ ! -z "$OCF_RESKEY_httpd" ]
+  then
+    ocf_log info "Using $NGINXD as nginx"
+  fi
+fi
+
+httpd_basename=`basename $NGINXD`
+case $httpd_basename in
+  *-*)	httpd_basename=`echo "$httpd_basename" | sed -e 's%\-.*%%'`;;
+esac
+NGINX_CONFIGURATION=`$NGINXD -V 2>&1 |grep 'configure arguments:'`
+DEFAULT_CONFIG=`echo "$NGINX_CONFIGURATION" | sed -e 's%.*--conf-path=%%' -e 's% *--.*%%'`
+
+case "$CONFIGFILE" in
+  "") CONFIGFILE=$DEFAULT_CONFIG;;
+  *)		;;
+esac
+
+if
+  [ ! -f "$CONFIGFILE" ]
+then
+  case $COMMAND in
+    stop)	ocf_log warn "$CONFIGFILE not found - nginx considered stopped"
+    		exit $OCF_SUCCESS;;
+    monitor)	exit $OCF_NOT_RUNNING;;
+    status)	exit $LSB_STATUS_STOPPED;;
+  esac
+fi
+
+if
+  [ "X$COMMAND" = Xmeta-data ] || GetParams $CONFIGFILE
+then
+  : OK
+else
+  ocf_log err "Cannot parse config file [$CONFIGFILE]"
+  exit $OCF_ERR_CONFIGURED
+fi
+
+case $COMMAND in
+  start)	start_nginx;;
+  stop)		stop_nginx;;
+  reload)	reload_nginx;;
+  status)	status_nginx;;
+  monitor)	monitor_nginx;;
+  meta-data)	metadata_nginx;;
+  validate-all)	validate_all_nginx;;
+  *)		usage $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/heartbeat/ocf-binaries.in b/heartbeat/ocf-binaries.in
new file mode 100644
index 0000000..a78a348
--- /dev/null
+++ b/heartbeat/ocf-binaries.in
@@ -0,0 +1,74 @@
+# Make sure PATH contains all the usual suspects
+PATH="$PATH:/sbin:/bin:/usr/sbin:/usr/bin"
+
+# Include /usr/ucb for finding whoami on Solaris
+PATH="$PATH:/usr/ucb"
+
+export PATH
+
+# Binaries and binary options for use in Resource Agents
+: ${AWK:=@AWK@}
+: ${EGREP:="@EGREP@"}
+: ${IFCONFIG_A_OPT:="@IFCONFIG_A_OPT@"}
+: ${MAILCMD:=@MAILCMD@}
+: ${PING:=@PING@}
+: ${SH:=@SHELL@}
+: ${TEST:=@TEST@}
+: ${TESTPROG:=@TEST@}
+
+# Entries that should probably be removed
+: ${BASENAME:=basename}
+: ${BLOCKDEV:=blockdev}
+: ${CAT:=cat}
+: ${FSCK:=fsck}
+: ${FUSER:=fuser}
+: ${GETENT:=getent}
+: ${GREP:=grep}
+: ${IFCONFIG:=ifconfig}
+: ${IPTABLES:=iptables}
+: ${IP2UTIL:=ip}
+: ${MDADM:=mdadm}
+: ${MODPROBE:=modprobe}
+: ${MOUNT:=mount}
+: ${MSGFMT:=msgfmt}
+: ${NETSTAT:=netstat}
+: ${PERL:=perl}
+: ${PYTHON:=python}
+: ${RAIDSTART:=raidstart}
+: ${RAIDSTOP:=raidstop}
+: ${ROUTE:=route}
+: ${UMOUNT:=umount}
+: ${REBOOT:=reboot}
+: ${POWEROFF_CMD:=poweroff}
+: ${WGET:=wget}
+: ${WHOAMI:=whoami}
+: ${STRINGSCMD:=strings}
+: ${SCP:=scp}
+: ${SSH:=ssh}
+: ${SWIG:=swig}
+: ${GZIP_PROG:=gzip}
+: ${TAR:=tar}
+: ${MD5:=md5}
+: ${DRBDADM:=drbdadm}
+: ${DRBDSETUP:=drbdsetup}
+
+check_binary () {
+    if ! have_binary "$1"; then
+	if [ "$OCF_NOT_RUNNING" = 7 ]; then
+	    # Chances are we have a fully setup OCF environment
+	    ocf_log err "Setup problem: couldn't find command: $1"
+	else 
+	    echo "Setup problem: couldn't find command: $1"
+	fi
+	exit $OCF_ERR_INSTALLED
+    fi
+}
+
+have_binary () {
+    if [ "$OCF_TESTER_FAIL_HAVE_BINARY" = "1" ]; then
+    	false
+    else
+	local bin=`echo $1 | sed -e 's/ -.*//'`
+	test -x "`which $bin 2>/dev/null`"
+    fi
+}
diff --git a/heartbeat/ocf-directories.in b/heartbeat/ocf-directories.in
new file mode 100644
index 0000000..6e0a9d5
--- /dev/null
+++ b/heartbeat/ocf-directories.in
@@ -0,0 +1,22 @@
+# Binaries and binary options for use in Resource Agents
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+: ${INITDIR:=@INITDIR@}
+: ${HA_DIR:=@sysconfdir@/ha.d}
+: ${HA_RCDIR:=$HA_DIR/rc.d}
+: ${HA_CONFDIR=$HA_DIR/conf}
+: ${HA_CF:=$HA_DIR/ha.cf}
+: ${HA_VARLIB:=@localstatedir@/lib/heartbeat}
+: ${HA_RSCTMP:=@HA_RSCTMPDIR@}
+: ${HA_RSCTMP_OLD:=@HA_VARRUNDIR@/heartbeat/rsctmp}
+: ${HA_FIFO:=@localstatedir@/lib/heartbeat/fifo}
+: ${HA_BIN:=@libexecdir@/heartbeat}
+: ${HA_SBIN_DIR:=@sbindir@}
+: ${HA_DATEFMT:="%Y/%m/%d_%T "}
+: ${HA_DEBUGLOG:=/dev/null}
+: ${HA_RESOURCEDIR:=$HA_DIR/resource.d}
+: ${HA_DOCDIR:=@datadir@/doc/heartbeat}
+: ${__SCRIPT_NAME:=`basename $0`}
+: ${HA_VARRUN:=@localstatedir@/run/}
+: ${HA_VARLOCK:=@localstatedir@/lock/subsys/}
diff --git a/heartbeat/ocf-rarun b/heartbeat/ocf-rarun
new file mode 100644
index 0000000..ec4bdba
--- /dev/null
+++ b/heartbeat/ocf-rarun
@@ -0,0 +1,146 @@
+#
+# This is the OCF RA driver. It should take care of all the
+# boring details and leave only the parts which are really about
+# the actual resource to the resource agent.
+# 
+# The interface
+#
+# The RA needs to define functions for all supported actions and
+# name them <RA>_<action>. For instance, apache_start or
+# apache_meta_data.
+#
+# The following functions are required:
+#
+# - <RA>_methods
+# - <RA>_usage
+# - <RA>_meta_data
+# - <RA>_start
+# - <RA>_stop
+# - <RA>_monitor
+#
+# The required parameters should all be listed in the
+# OCF_REQUIRED_PARAMS variable. For example, "config user group".
+#
+# The OCF_REQUIRED_BINARIES variable should contain a list of all
+# programs which are needed for the correct operation of the
+# resource agent.
+#
+# <RA>_getconfig and <RA>_validate_all are optional. getconfig is
+# where RA can read more configuration from the file system or do
+# some other configuration processing.
+# validate_all checks if the environment is OK.
+#
+# If it exists, the <RA>_probe function is invoked on probes
+# (monitor with interval 0) instead of <RA>_monitor.
+#
+# NB: If the RA name contains a '-', it is going to be converted
+# to '_' when generating function names. For syslog-ng for
+# instance, the monitor function name would be syslog_ng_monitor
+
+is_function() {
+	test z"`command -v $1`" = z"$1"
+}
+run_function() {
+	is_function $1 && $1
+}
+is_var_defined() {
+	test z != "z$(eval echo $`echo $1`)"
+}
+mk_action_func() {
+	ACTION_FUNC=`echo ${OCF_RESOURCE_TYPE}_$__OCF_ACTION | tr '-' '_'`
+}
+validate_args() {
+	is_function $ACTION_FUNC || {
+		ocf_log err "$__OCF_ACTION: action not supported"
+		run_function ${OCF_RESOURCE_TYPE}_methods
+		exit $OCF_ERR_UNIMPLEMENTED
+	}
+}
+simple_actions() {
+	case $__OCF_ACTION in
+	meta-data|usage|methods)
+		$ACTION_FUNC
+		exit $OCF_SUCCESS
+		;;
+	esac
+}
+run_probe() {
+	if is_function ${OCF_RESOURCE_TYPE}_probe; then
+		${OCF_RESOURCE_TYPE}_probe
+		exit
+	fi
+}
+check_required_params() {
+	local v
+	for v in $OCF_REQUIRED_PARAMS; do
+		is_var_defined OCF_RESKEY_$v || {
+			ocf_log err "$v: required parameter not set"
+			exit $OCF_ERR_CONFIGURED
+		}
+	done
+}
+# this function does an exit (end of the road)
+handle_invalid_env() {
+	local rc msg
+	rc=$1
+	msg=${2:-"environment is invalid, resource considered stopped"}
+	case "$__OCF_ACTION" in
+		stop)
+			ocf_log info $msg
+			exit $OCF_SUCCESS
+		;;
+		monitor)
+			if ocf_is_probe; then
+				ocf_log info $msg
+				exit $OCF_NOT_RUNNING
+			else
+				# in recurring monitor, this amounts to error
+				ocf_log err $msg
+				exit $OCF_ERR_GENERIC
+			fi
+		;;
+		status)
+			ocf_log info $msg
+			exit $LSB_STATUS_STOPPED
+		;;
+		*)
+			ocf_log err $msg
+			exit $rc
+		;;
+	esac
+}
+check_required_binaries() {
+	local v
+	for v in $OCF_REQUIRED_BINARIES; do
+		have_binary $v || {
+			handle_invalid_env $OCF_ERR_INSTALLED "$v: required binary not installed"
+			# unreachable
+		}
+	done
+}
+validate_env() {
+	check_required_binaries  # all binaries present?
+	is_function ${OCF_RESOURCE_TYPE}_validate_all ||
+		return
+	local rc
+	LSB_STATUS_STOPPED=3
+	${OCF_RESOURCE_TYPE}_validate_all # is environment ok?
+	rc=$?
+	if [ $rc -ne 0 ]; then
+		handle_invalid_env $rc
+		# unreachable
+	fi
+}
+
+# ocf_rarun: the main function
+ocf_rarun() {
+	mk_action_func  # create action function name
+	validate_args  # validate command line arguments
+	simple_actions  # run meta-data (or similar)
+	check_required_params  # all required parameters defined?
+	run_function ${OCF_RESOURCE_TYPE}_getconfig # get extra configuration
+	validate_env # is environment ok?
+	ocf_is_probe && run_probe  # do probe
+	shift 1  # skip action
+	$ACTION_FUNC $*  # run action
+}
diff --git a/heartbeat/ocf-returncodes b/heartbeat/ocf-returncodes
new file mode 100644
index 0000000..dd5f017
--- /dev/null
+++ b/heartbeat/ocf-returncodes
@@ -0,0 +1,55 @@
+#
+# 	Common varibales for the OCF Resource Agents supplied by
+# 	heartbeat.
+#
+# Copyright (c) 2004 SUSE LINUX AG, Andrew Beekhof
+#                    All Rights Reserved.
+#
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# 
+
+OCF_SUCCESS=0
+OCF_ERR_GENERIC=1
+OCF_ERR_ARGS=2
+OCF_ERR_UNIMPLEMENTED=3
+OCF_ERR_PERM=4
+OCF_ERR_INSTALLED=5
+OCF_ERR_CONFIGURED=6
+OCF_NOT_RUNNING=7
+
+# Non-standard values.
+#
+# OCF does not include the concept of master/slave resources so we
+#   need to extend it so we can discover a resource's complete state.
+#
+# OCF_RUNNING_MASTER:  
+#    The resource is in "master" mode and fully operational
+# OCF_FAILED_MASTER:
+#    The resource is in "master" mode but in a failed state
+# 
+# The extra two values should only be used during a probe.
+#
+# Probes are used to discover resources that were started outside of
+#    the CRM and/or left behind if the LRM fails.
+# 
+# They can be identified in RA scripts by checking for:
+#   [ "${__OCF_ACTION}" = "monitor" -a "${OCF_RESKEY_CRM_meta_interval}" = "0" ]
+# 
+# Failed "slaves" should continue to use: OCF_ERR_GENERIC
+# Fully operational "slaves" should continue to use: OCF_SUCCESS
+#
+OCF_RUNNING_MASTER=8
+OCF_FAILED_MASTER=9
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
new file mode 100644
index 0000000..edeb47f
--- /dev/null
+++ b/heartbeat/ocf-shellfuncs.in
@@ -0,0 +1,780 @@
+#
+#
+# 	Common helper functions for the OCF Resource Agents supplied by
+# 	heartbeat.
+#
+# Copyright (c) 2004 SUSE LINUX AG, Lars Marowsky-Brée
+#                    All Rights Reserved.
+#
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# 
+
+# Build version: 32dd79a119834cd3482b01d4bba623e7b8c0d8b4
+
+# TODO: Some of this should probably split out into a generic OCF
+# library for shell scripts, but for the time being, we'll just use it
+# ourselves...
+#
+
+# TODO wish-list:
+# - Generic function for evaluating version numbers
+# - Generic function(s) to extract stuff from our own meta-data
+# - Logging function which automatically adds resource identifier etc
+#   prefixes
+# TODO: Move more common functionality for OCF RAs here.
+#
+
+# This was common throughout all legacy Heartbeat agents
+unset LC_ALL; export LC_ALL
+unset LANGUAGE; export LANGUAGE
+
+__SCRIPT_NAME=`basename $0`
+
+if [ -z "$OCF_ROOT" ]; then
+    : ${OCF_ROOT=@OCF_ROOT_DIR@}
+fi
+
+if [ "$OCF_FUNCTIONS_DIR" = ${OCF_ROOT}/resource.d/heartbeat ]; then  # old
+	unset OCF_FUNCTIONS_DIR
+fi
+
+: ${OCF_FUNCTIONS_DIR:=${OCF_ROOT}/lib/heartbeat}
+
+. ${OCF_FUNCTIONS_DIR}/ocf-binaries
+. ${OCF_FUNCTIONS_DIR}/ocf-returncodes
+. ${OCF_FUNCTIONS_DIR}/ocf-directories
+. ${OCF_FUNCTIONS_DIR}/ocf-rarun
+
+# Define OCF_RESKEY_CRM_meta_interval in case it isn't already set,
+# to make sure that ocf_is_probe() always works
+: ${OCF_RESKEY_CRM_meta_interval=0}
+
+ocf_is_root() {
+	if [ X`id -u` = X0 ]; then
+		true
+	else
+		false
+	fi
+}
+
+ocf_maybe_random() {
+	local rnd="$RANDOM"
+	# Something sane-ish in case a shell doesn't support $RANDOM
+	[ -n "$rnd" ] || rnd=$$
+	echo $rnd
+}
+
+# Portability comments:
+# o The following rely on Bourne "sh" pattern-matching, which is usually
+#   that for filename generation (note: not regexp).
+# o The "*) true ;;" clause is probably unnecessary, but is included
+#   here for completeness.
+# o The negation in the pattern uses "!".  This seems to be common
+#   across many OSes (whereas the alternative "^" fails on some).
+# o If an OS is encountered where this negation fails, then a possible
+#   alternative would be to replace the function contents by (e.g.):
+#	[ -z "`echo $1 | tr -d '[0-9]'`" ]
+#
+ocf_is_decimal() {
+	case "$1" in
+	""|*[!0-9]*)	# empty, or at least one non-decimal
+		false ;;
+	*)
+		true ;;
+	esac
+}
+
+ocf_is_true() {
+	case "$1" in
+	yes|true|1|YES|TRUE|ja|on|ON) true ;;
+	*)	false ;;
+	esac
+}
+
+ocf_is_hex() {
+	case "$1" in
+        ""|*[!0-9a-fA-F]*)	# empty, or at least one non-hex
+		false ;;
+	*)
+		true ;;
+	esac
+}
+
+ocf_is_octal() {
+	case "$1" in
+        ""|*[!0-7]*)	# empty, or at least one non-octal
+		false ;;
+	*)
+		true ;;
+	esac
+}
+
+__ocf_set_defaults() {
+	__OCF_ACTION="$1"
+
+	# Return to sanity for the agents...
+	unset LANG
+	LC_ALL=C
+	export LC_ALL
+
+	# TODO: Review whether we really should source this. Or rewrite
+	# to match some emerging helper function syntax...? This imports
+	# things which no OCF RA should be using...
+
+	# Strip the OCF_RESKEY_ prefix from this particular parameter
+	if [ -z "$OCF_RESKEY_OCF_CHECK_LEVEL" ]; then
+		: ${OCF_CHECK_LEVEL:=0}
+	else
+		: ${OCF_CHECK_LEVEL:=$OCF_RESKEY_OCF_CHECK_LEVEL}
+	fi
+
+	if [ ! -d "$OCF_ROOT" ]; then
+		ha_log "ERROR: OCF_ROOT points to non-directory $OCF_ROOT."
+		exit $OCF_ERR_GENERIC
+	fi
+
+	if [ -z "$OCF_RESOURCE_TYPE" ]; then
+		: ${OCF_RESOURCE_TYPE:=$__SCRIPT_NAME}
+	fi
+
+	if [ -z "$OCF_RA_VERSION_MAJOR" ]; then
+		: We are being invoked as an init script.
+		: Fill in some things with reasonable values.
+		: ${OCF_RESOURCE_INSTANCE:="default"}
+		return 0
+        fi
+
+	if [ "x$__OCF_ACTION" = "xmeta-data" ]; then
+		OCF_RESOURCE_INSTANCE="undef"
+	fi	
+
+	if [ -z "$OCF_RESOURCE_INSTANCE" ]; then
+		ha_log "ERROR: Need to tell us our resource instance name."
+		exit $OCF_ERR_ARGS
+	fi
+}
+
+hadate() {
+  date "+${HA_DATEFMT}"
+}
+
+set_logtag() {
+	if [ -z "$HA_LOGTAG" ]; then
+		if [ -n "$OCF_RESOURCE_INSTANCE" ]; then
+			HA_LOGTAG="$__SCRIPT_NAME($OCF_RESOURCE_INSTANCE)[$$]"
+		else
+			HA_LOGTAG="$__SCRIPT_NAME[$$]"
+		fi
+	fi
+}
+
+ha_log() {
+	local loglevel
+	[ none = "$HA_LOGFACILITY" ] && HA_LOGFACILITY=""
+	# if we're connected to a tty, then output to stderr
+	if tty >/dev/null; then
+		if [ "x$HA_debug" = "x0" -a "x$loglevel" = xdebug ] ; then
+			return 0
+		fi
+		if [ "$HA_LOGTAG" ]; then
+			echo "$HA_LOGTAG: $*"
+		else
+			echo "$*"
+		fi >&2
+		return 0
+	fi
+
+	set_logtag
+
+	if [ "x${HA_LOGD}" = "xyes" ] ; then 
+		ha_logger -t "${HA_LOGTAG}" "$@"
+		if [ "$?" -eq "0" ] ; then
+			return 0
+		fi
+	fi
+
+	if
+	  [ -n "$HA_LOGFACILITY" ]
+        then
+	  : logging through syslog
+	  # loglevel is unknown, use 'notice' for now
+          loglevel=notice
+          case "${*}" in
+            *ERROR*)		loglevel=err;;
+            *WARN*)		loglevel=warning;;
+            *INFO*|info)	loglevel=info;;
+	  esac
+	  logger -t "$HA_LOGTAG" -p ${HA_LOGFACILITY}.${loglevel} "${*}"
+        fi	
+        if
+	  [ -n "$HA_LOGFILE" ]
+	then
+	  : appending to $HA_LOGFILE
+	  echo "$HA_LOGTAG:	"`hadate`"${*}" >> $HA_LOGFILE
+	fi
+	if
+	  [ -z "$HA_LOGFACILITY" -a -z "$HA_LOGFILE" ]
+	then
+	  : appending to stderr
+	  echo `hadate`"${*}" >&2
+	fi
+        if
+          [ -n "$HA_DEBUGLOG" ]
+        then
+          : appending to $HA_DEBUGLOG
+		  if [ "$HA_LOGFILE"x != "$HA_DEBUGLOG"x ]; then
+            echo "$HA_LOGTAG:	"`hadate`"${*}" >> $HA_DEBUGLOG
+          fi
+        fi
+}
+
+ha_debug() {
+
+        if [ "x${HA_debug}" = "x0" ] ; then
+                return 0
+        fi
+	if tty >/dev/null; then
+		if [ "$HA_LOGTAG" ]; then
+			echo "$HA_LOGTAG: $*"
+		else
+			echo "$*"
+		fi >&2
+		return 0
+	fi
+
+	set_logtag
+
+        if [ "x${HA_LOGD}" = "xyes" ] ; then  
+		ha_logger -t "${HA_LOGTAG}" -D "ha-debug" "$@"
+                if [ "$?" -eq "0" ] ; then
+                        return 0
+                fi
+        fi
+
+	[ none = "$HA_LOGFACILITY" ] && HA_LOGFACILITY=""
+
+	if
+	  [ -n "$HA_LOGFACILITY" ]
+	then
+	  : logging through syslog
+	  logger -t "$HA_LOGTAG" -p "${HA_LOGFACILITY}.debug" "${*}"
+	fi
+        if
+	  [ -n "$HA_DEBUGLOG" ]
+	then
+	  : appending to $HA_DEBUGLOG
+	  echo "$HA_LOGTAG:	"`hadate`"${*}" >> $HA_DEBUGLOG
+	fi
+	if
+	  [ -z "$HA_LOGFACILITY" -a -z "$HA_DEBUGLOG" ]
+	then
+	  : appending to stderr
+	  echo "$HA_LOGTAG:	`hadate`${*}:	${HA_LOGFACILITY}" >&2
+	fi
+}
+
+ha_parameter() {
+	local VALUE
+    VALUE=`sed -e 's%[	][	]*% %' -e 's%^ %%' -e 's%#.*%%'   $HA_CF | grep -i "^$1 " | sed 's%[^ ]* %%'`
+    if
+	[ "X$VALUE" = X ]
+    then
+	
+	case $1 in
+	    keepalive)	VALUE=2;;
+	    deadtime)
+		ka=`ha_parameter keepalive`
+		VALUE=`expr $ka '*' 2 '+' 1`;;
+	esac
+    fi
+    echo $VALUE
+}
+
+ocf_log() {
+	# TODO: Revisit and implement internally.
+	if
+          [ $# -lt 2 ]
+        then
+          ocf_log err "Not enough arguments [$#] to ocf_log."
+        fi
+        __OCF_PRIO="$1"
+        shift
+        __OCF_MSG="$*"
+
+        case "${__OCF_PRIO}" in
+          crit)	__OCF_PRIO="CRIT";;
+          err)	__OCF_PRIO="ERROR";;
+          warn)	__OCF_PRIO="WARNING";;
+          info)	__OCF_PRIO="INFO";;
+          debug)__OCF_PRIO="DEBUG";;
+          *)	__OCF_PRIO=`echo ${__OCF_PRIO}| tr '[a-z]' '[A-Z]'`;;
+	esac
+
+	if [ "${__OCF_PRIO}" = "DEBUG" ]; then
+		ha_debug "${__OCF_PRIO}: $__OCF_MSG"
+	else
+		ha_log "${__OCF_PRIO}: $__OCF_MSG"
+	fi
+}
+
+#
+# ocf_deprecated: Log a deprecation warning
+# Usage:          ocf_deprecated [param-name]
+# Arguments:      param-name optional, name of a boolean resource
+#                            parameter that can be used to suppress
+#                            the warning (default
+#                            "ignore_deprecation")
+ocf_deprecated() {
+    local param
+    param=${1:-ignore_deprecation}
+    # don't use ${!param} here, it's a bashism
+    if ! ocf_is_true $(eval echo \$OCF_RESKEY_$param); then
+	ocf_log warn "This resource agent is deprecated" \
+	    "and may be removed in a future release." \
+	    "See the man page for details." \
+	    "To suppress this warning, set the \"${param}\"" \
+	    "resource parameter to true."
+    fi
+}
+
+#
+# Ocf_run: Run a script, and log its output.
+# Usage:   ocf_run [-q] [-info|-warn|-err] <command>
+#	-q: don't log the output of the command if it succeeds
+#	-info|-warn|-err: log the output of the command at given
+#		severity if it fails (defaults to err)
+#
+ocf_run() {
+	local rc
+	local output
+	local verbose=1
+	local loglevel=err
+	local var
+
+	for var in 1 2
+	do
+	    case "$1" in
+		"-q")
+		    verbose=""
+		    shift 1;;
+		"-info"|"-warn"|"-err")
+		    loglevel=`echo $1 | sed -e s/-//g`
+		    shift 1;;
+		*)
+		    ;;		
+	    esac
+	done
+
+	output=`"$@" 2>&1`
+	rc=$?
+	output=`echo $output`
+	if [ $rc -eq 0 ]; then 
+	    if [ "$verbose" -a ! -z "$output" ]; then
+		ocf_log info "$output"
+	    fi
+	    return $OCF_SUCCESS
+	else
+	    if [ ! -z "$output" ]; then
+		ocf_log $loglevel "$output"
+	    else
+		ocf_log $loglevel "command failed: $*"
+	    fi
+	    return $rc
+	fi
+}
+
+ocf_pidfile_status() {
+    local pid pidfile=$1
+    if [ ! -e $pidfile ]; then
+	# Not exists
+	return 2
+    fi
+    pid=`cat $pidfile`
+    kill -0 $pid 2>&1 > /dev/null
+    if [ $? = 0 ]; then
+	return 0
+    fi
+
+    # Stale
+    return 1
+}
+
+ocf_take_lock() {
+    local lockfile=$1
+    local rnd=$(ocf_maybe_random)
+
+    sleep 0.$rnd
+    while 
+	ocf_pidfile_status $lockfile
+    do
+	ocf_log info "Sleeping until $lockfile is released..."
+	sleep 0.$rnd
+    done
+    echo $$ > $lockfile
+}
+
+
+ocf_release_lock_on_exit() {
+    local lockfile=$1
+    trap "rm -f $lockfile" EXIT
+}
+
+# returns true if the CRM is currently running a probe. A probe is
+# defined as a monitor operation with a monitoring interval of zero.
+ocf_is_probe() {
+    [ "$__OCF_ACTION" = "monitor" -a "$OCF_RESKEY_CRM_meta_interval" = 0 ]
+}
+
+# returns true if the resource is configured as a clone. This is
+# defined as a resource where the clone-max meta attribute is present,
+# and set to greater than zero.
+ocf_is_clone() {
+    [ ! -z "${OCF_RESKEY_CRM_meta_clone_max}" ] && [ "${OCF_RESKEY_CRM_meta_clone_max}" -gt 0 ]
+}
+
+# returns true if the resource is configured as a multistate
+# (master/slave) resource. This is defined as a resource where the
+# master-max meta attribute is present, and set to greater than zero.
+ocf_is_ms() {
+    [ ! -z "${OCF_RESKEY_CRM_meta_master_max}" ] && [ "${OCF_RESKEY_CRM_meta_master_max}" -gt 0 ]
+}
+
+# version check functions
+# allow . and - to delimit version numbers
+# max version number is 999
+# letters and such are effectively ignored
+#
+ocf_is_ver() {
+	echo $1 | grep '^[0-9][0-9.-]*[0-9]$' >/dev/null 2>&1
+}
+ocf_ver2num() {
+	echo $1 | awk -F'[.-]' '
+	{for(i=1; i<=NF; i++) s=s*1000+$i; print s}
+	'
+}
+ocf_ver_level(){
+	echo $1 | awk -F'[.-]' '{print NF}'
+}
+ocf_ver_complete_level(){
+	local ver="$1"
+	local level="$2"
+	local i=0
+	while [ $i -lt $level ]; do
+		ver=${ver}.0
+		i=`expr $i + 1`
+	done
+	echo $ver
+}
+
+# usage: ocf_version_cmp VER1 VER2
+#     version strings can contain digits, dots, and dashes
+#     must start and end with a digit
+# returns:
+#     0: VER1 smaller (older) than VER2
+#     1: versions equal
+#     2: VER1 greater (newer) than VER2
+#     3: bad format
+ocf_version_cmp() {
+	ocf_is_ver "$1" || return 3
+	ocf_is_ver "$2" || return 3
+	local v1=$1
+	local v2=$2
+	local v1_level=`ocf_ver_level $v1`
+	local v2_level=`ocf_ver_level $v2`
+	local level_diff
+	if [ $v1_level -lt $v2_level ]; then
+		level_diff=`expr $v2_level - $v1_level`
+		v1=`ocf_ver_complete_level $v1 $level_diff`
+	elif [ $v1_level -gt $v2_level ]; then
+		level_diff=`expr $v1_level - $v2_level`
+		v2=`ocf_ver_complete_level $v2 $level_diff`
+	fi
+	v1=`ocf_ver2num $v1`
+	v2=`ocf_ver2num $v2`
+	if [ $v1 -eq $v2 ]; then
+		return 1
+	elif [ $v1 -lt $v2 ]; then
+		return 0
+	else
+		return 2 # -1 would look funny in shell ;-)
+	fi
+}
+
+ocf_local_nodename() {
+	# use crm_node -n for pacemaker > 1.1.8
+	which pacemakerd > /dev/null 2>&1
+	if [ $? -eq 0 ]; then
+		local version=$(pacemakerd -$ | grep "Pacemaker .*" | awk '{ print $2 }')
+		ocf_version_cmp "$version" "1.1.8"
+		if [ $? -eq 2 ]; then
+			which crm_node > /dev/null 2>&1
+			if [ $? -eq 0 ]; then
+				crm_node -n
+				return
+			fi
+		fi
+	fi
+
+	# otherwise use uname -n
+	uname -n
+}
+
+# usage: dirname DIR
+dirname()
+{
+	local a
+	local b
+
+	[ $# = 1 ] || return 1
+	a="$1"
+	while [ 1 ]; do
+		b="${a%/}"
+		[ "$a" = "$b" ] && break
+		a="$b"
+	done
+	b=${a%/*}
+	[ -z "$b" -o "$a" = "$b"  ] && b="."
+
+	echo "$b"
+	return 0
+}
+
+#
+# pseudo_resource status tracking function...
+#
+# This allows pseudo resources to give correct status information.  As we add
+# resource monitoring, and better resource tracking in general, this will
+# become essential.
+#
+# These scripts work because ${HA_RSCTMP} is cleaned out every time
+# heartbeat is started.
+#
+# We create "resource-string" tracking files under ${HA_RSCTMP} in a
+# very simple way:
+#
+#	Existence of "${HA_RSCTMP}/resource-string" means that we consider
+#	the resource named by "resource-string" to be running.
+#
+# Note that "resource-string" needs to be unique.  Using the resource type
+# plus the resource instance arguments to make up the resource string
+# is probably sufficient...
+#
+# usage: ha_pseudo_resource resource-string op [tracking_file]
+# 	where op is {start|stop|monitor|status|restart|reload|print}
+#	print is a special op which just prints the tracking file location
+#	user can override our choice of the tracking file location by
+#		specifying it as the third arg
+#	Note that all operations are silent...
+#
+ha_pseudo_resource()
+{
+  local ha_resource_tracking_file="${3:-${HA_RSCTMP}/$1}"
+  case $2 in
+    start|restart|reload)  touch "$ha_resource_tracking_file";;
+    stop) rm -f "$ha_resource_tracking_file";;
+    status|monitor)
+           if
+             [ -f "$ha_resource_tracking_file" ]
+           then
+             return 0
+           else
+             case $2 in
+               status)	return 3;;
+               *)	return 7;;
+             esac
+           fi;;
+    print)  echo "$ha_resource_tracking_file";;
+    *)	return 3;;
+  esac
+}
+
+# usage: rmtempdir TMPDIR
+rmtempdir()
+{
+	[ $# = 1 ] || return 1
+	if [ -e "$1" ]; then
+		rmdir "$1" || return 1
+	fi
+	return 0
+}
+
+# usage: maketempfile [-d]
+maketempfile()
+{
+	if [ $# = 1 -a "$1" = "-d" ]; then
+		mktemp -d
+		return -0
+	elif [ $# != 0 ]; then
+		return 1
+	fi
+
+	mktemp
+	return 0
+}
+
+# usage: rmtempfile TMPFILE
+rmtempfile ()
+{
+	[ $# = 1 ] || return 1
+	if [ -e "$1" ]; then
+		rm "$1" || return 1
+	fi
+	return 0
+}
+
+# echo the first lower supported check level
+# pass set of levels supported by the agent
+# (in increasing order, 0 is optional)
+ocf_check_level()
+{
+	local lvl prev
+	lvl=0
+	prev=0
+	if ocf_is_decimal "$OCF_CHECK_LEVEL"; then
+		# the level list should be very short
+		for lvl; do
+			if [ "$lvl" -eq "$OCF_CHECK_LEVEL" ]; then
+				break
+			elif [ "$lvl" -gt "$OCF_CHECK_LEVEL" ]; then
+				lvl=$prev # the previous one
+				break
+			fi
+			prev=$lvl
+		done
+	fi
+	echo $lvl
+}
+
+# usage: ocf_stop_processes SIGNALS WAIT_TIME PIDS
+#
+# we send signals (use quotes for more than one!) in the order
+# given; if one or more processes are still running we try KILL;
+# the wait_time is the _total_ time we'll spend in this function
+# this time may be slightly exceeded if the processes won't leave
+# 
+# returns:
+#     0: all processes left
+#     1: some processes still running
+#
+# example:
+#
+# ocf_stop_processes TERM 5 $pids
+# 
+ocf_stop_processes() {
+	local signals="$1"
+	local wait_time="$(($2/`echo $signals|wc -w`))"
+	shift 2
+	local pids="$*"
+	local sig i
+	test -z "$pids" &&
+		return 0
+	for sig in $signals KILL; do
+		kill -s $sig $pids 2>/dev/null
+		# try to leave early, and yet leave processes time to exit
+		sleep 0.2
+		for i in `seq $wait_time`; do
+			kill -s 0 $pids 2>/dev/null ||
+				return 0
+			sleep 1
+		done
+	done
+	return 1
+}
+
+#
+# RA tracing may be turned on by setting OCF_TRACE_RA
+# the trace output will be saved to OCF_TRACE_FILE, if set, or
+# by default to
+#   $HA_VARLIB/trace_ra/<type>/<id>.<action>.<timestamp>
+#   e.g. $HA_VARLIB/trace_ra/oracle/db.start.2012-11-27.08:37:08
+#
+# OCF_TRACE_FILE:
+# - FD (small integer [3-9]) in that case it is up to the callers
+#   to capture output; the FD _must_ be open for writing
+# - absolute path
+#
+# NB: FD 9 may be used for tracing with bash >= v4 in case
+# OCF_TRACE_FILE is set to a path.
+#
+ocf_is_bash4() {
+	echo "$SHELL" | grep bash > /dev/null &&
+			[ ${BASH_VERSINFO[0]} = "4" ]
+}
+ocf_trace_redirect_to_file() {
+	local dest=$1
+	if ocf_is_bash4; then
+		exec 9>$dest
+		BASH_XTRACEFD=9
+	else
+		exec 2>$dest
+	fi
+}
+ocf_trace_redirect_to_fd() {
+	local fd=$1
+	if ocf_is_bash4; then
+		BASH_XTRACEFD=$fd
+	else
+		exec 2>&$fd
+	fi
+}
+__ocf_test_trc_dest() {
+	local dest=$1
+	if ! touch $dest; then
+		ocf_log warn "$dest not writable, trace not going to happen"
+		__OCF_TRC_DEST=""
+		__OCF_TRC_MANAGE=""
+		return 1
+	fi
+	return 0
+}
+ocf_default_trace_dest() {
+	tty >/dev/null && return
+	if [ -n "$OCF_RESOURCE_TYPE" -a \
+			-n "$OCF_RESOURCE_INSTANCE" -a -n "$__OCF_ACTION" ]; then
+		local ts=`date +%F.%T`
+		__OCF_TRC_DEST=$HA_VARLIB/trace_ra/${OCF_RESOURCE_TYPE}/${OCF_RESOURCE_INSTANCE}.${__OCF_ACTION}.$ts
+		__OCF_TRC_MANAGE="1"
+	fi
+}
+
+ocf_start_trace() {
+	export __OCF_TRC_DEST="" __OCF_TRC_MANAGE=""
+	case "$OCF_TRACE_FILE" in
+	[3-9]) ocf_trace_redirect_to_fd "$OCF_TRACE_FILE" ;;
+	/*/*) __OCF_TRC_DEST=$OCF_TRACE_FILE ;;
+	"") ocf_default_trace_dest ;;
+	*)
+		ocf_log warn "OCF_TRACE_FILE must be set to either FD (open for writing) or absolute file path"
+		ocf_default_trace_dest
+		;;
+	esac
+	if [ "$__OCF_TRC_DEST" ]; then
+		mkdir -p `dirname $__OCF_TRC_DEST`
+		__ocf_test_trc_dest $__OCF_TRC_DEST ||
+			return
+		ocf_trace_redirect_to_file "$__OCF_TRC_DEST"
+	fi
+	PS4='+ `date +"%T"`: ${FUNCNAME[0]:+${FUNCNAME[0]}:}${LINENO}: '
+	set -x
+}
+ocf_stop_trace() {
+	set +x
+}
+
+__ocf_set_defaults "$@"
+
+: ${OCF_TRACE_RA:=$OCF_RESKEY_trace_ra}
+ocf_is_true "$OCF_TRACE_RA" && ocf_start_trace
diff --git a/heartbeat/ora-common.sh b/heartbeat/ora-common.sh
new file mode 100644
index 0000000..5bbb163
--- /dev/null
+++ b/heartbeat/ora-common.sh
@@ -0,0 +1,84 @@
+# ora-common.sh
+#
+# Description: Common code for oracle and oralsnr resource agents
+#
+#
+# Author:      Dejan Muhamedagic
+# Support:     linux-ha at lists.linux-ha.org
+# License:     GNU General Public License (GPL)
+# Copyright:   (C) 2012 Dejan Muhamedagic, SUSE/Attachmate
+#
+
+#      Gather up information about our oracle instance
+
+rmtmpfiles() {
+	rm -f $TMPFILES
+}
+
+ora_common_getconfig() {
+	ORACLE_SID=$1
+	ORACLE_HOME=$2
+	ORACLE_OWNER=$3
+	TNS_ADMIN=$4
+
+	# get ORACLE_HOME from /etc/oratab if not set
+	[ x = "x$ORACLE_HOME" ] &&
+		ORACLE_HOME=`awk -F: "/^$ORACLE_SID:/"'{print $2}' /etc/oratab`
+
+	# there a better way to find out ORACLE_OWNER?
+	[ x = "x$ORACLE_OWNER" ] &&
+		ORACLE_OWNER=`ls -ld $ORACLE_HOME/. 2>/dev/null | awk 'NR==1{print $3}'`
+
+	# There are use-cases were users want to be able to set a custom TMS_ADMIN path.
+	# When TNS_ADMIN is not provided, use the default path.
+	[ x = "x$TNS_ADMIN" ] &&
+		TNS_ADMIN=$ORACLE_HOME/network/admin
+
+	LD_LIBRARY_PATH=$ORACLE_HOME/lib
+	LIBPATH=$ORACLE_HOME/lib
+	PATH=$ORACLE_HOME/bin:$ORACLE_HOME/dbs:$PATH
+	export ORACLE_SID ORACLE_HOME ORACLE_OWNER TNS_ADMIN
+	export LD_LIBRARY_PATH LIBPATH
+
+	ORA_ENVF=`mktemp`
+	dumporaenv > $ORA_ENVF
+	chmod 644 $ORA_ENVF
+	TMPFILES="$ORA_ENVF"
+	trap "rmtmpfiles" EXIT
+}
+
+ora_common_validate_all() {
+	#	Let's make sure a few important things are set...
+	if [ x = "x$ORACLE_HOME" ]; then
+		ocf_log info "ORACLE_HOME not set"
+		return $OCF_ERR_INSTALLED
+	fi
+	if [ x = "x$ORACLE_OWNER" ]; then
+		ocf_log info "ORACLE_OWNER not set"
+		return $OCF_ERR_INSTALLED
+	fi
+
+	US=`id -u -n`
+	if [ $US != root -a $US != $ORACLE_OWNER ]
+	then
+	  ocf_log err "$0 must be run as root or $ORACLE_OWNER"
+	  return $OCF_ERR_PERM
+	fi
+	return 0
+}
+
+dumporaenv() {
+cat<<EOF
+PATH=$ORACLE_HOME/bin:$ORACLE_HOME/dbs:$PATH
+ORACLE_SID=$ORACLE_SID
+ORACLE_HOME=$ORACLE_HOME
+ORACLE_OWNER=$ORACLE_OWNER
+LD_LIBRARY_PATH=$ORACLE_HOME/lib
+LIBPATH=$ORACLE_HOME/lib
+TNS_ADMIN=$TNS_ADMIN
+export ORACLE_SID ORACLE_HOME ORACLE_OWNER TNS_ADMIN
+export LD_LIBRARY_PATH LIBPATH
+EOF
+}
+
+# vim:tabstop=4:shiftwidth=4:textwidth=0:wrapmargin=0
diff --git a/heartbeat/oracle b/heartbeat/oracle
new file mode 100755
index 0000000..d6b2c50
--- /dev/null
+++ b/heartbeat/oracle
@@ -0,0 +1,659 @@
+#!/bin/sh
+#
+# 
+# oracle
+#
+# Description:	Manages an Oracle Database as a High-Availability
+#		resource
+#
+#
+# Author:	Dejan Muhamedagic
+# Support:	linux-ha at lists.linux-ha.org
+# License:	GNU General Public License (GPL)
+# Copyright:	(C) 2006 International Business Machines, Inc.
+#
+#		This code inspired by the DB2 resource script
+#		written by Alan Robertson
+#
+# An example usage in /etc/ha.d/haresources: 
+#       node1  10.0.0.170 oracle::RK1::/oracle/10.2::orark1
+#
+# See oracle_usage() function below for more details...
+#
+# OCF instance parameters:
+#	OCF_RESKEY_sid
+#	OCF_RESKEY_home (optional; else read it from /etc/oratab)
+#	OCF_RESKEY_user (optional; figure it out by checking file ownership)
+#	OCF_RESKEY_ipcrm (optional; defaults to "instance")
+#	OCF_RESKEY_clear_backupmode (optional; default to "false")
+#	OCF_RESKEY_shutdown_method (optional; default to "checkpoint/abort")
+#
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+. ${OCF_FUNCTIONS_DIR}/ora-common.sh
+
+#######################################################################
+
+oracle_usage() {
+  methods=`oracle_methods`
+  methods=`echo $methods | tr ' ' '|'`
+  cat <<-!
+	usage: $0 {$methods}
+
+	$0 manages an Oracle Database instance as an HA resource.
+
+	The 'start' operation starts the database.
+	The 'stop' operation stops the database.
+	The 'status' operation reports whether the database is running
+	The 'monitor' operation reports whether the database seems to be working
+	The 'dumpinstipc' operation prints IPC resources used by the instance
+	The 'cleanup' operation tries to clean up after Oracle was brutally stopped
+	The 'validate-all' operation reports whether the parameters are valid
+	The 'methods' operation reports on the methods $0 supports
+
+	!
+}
+
+oracle_meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="oracle">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for oracle. Manages an Oracle Database instance
+as an HA resource.
+</longdesc>
+<shortdesc lang="en">Manages an Oracle Database instance</shortdesc>
+
+<parameters>
+
+<parameter name="sid" unique="1" required="1">
+<longdesc lang="en">
+The Oracle SID (aka ORACLE_SID).
+</longdesc>
+<shortdesc lang="en">sid</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="home" unique="0">
+<longdesc lang="en">
+The Oracle home directory (aka ORACLE_HOME).
+If not specified, then the SID along with its home should be listed in
+/etc/oratab.
+</longdesc>
+<shortdesc lang="en">home</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="user" unique="0">
+<longdesc lang="en">
+The Oracle owner (aka ORACLE_OWNER).
+If not specified, then it is set to the owner of
+file \$ORACLE_HOME/dbs/*\${ORACLE_SID}.ora.
+If this does not work for you, just set it explicitely.
+</longdesc>
+<shortdesc lang="en">user</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="ipcrm" unique="0">
+<longdesc lang="en">
+Sometimes IPC objects (shared memory segments and semaphores)
+belonging to an Oracle instance might be left behind which
+prevents the instance from starting. It is not easy to figure out
+which shared segments belong to which instance, in particular when
+more instances are running as same user.
+
+What we use here is the "oradebug" feature and its "ipc" trace
+utility. It is not optimal to parse the debugging information, but
+I am not aware of any other way to find out about the IPC
+information. In case the format or wording of the trace report
+changes, parsing might fail. There are some precautions, however,
+to prevent stepping on other peoples toes. There is also a
+dumpinstipc option which will make us print the IPC objects which
+belong to the instance. Use it to see if we parse the trace file
+correctly.
+
+Three settings are possible:
+
+- none: don't mess with IPC and hope for the best (beware: you'll
+  probably be out of luck, sooner or later)
+- instance: try to figure out the IPC stuff which belongs to the
+  instance and remove only those (default; should be safe)
+- orauser: remove all IPC belonging to the user which runs the
+  instance (don't use this if you run more than one instance as same
+  user or if other apps running as this user use IPC)
+
+The default setting "instance" should be safe to use, but in that
+case we cannot guarantee that the instance will start. In case IPC
+objects were already left around, because, for instance, someone
+mercilessly killing Oracle processes, there is no way any more to
+find out which IPC objects should be removed. In that case, human
+intervention is necessary, and probably _all_ instances running as
+same user will have to be stopped. The third setting, "orauser",
+guarantees IPC objects removal, but it does that based only on IPC
+objects ownership, so you should use that only if every instance
+runs as separate user.
+
+Please report any problems. Suggestions/fixes welcome.
+</longdesc>
+<shortdesc lang="en">ipcrm</shortdesc>
+<content type="string" default="instance" />
+</parameter>
+
+<parameter name="clear_backupmode" unique="0" required="0">
+<longdesc lang="en">
+The clear of the backup mode of ORACLE.
+</longdesc>
+<shortdesc lang="en">clear_backupmode</shortdesc>
+<content type="boolean" default="false" />
+</parameter>
+
+<parameter name="shutdown_method" unique="0" required="0">
+<longdesc lang="en">
+How to stop Oracle is a matter of taste it seems. The default
+method ("checkpoint/abort") is:
+
+	alter system checkpoint;
+	shutdown abort;
+
+This should be the fastest safe way bring the instance down. If
+you find "shutdown abort" distasteful, set this attribute to
+"immediate" in which case we will
+
+	shutdown immediate;
+
+If you still think that there's even better way to shutdown an
+Oracle instance we are willing to listen.
+</longdesc>
+<shortdesc lang="en">shutdown_method</shortdesc>
+<content type="string" default="checkpoint/abort" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="120" />
+<action name="stop" timeout="120" />
+<action name="status" timeout="5" />
+<action name="monitor" depth="0" timeout="30" interval="120" />
+<action name="validate-all" timeout="5" />
+<action name="methods" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+
+#
+# methods: What methods/operations do we support?
+#
+oracle_methods() {
+  cat <<-!
+	start
+	stop
+	status
+	monitor
+	dumpinstipc
+	showdbstat
+	cleanup
+	validate-all
+	methods
+	meta-data
+	usage
+	!
+}
+
+#
+#	Run commands as the Oracle owner...
+#
+execsql() {
+	if [ "$US" = "$ORACLE_OWNER" ]; then
+		sqlplus -S /nolog
+	else
+		su - $ORACLE_OWNER -s /bin/sh -c ". $ORA_ENVF; sqlplus -S /nolog"
+	fi
+}
+
+#
+#	Run commands in the oracle admin sqlplus...
+#
+common_sql_opts() {
+	cat<<EOF
+set feedback off
+set heading off
+set pagesize 0
+EOF
+}
+common_sql_filter() {
+	grep -v '^Connected' |
+		grep -v '^ENV MSG:' |
+		grep -v 'Your password will expire in'
+}
+runsql() {
+	local conn_s="$1"
+	shift 1
+	local func
+	(
+	echo "$conn_s"
+	common_sql_opts
+	for func; do $func; done
+	) |
+	execsql | common_sql_filter
+}
+dbasql() {
+	runsql "connect / as sysdba" $*
+}
+monsql() {
+	runsql "connect $MONUSR/$MONUSR" $*
+}
+# use dbasql_one if the query should result in a single line output
+# at times people stuff commands in oracle .profile
+# which may produce extra output
+dbasql_one() {
+	dbasql $* | tail -1
+}
+monsql_one() {
+	monsql $* | tail -1
+}
+
+#
+# various interesting sql
+#
+dbstat() {
+	echo 'select status from v$instance;'
+}
+dbmount() {
+	echo 'alter database mount;'
+}
+dbopen() {
+	echo 'alter database open;'
+}
+dbstop_immediate() {
+	echo 'shutdown immediate'
+}
+dbstop_checkpoint_abort() {
+	echo 'alter system checkpoint;'
+	echo 'shutdown abort'
+}
+dbstop() {
+	case "${shutdown_method}" in
+	"immediate")
+		dbstop_immediate
+	;;
+	"checkpoint/abort")
+		dbstop_checkpoint_abort
+	;;
+	esac
+}
+dbstart() {
+	echo 'startup'
+}
+dbstart_mount() {
+	echo 'startup mount'
+}
+dbendbackup() {
+	echo 'alter database end backup;'
+}
+db_backup_mode() {
+	echo "select 'COUNT'||count(*) from v\$backup where status='ACTIVE';"
+}
+is_clear_backupmode_set(){
+	[ x"${clear_backupmode}" = x"true" ]
+}
+is_instance_in_backup_mode() {
+	local count
+	count="`dbasql_one db_backup_mode | sed 's/COUNT//'`"
+	[ x"$count" != x"0" ]
+}
+clear_backup_mode() {
+	local output
+	output="`dbasql dbendbackup`"
+	ocf_log info "Oracle instance $ORACLE_SID alter database end backup: $output"
+}
+getdumpdest() {
+	#echo 'select value from v$parameter where name = \'user_dump_dest\';'
+	echo "select value from v\$parameter where name = 'user_dump_dest';"
+}
+getipc() {
+	echo "oradebug setmypid"
+	echo "oradebug tracefile_name"
+	echo "oradebug ipc"
+}
+show_mon_user() {
+	echo "select USERNAME, ACCOUNT_STATUS from dba_users where USERNAME='$MONUSR';"
+}
+mk_mon_user() {
+	cat<<EOF
+create user $MONUSR identified by $MONUSR;
+grant create session to $MONUSR;
+grant select on v_\$instance to $MONUSR;
+EOF
+}
+check_mon_user() {
+	local output
+	dbasql show_mon_user | grep -w "^$MONUSR" >/dev/null &&
+		return 0
+	output=`dbasql mk_mon_user show_mon_user`
+	if echo "$output" | grep -w "^$MONUSR" >/dev/null; then
+		return 0
+	else
+		ocf_log err "could not create $MONUSR oracle user"
+		ocf_log err "sqlplus output: $output"
+		return 1
+	fi
+}
+#
+# print the output of dbstat (for debugging)
+#
+showdbstat() {
+	echo "Full output:"
+	dbstat | execsql
+	echo "Stripped output:"
+	echo "<`dbasql dbstat`>"
+}
+
+#
+# IPC stuff: not overly complex, but quite involved :-/
+#
+
+# Part 1: Oracle
+other_trace_junk() {
+	echo $1 | sed 's/trc$/trm/'
+}
+dumpinstipc() {
+	local output tracef
+	output=`dbasql getipc` # filename in the 2nd line
+	tracef=`echo "$output" | awk 'NR==2' | grep '^/.*trc$'`
+	if [ "$tracef" ]; then
+		echo $tracef
+	else
+		ocf_log warn "'dbasql getipc' failed: $output"
+		return 1
+	fi
+}
+parseipc() {
+	local inf=$1
+	if [ ! -f "$1" ]; then
+		ocf_log warn "$1: no such ipc trace file"
+		return 1
+	fi
+	awk '
+		$3 == "Shmid" {n=1;next}
+		n {
+			if( $3~/^[0-9]+$/ ) print $3;
+			n=0
+		}
+	' $inf |
+	sort -u | sed 's/^/m:/'
+	awk '
+		/Semaphore List/ {insems=1;next}
+		insems {
+			for( i=1; i<=NF; i++ )
+				if( $i~/^[0-9]+$/ ) print $i;
+		}
+		/system semaphore information/ {exit}
+	' $inf |
+	sort -u | sed 's/^/s:/'
+	TMPFILES="$TMPFILES $inf `other_trace_junk $inf`"
+}
+
+# Part 2: OS (ipcs,ipcrm)
+filteroraipc() {  # this portable?
+	grep -w $ORACLE_OWNER | awk '{print $2}'
+}
+ipcdesc() {
+	local what=$1
+	case $what in
+	m) echo "shared memory segment";;
+	s) echo "semaphore";;
+	q) echo "message queue";;
+	esac
+}
+rmipc() {
+	local what=$1 id=$2
+	ipcs -$what | filteroraipc | grep -w $id >/dev/null 2>&1 ||
+		return
+	ocf_log info "Removing `ipcdesc $what` $id."
+	ipcrm -$what $id
+}
+ipcrm_orauser() {
+	local what id
+	for what in m s q; do
+		for id in `ipcs -$what | filteroraipc`; do
+			rmipc $what $id
+		done
+	done
+}
+ipcrm_instance() {
+	local ipcobj
+	for ipcobj; do
+		rmipc `echo $ipcobj | sed 's/:/ /'`
+	done
+}
+
+#
+# oracle_status: is the Oracle instance running?
+#
+# quick check to see if the instance is up
+is_proc_running() {
+	ps -ef | grep -wiqs "[^ ]*[_]pmon_${ORACLE_SID}"
+}
+# instance in OPEN state?
+instance_live() {
+	local status=`monsql_one dbstat`
+	if [ "$status" = OPEN ]; then
+		return 0
+	else
+		ocf_log info "$ORACLE_SID instance state is not OPEN (dbstat output: $status)"
+		return 1
+	fi
+}
+
+ora_cleanup() {
+	#rm -fr /tmp/.oracle #???
+	rm -f `ls $ORACLE_HOME/dbs/lk* | grep -i "$ORACLE_SID\$"`
+	#return
+
+	case $IPCRM in
+	none)
+		;;
+	instance)
+		ipcrm_instance $*
+		;;
+	orauser)
+		ipcrm_orauser $*
+		;;
+	esac
+}
+
+oracle_getconfig() {
+	ora_common_getconfig "$OCF_RESKEY_sid" "$OCF_RESKEY_home" "$OCF_RESKEY_user" "$OCF_RESKEY_tns_admin"
+
+	clear_backupmode=${OCF_RESKEY_clear_backupmode:-"false"}
+	shutdown_method=${OCF_RESKEY_shutdown_method:-"checkpoint/abort"}
+	IPCRM=${OCF_RESKEY_ipcrm:-"instance"}
+}
+
+#
+# oracle_start: Start the Oracle instance
+#
+# NOTE: We handle instance in the MOUNTED and STARTED states
+# efficiently
+# We *do not* handle instance in the restricted or read-only
+# mode, i.e. it appears as running, but its availability is
+# "not for general use"
+#
+
+oracle_start() {
+	local status output
+	if is_proc_running; then
+		status="`monsql_one dbstat`"
+		case "$status" in
+		"OPEN")
+			: nothing to be done, we can leave right now
+			ocf_log info "Oracle instance $ORACLE_SID already running"
+			return $OCF_SUCCESS
+		;;
+		"STARTED")
+			output=`dbasql dbmount`
+		;;
+		"MOUNTED")
+			: we proceed if mounted
+		;;
+		*) # status unknown
+			output=`dbasql dbstop dbstart_mount`
+		;;
+		esac
+	else
+		output="`dbasql dbstart_mount`"
+		# try to cleanup in case of
+		# ORA-01081: cannot start already-running ORACLE - shut it down first
+		if echo "$output" | grep ORA-01081 >/dev/null 2>&1; then
+			ocf_log info "ORA-01081 error found, trying to cleanup oracle (dbstart_mount output: $output)"
+			ora_cleanup
+			output=`dbasql dbstart_mount`
+		fi
+	fi
+
+	# oracle instance should be mounted.
+	status="`dbasql_one dbstat`"
+	case "$status" in
+	"MOUNTED")
+		;;
+	*)
+		: error!!
+		ocf_log err "oracle $ORACLE_SID can not be mounted (status: $status)"
+		return $OCF_ERR_GENERIC
+		;;
+	esac
+
+	# It is examined whether mode is "online backup mode",
+	# and if it is true, makes clear the mode.
+	# Afterwards, DB is opened.
+	if is_clear_backupmode_set && is_instance_in_backup_mode; then
+		clear_backup_mode
+	fi
+	output=`dbasql dbopen`
+
+	# check/create the monitor user
+	if ! check_mon_user; then
+		return $OCF_ERR_GENERIC
+	fi
+
+	if ! is_proc_running; then
+		ocf_log err "oracle process not running: $output"
+		return $OCF_ERR_GENERIC
+	elif ! instance_live; then
+		ocf_log err "oracle instance $ORACLE_SID not started: $output"
+		return $OCF_ERR_GENERIC
+	else
+		: cool, we are up and running
+		ocf_log info "Oracle instance $ORACLE_SID started: $output"
+		return $OCF_SUCCESS
+	fi
+}
+
+#
+# oracle_stop: Stop the Oracle instance
+#
+oracle_stop() {
+	local status output ipc=""
+	if is_proc_running; then
+		[ "$IPCRM" = "instance" ] && ipc=$(parseipc `dumpinstipc`)
+		output=`dbasql dbstop`
+	else
+		ocf_log info "Oracle instance $ORACLE_SID already stopped"
+		return $OCF_SUCCESS
+	fi
+	ocf_stop_processes TERM $PROCS_CLEANUP_TIME `proc_pids`  # kill the procs if they hanged
+	if is_proc_running; then
+		ocf_log err "Oracle instance $ORACLE_SID not stopped: $output"
+		return $OCF_ERR_GENERIC
+	else
+		ocf_log info "Oracle instance $ORACLE_SID stopped: $output"
+		sleep 1  # give em a chance to cleanup
+		ocf_log info "Cleaning up for $ORACLE_SID"
+		ora_cleanup "$ipc"
+		return $OCF_SUCCESS
+	fi
+}
+
+#
+# oracle_monitor: Can the Oracle instance do anything useful?
+#
+oracle_monitor() {
+	if ! is_proc_running; then
+		ocf_log info "oracle process not running"
+		return $OCF_NOT_RUNNING
+	fi
+	if ! instance_live; then
+		ocf_log err "oracle instance $ORACLE_SID is down"
+		return $OCF_ERR_GENERIC
+	fi
+	#ocf_log info "Oracle instance $ORACLE_SID is alive"
+	return $OCF_SUCCESS
+}
+
+# other supported actions
+oracle_status() {
+	if is_proc_running
+	then
+	  echo Oracle instance $ORACLE_SID is running
+	  exit $OCF_SUCCESS
+	else
+	  echo Oracle instance $ORACLE_SID is stopped
+	  exit $OCF_NOT_RUNNING
+	fi
+}
+oracle_dumpinstipc() {
+	is_proc_running && parseipc `dumpinstipc`
+}
+oracle_showdbstat() {
+	showdbstat
+}
+oracle_cleanup() {
+	if [ "$IPCRM" = "instance" ]; then
+		ora_cleanup $(parseipc `dumpinstipc`)
+	else
+		ora_cleanup
+	fi
+}
+oracle_validate_all() {
+	case "${shutdown_method}" in
+	"immediate") ;;
+	"checkpoint/abort") ;;
+	*) ocf_log err "unsupported shutdown_method, please read meta-data"
+		return $OCF_ERR_CONFIGURED
+		;;
+	esac
+
+	case "${IPCRM}" in
+	"none"|"instance"|"orauser") ;;
+	*) ocf_log err "unsupported ipcrm setting, please read meta-data"
+		return $OCF_ERR_CONFIGURED
+		;;
+	esac
+
+	ora_common_validate_all
+}
+
+# used in ora-common.sh
+show_procs() {
+	ps -e -o pid,args | grep -i "[o]ra[a-zA-Z0-9_]*$ORACLE_SID$"
+}
+proc_pids() { show_procs | awk '{print $1}'; }
+PROCS_CLEANUP_TIME="30"
+
+MONUSR="OCFMON"
+OCF_REQUIRED_PARAMS="sid"
+OCF_REQUIRED_BINARIES="sqlplus"
+ocf_rarun $*
+
+#
+# vim:tabstop=4:shiftwidth=4:textwidth=0:wrapmargin=0
diff --git a/heartbeat/oralsnr b/heartbeat/oralsnr
new file mode 100755
index 0000000..98fb120
--- /dev/null
+++ b/heartbeat/oralsnr
@@ -0,0 +1,281 @@
+#!/bin/sh
+#
+# 
+# oralsnr
+#
+# Description:	Manages an Oracle Listener as a High-Availability
+#		resource
+#
+#
+# Author:	Dejan Muhamedagic
+# Support:	linux-ha at lists.linux-ha.org
+# License:	GNU General Public License (GPL)
+# Copyright:	(C) 2006 International Business Machines, Inc.
+#
+#		This code inspired by the DB2 resource script
+#		written by Alan Robertson
+#
+# An example usage in /etc/ha.d/haresources: 
+#       node1  10.0.0.170 oralsnr::sid::home::user::listener
+#
+# See oralsnr_usage() function below for more details...
+#
+# OCF instance parameters:
+#	OCF_RESKEY_sid (mandatory; for the monitor op)
+#	OCF_RESKEY_home (optional; else read it from /etc/oratab)
+#	OCF_RESKEY_user (optional; user to run the listener)
+#	OCF_RESKEY_listener (optional; defaults to LISTENER)
+#
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+. ${OCF_FUNCTIONS_DIR}/ora-common.sh
+
+#######################################################################
+
+SH=/bin/sh
+
+oralsnr_usage() {
+  methods=`oralsnr_methods`
+  methods=`echo $methods | tr ' ' '|'`
+  cat <<-!
+	usage: $0 ($methods)
+
+	$0 manages an Oracle Database instance as an HA resource.
+
+	The 'start' operation starts the database.
+	The 'stop' operation stops the database.
+	The 'status' operation reports whether the database is running
+	The 'monitor' operation reports whether the database seems to be working
+	The 'validate-all' operation reports whether the parameters are valid
+	The 'methods' operation reports on the methods $0 supports
+
+	!
+}
+
+oralsnr_meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="oralsnr">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for Oracle Listener. It manages an
+Oracle Listener instance as an HA resource.
+</longdesc>
+<shortdesc lang="en">Manages an Oracle TNS listener</shortdesc>
+
+<parameters>
+
+<parameter name="sid" unique="1" required="1">
+<longdesc lang="en">
+The Oracle SID (aka ORACLE_SID). Necessary for the monitor op,
+i.e. to do tnsping SID.
+</longdesc>
+<shortdesc lang="en">sid</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="home" unique="0">
+<longdesc lang="en">
+The Oracle home directory (aka ORACLE_HOME).
+If not specified, then the SID should be listed in /etc/oratab.
+</longdesc>
+<shortdesc lang="en">home</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="user" unique="0">
+<longdesc lang="en">
+Run the listener as this user.
+</longdesc>
+<shortdesc lang="en">user</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="listener" unique="1">
+<longdesc lang="en">
+Listener instance to be started (as defined in listener.ora).
+Defaults to LISTENER.
+</longdesc>
+<shortdesc lang="en">listener</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="tns_admin" required="0" unique="1">
+<longdesc lang="en">
+	Full path to the directory that contains the Oracle
+	listener tnsnames.ora configuration file.  The shell
+	variable TNS_ADMIN is set to the value provided.
+</longdesc>
+<shortdesc lang="en">
+	Full path to the directory containing tnsnames.ora
+</shortdesc>
+<content type="string"/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="120" />
+<action name="stop" timeout="120" />
+<action name="status" timeout="60" />
+<action name="monitor" depth="0" timeout="30" interval="10" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+<action name="methods" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+
+#
+# methods: What methods/operations do we support?
+#
+oralsnr_methods() {
+  cat <<-!
+	start
+	stop
+	status
+	monitor
+	validate-all
+	methods
+	meta-data
+	usage
+	!
+}
+
+#
+#	Run commands as the Oracle owner...
+#
+runasdba() {
+	if [ "$US" = "$ORACLE_OWNER" ]; then
+		$SH
+	else
+		(
+		echo ". $ORA_ENVF"
+		cat
+		) | su -s $SH - $ORACLE_OWNER
+	fi
+}
+
+#
+# oralsnr_start: Start the Oracle listener instance
+#
+
+oralsnr_start() {
+	if is_proc_running && test_tnsping; then
+		: nothing to be done, we can leave right now
+		ocf_log info "Listener $listener already running"
+		return $OCF_SUCCESS
+	fi
+	output=`echo lsnrctl start $listener | runasdba`
+	if test_tnsping; then
+		: cool, we are up and running
+		ocf_log info "Listener $listener running: $output"
+		return $OCF_SUCCESS
+	else
+		ocf_log err "Listener $listener appears to have started, but is not running properly: $output"
+		ocf_log err "Probable Oracle configuration error"
+		return $OCF_ERR_GENERIC
+	fi
+}
+
+#
+# oralsnr_stop: Stop the Oracle instance
+#
+oralsnr_stop() {
+	if is_proc_running; then
+		output=`echo lsnrctl stop $listener | runasdba`
+	else
+		ocf_log info "Listener $listener already stopped"
+		return $OCF_SUCCESS
+	fi
+	ocf_stop_processes TERM $PROCS_CLEANUP_TIME `proc_pids`  # kill the procs if they hanged
+	if is_proc_running; then
+		ocf_log err "Listener $listener not stopped: $output"
+		return $OCF_ERR_GENERIC
+	else
+		ocf_log info "Listener $listener stopped: $output"
+		return $OCF_SUCCESS
+	fi
+}
+
+#
+# is_proc_running: is the listener running?
+#
+is_proc_running() {
+	show_procs | grep "." > /dev/null
+}
+# the following two should be run only if the process is running
+test_listener() {
+	local output
+	output=`lsnrctl status $listener`
+	if echo "$output" | tail -1 | grep -qs 'completed successfully'
+	then
+		return $OCF_SUCCESS
+	else
+		ocf_log err "$listener status failed: $output"
+		return $OCF_ERR_GENERIC
+	fi
+}
+# and does it work?
+test_tnsping() {
+	local output
+	output=`tnsping $ORACLE_SID`
+	if echo "$output" | tail -1 | grep -qs '^OK'; then
+		return $OCF_SUCCESS
+	else
+		ocf_log err "tnsping $ORACLE_SID failed: $output"
+		return $OCF_ERR_GENERIC
+	fi
+}
+
+#
+# oralsnr_monitor: Can we connect to the listener?
+#
+oralsnr_monitor() {
+	if is_proc_running; then
+		test_listener && test_tnsping
+	else
+		return $OCF_NOT_RUNNING
+	fi
+}
+
+oralsnr_status() {
+	if is_proc_running
+	then
+	  echo Listener $listener is running
+	  exit $OCF_SUCCESS
+	else
+	  echo Listener $listener is stopped
+	  exit $OCF_NOT_RUNNING
+	fi
+}
+
+oralsnr_getconfig() {
+	ora_common_getconfig "$OCF_RESKEY_sid" "$OCF_RESKEY_home" "$OCF_RESKEY_user" "$OCF_RESKEY_tns_admin"
+	listener=${OCF_RESKEY_listener:-"LISTENER"}
+}
+
+oralsnr_validate_all() {
+	ora_common_validate_all
+}
+
+# used in ora-common.sh
+show_procs() {
+	ps -e -o pid,user,args |
+		grep '[t]nslsnr' | grep -w "$listener" | grep -w "$ORACLE_OWNER"
+}
+proc_pids() { show_procs | awk '{print $1}'; }
+PROCS_CLEANUP_TIME="10"
+
+OCF_REQUIRED_PARAMS="sid"
+OCF_REQUIRED_BINARIES="lsnrctl tnsping"
+ocf_rarun $*
+
+#
+# vim:tabstop=4:shiftwidth=4:textwidth=0:wrapmargin=0
diff --git a/heartbeat/pgsql b/heartbeat/pgsql
new file mode 100755
index 0000000..a462627
--- /dev/null
+++ b/heartbeat/pgsql
@@ -0,0 +1,1872 @@
+#!/bin/sh
+#
+# Description:  Manages a PostgreSQL Server as an OCF High-Availability
+#               resource
+#
+# Authors:      Serge Dubrouski (sergeyfd at gmail.com) -- original RA
+#               Florian Haas (florian at linbit.com) -- makeover
+#               Takatoshi MATSUO (matsuo.tak at gmail.com) -- support replication
+#               David Corlette (dcorlette at netiq.com) -- add support for non-standard library locations and non-standard port
+#
+# Copyright:    2006-2012 Serge Dubrouski <sergeyfd at gmail.com>
+#                         and other Linux-HA contributors
+# License:      GNU General Public License (GPL)
+#
+###############################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#
+# Get PostgreSQL Configuration parameter
+#
+get_pgsql_param() {
+    local param_name
+
+    param_name=$1
+    perl_code="if (/^\s*$param_name[\s=]+\s*(.*)$/) {
+       \$dir=\$1;
+       \$dir =~ s/\s*\#.*//;
+       \$dir =~ s/^'(\S*)'/\$1/;
+       print \$dir;}"
+
+    perl -ne "$perl_code" < $OCF_RESKEY_config
+}
+
+# Defaults
+OCF_RESKEY_pgctl_default=/usr/bin/pg_ctl
+OCF_RESKEY_psql_default=/usr/bin/psql
+OCF_RESKEY_pgdata_default=/var/lib/pgsql/data
+OCF_RESKEY_pgdba_default=postgres
+OCF_RESKEY_pghost_default=""
+OCF_RESKEY_pgport_default=5432
+OCF_RESKEY_pglibs_default=/usr/lib
+OCF_RESKEY_start_opt_default=""
+OCF_RESKEY_pgdb_default=template1
+OCF_RESKEY_logfile_default=/dev/null
+OCF_RESKEY_stop_escalate_default=30
+OCF_RESKEY_monitor_user_default=""
+OCF_RESKEY_monitor_password_default=""
+OCF_RESKEY_monitor_sql_default="select now();"
+OCF_RESKEY_check_wal_receiver_default="false"
+# Defaults for replication
+OCF_RESKEY_rep_mode_default=none
+OCF_RESKEY_node_list_default=""
+OCF_RESKEY_restore_command_default=""
+OCF_RESKEY_archive_cleanup_command_default=""
+OCF_RESKEY_recovery_end_command_default=""
+OCF_RESKEY_master_ip_default=""
+OCF_RESKEY_repuser_default="postgres"
+OCF_RESKEY_primary_conninfo_opt_default=""
+OCF_RESKEY_restart_on_promote_default="false"
+OCF_RESKEY_tmpdir_default="/var/lib/pgsql/tmp"
+OCF_RESKEY_xlog_check_count_default="3"
+OCF_RESKEY_crm_attr_timeout_default="5"
+OCF_RESKEY_stop_escalate_in_slave_default=30
+
+: ${OCF_RESKEY_pgctl=${OCF_RESKEY_pgctl_default}}
+: ${OCF_RESKEY_psql=${OCF_RESKEY_psql_default}}
+: ${OCF_RESKEY_pgdata=${OCF_RESKEY_pgdata_default}}
+: ${OCF_RESKEY_pgdba=${OCF_RESKEY_pgdba_default}}
+: ${OCF_RESKEY_pghost=${OCF_RESKEY_pghost_default}}
+: ${OCF_RESKEY_pgport=${OCF_RESKEY_pgport_default}}
+: ${OCF_RESKEY_pglibs=${OCF_RESKEY_pglibs_default}}
+: ${OCF_RESKEY_config=${OCF_RESKEY_pgdata}/postgresql.conf}
+: ${OCF_RESKEY_start_opt=${OCF_RESKEY_start_opt_default}}
+: ${OCF_RESKEY_pgdb=${OCF_RESKEY_pgdb_default}}
+: ${OCF_RESKEY_logfile=${OCF_RESKEY_logfile_default}}
+: ${OCF_RESKEY_stop_escalate=${OCF_RESKEY_stop_escalate_default}}
+: ${OCF_RESKEY_monitor_user=${OCF_RESKEY_monitor_user_default}}
+: ${OCF_RESKEY_monitor_password=${OCF_RESKEY_monitor_password_default}}
+: ${OCF_RESKEY_monitor_sql=${OCF_RESKEY_monitor_sql_default}}
+: ${OCF_RESKEY_check_wal_receiver=${OCF_RESKEY_check_wal_receiver_default}}
+
+# for replication
+: ${OCF_RESKEY_rep_mode=${OCF_RESKEY_rep_mode_default}}
+: ${OCF_RESKEY_node_list=${OCF_RESKEY_node_list_default}}
+: ${OCF_RESKEY_restore_command=${OCF_RESKEY_restore_command_default}}
+: ${OCF_RESKEY_archive_cleanup_command=${OCF_RESKEY_archive_cleanup_command_default}}
+: ${OCF_RESKEY_recovery_end_command=${OCF_RESKEY_recovery_end_command_default}}
+: ${OCF_RESKEY_master_ip=${OCF_RESKEY_master_ip_default}}
+: ${OCF_RESKEY_repuser=${OCF_RESKEY_repuser_default}}
+: ${OCF_RESKEY_primary_conninfo_opt=${OCF_RESKEY_primary_conninfo_opt_default}}
+: ${OCF_RESKEY_restart_on_promote=${OCF_RESKEY_restart_on_promote_default}}
+: ${OCF_RESKEY_tmpdir=${OCF_RESKEY_tmpdir_default}}
+: ${OCF_RESKEY_xlog_check_count=${OCF_RESKEY_xlog_check_count_default}}
+: ${OCF_RESKEY_crm_attr_timeout=${OCF_RESKEY_crm_attr_timeout_default}}
+: ${OCF_RESKEY_stop_escalate_in_slave=${OCF_RESKEY_stop_escalate_in_slave_default}}
+
+usage() {
+    cat <<EOF
+        usage: $0 start|stop|status|monitor|promote|demote|notify|meta-data|validate-all|methods
+
+        $0 manages a PostgreSQL Server as an HA resource.
+
+        The 'start' operation starts the PostgreSQL server.
+        The 'stop' operation stops the PostgreSQL server.
+        The 'status' operation reports whether the PostgreSQL is up.
+        The 'monitor' operation reports whether the PostgreSQL is running.
+        The 'promote' operation promotes the PostgreSQL server.
+        The 'demote' operation demotes the PostgreSQL server.
+        The 'validate-all' operation reports whether the parameters are valid.
+        The 'methods' operation reports on the methods $0 supports.
+EOF
+  return $OCF_ERR_ARGS
+}
+
+meta_data() {
+    cat <<EOF
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="pgsql">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for PostgreSQL. It manages a PostgreSQL as an HA resource.
+</longdesc>
+<shortdesc lang="en">Manages a PostgreSQL database instance</shortdesc>
+
+<parameters>
+<parameter name="pgctl" unique="0" required="0">
+<longdesc lang="en">
+Path to pg_ctl command.
+</longdesc>
+<shortdesc lang="en">pgctl</shortdesc>
+<content type="string" default="${OCF_RESKEY_pgctl_default}" />
+</parameter>
+
+<parameter name="start_opt" unique="0" required="0">
+<longdesc lang="en">
+Start options (-o start_opt in pg_ctl). "-i -p 5432" for example.
+</longdesc>
+<shortdesc lang="en">start_opt</shortdesc>
+<content type="string" default="${OCF_RESKEY_start_opt_default}" />
+
+</parameter>
+<parameter name="ctl_opt" unique="0" required="0">
+<longdesc lang="en">
+Additional pg_ctl options (-w, -W etc..).
+</longdesc>
+<shortdesc lang="en">ctl_opt</shortdesc>
+<content type="string" default="${OCF_RESKEY_ctl_opt_default}" />
+</parameter>
+
+<parameter name="psql" unique="0" required="0">
+<longdesc lang="en">
+Path to psql command.
+</longdesc>
+<shortdesc lang="en">psql</shortdesc>
+<content type="string" default="${OCF_RESKEY_psql_default}" />
+</parameter>
+
+<parameter name="pgdata" unique="0" required="0">
+<longdesc lang="en">
+Path to PostgreSQL data directory.
+</longdesc>
+<shortdesc lang="en">pgdata</shortdesc>
+<content type="string" default="${OCF_RESKEY_pgdata_default}" />
+</parameter>
+
+<parameter name="pgdba" unique="0" required="0">
+<longdesc lang="en">
+User that owns PostgreSQL.
+</longdesc>
+<shortdesc lang="en">pgdba</shortdesc>
+<content type="string" default="${OCF_RESKEY_pgdba_default}" />
+</parameter>
+
+<parameter name="pghost" unique="0" required="0">
+<longdesc lang="en">
+Hostname/IP address where PostgreSQL is listening
+</longdesc>
+<shortdesc lang="en">pghost</shortdesc>
+<content type="string" default="${OCF_RESKEY_pghost_default}" />
+</parameter>
+
+<parameter name="pgport" unique="0" required="0">
+<longdesc lang="en">
+Port where PostgreSQL is listening
+</longdesc>
+<shortdesc lang="en">pgport</shortdesc>
+<content type="integer" default="${OCF_RESKEY_pgport_default}" />
+</parameter>
+
+<parameter name="pglibs" unique="0" required="0">
+<longdesc lang="en">
+Custom location of the Postgres libraries. If not set, the standard location
+will be used.
+</longdesc>
+<shortdesc lang="en">pglibs</shortdesc>
+<content type="string" default="${OCF_RESKEY_pglibs_default}" />
+</parameter>
+
+<parameter name="monitor_user" unique="0" required="0">
+<longdesc lang="en">
+PostgreSQL user that pgsql RA will user for monitor operations. If it's not set
+pgdba user will be used.
+</longdesc>
+<shortdesc lang="en">monitor_user</shortdesc>
+<content type="string" default="${OCF_RESKEY_monitor_user_default}" />
+</parameter>
+
+<parameter name="monitor_password" unique="0" required="0">
+<longdesc lang="en">
+Password for monitor user.
+</longdesc>
+<shortdesc lang="en">monitor_password</shortdesc>
+<content type="string" default="${OCF_RESKEY_monitor_password_default}" />
+</parameter>
+
+<parameter name="monitor_sql" unique="0" required="0">
+<longdesc lang="en">
+SQL script that will be used for monitor operations.
+</longdesc>
+<shortdesc lang="en">monitor_sql</shortdesc>
+<content type="string" default="${OCF_RESKEY_monitor_sql_default}" />
+</parameter>
+
+<parameter name="config" unique="0" required="0">
+<longdesc lang="en">
+Path to the PostgreSQL configuration file for the instance.
+</longdesc>
+<shortdesc lang="en">Configuration file</shortdesc>
+<content type="string" default="${OCF_RESKEY_pgdata}/postgresql.conf" />
+</parameter>
+
+<parameter name="pgdb" unique="0" required="0">
+<longdesc lang="en">
+Database that will be used for monitoring.
+</longdesc>
+<shortdesc lang="en">pgdb</shortdesc>
+<content type="string" default="${OCF_RESKEY_pgdb_default}" />
+</parameter>
+
+<parameter name="logfile" unique="0" required="0">
+<longdesc lang="en">
+Path to PostgreSQL server log output file.
+</longdesc>
+<shortdesc lang="en">logfile</shortdesc>
+<content type="string" default="${OCF_RESKEY_logfile_default}" />
+</parameter>
+
+<parameter name="socketdir" unique="0" required="0">
+<longdesc lang="en">
+Unix socket directory for PostgreSQL
+</longdesc>
+<shortdesc lang="en">socketdir</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="stop_escalate" unique="0" required="0">
+<longdesc lang="en">
+Number of shutdown retries (using -m fast) before resorting to -m immediate
+</longdesc>
+<shortdesc lang="en">stop escalation</shortdesc>
+<content type="integer" default="${OCF_RESKEY_stop_escalate_default}" />
+</parameter>
+
+<parameter name="rep_mode" unique="0" required="0">
+<longdesc lang="en">
+Replication mode may be set to "async" or "sync" or "slave".
+They require PostgreSQL 9.1 or later.
+Once set, "async" and "sync" require node_list, master_ip, and
+restore_command parameters,as well as configuring PostgreSQL
+for replication (in postgresql.conf and pg_hba.conf).
+
+"slave" means that RA only makes recovery.conf before starting
+to connect to primary which is running somewhere.
+It dosen't need master/slave setting.
+It requires master_ip restore_command parameters.
+</longdesc>
+<shortdesc lang="en">rep_mode</shortdesc>
+<content type="string" default="${OCF_RESKEY_rep_mode_default}" />
+</parameter>
+
+<parameter name="node_list" unique="0" required="0">
+<longdesc lang="en">
+All node names. Please separate each node name with a space.
+This is required for replication.
+</longdesc>
+<shortdesc lang="en">node list</shortdesc>
+<content type="string" default="${OCF_RESKEY_node_list_default}" />
+</parameter>
+
+<parameter name="restore_command" unique="0" required="0">
+<longdesc lang="en">
+restore_command for recovery.conf.
+This is required for replication.
+</longdesc>
+<shortdesc lang="en">restore_command</shortdesc>
+<content type="string" default="${OCF_RESKEY_restore_command_default}" />
+</parameter>
+
+<parameter name="archive_cleanup_command" unique="0" required="0">
+<longdesc lang="en">
+archive_cleanup_command for recovery.conf.
+This is used for replication and is optional.
+</longdesc>
+<shortdesc lang="en">archive_cleanup_command</shortdesc>
+<content type="string" default="${OCF_RESKEY_archive_cleanup_command_default}" />
+</parameter>
+
+<parameter name="recovery_end_command" unique="0" required="0">
+<longdesc lang="en">
+recovery_end_command for recovery.conf.
+This is used for replication and is optional.
+</longdesc>
+<shortdesc lang="en">recovery_end_command</shortdesc>
+<content type="string" default="${OCF_RESKEY_recovery_end_command_default}" />
+</parameter>
+
+<parameter name="master_ip" unique="0" required="0">
+<longdesc lang="en">
+Master's floating IP address to be connected from hot standby.
+This parameter is used for "primary_conninfo" in recovery.conf.
+This is required for replication.
+</longdesc>
+<shortdesc lang="en">master ip</shortdesc>
+<content type="string" default="${OCF_RESKEY_master_ip_default}" />
+</parameter>
+
+<parameter name="repuser" unique="0" required="0">
+<longdesc lang="en">
+User used to connect to the master server.
+This parameter is used for "primary_conninfo" in recovery.conf.
+This is required for replication.
+</longdesc>
+<shortdesc lang="en">repuser</shortdesc>
+<content type="string" default="${OCF_RESKEY_repuser_default}" />
+</parameter>
+
+<parameter name="primary_conninfo_opt" unique="0" required="0">
+<longdesc lang="en">
+primary_conninfo options of recovery.conf except host, port, user and application_name.
+This is optional for replication.
+</longdesc>
+<shortdesc lang="en">primary_conninfo_opt</shortdesc>
+<content type="string" default="${OCF_RESKEY_primary_conninfo_opt_default}" />
+</parameter>
+
+<parameter name="restart_on_promote" unique="0" required="0">
+<longdesc lang="en">
+If this is true, RA deletes recovery.conf and restarts PostgreSQL
+on promote to keep Timeline ID. It probably makes fail-over slower.
+It's recommended to set on-fail of promote up as fence.
+This is optional for replication.
+</longdesc>
+<shortdesc lang="en">restart_on_promote</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_restart_on_promote_default}" />
+</parameter>
+
+<parameter name="tmpdir" unique="0" required="0">
+<longdesc lang="en">
+Path to temporary directory.
+This is optional for replication.
+</longdesc>
+<shortdesc lang="en">tmpdir</shortdesc>
+<content type="string" default="${OCF_RESKEY_tmpdir_default}" />
+</parameter>
+
+<parameter name="xlog_check_count" unique="0" required="0">
+<longdesc lang="en">
+Number of checks of xlog on monitor before promote.
+This is optional for replication.
+</longdesc>
+<shortdesc lang="en">xlog check count</shortdesc>
+<content type="integer" default="${OCF_RESKEY_check_count_default}" />
+</parameter>
+
+<parameter name="crm_attr_timeout" unique="0" required="0">
+<longdesc lang="en">
+The timeout of crm_attribute forever update command.
+Default value is 5 seconds.
+This is optional for replication.
+</longdesc>
+<shortdesc lang="en">The timeout of crm_attribute forever update command.</shortdesc>
+<content type="integer" default="${OCF_RESKEY_crm_attr_timeout_default}" />
+</parameter>
+
+<parameter name="stop_escalate_in_slave" unique="0" required="0">
+<longdesc lang="en">
+Number of shutdown retries (using -m fast) before resorting to -m immediate
+in slave state.
+This is optional for replication.
+</longdesc>
+<shortdesc lang="en">stop escalation_in_slave</shortdesc>
+<content type="integer" default="${OCF_RESKEY_stop_escalate_in_slave_default}" />
+</parameter>
+
+<parameter name="check_wal_receiver" unique="0" required="0">
+<longdesc lang="en">
+If this is true, RA checks wal_receiver process on monitor
+and notifies its status using "(resource name)-receiver-status" attribute.
+It's useful for checking whether PostgreSQL (hot standby) connects to primary.
+The attribute shows status as "normal" or "ERROR".
+</longdesc>
+<shortdesc lang="en">check_wal_receiver</shortdesc>
+<content type="boolean" default="${OCF_RESKEY_check_wal_receiver_default}" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="120" />
+<action name="stop" timeout="120" />
+<action name="status" timeout="60" />
+<action name="monitor" depth="0" timeout="30" interval="30"/>
+<action name="monitor" depth="0" timeout="30" interval="29" role="Master" />
+<action name="promote" timeout="120" />
+<action name="demote" timeout="120" />
+<action name="notify"   timeout="90" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+<action name="methods" timeout="5" />
+</actions>
+</resource-agent>
+EOF
+}
+
+
+#
+#   Run the given command in the Resource owner environment...
+#
+runasowner() {
+    local quietrun=""
+    local loglevel="-err"
+    local var
+
+    for var in 1 2
+    do
+        case "$1" in
+            "-q")
+                quietrun="-q"
+                shift 1;;
+            "warn"|"err")
+                loglevel="-$1"
+                shift 1;;
+            *)
+                ;;
+        esac
+    done
+
+    ocf_run $quietrun $loglevel su $OCF_RESKEY_pgdba -c "cd $OCF_RESKEY_pgdata; $*"
+}
+
+#
+#       Shell escape
+#
+escape_string() {
+    echo "$*" | sed -e "s/'/'\\\\''/g"
+}
+
+
+#
+# methods: What methods/operations do we support?
+#
+
+pgsql_methods() {
+    cat <<EOF
+    start
+    stop
+    status
+    monitor
+    promote
+    demote
+    notify
+    methods
+    meta-data
+    validate-all
+EOF
+}
+
+
+#pgsql_real_start: Starts PostgreSQL
+pgsql_real_start() {
+    local pgctl_options
+    local postgres_options
+    local rc
+
+    if pgsql_status; then
+        ocf_log info "PostgreSQL is already running. PID=`cat $PIDFILE`"
+        if is_replication; then
+            return $OCF_ERR_GENERIC
+        else
+            return $OCF_SUCCESS
+        fi
+    fi
+
+    # Remove postmaster.pid if it exists
+    rm -f $PIDFILE
+
+    # Remove backup_label if it exists
+    if [ -f $BACKUPLABEL ] && ! is_replication; then
+        ocf_log info "Removing $BACKUPLABEL. The previous backup might have failed."
+        rm -f $BACKUPLABEL
+    fi
+
+    # Check if we need to create a log file
+    if ! check_log_file $OCF_RESKEY_logfile
+    then
+        ocf_log err "PostgreSQL can't write to the log file: $OCF_RESKEY_logfile"
+        return $OCF_ERR_PERM
+    fi
+
+    # Check socket directory
+    if [ -n "$OCF_RESKEY_socketdir" ]
+    then
+        check_socket_dir
+    fi
+
+    if [ "$OCF_RESKEY_rep_mode" = "slave" ]; then
+        rm -f $RECOVERY_CONF
+        make_recovery_conf || return $OCF_ERR_GENERIC
+    fi
+
+    # Set options passed to pg_ctl
+    pgctl_options="$OCF_RESKEY_ctl_opt -D $OCF_RESKEY_pgdata -l $OCF_RESKEY_logfile"
+
+    # Set options passed to the PostgreSQL server process
+    postgres_options="-c config_file=${OCF_RESKEY_config}"
+
+    if [ -n "$OCF_RESKEY_pghost" ]; then
+        postgres_options="$postgres_options -h $OCF_RESKEY_pghost"
+    fi
+    if [ -n "$OCF_RESKEY_start_opt" ]; then
+        postgres_options="$postgres_options $OCF_RESKEY_start_opt"
+    fi
+
+    # Tack pass-through options onto pg_ctl options
+    pgctl_options="$pgctl_options -o '$postgres_options'"
+
+    # Invoke pg_ctl
+    runasowner "unset PGUSER; unset PGPASSWORD; $OCF_RESKEY_pgctl $pgctl_options start"
+
+    if [ $? -eq 0 ]; then
+        # Probably started.....
+        ocf_log info "PostgreSQL start command sent."
+    else
+        ocf_log err "Can't start PostgreSQL."
+        return $OCF_ERR_GENERIC
+    fi
+
+    while :
+    do
+        pgsql_real_monitor warn
+        rc=$?
+        if [ $rc -eq $OCF_SUCCESS -o $rc -eq $OCF_RUNNING_MASTER ]; then
+            break;
+        fi
+        sleep 1
+        ocf_log debug "PostgreSQL still hasn't started yet. Waiting..."
+    done
+
+    ocf_log info "PostgreSQL is started."
+    return $rc
+}
+
+pgsql_replication_start() {
+    local rc
+
+    # initializing for replication
+    change_pgsql_status "$NODENAME" "STOP"
+    delete_master_baseline
+    exec_with_retry 0 $CRM_MASTER -v $CAN_NOT_PROMOTE
+    rm -f ${XLOG_NOTE_FILE}.* $REP_MODE_CONF $RECOVERY_CONF
+    if ! make_recovery_conf || ! delete_xlog_location || ! set_async_mode_all; then
+        return $OCF_ERR_GENERIC
+    fi
+
+    if [ -f $PGSQL_LOCK ]; then
+        ocf_log err "My data may be inconsistent. You have to remove $PGSQL_LOCK file to force start."
+        return $OCF_ERR_GENERIC
+    fi
+
+    # start
+    pgsql_real_start
+    if [ $? -ne $OCF_SUCCESS ]; then
+        return $OCF_ERR_GENERIC
+    fi
+    change_pgsql_status "$NODENAME" "HS:alone"
+    return $OCF_SUCCESS
+}
+
+#pgsql_start: pgsql_real_start() wrapper for replication
+pgsql_start() {
+    if ! is_replication; then
+        pgsql_real_start
+        return $?
+    else
+        pgsql_replication_start
+        return $?
+    fi
+}
+
+#pgsql_promote: Promote PostgreSQL
+pgsql_promote() {
+    local target
+    local rc
+
+    if ! is_replication; then
+        ocf_log err "Not in a replication mode."
+        return $OCF_ERR_CONFIGURED
+    fi
+    rm -f ${XLOG_NOTE_FILE}.*
+
+    for target in $NODE_LIST; do
+        [ "$target" = "$NODENAME" ] && continue
+        change_data_status "$target" "DISCONNECT"
+        change_master_score "$target" "$CAN_NOT_PROMOTE"
+    done
+
+    ocf_log info "Creating $PGSQL_LOCK."
+    touch $PGSQL_LOCK
+    show_master_baseline
+
+    if ocf_is_true ${OCF_RESKEY_restart_on_promote}; then
+        ocf_log info "Restarting PostgreSQL instead of promote."
+        #stop : this function returns $OCF_SUCCESS only.
+        pgsql_real_stop slave
+        rm -f $RECOVERY_CONF
+        pgsql_real_start
+        rc=$?
+        if [ $rc -ne $OCF_RUNNING_MASTER ]; then
+            ocf_log err "Can't start PostgreSQL as primary on promote."
+            if [ $rc -ne $OCF_SUCCESS ]; then
+                change_pgsql_status "$NODENAME" "STOP"
+            fi
+            return $OCF_ERR_GENERIC
+        fi
+    else
+        runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata promote"
+        if [ $? -eq 0 ]; then
+            ocf_log info "PostgreSQL promote command sent."
+        else
+            ocf_log err "Can't promote PostgreSQL."
+            return $OCF_ERR_GENERIC
+        fi
+
+        while :
+        do
+            pgsql_real_monitor warn
+            rc=$?
+            if [ $rc -eq $OCF_RUNNING_MASTER ]; then
+                break;
+            elif [ $rc -eq $OCF_ERR_GENERIC ]; then
+                ocf_log err "Can't promote PostgreSQL."
+                return $rc
+            fi
+            sleep 1
+            ocf_log debug "PostgreSQL still hasn't promoted yet. Waiting..."
+        done
+        ocf_log info "PostgreSQL is promoted."
+    fi
+
+    change_data_status "$NODENAME" "LATEST"
+    exec_with_retry 0 $CRM_MASTER -v $PROMOTE_ME
+    change_pgsql_status "$NODENAME" "PRI"
+    return $OCF_SUCCESS
+}
+
+#pgsql_demote: Demote PostgreSQL
+pgsql_demote() {
+    local rc
+
+    if ! is_replication; then
+        ocf_log err "Not in a replication mode."
+        return $OCF_ERR_CONFIGURED
+    fi
+
+    exec_with_retry 0 $CRM_MASTER -v $CAN_NOT_PROMOTE
+    delete_master_baseline
+
+    if ! pgsql_status; then
+        ocf_log info "PostgreSQL is already stopped on demote."
+    else
+        ocf_log info "Stopping PostgreSQL on demote."
+        pgsql_real_stop master
+        rc=$?
+        if [ "$rc" -ne "$OCF_SUCCESS" ]; then
+            change_pgsql_status "$NODENAME" "UNKNOWN"
+            return $rc
+        fi
+    fi
+    change_pgsql_status "$NODENAME" "STOP"
+    return $OCF_SUCCESS
+}
+
+#pgsql_real_stop: Stop PostgreSQL
+pgsql_real_stop() {
+    local rc
+    local count
+    local stop_escalate
+
+    if ocf_is_true ${OCF_RESKEY_check_wal_receiver}; then
+        attrd_updater -n "$PGSQL_WAL_RECEIVER_STATUS_ATTR" -D -q
+    fi
+
+    if ! pgsql_status
+    then
+        #Already stopped
+        return $OCF_SUCCESS
+    fi
+
+    stop_escalate=$OCF_RESKEY_stop_escalate
+    if [ "$1" = "slave" ]; then
+        stop_escalate="$OCF_RESKEY_stop_escalate_in_slave"
+    fi
+
+    # Stop PostgreSQL, do not wait for clients to disconnect
+    if [ $stop_escalate -gt 0 ]; then
+            runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata stop -m fast"
+    fi
+
+    # stop waiting
+    count=0
+    while [ $count -lt $stop_escalate ]
+    do
+        if ! pgsql_status
+        then
+            #PostgreSQL stopped
+            break;
+        fi
+        count=`expr $count + 1`
+        sleep 1
+    done
+
+    if pgsql_status
+    then
+        #PostgreSQL is still up. Use another shutdown mode.
+        ocf_log info "PostgreSQL failed to stop after ${OCF_RESKEY_stop_escalate}s using -m fast. Trying -m immediate..."
+        runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata stop -m immediate"
+    fi
+
+    while :
+    do
+        pgsql_real_monitor
+        rc=$?
+        if [ $rc -eq $OCF_NOT_RUNNING ]; then
+            # An unnecessary debug log is prevented.
+            break;
+        fi
+        sleep 1
+        ocf_log debug "PostgreSQL still hasn't stopped yet. Waiting..."
+    done
+
+    # Remove postmaster.pid if it exists
+    rm -f $PIDFILE
+
+    if  [ "$1" = "master" -a "$OCF_RESKEY_CRM_meta_notify_slave_uname" = " " ]; then
+        ocf_log info "Removing $PGSQL_LOCK."
+        rm -f $PGSQL_LOCK
+    fi
+    return $OCF_SUCCESS
+}
+
+pgsql_replication_stop() {
+    local rc
+
+    exec_with_retry 5 $CRM_MASTER -v $CAN_NOT_PROMOTE
+    delete_xlog_location
+
+    if ! pgsql_status
+    then
+        ocf_log info "PostgreSQL is already stopped."
+        change_pgsql_status "$NODENAME" "STOP"
+        return $OCF_SUCCESS
+    fi
+
+    pgsql_real_stop slave
+    rc=$?
+    if [ $rc -ne $OCF_SUCCESS ]; then
+        change_pgsql_status "$NODENAME" "UNKNOWN"
+        return $rc
+    fi
+
+    change_pgsql_status "$NODENAME" "STOP"
+    set_async_mode_all
+    delete_master_baseline
+    return $OCF_SUCCESS
+}
+
+#pgsql_stop: pgsql_real_stop() wrapper for replication
+pgsql_stop() {
+    if ! is_replication; then
+        pgsql_real_stop
+        return $?
+    else
+        pgsql_replication_stop
+        return $?
+    fi
+}
+
+#
+# pgsql_status: is PostgreSQL up?
+#
+
+pgsql_status() {
+     if [ -f $PIDFILE ]
+     then
+         PID=`head -n 1 $PIDFILE`
+         runasowner "kill -s 0 $PID >/dev/null 2>&1"
+         return $?
+     fi
+
+     # No PID file
+     false
+}
+
+pgsql_wal_receiver_status() {
+    local PID
+    local receiver_parent_pids
+
+    PID=`head -n 1 $PIDFILE`
+    receiver_parent_pids=`ps -ef | tr -s " " | grep "[w]al receiver process" | cut -d " " -f 3`
+    if echo "$receiver_parent_pids" | grep -q -w "$PID" ; then
+        attrd_updater -n "$PGSQL_WAL_RECEIVER_STATUS_ATTR" -v "normal" -q
+        return 0
+    fi
+    attrd_updater -n "$PGSQL_WAL_RECEIVER_STATUS_ATTR" -v "ERROR" -q
+    ocf_log warn "wal receiver process is not running"
+    return 1
+}
+
+#
+# pgsql_real_monitor
+#
+
+pgsql_real_monitor() {
+    local loglevel
+    local rc
+    local output
+
+    # Set the log level of the error message
+    loglevel=${1:-err}
+
+    if ! pgsql_status
+    then
+        ocf_log info "PostgreSQL is down"
+        return $OCF_NOT_RUNNING
+    fi
+
+    if ocf_is_true ${OCF_RESKEY_check_wal_receiver}; then
+        pgsql_wal_receiver_status
+    fi
+
+    if is_replication; then
+        #Check replication state
+        output=`su $OCF_RESKEY_pgdba -c "cd $OCF_RESKEY_pgdata; \
+                $OCF_RESKEY_psql $psql_options -U $OCF_RESKEY_pgdba \
+                -Atc \"${CHECK_MS_SQL}\""`
+        rc=$?
+        if [ $rc -ne  0 ]; then
+            report_psql_error $rc $loglevel "Can't get PostgreSQL recovery status."
+            return $OCF_ERR_GENERIC
+        fi
+
+        case "$output" in
+            f)  ocf_log debug "PostgreSQL is running as a primary."
+                if [ "$OCF_RESKEY_monitor_sql" = "$OCF_RESKEY_monitor_sql_default" ]; then
+                    return $OCF_RUNNING_MASTER
+                fi
+                ;;
+
+            t)  ocf_log debug "PostgreSQL is running as a hot standby."
+                return $OCF_SUCCESS;;
+
+            *)  ocf_log err "$CHECK_MS_SQL output is $output"
+                return $OCF_ERR_GENERIC;;
+        esac
+    fi
+
+    OCF_RESKEY_monitor_sql=`escape_string "$OCF_RESKEY_monitor_sql"`
+    runasowner -q $loglevel "$OCF_RESKEY_psql $psql_options \
+                  -c '$OCF_RESKEY_monitor_sql'"
+    rc=$?
+    if [ $rc -ne  0 ]; then
+        report_psql_error $rc $loglevel "PostgreSQL $OCF_RESKEY_pgdb isn't running."
+        return $OCF_ERR_GENERIC
+    fi
+
+    if is_replication; then
+        return $OCF_RUNNING_MASTER
+    fi
+    return $OCF_SUCCESS
+}
+
+pgsql_replication_monitor() {
+    local rc
+
+    rc=$1
+    if [ $rc -ne $OCF_SUCCESS -a $rc -ne "$OCF_RUNNING_MASTER" ]; then
+        return $rc
+    fi
+    # If I am Master
+    if [ $rc -eq $OCF_RUNNING_MASTER ]; then
+        change_data_status "$NODENAME" "LATEST"
+        change_pgsql_status "$NODENAME" "PRI"
+        control_slave_status || return $OCF_ERR_GENERIC
+        if [ "$RE_CONTROL_SLAVE" = "true" ]; then
+            sleep 2
+            ocf_log info "re-controlling slave status."
+            RE_CONTROL_SLAVE="none"
+            control_slave_status || return $OCF_ERR_GENERIC
+        fi
+        return $rc
+    fi
+
+    # I can't get master node name from $OCF_RESKEY_CRM_meta_notify_master_uname on monitor,
+    # so I will get master node name using crm_mon -n
+    print_crm_mon | tr -d "\t" | tr -d " " | grep -q "^${RESOURCE_NAME}[(:].*[):]Master"
+    if [ $? -ne 0 ] ; then
+        # If I am Slave and Master is not exist
+        ocf_log info "Master does not exist."
+        change_pgsql_status "$NODENAME" "HS:alone"
+        have_master_right
+        if [ $? -eq 0 ]; then
+            rm -f ${XLOG_NOTE_FILE}.*
+        fi
+    else
+        output=`exec_with_retry 0 $CRM_ATTR_FOREVER -N "$NODENAME" \
+                -n "$PGSQL_DATA_STATUS_ATTR" -G -q`
+        if [ "$output" = "DISCONNECT" ]; then
+            change_pgsql_status "$NODENAME" "HS:alone"
+        fi
+    fi
+    return $rc
+}
+
+#pgsql_monitor: pgsql_real_monitor() wrapper for replication
+pgsql_monitor() {
+    local rc
+
+    pgsql_real_monitor
+    rc=$?
+    if ! is_replication; then
+        return $rc
+    else
+        pgsql_replication_monitor $rc
+        return $?
+    fi
+}
+
+# pgsql_post_demote
+pgsql_post_demote() {
+    DEMOTE_NODE=`echo $OCF_RESKEY_CRM_meta_notify_demote_uname | sed "s/ /\n/g" | head -1 | tr '[A-Z]' '[a-z]'`
+    ocf_log debug "post-demote called. Demote uname is $DEMOTE_NODE"
+    if [ "$DEMOTE_NODE" != "$NODENAME" ]; then
+        if ! echo $OCF_RESKEY_CRM_meta_notify_master_uname | tr '[A-Z]' '[a-z]' | grep $NODENAME; then
+            show_master_baseline
+            change_pgsql_status "$NODENAME" "HS:alone"
+        fi
+    fi
+    return $OCF_SUCCESS
+}
+
+pgsql_pre_promote() {
+    local master_baseline
+    local my_master_baseline
+    local cmp_location
+    local number_of_nodes
+
+    # If my data is newer than new master's one, I fail my resource.
+    PROMOTE_NODE=`echo $OCF_RESKEY_CRM_meta_notify_promote_uname | \
+                  sed "s/ /\n/g" | head -1 | tr '[A-Z]' '[a-z]'`
+    number_of_nodes=`echo $NODE_LIST | wc -w`
+    if [ $number_of_nodes -ge 3 -a \
+         "$OCF_RESKEY_rep_mode" = "sync" -a \
+         "$PROMOTE_NODE" != "$NODENAME" ]; then
+        master_baseline=`$CRM_ATTR_REBOOT -N "$PROMOTE_NODE" -n \
+                         "$PGSQL_MASTER_BASELINE" -G -q 2>/dev/null`
+        if [ $? -eq 0 ]; then
+            my_master_baseline=`$CRM_ATTR_REBOOT -N "$NODENAME" -n \
+                                "$PGSQL_MASTER_BASELINE" -G -q 2>/dev/null`
+            # get older location
+            cmp_location=`printf "$master_baseline\n$my_master_baseline\n" |\
+                          sort | head -1`
+            if [ "$cmp_location" != "$my_master_baseline" ]; then
+                ocf_log err "My data is newer than new master's one. New master's location : $master_baseline"
+                exec_with_retry 0 $CRM_FAILCOUNT -r $OCF_RESOURCE_INSTANCE -U $NODENAME -v INFINITY
+                return $OCF_ERR_GENERIC
+            fi
+        fi
+    fi
+    return $OCF_SUCCESS
+}
+
+pgsql_notify() {
+    local type="${OCF_RESKEY_CRM_meta_notify_type}"
+    local op="${OCF_RESKEY_CRM_meta_notify_operation}"
+    local rc
+
+    if ! is_replication; then
+        return $OCF_SUCCESS
+    fi
+
+    ocf_log debug "notify: ${type} for ${op}"
+    case $type in
+        pre)
+            case $op in
+                promote)
+                    pgsql_pre_promote
+                    return $?
+                    ;;
+            esac
+            ;;
+        post)
+            case $op in
+                promote)
+                    delete_xlog_location
+                    PROMOTE_NODE=`echo $OCF_RESKEY_CRM_meta_notify_promote_uname | \
+                                  sed "s/ /\n/g" | head -1 | tr '[A-Z]' '[a-z]'`
+                    if [ "$PROMOTE_NODE" != "$NODENAME" ]; then
+                        delete_master_baseline
+                    fi
+                    return $OCF_SUCCESS
+                    ;;
+                demote)
+                    pgsql_post_demote
+                    return $?
+                    ;;
+                start|stop)
+                    MASTER_NODE=`echo $OCF_RESKEY_CRM_meta_notify_master_uname | \
+                                  sed "s/ /\n/g" | head -1 | tr '[A-Z]' '[a-z]'`
+                    if [ "$NODENAME" = "$MASTER_NODE" ]; then
+                        control_slave_status
+                    fi
+                    return $OCF_SUCCESS
+                    ;;
+            esac
+            ;;
+    esac
+    return $OCF_SUCCESS
+}
+
+control_slave_status() {
+    local rc
+    local data_status
+    local target
+    local all_data_status
+    local tmp_data_status
+    local number_of_nodes
+
+    all_data_status=`su $OCF_RESKEY_pgdba -c "cd $OCF_RESKEY_pgdata; \
+                     $OCF_RESKEY_psql $psql_options -U $OCF_RESKEY_pgdba \
+                     -Atc \"${CHECK_REPLICATION_STATE_SQL}\""`
+    rc=$?
+    if [ $rc -eq 0 ]; then
+        if [ -n "$all_data_status" ]; then
+            all_data_status=`echo $all_data_status | sed "s/\n/ /g"`
+        fi
+    else
+        report_psql_error $rc err "Can't get PostgreSQL replication status."
+        return 1
+    fi
+
+    number_of_nodes=`echo $NODE_LIST | wc -w`
+    for target in $NODE_LIST; do
+        if [ "$target" = "$NODENAME" ]; then
+            continue
+        fi
+
+        data_status="DISCONNECT"
+        if [ -n "$all_data_status" ]; then
+            for tmp_data_status in $all_data_status; do
+                if ! echo $tmp_data_status | grep -q "^${target}|"; then
+                    continue
+                fi
+                data_status=`echo $tmp_data_status | cut -d "|" -f 2,3`
+                ocf_log debug "node_name and data_status is $tmp_data_status"
+                break
+            done
+        fi
+
+        case "$data_status" in
+            "STREAMING|SYNC")
+                change_data_status "$target" "$data_status"
+                change_master_score "$target" "$CAN_PROMOTE"
+                change_pgsql_status "$target" "HS:sync"
+                ;;
+            "STREAMING|ASYNC")
+                change_data_status "$target" "$data_status"
+                if [ "$OCF_RESKEY_rep_mode" = "sync" ]; then
+                    change_master_score "$target" "$CAN_NOT_PROMOTE"
+                    set_sync_mode "$target"
+                else
+                    if [ $number_of_nodes -le 2 ]; then
+                        change_master_score "$target" "$CAN_PROMOTE"
+                    else
+                        # I can't determine which slave's data is newest in async mode.
+                        change_master_score "$target" "$CAN_NOT_PROMOTE"
+                    fi
+                fi
+                change_pgsql_status "$target" "HS:async"
+                ;;
+            "STREAMING|POTENTIAL")
+                change_data_status "$target" "$data_status"
+                change_master_score "$target" "$CAN_NOT_PROMOTE"
+                change_pgsql_status "$target" "HS:potential"
+                ;;
+            "DISCONNECT")
+                change_data_status "$target" "$data_status"
+                change_master_score "$target" "$CAN_NOT_PROMOTE"
+                if [ "$OCF_RESKEY_rep_mode" = "sync" ]; then
+                    set_async_mode "$target"
+                fi
+                ;;
+            *)
+                change_data_status "$target" "$data_status"
+                change_master_score "$target" "$CAN_NOT_PROMOTE"
+                if [ "$OCF_RESKEY_rep_mode" = "sync" ]; then
+                    set_async_mode "$target"
+                fi
+                change_pgsql_status "$target" "HS:connected"
+                ;;
+        esac
+    done
+    return 0
+}
+
+have_master_right() {
+    local old
+    local new
+    local output
+    local data_status
+    local node
+    local mylocation
+    local count
+    local newestXlog
+    local oldfile
+    local newfile
+
+    ocf_log debug "Checking if I have a master right."
+
+    data_status=`$CRM_ATTR_FOREVER -N "$NODENAME" -n \
+                 "$PGSQL_DATA_STATUS_ATTR" -G -q 2>/dev/null`
+    if [ "$OCF_RESKEY_rep_mode" = "sync" ]; then
+        if [ -n "$data_status" -a "$data_status" != "STREAMING|SYNC" -a \
+             "$data_status" != "LATEST" ]; then
+            ocf_log warn "My data is out-of-date. status=$data_status"
+            return 1
+        fi
+    else
+        if [ -n "$data_status" -a "$data_status" != "STREAMING|SYNC" -a \
+             "$data_status" != "STREAMING|ASYNC" -a \
+             "$data_status" != "LATEST" ]; then
+            ocf_log warn "My data is out-of-date. status=$data_status"
+            return 1
+        fi
+    fi
+    ocf_log info "My data status=$data_status."
+
+    show_xlog_location
+    if [ $? -ne 0 ]; then
+        ocf_log err "Failed to show my xlog location."
+        exit $OCF_ERR_GENERIC
+    fi
+
+    old=0
+    for count in `seq $OCF_RESKEY_xlog_check_count`; do
+       if [ -f ${XLOG_NOTE_FILE}.$count ]; then
+           old=$count
+           continue
+       fi
+       break
+    done
+    new=`expr $old + 1`
+
+    # get xlog locations of all nodes
+    for node in ${NODE_LIST}; do
+        output=`$CRM_ATTR_REBOOT -N "$node" -n \
+                "$PGSQL_XLOG_LOC_NAME" -G -q 2>/dev/null`
+        if [ $? -ne 0 ]; then
+            ocf_log warn "Can't get $node xlog location."
+            continue
+        else
+            ocf_log info "$node xlog location : $output"
+            echo "$node $output" >> ${XLOG_NOTE_FILE}.${new}
+            if [ "$node" = "$NODENAME" ]; then
+                mylocation=$output
+            fi
+        fi
+    done
+
+    oldfile=`cat ${XLOG_NOTE_FILE}.${old} 2>/dev/null`
+    newfile=`cat ${XLOG_NOTE_FILE}.${new} 2>/dev/null`
+    if [ "$oldfile" != "$newfile" ]; then
+        # reset counter
+        rm -f ${XLOG_NOTE_FILE}.*
+        printf "$newfile\n" > ${XLOG_NOTE_FILE}.0
+        return 1
+    fi
+
+    if [ "$new" -ge "$OCF_RESKEY_xlog_check_count" ]; then
+        newestXlog=`printf "$newfile\n" | sort -t " " -k 2,3 -r | \
+                    head -1 | cut -d " " -f 2`
+        if [ "$newestXlog" = "$mylocation" ]; then
+            ocf_log info "I have a master right."
+            exec_with_retry 5 $CRM_MASTER -v $PROMOTE_ME
+            return 0
+        fi
+        change_data_status "$NODENAME" "DISCONNECT"
+        ocf_log info "I don't have correct master data."
+        # reset counter
+        rm -f ${XLOG_NOTE_FILE}.*
+        printf "$newfile\n" > ${XLOG_NOTE_FILE}.0
+    fi
+
+    return 1
+}
+
+is_replication() {
+    if [ "$OCF_RESKEY_rep_mode" != "none" -a "$OCF_RESKEY_rep_mode" != "slave" ]; then
+        return 0
+    fi
+    return 1
+}
+
+get_my_location() {
+    local rc
+    local output
+    local replay_loc
+    local receive_loc
+    local output1
+    local output2
+    local log1
+    local log2
+    local newer_location
+
+    output=`su $OCF_RESKEY_pgdba -c "cd $OCF_RESKEY_pgdata; \
+            $OCF_RESKEY_psql $psql_options -U $OCF_RESKEY_pgdba \
+            -Atc \"${CHECK_XLOG_LOC_SQL}\""`
+    rc=$?
+    if [ $rc -ne 0 ]; then
+        report_psql_error $rc err "Can't get my xlog location."
+        return 1
+    fi
+    replay_loc=`echo $output | cut -d "|" -f 1`
+    receive_loc=`echo $output | cut -d "|" -f 2`
+
+    output1=`echo "$replay_loc" | cut -d "/" -f 1`
+    output2=`echo "$replay_loc" | cut -d "/" -f 2`
+    log1=`printf "%08s\n" $output1 | sed "s/ /0/g"`
+    log2=`printf "%08s\n" $output2 | sed "s/ /0/g"`
+    replay_loc="${log1}${log2}"
+
+    output1=`echo "$receive_loc" | cut -d "/" -f 1`
+    output2=`echo "$receive_loc" | cut -d "/" -f 2`
+    log1=`printf "%08s\n" $output1 | sed "s/ /0/g"`
+    log2=`printf "%08s\n" $output2 | sed "s/ /0/g"`
+    receive_loc="${log1}${log2}"
+
+    newer_location=`printf "$replay_loc\n$receive_loc" | sort -r | head -1`
+    echo "$newer_location"
+    return 0
+}
+
+show_xlog_location() {
+    local location
+
+    location=`get_my_location` || return 1
+    exec_with_retry 0 $CRM_ATTR_REBOOT -N "$NODENAME" -n "$PGSQL_XLOG_LOC_NAME" -v "$location"
+}
+
+delete_xlog_location() {
+    exec_with_retry 5 $CRM_ATTR_REBOOT -N "$NODENAME" -n "$PGSQL_XLOG_LOC_NAME" -D
+}
+
+show_master_baseline() {
+    local rc
+    local location
+
+    location=`get_my_location`
+    ocf_log info "My master baseline : $location."
+    exec_with_retry 0 $CRM_ATTR_REBOOT -N "$NODENAME" -n "$PGSQL_MASTER_BASELINE" -v "$location"
+}
+
+delete_master_baseline() {
+    exec_with_retry 5 $CRM_ATTR_REBOOT -N "$NODENAME" -n "$PGSQL_MASTER_BASELINE" -D
+}
+
+set_async_mode_all() {
+    [ "$OCF_RESKEY_rep_mode" = "sync" ] || return 0
+    ocf_log info "Set all nodes into async mode."
+    runasowner -q err "echo \"synchronous_standby_names = ''\" > \"$REP_MODE_CONF\""
+    if [ $? -ne 0 ]; then
+        ocf_log err "Can't set all nodes into async mode."
+        return 1
+    fi
+    return 0
+}
+
+set_async_mode() {
+    cat $REP_MODE_CONF |  grep -q -e "[,' ]$1[,' ]"
+    if [ $? -eq 0 ]; then
+        ocf_log info "Setup $1 into async mode."
+        runasowner -q err "echo \"synchronous_standby_names = ''\" > \"$REP_MODE_CONF\""
+    else
+        ocf_log debug "$1 is already in async mode."
+        return 0
+    fi
+    exec_with_retry 0 reload_conf
+}
+
+set_sync_mode() {
+    local sync_node_in_conf
+
+    sync_node_in_conf=`cat $REP_MODE_CONF | cut -d "'" -f 2`
+    if [ -n "$sync_node_in_conf" ]; then
+        ocf_log debug "$sync_node_in_conf is already sync mode."
+    else
+        ocf_log info "Setup $1 into sync mode."
+        runasowner -q err "echo \"synchronous_standby_names = '$1'\" > \"$REP_MODE_CONF\""
+        [ "$RE_CONTROL_SLAVE" = "false" ] && RE_CONTROL_SLAVE="true"
+        exec_with_retry 0 reload_conf
+    fi
+}
+
+reload_conf() {
+    # Invoke pg_ctl
+    runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata reload"
+    if [ $? -eq 0 ]; then
+        ocf_log info "Reload configuration file."
+    else
+        ocf_log err "Can't reload configuration file."
+        return 1
+    fi
+
+    return 0
+}
+
+user_recovery_conf() {
+    # put archive_cleanup_command and recovery_end_command only when defined by user
+    if [ -n "$OCF_RESKEY_archive_cleanup_command" ]; then
+        echo "archive_cleanup_command = '${OCF_RESKEY_archive_cleanup_command}'"
+    fi
+    if [ -n "$OCF_RESKEY_recovery_end_command" ]; then
+        echo "recovery_end_command = '${OCF_RESKEY_recovery_end_command}'"
+    fi
+}
+
+make_recovery_conf() {
+    runasowner "touch $RECOVERY_CONF"
+    if [ $? -ne 0 ]; then
+        ocf_log err "Can't create recovery.conf."
+        return 1
+    fi
+
+cat > $RECOVERY_CONF <<END
+standby_mode = 'on'
+primary_conninfo = 'host=${OCF_RESKEY_master_ip} port=${OCF_RESKEY_pgport} user=${OCF_RESKEY_repuser} application_name=${NODENAME} ${OCF_RESKEY_primary_conninfo_opt}'
+restore_command = '${OCF_RESKEY_restore_command}'
+recovery_target_timeline = 'latest'
+END
+
+    user_recovery_conf >> $RECOVERY_CONF
+    ocf_log debug "Created recovery.conf. host=${OCF_RESKEY_master_ip}, user=${OCF_RESKEY_repuser}"
+    return 0
+}
+
+# change pgsql-status.
+# arg1:node, arg2: value
+change_pgsql_status() {
+    local output
+
+    if ! is_node_online $1; then
+        return 0
+    fi
+
+    output=`$CRM_ATTR_REBOOT -N "$1" -n "$PGSQL_STATUS_ATTR" -G -q 2>/dev/null`
+    if [ "$output" != "$2" ]; then
+        # If slave's disk is broken, RA cannot read PID file
+        # and misjudges the PostgreSQL as down while it is running.
+        # It causes overwriting of pgsql-status by Master because replication is still connected.
+        if [ "$output" = "STOP" -o "$output" = "UNKNOWN" ]; then
+            if [ "$1" != "$NODENAME" ]; then
+                ocf_log warn "Changing $PGSQL_STATUS_ATTR on $1 : $output->$2 by $NODENAME is prohibited."
+                return 0
+            fi
+        fi
+        ocf_log info "Changing $PGSQL_STATUS_ATTR on $1 : $output->$2."
+        exec_with_retry 0 $CRM_ATTR_REBOOT -N "$1" -n "$PGSQL_STATUS_ATTR" -v "$2"
+    fi
+    return 0
+}
+
+# change pgsql-data-status.
+# arg1:node, arg2: value
+change_data_status() {
+    local output
+
+    if ! node_exist $1; then
+        return 0
+    fi
+
+    while :
+    do
+        output=`$CRM_ATTR_FOREVER -N "$1" -n "$PGSQL_DATA_STATUS_ATTR" -G -q 2>/dev/null`
+        if [ "$output" != "$2" ]; then
+            ocf_log info "Changing $PGSQL_DATA_STATUS_ATTR on $1 : $output->$2."
+            exec_with_retry 0 exec_with_timeout 0 "$CRM_ATTR_FOREVER" -N $1 -n $PGSQL_DATA_STATUS_ATTR -v "$2"
+        else
+            break
+        fi
+    done
+    return 0
+}
+
+# set master-score
+# arg1:node, arg2: score, arg3: resoure
+set_master_score() {
+    local current_score
+
+    current_score=`$CRM_ATTR_REBOOT -N "$1" -n "master-$3" -G -q 2>/dev/null`
+    if [ -n "$current_score" -a "$current_score" != "$2" ]; then
+        ocf_log info "Changing $3 master score on $1 : $current_score->$2."
+        exec_with_retry 0 $CRM_ATTR_REBOOT -N "$target" -n "master-$3" -v "$2"
+    fi
+    return 0
+}
+
+# change master-score
+# arg1:node, arg2: score
+change_master_score() {
+    local instance
+
+    if ! is_node_online $1; then
+        return 0
+    fi
+
+    if echo $OCF_RESOURCE_INSTANCE | grep -q ":"; then
+        # If Pacemaker version is 1.0.x
+        instance=0
+        while :
+        do
+            if [ "$instance" -ge "$OCF_RESKEY_CRM_meta_clone_max" ]; then
+                break
+            fi
+            if [ "${RESOURCE_NAME}:${instance}" = "$OCF_RESOURCE_INSTANCE" ]; then
+                instance=`expr $instance + 1`
+                continue
+            fi
+            set_master_score $1 $2 "${RESOURCE_NAME}:${instance}" || return 1
+            instance=`expr $instance + 1`
+        done
+    else
+        # If globally-unique=false and Pacemaker version is 1.1.8 or higher 
+        # Master/Slave resource has no instance number
+        set_master_score $1 $2 ${RESOURCE_NAME} || return 1
+    fi
+    return 0
+}
+
+report_psql_error()
+{
+    local rc
+    local loglevel
+    local message
+
+    rc=$1
+    loglevel=${2:-err}
+    message="$3"
+
+    ocf_log $loglevel "$message rc=$rc"
+    if [ $rc -eq 1 ]; then
+        ocf_log err "Fatal error (out of memory, file not found, etc.) occurred while executing the psql command."
+    elif [ $rc -eq 2 ]; then
+        ocf_log $loglevel "Connection error (connection to the server went bad and the session was not interactive) occurred while executing the psql command."
+    elif [ $rc -eq 3 ]; then
+        ocf_log err "Script error (the variable ON_ERROR_STOP was set) occurred while executing the psql command."
+    fi
+}
+
+#
+# timeout management function
+# arg1   timeout >= 0 (if arg1 is 0, OCF_RESKEY_crm_attr_timeout is used.)
+# arg2 : command
+# arg3 : command's args
+exec_with_timeout() {
+    local func_pid
+    local count=$OCF_RESKEY_crm_attr_timeout
+    local rc
+
+    if [ "$1" -ne 0 ]; then
+        count=$1
+    fi
+    shift
+
+    $* &
+    func_pid=$!
+    sleep .1
+
+    while kill -s 0 $func_pid >/dev/null 2>&1; do
+        sleep 1
+        count=`expr $count - 1`
+        if [ $count -le 0 ]; then
+            ocf_log err "\"$*\" (pid=$func_pid) timed out."
+            kill -s 9 $func_pid >/dev/null 2>&1
+            return 1
+        fi
+        ocf_log info "Waiting($count). \"$*\" (pid=$func_pid)."
+    done
+    wait $func_pid
+}
+
+# retry command when command doesn't return 0
+# arg1       : count >= 0 (if arg1 is 0, it retries command in infinitum(1day))
+# arg2..argN : command and args
+exec_with_retry() {
+    local count="86400"
+    local output
+    local rc
+
+    if [ "$1" -ne 0 ]; then
+        count=$1
+    fi
+    shift
+
+    while [ $count -gt 0 ]; do
+        output=`$*`
+        rc=$?
+        if [ $rc -ne 0 ]; then
+            ocf_log warn "Retrying(remain $count). \"$*\" failed. rc=$rc. stdout=\"$output\"."
+            count=`expr $count - 1`
+            sleep 1
+        else
+            printf "${output}"
+            return 0
+        fi
+    done
+
+    ocf_log err "giving up executing \"$*\""
+    return $rc
+}
+
+is_node_online() {
+    print_crm_mon | tr '[A-Z]' '[a-z]' | grep -e "^node $1 " -e "^node $1:" | grep -q -v "offline"
+}
+
+node_exist() {
+    print_crm_mon | tr '[A-Z]' '[a-z]' | grep -q "^node $1"
+}
+
+check_binary2() {
+    if ! have_binary "$1"; then
+        ocf_log err "Setup problem: couldn't find command: $1"
+        return 1
+    fi
+    return 0
+}
+
+check_config() {
+    local rc=0
+
+    if [ ! -f "$1" ]; then
+        if ocf_is_probe; then
+           ocf_log info "Configuration file is $1 not readable during probe."
+           rc=1
+        else
+           ocf_log err "Configuration file $1 doesn't exist"
+           rc=2
+        fi
+    fi
+
+    return $rc
+}
+
+# Validate most critical parameters
+pgsql_validate_all() {
+    local version
+    local check_config_rc
+    local rep_mode_string
+
+    if ! check_binary2 "$OCF_RESKEY_pgctl" || 
+       ! check_binary2 "$OCF_RESKEY_psql"; then
+        return $OCF_ERR_INSTALLED
+    fi
+
+    check_config "$OCF_RESKEY_config"
+    check_config_rc=$?
+    [ $check_config_rc -eq 2 ] && return $OCF_ERR_INSTALLED
+    [ $check_config_rc -eq 0 ] && : ${OCF_RESKEY_socketdir=`get_pgsql_param unix_socket_directory`}
+
+    getent passwd $OCF_RESKEY_pgdba >/dev/null 2>&1
+    if [ ! $? -eq 0 ]; then
+        ocf_log err "User $OCF_RESKEY_pgdba doesn't exist";
+        return $OCF_ERR_INSTALLED;
+    fi
+
+    if ocf_is_probe; then
+        ocf_log info "Don't check $OCF_RESKEY_pgdata during probe"
+    else
+        if ! runasowner "test -w $OCF_RESKEY_pgdata"; then
+            ocf_log err "Directory $OCF_RESKEY_pgdata is not writable by $OCF_RESKEY_pgdba"
+            return $OCF_ERR_PERM;
+        fi
+    fi
+
+    if [ -n "$OCF_RESKEY_monitor_user" -a ! -n "$OCF_RESKEY_monitor_password" ]
+    then
+        ocf_log err "monitor password can't be empty"
+        return $OCF_ERR_CONFIGURED
+    fi
+
+    if [ ! -n "$OCF_RESKEY_monitor_user" -a -n "$OCF_RESKEY_monitor_password" ]
+    then
+        ocf_log err "monitor_user has to be set if monitor_password is set"
+        return $OCF_ERR_CONFIGURED
+    fi
+
+    if is_replication || [ "$OCF_RESKEY_rep_mode" = "slave" ]; then
+        version=`cat $OCF_RESKEY_pgdata/PG_VERSION`
+        if [ `printf "$version\n9.1" | sort -n | head -1` != "9.1" ]; then
+            ocf_log err "Replication mode needs PostgreSQL 9.1 or higher."
+            return $OCF_ERR_INSTALLED
+        fi
+        if [ ! -n "$OCF_RESKEY_master_ip" ]; then
+            ocf_log err "master_ip can't be empty."
+            return $OCF_ERR_CONFIGURED
+        fi
+    fi
+
+    if is_replication; then
+        if ! ocf_is_ms; then
+            ocf_log err "Replication(rep_mode=async or sync) requires Master/Slave configuration."
+            return $OCF_ERR_CONFIGURED
+        fi
+        if [ ! "$OCF_RESKEY_rep_mode" = "sync" -a ! "$OCF_RESKEY_rep_mode" = "async" ]; then
+            ocf_log err "Invalid rep_mode : $OCF_RESKEY_rep_mode"
+            return $OCF_ERR_CONFIGURED
+        fi
+        if [ ! -n "$NODE_LIST" ]; then
+            ocf_log err "node_list can't be empty."
+            return $OCF_ERR_CONFIGURED
+        fi
+        if [ $check_config_rc -eq 0 ]; then
+            rep_mode_string="include '$REP_MODE_CONF' # added by pgsql RA"
+            if [ "$OCF_RESKEY_rep_mode" = "sync" ]; then
+                if ! grep -q "$rep_mode_string" $OCF_RESKEY_config; then
+                    ocf_log info "adding include directive into $OCF_RESKEY_config"
+                    echo "$rep_mode_string" >> $OCF_RESKEY_config
+                fi
+            else
+                if grep -q "$rep_mode_string" $OCF_RESKEY_config; then
+                    ocf_log info "deleting include directive from $OCF_RESKEY_config"
+                    sed -i "/${rep_mode_string//\//\\/}/d" $OCF_RESKEY_config
+                fi
+            fi
+        fi
+        if ! mkdir -p $OCF_RESKEY_tmpdir || ! chown $OCF_RESKEY_pgdba $OCF_RESKEY_tmpdir || ! chmod 700 $OCF_RESKEY_tmpdir; then
+            ocf_log err "Can't create directory $OCF_RESKEY_tmpdir or it is not readable by $OCF_RESKEY_pgdba"
+            return $OCF_ERR_PERM
+        fi
+    fi
+
+    if [ "$OCF_RESKEY_rep_mode" = "slave" ]; then
+        if ocf_is_ms; then
+            ocf_log err "Replication(rep_mode=slave) does not support Master/Slave configuration."
+            return $OCF_ERR_CONFIGURED
+        fi
+    fi
+
+    return $OCF_SUCCESS
+}
+
+
+#
+# Check if we need to create a log file
+#
+
+check_log_file() {
+    if [ ! -f "$1" ]
+    then
+        touch $1 > /dev/null 2>&1
+        chown $OCF_RESKEY_pgdba:`getent passwd $OCF_RESKEY_pgdba | cut -d ":" -f 4` $1
+    fi
+
+    #Check if $OCF_RESKEY_pgdba can write to the log file
+    if ! runasowner "test -w $1"
+    then
+        return 1
+    fi
+
+    return 0
+}
+
+#
+# Check socket directory
+#
+check_socket_dir() {
+    if [ ! -d "$OCF_RESKEY_socketdir" ]; then
+        if ! mkdir "$OCF_RESKEY_socketdir"; then
+            ocf_log err "Can't create directory $OCF_RESKEY_socketdir"
+            exit $OCF_ERR_PERM
+        fi
+
+        if ! chown $OCF_RESKEY_pgdba:`getent passwd \
+             $OCF_RESKEY_pgdba | cut -d ":" -f 4` "$OCF_RESKEY_socketdir" 
+        then
+            ocf_log err "Can't change ownership for $OCF_RESKEY_socketdir"
+            exit $OCF_ERR_PERM
+        fi
+
+        if ! chmod 2775 "$OCF_RESKEY_socketdir"; then
+            ocf_log err "Can't change permissions for $OCF_RESKEY_socketdir"
+            exit $OCF_ERR_PERM
+        fi
+    else
+        if ! runasowner "touch $OCF_RESKEY_socketdir/test.$$"; then
+            ocf_log err "$OCF_RESKEY_pgdba can't create files in $OCF_RESKEY_socketdir"
+            exit $OCF_ERR_PERM
+        fi
+        rm $OCF_RESKEY_socketdir/test.$$
+    fi
+}
+
+print_crm_mon() {
+    if [ -z "$CRM_MON_OUTPUT" ]; then
+        CRM_MON_OUTPUT=`exec_with_retry 0 crm_mon -n1`
+    fi
+    printf "${CRM_MON_OUTPUT}\n"
+}
+
+#
+#   'main' starts here...
+#
+
+
+if [ $# -ne 1 ]
+then
+    usage
+    exit $OCF_ERR_GENERIC
+fi
+
+
+PIDFILE=${OCF_RESKEY_pgdata}/postmaster.pid
+BACKUPLABEL=${OCF_RESKEY_pgdata}/backup_label
+RESOURCE_NAME=`echo $OCF_RESOURCE_INSTANCE | cut -d ":" -f 1`
+PGSQL_WAL_RECEIVER_STATUS_ATTR="${RESOURCE_NAME}-receiver-status"
+RECOVERY_CONF=${OCF_RESKEY_pgdata}/recovery.conf
+NODENAME=$(ocf_local_nodename | tr '[A-Z]' '[a-z]')
+
+if is_replication; then
+    REP_MODE_CONF=${OCF_RESKEY_tmpdir}/rep_mode.conf
+    PGSQL_LOCK=${OCF_RESKEY_tmpdir}/PGSQL.lock
+    XLOG_NOTE_FILE=${OCF_RESKEY_tmpdir}/xlog_note
+
+    CRM_MASTER="${HA_SBIN_DIR}/crm_master -l reboot"
+    CRM_ATTR_REBOOT="${HA_SBIN_DIR}/crm_attribute -l reboot"
+    CRM_ATTR_FOREVER="${HA_SBIN_DIR}/crm_attribute -l forever"
+    CRM_FAILCOUNT="${HA_SBIN_DIR}/crm_failcount"
+
+    CAN_NOT_PROMOTE="-INFINITY"
+    CAN_PROMOTE="100"
+    PROMOTE_ME="1000"
+
+    CHECK_MS_SQL="select pg_is_in_recovery()"
+    CHECK_XLOG_LOC_SQL="select pg_last_xlog_replay_location(),pg_last_xlog_receive_location()"
+    CHECK_REPLICATION_STATE_SQL="select application_name,upper(state),upper(sync_state) from pg_stat_replication"
+
+    PGSQL_STATUS_ATTR="${RESOURCE_NAME}-status"
+    PGSQL_DATA_STATUS_ATTR="${RESOURCE_NAME}-data-status"
+    PGSQL_XLOG_LOC_NAME="${RESOURCE_NAME}-xlog-loc"
+    PGSQL_MASTER_BASELINE="${RESOURCE_NAME}-master-baseline"
+
+    NODE_LIST=`echo $OCF_RESKEY_node_list | tr '[A-Z]' '[a-z]'`
+    RE_CONTROL_SLAVE="false"
+fi
+
+case "$1" in
+    methods)    pgsql_methods
+                exit $?;;
+
+    meta-data)  meta_data
+                exit $OCF_SUCCESS;;
+esac
+
+pgsql_validate_all
+rc=$?
+
+[ "$1" = "validate-all" ] && exit $rc
+
+if [ $rc -ne 0 ]
+then
+    case "$1" in
+        stop)    if is_replication; then
+                    change_pgsql_status "$NODENAME" "UNKNOWN"
+                 fi
+                 exit $OCF_SUCCESS;;
+        monitor) exit $OCF_NOT_RUNNING;;
+        status)  exit $OCF_NOT_RUNNING;;
+        *)       exit $rc;;
+    esac
+fi
+
+US=`id -u -n`
+
+if [ $US != root -a $US != $OCF_RESKEY_pgdba ]
+then
+    ocf_log err "$0 must be run as root or $OCF_RESKEY_pgdba"
+    exit $OCF_ERR_GENERIC
+fi
+
+# make psql command options
+if [ -n "$OCF_RESKEY_monitor_user" ]; then
+    PGUSER=$OCF_RESKEY_monitor_user; export PGUSER
+    PGPASSWORD=$OCF_RESKEY_monitor_password; export PGPASSWORD
+    psql_options="-p $OCF_RESKEY_pgport $OCF_RESKEY_pgdb"
+else
+    psql_options="-p $OCF_RESKEY_pgport -U $OCF_RESKEY_pgdba $OCF_RESKEY_pgdb"
+fi
+
+if [ -n "$OCF_RESKEY_pghost" ]; then
+    psql_options="$psql_options -h $OCF_RESKEY_pghost"
+else
+    if [ -n "$OCF_RESKEY_socketdir" ]; then
+        psql_options="$psql_options -h $OCF_RESKEY_socketdir"
+    fi
+fi
+
+if [ -n "$OCF_RESKEY_pgport" ]; then
+    export PGPORT=$OCF_RESKEY_pgport
+fi
+
+if [ -n "$OCF_RESKEY_pglibs" ]; then
+    if [ -n "$LD_LIBRARY_PATH" ]; then
+        export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$OCF_RESKEY_pglibs
+    else
+        export LD_LIBRARY_PATH=$OCF_RESKEY_pglibs
+    fi
+fi
+   
+
+# What kind of method was invoked?
+case "$1" in
+    status)     if pgsql_status
+                then
+                    ocf_log info "PostgreSQL is up"
+                    exit $OCF_SUCCESS
+                else
+                    ocf_log info "PostgreSQL is down"
+                    exit $OCF_NOT_RUNNING
+                fi;;
+
+    monitor)    pgsql_monitor
+                exit $?;;
+
+    start)      pgsql_start
+                exit $?;;
+
+    promote)    pgsql_promote
+                exit $?;;
+
+    demote)     pgsql_demote
+                exit $?;;
+
+    notify)     pgsql_notify
+                exit $?;;
+
+    stop)       pgsql_stop
+                exit $?;;
+    *)
+                exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/heartbeat/pingd b/heartbeat/pingd
new file mode 100755
index 0000000..34ed704
--- /dev/null
+++ b/heartbeat/pingd
@@ -0,0 +1,279 @@
+#!/bin/sh
+#
+#
+#	pingd OCF Resource Agent
+#	Records (in the CIB) the current number of ping nodes a
+#	   cluster node can connect to.
+#
+# Copyright (c) 2006 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.
+#
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="pingd">
+<version>1.0</version>
+
+<longdesc lang="en">
+Deprecation warning: This agent is deprecated and may be removed from
+a future release. See the ocf:pacemaker:pingd resource agent for a
+supported alternative. --
+This is a pingd Resource Agent.
+It records (in the CIB) the current number of ping nodes a node can connect to.
+</longdesc>
+<shortdesc lang="en">Monitors connectivity to specific hosts or
+IP addresses ("ping nodes") (deprecated)</shortdesc>
+
+<parameters>
+
+<parameter name="pidfile" unique="0">
+<longdesc lang="en">PID file</longdesc>
+<shortdesc lang="en">PID file</shortdesc>
+<content type="string" default="$HA_RSCTMP/pingd-${OCF_RESOURCE_INSTANCE}" />
+</parameter>
+
+
+<parameter name="user" unique="0">
+<longdesc lang="en">
+The user we want to run pingd as
+</longdesc>
+<shortdesc lang="en">The user we want to run pingd as</shortdesc>
+<content type="string" default="root" />
+</parameter>
+
+<parameter name="dampen" unique="0">
+<longdesc lang="en">
+The time to wait (dampening) further changes occur
+</longdesc>
+<shortdesc lang="en">Dampening interval</shortdesc>
+<content type="integer" default="1s"/>
+</parameter>
+
+<parameter name="set" unique="0">
+<longdesc lang="en">
+The name of the instance_attributes set to place the value in.  Rarely needs to be specified.
+</longdesc>
+<shortdesc lang="en">Set name</shortdesc>
+<content type="integer" default=""/>
+</parameter>
+
+<parameter name="name" unique="0">
+<longdesc lang="en">
+The name of the attributes to set.  This is the name to be used in the constraints.
+</longdesc>
+<shortdesc lang="en">Attribute name</shortdesc>
+<content type="integer" default="${OCF_RESOURCE_INSTANCE}"/>
+</parameter>
+
+<parameter name="section" unique="0">
+<longdesc lang="en">
+The section place the value in.  Rarely needs to be specified.
+</longdesc>
+<shortdesc lang="en">Section name</shortdesc>
+<content type="integer" default=""/>
+</parameter>
+
+<parameter name="multiplier" unique="0">
+<longdesc lang="en">
+The number by which to multiply the number of connected ping nodes by
+</longdesc>
+<shortdesc lang="en">Value multiplier</shortdesc>
+<content type="integer" default=""/>
+</parameter>
+
+<parameter name="host_list" unique="0">
+<longdesc lang="en">
+The list of ping nodes to count.  Defaults to all configured ping nodes.  Rarely needs to be specified.
+</longdesc>
+<shortdesc lang="en">Host list</shortdesc>
+<content type="integer" default=""/>
+</parameter>
+
+<parameter name="ignore_deprecation">
+<longdesc lang="en">
+If set to true, suppresses the deprecation warning for this agent.
+</longdesc>
+<shortdesc lang="en">Suppress deprecation warning</shortdesc>
+<content type="boolean" default="false" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" depth="0"  timeout="20s" interval="10" />
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="20s" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+pingd_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+pingd_start() {
+    extras=""
+    if [ ! -z "$OCF_RESKEY_multiplier" ]; then
+	extras="$extras -m $OCF_RESKEY_multiplier"
+    fi
+    if [ ! -z "$OCF_RESKEY_set" ]; then
+	extras="$extras -s $OCF_RESKEY_set"
+    fi
+    if [ ! -z "$OCF_RESKEY_section" ]; then
+	extras="$extras -S $OCF_RESKEY_section"
+    fi
+    for a_host in $OCF_RESKEY_host_list; do
+	extras="$extras -h $a_host"
+    done
+    pingd_cmd="${HA_BIN}/pingd -D -p $OCF_RESKEY_pidfile -a $OCF_RESKEY_name -d $OCF_RESKEY_dampen $extras"
+
+    if [ ! -z $OCF_RESKEY_user ]; then
+	sudo -u $OCF_RESKEY_user $pingd_cmd
+    else
+	$pingd_cmd
+    fi
+
+    rc=$?
+    if [ $rc = 0 ]; then
+	exit $OCF_SUCCESS
+    fi
+
+    ocf_log err "Could not run $pingd_cmd : rc=$rc"
+    exit $OCF_ERR_GENERIC
+}
+
+pingd_stop() {
+    if [ -f $OCF_RESKEY_pidfile ]; then
+	pid=`cat $OCF_RESKEY_pidfile`
+    fi
+    if [ ! -z $pid ]; then
+	kill -s 9 $pid
+	rc=$?
+
+	if [ $rc = 0 -o $rc = 1 ]; then
+	    rm $OCF_RESKEY_pidfile
+	    exit $OCF_SUCCESS
+	fi
+
+	ocf_log err "Unexpected result from kill -9 $pid: $rc"
+	exit $OCF_ERR_GENERIC
+    fi
+    exit $OCF_SUCCESS
+}
+
+pingd_monitor() {
+    if [ -f $OCF_RESKEY_pidfile ]; then
+	pid=`cat $OCF_RESKEY_pidfile`
+    fi
+    if [ ! -z $pid ]; then
+	kill -s 0 $pid
+	if [ $? = 0 ]; then
+	    exit $OCF_SUCCESS
+	fi
+    fi
+    exit $OCF_NOT_RUNNING
+}
+
+pingd_validate() {
+# Existence of the user
+    if [ ! -z $OCF_RESKEY_user ]; then
+	getent passwd "$OCF_RESKEY_user" >/dev/null
+	if [ $? -eq 0 ]; then
+	    : Yes, user exists. We can further check his permission on crm_mon if necessary
+	else
+	    ocf_log err "The user $OCF_RESKEY_user does not exist!"
+	    exit $OCF_ERR_ARGS
+	fi
+    fi
+
+# Pidfile better be an absolute path
+    case $OCF_RESKEY_pidfile in
+	/*) ;;
+	*) ocf_log warn "You should have pidfile($OCF_RESKEY_pidfile) of absolute path!" ;;
+    esac
+
+# Check the update interval
+    if ocf_is_decimal "$OCF_RESKEY_update" && [ $OCF_RESKEY_update -gt 0 ]; then
+	:
+    else
+	ocf_log err "Invalid update interval $OCF_RESKEY_update. It should be positive integer!"
+	exit $OCF_ERR_ARGS
+    fi
+
+    echo "Validate OK"
+    return $OCF_SUCCESS
+}
+
+if [ $# -ne 1 ]; then
+    pingd_usage
+    exit $OCF_ERR_ARGS
+fi
+
+: ${OCF_RESKEY_pidfile:="$HA_RSCTMP/pingd-${OCF_RESOURCE_INSTANCE}"}
+: ${OCF_RESKEY_name:="pingd"}
+: ${OCF_RESKEY_dampen:="1s"}
+
+if [ "$__OCF_ACTION" = "meta-data" ]; then
+    meta_data
+    exit $OCF_SUCCESS
+fi
+
+# Be obnoxious, log deprecation warning on every invocation (unless
+# suppressed by resource configuration).
+ocf_deprecated
+
+case $__OCF_ACTION in
+start)		pingd_start
+		;;
+stop)		pingd_stop
+		;;
+monitor)	pingd_monitor
+		;;
+validate-all)	pingd_validate
+		;;
+usage|help)	pingd_usage
+		exit $OCF_SUCCESS
+		;;
+*)		pingd_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+
+exit $?
diff --git a/heartbeat/portblock b/heartbeat/portblock
new file mode 100755
index 0000000..53b35e9
--- /dev/null
+++ b/heartbeat/portblock
@@ -0,0 +1,477 @@
+#!/bin/sh
+#
+# portblock: iptables temporary portblocking control 
+#
+# Author:	Sun Jiang Dong (initial version)
+#               Philipp Reisner (per-IP filtering)
+#
+# License:	GNU General Public License (GPL)
+#
+# Copyright:	(C) 2005 International Business Machines
+#
+#	  OCF parameters are as below:
+#		OCF_RESKEY_protocol
+#		OCF_RESKEY_portno
+#		OCF_RESKEY_action
+#		OCF_RESKEY_ip
+#		OCF_RESKEY_tickle_dir
+#		OCF_RESKEY_sync_script
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Defaults
+OCF_RESKEY_ip_default="0.0.0.0/0"
+
+: ${OCF_RESKEY_ip=${OCF_RESKEY_ip_default}}
+#######################################################################
+CMD=`basename $0`
+TICKLETCP=$HA_BIN/tickle_tcp
+
+usage()
+{
+	cat <<END >&2
+	usage: $CMD {start|stop|status|monitor|meta-data|validate-all}
+
+	$CMD is used to temporarily block ports using iptables.
+
+	It can be used to turn off a port before bringing
+	up an IP address, and enable it after a service is started.
+	To do that for samba, the following resource line can be used:
+
+	$CMD::tcp::137,138::block		\\
+	    10.10.10.20				\\
+	    nmbd smbd 				\\
+	    $CMD::tcp::137,138::unblock
+
+	This will do the follwing things:
+
+	  - DROP all incoming packets for TCP ports 137 and 138
+	  - Bring up the IP alias 10.10.10.20
+	  - start the nmbd and smbd services
+	  - Re-enable TCP ports 137 and 138
+	        (enable normal firewall rules on those ports)
+
+	This prevents clients from getting ICMP port unreachable
+	if they try to reconnect to the service after the alias is
+	enabled but before nmbd and smbd are running.  These packets
+	will cause some clients to give up attempting to reconnect to
+	the server.
+
+	NOTE:  iptables is linux-specific...
+
+	An additional feature in the portblock RA is the tickle ACK function
+	enabled by specifying the tickle_dir parameter. The tickle ACK 
+	triggers the clients to faster reconnect their TCP connections to the 
+	fail-overed server.
+
+	Please note that this feature is often used for the floating IP fail-
+	over scenario where the long-lived TCP connections need to be tickled.
+	It doesn't support the cluster alias IP scenario.
+
+	When using the tickle ACK function, in addition to the normal usage
+	of portblock RA, the parameter tickle_dir must be specified in the 
+	action=unblock instance of the portblock resources.
+	For example, you may stack resources like below:
+		portblock action=block
+		services
+		portblock action=unblock tickle_dir=/tickle/state/dir
+
+	If you want to tickle all the TCP connections which connected to _one_
+	floating IP but different ports, no matter how many portblock resources 
+	you have defined, you should enable tickles for _one_ portblock 
+	resource(action=unblock) only.
+	
+	The tickle_dir is a location which stores the established TCP 
+	connections. It can be a shared directory(which is cluster-visible to 
+	all nodes) or a local directory.
+	If you use the shared directory, you needn't do any other things.
+	If you use the local directory, you must also specify the sync_script
+	paramater. We recommend you to use csync2 as the sync_script.
+	For example, if you use the local directory /tmp/tickle as tickle_dir, 
+	you could setup the csync2 as the csync2 documentation says and 
+	configure your /etc/csync2/csync2.cfg like:
+		group ticklegroup {
+		  host node1;
+		  host node2;
+		  key  /etc/csync2/ticklegroup.key;
+		  include /etc/csync2/csync2.cfg;
+		  include /tmp/tickle;
+		  auto younger;
+		}
+	Then specify the parameter sync_script as "csync2 -xv".
+
+END
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="portblock">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for portblock. It is used to temporarily block ports 
+using iptables. In addition, it may allow for faster TCP reconnects
+for clients on failover. Use that if there are long lived TCP
+connections to an HA service. This feature is enabled by setting the
+tickle_dir parameter and only in concert with action set to unblock.
+Note that the tickle ACK function is new as of version 3.0.2 and
+hasn't yet seen widespread use.
+</longdesc>
+<shortdesc lang="en">Block and unblocks access to TCP and UDP ports</shortdesc>
+
+<parameters>
+<parameter name="protocol" unique="0" required="1">
+<longdesc lang="en">
+The protocol used to be blocked/unblocked.
+</longdesc>
+<shortdesc lang="en">protocol</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="portno" unique="0" required="1">
+<longdesc lang="en">
+The port number used to be blocked/unblocked.
+</longdesc>
+<shortdesc lang="en">portno</shortdesc>
+<content type="integer" default="" />
+</parameter>
+
+<parameter name="action" unique="0" required="1">
+<longdesc lang="en">
+The action (block/unblock) to be done on the protocol::portno.
+</longdesc>
+<shortdesc lang="en">action</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="ip" unique="0" required="0">
+<longdesc lang="en">
+The IP address used to be blocked/unblocked.
+</longdesc>
+<shortdesc lang="en">ip</shortdesc>
+<content type="string" default="${OCF_RESKEY_ip_default}" />
+</parameter>
+
+<parameter name="tickle_dir" unique="0" required="0">
+<longdesc lang="en">
+The shared or local directory (_must_ be absolute path) which 
+stores the established TCP connections.
+</longdesc>
+<shortdesc lang="en">Tickle directory</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="sync_script" unique="0" required="0">
+<longdesc lang="en">
+If the tickle_dir is a local directory, then the TCP connection state
+file has to be replicated to other nodes in the cluster. It can be
+csync2 (default), some wrapper of rsync, or whatever. It takes the
+file name as a single argument. For csync2, set it to "csync2 -xv".
+</longdesc>
+<shortdesc lang="en">Connection state file synchronization script</shortdesc>
+<content type="string" default="" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="20" />
+<action name="stop" timeout="20" />
+<action name="status" depth="0" timeout="10" interval="10" />
+<action name="monitor" depth="0" timeout="10" interval="10" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+
+#
+#	Because this is the normal usage, we consider "block"
+#	resources to be pseudo-resources -- that is, their status can't
+#	be reliably determined through external means.
+#	This is because we expect an "unblock" resource to come along
+#	and disable us -- but we're still in some sense active...
+#
+
+#active_grep_pat {udp|tcp} portno,portno
+active_grep_pat()
+{
+  w="[ 	][ 	]*"
+  any="0\\.0\\.0\\.0/0"
+  echo "^DROP${w}${1}${w}--${w}${any}${w}${3}${w}multiport${w}dports${w}${2}\>"
+}
+
+#chain_isactive  {udp|tcp} portno,portno ip
+chain_isactive()
+{
+  PAT=`active_grep_pat "$1" "$2" "$3"`
+  $IPTABLES -n -L INPUT | grep "$PAT" >/dev/null
+}
+
+save_tcp_connections()
+{
+	[ -z "$OCF_RESKEY_tickle_dir" ] && return
+	statefile=$OCF_RESKEY_tickle_dir/$OCF_RESKEY_ip
+	if [ -z "$OCF_RESKEY_sync_script" ]; then
+		netstat -tn |awk -F '[:[:space:]]+' '
+			$8 == "ESTABLISHED" && $4 == "'$OCF_RESKEY_ip'" \
+			{printf "%s:%s\t%s:%s\n", $4,$5, $6,$7}' |
+			dd of="$statefile".new conv=fsync && 
+			mv "$statefile".new "$statefile"
+	else
+		netstat -tn |awk -F '[:[:space:]]+' '
+			$8 == "ESTABLISHED" && $4 == "'$OCF_RESKEY_ip'" \
+			{printf "%s:%s\t%s:%s\n", $4,$5, $6,$7}' \
+			> $statefile
+		$OCF_RESKEY_sync_script $statefile > /dev/null 2>&1 &
+	fi
+}
+
+run_tickle_tcp()
+{
+	[ -z "$OCF_RESKEY_tickle_dir" ] && return
+	echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
+	f=$OCF_RESKEY_tickle_dir/$OCF_RESKEY_ip
+	[ -f $f ] && cat $f | $TICKLETCP -n 3
+}
+
+SayActive()
+{
+  echo "$CMD DROP rule for INPUT chain [$*]  is running (OK)"
+}
+
+SayConsideredActive()
+{
+  echo "$CMD DROP rule for INPUT chain [$*] considered to be running (OK)"
+}
+
+SayInactive()
+{
+  echo "$CMD DROP rule for INPUT chain [$*] is inactive"
+}
+
+#IptablesStatus  {udp|tcp} portno,portno ip {block|unblock}
+IptablesStatus() {
+    local rc
+    rc=$OCF_ERR_GENERIC
+    activewords="$CMD $1 $2 is running (OK)"
+    if chain_isactive "$1" "$2" "$3"; then
+	case $4 in
+	    block)	
+		SayActive $*
+		rc=$OCF_SUCCESS
+		;;
+	    *)
+ 		SayInactive $*
+		rc=$OCF_NOT_RUNNING
+		;;
+	esac
+    else
+	case $4 in
+	    block)
+		if ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" status; then
+		    SayConsideredActive $*
+		    rc=$OCF_SUCCESS
+		else
+		    SayInactive $*
+		    rc=$OCF_NOT_RUNNING
+		fi
+		;;
+	    
+	    *)
+		if ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" status; then
+			SayActive $*
+			#This is only run on real monitor events.
+			save_tcp_connections
+			rc=$OCF_SUCCESS
+		else
+			SayInactive $*
+			rc=$OCF_NOT_RUNNING
+		fi
+		;;
+	esac
+    fi      
+    
+    return $rc
+}
+
+#IptablesBLOCK  {udp|tcp} portno,portno ip
+IptablesBLOCK()
+{
+  if
+    chain_isactive "$1" "$2" "$3"
+  then
+    : OK -- chain already active
+  else
+    $IPTABLES -I INPUT -p "$1" -d "$3" -m multiport --dports "$2" -j DROP
+  fi
+
+  return $?
+}
+
+#IptablesUNBLOCK  {udp|tcp} portno,portno ip
+IptablesUNBLOCK()
+{
+  if
+    chain_isactive "$1" "$2" "$3"
+  then
+    $IPTABLES -D INPUT -p "$1" -d "$3" -m multiport --dports "$2" -j DROP
+  else
+    : Chain Not active
+  fi
+
+  return $?
+}
+
+#IptablesStart  {udp|tcp} portno,portno ip {block|unblock}
+IptablesStart()
+{
+  ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" start
+  case $4 in
+    block)	IptablesBLOCK "$@";;
+    unblock)
+		IptablesUNBLOCK "$@"
+		rc=$?
+		run_tickle_tcp
+		#ignore run_tickle_tcp exit code!
+		return $rc
+		;;
+    *)		usage; return 1;
+  esac
+
+  return $?
+}
+
+#IptablesStop  {udp|tcp} portno,portno ip {block|unblock}
+IptablesStop()
+{
+  ha_pseudo_resource "${OCF_RESOURCE_INSTANCE}" stop
+  case $4 in
+    block)	IptablesUNBLOCK "$@";;
+    unblock)
+		save_tcp_connections
+		IptablesBLOCK "$@"
+		;;
+    *)		usage; return 1;;
+  esac
+
+  return $?
+}
+
+#
+#	Check if the port is valid, this function code is not decent, but works
+#
+CheckPort() {
+#	Examples of valid port: "1080", "1", "0080"
+#	Examples of invalid port: "1080bad", "0", "0000", ""
+  echo $1 |egrep -qx '[0-9]+(:[0-9]+)?(,[0-9]+(:[0-9]+)?)*'
+}
+
+IptablesValidateAll()
+{
+  check_binary $IPTABLES
+  case $protocol in
+    tcp|udp)
+	;;
+    *)
+	ocf_log err "Invalid protocol $protocol!"
+	exit $OCF_ERR_CONFIGURED
+	;;
+  esac
+
+  if CheckPort "$portno"; then
+	:
+  else
+	ocf_log err "Invalid port number $portno!"
+	exit $OCF_ERR_CONFIGURED
+  fi
+
+  if [ -n "$OCF_RESKEY_tickle_dir" ]; then
+	if [ x"$action" != x"unblock" ]; then
+		ocf_log err "Tickles are only useful with action=unblock!"
+		exit $OCF_ERR_CONFIGURED
+	fi
+	if [ ! -d "$OCF_RESKEY_tickle_dir" ]; then
+		ocf_log err "The tickle dir doesn't exist!"
+		exit $OCF_ERR_INSTALLED	  	
+	fi
+  fi
+
+  case $action in
+    block|unblock)	
+	;;
+    *)		
+	ocf_log err "Invalid action $action!"
+	exit $OCF_ERR_CONFIGURED
+	;; 
+  esac
+  return $OCF_SUCCESS
+}
+
+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
+
+if [ -z "$OCF_RESKEY_protocol" ]; then
+  ocf_log err "Please set OCF_RESKEY_protocol"
+  exit $OCF_ERR_CONFIGURED
+fi 
+
+if [ -z "$OCF_RESKEY_portno" ]; then
+  ocf_log err "Please set OCF_RESKEY_portno"
+  exit $OCF_ERR_CONFIGURED
+fi 
+
+if [ -z "$OCF_RESKEY_action" ]; then
+  ocf_log err "Please set OCF_RESKEY_action"
+  exit $OCF_ERR_CONFIGURED
+fi 
+
+protocol=$OCF_RESKEY_protocol
+portno=$OCF_RESKEY_portno
+action=$OCF_RESKEY_action
+ip=$OCF_RESKEY_ip
+
+case $1 in
+  start)	
+			IptablesStart $protocol $portno $ip $action 
+			;;
+
+  stop)		
+			IptablesStop $protocol $portno $ip $action
+			;;
+
+  status|monitor)	
+			IptablesStatus $protocol $portno $ip $action
+			;;
+
+  validate-all)
+			IptablesValidateAll
+			;;
+
+  *)			usage
+			exit $OCF_ERR_UNIMPLEMENTED
+			;;
+esac
+
+exit $?
diff --git a/heartbeat/postfix b/heartbeat/postfix
new file mode 100755
index 0000000..8619af6
--- /dev/null
+++ b/heartbeat/postfix
@@ -0,0 +1,415 @@
+#!/bin/sh
+#
+# Resource script for Postfix
+#
+# Description:  Manages Postfix as an OCF resource in
+#               an high-availability setup.
+#
+# Author:       Raoul Bhatia <r.bhatia at ipax.at> : Original Author
+# License:      GNU General Public License (GPL)
+# Note:         If you want to run multiple Postfix instances, please see
+#               http://amd.co.at/adminwiki/Postfix#Adding_a_Second_Postfix_Instance_on_one_Server
+#               http://www.postfix.org/postconf.5.html
+#
+#
+#       usage: $0 {start|stop|reload|monitor|validate-all|meta-data}
+#
+#       The "start" arg starts a Postfix instance
+#
+#       The "stop" arg stops it.
+#
+# OCF parameters:
+#  OCF_RESKEY_binary
+#  OCF_RESKEY_config_dir
+#  OCF_RESKEY_parameters
+#
+##########################################################################
+
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+: ${OCF_RESKEY_binary="/usr/sbin/postfix"}
+: ${OCF_RESKEY_config_dir=""}
+: ${OCF_RESKEY_parameters=""}
+USAGE="Usage: $0 {start|stop|reload|monitor|validate-all|meta-data}";
+
+##########################################################################
+
+usage() {
+    echo $USAGE >&2
+}
+
+meta_data() {
+        cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="postfix">
+<version>0.1</version>
+<longdesc lang="en">
+This script manages Postfix as an OCF resource in a high-availability setup.
+</longdesc>
+<shortdesc lang="en">Manages a highly available Postfix mail server instance</shortdesc>
+
+<parameters>
+
+<parameter name="binary" unique="0" required="0">
+<longdesc lang="en">
+Full path to the Postfix binary.
+For example, "/usr/sbin/postfix".
+</longdesc>
+<shortdesc lang="en">Full path to Postfix binary</shortdesc>
+<content type="string" default="/usr/sbin/postfix" />
+</parameter>
+
+<parameter name="config_dir" unique="1" required="0">
+<longdesc lang="en">
+Full path to a Postfix configuration directory.
+For example, "/etc/postfix".
+</longdesc>
+<shortdesc lang="en">Full path to configuration directory</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="parameters" unique="0" required="0">
+<longdesc lang="en">
+The Postfix daemon may be called with additional parameters.
+Specify any of them here.
+</longdesc>
+<shortdesc lang="en"></shortdesc>
+<content type="string" default="" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="reload"  timeout="20s" />
+<action name="monitor" depth="0"  timeout="20s" interval="60s" />
+<action name="validate-all"  timeout="20s" />
+<action name="meta-data"  timeout="5s" />
+</actions>
+</resource-agent>
+END
+}
+
+postfix_running() {
+    local loglevel
+    loglevel=${1:-err}
+
+    # run Postfix status if available
+    if ocf_is_true $status_support; then
+        $binary $OPTION_CONFIG_DIR status 2>&1
+        ret=$?
+        if [ $ret -ne 0 ]; then
+            ocf_log $loglevel "Postfix status: " $ret
+        fi
+        return $ret
+    fi
+
+    # manually check Postfix's pid
+    PIDFILE=${queue_dir}/pid/master.pid
+    if [ -f $PIDFILE ]; then
+         PID=`head -n 1 $PIDFILE`
+         kill -s 0 $PID >/dev/null 2>&1 && [ `ps -p $PID | grep master | wc -l` -eq 1 ]
+         return $?
+    fi
+
+    # Postfix is not running
+    false
+}
+
+postfix_start()
+{
+    # if Postfix is running return success
+    if postfix_running info; then
+        ocf_log info "Postfix already running."
+        return $OCF_SUCCESS
+    fi
+
+    # start Postfix
+    $binary $OPTIONS start >/dev/null 2>&1
+    ret=$?
+
+    if [ $ret -ne 0 ]; then
+        ocf_log err "Postfix returned error: " $ret
+        return $OCF_ERR_GENERIC
+    fi
+
+    # grant some time for startup/forking the sub processes
+    # and loop initial monitoring until success or timeout
+    while true; do
+        sleep 1
+        # break if postfix is up and running; log failure otherwise
+        postfix_running info && break
+        ocf_log info "Postfix failed initial monitor action: " $ret
+    done
+
+    ocf_log info "Postfix started."
+    return $OCF_SUCCESS
+}
+
+
+postfix_stop()
+{
+    # if Postfix is not running return success
+    if ! postfix_running info; then
+        ocf_log info "Postfix already stopped."
+        return $OCF_SUCCESS
+    fi
+
+    # stop Postfix
+    $binary $OPTIONS stop >/dev/null 2>&1
+    ret=$?
+
+    if [ $ret -ne 0 ]; then
+        ocf_log err "Postfix returned an error while stopping: " $ret
+        return $OCF_ERR_GENERIC
+    fi
+
+    # grant some time for shutdown and recheck 5 times
+    for i in 1 2 3 4 5; do
+        if postfix_running info; then
+            sleep 1
+        else
+            break
+        fi
+    done
+
+    # escalate to abort if we did not stop by now
+    # @TODO shall we loop here too?
+    if postfix_running info; then
+        ocf_log err "Postfix failed to stop. Escalating to 'abort'."
+
+        $binary $OPTIONS abort >/dev/null 2>&1; ret=$?
+        sleep 5
+
+        # postfix abort did not succeed
+        if postfix_running; then
+            ocf_log err "Postfix failed to abort."
+            return $OCF_ERR_GENERIC
+        fi
+    fi
+
+    ocf_log info "Postfix stopped."
+    return $OCF_SUCCESS
+}
+
+postfix_reload()
+{
+    if postfix_running; then
+        ocf_log info "Reloading Postfix."
+        $binary $OPTIONS reload
+    fi
+}
+
+postfix_monitor()
+{
+    local status_loglevel="err"
+
+    # Set loglevel to info during probe
+    if ocf_is_probe; then
+        status_loglevel="info"
+    fi
+
+    if postfix_running $status_loglevel; then
+        return $OCF_SUCCESS
+    fi
+
+    return $OCF_NOT_RUNNING
+}
+
+postfix_validate_all()
+{
+    # check that the Postfix binaries exist and can be executed
+    check_binary "$binary"
+    check_binary "postconf"
+
+    # if true, run in-depth directory checks
+    dir_check=true
+
+    # check config_dir and alternate_config_directories parameter
+    if [ "x$config_dir" != "x" ]; then
+        if [ ! -d "$config_dir" ]; then
+            if ocf_is_probe; then
+                ocf_log info "Postfix configuration directory '$config_dir' not readable during probe."
+                # skip in-depth directory checks if config file isn't readable during probe
+                dir_check=false
+            else
+                ocf_log err "Postfix configuration directory '$config_dir' does not exist or is not readable."
+                return $OCF_ERR_INSTALLED
+            fi
+        fi
+
+        alternate_config_directories=`postconf -h alternate_config_directories 2>/dev/null | grep "$config_dir/\?"`
+        if [ "x$alternate_config_directories" = "x" ]; then
+            ocf_log err "Postfix main configuration must contain correct 'alternate_config_directories' parameter."
+            return $OCF_ERR_INSTALLED
+        fi
+    fi
+
+    # check spool/queue and data directories (if applicable)
+    # this is required because "postfix check" does not catch all errors
+    if ocf_is_true $dir_check; then
+        if [ ! -d "$queue_dir" ]; then
+            if ocf_is_probe; then
+                ocf_log info "Postfix queue directory '$queue_dir' not readable during probe."
+            else
+                ocf_log err "Postfix queue directory '$queue_dir' does not exist or is not readable."
+                return $OCF_ERR_INSTALLED
+            fi
+        fi
+
+        if ocf_is_true $status_support; then
+            data_dir=`postconf $OPTION_CONFIG_DIR -h data_directory 2>/dev/null`
+            data_dir_count=`echo "$data_dir" | tr ',' ' ' | wc -w`
+            if [ $data_dir_count -gt 1 ]; then
+            	ocf_log err "Postfix data directory '$orig_data_dir' cannot be set to multiple directories."
+                return $OCF_ERR_INSTALLED
+            fi
+            if [ ! -d "$data_dir" ]; then
+                if ocf_is_probe; then
+                    ocf_log info "Postfix data directory '$data_dir' not readable during probe."
+                else
+                    ocf_log err "Postfix data directory '$data_dir' does not exist or is not readable."
+                    return $OCF_ERR_INSTALLED
+                fi
+            fi
+        fi
+
+        # check directory permissions
+        if ocf_is_true $status_support; then
+            user=`postconf $OPTION_CONFIG_DIR -h mail_owner 2>/dev/null`
+            for dir in "$data_dir"; do
+                if ! su -s /bin/sh - $user -c "test -w $dir"; then
+                    if ocf_is_probe; then
+                        ocf_log info "Directory '$dir' is not writable by user '$user' during probe."
+                    else
+                        ocf_log err "Directory '$dir' is not writable by user '$user'."
+                        return $OCF_ERR_PERM;
+                    fi
+                fi
+            done
+        fi
+    fi
+
+    # run Postfix internal check, if not probing
+    if ! ocf_is_probe; then
+        $binary $OPTIONS check >/dev/null 2>&1
+        ret=$?
+        if [ $ret -ne 0 ]; then
+            ocf_log err "Postfix 'check' failed: " $ret
+            return $OCF_ERR_GENERIC
+        fi
+    fi
+
+    return $OCF_SUCCESS
+}
+
+#
+# Main
+#
+
+if [ $# -ne 1 ]; then
+    usage
+    exit $OCF_ERR_ARGS
+fi
+
+binary=$OCF_RESKEY_binary
+config_dir=$OCF_RESKEY_config_dir
+parameters=$OCF_RESKEY_parameters
+
+
+# handle parameters
+case $1 in
+    meta-data)  meta_data
+                exit $OCF_SUCCESS
+                ;;
+
+    usage|help) usage
+                exit $OCF_SUCCESS
+                ;;
+esac
+
+# build Postfix options string *outside* to access from each method
+OPTIONS=''
+OPTION_CONFIG_DIR=''
+
+# check for Postfix's postconf binary
+check_binary "postconf"
+
+# check if the Postfix config_dir exist
+if [ "x$config_dir" != "x" ]; then
+    # remove all trailing slashes to ease "postconf alternate_config_directories" match
+    config_dir=`echo $config_dir | sed 's/\/*$//'`
+
+    # reset config_dir if it equals Postfix's default config_directory
+    postconf -h config_directory 2>/dev/null | grep -q "^$config_dir/\?$"
+    if [ $? -eq 0 ]; then
+        config_dir=""
+    fi
+
+    # set OPTIONS if config_dir is still set
+    # save OPTION_CONFIG_DIR seperatly
+    if [ "x$config_dir" != "x" ]; then
+        OPTION_CONFIG_DIR="-c $config_dir"
+        OPTIONS=$OPTION_CONFIG_DIR
+   fi
+fi
+
+# add all additional parameters to options string
+if [ "x$parameters" != "x" ]; then
+    OPTIONS="$OPTIONS $parameters"
+fi
+
+# important directories, used in different methods
+queue_dir=`postconf $OPTION_CONFIG_DIR -h queue_directory 2>/dev/null`
+
+# check Postfix version and status support
+status_support=false
+postfix_version=`postconf -h mail_version 2>/dev/null`
+ocf_version_cmp "$postfix_version" "2.5.0"
+ret=$?
+
+# we need Postfix 2.5.0 or greater for status/data_directory support
+if [ $ret -eq 1 -o $ret -eq 2 ]; then
+    status_support=true
+fi
+
+
+postfix_validate_all
+ret=$?
+
+LSB_STATUS_STOPPED=3
+if [ $ret -ne $OCF_SUCCESS ]; then
+    case $1 in
+    stop)       exit $OCF_SUCCESS ;;
+    *)          exit $ret;;
+    esac
+fi
+
+case $1 in
+    monitor)    postfix_monitor
+                exit $?
+                ;;
+    start)      postfix_start
+                exit $?
+                ;;
+
+    stop)       postfix_stop
+                exit $?
+                ;;
+
+    reload)     postfix_reload
+                exit $?
+                ;;
+
+    validate-all)   exit $OCF_SUCCESS
+                    ;;
+
+    *)          usage
+                exit $OCF_ERR_UNIMPLEMENTED
+                ;;
+esac
diff --git a/heartbeat/pound b/heartbeat/pound
new file mode 100755
index 0000000..ab7dd31
--- /dev/null
+++ b/heartbeat/pound
@@ -0,0 +1,339 @@
+#!/bin/sh
+#
+#
+# Pound
+#
+# Description:  Manage pound instances as a HA resource
+#
+# Author:       Taro Matsuzawa <btm at tech.email.ne.jp>
+#
+# License:      GNU General Public License (GPL)
+#
+# See usage() for more details
+#
+# OCF instance parameters:
+#   OCF_RESKEY_pid
+#   OCF_RESKEY_binary
+#   OCF_RESKEY_ctl_binary
+#   OCF_RESKEY_socket_path
+#   OCF_RESKEY_config
+#   OCF_RESKEY_name
+#   OCF_RESKEY_maxfiles
+#
+#######################################################################
+# Initialization:
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+# Set default paramenter values
+
+# Set these two first, as other defaults depend on it
+OCF_RESKEY_name_default=${OCF_RESOURCE_INSTANCE}
+: ${OCF_RESKEY_name=${OCF_RESKEY_name_default}}
+
+OCF_RESKEY_binary_default=pound
+OCF_RESKEY_ctl_binary_default=poundctl
+OCF_RESKEY_pid_default=/var/run/pound_${OCF_RESKEY_name}.pid
+OCF_RESKEY_socket_path_default=/var/lib/pound/pound.cfg
+
+: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
+: ${OCF_RESKEY_ctl_binary=${OCF_RESKEY_ctl_binary_default}}
+: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
+: ${OCF_RESKEY_socket_path=${OCF_RESKEY_socket_path_default}}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="pound" version="0.1">
+<version>1.0</version>
+
+<longdesc lang="en">
+The Pound Resource Agent can manage Pound instances.
+</longdesc>
+<shortdesc lang="en">Manage a Pound instance</shortdesc>
+
+<parameters>
+
+<parameter name="config" unique="1" required="1">
+<longdesc lang="en">
+The Pound configuration file that Pound should manage, for example
+"/etc/pound.cfg".
+</longdesc>
+<shortdesc lang="en">Pound configuration file</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="name" unique="1">
+<longdesc lang="en">
+Override the name of the instance that should be given to Pound
+(defaults to the resource identifier).
+</longdesc>
+<shortdesc lang="en">Instance name</shortdesc>
+<content type="string" default="${OCF_RESKEY_name_default}" />
+</parameter>
+
+<parameter name="pid" unique="1">
+<longdesc lang="en">
+Write the process's PID to the specified file.
+The default will include the specified name, i.e.:
+"/var/run/pound_production.pid". Unlike what this help message shows,
+it is most likely not necessary to change this parameter.
+</longdesc>
+<shortdesc lang="en">Pidfile</shortdesc>
+<content type="string" default="${OCF_RESKEY_pid_default}" />
+</parameter>
+
+<parameter name="binary">
+<longdesc lang="en">
+This is used to start Pound server.
+Normally use pound.
+</longdesc>
+<shortdesc lang="en"></shortdesc>
+<content type="string" default="${OCF_RESKEY_binary_default}" />
+</parameter>
+
+<parameter name="ctl_binary">
+<longdesc lang="en">
+This is used to watch Pound status via Unix socket.
+Normally use poundctl.
+</longdesc>
+<shortdesc lang="en"></shortdesc>
+<content type="string" default="${OCF_RESKEY_ctl_binary_default}" />
+</parameter>
+
+<parameter name="socket_path">
+<longdesc lang="en">
+Write the process's Unix socket.
+This parameter is same 'Control' parameter in configuration file, i.e.:
+Control "/var/lib/pound/pound.cfg".
+</longdesc>
+<shortdesc lang="en"></shortdesc>
+<content type="string" default="${OCF_RESKEY_socket_path_default}" />
+</parameter>
+
+<parameter name="maxfiles">
+<longdesc lang="en">
+Determines how many files pound is allowed to open at
+a time. Helps to fix the 'Too many open files' error message.
+</longdesc>
+<shortdesc lang="en">Allowed number of open files.</shortdesc>
+<content type="integer" default="" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="20" />
+<action name="stop"         timeout="20" />
+<action name="monitor"      timeout="20" interval="10" depth="0" />
+<action name="status"       timeout="20" />
+<action name="meta-data"    timeout="5" />
+<action name="validate-all"   timeout="20" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+
+pound_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+pound_status() {
+    local pid
+    local rc
+
+    # FAILED = pidfile exist, but no running proc (or mismatch pid)
+    # SUCCES = contents of pidfile == running process id
+    # NOTRUN = no pidfile, no running process
+
+    # check if pidfile exists and larger than 0 bytes
+    if [ -s $OCF_RESKEY_pid ]; then
+        # it does, now check if the pid exists
+        pid=$(cat $OCF_RESKEY_pid)
+        ocf_run kill -s 0 $pid
+        rc=$?
+        if [ $rc -eq 0 ]; then
+            ocf_log info "Pound is running"
+            # check if the poundctl
+            ocf_run $OCF_RESKEY_ctl_binary -c $OCF_RESKEY_socket_path
+            p_rc=$?
+            if [ "$p_rc" -eq 0 ]; then
+                ocf_log info "poundctl reports success"
+                return $OCF_SUCCESS
+            else
+                ocf_log err "poundctl reports error"
+                return $OCF_ERR_GENERIC
+            fi
+        else
+            ocf_log err "Pound PID file exists, but pound is not running"
+            return $OCF_ERR_GENERIC
+        fi
+    fi
+    
+    return $OCF_NOT_RUNNING
+}
+
+pound_start() {
+    local rc
+    local backend_options
+
+    pound_status
+    rc=$?
+    if [ $rc -eq $OCF_SUCCESS ]; then
+        ocf_log info "Pound already running"
+        return $OCF_SUCCESS
+    fi
+
+    # check configuration before start
+    ocf_run $OCF_RESKEY_binary \
+        -c -f $OCF_RESKEY_config
+    c_rc=$?
+    if [ "$c_rc" -ne 0 ]; then
+        ocf_log err "Pound configuration file is not valid"
+        return $OCF_ERR_CONFIGURED
+    fi 
+
+    if [ -n "$OCF_RESKEY_maxfiles" ]; then
+        ulimit -n $OCF_RESKEY_maxfiles
+        u_rc=$?
+        if [ "$u_rc" -ne 0 ]; then
+           ocf_log warn "Could not set ulimit for open files for Pound to '$OCF_RESKEY_maxfiles'"
+        fi
+    fi
+
+    ocf_run $OCF_RESKEY_binary \
+        -f $OCF_RESKEY_config \
+        -p $OCF_RESKEY_pid
+    rc=$?
+    if [ $rc -ne 0 ]; then
+        ocf_log err "Pound failed to start"
+        return $OCF_ERR_GENERIC
+    fi
+
+    # Spin waiting for pound to come up.
+    # Let the CRM/LRM time us out if required
+    while true; do
+        pound_status
+        rc=$?
+        [ $rc -eq $OCF_SUCCESS ] && break
+        if [ $rc -ne $OCF_NOT_RUNNING ]; then
+            ocf_log err "Pound start failed"
+            exit $OCF_ERR_GENERIC
+        fi
+        sleep 2
+    done
+
+    ocf_log info "Pound started succesfully"
+    return $OCF_SUCCESS
+}
+
+pound_stop() {
+    local rc
+    local pid
+
+    pound_status
+    rc=$?
+    if [ $rc -eq $OCF_NOT_RUNNING ]; then
+        ocf_log info "Pound already stopped"
+        return $OCF_SUCCESS
+    fi
+
+    # kill the pound process
+    pid=$(cat $OCF_RESKEY_pid)
+    ocf_run kill -s 0 $pid
+    rc=$?
+
+    if [ $rc -ne 0 ]; then
+        ocf_log warn "Pound pid is not a valid process. Assume it is already stopped"
+        rm -f $OCF_RESKEY_pid
+        return $OCF_SUCCESS
+    fi
+
+    ocf_run kill -s TERM $pid
+    rc=$?
+
+    if [ $rc -ne 0 ]; then
+        ocf_log err "Pound failed to stop"
+        return $OCF_ERR_GENERIC
+    fi
+
+    # stop waiting
+    shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5))
+    count=0
+    while [ $count -lt $shutdown_timeout ]; do
+        # check if process still exists
+        ocf_run kill -s 0 $pid
+        rc=$?
+        if [ $rc -ne 0 ]; then
+            # Pound stopped succesfully, so let's delete the pidfile
+            rm -f $OCF_RESKEY_pid
+            break
+        fi
+        count=$(expr $count + 1)
+        sleep 1
+        ocf_log info "Pound still hasn't stopped yet. Waiting..."
+    done 
+
+    pound_status
+    rc=$?
+    if [ $rc -ne $OCF_NOT_RUNNING ]; then
+        # Poound didn't quit on a SIGTERM, try SIGKILL
+        ocf_log warn "Pound failed to stop after ${shutdown_timeout}s using SIGTERM. Trying SIGKILL..."
+        ocf_run kill -s KILL $pid
+        # delete the pidfile
+        rm -f $OCF_RESKEY_pid
+    fi
+
+    ocf_log info "Pound stopped"
+    return $OCF_SUCCESS
+}
+
+
+pound_validate() {
+    if [ -f $OCF_RESKEY_config ]; then
+        return $OCF_SUCCESS
+    else
+        return $OCF_ERR_INSTALLED
+    fi
+}
+
+
+case $__OCF_ACTION in
+    meta-data)
+        meta_data
+        exit $OCF_SUCCESS
+        ;;
+    start)
+        pound_start
+        ;;
+    stop)
+        pound_stop
+        ;;
+    monitor|status)
+        pound_status
+        ;;
+    validate-all)
+        pound_validate
+        ;;
+    usage|help)
+        pound_usage
+        exit $OCF_SUCCESS
+        ;;
+    *)
+        pound_usage
+        exit $OCF_ERR_UNIMPLEMENTED
+        ;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
+
diff --git a/heartbeat/proftpd b/heartbeat/proftpd
new file mode 100755
index 0000000..38c4dcf
--- /dev/null
+++ b/heartbeat/proftpd
@@ -0,0 +1,301 @@
+#!/bin/sh
+#
+# Resource script for Proftpd
+#
+# Description:  Manages Proftpd as an OCF resource in 
+#		an Active-Passive High Availability setup.
+#
+# Author:	Rajat Upadhyaya <urajat at novell.com> : Pure-FTPd script 
+# Author:	Achim Stumpf <hakim.news at googlemail.com> : Rewrite as Proftpd
+# License:      GNU General Public License (GPL) 
+#
+#
+#	usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+#
+#	The "start" arg starts Proftpd.
+#
+#	The "stop" arg stops it.
+#
+# OCF parameters:
+#  OCF_RESKEY_binary
+#  OCF_RESKEY_conffile
+#  OCF_RESKEY_pidfile
+#  OCF_RESKEY_curl_binary
+#  OCF_RESKEY_curl_url
+#  OCF_RESKEY_test_user
+#  OCF_RESKEY_test_pass
+#
+##########################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+: ${OCF_RESKEY_binary="/usr/sbin/proftpd"}
+: ${OCF_RESKEY_conffile="/etc/proftpd.conf"}
+: ${OCF_RESKEY_pidfile="/var/run/proftpd.pid"}
+: ${OCF_RESKEY_curl_binary="/usr/bin/curl"}
+: ${OCF_RESKEY_curl_url="ftp://localhost/"}
+: ${OCF_RESKEY_test_user="test"}
+: ${OCF_RESKEY_test_pass=""}
+
+USAGE="Usage: $0 {start|stop|status|monitor|validate-all|meta-data}";
+
+##########################################################################
+
+usage() {
+	echo $USAGE >&2
+}
+
+meta_data() {
+        cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="proftpd">
+<version>1.0</version>
+<longdesc lang="en">
+This script manages Proftpd in an Active-Passive setup
+</longdesc>
+<shortdesc lang="en">OCF Resource Agent compliant FTP script.</shortdesc>
+
+<parameters>
+
+<parameter name="binary" unique="0" required="0">
+<longdesc lang="en">The Proftpd binary</longdesc>
+<shortdesc lang="en">The Proftpd binary</shortdesc>
+<content type="string" default="/usr/sbin/proftpd" />
+</parameter>
+
+<parameter name="conffile" unique="0" required="0">
+<longdesc lang="en">
+The Proftpd configuration file name with full path. 
+For example, "/etc/proftpd.conf"
+</longdesc>
+<shortdesc lang="en">Configuration file name with full path</shortdesc>
+<content type="string" default="/etc/proftpd.conf" />
+</parameter>
+
+<parameter name="pidfile" unique="0" required="0">
+<longdesc lang="en">The Proftpd PID file. The location of the PID file is configured in the Proftpd configuration file.</longdesc>
+<shortdesc lang="en">PID file</shortdesc>
+<content type="string" default="/var/run/proftpd.pid" />
+</parameter>
+
+<parameter name="curl_binary" unique="0" required="0">
+<longdesc lang="en">The absolute path to the curl binary for monitoring with OCF_CHECK_LEVEL greater zero.</longdesc>
+<shortdesc lang="en">The absolute path to the curl binary</shortdesc>
+<content type="string" default="/usr/bin/curl" />
+</parameter>
+
+<parameter name="curl_url" unique="0" required="0">
+<longdesc lang="en">The URL which is checked by curl with OCF_CHECK_LEVEL greater zero.</longdesc>
+<shortdesc lang="en">The URL which is checked by curl</shortdesc>
+<content type="string" default="ftp://localhost/" />
+</parameter>
+
+<parameter name="test_user" unique="0" required="0">
+<longdesc lang="en">The name of the ftp user for monitoring with OCF_CHECK_LEVEL greater zero.</longdesc>
+<shortdesc lang="en">The name of the ftp user</shortdesc>
+<content type="string" default="test" />
+</parameter>
+
+<parameter name="test_pass" unique="0" required="0">
+<longdesc lang="en">The password of the ftp user for monitoring with OCF_CHECK_LEVEL greater zero.</longdesc>
+<shortdesc lang="en">The password of the ftp user</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" depth="0"  timeout="20s" interval="60s" />
+<action name="monitor" depth="10"  timeout="20s" interval="120s" />
+<action name="validate-all"  timeout="20s" />
+<action name="meta-data"  timeout="5s" />
+</actions>
+</resource-agent>
+END
+        exit $OCF_SUCCESS
+}
+
+isRunning()
+{
+	kill -s 0 "$1" > /dev/null 2>&1
+}
+
+proftpd_status()
+{
+	if [ -f "$OCF_RESKEY_pidfile" ]
+	then
+	# Proftpd is probably running
+		PID=`head -n 1 $OCF_RESKEY_pidfile`
+		if [ ! -z "$PID" ] ; then
+			isRunning "$PID" && `ps -p $PID | grep proftpd > /dev/null 2>&1`
+			return $?
+		fi
+	fi
+	
+	# Proftpd is not running
+	return $OCF_NOT_RUNNING;
+}
+
+proftpd_start()
+{
+	# make a few checks and start Proftpd
+  	if ocf_is_root ; then : ; else
+		ocf_log err "You must be root"
+		exit $OCF_ERR_PERM
+	fi
+	
+	# if Proftpd is running return success
+	if proftpd_status ; then
+		ocf_log info "Proftpd is running already"
+		exit $OCF_SUCCESS
+	fi
+
+	# starting Proftpd
+	${OCF_RESKEY_binary} --config ${OCF_RESKEY_conffile} 2>/dev/null
+
+	if [ "$?" -ne 0 ]; then
+		ocf_log err "Proftpd returned error" $?
+		exit $OCF_ERR_GENERIC
+	fi
+
+	exit $OCF_SUCCESS
+}
+
+
+proftpd_stop()
+{
+	if proftpd_status ; then
+		PID=`head -n 1 $OCF_RESKEY_pidfile`
+		if [ ! -z "$PID" ]; then
+			ocf_log info "Killing Proftpd PID $PID"
+			kill $PID > /dev/null 2>&1 
+			if [ "$?" -eq 0 ]; then
+				TRIES=0
+				while isRunning "$PID" && [ "$TRIES" -lt 30 ]
+				do
+					sleep 1
+					ocf_log info "Proftpd PID $PID is still running"
+					TRIES=`expr $TRIES + 1`
+				done
+				isRunning "$PID"
+				RET=$?
+				if [ "$RET" -eq 0 ]; then
+					ocf_log info "Killing Proftpd PID $PID with SIGKILL"
+					kill -s 9 $PID > /dev/null 2>&1
+					while isRunning "$PID" 
+					do
+						sleep 1
+						ocf_log info "Proftpd PID $PID is still running"
+					done
+				fi
+			else
+				ocf_log err "Killing Proftpd PID $PID FAILED"
+				exit $OCF_ERR_GENERIC
+			fi	
+		fi
+	fi
+
+	exit $OCF_SUCCESS
+}
+
+proftpd_monitor()
+{
+	proftpd_status
+	RET=$?
+
+	if [ "$RET" -ne 0 -o "$OCF_CHECK_LEVEL" = 0 ]; then	
+		if [ "$RET" -eq 0 ]; then
+			PID=`head -n 1 $OCF_RESKEY_pidfile`
+			ocf_log debug "Proftpd monitor on PID $PID succeeded"
+			return $OCF_SUCCESS
+		else
+			ocf_log debug "Proftpd monitor on PID $PID failed"
+			return $OCF_NOT_RUNNING
+		fi
+	else
+		${OCF_RESKEY_curl_binary} -sS -u "${OCF_RESKEY_test_user}:${OCF_RESKEY_test_pass}" ${OCF_RESKEY_curl_url} > /dev/null 2>&1
+		if [ "$?" -eq 0 ]; then
+			ocf_log debug "Proftpd monitor with curl on URL $OCF_RESKEY_curl_url succeeded"
+			return $OCF_SUCCESS
+		else
+			ocf_log err "Proftpd monitor with curl on URL $OCF_RESKEY_curl_url failed"
+			return $OCF_NOT_RUNNING
+		fi
+	fi
+}
+
+proftpd_validate_all()
+{
+
+	# check that the proftpd binary exists
+	if [ ! -x "$OCF_RESKEY_binary" ]; then
+		ocf_log err "Proftpd binary $OCF_RESKEY_binary does not exist"
+		exit $OCF_ERR_INSTALLED
+	fi	
+
+	# check that the Proftpd config file exists
+	if [ ! -f "$OCF_RESKEY_conffile" ]; then
+		ocf_log err "Proftpd config file $OCF_RESKEY_conffile does not exist"
+		exit $OCF_ERR_CONFIGURED
+	fi
+
+	# check that the curl binary exists
+	if [ ! -x "$OCF_RESKEY_curl_binary" ]; then
+		ocf_log err "$OCF_RESKEY_curl_binary does not exist"
+		exit $OCF_ERR_INSTALLED
+	fi
+}
+
+#
+# Main
+#
+
+if [ $# -ne 1 ]
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+case $1 in
+    start)	proftpd_validate_all
+			proftpd_start
+			;;
+	
+    stop)	proftpd_stop
+    		;;
+		
+    status)	if proftpd_status
+    		then
+				ocf_log info "Proftpd is running"
+				exit $OCF_SUCCESS
+			else
+				ocf_log info "Proftpd is stopped"
+				exit $OCF_NOT_RUNNING
+			fi
+    		;;
+		
+    monitor)	proftpd_monitor
+    			exit $?
+    			;;
+		
+    validate-all)	proftpd_validate_all
+					exit $OCF_SUCCESS
+    				;;
+			
+    meta-data)	meta_data
+  				;;
+		
+    usage)	usage
+    		exit $OCF_SUCCESS
+			;;
+		
+    *)	usage
+ 		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+
diff --git a/heartbeat/ra-api-1.dtd b/heartbeat/ra-api-1.dtd
new file mode 100644
index 0000000..0a0a889
--- /dev/null
+++ b/heartbeat/ra-api-1.dtd
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!ELEMENT resource-agent (version,longdesc,shortdesc,parameters?,actions) >
+<!ATTLIST resource-agent
+        name    CDATA   #REQUIRED
+        version CDATA   #IMPLIED>
+
+<!ELEMENT version (#PCDATA)>
+
+<!ELEMENT parameters (parameter*)>
+
+<!ELEMENT actions (action*)>
+
+<!ELEMENT parameter (longdesc+,shortdesc+,content)>
+<!ATTLIST parameter
+        name    CDATA   #REQUIRED
+        required  (1|0)   "0"
+        unique  (1|0)   "0">
+
+<!ELEMENT longdesc ANY>
+<!ATTLIST longdesc
+        lang    NMTOKEN #IMPLIED>
+
+<!ELEMENT shortdesc ANY>
+<!ATTLIST shortdesc
+        lang    NMTOKEN #IMPLIED>
+
+<!ELEMENT content EMPTY>
+<!ATTLIST content
+        type    (string|integer|boolean|time)        #REQUIRED
+        default CDATA   #IMPLIED>
+
+<!ELEMENT action EMPTY>
+<!ATTLIST action
+        name (start|stop|recover|monitor|restart|migrate_to|migrate_from|promote|demote|notify|status|reload|meta-data|usage|methods|validate-all) #REQUIRED
+        timeout         CDATA   #REQUIRED
+        interval        CDATA   #IMPLIED
+        start-delay     CDATA   #IMPLIED
+        role            CDATA   #IMPLIED
+        depth           CDATA   #IMPLIED>
diff --git a/heartbeat/rsyncd b/heartbeat/rsyncd
new file mode 100755
index 0000000..b8cdeb7
--- /dev/null
+++ b/heartbeat/rsyncd
@@ -0,0 +1,270 @@
+#!/bin/sh
+#
+# Resource script for rsync daemon
+#
+# Description:  Manages rsync daemon as an OCF resource in 
+#               an High Availability setup.
+#
+# Author: Dhairesh Oza <odhairesh at novell.com>
+# License: GNU General Public License (GPL) 
+#
+#
+#	usage: $0 {start|stop|status|monitor|validate-all|meta-data}
+#
+#	The "start" arg starts rsyncd.
+#
+#	The "stop" arg stops it.
+#
+# OCF parameters:
+# OCF_RESKEY_binpath
+# OCF_RESKEY_conffile
+# OCF_RESKEY_bwlimit
+#
+# Note:This RA requires that the rsyncd config files has a "pid file" 
+# entry so that it is able to act on the correct process
+##########################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+USAGE="Usage: $0 {start|stop|status|monitor|validate-all|meta-data}";
+
+##########################################################################
+
+usage() 
+{
+	echo $USAGE >&2
+}
+
+meta_data() 
+{
+cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="rsyncd">
+<version>1.0</version>
+<longdesc lang="en">
+This script manages rsync daemon
+</longdesc>
+<shortdesc lang="en">Manages an rsync daemon</shortdesc>
+
+<parameters>
+
+<parameter name="binpath">
+<longdesc lang="en">
+The rsync binary path.
+For example, "/usr/bin/rsync"
+</longdesc>
+<shortdesc lang="en">Full path to the rsync binary</shortdesc>
+<content type="string" default="rsync"/>
+</parameter>
+
+<parameter name="conffile">
+<longdesc lang="en">
+The rsync daemon configuration file name with full path. 
+For example, "/etc/rsyncd.conf"
+</longdesc>
+<shortdesc lang="en">Configuration file name with full path</shortdesc>
+<content type="string" default="/etc/rsyncd.conf" />
+</parameter>
+
+<parameter name="bwlimit">
+<longdesc lang="en">
+This  option allows you to specify a maximum transfer 
+rate in kilobytes per second.  This  option  is
+most  effective  when  using rsync with large files
+(several megabytes and up). Due to  the  nature  of
+rsync  transfers,  blocks of data are sent, then if
+rsync determines the transfer was too fast, it will
+wait before sending the next data block. The result
+is an average transfer rate equaling the  specified
+limit. A value of zero specifies no limit.
+</longdesc>
+<shortdesc lang="en">limit I/O bandwidth, KBytes per second</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="20s"/>
+<action name="stop" timeout="20s"/>
+<action name="monitor" depth="0" timeout="20s" interval="60s" />
+<action name="validate-all" timeout="20s"/>
+<action name="meta-data"  timeout="5s"/>
+</actions>
+</resource-agent>
+END
+exit $OCF_SUCCESS
+}
+
+get_pid_and_conf_file()
+{
+	if [ -n "$OCF_RESKEY_conffile" ]; then
+		CONF_FILE=$OCF_RESKEY_conffile
+	else
+		CONF_FILE="/etc/rsyncd.conf"
+	fi
+               
+	grep -v "^#" "$CONF_FILE" | grep "pid file" > /dev/null
+	if [ $? -eq 0 ]; then
+		PIDFILE=`grep -v "^#" "$CONF_FILE" | grep "pid file" | awk -F "=" '{ print $2 }'`
+	fi
+}
+
+rsyncd_status()
+{
+	if [ -n "$PIDFILE" -a -f $PIDFILE ]; then
+		# rsync is probably running
+		PID=`cat $PIDFILE`
+		if [ -n "$PID" ]; then
+			if ps -p $PID | grep rsync >/dev/null ; then
+				ocf_log info "rsync daemon running"
+				return $OCF_SUCCESS
+			else
+				ocf_log info "rsync daemon is not running but pid file exists"
+				return $OCF_ERR_GENERIC
+			fi
+		else
+			ocf_log err "PID file empty!"
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+		
+	# rsyncd is not running
+	ocf_log info "rsync daemon is not running"
+	return $OCF_NOT_RUNNING
+}
+
+rsyncd_start()
+{
+	# if rsyncd is running return success
+	rsyncd_status
+	retVal=$?
+	if [ $retVal -eq $OCF_SUCCESS ]; then
+		exit $OCF_SUCCESS
+	elif [ $retVal -ne $OCF_NOT_RUNNING ]; then
+		ocf_log err "Error. Unknown status."
+		exit $OCF_ERR_GENERIC
+	fi
+
+	if [ -n "$OCF_RESKEY_binpath" ]; then
+		COMMAND="$OCF_RESKEY_binpath --daemon"
+	else
+		COMMAND="rsync --daemon"
+	fi
+	if [ -n "$OCF_RESKEY_conffile" ]; then
+		COMMAND="$COMMAND --config $OCF_RESKEY_conffile"
+	fi
+	if [ -n "$OCF_RESKEY_bwlimit" ]; then
+		COMMAND="$COMMAND --bwlimit $OCF_RESKEY_bwlimit"
+	fi
+
+	if  grep -v "^#" "$CONF_FILE" | grep "pid file" > /dev/null ; then
+		$COMMAND;
+		if [ $? -ne 0 ]; then
+			ocf_log err "Error. rsycn daemon returned error $?."
+			exit $OCF_ERR_GENERIC
+		fi
+	else
+		ocf_log err "Error. \"pid file\" entry required in the rsyncd config file by rsyncd OCF RA."
+		return $OCF_ERR_GENERIC
+	fi
+
+	ocf_log info "Started rsync daemon."
+	exit $OCF_SUCCESS
+}
+
+
+rsyncd_stop()
+{
+	if rsyncd_status ; then
+		PID=`cat $PIDFILE`
+		if [ -n "$PID" ] ; then
+			kill $PID
+			if [ $? -ne 0 ]; then
+				kill -s KILL $PID
+				if [ $? -ne 0 ]; then
+					ocf_log err "Error. Could not stop rsync daemon."
+					return $OCF_ERR_GENERIC
+				fi
+			fi
+			rm $PIDFILE 2>/dev/null
+		fi
+	fi
+	ocf_log info "Stopped rsync daemon."
+	exit $OCF_SUCCESS
+}
+
+rsyncd_monitor()
+{
+	rsyncd_status
+}
+
+rsyncd_validate_all()
+{
+	if [ -n "$OCF_RESKEY_binpath" -a ! -x "$OCF_RESKEY_binpath" ]; then
+		ocf_log err "Binary path $OCF_RESKEY_binpath does not exist."
+		exit $OCF_ERR_ARGS
+	fi
+	if [ -n "$OCF_RESKEY_conffile" -a ! -f "$OCF_RESKEY_conffile" ]; then
+		ocf_log err "Config file $OCF_RESKEY_conffile does not exist."
+		exit $OCF_ERR_ARGS
+	fi
+
+	if  grep -v "^#" "$CONF_FILE" | grep "pid file" > /dev/null ; then
+		:
+	else
+		ocf_log err "Error. \"pid file\" entry required in the rsyncd config file by rsyncd OCF RA."
+		return $OCF_ERR_GENERIC
+	fi
+
+#Not checking "$OCF_RESKEY_bwlimit"
+
+	return $OCF_SUCCESS
+}
+
+
+#
+# Main
+#
+ 
+if [ $# -ne 1 ]; then
+	usage
+	exit $OCF_ERR_ARGS
+fi
+
+case $1 in
+	start)	get_pid_and_conf_file
+		rsyncd_start
+		;;
+	
+	stop)	get_pid_and_conf_file
+		rsyncd_stop
+		;;
+
+	status)	get_pid_and_conf_file
+		rsyncd_status
+		;;
+
+	monitor)get_pid_and_conf_file
+		rsyncd_monitor
+		;;
+
+	validate-all)	get_pid_and_conf_file
+			rsyncd_validate_all
+			;;
+
+	meta-data)	meta_data
+			;;
+
+	usage)	usage
+		exit $OCF_SUCCESS
+		;;
+
+	*)	usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+
diff --git a/heartbeat/rsyslog b/heartbeat/rsyslog
new file mode 100755
index 0000000..c538afb
--- /dev/null
+++ b/heartbeat/rsyslog
@@ -0,0 +1,254 @@
+#!/bin/bash
+#
+# Description:  Manages a rsyslog instance, provided by NTT OSSC as an 
+#               OCF High-Availability resource under Heartbeat/LinuxHA control
+#
+# Copyright (c) 2011 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+##############################################################################
+# OCF parameters:
+#   OCF_RESKEY_rsyslog_binary   : Path to rsyslog binary.
+#                                 Default is "/sbin/rsyslogd"
+#   OCF_RESKEY_configfile       : Configuration file
+#   OCF_RESKEY_start_opts       : Startup options
+#
+#   Only OCF_RESKEY_configfile must be specified. Each of the rests 
+#   has its default value or refers OCF_RESKEY_configfile to make
+#   its value when no explicit value is given.
+#
+# Further infomation for setup:
+#   There are sample configurations at the end of this file.
+#
+###############################################################################
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+usage() 
+{
+	cat <<-!
+usage: $0 action
+
+action:
+        start       : start a new rsyslog instance
+
+        stop        : stop the running rsyslog instance
+
+        status      : return the status of rsyslog, run or down
+
+        monitor     : return TRUE if the rsyslog appears to be working.
+
+        meta-data   : show meta data message
+
+        validate-all: validate the instance parameters
+!
+	return $OCF_ERR_UNIMPLEMENTED
+}
+
+metadata_rsyslog()
+{
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="rsyslog">
+<version>1.0</version>
+
+<longdesc lang="en">
+This script manages a rsyslog instance as an HA resource.
+</longdesc>
+<shortdesc lang="en">rsyslog resource agent</shortdesc>
+
+<parameters>
+
+<parameter name="configfile" unique="1" required="1">
+<longdesc lang="en">
+This parameter specifies a configuration file 
+for a rsyslog instance managed by this RA.
+</longdesc>
+<shortdesc>Configuration file</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="rsyslog_binary" unique="0">
+<longdesc lang="en">
+This parameter specifies rsyslog's executable file.
+</longdesc>
+<shortdesc>rsyslog executable</shortdesc>
+<content type="string" default="/sbin/rsyslogd"/>
+</parameter>
+
+<parameter name="start_opts" unique="0">
+<longdesc lang="en">
+This parameter specifies startup options for a 
+rsyslog instance managed by this RA. When no value is given, no startup 
+options is used. Don't use option '-F'. It causes a stuck of a start action.
+</longdesc>
+<shortdesc>Start options</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="20s" />
+<action name="stop" timeout="60s" />
+<action name="status" timeout="20s" />
+<action name="monitor" depth="0" timeout="20s" interval="20s" />
+<action name="meta-data" timeout="5s" />
+<action name="validate-all"  timeout="5"/>
+</actions>
+</resource-agent>
+END
+	return $OCF_SUCCESS
+}
+
+monitor_rsyslog()
+{
+	set -- $(pgrep -f "$PROCESS_PATTERN" 2>/dev/null)
+	case $# in
+		0) ocf_log debug "No rsyslog process for $CONFIGFILE"
+		   return $OCF_NOT_RUNNING;;
+		1) return $OCF_SUCCESS;;
+	esac
+	ocf_log warn "Multiple rsyslog process for $CONFIGFILE"
+	return $OCF_SUCCESS
+}
+
+start_rsyslog()
+{
+	local ocf_status
+	monitor_rsyslog
+	if [ $? = "$OCF_SUCCESS" ]; then
+		return $OCF_SUCCESS
+	fi
+
+	$RSYSLOG_EXE -f $CONFIGFILE $START_OPTS 2>&1
+	ocf_status=$?
+	if [ "$ocf_status" != "$OCF_SUCCESS" ]; then
+		return $OCF_ERR_GENERIC
+	fi
+
+	while true; do
+		monitor_rsyslog
+		if [ $? = "$OCF_SUCCESS" ]; then
+			return $OCF_SUCCESS
+		fi
+		sleep 1
+	done
+}
+
+stop_rsyslog()
+{
+	pkill -TERM -f "$PROCESS_PATTERN"
+
+	typeset lapse_sec=0
+	while pgrep -f "$PROCESS_PATTERN" > /dev/null; do
+		sleep 1
+		lapse_sec=$(( lapse_sec + 1 ))
+		ocf_log debug "stop_rsyslog[${OCF_RESOURCE_INSTANCE}]: stop NORM $lapse_sec/$OCF_RESKEY_CRM_meta_timeout"
+		if [ $lapse_sec -ge $OCF_RESKEY_CRM_meta_timeout ]; then
+			break
+		fi
+	done
+
+	lapse_sec=0
+	while pgrep -f "$PROCESS_PATTERN" > /dev/null; do
+		pkill -KILL -f "$PROCESS_PATTERN"
+		sleep 1
+		lapse_sec=$(( lapse_sec + 1 ))
+		ocf_log debug "stop_rsyslog[${OCF_RESOURCE_INSTANCE}]: suspend rsyslog by SIGKILL ($lapse_sec/@@@)"
+	done
+
+	return $OCF_SUCCESS
+}
+
+status_rsyslog()
+{
+	monitor_rsyslog
+	rc=$?
+	if [ $rc = $OCF_SUCCESS ]; then
+		echo "rsyslog service is running."
+	elif [ $rc = $OCF_NOT_RUNNING ]; then
+		echo "rsyslog service is stopped."
+	fi
+	return $rc
+}
+
+validate_all_rsyslog()
+{
+	ocf_log info "validate_all_rsyslog[${OCF_RESOURCE_INSTANCE}]"
+	return $OCF_SUCCESS
+}
+
+if [[ "$1" = "meta-data" ]]; then
+	metadata_rsyslog
+	exit $?
+fi
+
+CONFIGFILE="${OCF_RESKEY_configfile}"
+if [[ -z "$CONFIGFILE" ]]; then
+	ocf_log err "undefined parameter:configfile"
+	exit $OCF_ERR_CONFIGURED
+fi
+if [[ ! -f "$CONFIGFILE" ]]; then
+	ocf_log err "Config file $CONFIGFILE does not exist."
+	exit $OCF_ERR_CONFIGURED
+fi
+
+RSYSLOG_EXE="${OCF_RESKEY_rsyslog_binary-/sbin/rsyslogd}"
+if [[ ! -x "$RSYSLOG_EXE" ]]; then
+	ocf_log err "Invalid value:rsyslog_binary:$RSYSLOG_EXE"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+START_OPTS=${OCF_RESKEY_start_opts}
+PROCESS_PATTERN="$RSYSLOG_EXE -f $CONFIGFILE"
+
+COMMAND=$1
+
+case "$COMMAND" in
+	start)
+		ocf_log debug "[${OCF_RESOURCE_INSTANCE}] Enter rsyslog start"
+		start_rsyslog
+		func_status=$?
+		ocf_log debug "[${OCF_RESOURCE_INSTANCE}] Leave rsyslog start $func_status"
+		exit $func_status
+		;;
+	stop)
+		ocf_log debug "[${OCF_RESOURCE_INSTANCE}] Enter rsyslog stop"
+		stop_rsyslog
+		func_status=$?
+		ocf_log debug "[${OCF_RESOURCE_INSTANCE}] Leave rsyslog stop $func_status"
+		exit $func_status
+		;;
+	status)
+		status_rsyslog
+		exit $?
+		;;
+	monitor)
+		monitor_rsyslog
+		func_status=$?
+		exit $func_status
+		;;
+	validate-all)
+		validate_all_rsyslog
+		exit $?
+		;;
+	*)
+		usage
+		;;
+esac
diff --git a/heartbeat/sapdb-nosha.sh b/heartbeat/sapdb-nosha.sh
new file mode 100644
index 0000000..c659909
--- /dev/null
+++ b/heartbeat/sapdb-nosha.sh
@@ -0,0 +1,744 @@
+#
+# sapdatabase-nosha - for systems not having SAPHostAgent installed
+# (sourced by SAPDatabase)
+#
+# Description:	this code is separated from the SAPDatabase agent to
+#               be downward compatible and support systems which do
+#               not have SAPHostAgent installed.
+#               It will be removed in a later release completely. 
+#
+# Author:       Alexander Krauth, October 2006
+# Support:      linux at sap.com
+# License:      GNU General Public License (GPL)
+# Copyright:    (c) 2006, 2007 Alexander Krauth
+#
+
+
+trap_handler() {
+  rm -f $TEMPFILE
+  exit $OCF_ERR_GENERIC
+}
+
+
+#
+# listener_start: Start the given listener
+#
+listener_start() {
+  local orasid="ora`echo $SID | tr '[:upper:]' '[:lower:]'`"
+  local lrc=$OCF_SUCCESS
+  local output
+  output=`echo "lsnrctl start $NETSERVICENAME" | su - $orasid 2>&1`
+  if [ $? -eq 0 ]
+  then
+    ocf_log info "Oracle Listener $NETSERVICENAME started: $output"
+    lrc=$OCF_SUCCESS
+  else
+    ocf_log err "Oracle Listener $NETSERVICENAME start failed: $output"
+    lrc=$OCF_ERR_GENERIC
+  fi
+  return $lrc
+}
+
+#
+# listener_stop: Stop the given listener
+#
+listener_stop() {
+  local orasid="ora`echo $SID | tr '[:upper:]' '[:lower:]'`"
+  local lrc=$OCF_SUCCESS
+  if
+      listener_status
+  then
+      : listener is running, trying to stop it later...
+  else
+      return $OCF_SUCCESS
+  fi
+  local output
+  output=`echo "lsnrctl stop $NETSERVICENAME" | su - $orasid 2>&1`
+  if [ $? -eq 0 ]
+  then
+    ocf_log info "Oracle Listener $NETSERVICENAME stopped: $output"
+  else
+    ocf_log err "Oracle Listener $NETSERVICENAME stop failed: $output"
+    lrc=$OCF_ERR_GENERIC
+  fi
+  return $lrc
+}
+
+#
+# listener_status: is the given listener running?
+#
+listener_status() {
+  local lrc=$OCF_SUCCESS
+  local orasid="ora`echo $SID | tr '[:upper:]' '[:lower:]'`"
+  # Note: ps cuts off it's output at column $COLUMNS, so "ps -ef" can not be used here
+  # as the output might be to long.
+  local cnt=`ps efo args --user $orasid | grep $NETSERVICENAME | grep -c tnslsnr`
+  if [ $cnt -eq 1 ]
+  then
+    lrc=$OCF_SUCCESS
+  else
+    ocf_log info "listener process not running for $NETSERVICENAME for $SID"
+    lrc=$OCF_ERR_GENERIC
+  fi
+  return $lrc
+}
+
+#
+# x_server_start: Start the given x_server
+#
+x_server_start() {
+  local rc=$OCF_SUCCESS
+  local output
+  output=`echo "x_server start" | su - $sidadm 2>&1`
+  if [ $? -eq 0 ]
+  then
+    ocf_log info "MaxDB x_server start: $output"
+    lrc=$OCF_SUCCESS
+  else
+    ocf_log err "MaxDB x_server start failed: $output"
+    lrc=$OCF_ERR_GENERIC
+  fi
+  return $lrc
+}
+
+#
+# x_server_stop: Stop the x_server
+#
+x_server_stop() {
+  local lrc=$OCF_SUCCESS
+  local output
+  output=`echo "x_server stop" | su - $sidadm 2>&1`
+  if [ $? -eq 0 ]
+  then
+    ocf_log info "MaxDB x_server stop: $output"
+  else
+    ocf_log err "MaxDB x_server stop failed: $output"
+    lrc=$OCF_ERR_GENERIC
+  fi
+  return $lrc
+}
+
+#
+# x_server_status: is the x_server running?
+#
+x_server_status() {
+  local lrc=$OCF_SUCCESS
+  local sdbuser=`grep "^SdbOwner" /etc/opt/sdb | awk -F'=' '{print $2}'`
+  # Note: ps cuts off it's output at column $COLUMNS, so "ps -ef" can not be used here
+  # as the output might be to long.
+  local cnt=`ps efo args --user $sdbuser | grep -c vserver`
+  if [ $cnt -ge 1 ]
+  then
+    lrc=$OCF_SUCCESS
+  else
+    ocf_log info "x_server process not running"
+    lrc=$OCF_ERR_GENERIC
+  fi
+  return $lrc
+}
+
+#
+# oracle_stop: Stop the Oracle database without any condition
+#
+oracle_stop() {
+echo '#!/bin/sh
+LOG=$HOME/stopdb.log
+date > $LOG
+
+if [ -x "${ORACLE_HOME}/bin/sqlplus" ]
+then
+    SRVMGRDBA_EXE="${ORACLE_HOME}/bin/sqlplus"
+else
+   echo "Can not find executable sqlplus" >> $LOG
+   exit 1
+fi
+
+$SRVMGRDBA_EXE /NOLOG >> $LOG << !
+connect / as sysdba
+shutdown immediate
+exit
+!
+rc=$?
+cat $LOG
+exit $rc' > $TEMPFILE
+
+chmod 700 $TEMPFILE
+chown $sidadm $TEMPFILE
+
+su - $sidadm -c $TEMPFILE
+retcode=$?
+rm -f $TEMPFILE
+
+if [ $retcode -eq 0 ]; then
+  sapdatabase_status
+  if [ $? -ne $OCF_NOT_RUNNING ]; then
+    retcode=1
+  fi
+fi
+
+return $retcode
+}
+
+#
+# maxdb_stop: Stop the MaxDB database without any condition
+#
+maxdb_stop() {
+
+# x_Server must be running to stop database
+x_server_status
+if [ $? -ne $OCF_SUCCESS ]; then x_server_start; fi
+
+if [ $DBJ2EE_ONLY -eq 1 ]; then
+   userkey=c_J2EE
+else
+   userkey=c
+fi
+
+echo "#!/bin/sh
+LOG=\$HOME/stopdb.log
+date > \$LOG
+echo \"Stop database with xuserkey >$userkey<\" >> \$LOG
+dbmcli -U ${userkey} db_offline >> \$LOG 2>&1
+exit \$?" > $TEMPFILE
+
+chmod 700 $TEMPFILE
+chown $sidadm $TEMPFILE
+
+su - $sidadm -c $TEMPFILE
+retcode=$?
+rm -f $TEMPFILE
+
+if [ $retcode -eq 0 ]; then
+  sapdatabase_status
+  if [ $? -ne $OCF_NOT_RUNNING ]; then
+    retcode=1
+  fi
+fi
+
+return $retcode
+}
+
+#
+# db6udb_stop: Stop the DB2/UDB database without any condition
+#
+db6udb_stop() {
+echo '#!/bin/sh
+LOG=$HOME/stopdb.log
+date > $LOG
+echo "Shut down the database" >> $LOG
+$INSTHOME/sqllib/bin/db2 deactivate database $DB2DBDFT |tee -a $LOG  2>&1
+$INSTHOME/sqllib/adm/db2stop force |tee -a $LOG  2>&1
+exit $?' > $TEMPFILE
+
+chmod 700 $TEMPFILE
+chown $sidadm $TEMPFILE
+
+su - $sidadm -c $TEMPFILE
+retcode=$?
+rm -f $TEMPFILE
+
+if [ $retcode -eq 0 ]; then
+  sapdatabase_status
+  if [ $? -ne $OCF_NOT_RUNNING ]; then
+    retcode=1
+  fi
+fi
+
+return $retcode
+}
+
+#
+# oracle_recover: try to clean up oracle after a crash
+#
+oracle_recover() {
+echo '#!/bin/sh
+LOG=$HOME/recover.log
+date > $LOG
+echo "Logfile written by heartbeat SAPDatabase resource agent" >> $LOG
+
+if [ -x "${ORACLE_HOME}/bin/sqlplus" ]
+then
+    SRVMGRDBA_EXE="${ORACLE_HOME}/bin/sqlplus"
+else
+   echo "Can not find executable sqlplus" >> $LOG
+   exit 1
+fi
+
+$SRVMGRDBA_EXE /NOLOG >> $LOG << !
+connect / as sysdba
+shutdown abort
+startup mount
+alter database end backup;
+alter database open;
+exit
+!
+rc=$?
+cat $LOG
+exit $rc' > $TEMPFILE
+
+  chmod 700 $TEMPFILE
+  chown $sidadm $TEMPFILE
+
+  su - $sidadm -c $TEMPFILE
+  retcode=$?
+  rm -f $TEMPFILE
+
+  return $retcode
+}
+
+#
+# maxdb_recover: try to clean up MaxDB after a crash
+#
+maxdb_recover() {
+  # x_Server must be running to stop database
+  x_server_status
+  if [ $? -ne $OCF_SUCCESS ]; then x_server_start; fi
+
+  if [ $DBJ2EE_ONLY -eq 1 ]; then
+     userkey=c_J2EE
+  else
+     userkey=c
+  fi
+
+echo "#!/bin/sh
+LOG=\$HOME/recover.log
+date > \$LOG
+echo \"Logfile written by heartbeat SAPDatabase resource agent\" >> \$LOG
+echo \"Cleanup database with xuserkey >$userkey<\" >> \$LOG
+echo \"db_stop\" >> \$LOG 2>&1
+dbmcli -U ${userkey} db_stop >> \$LOG 2>&1
+echo \"db_clear\" >> \$LOG 2>&1
+dbmcli -U ${userkey} db_clear >> \$LOG 2>&1
+echo \"db_online\" >> \$LOG 2>&1
+dbmcli -U ${userkey} db_online >> \$LOG 2>&1
+rc=\$?
+cat \$LOG
+exit \$rc" > $TEMPFILE
+
+  chmod 700 $TEMPFILE
+  chown $sidadm $TEMPFILE
+
+  su - $sidadm -c $TEMPFILE
+  retcode=$?
+  rm -f $TEMPFILE
+
+  return $retcode
+}
+
+#
+# db6udb_recover: try to recover DB/2 after a crash
+#
+db6udb_recover() {
+  db2sid="db2`echo $SID | tr '[:upper:]' '[:lower:]'`"
+
+echo '#!/bin/sh
+LOG=$HOME/recover.log
+date > $LOG
+echo "Logfile written by heartbeat SAPDatabase resource agent" >> $LOG
+$INSTHOME/sqllib/bin/db2_kill >> $LOG  2>&1
+$INSTHOME/sqllib/adm/db2start >> $LOG  2>&1
+$INSTHOME/sqllib/bin/db2 activate database $DB2DBDFT >> $LOG  2>&1
+rc=$?
+cat $LOG
+exit $rc' > $TEMPFILE
+
+  chmod 700 $TEMPFILE
+  chown $db2sid $TEMPFILE
+
+  su - $db2sid -c $TEMPFILE
+  retcode=$?
+  rm -f $TEMPFILE
+
+  return $retcode
+}
+
+
+#
+# sapdatabase_start : Start the SAP database
+#
+sapdatabase_start() {
+  sapuserexit PRE_START_USEREXIT "$OCF_RESKEY_PRE_START_USEREXIT"
+
+  case $DBTYPE in
+    ADA) x_server_start
+         ;;
+    ORA) listener_start
+         ;;
+  esac
+
+  output=`su - $sidadm -c $SAPSTARTDB`
+  rc=$?
+
+  if [ $DBJ2EE_ONLY -eq 1 ]
+  then
+    sapdatabase_monitor 1
+    rc=$?
+  fi
+
+  if [ $rc -ne 0 -a $OCF_RESKEY_AUTOMATIC_RECOVER -eq 1 ]
+  then
+    ocf_log warn "SAP database $SID start failed: $output"
+    ocf_log warn "Try to recover database $SID"
+
+    output=''
+    sapdatabase_recover
+    rc=$?
+  fi
+
+  if [ $rc -eq 0 ]
+  then
+    ocf_log info "SAP database $SID started: $output"
+    rc=$OCF_SUCCESS
+    sapuserexit POST_START_USEREXIT "$OCF_RESKEY_POST_START_USEREXIT"
+  else
+    ocf_log err "SAP database $SID start failed: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+
+  return $rc
+}
+
+#
+# sapdatabase_stop: Stop the SAP database
+#
+sapdatabase_stop() {
+
+  sapuserexit PRE_STOP_USEREXIT "$OCF_RESKEY_PRE_STOP_USEREXIT"
+
+  # use of the stopdb kernel script is not possible, because there are to may checks in that
+  # script. We want to stop the database regardless of anything.
+  #output=`su - $sidadm -c $SAPSTOPDB`
+
+  case $DBTYPE in
+    ORA) output=`oracle_stop`
+         ;;
+    ADA) output=`maxdb_stop`
+         ;;
+    DB6) output=`db6udb_stop`
+         ;;
+  esac
+
+  if [ $? -eq 0 ]
+  then
+    ocf_log info "SAP database $SID stopped: $output"
+    rc=$OCF_SUCCESS
+  else
+    ocf_log err "SAP database $SID stop failed: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+
+  case $DBTYPE in
+    ORA) listener_stop
+         ;;
+    ADA) x_server_stop
+         ;;
+  esac
+
+  sapuserexit POST_STOP_USEREXIT "$OCF_RESKEY_POST_STOP_USEREXIT"
+
+  return $rc
+}
+
+
+#
+# sapdatabase_monitor: Can the given database instance do anything useful?
+#
+sapdatabase_monitor() {
+  strict=$1
+
+  sapdatabase_status
+  rc=$?
+  if [ $rc -ne $OCF_SUCCESS ]; then
+    return $rc
+  fi
+
+  case $DBTYPE in
+    ADA) x_server_status 
+         if [ $? -ne $OCF_SUCCESS ]; then x_server_start; fi
+         ;;
+    ORA) listener_status
+         if [ $? -ne $OCF_SUCCESS ]; then listener_start; fi
+         ;;
+  esac
+
+  if [ $strict -eq 0 ]
+  then
+    return $rc
+  else
+    if [ $DBJ2EE_ONLY -eq 0 ]
+    then
+      output=`echo "$SAPDBCONNECT -d -w /dev/null" | su $sidadm 2>&1`
+      if [ $? -le 4 ]
+      then
+        rc=$OCF_SUCCESS
+      else
+        rc=$OCF_NOT_RUNNING
+      fi
+    else
+      MYCP=""
+      EXECMD=""
+
+      # WebAS Java 6.40+7.00
+      IAIK_JCE="$SECSTORE"/iaik_jce.jar
+      IAIK_JCE_EXPORT="$SECSTORE"/iaik_jce_export.jar
+      EXCEPTION="$BOOTSTRAP"/exception.jar
+      LOGGING="$BOOTSTRAP"/logging.jar
+      OPENSQLSTA="$BOOTSTRAP"/opensqlsta.jar
+      TC_SEC_SECSTOREFS="$BOOTSTRAP"/tc_sec_secstorefs.jar
+      JDDI="$BOOTSTRAP"/../server0/bin/ext/jdbdictionary/jddi.jar
+      ANTLR="$BOOTSTRAP"/../server0/bin/ext/antlr/antlr.jar
+      FRAME="$BOOTSTRAP"/../server0/bin/system/frame.jar
+  
+      # only start jdbcconnect when all jars available
+      if [ -f "$EXCEPTION" -a -f "$LOGGING" -a -f "$OPENSQLSTA" -a -f "$TC_SEC_SECSTOREFS" -a -f "$JDDI" -a -f "$ANTLR" -a -f "$FRAME" -a -f "$SAPDBCONNECT" ]
+      then
+        MYCP=".:$FRAME:$ANTLR:$JDDI:$IAIK_JCE_EXPORT:$IAIK_JCE:$EXCEPTION:$LOGGING:$OPENSQLSTA:$TC_SEC_SECSTOREFS:$DB_JARS:$SAPDBCONNECT" 
+        EXECMD="com.sap.inst.jdbc.connect.JdbcCon -sec $SID:$SID"
+      else
+      # WebAS Java 7.10
+        LAUNCHER=${BOOTSTRAP}/sap.com~tc~bl~offline_launcher~impl.jar
+
+        if [ -f "$DB_JARS" -a -f "$SAPDBCONNECT" -a -f "$LAUNCHER" ]
+        then
+          MYCP="$LAUNCHER"
+          EXECMD="com.sap.engine.offline.OfflineToolStart com.sap.inst.jdbc.connect.JdbcCon ${SAPDBCONNECT}:${SECSTORE}:${DB_JARS}:${BOOTSTRAP} -sec $SID:$SID"
+        fi
+      fi
+
+      if [ -n "$EXECMD" ]
+      then
+        output=`${JAVA_HOME}/bin/java -cp $MYCP $EXECMD 2> /dev/null`
+        if [ $? -le 0 ]
+        then
+          rc=$OCF_SUCCESS
+        else
+          rc=$OCF_NOT_RUNNING
+        fi
+      else
+        output="Cannot find all jar files needed for database monitoring."
+        rc=$OCF_ERR_GENERIC
+      fi
+    fi
+  fi
+
+  if [ $rc -ne $OCF_SUCCESS ]
+  then
+    ocf_log err "The SAP database $SID ist not running: $output"
+  fi
+  return $rc
+}
+
+
+#
+# sapdatabase_status: Are there any database processes on this host ?
+#
+sapdatabase_status() {
+  case $DBTYPE in
+    ADA) SEARCH="$SID/db/pgm/kernel"
+         SUSER=`grep "^SdbOwner" /etc/opt/sdb | awk -F'=' '{print $2}'`
+         SNUM=2
+         ;;
+    ORA) SEARCH="ora_[a-z][a-z][a-z][a-z]_"
+         SUSER="ora`echo $SID | tr '[:upper:]' '[:lower:]'`"
+         SNUM=4
+         ;;
+    DB6) SEARCH="db2[a-z][a-z][a-z]"
+         SUSER="db2`echo $SID | tr '[:upper:]' '[:lower:]'`"
+         SNUM=2
+         ;;
+  esac
+
+  # Note: ps cuts off it's output at column $COLUMNS, so "ps -ef" can not be used here
+  # as the output might be to long.
+  cnt=`ps efo args --user $SUSER 2> /dev/null | grep -c "$SEARCH"`
+  if [ $cnt -ge $SNUM ]
+  then
+    rc=$OCF_SUCCESS
+  else
+    # ocf_log info "Database Instance $SID is not running on `hostname`"
+    rc=$OCF_NOT_RUNNING
+  fi
+  return $rc
+}
+
+
+#
+# sapdatabase_recover:
+#
+sapdatabase_recover() {
+
+  case $DBTYPE in
+    ORA) recoutput=`oracle_recover`
+         ;;
+    ADA) recoutput=`maxdb_recover`
+         ;;
+    DB6) recoutput=`db6udb_recover`
+         ;;
+  esac
+
+  sapdatabase_monitor 1
+  retcode=$?
+
+  if [ $retcode -eq $OCF_SUCCESS ]
+  then
+    ocf_log info "Recover of SAP database $SID was successful: $recoutput"
+  else
+    ocf_log err "Recover of SAP database $SID failed: $recoutput"
+  fi
+
+  return $retcode
+}
+
+
+#
+# sapdatabase_validate: Check the symantic of the input parameters 
+#
+sapdatabase_validate() {
+  rc=$OCF_SUCCESS
+  if [ `echo "$SID" | grep -c '^[A-Z][A-Z0-9][A-Z0-9]$'` -ne 1 ]
+  then
+    ocf_log err "Parsing parameter SID: '$SID' is not a valid system ID!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  case "$DBTYPE" in
+   ORA|ADA|DB6) ;;
+   *) ocf_log err "Parsing parameter DBTYPE: '$DBTYPE' is not a supported database type!"
+      rc=$OCF_ERR_ARGS ;;
+  esac
+
+  return $rc
+}
+
+
+#
+# sapdatabase_init: initialize global variables at the beginning
+#
+sapdatabase_init() {
+
+ocf_log warn "Usage of SAPDatabase resource agent without SAPHostAgent is deprecated. Please read documentation of SAPDatabase resource agent and follow SAP note 1031096 for the installation of SAPHostAgent."
+
+# optional OCF parameters, we try to guess which directories are correct
+EXESTARTDB="startdb"
+EXESTOPDB="stopdb"
+EXEDBCONNECT="R3trans"
+if [ -z "$OCF_RESKEY_DBJ2EE_ONLY" ]; then
+  DBJ2EE_ONLY=0
+else
+  case "$OCF_RESKEY_DBJ2EE_ONLY" in
+   1|true|TRUE|yes|YES) DBJ2EE_ONLY=1
+                        EXESTARTDB="startj2eedb"
+                        EXESTOPDB="stopj2eedb"
+                        EXEDBCONNECT="jdbcconnect.jar"
+                        ;;
+   0|false|FALSE|no|NO) DBJ2EE_ONLY=0;;
+   *) ocf_log err "Parsing parameter DBJ2EE_ONLY: '$DBJ2EE_ONLY' is not a boolean value!"
+      exit $OCF_ERR_ARGS ;;
+  esac
+fi
+
+if [ -z "$OCF_RESKEY_NETSERVICENAME" ]; then
+  case "$DBTYPE" in
+    ORA|ora) NETSERVICENAME="LISTENER";;
+    *)       NETSERVICENAME="";;
+  esac
+else
+  NETSERVICENAME="$OCF_RESKEY_NETSERVICENAME"
+fi
+
+if [ -z "$OCF_RESKEY_STRICT_MONITORING" ]; then
+  OCF_RESKEY_STRICT_MONITORING=0
+else
+  case "$OCF_RESKEY_STRICT_MONITORING" in
+   1|true|TRUE|yes|YES) OCF_RESKEY_STRICT_MONITORING=1;;
+   0|false|FALSE|no|NO) OCF_RESKEY_STRICT_MONITORING=0;;
+   *)  ocf_log err "Parsing parameter STRICT_MONITORING: '$OCF_RESKEY_STRICT_MONITORING' is not a boolean value!"
+       exit $OCF_ERR_ARGS ;;
+  esac
+fi
+
+PATHLIST="
+$OCF_RESKEY_DIR_EXECUTABLE
+/usr/sap/$SID/*/exe
+/usr/sap/$SID/SYS/exe/run
+/sapmnt/$SID/exe
+"
+DIR_EXECUTABLE=""
+for EXEPATH in $PATHLIST
+do
+  if [ -x $EXEPATH/$EXESTARTDB -a -x $EXEPATH/$EXESTOPDB -a -x $EXEPATH/$EXEDBCONNECT ]
+  then
+    DIR_EXECUTABLE=$EXEPATH
+    SAPSTARTDB=$EXEPATH/$EXESTARTDB
+    SAPSTOPDB=$EXEPATH/$EXESTOPDB
+    SAPDBCONNECT=$EXEPATH/$EXEDBCONNECT
+    break
+  fi
+done
+if [ -z "$DIR_EXECUTABLE" ]
+then
+  ocf_log warn "Cannot find $EXESTARTDB,$EXESTOPDB and $EXEDBCONNECT executable, please set DIR_EXECUTABLE parameter!"
+  exit $OCF_NOT_RUNNING
+fi
+
+if [ $DBJ2EE_ONLY -eq 1 ]
+then
+  if [ -n "$OCF_RESKEY_DIR_BOOTSTRAP" ]
+  then
+    BOOTSTRAP="$OCF_RESKEY_DIR_BOOTSTRAP"
+  else
+    BOOTSTRAP=`ls -1d /usr/sap/$SID/*/j2ee/cluster/bootstrap | head -1`
+  fi
+
+  if [ -n "$OCF_RESKEY_DIR_SECSTORE" ]
+  then
+    SECSTORE="$OCF_RESKEY_DIR_SECSTORE"
+  else
+    SECSTORE=/usr/sap/$SID/SYS/global/security/lib/tools
+  fi
+
+  if [ -n "$OCF_RESKEY_JAVA_HOME" ]
+  then
+    JAVA_HOME="$OCF_RESKEY_JAVA_HOME"
+    PATH=$JAVA_HOME/bin:$PATH
+  else
+    if [ -n "$JAVA_HOME" ]
+    then
+      PATH=$JAVA_HOME/bin:$PATH
+    else
+      ocf_log err "Cannot find JAVA_HOME directory, please set JAVA_HOME parameter!"
+      exit $OCF_NOT_RUNNING
+    fi
+  fi
+
+  if [ -n "$OCF_RESKEY_DB_JARS" ]
+  then
+    DB_JARS=$OCF_RESKEY_DB_JARS
+  else
+    if [ -f "$BOOTSTRAP"/bootstrap.properties ]; then
+      DB_JARS=`cat $BOOTSTRAP/bootstrap.properties | grep -i rdbms.driverLocation | sed -e 's/\\\:/:/g' | awk -F= '{print $2}'`
+    fi
+  fi
+fi
+
+if [ -z "$OCF_RESKEY_AUTOMATIC_RECOVER" ]
+then
+  OCF_RESKEY_AUTOMATIC_RECOVER=0
+else
+  case "$OCF_RESKEY_AUTOMATIC_RECOVER" in
+   1|true|TRUE|yes|YES) OCF_RESKEY_AUTOMATIC_RECOVER=1;;
+   0|false|FALSE|no|NO) OCF_RESKEY_AUTOMATIC_RECOVER=0;;
+  esac
+fi
+
+# as root user we need the library path to the SAP kernel to be able to call executables
+if [ `echo $LD_LIBRARY_PATH | grep -c "^$DIR_EXECUTABLE\>"` -eq 0 ]; then
+  LD_LIBRARY_PATH=$DIR_EXECUTABLE${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH
+  export LD_LIBRARY_PATH
+fi
+sidadm="`echo $SID | tr '[:upper:]' '[:lower:]'`adm"
+}
+
+# Set a tempfile and make sure to clean it up again
+TEMPFILE="/tmp/SAPDatabase.$$.tmp"
+trap trap_handler INT TERM
\ No newline at end of file
diff --git a/heartbeat/sapdb.sh b/heartbeat/sapdb.sh
new file mode 100755
index 0000000..ee30ec1
--- /dev/null
+++ b/heartbeat/sapdb.sh
@@ -0,0 +1,340 @@
+#
+# sapdb.sh - for systems having SAPHostAgent installed
+# (sourced by SAPDatabase)
+#
+# Description:	This code is separated from the SAPDatabase agent to
+#               introduce new functions for systems which having
+#               SAPHostAgent installed.
+#               Someday it might be merged back into SAPDatabase agein.
+#
+# Author:       Alexander Krauth, September 2010
+# Support:      linux at sap.com
+# License:      GNU General Public License (GPL)
+# Copyright:    (c) 2010, 2012 Alexander Krauth
+#
+
+
+#
+# background_check_saphostexec : Run a request to saphostexec in a separat task, to be able to react on a hanging process
+#
+background_check_saphostexec() {
+  timeout=600
+  count=0
+
+  $SAPHOSTCTRL -function ListDatabases >/dev/null 2>&1 &
+  pid=$!
+
+  while kill -0 $pid > /dev/null 2>&1
+  do
+    sleep 0.1
+    count=$(( $count + 1 ))
+    if [ $count -ge $timeout ]; then
+      kill -9 $pid >/dev/null 2>&1
+      ocf_log warn "saphostexec did not respond to the method 'ListDatabases' within 60 seconds"
+      return $OCF_ERR_GENERIC                # Timeout
+    fi
+  done
+
+  # child already has finished, now evaluate it's returncode 
+  wait $pid
+}
+
+#
+# cleanup_saphostexec : make sure to cleanup the SAPHostAgent in case of any
+#                       misbehavior
+#
+cleanup_saphostexec() {
+  pkill -9 -f "$SAPHOSTEXEC"
+  pkill -9 -f "$SAPHOSTSRV"
+  oscolpid=`pgrep -f "$SAPHOSTOSCOL"`       # we check saposcol pid, because it
+                                            # might not run under control of
+					    # saphostexec
+
+  # cleanup saposcol shared memory, otherwise it will not start again
+  if [ -n "$oscolpid" ];then
+    kill -9 $oscolpid
+    oscolipc=`ipcs -m | grep "4dbe " | awk '{print $2}'`
+    if [ -n "$oscolipc" ]; then
+      ipcrm -m $oscolipc
+    fi
+  fi
+
+  # removing the unix domain socket file as it might have wrong permissions or 
+  # ownership - it will be recreated by saphostexec during next start
+  [ -r /tmp/.sapstream1128 ] && rm -f /tmp/.sapstream1128
+}
+
+#
+# check_saphostexec : Before using saphostctrl we make sure that the
+#                     saphostexec is running on the current node.
+#
+check_saphostexec() {
+  chkrc=$OCF_SUCCESS
+  running=`pgrep -f "$SAPHOSTEXEC" | wc -l`
+
+  if [ $running -gt 0 ]; then
+    if background_check_saphostexec; then
+      return $OCF_SUCCESS
+    else
+      ocf_log warn "saphostexec did not respond to the method 'ListDatabases' correctly (rc=$?), it will be killed now"
+      running=0
+    fi
+  fi
+
+  if [ $running -eq 0 ]; then
+    ocf_log warn "saphostexec is not running on node `hostname`, it will be started now"
+    cleanup_saphostexec
+    output=`$SAPHOSTEXEC -restart 2>&1`
+    
+    # now make sure the daemon has been started and is able to respond
+    srvrc=1
+    while [ $srvrc -ne 0 -a `pgrep -f "$SAPHOSTEXEC" | wc -l` -gt 0 ]
+    do
+      sleep 1
+      background_check_saphostexec
+      srvrc=$?
+    done
+
+    if [ $srvrc -eq 0 ]
+    then
+      ocf_log info "saphostexec on node `hostname` was restarted !"
+      chkrc=$OCF_SUCCESS
+    else
+      ocf_log error "saphostexec on node `hostname` could not be started! - $output"
+      chkrc=$OCF_ERR_GENERIC
+    fi
+  fi
+  
+  return $chkrc
+}
+
+
+#
+# sapdatabase_start : Start the SAP database
+#
+sapdatabase_start() {
+
+  check_saphostexec
+  rc=$?
+  
+  if [ $rc -eq $OCF_SUCCESS ]
+  then
+    sapuserexit PRE_START_USEREXIT "$OCF_RESKEY_PRE_START_USEREXIT"
+
+    DBINST=""
+    if [ -n "$OCF_RESKEY_DBINSTANCE" ]
+    then
+      DBINST="-dbinstance $OCF_RESKEY_DBINSTANCE "
+    fi
+    FORCE=""
+    if ocf_is_true $OCF_RESKEY_AUTOMATIC_RECOVER
+    then
+      FORCE="-force"
+    fi
+    output=`$SAPHOSTCTRL -function StartDatabase -dbname $SID -dbtype $DBTYPE $DBINST $FORCE -service`
+
+    sapdatabase_monitor 1
+    rc=$?
+
+    if [ $rc -eq 0 ]
+    then
+      ocf_log info "SAP database $SID started: $output"
+      rc=$OCF_SUCCESS
+    
+      sapuserexit POST_START_USEREXIT "$OCF_RESKEY_POST_START_USEREXIT"
+    else
+      ocf_log err "SAP database $SID start failed: $output"
+      rc=$OCF_ERR_GENERIC
+    fi
+  fi
+  
+  return $rc
+}
+
+#
+# sapdatabase_stop: Stop the SAP database
+#
+sapdatabase_stop() {
+
+  check_saphostexec
+  rc=$?
+  
+  if [ $rc -eq $OCF_SUCCESS ]
+  then
+    sapuserexit PRE_STOP_USEREXIT "$OCF_RESKEY_PRE_STOP_USEREXIT"
+
+    DBINST=""
+    if [ -n "$OCF_RESKEY_DBINSTANCE" ]
+    then
+      DBINST="-dbinstance $OCF_RESKEY_DBINSTANCE "
+    fi
+    output=`$SAPHOSTCTRL -function StopDatabase -dbname $SID -dbtype $DBTYPE $DBINST -force -service`
+
+    if [ $? -eq 0 ]
+    then
+      ocf_log info "SAP database $SID stopped: $output"
+      rc=$OCF_SUCCESS
+    else
+      ocf_log err "SAP database $SID stop failed: $output"
+      rc=$OCF_ERR_GENERIC
+    fi
+  fi
+
+  sapuserexit POST_STOP_USEREXIT "$OCF_RESKEY_POST_STOP_USEREXIT"
+  
+  return $rc
+}
+
+
+#
+# sapdatabase_monitor: Can the given database instance do anything useful?
+#
+sapdatabase_monitor() {
+  strict=$1
+  rc=$OCF_SUCCESS
+
+  if ! ocf_is_true $strict
+  then
+    sapdatabase_status
+    rc=$?
+  else
+    check_saphostexec
+    rc=$?
+  
+    if [ $rc -eq $OCF_SUCCESS ]
+    then
+      count=0
+      
+      DBINST=""
+      if [ -n "$OCF_RESKEY_DBINSTANCE" ]
+      then
+        DBINST="-dbinstance $OCF_RESKEY_DBINSTANCE "
+      fi
+      output=`$SAPHOSTCTRL -function GetDatabaseStatus -dbname $SID -dbtype $DBTYPE $DBINST`
+
+      # we have to parse the output, because the returncode doesn't tell anything about the instance status
+      for SERVICE in `echo "$output" | grep -i 'Component[ ]*Name *[:=] [A-Za-z][A-Za-z0-9_]* (' | sed 's/^.*Component[ ]*Name *[:=] *\([A-Za-z][A-Za-z0-9_]*\).*$/\1/i'`
+      do 
+        COLOR=`echo "$output" | grep -i "Component[ ]*Name *[:=] *$SERVICE (" | sed 's/^.*Status *[:=] *\([A-Za-z][A-Za-z0-9_]*\).*$/\1/i'`
+        STATE=0
+
+        case $COLOR in
+          Running)       STATE=$OCF_SUCCESS;;
+          *)             STATE=$OCF_NOT_RUNNING;;
+        esac 
+
+        SEARCH=`echo "$OCF_RESKEY_MONITOR_SERVICES" | sed 's/\+/\\\+/g' | sed 's/\./\\\./g'`
+        if [ `echo "$SERVICE" | egrep -c "$SEARCH"` -eq 1 ]
+        then
+            if [ $STATE -eq $OCF_NOT_RUNNING ]
+            then
+              ocf_log err "SAP database service $SERVICE is not running with status $COLOR !"
+              rc=$STATE
+            fi
+            count=1
+        fi
+      done
+
+      if [ $count -eq 0 -a $rc -eq $OCF_SUCCESS ]
+      then
+        ocf_log err "The resource does not run any services which this RA could monitor!"
+        rc=$OCF_ERR_ARGS
+      fi
+      
+      if [ $rc -ne $OCF_SUCCESS ]
+      then
+        ocf_log err "The SAP database $SID ist not running: $output"
+      fi
+    fi
+  fi
+  return $rc
+}
+
+
+#
+# sapdatabase_status: Are there any database processes on this host ?
+#
+sapdatabase_status() {
+  case $DBTYPE in
+    ADA) SEARCH="$SID/db/pgm/kernel"
+         SUSER=`grep "^SdbOwner" /etc/opt/sdb | awk -F'=' '{print $2}'`
+         SNUM=2
+         ;;
+    ORA) SEARCH="ora_[a-z][a-z][a-z][a-z]_"
+         SUSER="ora`echo $SID | tr '[:upper:]' '[:lower:]'`"
+         SNUM=4
+         ;;
+    DB6) SEARCH="db2[a-z][a-z][a-z]"
+         SUSER="db2`echo $SID | tr '[:upper:]' '[:lower:]'`"
+         SNUM=2
+         ;;
+    SYB) SEARCH="dataserver"
+         SUSER="syb`echo $SID | tr '[:upper:]' '[:lower:]'`"
+         SNUM=1
+		 ;;
+    HDB) SEARCH="hdb[a-z]*server"
+         SUSER="`echo $SID | tr '[:upper:]' '[:lower:]'`adm"
+         SNUM=1
+		 ;;
+  esac
+
+  cnt=`ps -u $SUSER -o args 2> /dev/null | grep -c $SEARCH`
+  [ $cnt -ge $SNUM ] && return $OCF_SUCCESS
+  return $OCF_NOT_RUNNING
+}
+
+
+#
+# sapdatabase_recover:
+#
+sapdatabase_recover() {
+  OCF_RESKEY_AUTOMATIC_RECOVER=1
+  sapdatabase_stop
+  sapdatabase_start
+}
+
+
+#
+# sapdatabase_validate: Check the symantic of the input parameters 
+#
+sapdatabase_validate() {
+  rc=$OCF_SUCCESS
+  if [ `echo "$SID" | grep -c '^[A-Z][A-Z0-9][A-Z0-9]$'` -ne 1 ]
+  then
+    ocf_log err "Parsing parameter SID: '$SID' is not a valid system ID!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  case "$DBTYPE" in
+   ORA|ADA|DB6|SYB|HDB) ;;
+   *) ocf_log err "Parsing parameter DBTYPE: '$DBTYPE' is not a supported database type!"
+      rc=$OCF_ERR_ARGS ;;
+  esac
+
+  return $rc
+}
+
+#
+# sapdatabase_init: initialize global variables at the beginning
+#
+sapdatabase_init() {
+OCF_RESKEY_AUTOMATIC_RECOVER_default=0
+: ${OCF_RESKEY_AUTOMATIC_RECOVER=${OCF_RESKEY_AUTOMATIC_RECOVER_default}}
+
+if [ -z "$OCF_RESKEY_MONITOR_SERVICES" ]
+then
+  case $DBTYPE in
+    ORA) export OCF_RESKEY_MONITOR_SERVICES="Instance|Database|Listener"
+         ;;
+    ADA) export OCF_RESKEY_MONITOR_SERVICES="Database"
+         ;;
+    DB6) db2sid="db2`echo $SID | tr '[:upper:]' '[:lower:]'`"
+         export OCF_RESKEY_MONITOR_SERVICES="${SID}|${db2sid}"
+         ;;
+    SYB) export OCF_RESKEY_MONITOR_SERVICES="Server"
+         ;;
+    HDB) export OCF_RESKEY_MONITOR_SERVICES="hdbindexserver"
+         ;;
+  esac
+fi
+}
diff --git a/heartbeat/scsi2reservation b/heartbeat/scsi2reservation
new file mode 100755
index 0000000..be0c53a
--- /dev/null
+++ b/heartbeat/scsi2reservation
@@ -0,0 +1,170 @@
+#!/bin/sh
+# by hxinwei at gmail.com
+# License: GNU General Public License 2 (GPL2)
+
+if [ -n "$OCF_DEBUG_LIBRARY" ]; then
+    . $OCF_DEBUG_LIBRARY
+else
+    : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+fi
+
+: ${OCF_RESKEY_scsi_reserve="/usr/sbin/scsi_reserve"}
+: ${OCF_RESKEY_sharedisk="/dev/sdb"}
+: ${OCF_RESKEY_start_loop=10}
+
+scsi2reserve_meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="scsi2reservation">
+<version>1.0</version>
+
+<longdesc lang="en">
+The scsi-2-reserve resource agent is a place holder for SCSI-2 reservation.
+A healthy instance of scsi-2-reserve resource, indicates the own of the specified SCSI device.
+This resource agent depends on the scsi_reserve from scsires package, which is Linux specific.
+</longdesc>
+
+<shortdesc lang="en">
+scsi-2 reservation
+</shortdesc>
+
+<parameters>
+
+<parameter name="scsi_reserve" unique="0" required="0">
+<longdesc lang="en">
+The scsi_reserve is a command from scsires package. 
+It helps to issue SCSI-2 reservation on SCSI devices.
+</longdesc>
+<shortdesc lang="en">Manages exclusive access to shared storage media thrugh SCSI-2 reservations</shortdesc>
+<content type="string" default="/usr/sbin/scsi_reserve" />
+</parameter>
+
+
+<parameter name="sharedisk" unique="0" required="0">
+<longdesc lang="en">
+The shared disk that can be reserved.
+</longdesc>
+<shortdesc lang="en">
+Shared disk.
+</shortdesc>
+<content type="string" default="/dev/sdb" />
+</parameter>
+
+<parameter name="start_loop" unique="0" required="0">
+<longdesc lang="en">
+We are going to try several times before giving up. Start_loop indicates how many times we are going to re-try.
+</longdesc>
+<shortdesc lang="en">
+Times to re-try before giving up.
+</shortdesc>
+<content type="string" default="10" />
+</parameter>
+
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="300" />
+<action name="stop"    timeout="100" />
+<action name="monitor" depth="0"  timeout="20" interval="20" />
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="30" />
+</actions>
+</resource-agent>
+END
+
+	return $OCF_SUCCESS
+}
+
+scsi2reserve_usage() {
+	cat <<END
+		usage: $0 {start|stop|monitor|validate-all|meta-data}
+END
+}
+
+case $__OCF_ACTION in
+	meta-data)  scsi2reserve_meta_data
+		exit $OCF_SUCCESS
+		;;
+	usage|help) scsi2reserve_usage
+		exit $OCF_SUCCESS
+		;;
+	*)
+		;;
+esac		
+	
+
+scsi2reserve_validate ()
+{
+	if [ ! -x "${OCF_RESKEY_scsi_reserve}" ]; then
+		exit $OCF_ERR_INSTALLED
+	fi
+	if [ -z "${OCF_RESKEY_sharedisk}" ]; then
+		exit $OCF_ERR_GENERIC
+	fi	
+	if [ ! -b "${OCF_RESKEY_sharedisk}" ]; then
+		exit $OCF_ERR_ARGS
+	fi
+}
+
+scsi2reserve_validate
+
+scsi2reserve_start ()
+{
+	ite=$OCF_RESKEY_start_loop
+	while [ $ite -ge 0 ]; do	
+		/sbin/startproc ${OCF_RESKEY_scsi_reserve} -d ${OCF_RESKEY_sharedisk} --preempt --hold --stonith
+		sleep 15
+		/sbin/checkproc ${OCF_RESKEY_scsi_reserve}
+		rc=$?
+		if [ $rc -eq 0 ]; then
+			exit $OCF_SUCCESS
+		fi		
+		ite=`expr $ite - 1`
+	done	
+	exit $OCF_ERR_GENERIC
+}
+
+scsi2reserve_monitor ()
+{
+	/sbin/checkproc ${OCF_RESKEY_scsi_reserve}
+	rc=$?
+	if [ $rc -eq 0 ]; then
+		exit $OCF_SUCCESS
+	else
+		exit $OCF_NOT_RUNNING
+	fi	
+}
+
+scsi2reserve_stop ()
+{
+	/sbin/killproc ${OCF_RESKEY_scsi_reserve}
+	${OCF_RESKEY_scsi_reserve} -d ${OCF_RESKEY_sharedisk} --release
+	exit $OCF_SUCCESS
+}
+
+if [ $# -ne 1 ]; then
+	scsi2reserve_usage
+	exit $OCF_ERR_ARGS
+fi
+
+case $__OCF_ACTION in
+	start)      scsi2reserve_start
+		;;
+	stop)       scsi2reserve_stop
+		;;
+	monitor)    scsi2reserve_monitor
+		;;
+	validate-all)   scsi2reserve_validate
+			exit $OCF_SUCCESS
+		;;
+	*)      scsi2reserve_usage
+		exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+
+exit $?
+
+
diff --git a/heartbeat/send_ua.c b/heartbeat/send_ua.c
new file mode 100644
index 0000000..ef5357b
--- /dev/null
+++ b/heartbeat/send_ua.c
@@ -0,0 +1,127 @@
+
+/*
+ * This program manages IPv6 address with OCF Resource Agent standard.
+ *
+ * Author: Huang Zhen <zhenh at cn.ibm.com>
+ * Copyright (c) 2004 International Business Machines
+ *
+ * This library 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 library 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.
+ */
+
+#include <IPv6addr.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <arpa/inet.h> /* for inet_pton */
+#include <net/if.h> /* for if_nametoindex */
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+
+static void usage_send_ua(const char* self);
+static void byebye(int nsig);
+
+int
+main(int argc, char* argv[])
+{
+	char*		ipv6addr;
+	int		count = UA_REPEAT_COUNT;
+	int		interval = 1000;	/* default 1000 msec */
+	int		ch;
+	int		i;
+	char*		cp;
+	char*		prov_ifname = NULL;
+	struct in6_addr	addr6;
+
+	/* Check binary name */
+	if (argc < 4) {
+		usage_send_ua(argv[0]);
+		return OCF_ERR_ARGS;
+	}
+	while ((ch = getopt(argc, argv, "h?c:i:")) != EOF) {
+		switch(ch) {
+		case 'c': /* count option */
+			count = atoi(optarg);
+		    break;
+		case 'i': /* interval option */
+			interval = atoi(optarg);
+		    break;
+		case 'h':
+		case '?':
+		default:
+			usage_send_ua(argv[0]);
+			return OCF_ERR_ARGS;
+		}
+	}
+
+	/* set termination signal */
+	siginterrupt(SIGTERM, 1);
+	signal(SIGTERM, byebye);
+
+	ipv6addr = argv[optind];
+
+	if (ipv6addr == NULL) {
+		printf("ERROR: Please set OCF_RESKEY_ipv6addr to the IPv6 address you want to manage.");
+		usage_send_ua(argv[0]);
+		return OCF_ERR_ARGS;
+	}
+
+	/* legacy option */
+	if ((cp = strchr(ipv6addr, '/'))) {
+		*cp=0;
+	}
+
+	prov_ifname = argv[optind+2];
+
+	if (inet_pton(AF_INET6, ipv6addr, &addr6) <= 0) {
+		printf("ERROR: Invalid IPv6 address [%s]", ipv6addr);
+		usage_send_ua(argv[0]);
+		return OCF_ERR_ARGS;
+	}
+
+	/* Check whether this system supports IPv6 */
+	if (access(IF_INET6, R_OK)) {
+		printf("ERROR: No support for INET6 on this system.");
+		return OCF_ERR_GENERIC;
+	}
+
+	/* Send unsolicited advertisement packet to neighbor */
+	for (i = 0; i < count; i++) {
+		send_ua(&addr6, prov_ifname);
+		usleep(interval * 1000);
+	}
+
+	return OCF_SUCCESS;
+}
+
+static void usage_send_ua(const char* self)
+{
+	printf("usage: %s [-i[=Interval]] [-c[=Count]] [-h] IPv6-Address Prefix Interface\n",self);
+	return;
+}
+
+/* Following code is copied from send_arp.c, linux-HA project. */
+void
+byebye(int nsig)
+{
+	(void)nsig;
+	/* Avoid an "error exit" log message if we're killed */
+	exit(0);
+}
+
diff --git a/heartbeat/sfex b/heartbeat/sfex
new file mode 100755
index 0000000..e6a97d4
--- /dev/null
+++ b/heartbeat/sfex
@@ -0,0 +1,297 @@
+#!/bin/sh
+#
+#       Shared Disk File EXclusiveness (SF-EX) OCF RA. 
+#       prevent a destruction of data on shared disk file system 
+#	due to Split-Brain.
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA  
+# 02110-1301, USA.
+#
+# Copyright (c) 2007 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+#
+# NOTE:
+#	As a prerequisite for running SF-EX, one device should be
+#	initialized as below.
+#
+#		sfex_init [-n <numlocks>] <device>
+#
+#	Example:
+#
+#		/usr/sbin/sfex_init -n 10 /dev/sdb1
+#
+#	if further information is necessary, See README.
+#
+#######################################################################
+# Initialization:
+
+# switching ocf-shellfuncs path
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+SFEX_DAEMON=${HA_BIN}/sfex_daemon
+
+usage() {
+    cat <<END
+    usage: $0 {start|stop|monitor|meta-data}
+END
+}
+
+meta_data() {
+    cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="sfex">
+<version>1.3</version>
+
+<longdesc lang="en">
+Resource script for SF-EX. It manages a shared storage medium exclusively .
+</longdesc>
+<shortdesc lang="en">Manages exclusive access to shared storage using Shared Disk File EXclusiveness (SF-EX)</shortdesc>
+<parameters>
+<parameter name="device" unique="0" required="1">
+<longdesc lang="en">
+Block device path that stores exclusive control data.
+</longdesc>
+<shortdesc lang="en">block device</shortdesc>
+<content type="string" default="" />
+</parameter>
+<parameter name="index" unique="0" required="0">
+<longdesc lang="en">
+Location in block device where exclusive control data is stored. 1 or more is specified. Default is 1.
+</longdesc>
+<shortdesc lang="en">index</shortdesc>
+<content type="integer" default="1" />
+</parameter>
+<parameter name="collision_timeout" unique="0" required="0">
+<longdesc lang="en">
+Waiting time when a collision of lock acquisition is detected. Default is 1 second.
+</longdesc>
+<shortdesc lang="en">waiting time for lock acquisition</shortdesc>
+<content type="integer" default="1" />
+</parameter>
+<parameter name="monitor_interval" unique="0" required="0">
+<longdesc lang="en">
+Monitor interval(sec). Default is 10 seconds
+</longdesc>
+<shortdesc lang="en">monitor interval</shortdesc>
+<content type="integer" default="10" />
+</parameter>
+<parameter name="lock_timeout" unique="0" required="0">
+<longdesc lang="en">
+Valid term of lock(sec). Default is 100 seconds.
+The lock_timeout is calculated by the following formula.
+
+  lock_timeout = monitor_interval + "The expiration time of the lock"
+
+We suggest 90 seconds as a default value of the "The expiration time of the lock", but you should change it in consideration of access delay to the shared disk and the switch time of the multipath driver.
+
+The lock timeout have an impact on start action timeout because start action timeout value is calculated by the following formula.
+
+  start timeout = collision_timeout + lock_timeout + "safety margin"
+
+The "safety margin" is decided within the range of about 10-20 seconds(It depends on your system requirement).
+</longdesc>
+<shortdesc lang="en">Valid term of lock</shortdesc>
+<content type="integer" default="100" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="120s" />
+<action name="stop" timeout="20s" />
+<action name="monitor" depth="0" timeout="10s" interval="10s" />
+<action name="meta-data" timeout="5s" />
+<action name="validate-all" timeout="5s" />
+</actions>
+</resource-agent>
+END
+}
+
+#
+# START: Exclusive control starts.
+#
+# It loops permanently until the lock can be acquired when locked with 
+# the other node. In this case, the reception of the stop signal by the 
+# timeout time passage set to CIB becomes the only stop opportunity. 
+#
+sfex_start() {
+	ocf_log info "sfex_daemon: starting..."
+
+	sfex_monitor
+	if [ $? -eq $OCF_SUCCESS ]; then
+		ocf_log info "sfex_daemon already started."
+		return $OCF_SUCCESS
+	fi
+
+	$SFEX_DAEMON -i $INDEX -c $COLLISION_TIMEOUT -t $LOCK_TIMEOUT -m $MONITOR_INTERVAL -r ${OCF_RESOURCE_INSTANCE} $DEVICE
+
+	rc=$?
+	if [ $rc -ne 0 ]; then
+		ocf_log err "sfex_daemon failed to start."
+		return $OCF_ERR_GENERIC
+	fi
+	
+	while :
+	do
+		sfex_monitor
+		if [ $? -eq $OCF_SUCCESS ]; then
+			ocf_log info "sfex_daemon: started."
+			return $OCF_SUCCESS
+		fi
+		ocf_log debug "Waiting for the start-up of the sfex_daemon..."
+		sleep 1
+	done
+	ocf_log err "Can't find a sfex_daemon process. Starting a sfex_daemon failed."
+	return $OCF_ERR_GENERIC
+}
+
+#
+# STOP: stop exclusive control 
+#
+sfex_stop() {
+	ocf_log info "sfex_daemon: stopping..."
+
+	# Check the sfex daemon has already stopped.
+	sfex_monitor
+	if [ $? -eq $OCF_NOT_RUNNING ]; then
+		ocf_log info "sfex_daemon already stopped."
+		return $OCF_SUCCESS
+	fi
+
+	# Stop sfex daemon by sending SIGTERM signal.
+	pid=`/usr/bin/pgrep -f "$SFEX_DAEMON .* ${OCF_RESOURCE_INSTANCE} "`
+	/bin/kill $pid
+	rc=$?
+	if [ $rc -ne 0 ]; then
+		ocf_log err "sfex_daemon failed to stop"
+		return $rc
+	fi
+
+#sfex could be in state D if the device is gone, and then not terminate.	
+#Wait and check again if the daemon is already properly shutdown.
+
+	shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5))
+	count=0
+	while [ $count -lt $shutdown_timeout ]
+	do
+		sfex_monitor
+		if [ $? -eq $OCF_NOT_RUNNING ]; then
+			ocf_log info "sfex_daemon: stopped."
+			return $OCF_SUCCESS
+		fi
+		count=`expr $count + 1`
+		ocf_log debug "waiting for sfex_daemon to exit ($count/$shutdown_timeout)"
+		sleep 1
+	done
+	
+	sfex_monitor
+	if [ $? -ne $OCF_NOT_RUNNING ]; then
+		ocf_log warn "regular shutdown of sfex_daemon timed out, using SIGKILL"
+		/bin/kill -s KILL $pid
+	fi
+
+	while :
+	do
+		sfex_monitor
+		if [ $? -eq $OCF_NOT_RUNNING ]; then
+			break;
+		fi
+		ocf_log debug "waiting for sfex_daemon to exit after SIGKILL"
+		sleep 1
+	done
+
+	ocf_log info "sfex_daemon: stopped."
+	return $OCF_SUCCESS
+}
+
+sfex_monitor() {
+	ocf_log debug "sfex_monitor: started..."
+
+	# Find a sfex_daemon process using daemon name and resource name.
+	if /usr/bin/pgrep -f "$SFEX_DAEMON .* ${OCF_RESOURCE_INSTANCE} " > /dev/null 2>&1; then
+		ocf_log debug "sfex_monitor: complete. sfex_daemon is running."
+		return $OCF_SUCCESS
+	fi
+
+	ocf_log debug "sfex_monitor: complete. sfex_daemon is not running."
+	return $OCF_NOT_RUNNING
+}
+
+#
+# main process 
+#
+
+# check arguments
+if [ $# -ne 1 ]; then
+	usage
+	exit $OCF_ERR_ARGS
+fi
+OP=$1
+
+# These operations do not require instance parameters
+case $OP in
+	meta-data)
+		meta_data
+		exit $OCF_SUCCESS
+		;;
+	usage)
+		usage
+		exit $OCF_SUCCESS
+		;;
+esac
+
+# check parameters
+DEVICE=$OCF_RESKEY_device
+INDEX=${OCF_RESKEY_index:-1}
+COLLISION_TIMEOUT=${OCF_RESKEY_collision_timeout:-1}
+LOCK_TIMEOUT=${OCF_RESKEY_lock_timeout:-100}
+MONITOR_INTERVAL=${OCF_RESKEY_monitor_interval:-10}
+
+sfex_validate () {
+if [ -z "$DEVICE" ]; then
+	ocf_log err "Please set OCF_RESKEY_device to device for sfex meta-data"
+	exit $OCF_ERR_ARGS
+fi
+if [ ! -w "$DEVICE" ]; then
+	ocf_log warn "Couldn't find device [$DEVICE]. Expected /dev/??? to exist"
+	exit $OCF_ERR_ARGS
+fi
+}
+
+if [ -n "$OCF_RESKEY_CRM_meta_clone" ]; then
+	ocf_log err "THIS RA DO NOT SUPPORT CLONE MODE!"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+case $OP in
+	start)
+		sfex_start
+		;;
+	stop)
+		sfex_stop
+		;;
+	monitor)
+		sfex_monitor
+		;;
+	validate-all)
+		sfex_validate
+		;;
+	*)
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+exit $?
diff --git a/heartbeat/shellfuncs.in b/heartbeat/shellfuncs.in
new file mode 100644
index 0000000..7786ec3
--- /dev/null
+++ b/heartbeat/shellfuncs.in
@@ -0,0 +1,96 @@
+# Author:       Alan Robertson
+# Support:      linux-ha-dev at lists.tummy.com
+# License:      GNU Lesser General Public License (LGPL)
+#
+#	Set these variables if they're not already set...
+#
+
+: ${HA_SBIN_DIR:=@sbindir@}
+: ${HA_NOARCHBIN:=@datadir@/heartbeat}
+: ${OCF_AGENTS:=@OCF_RA_DIR@/heartbeat/}
+
+export HA_DIR HA_RCDIR HA_FIFO HA_BIN 
+export HA_DEBUGLOG HA_LOGFILE HA_LOGFACILITY
+export HA_DATEFMT HA_RESOURCEDIR HA_DOCDIR
+export OCF_AGENTS
+
+PATH=$HA_BIN:${HA_SBIN_DIR}:${HA_NOARCHBIN}:$PATH
+PATH=`echo $PATH | sed -e 's%::%%' -e 's%:\.:%:%' -e 's%^:%%' -e 's%^\.:%%'`
+export PATH
+
+#	A suitable echo command
+Echo() {
+  echo "$@"
+}
+
+# copy stdin (text) to FIFO, with surrounding ">>>" and "<<<" marker lines.
+# no args.; no result
+# Notes:
+#	o Using "cat -" rather than "cat" simply for clarity.
+#	o The trailing "| cat -" tries to hold things together as a single
+#	  write (which is probably preferable behaviour in this context).
+ha_clustermsg() {
+	(echo ">>>"; cat -; echo "<<<")	| cat - >> $HA_FIFO
+}
+
+ha_parameter() {
+  VALUE=`sed -e 's%[ 	][ 	]*% %' -e 's%^ %%' -e 's%#.*%%'   $HA_CF |
+  grep -i "^$1 " | sed 's%[^ ]* %%'`
+  if
+    [ "X$VALUE" = X ]
+  then
+    
+    case $1 in
+      keepalive)	VALUE=2;;
+      deadtime)
+			ka=`ha_parameter keepalive`
+			VALUE=`expr $ka '*' 2 '+' 1`;;
+    esac
+  fi
+  Echo $VALUE
+}
+
+BSD_Status() {
+  local base=${1##*/}
+  local pid
+
+  ret_status=`/bin/ps -ao pid,command | grep $base | sed 's/ .*//'`
+
+  if 
+    [ "$ret_status" != "" ]
+  then
+    echo "${base} is running..."
+  return 0
+  fi
+
+  if 
+    [ -f $HA_VARRUN/${base}.pid ] 
+  then
+    echo "${base} dead but pid file exists"
+    return 1
+  fi
+
+  if 
+    [ -f /var/run/${base}.pid ] 
+  then
+    echo "${base} dead but pid file exists"
+    return 1
+  fi
+
+  if 
+    [ -f $HA_VARLOCK/var/lock/subsys/${base}.pid ] 
+  then
+    echo "${base} dead but lock file exists"
+    return 2
+  fi
+
+  if 
+    [ -f /var/spool/lock/${base} ] 
+  then
+    echo "${base} dead but lock file exists"
+    return 2
+  fi
+}
+
+# Now get the good stuff
+. @OCF_LIB_DIR@/heartbeat/ocf-shellfuncs
diff --git a/heartbeat/slapd b/heartbeat/slapd
new file mode 100755
index 0000000..ffb40e8
--- /dev/null
+++ b/heartbeat/slapd
@@ -0,0 +1,591 @@
+#!/bin/bash
+#
+# Stand-alone LDAP Daemon (slapd)
+#
+# Description:  Manages Stand-alone LDAP Daemon (slapd) as an OCF resource in
+#               an high-availability setup.
+#
+# Authors:      Jeroen Koekkoek
+#               nozawat at gmail.com
+#               John Keith Hohm
+#
+# License:      GNU General Public License (GPL)
+# Copyright:    (C) 2011 Pagelink B.V.
+#
+#       The OCF code was inspired by the Postfix resource script written by
+#       Raoul Bhatia <r.bhatia at ipax.at>.
+#
+#       The code for managing the slapd instance is based on the the slapd init
+#       script found in Debian GNU/Linux 6.0.
+#
+# OCF parameters:
+#   OCF_RESKEY_slapd
+#   OCF_RESKEY_ldapsearch
+#   OCF_RESKEY_config
+#   OCF_RESKEY_pidfile
+#   OCF_RESKEY_user
+#   OCF_RESKEY_group
+#   OCF_RESKEY_services
+#   OCF_RESKEY_watch_suffix
+#   OCF_RESKEY_ignore_suffix
+#   OCF_RESKEY_bind_dn
+#   OCF_RESKEY_password
+#   OCF_RESKEY_parameters
+#   OCF_RESKEY_stop_escalate
+#
+################################################################################
+
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+: ${OCF_RESKEY_slapd="/usr/sbin/slapd"}
+: ${OCF_RESKEY_ldapsearch="ldapsearch"}
+: ${OCF_RESKEY_config=""}
+: ${OCF_RESKEY_pidfile=""}
+: ${OCF_RESKEY_user=""}
+: ${OCF_RESKEY_group=""}
+: ${OCF_RESKEY_services="ldap:///"}
+: ${OCF_RESKEY_watch_suffix=""}
+: ${OCF_RESKEY_ignore_suffix=""}
+: ${OCF_RESKEY_bind_dn=""}
+: ${OCF_RESKEY_password=""}
+: ${OCF_RESKEY_parameters=""}
+: ${OCF_RESKEY_stop_escalate=15}
+
+USAGE="Usage: $0 {start|stop|status|monitor|validate-all|meta-data}"
+ORIG_IFS=$IFS
+NEWLINE='
+'
+
+################################################################################
+
+usage() {
+    echo $USAGE >&2
+}
+
+meta_data()
+{
+  cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="slapd">
+<version>0.1</version>
+
+<longdesc lang="en">
+Resource script for Stand-alone LDAP Daemon (slapd). It manages a slapd instance as an OCF resource.
+</longdesc>
+<shortdesc lang="en">Manages a Stand-alone LDAP Daemon (slapd) instance</shortdesc>
+
+<parameters>
+
+<parameter name="slapd" unique="0" required="0">
+<longdesc lang="en">
+Full path to the slapd binary.
+For example, "/usr/sbin/slapd".
+</longdesc>
+<shortdesc lang="en">Full path to slapd binary</shortdesc>
+<content type="string" default="/usr/sbin/slapd" />
+</parameter>
+
+<parameter name="ldapsearch" unique="0" required="0">
+<longdesc lang="en">
+Full path to the ldapsearch binary.
+For example, "/usr/bin/ldapsearch".
+</longdesc>
+<shortdesc lang="en">Full path to ldapsearch binary</shortdesc>
+<content type="string" default="ldapsearch" />
+</parameter>
+
+<parameter name="config" required="0" unique="1">
+<longdesc lang="en">
+Full path to a slapd configuration directory or a slapd configuration file.
+For example, "/etc/ldap/slapd.d" or "/etc/ldap/slapd.conf".
+</longdesc>
+<shortdesc>Full path to configuration directory or file</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="pidfile" required="0" unique="0">
+<longdesc lang="en">
+File to read the PID from; read from olcPidFile/pidfile in config if not set.
+</longdesc>
+<shortdesc lang="en">File to read PID from</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="user" unique="0" required="0">
+<longdesc lang="en">
+User name or id slapd will run with. The group id is also changed to this
+user's gid, unless the group parameter is used to override.
+</longdesc>
+<shortdesc lang="en">User name or id slapd will run with</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="group" unique="0" required="0">
+<longdesc lang="en">
+Group name or id slapd will run with.
+</longdesc>
+<shortdesc lang="en">Group name or id slapd will run with</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="services" required="0" unique="1">
+<longdesc lang="en">
+LDAP (and other scheme) URLs slapd will serve.
+For example, "ldap://127.0.0.1:389 ldaps:/// ldapi:///"
+</longdesc>
+<shortdesc>LDAP (and other scheme) URLs to serve</shortdesc>
+<content type="string" default="ldap:///"/>
+</parameter>
+
+<parameter name="watch_suffix" required="0" unique="0">
+<longdesc lang="en">
+Suffix (database backend) that will be monitored for availability. Multiple
+suffixes can be specified by providing a space seperated list. By providing one
+or more suffixes here, the ignore_suffix parameter is discarded. All suffixes
+will be monitored if left blank.
+</longdesc>
+<shortdesc>Suffix that will be monitored for availability.</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="ignore_suffix" required="0" unique="0">
+<longdesc lang="en">
+Suffix (database backend) that will not be monitored for availability. Multiple
+suffixes can be specified by providing a space seperated list. No suffix will
+be excluded if left blank.
+</longdesc>
+<shortdesc>Suffix that will not be monitored for availability.</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="bind_dn" required="0" unique="0">
+<longdesc lang="en">
+Distinguished Name used to bind to the LDAP directory for testing. Leave blank
+to bind to the LDAP directory anonymously.
+</longdesc>
+<shortdesc>Distinguished Name used to bind to the LDAP directory for testing.</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="password" required="0" unique="0">
+<longdesc lang="en">
+Password used to bind to the LDAP directory for testing.
+</longdesc>
+<shortdesc>Password used to bind to the LDAP directory for testing.</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="parameters" unique="0" required="0">
+<longdesc lang="en">
+slapd may be called with additional parameters.
+Specify any of them here.
+</longdesc>
+<shortdesc lang="en">Any additional parameters to slapd.</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="stop_escalate" unique="0" required="0">
+<longdesc lang="en">
+Number of seconds to wait for shutdown (using SIGTERM) before resorting to
+SIGKILL
+</longdesc>
+<shortdesc lang="en">Seconds before stop escalation to KILL</shortdesc>
+<content type="integer" default="15" />
+</parameter>
+</parameters>
+
+<actions>
+<action name="start"   timeout="20s" />
+<action name="stop"    timeout="20s" />
+<action name="monitor" depth="0"  timeout="20s" interval="60s" />
+<action name="validate-all"  timeout="20s" />
+<action name="meta-data"  timeout="5s" />
+</actions>
+</resource-agent>
+END
+}
+
+terminate()
+{
+  local pid=$1
+  local signal=$2
+  local recheck=${3-0}
+  local rc
+  local waited=0
+
+  kill -$signal $pid >/dev/null 2>&1; rc=$?
+
+  while [ \( $rc -eq 0 \) -a \( $recheck -eq 0 -o $waited -lt $recheck \) ]; do
+    kill -0 $pid >/dev/null 2>&1; rc=$?
+    let "waited += 1"
+
+    if [ $rc -eq 0 ]; then
+      sleep 1
+    fi
+  done
+
+  if [ $rc -ne 0 ]; then
+    return 0
+  fi
+
+  return 1
+}
+
+watch_suffix()
+{
+  local rc
+
+  if [ -n "$OCF_RESKEY_watch_suffix" ]; then
+    if echo "'$OCF_RESKEY_watch_suffix'" | grep "'$1'" >/dev/null 2>&1; then
+      rc=0
+    else
+      rc=1
+    fi
+  else
+    if echo "'$OCF_RESKEY_ignore_suffix'" | grep "'$1'" >/dev/null 2>&1; then
+      rc=1
+    else
+      rc=0
+    fi
+  fi
+
+  return $rc
+}
+
+slapd_pid()
+{
+  local pid
+
+  if [ -f "$pid_file" ]; then
+    pid=`head -n 1 "$pid_file" 2>/dev/null`
+
+    if [ "X$pid" != "X" ]; then
+      echo "$pid"
+      return $OCF_SUCCESS
+    fi
+
+    ocf_log err "slapd pid file '$pid_file' empty."
+    return $OCF_ERR_GENERIC
+  fi
+
+  ocf_log info "slapd pid file '$pid_file' does not exist."
+  return $OCF_NOT_RUNNING
+}
+
+slapd_status()
+{
+  local pid=$1
+  local state=$?
+
+  if [ $state -eq $OCF_SUCCESS ]; then
+
+    if ! kill -0 $pid >/dev/null 2>&1; then
+      return $OCF_NOT_RUNNING
+    else
+      return $OCF_SUCCESS
+    fi
+  fi
+
+  return $state
+}
+
+slapd_start()
+{
+  local options
+  local reason
+  local rc
+  local state
+
+  slapd_status `slapd_pid`; state=$?
+
+  if [ $state -eq $OCF_SUCCESS ]; then
+    ocf_log info "slapd already running."
+    return $state
+  elif [ $state -eq $OCF_ERR_GENERIC ]; then
+    return $state
+  fi
+
+  options="-u $user -g $group"
+
+  if [ -d "$config" ]; then
+    options="$options -F $config"
+  elif [ -f "$config" ]; then
+    options="$options -f $config"
+  else
+    ocf_log err "slapd configuration '$config' does not exist."
+    return $OCF_ERR_INSTALLED
+  fi
+
+  if [ -n "$parameters" ]; then
+    options="$options $parameters"
+  fi
+
+  if [ -n "$services" ]; then
+    $slapd -h "$services" $options 2>&1; rc=$?
+  else
+    $slapd $options 2>&1; rc=$?
+  fi
+
+  if [ $rc -ne 0 ]; then
+    ocf_log err "slapd returned error."
+
+    return $OCF_ERR_GENERIC
+  fi
+
+  while true; do
+    slapd_monitor start
+    if [ $? = "$OCF_SUCCESS" ]; then
+      break
+    fi
+    sleep 1
+  done
+
+  ocf_log info "slapd started."
+
+  return $OCF_SUCCESS
+}
+
+slapd_stop()
+{
+  local pid
+  local rc
+  local state
+
+  pid=`slapd_pid`; slapd_status $pid; state=$?
+
+  if [ $state -eq $OCF_NOT_RUNNING ]; then
+    ocf_log info "slapd already stopped."
+    return $OCF_SUCCESS
+  elif [ $state -eq $OCF_ERR_GENERIC ]; then
+    return $state
+  fi
+
+  terminate $pid TERM $OCF_RESKEY_stop_escalate; rc=$?
+  if [ $rc -ne 0  ]; then
+    ocf_log err "slapd failed to stop. Escalating to KILL."
+    terminate $pid KILL; rc=$?
+  fi
+
+  if [ -f "$pid_file" ]; then
+    rm -f "$pid_file" >/dev/null 2>&1
+  fi
+
+  ocf_log info "slapd stopped."
+  return $OCF_SUCCESS
+}
+
+slapd_monitor()
+{
+  local options
+  local rc
+  local state
+  local suffix
+  local suffixes
+  local err_option="-info"
+
+  slapd_status `slapd_pid`; state=$?
+  if [ $state -eq $OCF_NOT_RUNNING ]; then
+    if [ -z "$1" ];then
+      if ! ocf_is_probe; then
+        ocf_log err "slapd process not found."
+      fi
+    fi
+    return $state
+  elif [ $state -ne $OCF_SUCCESS ]; then
+    ocf_log err "slapd returned error."
+    return $state
+  fi
+
+  if [ -d "$config" ]; then
+    for suffix in `find "$config"/'cn=config' -type f -name olcDatabase* -exec \
+                   sed -ne 's/^[[:space:]]*olcSuffix:[[:space:]]\+\(.\+\)/\1/p' {} \;`
+    do
+      suffix=${suffix#\"*}
+      suffix=${suffix%\"*}
+
+      if watch_suffix $suffix; then
+        suffixes="$suffixes $suffix"
+      fi
+    done
+
+  elif [ -f "$config" ]; then
+    for suffix in `sed -ne 's/^[[:space:]]*suffix[[:space:]]\+\(.\+\)/\1/p' "$config"`
+    do
+      suffix=${suffix#\"*}
+      suffix=${suffix%\"*}
+
+      if watch_suffix $suffix; then
+        suffixes="$suffixes $suffix"
+      fi
+    done
+
+  else
+    if ocf_is_probe; then
+      ocf_log info "slapd configuration '$config' does not exist during probe."
+    else
+      ocf_log err "slapd configuration '$config' does not exist."
+      return $OCF_ERR_INSTALLED
+    fi
+  fi
+
+  options="-LLL -s base -x"
+
+  if [ -n "$bind_dn" ]; then
+    options="$options -D $bind_dn -w $password"
+  fi
+
+  [ -z "$1" ] && err_option=""
+  for suffix in $suffixes; do
+    ocf_run -q $err_option "$ldapsearch" -H "$services" -b "$suffix" $options >/dev/null 2>&1; rc=$?
+
+    case "$rc" in
+      "0")
+        ocf_log debug "slapd database with suffix '$suffix' reachable"
+        ;;
+      "49")
+        ocf_log err "slapd database with suffix '$suffix' unreachable. Invalid credentials."
+        return $OCF_ERR_CONFIGURED
+        ;;
+      *)
+        if [ -z "$1" ] || [ -n "$1" -a $rc -ne 1 ]; then
+          ocf_log err "slapd database with suffix '$suffix' unreachable. exit code ($rc)"
+        fi
+        state=$OCF_ERR_GENERIC
+        ;;
+    esac
+  done
+
+  return $state
+}
+
+slapd_validate_all()
+{
+  check_binary "$slapd"
+  check_binary "$ldapsearch"
+
+  if [ -z "$pid_file" ]; then
+    if [ -d "$config" ]; then
+      pid_file=`sed -ne \
+	       's/^olcPidFile:[[:space:]]\+\(.\+\)[[:space:]]*/\1/p' \
+	       "$config"/'cn=config.ldif' 2>/dev/null`
+    elif [ -f "$config" ]; then
+      pid_file=`sed -ne \
+		's/^pidfile[[:space:]]\+\(.\+\)/\1/p' \
+		"$config" 2>/dev/null`
+    else
+      if ocf_is_probe; then
+        ocf_log info "slapd configuration '$config' does not exist during probe."
+      else
+        ocf_log err "slapd configuration '$config' does not exist."
+        return $OCF_ERR_INSTALLED
+      fi
+    fi
+  fi
+
+  if [ -z "$user" ]; then
+    user=`id -nu 2>/dev/null`
+  elif ! id "$user" >/dev/null 2>&1; then
+    ocf_log err "slapd user '$user' does not exist"
+    return $OCF_ERR_INSTALLED
+  fi
+
+  if [ -z "$group" ]; then
+    group=`id -ng 2>/dev/null`
+  elif ! grep "^$group:" /etc/group >/dev/null 2>&1; then
+    ocf_log err "slapd group '$group' does not exist"
+    return $OCF_ERR_INSTALLED
+  fi
+
+  pid_dir=`dirname "$pid_file"`
+  if [ ! -d "$pid_dir" ]; then
+    mkdir -p "$pid_dir"
+    chown -R "$user" "$pid_dir"
+    chgrp -R "$group" "$pid_dir"
+  fi
+
+  return $OCF_SUCCESS
+}
+
+#
+# Main
+#
+
+slapd=$OCF_RESKEY_slapd
+ldapsearch=$OCF_RESKEY_ldapsearch
+config=$OCF_RESKEY_config
+user=$OCF_RESKEY_user
+group=$OCF_RESKEY_group
+services=$OCF_RESKEY_services
+bind_dn=$OCF_RESKEY_bind_dn
+password=$OCF_RESKEY_password
+parameters=$OCF_RESKEY_parameters
+pid_file=$OCF_RESKEY_pidfile
+
+if [ -z "$config" ]; then
+  config_dirname="/etc/ldap"
+  if [ -e "/etc/openldap" ]; then
+    config_dirname="/etc/openldap"
+  fi
+
+  config="$config_dirname/slapd.conf"
+  if [ -e "$config_dirname/slapd.d" ]; then
+    config="$config_dirname/slapd.d"
+  fi
+fi
+
+if [ $# -ne 1 ]; then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+case $1 in
+  meta-data)
+    meta_data
+    exit $OCF_SUCCESS
+    ;;
+  usage|help)
+    usage
+    exit $OCF_SUCCESS
+    ;;
+esac
+
+slapd_validate_all
+rc=$?
+[ $rc -eq $OCF_SUCCESS ] || exit $rc
+
+case $1 in
+  status)
+    slapd_status `slapd_pid`; state=$?
+
+    if [ $state -eq $OCF_SUCCESS ]; then
+      ocf_log debug "slapd is running."
+    elif [ $state -eq $OCF_NOT_RUNNING ]; then
+      ocf_log debug "slapd is stopped."
+    fi
+
+    exit $state
+    ;;
+  start)
+    slapd_start
+    exit $?
+    ;;
+  stop)
+    slapd_stop
+    exit $?
+    ;;
+  monitor)
+    slapd_monitor; state=$?
+    exit $state
+    ;;
+  validate-all)
+    exit $OCF_SUCCESS
+    ;;
+  *)
+    usage
+    exit $OCF_ERR_UNIMPLEMENTED
+    ;;
+esac
diff --git a/heartbeat/symlink b/heartbeat/symlink
new file mode 100755
index 0000000..214092d
--- /dev/null
+++ b/heartbeat/symlink
@@ -0,0 +1,245 @@
+#!/bin/sh
+#
+#
+#   An OCF RA that manages a symlink
+#
+# Copyright (c) 2011 Dominik Klein
+#
+# 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.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+meta_data() {
+        cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="symlink">
+<version>1.1</version>
+
+<longdesc lang="en">
+This resource agent that manages a symbolic link (symlink).
+
+It is primarily intended to manage configuration files which should be
+enabled or disabled based on where the resource is running, such as
+cron job definitions and the like.
+</longdesc>
+<shortdesc lang="en">Manages a symbolic link</shortdesc>
+<parameters>
+<parameter name="link" required="1">
+<longdesc lang="en">
+Full path of the symbolic link to be managed. This must obviously be
+in a filesystem that supports symbolic links.
+</longdesc>
+<shortdesc lang="en">Full path of the symlink</shortdesc>
+<content type="string"/>
+</parameter>
+<parameter name="target" required="1">
+<longdesc lang="en">
+Full path to the link target (the file or directory which the symlink points to).
+</longdesc>
+<shortdesc lang="en">Full path to the link target</shortdesc>
+<content type="string" />
+</parameter>
+<parameter name="backup_suffix">
+<longdesc lang="en">
+A suffix to append to any files that the resource agent moves out of
+the way because they clash with "link".
+
+If this is unset (the default), then the resource agent will simply
+refuse to create a symlink if it clashes with an existing file.
+</longdesc>
+<shortdesc lang="en">Suffix to append to backup files</shortdesc>
+<content type="string" />
+</parameter>
+</parameters>
+<actions>
+<action name="start"   timeout="15" />
+<action name="stop"    timeout="15" />
+<action name="monitor" depth="0"  timeout="15" interval="60"/>
+<action name="meta-data"  timeout="5" />
+<action name="validate-all"  timeout="10" />
+</actions>
+</resource-agent>
+END
+}
+
+symlink_monitor() {
+    # This applies the following logic:
+    #
+    # * If $OCF_RESKEY_link does not exist, then the resource is
+    #   definitely stopped.
+    #
+    # * If $OCF_RESKEY_link exists and is a symlink that points to
+    #   ${OCF_RESKEY_target}, then the resource is definitely started.
+    #
+    # * If $OCF_RESKEY_link exists, but is anything other than a
+    #   symlink to ${OCF_RESKEY_target}, then the status depends on whether
+    #   ${OCF_RESKEY_backup_suffix} is set:
+    #
+    #   - if ${OCF_RESKEY_backup_suffix} is set, then the resource is
+    #     simply not running. The existing file will be moved out of
+    #     the way, to ${OCF_RESKEY_link}${OCF_RESKEY_backup_suffix},
+    #     when the resource starts.
+    #
+    #   - if ${OCF_RESKEY_backup_suffix} is not set, then an existing
+    #     file ${OCF_RESKEY_link} is an error condition, and the
+    #     resource can't start here.
+    rc=$OCF_ERR_GENERIC
+
+    # Using ls here instead of "test -e", as "test -e" returns false
+    # if the file does exist, but it a symlink to a file that doesn't
+    if ! ls "$OCF_RESKEY_link" >/dev/null 2>&1; then
+        ocf_log debug "$OCF_RESKEY_link does not exist"
+        rc=$OCF_NOT_RUNNING
+    elif [ ! -L  "$OCF_RESKEY_link" ]; then
+        if [ -z "$OCF_RESKEY_backup_suffix" ]; then
+            ocf_log err "$OCF_RESKEY_link exists but is not a symbolic link!"
+            exit $OCF_ERR_INSTALLED
+        else
+            ocf_log debug "$OCF_RESKEY_link exists but is not a symbolic link, will be moved to ${OCF_RESKEY_link}${OCF_RESKEY_backup_suffix} on start"
+            rc=$OCF_NOT_RUNNING
+        fi
+    elif readlink -f "$OCF_RESKEY_link" | egrep -q "^${OCF_RESKEY_target}$"; then
+        ocf_log debug "$OCF_RESKEY_link exists and is a symbolic link to ${OCF_RESKEY_target}."
+        rc=$OCF_SUCCESS
+    else
+        if [ -z "$OCF_RESKEY_backup_suffix" ]; then
+            ocf_log err "$OCF_RESKEY_link does not point to ${OCF_RESKEY_target}!"
+            exit $OCF_ERR_INSTALLED
+        else
+            ocf_log debug "$OCF_RESKEY_link does not point to ${OCF_RESKEY_target}, will be moved to ${OCF_RESKEY_link}${OCF_RESKEY_backup_suffix} on start"
+            rc=$OCF_NOT_RUNNING
+        fi
+    fi
+    return $rc
+}
+
+symlink_start() {
+    if ! symlink_monitor; then
+        if [ -e "$OCF_RESKEY_link" ]; then
+            if [ -z "$OCF_RESKEY_backup_suffix" ]; then
+                # Shouldn't happen, because symlink_monitor should
+                # have errored out. But there is a chance that
+                # something else put that file there after
+                # symlink_monitor ran.
+                ocf_log err "$OCF_RESKEY_link exists and no backup_suffix is set, won't overwrite."
+                exit $OCF_ERR_GENERIC
+            else
+                ocf_log debug "Found $OCF_RESKEY_link, moving to ${OCF_RESKEY_link}${OCF_RESKEY_backup_suffix}"
+                ocf_run mv -v "$OCF_RESKEY_link" "${OCF_RESKEY_link}${OCF_RESKEY_backup_suffix}" \
+                    || exit $OCF_ERR_GENERIC
+            fi
+        fi
+        ocf_run ln -sv "$OCF_RESKEY_target" "$OCF_RESKEY_link"
+        symlink_monitor
+        return $?
+    else
+        return $OCF_SUCCESS
+    fi
+}
+
+symlink_stop() {
+    if symlink_monitor; then   
+        ocf_run rm -vf "$OCF_RESKEY_link" || exit $OCF_ERR_GENERIC
+        if ! symlink_monitor; then
+            if [ -e "${OCF_RESKEY_link}${OCF_RESKEY_backup_suffix}" ]; then
+                ocf_log debug "Found backup ${OCF_RESKEY_link}${OCF_RESKEY_backup_suffix}, moving to $OCF_RESKEY_link"
+                # if restoring the backup fails then still return with
+                # $OCF_SUCCESS, but log a warning
+                ocf_run -warn mv "${OCF_RESKEY_link}${OCF_RESKEY_backup_suffix}" "$OCF_RESKEY_link"
+            fi
+            return $OCF_SUCCESS
+        else
+            ocf_log err "Removing $OCF_RESKEY_link failed."
+            return $OCF_ERR_GENERIC
+        fi
+    else
+        return $OCF_SUCCESS
+    fi
+}
+
+symlink_validate_all() {
+    if [ "x${OCF_RESKEY_link}" = "x" ]; then
+        ocf_log err "Mandatory parameter link is unset"
+        exit $OCF_ERR_CONFIGURED
+    fi
+    if [ "x${OCF_RESKEY_target}" = "x" ]; then
+        ocf_log err "Mandatory parameter target is unset"
+        exit $OCF_ERR_CONFIGURED
+    fi
+
+    # Having a non-existant target is technically not an error, as
+    # symlinks are allowed to point to non-existant paths. But it
+    # still doesn't hurt to warn people if the target does not exist
+    # (but only during non-probes).
+    if [ ! -e "${OCF_RESKEY_target}" ]; then
+        ocf_log warn "${OCF_RESKEY_target} does not exist!"
+    fi
+}
+
+symlink_usage() {
+        cat <<EOF
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+Expects to have a fully populated OCF RA-compliant environment set.
+EOF
+}
+
+if [ $# -ne 1 ]; then
+        symlink_usage
+        exit $OCF_ERR_ARGS
+fi
+
+case $__OCF_ACTION in
+meta-data)
+        meta_data
+        exit $OCF_SUCCESS
+        ;;
+usage)
+        symlink_usage
+        exit $OCF_SUCCESS
+esac
+
+# Everything except usage and meta-data must pass the validate test
+symlink_validate_all || exit
+
+case $__OCF_ACTION in
+start)
+        symlink_start
+        ;;
+stop)
+        symlink_stop
+        ;;
+status|monitor)
+        symlink_monitor
+        ;;
+validate-all)
+        ;;
+*)
+        symlink_usage
+        exit $OCF_ERR_UNIMPLEMENTED
+esac
+# exit code is the exit code (return code) of the last command (shell function)
diff --git a/heartbeat/syslog-ng b/heartbeat/syslog-ng
new file mode 100755
index 0000000..dfca65a
--- /dev/null
+++ b/heartbeat/syslog-ng
@@ -0,0 +1,372 @@
+#!/bin/bash
+#
+# Description:  Manages a syslog-ng instance, provided by NTT OSSC as an 
+#               OCF High-Availability resource under Heartbeat/LinuxHA control
+#
+# Copyright (c) 2009 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+##############################################################################
+# OCF parameters:
+#   OCF_RESKEY_syslog_ng_binary : Path to syslog-ng binary.
+#                                 Default is "/sbin/syslog-ng"
+#   OCF_RESKEY_configfile       : Configuration file
+#   OCF_RESKEY_start_opts       : Startup options
+#   OCF_RESKEY_kill_term_timeout: Number of seconds to await to confirm a 
+#                                 normal stop method
+#
+#   Only OCF_RESKEY_configfile must be specified. Each of the rests 
+#   has its default value or refers OCF_RESKEY_configfile to make
+#   its value when no explicit value is given.
+#
+# Further infomation for setup:
+#   There are sample configurations at the end of this file.
+#
+###############################################################################
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+usage() 
+{
+	cat <<-!
+usage: $0 action
+
+action:
+        start       : start a new syslog-ng instance
+
+        stop        : stop the running syslog-ng instance
+
+        status      : return the status of syslog-ng, run or down
+
+        monitor     : return TRUE if the syslog-ng appears to be working.
+
+        meta-data   : show meta data message
+
+        validate-all: validate the instance parameters
+!
+	return $OCF_ERR_UNIMPLEMENTED
+}
+
+metadata_syslog_ng()
+{
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="syslog-ng">
+<version>1.0</version>
+
+<longdesc lang="en">
+This script manages a syslog-ng instance as an HA resource.
+</longdesc>
+<shortdesc lang="en">Syslog-ng resource agent</shortdesc>
+
+<parameters>
+
+<parameter name="configfile" unique="0" required="1">
+<longdesc lang="en">
+This parameter specifies a configuration file 
+for a syslog-ng instance managed by this RA.
+</longdesc>
+<shortdesc>Configuration file</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="syslog_ng_binary" unique="0">
+<longdesc lang="en">
+This parameter specifies syslog-ng's executable file.
+</longdesc>
+<shortdesc>syslog-ng executable</shortdesc>
+<content type="string" default="/sbin/syslog-ng"/>
+</parameter>
+
+<parameter name="start_opts" unique="0">
+<longdesc lang="en">
+This parameter specifies startup options for a 
+syslog-ng instance managed by this RA. When no value is given, no startup 
+options is used. Don't use option '-F'. It causes a stuck of a start action.
+</longdesc>
+<shortdesc>Start options</shortdesc>
+<content type="string" default=""/>
+</parameter>
+
+<parameter name="kill_term_timeout" unique="0">
+<longdesc lang="en">
+On a stop action, a normal stop method(pkill -TERM) is firstly used.
+And then the confirmation of its completion is waited for
+the specified seconds by this parameter.
+The default value is 10.
+</longdesc>
+<shortdesc>Number of seconds to await to confirm a normal stop method</shortdesc>
+<content type="integer" default="10"/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="60s" />
+<action name="stop" timeout="120s" />
+<action name="status" timeout="60s" />
+<action name="monitor" depth="0" timeout="60s" interval="60s" />
+<action name="meta-data" timeout="5s" />
+<action name="validate-all"  timeout="5"/>
+</actions>
+</resource-agent>
+END
+	return $OCF_SUCCESS
+}
+
+monitor_syslog_ng()
+{
+	set -- $(pgrep -f "$PROCESS_PATTERN" 2>/dev/null)
+	case $# in
+		0) ocf_log debug "No syslog-ng process for $CONFIGFILE"
+		   return $OCF_NOT_RUNNING;;
+		1) return $OCF_SUCCESS;;
+	esac
+	ocf_log warn "Multiple syslog-ng process for $CONFIGFILE"
+	return $OCF_SUCCESS
+}
+
+start_syslog_ng()
+{
+	monitor_syslog_ng
+	if [[ $? = "$OCF_SUCCESS" ]]; then
+		return $OCF_SUCCESS
+	fi
+
+	# set -- $SYSLOG_NG_OPTS
+	# ocf_run "$SYSLOG_NG_EXE" -f "$SYSLOG_NG_CONF" "$@"
+	# reduce to this?
+	ocf_run "$SYSLOG_NG_EXE" -f "$CONFIGFILE" $START_OPTS
+	ocf_status=$?
+	if [[ "$ocf_status" != "$OCF_SUCCESS" ]]; then
+		return $OCF_ERR_GENERIC
+	fi
+
+	while true; do
+		monitor_syslog_ng
+		if [[ $? = "$OCF_SUCCESS" ]]; then
+			return $OCF_SUCCESS
+		fi
+		sleep 1
+	done
+}
+
+stop_syslog_ng()
+{
+	pkill -TERM -f "$PROCESS_PATTERN"
+
+	typeset lapse_sec=0
+	while pgrep -f "$PROCESS_PATTERN" > /dev/null; do
+		sleep 1
+		lapse_sec=$(( lapse_sec + 1 ))
+		ocf_log debug "stop_syslog_ng[$SYSLOG_NG_NAME]: stop NORM $lapse_sec/$KILL_TERM_TIMEOUT"
+		if [ $lapse_sec -ge $KILL_TERM_TIMEOUT ]; then
+			break
+		fi
+	done
+
+	# if the process can't be removed, then the following part is
+	# not going to be executed (the RA will be killed by lrmd on
+	# timeout) and the pidfile will remain; don't know if that
+	# has any consequences
+	# 2009/09/18 Nakahira
+	# If the syslog-ng process hangs, syslog-ng RA waits
+	# $KILL_TERM_TIMEOUT seconds.
+	# The stop timeout of RA should be longer than $KILL_TERM_TIMEOUT.
+	lapse_sec=0
+	while pgrep -f "$PROCESS_PATTERN" > /dev/null; do
+		pkill -KILL -f "$PROCESS_PATTERN"
+		sleep 1
+		lapse_sec=$(( lapse_sec + 1 ))
+		ocf_log debug "stop_syslog_ng[$SYSLOG_NG_NAME]: suspend syslog_ng by SIGKILL ($lapse_sec/@@@)"
+	done
+
+	return $OCF_SUCCESS
+}
+
+status_syslog_ng()
+{
+	# ???? why not monitor and then print running or stopped
+	monitor_syslog_ng
+	rc=$?
+	if [ $rc = $OCF_SUCCESS ]; then
+		echo "Syslog-ng service is running."
+	elif [ $rc = $OCF_NOT_RUNNING ]; then
+		echo "Syslog-ng service is stopped."
+	else
+		echo "Mutiple syslog-ng process for $CONFIGFILE."
+	fi
+	return $rc
+}
+
+validate_all_syslog_ng()
+{
+	ocf_log info "validate_all_syslog_ng[$SYSLOG_NG_NAME]"
+	return $OCF_SUCCESS
+}
+
+if [[ "$1" = "meta-data" ]]; then
+	metadata_syslog_ng
+	exit $?
+fi
+
+CONFIGFILE="${OCF_RESKEY_configfile}"
+if [[ -z "$CONFIGFILE" ]]; then
+	ocf_log err "undefined parameter:configfile"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+SYSLOG_NG_NAME=${CONFIGFILE##*/}
+SYSLOG_NG_NAME=${SYSLOG_NG_NAME%.*}
+
+SYSLOG_NG_EXE="${OCF_RESKEY_syslog_ng_binary-/sbin/syslog-ng}"
+# why not default to /sbin/syslog-ng?
+#if [[ -z "$SYSLOG_NG_EXE" ]]; then
+#	ocf_log err "Undefined parameter:syslog_ng_binary"
+#	exit $OCF_ERR_CONFIGURED
+#fi
+if [[ ! -x "$SYSLOG_NG_EXE" ]]; then
+	ocf_log err "Invalid value:syslog_ng_binary:$SYSLOG_NG_EXE"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+# actually, the pidfile has no function; the status is checked by
+# testing for a running process only
+
+KILL_TERM_TIMEOUT="${OCF_RESKEY_kill_term_timeout-10}"
+if ! ocf_is_decimal "$KILL_TERM_TIMEOUT"; then
+	ocf_log err "Invalid value:kill_term_timeout:$KILL_TERM_TIMEOUT"
+	exit $OCF_ERR_CONFIGURED
+fi
+
+START_OPTS=${OCF_RESKEY_start_opts}
+PROCESS_PATTERN="$SYSLOG_NG_EXE -f $CONFIGFILE"
+
+COMMAND=$1
+
+case "$COMMAND" in
+	start)
+		ocf_log debug  "[$SYSLOG_NG_NAME] Enter syslog_ng start"
+		start_syslog_ng
+		func_status=$?
+		ocf_log debug  "[$SYSLOG_NG_NAME] Leave syslog_ng start $func_status"
+		exit $func_status
+		;;
+	stop)
+		ocf_log debug  "[$SYSLOG_NG_NAME] Enter syslog_ng stop"
+		stop_syslog_ng
+		func_status=$?
+		ocf_log debug  "[$SYSLOG_NG_NAME] Leave syslog_ng stop $func_status"
+		exit $func_status
+		;;
+	status)
+		status_syslog_ng
+		exit $?
+		;;
+	monitor)
+		#ocf_log debug  "[$SYSLOG_NG_NAME] Enter syslog_ng monitor"
+		monitor_syslog_ng
+		func_status=$?
+		#ocf_log debug  "[$SYSLOG_NG_NAME] Leave syslog_ng monitor $func_status"
+		exit $func_status
+		;;
+	validate-all)
+		validate_all_syslog_ng
+		exit $?
+		;;
+	*)
+		usage
+		;;
+esac
+
+# vim: set sw=4 ts=4 :
+
+### A sample snippet of cib.xml for a syslog-ng resource
+##
+#         <primitive id="prmApSyslog-ng" class="ocf" type="syslog-ng" provider="heartbeat">
+#           <instance_attributes id="prmDummyB_instance_attrs">
+#             <attributes>
+#	       <nvpair id="atr:Syslog-ng:syslog-ng:configfile" name="configfile" value="/etc/syslog-ng/syslog-ng-ext.conf"/>
+#             </attributes>
+#           </instance_attributes>
+#           <operations>
+#             <op id="op:prmSyslog-ng:start"   name="start" timeout="60s" on_fail="restart"/>
+#             <op id="op:prmSyslog-ng:monitor" name="monitor" interval="10s" timeout="60s" on_fail="restart"/>
+#             <op id="op:prmSyslog-ng:stop"    name="stop" timeout="60s" on_fail="block"/>
+#           </operations>
+#         </primitive>
+
+### A sample syslog-ng configuration file for a log collecting host
+### 
+### This sample is for a log collecting host by syslog-ng.
+### A syslog-ng process configurated by this sample accepts all messages
+### from a certain network. Any message from the network is preserved into
+### a file for security infomation. Restricting messages to "authpriv" from
+### the network is done on log sending hosts. (See the sample below)
+### Any internal message of the syslog-ng process is preserved into its 
+### dedicated file. And any "authpriv" internal message of the syslog-ng 
+### process is also preserved into the security infomation file.
+###
+### Change "f_incoming" to suit your enviroment.
+### If you use it as a configuration file for the sample cib.xml above,
+### save it into "/etc/syslog-ng/syslog-ng-ext.conf".
+##
+#options {
+#    sync (0);
+#    time_reopen (10);
+#    log_fifo_size (1000);
+#    long_hostnames (off);
+#    use_dns (yes);
+#    use_fqdn (no);
+#    create_dirs (no);
+#    keep_hostname (yes); };
+#
+#source s_internal { internal(); };
+#source s_incoming { udp(port(514)); };
+#filter f_internal { facility(authpriv); };
+#filter f_incoming { netmask("172.20.0.0/255.255.192.0"); };
+#
+#destination d_internal { file("/var/log/syslog-ng-ext.log" perm(0640));};
+#destination d_incoming {
+#    file("/var/log/secure-ext.log" create_dirs(yes) perm(0640)); };
+#
+#log { source(s_internal); destination(d_internal); };
+#log { source(s_internal); filter(f_internal); destination(d_incoming); };
+#log { source(s_incoming); filter(f_incoming); destination(d_incoming); };
+
+### A sample snippet of syslog-ng configuration file for a log sending host
+###
+### This sample is for a log sending host that uses syslog-ng.
+###
+### Replace "syslog-ng-ext" to the IP address or the hostname of your
+### log collecting host and append it to "syslog-ng.conf" of each log sending
+### host. See the install default syslog-ng.conf to know what "s_sys" and 
+### "f_auth" are.
+##
+#destination d_outgoing  { udp("syslog-ng-ext" port(514)); };
+#log { source(s_sys); filter(f_auth); destination(d_outgoing); };
+
+### A sample snippet of syslog configuration file for a log sending host
+###
+### This sample is for a log sending host that uses syslog.
+###
+### Replace "syslog-ng-ext" to the IP address or the hostname of your
+### log collecting host and append it to "syslog.conf" of each log sending
+### host.
+##
+# authpriv.*                                              @syslog-ng-ext
diff --git a/heartbeat/tomcat b/heartbeat/tomcat
new file mode 100755
index 0000000..23a7e2f
--- /dev/null
+++ b/heartbeat/tomcat
@@ -0,0 +1,720 @@
+#!/bin/sh
+#
+# Description:  Manages a Tomcat Server as an OCF High-Availability
+#               resource under Heartbeat/LinuxHA control
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA  
+# 02110-1301, USA.
+#
+# Copyright (c) 2007 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+#
+#######################################################################
+# OCF parameters:
+#   OCF_RESKEY_tomcat_name - The name of the resource. Default is tomcat
+#   OCF_RESKEY_script_log  - A destination of the log of this script. Default /var/log/OCF_RESKEY_tomcat_name.log
+#   OCF_RESKEY_tomcat_stop_timeout  - Time-out at the time of the stop. Default is 5. DEPRECATED
+#   OCF_RESKEY_tomcat_suspend_trialcount  - The re-try number of times awaiting a stop. Default is 10. DEPRECATED
+#   OCF_RESKEY_tomcat_user  - A user name to start a resource.
+#   OCF_RESKEY_statusurl - URL for state confirmation. Default is http://127.0.0.1:8080
+#   OCF_RESKEY_max_stop_time - The max time it should take for proper shutdown. Restrictions, only Tomcat6.
+#   OCF_RESKEY_java_home - Home directory of Java. Default is none
+#   OCF_RESKEY_java_opts - Options to pass to Java JVM for start and stop. Default is none
+#   OCF_RESKEY_catalina_home - Home directory of Tomcat. Default is none
+#   OCF_RESKEY_catalina_base - Base directory of Tomcat. Default is OCF_RESKEY_catalina_home
+#   OCF_RESKEY_catalina_out - Log file name of Tomcat. Default is OCF_RESKEY_catalina_base/logs/catalina.out
+#   OCF_RESKEY_catalina_pid  - A PID file name of Tomcat. Default is OCF_RESKEY_catalina_base/logs/catalina.pid
+#   OCF_RESKEY_tomcat_start_opts - Start options of Tomcat. Default is none.
+#   OCF_RESKEY_catalina_opts - CATALINA_OPTS environment variable. Default is none.
+#   OCF_RESKEY_catalina_tmpdir - CATALINA_TMPDIR environment variable. Default is none.
+#   OCF_RESKEY_catalina_rotate_log - Control catalina.out logrotation flag. Default is NO.
+#   OCF_RESKEY_catalina_rotatetime - catalina.out logrotation time span(seconds). Default is 86400.
+#   OCF_RESKEY_java_endorsed_dirs - JAVA_ENDORSED_DIRS environment variable. Default is none.
+#   OCF_RESKEY_logging_config - LOGGING_CONFIG environment variable. Default is none.
+#   OCF_RESKEY_logging_manager - LOGGING_MANAGER environment variable. Default is none.
+###############################################################################
+
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+############################################################################
+# Usage
+usage() 
+{
+	cat <<-!
+usage: $0 action
+
+action:
+        start   start Tomcat
+
+        stop    stop Tomcat
+
+        status  return the status of Tomcat, up or down
+
+        monitor  return TRUE if Tomcat appears to be working.
+                 You have to have installed $WGETNAME for this to work.
+
+        meta-data       show meta data message
+
+        validate-all    validate the instance parameters
+!
+}
+
+############################################################################
+# Check tomcat service availability
+isrunning_tomcat()
+{
+	$WGET --tries=20 -O /dev/null $RESOURCE_STATUSURL >/dev/null 2>&1
+}
+
+############################################################################
+# 
+isalive_tomcat()
+{
+	# As the server stops, the PID file disappears. To avoid race conditions, 
+	# we will have remembered the PID of a running instance on script entry.
+	local pid=$rememberedPID
+	# If there is a PID file, attempt to use that
+	if [ -f $CATALINA_PID ]; then
+		local tmp
+		ocf_log debug "Reading pid from $CATALINA_PID"
+		tmp=`head -n 1 $CATALINA_PID`
+		if [ $? -eq 0 ]; then
+			pid=$tmp
+		fi
+	fi
+	if [ -n "$pid" ] && [ "$pid" -gt 0 ]; then
+		# Retry message for restraint
+		ocf_log debug "Sending noop signal to $pid"
+		kill -s 0 $pid >/dev/null 2>&1
+		return $?
+	fi
+	# No PID file
+	false
+}
+
+############################################################################
+# Check rotatelogs process and restart if it is stopped
+monitor_rotatelogs()
+{
+	pgrep -f "$ROTATELOGS.*$CATALINA_BASE/logs/catalina_%F.log" > /dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		ocf_log warn "A rotatelogs command for $CATALINA_BASE/logs/catalina_%F.log is not running. Restarting it."
+		start_rotatelogs
+		if [ $? -eq 0 ]; then
+			ocf_log info "Restart rotatelogs process succeeded."
+		else
+			ocf_log warn "Restart rotatelogs process failed."
+		fi
+	fi
+}
+
+############################################################################
+# Check tomcat process and service availability
+monitor_tomcat()
+{
+	isalive_tomcat ||
+		return $OCF_NOT_RUNNING
+	isrunning_tomcat ||
+		return $OCF_ERR_GENERIC
+	if ocf_is_true ${CATALINA_ROTATE_LOG}; then
+		# Monitor rotatelogs process and restart it if it is stopped.
+		# And never consider rotatelogs process failure to be a monitor failure
+		# as long as Tomcat process works fine.
+		monitor_rotatelogs
+	fi
+	return $OCF_SUCCESS
+}
+
+############################################################################
+# Startup rotatelogs process
+start_rotatelogs()
+{
+	# -s is required because tomcat5.5's login shell is /bin/false
+	su - -s /bin/sh $RESOURCE_TOMCAT_USER \
+        	-c "$ROTATELOGS -l \"$CATALINA_BASE/logs/catalina_%F.log\" $CATALINA_ROTATETIME" \
+        	< "$CATALINA_OUT" > /dev/null 2>&1 &
+}
+
+############################################################################
+# Execute catalina.out log rotation
+rotate_catalina_out()
+{
+	# Check catalina_%F.log is writable or not.
+	CURRENT_ROTATELOG_SUFFIX=`date +"%F"`
+	su - -s /bin/sh $RESOURCE_TOMCAT_USER \
+		-c "touch \"$CATALINA_BASE/logs/catalina_$CURRENT_ROTATELOG_SUFFIX.log\"" > /dev/null 2>&1
+	if [ $? -ne 0 ]; then
+		ocf_log err "$CATALINA_BASE/logs/catalina_$CURRENT_ROTATELOG_SUFFIX.log is not writable."
+		return $OCF_ERR_GENERIC
+	fi
+
+	# Clean up and set permissions on required files
+	rm -rf "$CATALINA_BASE"/temp/*
+	if [ -p "$CATALINA_OUT" ]; then
+		rm -f "$CATALINA_OUT"
+	elif [ -e "$CATALINA_OUT" ]; then
+		DATE=`date +"%F-%H%M%S"`
+		ocf_log warn "$CATALINA_OUT already exists. It is saved as $CATALINA_OUT-$DATE"
+		mv "$CATALINA_OUT" "$CATALINA_OUT-$DATE"
+	fi
+	mkfifo -m700 "$CATALINA_OUT"
+	chown --dereference "$RESOURCE_TOMCAT_USER" "$CATALINA_OUT" || true
+
+	start_rotatelogs
+}
+
+############################################################################
+# Tomcat Command
+tomcatCommand()
+{
+cat<<-END_TOMCAT_COMMAND
+	export JAVA_HOME=${JAVA_HOME}
+	export JAVA_OPTS="${JAVA_OPTS}"
+	export CATALINA_HOME=${CATALINA_HOME}
+	export CATALINA_BASE=${CATALINA_BASE}
+	export CATALINA_OUT=${CATALINA_OUT}
+	export CATALINA_PID=${CATALINA_PID}
+	export CATALINA_OPTS="${CATALINA_OPTS}"
+	export CATALINA_TMPDIR="${CATALINA_TMPDIR}"
+	export JAVA_ENDORSED_DIRS="${JAVA_ENDORSED_DIRS}"
+	export LOGGING_CONFIG="${LOGGING_CONFIG}"
+	export LOGGING_MANAGER="${LOGGING_MANAGER}"
+	export TOMCAT_CFG=${TOMCAT_CFG}
+	$TOMCAT_START_SCRIPT $@
+END_TOMCAT_COMMAND
+}
+attemptTomcatCommand()
+{
+	if [ -n "$REDIRECT_DEFAULT_CONFIG" ]; then
+		export TOMCAT_CFG=$(mktemp ${HA_RSCTMP}/tomcat-tmp-XXXXX.cfg)
+	fi
+
+	if [ "$RESOURCE_TOMCAT_USER" = root ]; then
+		"$TOMCAT_START_SCRIPT" $@ >> "$TOMCAT_CONSOLE" 2>&1
+	else
+		tomcatCommand $@ | su - -s /bin/sh "$RESOURCE_TOMCAT_USER" >> "$TOMCAT_CONSOLE" 2>&1
+	fi
+
+	if [ -n "$REDIRECT_DEFAULT_CONFIG" ]; then
+		rm -f "$TOMCAT_CFG"
+	fi
+}
+
+############################################################################
+# Start Tomcat
+start_tomcat()
+{
+	cd "$CATALINA_HOME/bin"
+
+	validate_all_tomcat || exit $?
+
+	monitor_tomcat
+	if [ $? -eq $OCF_SUCCESS ]; then
+		return $OCF_SUCCESS
+	fi
+
+	# Remove $CATALINA_PID if it exists
+	rm -f $CATALINA_PID
+
+	#ocf_log debug "catalina.out rotation FLG = ${CATALINA_ROTATE_LOG}"
+	if ocf_is_true ${CATALINA_ROTATE_LOG}; then
+		rotate_catalina_out
+		if [ $? -eq 0 ]; then
+			ocf_log debug "Rotate catalina.out succeeded."
+		else
+			ocf_log err "Rotate catalina.out failed. Avoid starting tomcat without catalina.out rotation."
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+	
+	echo "`date "+%Y/%m/%d %T"`: start ===========================" >> "$TOMCAT_CONSOLE"
+
+	ocf_log debug "CATALINA_OPTS value = ${CATALINA_OPTS}"
+	attemptTomcatCommand start ${TOMCAT_START_OPTS} &
+
+	while true; do
+		monitor_tomcat
+		if [ $? -eq $OCF_SUCCESS ]; then
+			break
+		fi
+		ocf_log debug "start_tomcat[$TOMCAT_NAME]: retry monitor_tomcat"
+		sleep 3
+	done
+
+	return $OCF_SUCCESS
+}
+
+############################################################################
+# Stop Tomcat
+stop_tomcat()
+{
+	local stop_time
+	local RA_TIMEOUT=20
+	local TOMCAT_STOP_OPTS=""
+
+	if [ -n $OCF_RESKEY_CRM_meta_timeout ]; then
+		RA_TIMEOUT=$((OCF_RESKEY_CRM_meta_timeout/1000))
+	fi
+
+	STOP_TIMEOUT=$((RA_TIMEOUT-5))
+	if [ -n "$MAX_STOP_TIME" ]; then
+		if [ $MAX_STOP_TIME -gt $RA_TIMEOUT ]; then
+			ocf_log warn "max_stop_timeout must be shorter than the timeout of stop operation."
+		fi
+		if [ $MAX_STOP_TIME -eq 0 ]; then
+			STOP_TIMEOUT=$RA_TIMEOUT
+		else
+			STOP_TIMEOUT=$MAX_STOP_TIME
+		fi
+	fi
+
+	cd "$CATALINA_HOME/bin"
+
+	memorize_pid # This lets monitoring continue to work reliably
+
+	echo "`date "+%Y/%m/%d %T"`: stop  ###########################" >> "$TOMCAT_CONSOLE"
+
+	if [ "$TOMCAT_START_SCRIPT" = "$CATALINA_HOME/bin/catalina.sh" ]; then
+		TOMCAT_STOP_OPTS="$STOP_TIMEOUT --force"
+	fi
+	stop_time=$(date +%s)
+	attemptTomcatCommand stop $TOMCAT_STOP_OPTS
+
+	lapse_sec=0
+	while isalive_tomcat; do
+		sleep 1
+		lapse_sec=`expr $(date +%s) - $stop_time`
+		if [ $lapse_sec -ge $STOP_TIMEOUT ]; then
+			ocf_log debug "stop_tomcat[$TOMCAT_NAME]: stop failed, killing with SIGKILL ($lapse_sec)"
+			kill -s KILL $rememberedPID > /dev/null 2>&1
+		fi
+	done
+
+	if ocf_is_true ${CATALINA_ROTATE_LOG}; then
+		rm -f "$CATALINA_PID" "${CATALINA_OUT}"
+	else
+		rm -f "$CATALINA_PID"
+	fi
+	return $OCF_SUCCESS
+}
+
+metadata_tomcat()
+{
+    cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="tomcat">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for Tomcat. It manages a Tomcat instance as a cluster resource.
+</longdesc>
+<shortdesc lang="en">Manages a Tomcat servlet environment instance</shortdesc>
+
+<parameters>
+
+<parameter name="tomcat_name" unique="1" >
+<longdesc lang="en"><![CDATA[
+The name of the resource, added as a Java parameter in JAVA_OPTS:
+-Dname=<tomcat_name> to Tomcat process on start. Used to ensure
+process is still running and must be unique.
+]]></longdesc>
+<shortdesc>The name of the resource</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="script_log" unique="1">
+<longdesc lang="en">
+Log file, used during start and stop operations.
+</longdesc>
+<shortdesc>Log file</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="tomcat_stop_timeout" unique="0">
+<longdesc lang="en">
+Time-out for stop operation. DEPRECATED
+</longdesc>
+<shortdesc>Time-out for the stop operation. DEPRECATED</shortdesc>
+<content type="integer" default="" />
+</parameter>
+
+<parameter name="tomcat_suspend_trialcount" unique="0">
+<longdesc lang="en">
+Maximum number of times to retry stop operation before suspending
+and killing Tomcat. DEPRECATED. Does not retry.
+</longdesc>
+<shortdesc>Max retry count for stop operation. DEPRECATED</shortdesc>
+<content type="integer" default="" />
+</parameter>
+
+<parameter name="tomcat_user" unique="0">
+<longdesc lang="en">
+The user who starts Tomcat.
+</longdesc>
+<shortdesc>The user who starts Tomcat</shortdesc>
+<content type="string" default="root" />
+</parameter>
+
+<parameter name="statusurl" unique="0">
+<longdesc lang="en">
+URL for state confirmation.
+</longdesc>
+<shortdesc>URL for state confirmation</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="max_stop_time" unique="0">
+<longdesc lang="en">
+Number of seconds to wait during a stop before drastic measures
+(force kill) are used on the tomcat process. 
+This number MUST be less than your cluster stop timeout for the resource.
+The default value is five seconds before the timeout value of stop operation.
+When it is over this value, it stops a process in kill commands.
+This parameter is only effective on Tomcat 6 or later.
+</longdesc>
+<shortdesc>The max time it should take for proper shutdown.</shortdesc>
+<content type="integer" default="" />
+</parameter>
+
+<parameter name="java_home" unique="0" required="1">
+<longdesc lang="en">
+Home directory of Java.
+</longdesc>
+<shortdesc>Home directory of Java</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="java_opts" unique="0">
+<longdesc lang="en">
+Java JVM options used on start and stop.
+</longdesc>
+<shortdesc>Java options parsed to JVM, used on start and stop.</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="catalina_home" unique="0" required="1">
+<longdesc lang="en">
+Home directory of Tomcat.
+</longdesc>
+<shortdesc>Home directory of Tomcat</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="catalina_base" unique="1">
+<longdesc lang="en">
+Instance directory of Tomcat
+</longdesc>
+<shortdesc>Instance directory of Tomcat, defaults to catalina_home</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="catalina_out" unique="1">
+<longdesc lang="en">
+Log file name of Tomcat
+</longdesc>
+<shortdesc>Log file name of Tomcat, defaults to catalina_base/logs/catalina.out</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="catalina_pid" unique="1">
+<longdesc lang="en">
+A PID file name for Tomcat.
+</longdesc>
+<shortdesc>A PID file name for Tomcat</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="tomcat_start_script" unique="0" required="0">
+<longdesc lang="en">
+Absolute path to the custom tomcat start script to use.
+</longdesc>
+<shortdesc>Tomcat start script location</shortdesc>
+<content type="string" default="$TOMCAT_START_SCRIPT" />
+</parameter>
+
+<parameter name="tomcat_start_opts" unique="0">
+<longdesc lang="en">
+Tomcat start options.
+</longdesc>
+<shortdesc>Tomcat start options</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="catalina_opts" unique="0">
+<longdesc lang="en">
+Catalina options, for the start operation only.
+</longdesc>
+<shortdesc>Catalina options</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="catalina_tmpdir" unique="1">
+<longdesc lang="en">
+Temporary directory of Tomcat
+</longdesc>
+<shortdesc>Temporary directory of Tomcat, defaults to none</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="catalina_rotate_log" unique="0">
+<longdesc lang="en">
+Rotate catalina.out flag.
+</longdesc>
+<shortdesc>Rotate catalina.out flag</shortdesc>
+<content type="boolean" default="NO" />
+</parameter>
+
+<parameter name="catalina_rotatetime" unique="0">
+<longdesc lang="en">
+catalina.out rotation interval (seconds).
+</longdesc>
+<shortdesc>catalina.out rotation interval (seconds)</shortdesc>
+<content type="integer" default="" />
+</parameter>
+
+<parameter name="java_endorsed_dirs" unique="1">
+<longdesc lang="en">
+Java_endorsed_dirs of tomcat
+</longdesc>
+<shortdesc>Java_endorsed_dirs of Tomcat, defaults to none</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="logging_config" unique="1">
+<longdesc lang="en">
+Logging_config of tomcat
+</longdesc>
+<shortdesc>Logging_config of Tomcat, defaults to none</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="logging_manager" unique="1">
+<longdesc lang="en">
+Logging_manager of tomcat
+</longdesc>
+<shortdesc>Logging_manager of Tomcat, defaults to none.</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="60s" />
+<action name="stop" timeout="120s" />
+<action name="status" timeout="60" />
+<action name="monitor" depth="0" timeout="30s" interval="10s" />
+<action name="meta-data" timeout="5s" />
+<action name="validate-all"  timeout="5"/>
+</actions>
+</resource-agent>
+END
+	return $OCF_SUCCESS
+}
+
+validate_all_tomcat()
+{
+	local port
+	local rc=$OCF_SUCCESS
+	ocf_log info "validate_all_tomcat[$TOMCAT_NAME]"
+
+	check_binary $WGET
+
+	if [ -z "${TOMCAT_START_SCRIPT}" ]; then
+		ocf_log err "No default tomcat start script detected. Please specify start script location using the 'tomcat_start_script' option"
+		rc=$OCF_ERR_CONFIGURED
+	fi
+
+	if [ -n "$MAX_STOP_TIME" ] && [ "$MAX_STOP_TIME" -lt 0 ]; then
+		ocf_log err "max_stop_time must be set to a value greater than 0."
+		rc=$OCF_ERR_CONFIGURED
+	fi
+
+	if echo "$RESOURCE_STATUSURL" | grep -q ":[0-9][0-9]*" ; then
+		port=${RESOURCE_STATUSURL##*:}
+		port=${port%%/*}
+		ocf_log debug "Tomcat port is $port"
+		ocf_log debug "grep port=\"$port\" $CATALINA_BASE/conf/server.xml"
+		grep "port=\"$port\"" $CATALINA_BASE/conf/server.xml > /dev/null 2>&1
+		if [ $? -ne 0 ]; then
+			ocf_log err "Your configured status URL specifies a port ($port), but the server does not have a connector listening to that port in $CATALINA_BASE/conf/server.xml"
+			rc=$OCF_ERR_INSTALLED
+		fi
+	fi
+
+	if ocf_is_true ${CATALINA_ROTATE_LOG}; then
+		if [ ! -x "$ROTATELOGS" ]; then
+			ocf_log err "rotatelogs command does not exist."
+			rc=$OCF_ERR_INSTALLED
+		fi
+	fi
+
+	return $rc
+}
+
+# As we stop tomcat, it removes it's own pid file...we still want to know what it was
+memorize_pid()
+{
+	if [ -f $CATALINA_PID ]; then
+		rememberedPID=$(cat $CATALINA_PID)
+	fi
+}
+
+#
+### tomcat RA environment variables
+#
+
+COMMAND=$1
+TOMCAT_NAME="${OCF_RESKEY_tomcat_name-tomcat}"
+TOMCAT_CONSOLE="${OCF_RESKEY_script_log-/var/log/$TOMCAT_NAME.log}"
+RESOURCE_TOMCAT_USER="${OCF_RESKEY_tomcat_user-root}"
+RESOURCE_STATUSURL="${OCF_RESKEY_statusurl-http://127.0.0.1:8080}"
+
+JAVA_HOME="${OCF_RESKEY_java_home}"
+JAVA_OPTS="${OCF_RESKEY_java_opts}"
+CATALINA_HOME="${OCF_RESKEY_catalina_home}"
+CATALINA_BASE="${OCF_RESKEY_catalina_base-${OCF_RESKEY_catalina_home}}"
+CATALINA_OUT="${OCF_RESKEY_catalina_out-$CATALINA_BASE/logs/catalina.out}"
+
+CATALINA_PID=$OCF_RESKEY_catalina_pid
+if [ -z "$CATALINA_PID" ]; then
+	mkdir -p "${HA_RSCTMP}/${TOMCAT_NAME}_tomcatstate/"
+	if [ "${RESOURCE_TOMCAT_USER}" != "root" ]; then
+		chown ${RESOURCE_TOMCAT_USER} "${HA_RSCTMP}/${TOMCAT_NAME}_tomcatstate/"
+	fi
+	CATALINA_PID="${HA_RSCTMP}/${TOMCAT_NAME}_tomcatstate/catalina.pid"
+fi
+
+MAX_STOP_TIME="${OCF_RESKEY_max_stop_time}"
+
+TOMCAT_START_OPTS="${OCF_RESKEY_tomcat_start_opts}"
+TOMCAT_START_SCRIPT="${OCF_RESKEY_tomcat_start_script}"
+CATALINA_OPTS="-Dname=$TOMCAT_NAME ${OCF_RESKEY_catalina_opts}"
+CATALINA_TMPDIR="${OCF_RESKEY_catalina_tmpdir}"
+CATALINA_ROTATE_LOG="${OCF_RESKEY_catalina_rotate_log-NO}"
+CATALINA_ROTATETIME="${OCF_RESKEY_catalina_rotatetime-86400}"
+JAVA_ENDORSED_DIRS="${OCF_RESKEY_java_endorsed_dirs}"
+LOGGING_CONFIG="${OCF_RESKEY_logging_config}"
+LOGGING_MANAGER="${OCF_RESKEY_logging_manager}"
+
+LSB_STATUS_STOPPED=3
+if [ $# -ne 1 ]; then
+	usage
+	exit $OCF_ERR_ARGS
+fi
+case "$COMMAND" in
+	meta-data) metadata_tomcat; exit $OCF_SUCCESS;;
+	help|usage) usage; exit $OCF_SUCCESS;;
+esac
+
+if [ -z "${TOMCAT_START_SCRIPT}" ]; then
+	if [ -e "$CATALINA_HOME/bin/catalina.sh" ]; then
+		TOMCAT_START_SCRIPT="$CATALINA_HOME/bin/catalina.sh"
+	elif [ -e "/usr/sbin/tomcat" ]; then
+		REDIRECT_DEFAULT_CONFIG=1
+		TOMCAT_START_SCRIPT="/usr/sbin/tomcat"
+	fi
+fi
+
+if [ ! -d "$JAVA_HOME" -o ! -d "$CATALINA_HOME" -o ! -d "$CATALINA_BASE" ]; then
+	case $COMMAND in
+		stop)		exit	$OCF_SUCCESS;;
+		monitor)	exit	$OCF_NOT_RUNNING;;
+		status)		exit	$LSB_STATUS_STOPPED;;
+	esac
+	ocf_log err "JAVA_HOME or CATALINA_HOME or CATALINA_BASE does not exist."
+	exit $OCF_ERR_INSTALLED
+fi
+
+export JAVA_HOME JAVA_OPTS CATALINA_HOME CATALINA_BASE CATALINA_OUT CATALINA_PID CATALINA_OPTS CATALINA_TMPDIR JAVA_ENDORSED_DIRS LOGGING_CONFIG LOGGING_MANAGER
+
+JAVA=${JAVA_HOME}/bin/java
+
+if [ ! -x "$JAVA" ]; then
+	case $COMMAND in
+		stop)		exit	$OCF_SUCCESS;;
+		monitor)	exit	$OCF_NOT_RUNNING;;
+		status)		exit	$LSB_STATUS_STOPPED;;
+	esac
+	ocf_log err "java command does not exist."
+	exit $OCF_ERR_INSTALLED
+fi
+
+ROTATELOGS=""
+if ocf_is_true ${CATALINA_ROTATE_LOG}; then
+	# Look for rotatelogs/rotatelogs2
+	if [ -x /usr/sbin/rotatelogs ]; then
+		ROTATELOGS=/usr/sbin/rotatelogs
+	elif [ -x /usr/sbin/rotatelogs2 ]; then
+		ROTATELOGS=/usr/sbin/rotatelogs2
+	fi
+fi
+
+#
+# ------------------
+# the main script
+# ------------------
+# 
+case "$COMMAND" in
+	start)
+		ocf_log debug  "[$TOMCAT_NAME] Enter tomcat start"
+		start_tomcat
+		func_status=$?
+		ocf_log debug  "[$TOMCAT_NAME] Leave tomcat start $func_status"
+		exit $func_status
+		;;
+	stop)
+		ocf_log debug  "[$TOMCAT_NAME] Enter tomcat stop"
+		stop_tomcat
+		func_status=$?
+		ocf_log debug  "[$TOMCAT_NAME] Leave tomcat stop $func_status"
+		exit $func_status
+		;;
+	status)
+		if monitor_tomcat; then
+		  echo tomcat instance $TOMCAT_NAME is running
+		  exit $OCF_SUCCESS
+		else
+		  echo tomcat instance $TOMCAT_NAME is stopped
+		  exit $OCF_NOT_RUNNING
+		fi
+		exit $?
+		;;
+	monitor)
+		#ocf_log debug  "[$TOMCAT_NAME] Enter tomcat monitor"
+		monitor_tomcat
+		func_status=$?
+		#ocf_log debug  "[$TOMCAT_NAME] Leave tomcat monitor $func_status"
+		exit $func_status
+		;;
+	meta-data)
+		metadata_tomcat
+		exit $?
+		;;
+	validate-all)
+		validate_all_tomcat
+		exit $?
+		;;
+        usage|help)
+                usage
+                exit $OCF_SUCCESS
+                ;;
+	*)
+		usage
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+
diff --git a/heartbeat/varnish b/heartbeat/varnish
new file mode 100755
index 0000000..d565832
--- /dev/null
+++ b/heartbeat/varnish
@@ -0,0 +1,454 @@
+#!/bin/sh
+#
+#
+# Varnish
+#
+# Description:  Manage varnish instances as a HA resource
+#
+# Author:       Léon Keijser <keijser at stone-it.com>
+#
+# License:      GNU General Public License (GPL)
+#
+# See usage() for more details
+#
+# OCF instance parameters:
+#   OCF_RESKEY_pid
+#   OCF_RESKEY_binary
+#   OCF_RESKEY_client_binary
+#   OCF_RESKEY_config
+#   OCF_RESKEY_name
+#   OCF_RESKEY_listen_address
+#   OCF_RESKEY_mgmt_address
+#   OCF_RESKEY_ttl
+#   OCF_RESKEY_varnish_user
+#   OCF_RESKEY_varnish_group
+#   OCF_RESKEY_backend_type
+#   OCF_RESKEY_backend_size
+#   OCF_RESKEY_backend_file
+#   OCF_RESKEY_worker_threads
+#
+#######################################################################
+# Initialization:
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+# Set default paramenter values
+
+# Set these two first, as other defaults depend on it
+OCF_RESKEY_name_default=${OCF_RESOURCE_INSTANCE}
+: ${OCF_RESKEY_name=${OCF_RESKEY_name_default}}
+
+OCF_RESKEY_binary_default=varnishd
+OCF_RESKEY_client_binary_default=varnishadm
+OCF_RESKEY_pid_default=/var/run/varnishd_${OCF_RESKEY_name}.pid
+OCF_RESKEY_listen_address_default=0.0.0.0:80
+OCF_RESKEY_ttl_default=600
+OCF_RESKEY_varnish_user_default=varnish
+OCF_RESKEY_varnish_group_default=varnish
+OCF_RESKEY_backend_type_default=malloc
+OCF_RESKEY_backend_size_default=1G
+OCF_RESKEY_backend_file_default=/var/lib/varnish/${OCF_RESKEY_name}.bin
+OCF_RESKEY_worker_threads_default=100,3000,120
+OCF_RESKEY_maxfiles_default=131072
+OCF_RESKEY_max_locked_memory_default=82000
+
+: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
+: ${OCF_RESKEY_client_binary=${OCF_RESKEY_client_binary_default}}
+: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
+: ${OCF_RESKEY_listen_address=${OCF_RESKEY_listen_address_default}}
+: ${OCF_RESKEY_ttl=${OCF_RESKEY_ttl_default}}
+: ${OCF_RESKEY_varnish_user=${OCF_RESKEY_varnish_user_default}}
+: ${OCF_RESKEY_varnish_group=${OCF_RESKEY_varnish_group_default}}
+: ${OCF_RESKEY_backend_type=${OCF_RESKEY_backend_type_default}}
+: ${OCF_RESKEY_backend_size=${OCF_RESKEY_backend_size_default}}
+: ${OCF_RESKEY_backend_file=${OCF_RESKEY_backend_file_default}}
+: ${OCF_RESKEY_worker_threads=${OCF_RESKEY_worker_threads_default}}
+: ${OCF_RESKEY_maxfiles=${OCF_RESKEY_maxfiles_default}}
+: ${OCF_RESKEY_max_locked_memory=${OCF_RESKEY_max_locked_memory_default}}
+
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="varnish" version="0.1">
+<version>1.0</version>
+
+<longdesc lang="en">
+The Varnish Resource Agent can manage several varnishd
+instances throughout the cluster. It does so by creating
+a unique PID file and requires a unique listen address 
+and name for each instance.
+</longdesc>
+<shortdesc lang="en">Manage a Varnish instance</shortdesc>
+
+<parameters>
+
+<parameter name="config" unique="1" required="1">
+<longdesc lang="en">
+The VCL configuration file that Varnish should manage, for example
+"/etc/varnish/default.vcl".
+</longdesc>
+<shortdesc lang="en">VCL file</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+<parameter name="name" unique="1">
+<longdesc lang="en">
+Override the name of the instance that should be given to Varnish
+(defaults to the resource identifier).
+</longdesc>
+<shortdesc lang="en">Instance name</shortdesc>
+<content type="string" default="${OCF_RESKEY_name_default}" />
+</parameter>
+
+<parameter name="pid" unique="1">
+<longdesc lang="en">
+Write the process's PID to the specified file.
+The default will include the specified name, i.e.:
+"/var/run/varnish_production.pid". Unlike what this help message shows,
+it is most likely not necessary to change this parameter.
+</longdesc>
+<shortdesc lang="en">Listen address</shortdesc>
+<content type="string" default="${OCF_RESKEY_pid_default}" />
+</parameter>
+
+<parameter name="listen_address" unique="1">
+<longdesc lang="en">
+Listen on this address:port, for example "192.168.1.1:80"
+</longdesc>
+<shortdesc lang="en">Listen address</shortdesc>
+<content type="string" default="${OCF_RESKEY_listen_address_default}" />
+</parameter>
+
+<parameter name="mgmt_address" unique="1" required="1">
+<longdesc lang="en">
+Provide a management interface, for example "127.0.0.1:2222"
+</longdesc>
+<shortdesc lang="en">Management interface</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="ttl">
+<longdesc lang="en">
+Specify a hard minimum time to live for cached documents.
+</longdesc>
+<shortdesc lang="en">TTL</shortdesc>
+<content type="integer" default="${OCF_RESKEY_ttl_default}" />
+</parameter>
+
+<parameter name="varnish_user">
+<longdesc lang="en">
+Specify the name of an unprivileged user to which the 
+child process should switch before it starts accepting 
+connections.
+</longdesc>
+<shortdesc lang="en">Unprivileged user</shortdesc>
+<content type="string" default="${OCF_RESKEY_varnish_user_default}" />
+</parameter>
+
+<parameter name="varnish_group">
+<longdesc lang="en">
+Specify the name of an unprivileged group to which 
+the child process should switch before it starts accepting 
+connections.
+</longdesc>
+<shortdesc lang="en">Unprivileged group</shortdesc>
+<content type="string" default="${OCF_RESKEY_varnish_group_default}" />
+</parameter>
+
+<parameter name="backend_type">
+<longdesc lang="en">
+Use the specified storage backend. Valid options are
+'malloc' for memory and 'file' for a file backend.
+</longdesc>
+<shortdesc lang="en">Backend type</shortdesc>
+<content type="string" default="${OCF_RESKEY_backend_type_default}" />
+</parameter>
+
+<parameter name="backend_size">
+<longdesc lang="en">
+Specify the size of the backend. For example "1G".
+</longdesc>
+<shortdesc lang="en">Backend size</shortdesc>
+<content type="string" default="${OCF_RESKEY_backend_size_default}" />
+</parameter>
+
+<parameter name="backend_file" unique="1">
+<longdesc lang="en">
+Specify the backend filename if you use backend_type file. 
+For example /var/lib/varnish/mybackend.bin
+</longdesc>
+<shortdesc lang="en">Backend file</shortdesc>
+<content type="string" default="${OCF_RESKEY_backend_file_default}" />
+</parameter>
+
+<parameter name="worker_threads">
+<longdesc lang="en">
+Start  at  least  min but no more than max worker 
+threads with the specified idle timeout.
+
+Syntax: min[,max[,timeout]]
+For example: 100,3000,120
+</longdesc>
+<shortdesc lang="en">Worker threads</shortdesc>
+<content type="string" default="${OCF_RESKEY_worker_threads_default}" />
+</parameter>
+
+<parameter name="client_binary">
+<longdesc lang="en">
+This is used to control Varnish via a CLI. It's currently
+only used to check the status of the running child process.
+</longdesc>
+<shortdesc lang="en">Varnish admin utility</shortdesc>
+<content type="string" default="${OCF_RESKEY_client_binary_default}" />
+</parameter>
+
+<parameter name="maxfiles">
+<longdesc lang="en">
+Maximum number of open files (for ulimit -n)
+</longdesc>
+<shortdesc lang="en">Max open files</shortdesc>
+<content type="string" default="${OCF_RESKEY_maxfiles_default}" />
+</parameter>
+
+<parameter name="max_locked_memory">
+<longdesc lang="en">
+Locked shared memory limit (for ulimit -l)
+</longdesc>
+<shortdesc lang="en">Max locked memory</shortdesc>
+<content type="string" default="${OCF_RESKEY_max_locked_memory_default}" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="20" />
+<action name="stop"         timeout="20" />
+<action name="monitor"      timeout="20" interval="10" depth="0" />
+<action name="status"       timeout="20" />
+<action name="meta-data"    timeout="5" />
+<action name="validate-all"   timeout="20" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+
+varnish_usage() {
+	cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+varnish_status() {
+    local pid
+    local rc
+
+    # FAILED = pidfile exist, but no running proc (or mismatch pid)
+    # SUCCES = contents of pidfile == running process id
+    # NOTRUN = no pidfile, no running process
+
+    # check if pidfile exists and larger than 0 bytes
+    if [ -s $OCF_RESKEY_pid ]; then
+        # it does, now check if the pid exists
+        pid=$(cat $OCF_RESKEY_pid)
+        ocf_run kill -s 0 $pid
+        rc=$?
+        if [ $rc -eq 0 ]; then
+            ocf_log info "Varnish is running"
+            # check if the child process is started and varnish is
+            # reporting child status as ok
+            ocf_run $OCF_RESKEY_client_binary -T $OCF_RESKEY_mgmt_address status
+            v_rc=$?
+            if [ "$v_rc" -eq 0 ]; then
+                ocf_log info "Varnish child reported running"
+                return $OCF_SUCCESS
+            else
+                ocf_log err "Varnish child not running"
+                return $OCF_ERR_GENERIC
+            fi
+        else
+            ocf_log err "Varnish PID file exists, but varnishd is not running"
+            return $OCF_ERR_GENERIC
+        fi
+    fi
+    
+    return $OCF_NOT_RUNNING
+}
+
+varnish_start() {
+    local rc
+    local backend_options
+
+    varnish_status
+    rc=$?
+    if [ $rc -eq $OCF_SUCCESS ]; then
+        ocf_log info "Varnish already running"
+        return $OCF_SUCCESS
+    fi
+
+    # check which backend is to be used
+    case "$OCF_RESKEY_backend_type" in
+       malloc)  
+                backend_options="$OCF_RESKEY_backend_size"
+                ;;
+        file)
+                backend_options="$OCF_RESKEY_backend_file,$OCF_RESKEY_backend_size"
+                ;;
+        *)
+                # not implemented yet
+                return $OCF_ERR_CONFIGURED 
+                ;;
+    esac
+
+    # set maximum locked shared memory
+    if [ -n "$OCF_RESKEY_max_locked_memory" ]; then
+        ocf_log info "Setting max_locked_memory to ${OCF_RESKEY_max_locked_memory}"
+        ulimit -l $OCF_RESKEY_max_locked_memory
+        u_rc=$?
+        if [ "$u_rc" -ne 0 ]; then
+           ocf_log warn "Could not set ulimit for locked share memory for Varnish to '$OCF_RESKEY_max_locked_memory'"
+        fi
+    fi
+
+    # set maximum number of open files
+    if [ -n "$OCF_RESKEY_maxfiles" ]; then
+        ulimit -n $OCF_RESKEY_maxfiles
+        u_rc=$?
+        if [ "$u_rc" -ne 0 ]; then
+           ocf_log warn "Could not set ulimit for open files for Varnish to '$OCF_RESKEY_maxfiles'"
+        fi
+    fi
+
+    ocf_run $OCF_RESKEY_binary \
+        -P $OCF_RESKEY_pid \
+        -a $OCF_RESKEY_listen_address \
+        -f $OCF_RESKEY_config \
+        -T $OCF_RESKEY_mgmt_address \
+        -t $OCF_RESKEY_ttl \
+        -u $OCF_RESKEY_varnish_user \
+        -g $OCF_RESKEY_varnish_group \
+        -w $OCF_RESKEY_worker_threads \
+        -s $OCF_RESKEY_backend_type,$backend_options \
+        -n $OCF_RESKEY_name
+    rc=$?
+    if [ $rc -ne 0 ]; then
+        ocf_log err "Varnish failed to start"
+        return $OCF_ERR_GENERIC
+    fi
+
+    # Spin waiting for varnishd to come up.
+    # Let the CRM/LRM time us out if required
+    while true; do
+        varnish_status
+        rc=$?
+        [ $rc -eq $OCF_SUCCESS ] && break
+        if [ $rc -ne $OCF_NOT_RUNNING ]; then
+            ocf_log err "Varnish start failed"
+            exit $OCF_ERR_GENERIC
+        fi
+        sleep 2
+    done
+
+    ocf_log info "Varnish started succesfully"
+    return $OCF_SUCCESS
+}
+
+varnish_stop() {
+    local rc
+    local pid
+
+    varnish_status
+    rc=$?
+    if [ $rc -eq $OCF_NOT_RUNNING ]; then
+        ocf_log info "Varnish already stopped"
+        return $OCF_SUCCESS
+    fi
+
+    # kill the varnish process
+    pid=$(cat $OCF_RESKEY_pid)
+    ocf_run kill -s TERM $pid
+    rc=$?
+
+    if [ $rc -ne 0 ]; then
+        ocf_log err "Varnish failed to stop"
+        return $OCF_ERR_GENERIC
+    fi
+
+    # stop waiting
+    shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5))
+    count=0
+    while [ $count -lt $shutdown_timeout ]; do
+        # check if process still exists
+        ocf_run kill -s 0 $pid
+        rc=$?
+        if [ $rc -ne 0 ]; then
+            # Varnish stopped succesfully, so let's delete the pidfile
+            rm -f $OCF_RESKEY_pid
+            break
+        fi
+        count=$(expr $count + 1)
+        sleep 1
+        ocf_log info "Varnish still hasn't stopped yet. Waiting..."
+    done 
+
+    varnish_status
+    rc=$?
+    if [ $rc -ne $OCF_NOT_RUNNING ]; then
+        # varnish didn't quit on a SIGTERM, try SIGKILL
+        ocf_log warn "Varnish failed to stop after ${shutdown_timeout}s using SIGTERM. Trying SIGKILL..."
+        ocf_run kill -s KILL $pid
+        # delete the pidfile
+        rm -f $OCF_RESKEY_pid
+    fi
+
+    ocf_log info "Varnish stopped"
+    return $OCF_SUCCESS
+}
+
+
+varnish_validate() {
+    if [ -f $OCF_RESKEY_config ]; then
+        return $OCF_SUCCESS
+    else
+        return $OCF_ERR_INSTALLED
+    fi
+}
+
+
+case $__OCF_ACTION in
+    meta-data)
+        meta_data
+        exit $OCF_SUCCESS
+        ;;
+    start)
+        varnish_start
+        ;;
+    stop)
+        varnish_stop
+        ;;
+    monitor|status)
+        varnish_status
+        ;;
+    validate-all)
+        varnish_validate
+        ;;
+    usage|help)
+        varnish_usage
+        exit $OCF_SUCCESS
+        ;;
+    *)
+        varnish_usage
+        exit $OCF_ERR_UNIMPLEMENTED
+        ;;
+esac
+rc=$?
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
+exit $rc
+
diff --git a/heartbeat/vmware b/heartbeat/vmware
new file mode 100755
index 0000000..3c72891
--- /dev/null
+++ b/heartbeat/vmware
@@ -0,0 +1,393 @@
+#!/bin/sh
+#
+# VMware OCF resource agent
+#
+# Copyright (c) 2010 Apra Sistemi s.r.l.
+#                    All Rights Reserved.
+#
+# Description:  Manages VMware server 2.0 virtual machines
+#               as High-Availability resources
+#
+#
+# Author:       Cristian Mammoli <c.mammoli AT apra DOT it>
+# License:      GNU General Public License (GPL)
+# Copyright:    (C) 2010 Apra Sistemi s.r.l.
+#
+# See usage() function below for more details...
+#
+# OCF instance parameters:
+#  * OCF_RESKEY_vmxpath (mandatory: full path to the virtual machine vmx file)
+#  * OCF_RESKEY_vimshbin (optional: full path to the vmware-vim-cmd executable,
+#                        fallback to default location if not declared)
+#
+# Requirements/caveats:
+#  * vmware-server 2.0 installed and autostarted on all nodes
+#  * vmdk files must be in the same directory of the vmx file
+#  * vmx filenames must be unique, even if stored in different directories
+#  * Default_Action_Timeout stock value (20 sec) isn't enough if you are
+#    dealing with many virtual machines: raise it to something around 600 secs
+#    or use operation attributes with the proposed values
+#  * Moving a vm among nodes will cause its mac address to change: if you need
+#    to preserve the mac address set it manually in the nic options
+#  * The script should be able to deal with paths and filenames with spaces,
+#    anyway try to avoid it
+
+# Initialization
+#################################################################
+
+# Source ocf shell functions
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+# Basic variables configuration
+OCF_RESKEY_vimshbin_default="/usr/bin/vmware-vim-cmd"
+: ${OCF_RESKEY_vimshbin=${OCF_RESKEY_vimshbin_default}}
+#################################################################
+
+# Path to the virtual machine configuration file
+VMXPATH="$OCF_RESKEY_vmxpath"
+
+# Path to the vmware-vim-cmd executable
+VIMSHBIN="$OCF_RESKEY_vimshbin"
+
+# Global variables
+VMXDIR=
+RELVMXPATH=
+VMID=
+VM=
+VMAUTOMSG=
+
+# vmware-vim-cmd functions
+#################################################################
+
+# Get virtual machine vid
+vmware_get_vid() {
+  $VIMSHBIN vmsvc/getallvms \
+         | awk '/\/'"$1"'/ {print $1}'
+}
+
+# Is the vm waiting for input after a migration?
+vmware_uuid_alt() {
+  $VIMSHBIN vmsvc/message $1 \
+         | awk /^msg.uuid.altered/
+}
+
+# Get message id
+vmware_get_msgid() {
+  $VIMSHBIN vmsvc/message $1 \
+      | awk '/^Virtual machine message/ {print $4}' \
+      | awk -F : '{print $1}'
+}
+
+# Answers message
+vmware_answer_msg() {
+  $VIMSHBIN vmsvc/message $1 $2 $3 >/dev/null
+}
+
+# Register a virtual machine
+vmware_register_vm() {
+  $VIMSHBIN solo/registervm '"'$1'"' >/dev/null
+}
+
+# Unregister a virtual machine
+vmware_unregister_vm() {
+  $VIMSHBIN  vmsvc/unregister $1 >/dev/null
+}
+
+# Start a virtual machine
+vmware_poweron_vm() {
+  $VIMSHBIN vmsvc/power.on $1 >/dev/null
+}
+
+# Suspend a virtual machine
+vmware_suspend_vm() {
+  $VIMSHBIN vmsvc/power.suspend $1 >/dev/null
+}
+
+# Get virtual machine power state
+vmware_get_status() {
+  $VIMSHBIN vmsvc/power.getstate $1 \
+         | awk '/^Powered on/ || /^Powered off/ || /^Suspended/'
+}
+
+# Get vid of missing virtual machines
+vmware_get_broken() {
+  $VIMSHBIN vmsvc/getallvm 2>&1 \
+         | awk -F \' '/^Skipping/ {print $2}'
+}
+
+# Variables depending on the above functions
+#################################################################
+
+vmware_set_env() {
+	# Directory containing the virtual machine
+	VMXDIR="`dirname "$VMXPATH"`"
+
+	# Basename of the configuration file
+	RELVMXPATH="`basename "$VMXPATH"`"
+
+	# Vid of the virtual machine (can be empty if the vm is not registered)
+	VMID=`vmware_get_vid "$RELVMXPATH"`
+
+	# Virtual machine name
+	VM="`awk -F '"' '/^displayName/ {print $2}' "$VMXPATH"`"
+
+	# msg.autoAnswer value in config file
+	VMAUTOMSG="`awk -F '"' '/^msg.autoAnswer/ {print toupper($2)}' "$VMXPATH"`"
+}
+
+# Main functions
+#################################################################
+
+# Print usage summary
+vmware_usage() {
+    cat <<END
+usage: $0 {start|stop|status|monitor|meta-data|validate-all}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+# Check for mandatory files presence and consistency
+vmware_validate() {
+  if [ -z "`pidof vmware-hostd`" ]; then
+    ocf_log err "vmware-hostd is not running"
+    exit $OCF_ERR_GENERIC
+  fi
+
+  if [ ! -x "$VIMSHBIN" ]; then
+    ocf_log err "vmware-vim-cmd executable missing or not in path ($VIMSHBIN)"
+    exit $OCF_ERR_ARGS
+  fi
+
+  if [ ! -f "$VMXPATH" ]; then
+    ocf_log err "Specified vmx file ($VMXPATH) does not exist"
+    exit $OCF_ERR_ARGS
+  fi
+
+  # Now we can safely setup variables...
+  vmware_set_env
+
+  # ... and verify them
+  if [ -z "$VM" ]; then
+    ocf_log err "Could not find out virtual machine name"
+    exit $OCF_ERR_ARGS
+  fi
+
+  if [ "$VMAUTOMSG" != "TRUE" ]; then
+    ocf_log warn "Please set msg.autoAnswer = \"TRUE\" in your config file"
+  fi
+
+  # $VMID is allowed to be empty in case we are validating a
+  # virtual machine which is not registered
+
+  return $OCF_SUCCESS
+}
+
+# More relaxed checking in case of probes
+vmware_validate_probe() {
+  if [ ! -x "$VIMSHBIN" ]; then
+    ocf_log warn "vmware-vim-cmd executable missing or not in path ($VIMSHBIN)"
+    exit $OCF_NOT_RUNNING
+  fi
+
+  if [ ! -f "$VMXPATH" ]; then
+    ocf_log warn "Specified vmx file ($VMXPATH) does not exist"
+    exit $OCF_NOT_RUNNING
+  fi
+
+  # Now we can safely setup variables...
+  vmware_set_env
+}
+
+# Start a virtual machine
+vmware_start() {
+  # Don't start a VM if it's already running
+  if vmware_monitor; then
+    ocf_log info "Virtual machine $VM is already running"
+    return $OCF_SUCCESS
+  else
+    # Removes stale lockfiles and missing virtual machines
+    # in case of a crash.
+    # Do not use with a clustered filesystem or you could
+    # end up starting the same VM in more than one node
+    ocf_log info "Removing stale lockfiles"
+    find "$VMXDIR" -name \*.lck -type f -exec rm "{}" \;
+    for BVM in `vmware_get_broken`; do
+      ocf_log info "Unregistering missing virtual machine $BVM"
+      vmware_unregister_vm $BVM
+    done
+    if [ -z "$VMID" ]; then
+      # VM is not registered, need to register
+      ocf_log info "Virtual machine $VM is not registered"
+      ocf_log info "Registering Virtual machine $VM"
+      vmware_register_vm "$VMXPATH"
+      VMID=`vmware_get_vid "$RELVMXPATH"`
+      if [ -z "$VMID" ]; then
+        ocf_log err "Could not register virtual machine $VM"
+        exit $OCF_ERR_GENERIC
+      fi
+      ocf_log info "Virtual machine $VM registered with ID $VMID"
+    fi
+    ocf_log info "Powering on virtual machine $VM"
+    vmware_poweron_vm $VMID
+    # Give the VM some time to initialize
+    sleep 10
+
+    if [ "$VMAUTOMSG" != "TRUE" ]; then
+      # msg.autoAnswer is not set: we try to deal with the
+      # most common question: msg.uuid.altered
+      ocf_log info  "Checking msg.uuid.altered on VM $VM"
+      if [ -n "`vmware_uuid_alt $VMID`" ]; then
+        MSGID=`vmware_get_msgid $VMID`
+        vmware_answer_msg $VMID $MSGID 2
+      fi
+    fi
+
+    # Check if the VM is running. We don't bother
+    # with timeouts: we rely on the CRM for that.
+    while :; do
+      vmware_monitor && break
+      ocf_log info "Virtual machine $VM is still stopped: delaying 10 seconds"
+      sleep 10
+    done
+
+    ocf_log info "Virtual machine $VM is running"
+    return $OCF_SUCCESS
+  fi
+}
+
+# Stop a virtual machine
+vmware_stop() {
+  # Don't stop a VM if it's not registered
+  if [ -z "$VMID" ]; then
+    ocf_log info "Virtual machine $VM is not registered"
+    return $OCF_SUCCESS
+  else
+    # Don't stop a VM if it's already stopped
+    if vmware_monitor; then
+      # If the VM is running send a suspend signal and wait
+      # until it is off. We don't bother with timeouts: we
+      # rely on the CRM for that.
+      ocf_log info "Virtual machine $VM is running: suspending it"
+      vmware_suspend_vm $VMID
+      sleep 5
+      while vmware_monitor; do
+        ocf_log info "Virtual machine $VM is still running: delaying 10 seconds"
+        sleep 10
+      done
+    else
+      ocf_log info "Virtual machine $VM is already stopped"
+    fi
+    # VMware randomly fails to unregister VMs,
+    # so we loop until we have success or timeout
+    ocf_log info "Unregistering virtual machine $VM"
+    vmware_unregister_vm $VMID
+    VMID=`vmware_get_vid "$RELVMXPATH"`
+    while [ -n "$VMID" ]; do
+      ocf_log warn "Could not unregister virtual machine $VM: retrying."
+      sleep 10
+      vmware_unregister_vm $VMID
+      VMID=`vmware_get_vid "$RELVMXPATH"`
+    done
+    ocf_log info "Virtual machine $VM is stopped"
+    return $OCF_SUCCESS
+  fi
+}
+
+# Monitor a virtual machine
+vmware_monitor() {
+  if [ -n "$VMID" ] && [ "`vmware_get_status $VMID`" = "Powered on" ]; then
+    ocf_log debug "Virtual machine $VM (ID $VMID) is running..."
+    return $OCF_SUCCESS
+  else
+    ocf_log debug "Virtual machine $VM is stopped/suspended/not registered"
+    return $OCF_NOT_RUNNING
+  fi
+}
+
+# Print metadata informations
+meta_data() {
+  cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="vmware">
+<version>0.2</version>
+<longdesc lang="en">
+OCF compliant script to control vmware server 2.0 virtual machines.
+</longdesc>
+<shortdesc lang="en">Manages VMWare Server 2.0 virtual machines</shortdesc>
+
+<parameters>
+<parameter name="vmxpath" unique="0" required="1">
+<longdesc lang="en">
+VMX configuration file path
+</longdesc>
+<shortdesc lang="en">VMX file path</shortdesc>
+<content type="string"/>
+</parameter>
+
+<parameter name="vimshbin" unique="0" required="0">
+<longdesc lang="en">
+vmware-vim-cmd executable path
+</longdesc>
+<shortdesc lang="en">vmware-vim-cmd path</shortdesc>
+<content type="string" default="${OCF_RESKEY_vimshbin_default}"/>
+</parameter>
+</parameters>
+
+<actions>
+<action name="start"        timeout="600" />
+<action name="stop"         timeout="600" />
+<action name="monitor"      timeout="30" interval="300" depth="0"/>
+<action name="meta-data"    timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+# See how we were called
+#################################################################
+
+case $1 in
+meta-data)
+  meta_data
+  exit $OCF_SUCCESS
+  ;;
+
+start)
+  vmware_validate
+  vmware_start
+  ;;
+
+stop)
+  vmware_validate
+  vmware_stop
+  ;;
+
+status|monitor)
+  if ocf_is_probe; then
+    vmware_validate_probe
+  else
+    vmware_validate
+  fi
+  vmware_monitor
+  ;;
+
+usage|help)
+  vmware_usage
+  exit $OCF_SUCCESS
+  ;;
+
+validate-all)
+  vmware_validate
+  ;;
+
+*)
+  vmware_usage
+  exit $OCF_ERR_UNIMPLEMENTED
+  ;;
+
+esac
+
+exit $?
diff --git a/heartbeat/zabbixserver b/heartbeat/zabbixserver
new file mode 100755
index 0000000..fe7266e
--- /dev/null
+++ b/heartbeat/zabbixserver
@@ -0,0 +1,336 @@
+#!/bin/sh
+#
+#
+#   zabbixserver OCF RA for zabbix_server daemon
+#
+# Copyright (c) 2012 Krzysztof Gajdemski <songo at debian.org.pl>
+#                    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.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+#
+# Defaults
+#
+OCF_RESKEY_binary_default="zabbix_server"
+OCF_RESKEY_pid_default="/var/run/zabbix-server/zabbix_server.pid"
+OCF_RESKEY_config_default=""
+
+: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
+: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
+: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
+
+# sleep interval when waiting for threads cleanup
+sleepint=1
+
+#
+# Functions
+#
+zabbixserver_meta_data() {
+    cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="zabbixserver">
+<version>0.0.1</version>
+
+<longdesc lang="en">
+This is a Zabbix server Resource Agent for zabbix_server monitoring
+daemon. See: http://www.zabbix.com/
+</longdesc>
+<shortdesc lang="en">Zabbix server resource agent</shortdesc>
+
+<parameters>
+
+<parameter name="binary" unique="0" required="0">
+<longdesc lang="en">
+Location of the zabbix_server binary.
+</longdesc>
+<shortdesc lang="en">Zabbix server binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_binary_default}" />
+</parameter>
+
+<parameter name="pid" unique="1" required="0">
+<longdesc lang="en">
+Path to zabbix_server pidfile. As it's created by daemon itself
+it must be the same as specified in the Zabbix configuration file
+with parameter 'PidFile='.
+</longdesc>
+<shortdesc lang="en">Path to pidfile</shortdesc>
+<content type="string" default="${OCF_RESKEY_pid_default}" />
+</parameter>
+
+<parameter name="config" unique="1" required="0">
+<longdesc lang="en">
+Path to zabbix_server configuration file. Assumed server default
+if not specified.
+</longdesc>
+<shortdesc lang="en">Path to configuration file</shortdesc>
+<content type="string" default="${OCF_RESKEY_config_default}" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"        timeout="20" />
+<action name="stop"         timeout="20" />
+<action name="monitor"      timeout="20" interval="10" depth="0"/>
+<action name="validate-all" timeout="20" />
+<action name="meta-data"    timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+
+zabbixserver_usage() {
+    cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+#
+# Get an actual PID from a given pidfile. If it can't
+# be found then return 1
+#
+getpid() {
+    # pidfile doesn't exists
+    [ -f $1 ] || return 1
+    sed -n '1 { /[0-9]/p }' $1
+
+    return 0
+}
+
+#
+# Check if PID directory exists
+#
+check_piddir() {
+    local piddir
+    local severity
+
+    # lower severity to info during probe
+    severity=err
+    ocf_is_probe && severity=info
+
+    piddir=`dirname ${OCF_RESKEY_pid}`
+    if [ ! -d $piddir ]; then
+        ocf_log $severity "PID directory ${piddir} doesn't exist"
+        return 1
+    fi
+
+    return 0
+}
+
+#
+# Check for the server configuration file
+#
+check_config() {
+    # check only when it is specified by user
+    if [ ! -z "$1" ] && [ ! -f "$1" ]; then
+        if ocf_is_probe; then
+            ocf_log info "Can't read configuration file $1 during probe"
+        else
+            ocf_log err "Can't read configuration file $1"
+            return 1
+        fi
+    fi
+
+    return 0
+}
+
+#
+# Start Zabbix daemon
+#
+startserver() {
+    local command
+    local params
+
+    command=$OCF_RESKEY_binary
+
+    # use additional parameters if specified
+    if [ "$OCF_RESKEY_config" ]; then
+        params="--config $OCF_RESKEY_config"
+        command="$command $params"
+    fi
+
+    ocf_log debug "Starting server using command: $command"
+
+    ocf_run $command
+}
+
+#
+# Check the process status (PID is given as an argument)
+#
+process_status() {
+    local pid
+
+    pid=$1
+
+    # check if parent process is running
+    ocf_run -q kill -s 0 $pid 2> /dev/null 1>&2
+}
+
+#
+# start the agent
+#
+zabbixserver_start() {
+    local rc
+
+    # check the resource status
+    zabbixserver_monitor
+    rc=$?
+    case "$rc" in
+    $OCF_SUCCESS)
+        ocf_log info "Resource is already running"
+        return $OCF_SUCCESS
+        ;;
+    $OCF_NOT_RUNNING)
+        ;;
+    *)
+        exit $OCF_ERR_GENERIC
+        ;;
+    esac
+
+    # remove stale pidfile if it exists
+    if [ -f $OCF_RESKEY_pid ]; then
+        ocf_log info "Removing stale pidfile"
+        rm $OCF_RESKEY_pid
+    fi
+
+    startserver
+    if [ $? -ne 0 ]; then
+        ocf_log err "Can't start Zabbix server"
+        return $OCF_ERR_GENERIC
+    fi
+
+    # wait if it starts really
+    while ! zabbixserver_monitor; do
+        ocf_log debug "Resource has not started yet, waiting"
+        sleep $sleepint
+    done
+
+    return $OCF_SUCCESS
+}
+
+#
+# stop the agent
+#
+zabbixserver_stop() {
+    local pid
+    local rc
+
+    # check the resource status
+    zabbixserver_monitor
+    rc=$?
+    case "$rc" in
+    $OCF_SUCCESS)
+        ;;
+    $OCF_NOT_RUNNING)
+        ocf_log info "Resource is already stopped"
+        return $OCF_SUCCESS
+        ;;
+    *)
+        exit $OCF_ERR_GENERIC
+        ;;
+    esac
+
+    pid=`getpid $OCF_RESKEY_pid`
+    if [ $? -ne 0 ]; then
+        ocf_log err "Can't find process PID"
+        return $OCF_ERR_GENERIC
+    fi
+
+    # kill the process
+    ocf_run -q kill $pid
+    if [ $? -ne 0 ]; then
+        ocf_log err "Can't stop process (PID $pid)"
+        return $OCF_ERR_GENERIC
+    fi
+
+    # Wait until the parent process terminates.
+    # NOTE: The parent may be still waiting for its children. A regular monitor
+    # function will not detect this condition because the pidfile may be
+    # removed just now.
+    while process_status $pid; do
+        ocf_log debug "Waiting for process to terminate..."
+        sleep $sleepint
+    done
+
+    # wait if it stops really
+    while zabbixserver_monitor; do
+        ocf_log debug "Resource has not stopped yet, waiting"
+        sleep $sleepint
+    done
+
+    # remove stale pidfile if it exists
+    if [ -f $OCF_RESKEY_pid ]; then
+        ocf_log debug "Pidfile still exists, removing"
+        rm $OCF_RESKEY_pid
+    fi
+
+    return $OCF_SUCCESS
+}
+
+#
+# resource monitor
+#
+zabbixserver_monitor() {
+    local pid
+
+    pid=`getpid $OCF_RESKEY_pid`
+    if [ $? -eq 0 ]; then
+        process_status $pid
+        if [ $? -eq 0 ]; then
+            ocf_log debug "Resource is running"
+            return $OCF_SUCCESS
+        fi
+    fi
+
+    ocf_log info "Resource is not running"
+    return $OCF_NOT_RUNNING
+}
+
+#
+# validate configuration
+#
+zabbixserver_validate_all() {
+    check_piddir || return $OCF_ERR_INSTALLED
+    check_config $OCF_RESKEY_config || return $OCF_ERR_INSTALLED
+
+    return $OCF_SUCCESS
+}
+
+#
+# main
+#
+OCF_REQUIRED_PARAMS=""
+OCF_REQUIRED_BINARIES="$OCF_RESKEY_binary"
+ocf_rarun $*
diff --git a/include/IPv6addr.h b/include/IPv6addr.h
new file mode 100644
index 0000000..720edf9
--- /dev/null
+++ b/include/IPv6addr.h
@@ -0,0 +1,58 @@
+/*
+ * This program manages IPv6 address with OCF Resource Agent standard.
+ *
+ * Author: Huang Zhen <zhenh at cn.ibm.com>
+ * Copyright (c) 2004 International Business Machines
+ *
+ * This library 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 library 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.
+ */
+
+#ifndef OCF_IPV6_HELPER_H
+#define OCF_IPV6_HELPER_H
+#include <netinet/icmp6.h>
+#include <config.h>
+/*
+0	No error, action succeeded completely
+1 	generic or unspecified error (current practice)
+	The "monitor" operation shall return this for a crashed, hung or
+	otherwise non-functional resource.
+2 	invalid or excess argument(s)
+	Likely error code for validate-all, if the instance parameters
+	do not validate. Any other action is free to also return this
+	exit status code for this case.
+3 	unimplemented feature (for example, "reload")
+4 	user had insufficient privilege
+5 	program is not installed
+6 	program is not configured
+7 	program is not running
+8	resource is running in "master" mode and fully operational
+9	resource is in "master" mode but in a failed state
+*/
+#define	OCF_SUCCESS		0
+#define	OCF_ERR_GENERIC		1
+#define	OCF_ERR_ARGS		2
+#define	OCF_ERR_UNIMPLEMENTED	3
+#define	OCF_ERR_PERM		4
+#define	OCF_ERR_INSTALLED	5
+#define	OCF_ERR_CONFIGURED	6
+#define	OCF_NOT_RUNNING		7
+
+#define	HWADDR_LEN 6 /* mac address length */
+#define UA_REPEAT_COUNT	5
+#define  BCAST_ADDR "ff02::1"
+#define IF_INET6 "/proc/net/if_inet6"
+
+int send_ua(struct in6_addr* src_ip, char* if_name);
+#endif
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..6f46ec3
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2008 Andrew Beekhof
+#
+# 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 config.h.in config.h.in~
+
+idir=$(includedir)/heartbeat
+i_HEADERS = agent_config.h
+
+noinst_HEADERS = config.h IPv6addr.h
diff --git a/include/agent_config.h.in b/include/agent_config.h.in
new file mode 100644
index 0000000..acc6c18
--- /dev/null
+++ b/include/agent_config.h.in
@@ -0,0 +1,2 @@
+/* Where Resouce agents keep state files */
+#undef HA_RSCTMPDIR
diff --git a/ldirectord/Makefile.am b/ldirectord/Makefile.am
new file mode 100644
index 0000000..71461f9
--- /dev/null
+++ b/ldirectord/Makefile.am
@@ -0,0 +1,45 @@
+#
+# ldirectord: Linux-HA heartbeat code
+#
+# Copyright (C) 2001 Michael Moerz
+#
+# 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
+CLEANFILES	       	= ldirectord.8
+
+EXTRA_DIST              = ldirectord ldirectord.cf
+
+SUBDIRS			= logrotate.d init.d OCF
+
+ldirectord.8: ldirectord
+	$(POD2MAN) --section=8 $< > $@
+
+sbin_SCRIPTS		= ldirectord
+
+if BUILD_POD_DOC
+man_MANS	        = ldirectord.8
+endif
+
+harddir			= $(sysconfdir)/ha.d/resource.d
+
+.PHONY: install-exec-hook
+install-exec-hook:
+	$(INSTALL) -d $(DESTDIR)$(harddir)
+	cd $(DESTDIR)$(harddir) && ln -s -f $(sbindir)/ldirectord .
+
+.PHONY: uninstall-hook
+uninstall-hook:
+	rm -f $(DESTDIR)$(harddir)/ldirectord
diff --git a/ldirectord/OCF/Makefile.am b/ldirectord/OCF/Makefile.am
new file mode 100644
index 0000000..1bea5f5
--- /dev/null
+++ b/ldirectord/OCF/Makefile.am
@@ -0,0 +1,26 @@
+#
+# ldirectord: Linux-HA heartbeat code
+#
+# Copyright (C) 2007 Horms
+#
+# 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              = $(ocf_SCRIPTS)
+
+ocfdir			= $(OCF_RA_DIR_PREFIX)/heartbeat
+
+ocf_SCRIPTS		= ldirectord
diff --git a/ldirectord/OCF/ldirectord.in b/ldirectord/OCF/ldirectord.in
new file mode 100644
index 0000000..f7c639e
--- /dev/null
+++ b/ldirectord/OCF/ldirectord.in
@@ -0,0 +1,269 @@
+#!/bin/sh
+#
+#   ldirectord OCF RA. Wrapper around @sbindir@/ldirectord to
+#   be OCF RA compliant and therefore to get the possibility
+#   to monitor ldirectord by HAv2.
+#   Tested on SuSE Linux Enterprise Server 10.
+#
+#   Should conform to the specification found at
+#    http://www.linux-ha.org/OCFResourceAgent
+#   and
+#   http://www.opencf.org/cgi-bin/viewcvs.cgi/specs/ra/resource-agent-api.txt?rev=HEAD
+#
+#   ToDo: Add parameter to start several instances of ldirectord
+#   with different config files.
+#
+# Copyright (c) 2007 Andreas Mock (andreas.mock at web.de)
+#                    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.
+#
+#######################################################################
+#
+#	OCF Parameters
+#	OCF_RESKEY_configfile
+#	OCF_RESKEY_ldirectord
+#
+#######################################################################
+# Initialization:
+
+HA_VARRUNDIR=${HA_VARRUN}
+
+. ${OCF_ROOT}/lib/heartbeat/ocf-shellfuncs
+
+LDIRCONF=${OCF_RESKEY_configfile:- at sysconfdir@/ha.d/ldirectord.cf}
+LDIRECTORD=${OCF_RESKEY_ldirectord:- at sbindir@/ldirectord}
+
+meta_data() {
+        cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="ldirectord" version="0.9">
+<version>1.0</version>
+
+<longdesc lang="en">
+It's a simple OCF RA wrapper for ldirectord and uses the ldirectord interface
+to create the OCF compliant interface. You win monitoring of ldirectord.
+Be warned: Asking ldirectord status is an expensive action.
+</longdesc>
+<shortdesc lang="en">Wrapper OCF Resource Agent for ldirectord</shortdesc>
+
+<parameters>
+
+<parameter name="configfile" unique="1">
+<longdesc lang="en">
+The full pathname of the ldirectord configuration file.
+</longdesc>
+<shortdesc lang="en">configuration file path</shortdesc>
+<content type="string" default="@sysconfdir@/ha.d/ldirectord.cf" />
+</parameter>
+
+<parameter name="ldirectord">
+<longdesc lang="en">
+The full pathname of the ldirectord.
+</longdesc>
+<shortdesc lang="en">ldirectord binary path</shortdesc>
+<content type="string" default="@sbindir@/ldirectord" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start"   timeout="15" />
+<action name="stop"    timeout="15" />
+<action name="monitor" depth="0"  timeout="10" interval="20" />
+<action name="meta-data"  timeout="10" />
+<action name="validate-all"  timeout="10" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+ldir_init() {
+    # check the supplied parameters exist enough that we can do all the other
+    # operations
+    if [ ! -f $LDIRCONF ]; then
+        ocf_log warn "$LDIRCONF not found, ldirectord not installed"
+        exit $OCF_ERR_INSTALLED
+    fi
+
+    if [ ! -x $LDIRECTORD ]; then
+        ocf_log warn "$LDIRECTORD not found, ldirectord not installed"
+        exit $OCF_ERR_INSTALLED
+    fi
+}
+
+ldirectord_usage() {
+        cat <<END
+usage: $0 {start|stop|monitor|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+ldirectord_exit() {
+    exit $1
+}
+
+ldirectord_start() {
+    ldirectord_status
+    RET=$?
+
+    # if ldirectord is running or there's an error, pass on this return code
+    if [ $RET -ne $OCF_NOT_RUNNING ]; then
+        return $RET
+    fi
+
+    ocf_log info "Starting ldirectord"
+    echo $LDIRECTORD $LDIRCONF start
+    $LDIRECTORD $LDIRCONF start
+    RET=$?
+    if [ $RET -ne 0 ]; then
+        return $OCF_ERR_GENERIC
+    fi
+
+    # call status again to make sure we're running properly
+    ldirectord_status
+}
+
+ldirectord_stop() {
+    # a status check is simple enough to see if ldirectord is running or not.
+    # It will also error out if there's configuration parsing errors so we
+    # can try kill ldirectord even if the config is broken.
+    ldirectord_status
+    RET=$?
+
+    # ldirectord may be running, hard to tell when status returns an error
+    if [ $RET -eq $OCF_ERR_GENERIC ]; then
+        # get the PID of the right ldirectord process
+        PID=`pgrep -f "$LDIRECTORD $LDIRCONF start" 2>&1`
+        RET=$?
+        
+        if [ $RET -eq 0 ]; then
+            ocf_log warn "Killing ldirectord($PID) with SIGTERM"
+            kill $PID
+        fi
+
+        pgrep -f "$LDIRECTORD $LDIRCONF start" >/dev/null 2>&1
+        RET=$?
+        # if ldirectord is not running any more, we've (kind of) successfully
+        # stopped it
+        if [ $RET -eq 1 ]; then
+            return $OCF_SUCCESS
+        else
+            # ldirectord is still running? Kill it badly
+            ocf_log warn "Killing ldirectord($PID) with SIGKILL"
+            kill -9 $PID
+
+            pgrep -f "$LDIRECTORD $LDIRCONF start" >/dev/null 2>&1
+            RET=$?
+            # if it's not dead after here, we can't really do anything more
+            if [ $RET -eq 1 ]; then
+                return $OCF_SUCCESS
+            fi
+        fi
+
+        # if none of our kills work, return an error. This should force the
+        # resource unmanaged
+        # on this node, requiring manual intervention.
+        return $OCF_ERR_GENERIC
+    else
+        ocf_log info "Stopping ldirectord"
+        # if ldirectord status is not an error, issue a stop. Multiple stops
+        # will return 0
+        $LDIRECTORD $LDIRCONF stop
+        RET=$?
+        case $RET in
+            0) return $RET;;
+            *) return 1;;
+        esac
+    fi
+}
+
+# simple check to see if ldirectord is running, returns the proper OCF codes.
+ldirectord_status() {
+    OUTPUT=`$LDIRECTORD $LDIRCONF status 2>&1`
+    case $? in
+        0) return $OCF_SUCCESS;;
+        1) expr match "$OUTPUT" '.*ldirectord stale pid file.*' >/dev/null
+           if [ $? -eq 0 ]; then
+               return $OCF_NOT_RUNNING
+           else
+              return $OCF_ERR_GENERIC
+           fi;;
+        2) ocf_log err "$LDIRCONF has configuration errors"
+           echo $OUTPUT
+           return $OCF_ERR_GENERIC;;
+        3) return $OCF_NOT_RUNNING;;
+        *) echo $OUTPUT
+           return $OCF_ERR_GENERIC;;
+    esac
+}
+
+ldirectord_monitor() {
+    # check if the process is running first
+    ldirectord_status
+    RET=$?
+
+    if [ $RET -ne $OCF_SUCCESS ]; then
+        return $RET
+    fi
+
+    # do more advanced checks here for high OCF_CHECK_LEVELs. Don't know what
+    # more we can do at this time,
+    # a status call already hits LVS in the kernel.
+}
+
+ldirectord_validate() {
+    #ldir_init is already called, there's nothing more we can validate unless
+    #we add more attributes
+    return 0
+}
+
+case $1 in
+	meta-data|usage|help) : ;;
+	*) ldir_init $@ ;;
+esac
+
+case $__OCF_ACTION in
+meta-data)      meta_data
+                exit $OCF_SUCCESS
+                ;;
+start)  ldirectord_start
+                ldirectord_exit $?
+                ;;
+stop)   ldirectord_stop
+                ldirectord_exit $?
+                ;;
+monitor)    ldirectord_monitor
+                ldirectord_exit $?
+                ;;
+validate-all)   ldirectord_validate
+                ldirectord_exit $?
+                ;;
+usage|help)     ldirectord_usage
+                exit $OCF_SUCCESS
+                ;;
+*)              ldirectord_usage
+                exit $OCF_ERR_UNIMPLEMENTED
+                ;;
+esac
diff --git a/ldirectord/init.d/Makefile.am b/ldirectord/init.d/Makefile.am
new file mode 100644
index 0000000..1b7e05c
--- /dev/null
+++ b/ldirectord/init.d/Makefile.am
@@ -0,0 +1,28 @@
+#
+# ldirectord: Linux-HA heartbeat code
+#
+# Copyright (C) 2001 Michael Moerz
+#
+# 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
+
+initddir		= $(INITDIRPREFIX)
+
+initd_SCRIPTS	        = ldirectord
+
+EXTRA_DIST              = $(initd_SCRIPTS) \
+			  $(initd_SCRIPTS).debian $(initd_SCRIPTS).debian.default.in
+
diff --git a/ldirectord/init.d/ldirectord.debian.default.in b/ldirectord/init.d/ldirectord.debian.default.in
new file mode 100644
index 0000000..fe89991
--- /dev/null
+++ b/ldirectord/init.d/ldirectord.debian.default.in
@@ -0,0 +1,6 @@
+# @sysconfdir@/default/ldirectord
+# Defaults for the Debian ldirectord script
+
+# Set to the configuration file
+# May be absolute or relative to @sysconfdir@/ha.d/
+CONFIG_FILE=ldirectord.cf
diff --git a/ldirectord/init.d/ldirectord.debian.in b/ldirectord/init.d/ldirectord.debian.in
new file mode 100644
index 0000000..85e8f02
--- /dev/null
+++ b/ldirectord/init.d/ldirectord.debian.in
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+### BEGIN INIT INFO
+# Provides:          ldirectord
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+#
+# Author: Horms <horms at verge.net.au>
+#
+# Debian init script for ldirectord
+#
+
+NAME=ldirectord
+DAEMON="@sbindir@/$NAME"
+CONFIG="@sysconfdir@/default/$NAME"
+
+test -x $DAEMON || exit 0
+
+CONFIG_FILE=""
+[ -f "$CONFIG" ] && . "$CONFIG"
+CONFIG_FILE="${CONFIG_FILE:=ldirectord.cf}"
+
+case "$1" in
+	start|stop|restart|try-restart|status|reload|force-reload)
+        	exec "$DAEMON" $1
+		;;
+	*)
+		echo "Usage: /etc/init.d/$NAME" \
+			"{start|stop|restart|try-restart|status|reload|force-reload}" >&2
+    	exit 1
+	;;
+esac
diff --git a/ldirectord/init.d/ldirectord.in b/ldirectord/init.d/ldirectord.in
new file mode 100755
index 0000000..9d8083e
--- /dev/null
+++ b/ldirectord/init.d/ldirectord.in
@@ -0,0 +1,90 @@
+#!/bin/sh
+#
+# ldirectord  Linux Director Daemon
+#
+# chkconfig: - 92 40
+# description: Start and stop ldirectord on non-heartbeat systems
+#              Using the config file /etc/ha.d/ldirectord.cf
+#	       Normally ldirectord is started and stopped by heartbeat
+#              
+# processname: ldirectord
+# config: /etc/ha.d/ldirectord.cf
+#
+# Author: Horms <horms at vergenet.net>
+# Released: April 2000
+# Licence: GNU General Public Licence
+#
+### BEGIN INIT INFO
+# Provides:          ldirectord
+# Required-Start:    $syslog $network $remote_fs
+# Required-Stop:    $syslog $network $remote_fs
+# Should-Start: $time sshd
+# Default-Start:     3 5
+# Default-Stop:      0 1 2 6
+# Short-Description: Control Linux Virtual Server via ldirectord on non-heartbeat systems
+# Description:       Starts (and stops) the ldirectord service if
+#	running outside a heartbeat managed environment.
+#	ldirectord manages the Linux Virtual Server component for
+#	TCP/UDP load-balancing.
+#	It uses the config file @sysconfdir@/ha.d/ldirectord.cf.
+### END INIT INFO
+
+DAEMON=@sbindir@/ldirectord
+
+# Source function library.
+if
+  [ -f /etc/rc.d/init.d/functions ]
+then
+  . /etc/rc.d/init.d/functions
+fi
+
+[ -x $DAEMON ] || exit 0
+
+action() {
+  echo -n "$1... "
+  shift
+  $@
+  stat=$?
+  if [ $stat = 0 ]; then
+    echo success
+  else
+    echo failure
+  fi
+  return  $stat
+}
+
+######################################################################
+# Read arument and take action as appropriate
+######################################################################
+
+case "$1" in
+  start)
+        action "Starting ldirectord" $DAEMON start
+	touch /var/lock/subsys/ldirectord
+	;;
+  stop)
+        action "Stopping ldirectord" $DAEMON stop
+	rm -f /var/lock/subsys/ldirectord
+	;;
+  restart)
+        action "Restarting ldirectord" $DAEMON restart
+	;;
+  try-restart)
+        action "Try-Restarting ldirectord" $DAEMON try-restart
+	;;
+  status)
+	$DAEMON status
+	;;
+  reload)
+        action "Reloading ldirectord" $DAEMON reload
+	;;
+  force-reload)
+        action "Force-Reloading ldirectord" $DAEMON force-reload
+	;;
+  *)
+	echo "Usage: ldirectord
+	{start|stop|restart|try-restart|status|reload|force-reload}"
+	exit 1
+esac
+
+exit $?
diff --git a/ldirectord/ldirectord.cf b/ldirectord/ldirectord.cf
new file mode 100644
index 0000000..6948f55
--- /dev/null
+++ b/ldirectord/ldirectord.cf
@@ -0,0 +1,341 @@
+#
+# Sample ldirectord configuration file to configure various virtual services.
+#
+# Ldirectord will connect to each real server once per second and request
+# /index.html. If the data returned by the server does not contain the
+# string "Test Message" then the test fails and the real server will be
+# taken out of the available pool. The real server will be added back into
+# the pool once the test succeeds. If all real servers are removed from the
+# pool then localhost:80 is added to the pool as a fallback measure.
+
+# Global Directives
+checktimeout=3
+checkinterval=1
+#fallback=127.0.0.1:80
+#fallback6=[::1]:80
+autoreload=yes
+#logfile="/var/log/ldirectord.log"
+#logfile="local0"
+#emailalert="admin at x.y.z"
+#emailalertfreq=3600
+#emailalertstatus=all
+quiescent=no
+
+# Sample for an http virtual service
+virtual=192.168.6.240:80
+	real=192.168.6.2:80 gate
+	real=192.168.6.3:80 gate
+	real=192.168.6.6:80 gate
+	fallback=127.0.0.1:80 gate
+	service=http
+	scheduler=rr
+	#persistent=600
+	#netmask=255.255.255.255
+	protocol=tcp
+	checktype=negotiate
+	checkport=80
+	request="index.html"
+	receive="Test Page"
+	virtualhost=www.x.y.z
+
+# Sample configuration for a fwmark based service For an explanation of
+# fwmark see the ipvsadm(8) man page
+#virtual=1
+#	real=192.168.6.2 gate
+#	real=192.168.6.3 gate
+#	real=192.168.6.6 gate
+#	fallback=127.0.0.1:80 gate
+#	service=http
+#	scheduler=rr
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=fwm
+#	checktype=negotiate
+#	checkport=80
+#	request="index.html"
+#	receive="Test Page"
+#	virtualhost=x.y.z
+
+# Sample configuration for a service using a range of real servers
+# and a single real server for a virtual service
+#virtual=192.168.6.240:80
+#	real=192.168.6.2->192.168.6.7:80 gate
+#	real=192.168.6.32:80 gate
+#	fallback=127.0.0.1:80 gate
+#	service=http
+#	scheduler=rr
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	checkport=80
+#	request="index.html"
+#	receive="Test Page"
+#	virtualhost=x.y.z
+
+#Sample configuration for an https virtual service.
+#Fallback setting overrides global
+#virtual=192.168.6.240:443
+#	real=192.168.16.3:443 masq
+#	real=192.168.16.5:443 masq
+#	fallback=127.0.0.1:443
+#	service=https
+#	scheduler=rr
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	checkport=443
+#	request="index.html"
+#	receive="Test Page"
+#	virtualhost=x.y.z
+
+#Sample configuration for an ftp virtual service.
+#Fallback setting overrides global
+#virtual=192.168.6.240:21
+#	real=192.168.16.3:21 masq
+#	real=192.168.16.5:21 masq
+#	fallback=127.0.0.1:21
+#	service=ftp
+#	checkport=21
+#	scheduler=wlc
+#	scheduler=rr
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	login="anonymous"
+#	passwd="ldirectord at localhost"
+#	request="welcome.msg"
+#	receive="test"
+
+#Sample configuration for an smtp virtual service.
+#Fallback setting overrides global
+#virtual=192.168.6.240:25
+#	real=192.168.16.3:25 masq
+#	real=192.168.16.5:25 masq
+#	fallback=127.0.0.1:25
+#	service=smtp
+#	scheduler=wlc
+#	protocol=tcp
+#	persistent=600
+#	#netmask=255.255.255.255
+#	checktype=negotiate
+#	checkport=25
+
+#Sample configuration for an submission virtual service.
+#Fallback setting overrides global
+#virtual=192.168.6.240:587
+#	real=192.168.16.3:587 masq
+#	real=192.168.16.5:587 masq
+#	fallback=127.0.0.1:587
+#	service=submission
+#	scheduler=wlc
+#	protocol=tcp
+#	persistent=600
+#	#netmask=255.255.255.255
+#	checktype=negotiate
+#	checkport=587
+
+#Sample configuration for a pop virtual service.
+#Fallback setting overrides global
+#virtual=192.168.6.240:110
+#	real=192.168.16.3:110 masq
+#	real=192.168.16.5:110 masq
+#	fallback=127.0.0.1:110
+#	service=pop
+#	scheduler=wlc
+#	persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	checkport=110
+#	#login="test"
+#	#passwd="test"
+
+##Sample configuration for an imap virtual service.
+#Fallback setting overrides global
+#virtual=192.168.6.240:143
+#	real=127.0.0.1:143 masq
+#	real=192.168.16.3:143 masq
+#	real=192.168.16.5:143 masq
+#	fallback=127.0.0.1:143
+#	service=imap
+#	scheduler=wlc
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	checkport=143
+#	#login="test"
+#	#passwd="test"
+
+#Sample configuration for an ldap virtual service.
+#Fallback setting overrides global
+#virtual=192.168.84.5:389
+#	real=10.0.1.4:389 masq
+#	real=10.0.1.6:389 masq
+#	fallback=127.0.0.1:389
+#	service=ldap
+#	scheduler=wlc
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	checkport=369
+#	request="dc=upmc, dc=fr"
+#	receive="dc=upmc, dc=fr"
+#	#login="test"
+#	#passwd="test"
+
+#Sample configuration for an nntp virtual service.
+#Fallback setting overrides global
+#virtual=192.168.84.5:119
+#	real=10.0.1.4:119 masq
+#	real=10.0.1.6:119 masq
+#	fallback=127.0.0.1:119
+#	service=nntp
+#	scheduler=wlc
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	checkport=119
+
+#Sample configuration for a UDP DNS virtual service.
+#Fallback setting overrides global
+#virtual=192.168.84.5:53
+#	real=10.0.1.4:53 masq
+#	real=10.0.1.6:53 masq
+#	fallback=127.0.0.1:53
+#	service=dns
+#	scheduler=wlc
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=udp
+#	checktype=negotiate
+#	checkport=53
+#	request="x.y.z"
+#	receive="127.0.0.1"
+
+#Sample configuration for a MySQL virtual service.
+#virtual = 192.168.10.74:3306
+#	real=sql01->sql03:3306 gate 10
+#	fallback=127.0.0.1:3306
+#	service=mysql
+#	scheduler=wrr
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	login="readuser"
+#	passwd="genericpassword"
+#	database="portal"
+#	request="SELECT * FROM link"
+
+#Sample configuration for a PostgreSQL virtual service.
+#virtual = 192.168.10.74:5432
+#	real=sql01->sql03:5432 gate 10
+#	fallback=127.0.0.1:5432
+#	service=pgsql
+#	scheduler=wrr
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	login="readuser"
+#	passwd="genericpassword"
+#	database="portal"
+#	request="SELECT * FROM link"
+
+#Sample configuration for a Oracle virtual service.
+#virtual = 192.168.10.74:1521
+#	real=sql01->sql03:1521 gate 10
+#	fallback=127.0.0.1:1521
+#	service=oracle
+#	scheduler=wrr
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	login="readuser"
+#	passwd="genericpassword"
+#	database="portal"
+#	request="SELECT * FROM link"
+
+#Sample configuration for an unsuported protocol
+#The real servers will just be brought up without checking for availability
+#virtual=192.168.6.240:23
+#	real=192.168.16.3:23 masq
+#	real=192.168.16.5:23 masq
+#	fallback=127.0.0.1:23
+#	service=none
+#	scheduler=wlc
+#	persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=on
+
+# A sample virtual services that uses a ping check.
+# Note that using checktype=connect and protocol=udp
+# will also effect ping checks
+#virtual=192.168.6.240:53
+#	real=192.168.6.2:53 gate
+#	real=192.168.6.3:53 gate
+#	real=192.168.6.6:53 gate
+#	fallback=127.0.0.1:53 gate
+#	scheduler=rr
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=udp
+#	checktype=ping
+#	failurecount=3
+
+# A sample virtual services that uses a Radius check on UDP.
+# Note that using checktype=connect and protocol=udp
+# will also effect ping checks
+#virtual=192.168.6.240:1812
+#	real=192.168.6.2::1812 gate
+#	real=192.168.6.3::1812 gate
+#	real=192.168.6.6::1812 gate
+#	fallback=127.0.0.1:1812 gate
+#	scheduler=rr
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=udp
+#	checktype=negotiate
+#	service=radius
+#	password="readuser"
+#	passwd="genericpassword"
+#	secret="somesecret"
+#	checktimeout=1
+
+# A sample virtual services that uses a SIP check on UDP.
+# Note that using checktype=connect and protocol=udp
+# will also effect ping checks
+#virtual=192.168.6.240:5060
+#	real=192.168.6.2::5060 gate
+#	real=192.168.6.3::5060 gate
+#	real=192.168.6.6::5060 gate
+#	fallback=127.0.0.1:5060 gate
+#	scheduler=rr
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=udp
+#	checktype=negotiate
+#	service=sip
+#	checktimeout=1
+
+#Sample configuration for an nntp virtual service with IPv6.
+#Fallback setting overrides global
+#virtual6=[2001:db8::5]:119
+#	real6=[2001:db8:0:1::4]:119 masq
+#	real6=[2001:db8:0:1::6]:119 masq
+#	fallback6=[::1]:119
+#	service=nntp
+#	scheduler=wlc
+#	#persistent=600
+#	#netmask=255.255.255.255
+#	protocol=tcp
+#	checktype=negotiate
+#	checkport=119
diff --git a/ldirectord/ldirectord.in b/ldirectord/ldirectord.in
new file mode 100644
index 0000000..b871509
--- /dev/null
+++ b/ldirectord/ldirectord.in
@@ -0,0 +1,5258 @@
+#!/usr/bin/perl -w
+######################################################################
+# ldirectord                 http://www.vergenet.net/linux/ldirectord/
+# Linux Director Daemon - run "perldoc ldirectord" for details
+#
+# 1999-2006 (C) Jacob Rief <jacob.rief at tiscover.com>,
+#               Horms <horms at verge.net.au> and others
+#
+# License:      GNU General Public License (GPL)
+#
+# Note: * The original author of this software was Jacob Rief circa 1999
+#       * It was maintained by Jacob Rief and Horms
+#         from November 1999 to July 2003.
+#       * From July 2003 Horms is the maintainer
+#
+# 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
+#
+######################################################################
+
+# A Brief history of versions:
+#
+# From oldest to newest
+# 1.1-1.144: ldirecord maintained in CVS HEAD branch
+# 1.145-1.186: ldirectord.in maintained in CVS HEAD BRANCH
+# 1.186-ha-VERSION: ldirectord.in maintained in mercurial
+
+=head1 NAME
+
+ldirectord - Linux Director Daemon
+
+Daemon to monitor remote services and control Linux Virtual Server
+
+
+=head1 SYNOPSIS
+
+B<ldirectord> [B<-d|--debug>] [--] [I<configfile>]
+B<start> | B<stop> | B<restart> | B<try-restart> | B<reload> | B<force-reload> | B<status>
+
+B<ldirectord> [B<-h|-?|--help|-v|--version>]
+
+=head1 DESCRIPTION
+
+B<ldirectord> is a daemon to monitor and administer real servers in a
+cluster of load balanced virtual servers. B<ldirectord> typically is
+started from heartbeat but can also be run from the command line. On
+startup B<ldirectord> reads the file B<@sysconfdir@/ha.d/conf/>I<configuration>.
+After parsing the file, entries for virtual servers are created on the LVS.
+Now at regular intervals the specified real servers are monitored and if
+they are considered alive, added to a list for each virtual server. If a
+real server fails, it is removed from that list. Only one instance of
+B<ldirectord> can be started for each configuration, but more instances of
+B<ldirectord> may be started for different configurations. This helps to
+group clusters of services.  Normally one would put an entry inside
+B<@sysconfdir@/ha.d/haresources>
+
+I<nodename virtual-ip-address ldirectord::configuration>
+
+to start ldirectord from heartbeat.
+
+
+=head1 OPTIONS
+
+I<configuration>:
+This is the name for the configuration as specified in the file
+B<@sysconfdir@/ha.d/conf/>I<configuration>
+
+B<-d|--debug> Don't start as daemon and log verbosely.
+
+B<-h|--help> Print user manual and exit.
+
+B<-v|--version> Print version and exit.
+
+B<start> the daemon for the specified configuration.
+
+B<stop> the daemon for the specified configuration. This is the same as sending
+a TERM signal to the running daemon.
+
+B<restart> the daemon for the specified configuration. The same as stopping and starting.
+
+B<reload> the configuration file. This is only useful for modifications
+inside a virtual server entry. It will have no effect on adding or
+removing a virtual server block. This is the same as sending a HUP signal to
+the running daemon.
+
+B<status> of the running daemon for the specified configuration.
+
+
+=head1 SYNTAX
+
+=head2 Description of how to write configuration files
+
+B<virtual = >I<(ip_address|hostname:portnumber|servicename)|firewall-mark>
+
+Defines a virtual service by IP-address (or hostname) and port (or
+servicename) or firewall-mark.  A firewall-mark is an integer greater than
+zero. The configuration of marking packets is controlled using the C<-m>
+option to B<ipchains>(8).  All real services and flags for a virtual
+service must follow this line immediately and be indented.
+
+B<checktimeout = >I<n>
+
+Timeout in seconds for connect, external, external-perl and ping checks. If the timeout is
+exceeded then the real server is declared dead.
+
+If defined in a virtual server section then the global value is overridden.
+
+If undefined then the value of negotiatetimeout is used.  negotiatetimeout
+is also a global value that may be overridden by a per-virtual setting.
+
+If both checktimeout and negotiatetimeout are unset, the default is used.
+
+Default: 5 seconds
+
+B<negotiatetimeout = >I<n>
+
+Timeout in seconds for negotiate checks.
+
+If defined in a virtual server section then the global value is overridden.
+
+If undefined then the value of connecttimeout is used.  connecttimeout is
+also a global value that may be overridden by a per-virtual setting.
+
+If both negotiatetimeout and connecttimeout are unset, the default is used.
+
+Default: 30 seconds
+
+B<checkinterval = >I<n>
+
+Defines the number of second between server checks.
+
+When fork=no this option defines the amount of time ldirectord sleeps
+between running all of the realserver checks in all virtual service pools.
+
+When fork=yes this option defines the amount of time each forked child
+sleeps per virtual service pool after running all realserver checks for
+that pool.
+
+If set in the virtual server section then the global value is overridden,
+but ONLY if using forking mode (B<fork = >I<yes>).
+
+Default: 10 seconds
+
+B<checkcount = >I<n>
+
+This option is deprecated and slated for removal in a future version.
+Please see the 'failurecount' option.
+
+The number of times a check will be attempted before it is considered to
+have failed. Only works with ping checks. Note that the
+checktimeout/negotiatetimeout is additive, so if a connect check is used,
+checkcount is 3 and checktimeout is 2 seconds, then a total of 6 seconds
+worth of timeout will occur before the check fails.
+
+If defined in a virtual server section then the global value is overridden.
+
+Default: 1
+
+B<failurecount = >I<n>
+
+The number of consecutive times a failure will have to be reported by a
+check before the realserver is considered to have failed.  A
+value of 1 will have the realserver considered failed on the first failure.
+A successful check will reset the failure counter to 0.
+
+If defined in a virtual server section then the global value is overridden.
+
+Default: 1
+
+B<autoreload = >B<yes> | B<no>
+
+Defines if <ldirectord> should continuously check the configuration file
+for modification. If this is set to 'yes' and the configuration file
+changed on disk and its modification time (mtime) is newer than the
+previous version, the configuration is automatically reloaded.
+
+Default: no
+
+B<callback = ">I</path/to/callback>B<">
+
+If this directive is defined, B<ldirectord> automatically calls
+the executable I</path/to/callback> after the configuration
+file has changed on disk. This is useful to update the configuration
+file through B<scp> on the other heartbeated host. The first argument
+to the callback is the name of the configuration.
+
+This directive might also be used to restart B<ldirectord> automatically
+after the configuration file changed on disk. However, if B<autoreload>
+is set to yes, the configuration is reloaded anyway.
+
+B<fallback = >I<ip_address|hostname[:portnumber|sercvicename]> [B<gate> | B<masq> | B<ipip>]
+
+the server onto which a webservice is redirected if all real
+servers are down. Typically this would be 127.0.0.1 with
+an emergency page.
+
+If defined in a virtual server section then the global value is overridden.
+
+B<fallbackcommand = ">I<path to script>B<">
+
+If this directive is defined, the supplied script is executed whenever all
+real servers for a virtual service are down or when the first real server
+comes up again. In the first case, it is called with "start" as its first
+argument, in the latter with "stop".
+
+If defined in a virtual server section then the global value is overridden.
+
+B<logfile = ">I</path/to/logfile>B<">|syslog_facility
+
+An alternative logfile might be specified with this directive. If the logfile
+does not have a leading '/', it is assumed to be a syslog(3) facility name.
+
+Default: log directly to the file I</var/log/ldirectord.log>.
+
+
+B<emailalert = ">I<emailaddress>[, I<emailaddress>]...B<">
+
+A valid email address for sending alerts about the changed connection status
+to any real server defined in the virtual service.  This option requires
+perl module MailTools to be installed.  Automatically tries to send email
+using any of the built-in methods. See perldoc Mail::Mailer for more info on
+methods.
+
+Multiple addresses may be supplied, comma delimited.
+
+If defined in a virtual server section then the global value is overridden.
+
+
+B<emailalertfrom = >I<emailaddress>
+
+A valid email address to use as the from address of the email alerts.  You
+can use a plain email address or any RFC-compliant string for the From header
+in the body of an email message (such as: "ldirectord Alerts" <alerts at example.com>)
+Do not quote this string unless you want the quotes passed in as part of the
+From header.
+
+Default: unset, take system generated default (probably root at hostname)
+
+
+B<emailalertfreq => I<n>
+
+Delay in seconds between repeating email alerts while any given real server
+in the virtual service remains inaccessible.  A setting of zero seconds
+will inhibit the repeating alerts. The email timing accuracy of this
+setting is dependent on the number of seconds defined in the checkinterval
+configuration option.
+
+If defined in a virtual server section then the global value is overridden.
+
+Default: 0
+
+
+B<emailalertstatus = >B<all> | B<none> | B<starting> | B<running> | B<stopping> | B<reloading>,...
+
+Comma delimited list of server states in which email alerts should be sent.
+B<all> is a short-hand for
+"B<starting>,B<running>,B<stopping>,B<reloading>".  If B<none> is
+specified, no other option may be specified, otherwise options are ored
+with each other.
+
+If defined in a virtual server section then the global value is overridden.
+
+Default: all
+
+
+B<smtp = >I<ip_address|hostname>B<">
+
+A valid SMTP server address to use for sending email via SMTP.
+
+If defined in a virtual server section then the global value is overridden.
+
+
+B<execute = ">I<configuration>B<">
+
+Use this directive to start an instance of ldirectord for
+the named I<configuration>.
+
+
+B<supervised = >B<yes> | B<no>
+
+If I<yes>, then ldirectord does not go into background mode.
+All log-messages are redirected to stdout instead of a logfile.
+This is useful to run B<ldirectord> supervised from daemontools.
+See http://untroubled.org/rpms/daemontools/ or http://cr.yp.to/daemontools.html
+for details.
+
+Default: I<no>
+
+
+B<fork = >B<yes> | B<no>
+
+If I<yes>, then ldirectord will spawn a child process for every virtual server,
+and run checks against the real servers from them.  This will increase response
+times to changes in real server status in configurations with many virtual
+servers.  This may also use less memory then running many separate instances of
+ldirectord.  Child processes will be automatically restarted if they die.
+
+Default: I<no>
+
+
+B<quiescent = >B<yes> | B<no>
+
+If I<yes>, then when real or failback servers are determined
+to be down, they are not actually removed from the kernel's LVS
+table. Rather, their weight is set to zero which means that no
+new connections will be accepted.
+
+This has the side effect, that if the real server has persistent
+connections, new connections from any existing clients will continue to be
+routed to the real server, until the persistent timeout can expire. See
+L<ipvsadm> for more information on persistent connections.
+
+This side-effect can be avoided by running the following:
+
+echo 1 > /proc/sys/net/ipv4/vs/expire_quiescent_template
+
+If the proc file isn't present this probably means that
+the kernel doesn't have LVS support, LVS support isn't loaded,
+or the kernel is too old to have the proc file. Running
+ipvsadm as root should load LVS into the kernel if it is possible.
+
+If I<no>, then the real or failback servers will be removed
+from the kernel's LVS table. The default is I<yes>.
+
+If defined in a virtual server section then the global value is overridden.
+
+Default: I<yes>
+
+B<readdquiescent = >B<yes> | B<no>
+
+If I<yes>, then when real or failback servers are determined
+to be down, they are readded to the kernel's LVS table with weight 0 if
+they do not exist in the table. Setting the value to no, allows manually 
+removing the realserver to manually disable all persistent connections.
+
+B<cleanstop = >B<yes> | B<no>
+
+If I<yes>, then when ldirectord exits it will remove all of the virtual
+server pools that it is managing from the kernel's LVS table.
+
+If I<no>, then the virtual server pools it is managing and any real
+or failback servers listed in them at the time ldirectord exits will
+be left as-is.  If you want to be able to stop ldirectord without having
+traffic to your realservers interrupted you will want to set this to I<no>.
+
+If defined in a virtual server section then the global value is overridden.
+
+Default: I<yes>
+
+
+B<maintenancedir = >I<directoryname>
+
+If this option is set ldirectord will look for a special file in the specified
+directory and, if found, force the status of the real server identified by the
+file to down, skipping the normal health check.  This would be useful if you
+wish to force servers down for maintenance without having to modify the actual
+ldirectord configuration file.
+
+For example, given a realserver with IP 172.16.1.2, service on port 4444, and
+a resolvable reverse DNS entry pointing to "realserver2.example.com" ldirectord
+will check for the existence of the following files:
+
+=over
+
+=item 172.16.1.2:4444
+
+=item 172.16.1.2
+
+=item realserver2.example.com:4444
+
+=item realserver2.example.com
+
+=item realserver2:4444
+
+=item realserver2
+
+=back
+
+If any one of those files is found then ldirectord will immediately force the
+status of the server to down as if the check had failed.
+
+Note: Since it checks for the IP/hostname without the port this means you can
+decide to place an entire realserver into maintenance across a large number of
+virtual service pools with a single file (if you were going to reboot the server,
+for instance) or include the port number and put just a particular service into
+maintenance.
+
+This option is not valid in a virtual server section.
+
+Default: disabled
+
+
+=head2 Section virtual
+
+The following commands must follow a B<virtual> entry and must be indented
+with a minimum of 4 spaces or one tab.
+
+B<real => I<ip_address|hostname[-E<gt>ip_address|hostname][:portnumber|servicename>] B<gate> | B<masq> | B<ipip> [I<weight>] [B<">I<request>B<", ">I<receive>B<">]
+
+Defines a real service by IP-address (or hostname) and port (or
+servicename). If the port is omitted then a 0 will be used, this is
+intended primarily for fwmark services where the port for real servers is
+ignored. Optionally a range of IPv4 addresses (or two hostnames) may be
+given, in which case each IPv4 address in the range will be treated as a real
+server using the given port. The second argument defines the forwarding
+method, must be B<gate>, B<ipip> or B<masq>.  The third argument is
+optional and defines the weight for that real server. If omitted then a
+weight of 1 will be used. The last two arguments are also optional. They
+define a request-receive pair to be used to check if a server is alive.
+They override the request-receive pair in the virtual server section. These
+two strings must be quoted. If the request string starts with I<http://...>
+the IP-address and port of the real server is overridden, otherwise the
+IP-address and port of the real server is used.
+
+=head2
+For TCP and UDP (non fwmark) virtual services, unless the forwarding method
+is B<masq> and the IP address of a real server is non-local (not present on
+a interface on the host running ldirectord) then the port of the real
+server will be set to that of its virtual service. That is, port-mapping is
+only available to if the real server is another machine and the forwarding
+method is B<masq>.  This is due to the way that the underlying LVS code in
+the kernel functions.
+
+=head2
+More than one of these entries may be inside a virtual section.  The
+checktimeout, negotiatetimeout, checkcount, fallback, emailalert,
+emailalertfreq and quiescent options listed above may also appear inside a
+virtual section, in which case the global setting is overridden.
+
+B<checktype =
+>B<connect> | B<external> | B<external-perl> | B<negotiate> | B<off> | B<on> | B<ping> | B<checktimeout>I<N>
+
+Type of check to perform. Negotiate sends a request and matches a receive
+string. Connect only attempts to make a TCP/IP connection, thus the
+request and receive strings may be omitted.  If checktype is a number then
+negotiate and connect is combined so that after each N connect attempts one
+negotiate attempt is performed. This is useful to check often if a service
+answers and in much longer intervals a negotiating check is done. Ping
+means that ICMP ping will be used to test the availability of real servers.
+Ping is also used as the connect check for UDP services. Off means no
+checking will take place and no real or fallback servers will be activated.
+On means no checking will take place and real servers will always be
+activated. Default is I<negotiate>.
+
+B<service = >B<dns> | B<ftp> | B<http> | B<https> | B<http_proxy> | B<imap> | B<imaps> | B<ldap> | B<mysql> | B<nntp> | B<none> | B<oracle> | B<pgsql> | B<pop> | B<pops> | B<radius> | B<simpletcp> | B<sip> | B<smtp> | B<submission>
+
+The type of service to monitor when using checktype=negotiate. None denotes
+a service that will not be monitored.
+
+simpletcp sends the B<request> string to the server and tests it against
+the B<receive> regexp. The other types of checks connect to the server
+using the specified protocol. Please see the B<request> and B<receive>
+sections for protocol specific information.
+
+Default:
+
+=over 4
+
+=item * Virtual server port is 21: ftp
+
+=item * Virtual server port is 25: smtp
+
+=item * Virtual server port is 53: dns
+
+=item * Virtual server port is 80: http
+
+=item * Virtual server port is 110: pop
+
+=item * Virtual server port is 119: nntp
+
+=item * Virtual server port is 143: imap
+
+=item * Virtual server port is 389: ldap
+
+=item * Virtual server port is 443: https
+
+=item * Virtual server port is 587: submission
+
+=item * Virtual server port is 993: imaps
+
+=item * Virtual server port is 995: pops
+
+=item * Virtual server port is 1521: oracle
+
+=item * Virtual server port is 1812: radius
+
+=item * Virtual server port is 3128: http_proxy
+
+=item * Virtual server port is 3306: mysql
+
+=item * Virtual server port is 5432: pgsql
+
+=item * Virtual server port is 5060: sip
+
+=item * Otherwise: none
+
+=back
+
+
+B<checkcommand = ">I<path to script>B<">
+
+This setting is used if checktype is external or external-perl and is the command to be run
+to check the status of a real server. It should exit with status 0 if
+everything is ok, or non-zero otherwise.
+
+Four parameters are passed to the script:
+
+=over 4
+
+=item * virtual server ip/firewall mark
+
+=item * virtual server port
+
+=item * real server ip
+
+=item * real server port
+
+=back
+
+If the checktype is external-perl then the command is assumed to be a
+Perl script and it is evaluated into an anonymous subroutine which is
+called at check time, avoiding a fork-exec.  The argument signature and
+exit code conventions are identical to checktype external.  That is, an
+external-perl checktype should also work as an external checktype.
+
+Default: /bin/true
+
+B<checkport = >I<n>
+
+Number of port to monitor. Sometimes check port differs from service port.
+
+Default: port specified for each real server
+
+B<request = ">I<uri to requested object>B<">
+
+This object will be requested each checkinterval seconds on each real
+server.  The string must be inside quotes. Note that this string may be
+overridden by an optional per real-server based request-string.
+
+For an HTTP/HTTPS check, this should be a relative URI, while it has to
+be absolute for the 'http_proxy' check type. In the latter case, this
+URI will be requested through the proxy backend that is being checked.
+
+For a DNS check this should the name of an A record, or the address
+of a PTR record to look up.
+
+For a MySQL, Oracle or PostgeSQL check, this should be an SQL SELECT query.
+The data returned is not checked, only that the
+answer is one or more rows.  This is a required setting.
+
+For a simpletcp check, this string is sent verbatim except any occurrences
+of \n are replaced with a new line character.
+
+B<receive = ">I<regexp to compare>B<">
+
+If the requested result contains this I<regexp to compare>, the real server
+is declared alive. The regexp must be inside quotes. Keep in mind that
+regexps are not plain strings and that you need to escape the special
+characters if they should as literals. Note that this regexp may be
+overridden by an optional per real-server based receive regexp.
+
+For a DNS check this should be any one the A record's addresses or
+any one of the PTR record's names.
+
+For a MySQL check, the receive setting is not used.
+
+B<httpmethod = GET> | B<HEAD>
+
+Sets the HTTP method which should be used to fetch the URI specified in
+the request-string. GET is the method used by default if the parameter is
+not set. If HEAD is used, the receive-string should be unset.
+
+Default: GET
+
+B<virtualhost = ">I<hostname>B<">
+
+Used when using a negotiate check with HTTP or HTTPS. Sets the host header
+used in the HTTP request.  In the case of HTTPS this generally needs to
+match the common name of the SSL certificate. If not set then the host
+header will be derived from the request url for the real server if present.
+As a last resort the IP address of the real server will be used.
+
+B<login = ">I<username>B<">
+
+For FTP, IMAP, LDAP, MySQL, Oracle, POP and PostgreSQL, the username
+used to log in.
+
+For Radius the passwd is used for the attribute User-Name.
+
+For SIP, the username is used as both the to and from address for an
+OPTIONS query.
+
+Default:
+
+=over 4
+
+=item * FTP: Anonymous
+
+=item * MySQL Oracle, and PostgreSQL: Must be specified in the configuration
+
+=item * SIP: ldirectord\@<hostname>, hostname is derived as per the passwd
+	option below.
+
+=item * Otherwise: empty string, which denotes that
+	case authentication will not be attempted.
+
+=back
+
+B<passwd = ">I<password>B<">
+
+Password to use to login to FTP, IMAP, LDAP, MySQL, Oracle, POP, PostgreSQL
+and SIP servers.
+
+For Radius the passwd is used for the attribute User-Password.
+
+Default:
+
+=over 4
+
+=item * FTP: ldirectord\@<hostname>,
+	where hostname is the environment variable HOSTNAME evaluated at
+	run time, or sourced from uname if unset.
+
+=item * Otherwise: empty string.
+	In the case of LDAP, MySQL, Oracle, and PostgreSQL this means
+	that authentication will not be performed.
+
+=back
+
+B<database = ">I<databasename>B<">
+
+Database to use for MySQL, Oracle and PostgreSQL servers, this is the
+database that the query (set by B<receive> above) will be performed
+against.  This is a required setting.
+
+B<secret = ">I<radiussecret>B<">
+
+Secret to use for Radius servers, this is the secret used to perform an
+Access-Request with the username (set by B<login> above) and passwd (set by
+B<passwd> above).
+
+Default: empty string
+
+B<scheduler => I<scheduler_name>
+
+Scheduler to be used by LVS for loadbalancing.
+For an information on the available sehedulers please see
+the ipvsadm(8) man page.
+
+Default: "wrr"
+
+B<persistent => I<n>
+
+Number of seconds for persistent client connections.
+
+B<netmask => I<w.x.y.z> | I<prefixlen>
+
+Netmask to be used for granularity of persistent client connections.
+IPv4 netmask should be specified in dotted quad notation.
+IPv6 netmask should be specified as a prefix length between 1 and 128.
+
+B<protocol = tcp> | B<udp> | B<fwm>
+
+Protocol to be used. If the virtual is specified as an IP address and port
+then it must be one of tcp or udp. If a firewall
+mark then the protocol must be fwm.
+
+Default:
+
+=over 4
+
+=item * Virtual is an IP address and port, and the port is not 53: tcp
+
+=item * Virtual is an IP address and port, and the port is 53: udp
+
+=item * Virtual is a firewall mark: fwm
+
+=back
+
+B<monitorfile = ">I</path/to/monitorfile>B<">
+
+File to continuously log the real service checks to for this virtual
+service. This is useful for monitoring when and why real services were down
+or for statistics.
+
+The log format is:
+[timestamp|pid|real_service_id|status|message]
+
+Default: no separate logging of service checks.
+
+=head1 IPv6
+
+Directives for IPv6 are virtual6, real6, fallback6.
+IPv6 addresses specified for virtual6, real6, fallback6 and a file
+of maintenance directory should be enclosed by
+brackets ([2001:db8::abcd]:80).
+
+Following checktype and service are supported.
+
+B<checktype: >B<connect> | B<external> | B<external-perl> | B<negotiate> | B<off> | B<on> | B<checktimeout>I<N>
+
+B<service: >B<dns> | B<nntp> | B<none> | B<simpletcp> | B<sip>
+
+
+=head1 FILES
+
+B<@sysconfdir@/ha.d/ldirectord.cf>
+
+B</var/log/ldirectord.log>
+
+B</var/run/ldirectord.>I<configuration>B<.pid>
+
+B</etc/services>
+
+=head1 SEE ALSO
+
+L<ipvsadm>, L<heartbeat>
+
+Ldirectord Web Page: http://www.vergenet.net/linux/ldirectord/
+
+
+=head1 AUTHORS
+
+Horms <horms at verge.net.au>
+
+Jacob Rief <jacob.rief at tiscover.com>
+
+=cut
+
+use strict;
+# Set defaults for configuration variables in the "set_defaults" function
+use vars qw(
+	    $VERSION_STR
+	    $AUTOCHECK
+	    $CHECKINTERVAL
+	    $LDIRECTORD
+	    $LDIRLOG
+	    $NEGOTIATETIMEOUT
+	    $DEFAULT_NEGOTIATETIMEOUT
+	    $RUNPID
+	    $CHECKTIMEOUT
+	    $DEFAULT_CHECKTIMEOUT
+	    $CHECKCOUNT
+	    $FAILURECOUNT
+	    $QUIESCENT
+	    $READDQUIESCENT
+	    $FORKING
+	    $EMAILALERT
+	    $EMAILALERTFREQ
+	    $EMAILALERTSTATUS
+	    $EMAILALERTFROM
+	    $SMTP
+	    $CLEANSTOP
+	    $MAINTDIR
+
+	    $CALLBACK
+	    $CFGNAME
+	    $CMD
+	    $CONFIG
+	    $DEBUG
+	    $FALLBACK
+	    $FALLBACK6
+	    $FALLBACKCOMMAND
+	    $SUPERVISED
+	    $IPVSADM
+	    $checksum
+	    $DAEMON_STATUS
+	    $DAEMON_STATUS_STARTING
+	    $DAEMON_STATUS_RUNNING
+	    $DAEMON_STATUS_STOPPING
+	    $DAEMON_STATUS_RELOADING
+	    $DAEMON_STATUS_ALL
+	    $DAEMON_TERM
+	    $DAEMON_HUP
+	    $DAEMON_CHLD
+	    $opt_d
+	    $opt_h
+	    $stattime
+	    %LD_INSTANCE
+	    @OLDVIRTUAL
+	    @REAL
+	    @VIRTUAL
+	    $HOSTNAME
+	    %EMAILSTATUS
+	    %FORK_CHILDREN
+	    $SERVICE_UP
+	    $SERVICE_DOWN
+	    %check_external_perl__funcs
+
+	    $CRLF
+);
+
+$VERSION_STR = "Linux Director v1.186-ha";
+
+$DAEMON_STATUS_STARTING  = 0x1;
+$DAEMON_STATUS_RUNNING   = 0x2;
+$DAEMON_STATUS_STOPPING  = 0x4;
+$DAEMON_STATUS_RELOADING = 0x8;
+$DAEMON_STATUS_ALL       = $DAEMON_STATUS_STARTING |
+			   $DAEMON_STATUS_RUNNING  |
+			   $DAEMON_STATUS_STOPPING |
+			   $DAEMON_STATUS_RELOADING;
+
+$SERVICE_UP	= 0;
+$SERVICE_DOWN	=1;
+
+# default values
+$DAEMON_TERM      = undef;
+$DAEMON_HUP       = undef;
+$LDIRECTORD       = ld_find_cmd("ldirectord", 1);
+if (! defined $LDIRECTORD) {
+	$LDIRECTORD = "@sbindir@/ldirectord";
+}
+$RUNPID           = "/var/run/ldirectord";
+
+$CRLF = "\x0d\x0a";
+
+# Set global configuration default values:
+set_defaults();
+
+use Getopt::Long;
+use Pod::Usage;
+#use English;
+#use Time::HiRes qw( gettimeofday tv_interval );
+use Socket;
+use Socket6 qw(NI_NUMERICHOST NI_NUMERICSERV NI_NAMEREQD getaddrinfo getnameinfo);
+use Sys::Hostname;
+use POSIX qw(setsid :sys_wait_h);
+use Sys::Syslog qw(:DEFAULT setlogsock);
+
+BEGIN
+{
+	# wrap exit() to preserve replacability
+	*CORE::GLOBAL::exit = sub { CORE::exit(@_ ? shift : 0); };
+}
+
+# command line options
+my @OLD_ARGV = @ARGV;
+my $opt_d = '';
+my $opt_h = '';
+my $opt_v = '';
+Getopt::Long::Configure ("bundling", "no_auto_abbrev", "require_order");
+GetOptions("debug|d" => \$opt_d,
+	   "help|h|?" => \$opt_h,
+	   "version|v" => \$opt_v) or usage();
+
+# main code
+$DEBUG = $opt_d ? 3 : 0;
+
+if ($opt_h) {
+	exec_wrapper("/usr/bin/perldoc -U $LDIRECTORD");
+	&ld_exit(127, "Exec failed");
+}
+if ($opt_v) {
+	print("$VERSION_STR\n" .
+	      "1999-2006 Jacob Rief, Horms and others\n" .
+	      "<http://www.vergenet.net/linux/ldirectord/>\n".
+	      "\n" .
+	      "ldirectord comes with ABSOLUTELY NO WARRANTY.\n" .
+	      "This is free software, and you are welcome to redistribute it\n".
+	      "under certain conditions. " .
+		      "See the GNU General Public Licence for details.\n");
+
+	&ld_exit(0, "");
+}
+
+if ($DEBUG>0 and -f "./ipvsadm") {
+	$IPVSADM="./ipvsadm";
+} else {
+	if (-x "/sbin/ipvsadm") {
+		$IPVSADM="/sbin/ipvsadm";
+	} elsif (-x "/usr/sbin/ipvsadm") {
+		$IPVSADM="/usr/sbin/ipvsadm";
+	} else {
+		die "Can not find ipvsadm";
+	}
+}
+
+# There is a memory leak in perl's socket code when
+# the default IO layer is used. So use "perlio" unless
+# something else has been explicitly set.
+# http://archive.develooper.com/perl5-porters@perl.org/msg85468.html
+unless(defined($ENV{'PERLIO'})) {
+	$ENV{'PERLIO'} = "perlio";
+	exec_wrapper($0, @OLD_ARGV);
+}
+
+$DAEMON_STATUS = $DAEMON_STATUS_STARTING;
+ld_init();
+ld_setup();
+ld_start();
+ld_cmd_children("start", %LD_INSTANCE);
+$DAEMON_STATUS = $DAEMON_STATUS_RUNNING;
+ld_main();
+
+&ld_rm_file("$RUNPID.$CFGNAME.pid");
+&ld_exit(0, "Reached end of \"main\"");
+
+# functions
+sub ld_init
+{
+	# install signal handlers (this covers TERM)
+	#require Net::LDAP;
+	$SIG{'INT'} = \&ld_handler_term;
+	$SIG{'QUIT'} = \&ld_handler_term;
+	$SIG{'ILL'} = \&ld_handler_term;
+	$SIG{'ABRT'} = \&ld_handler_term;
+	$SIG{'FPE'} = \&ld_handler_term;
+	$SIG{'SEGV'} = \&ld_handler_term;
+	$SIG{'TERM'} = \&ld_handler_term;
+
+	$SIG{'BUS'} = \&ld_handler_term;
+	$SIG{'SYS'} = \&ld_handler_term;
+	$SIG{'XCPU'} = \&ld_handler_term;
+	$SIG{'XFSZ'} = \&ld_handler_term;
+
+	$SIG{'IOT'} = \&ld_handler_term;
+
+
+	# This used to call a signal handler, that logged a message
+	# However, this typically goes to syslog and if syslog
+	# is playing up a loop will occur.
+	$SIG{'PIPE'} = "IGNORE";
+
+	# HUP is actually used
+	$SIG{'HUP'} = \&ld_handler_hup;
+
+	# Reap Children
+	$SIG{'CHLD'} = \&ld_handler_chld;
+
+	if (defined $ENV{HOSTNAME}) {
+		$HOSTNAME = "$ENV{HOSTNAME}";
+	}
+	else {
+		use POSIX "uname";
+		my ($s, $n, $r, $v, $m) = uname;
+		$HOSTNAME = $n;
+	}
+
+	# search for the correct configuration file
+	if ( !defined $ARGV[0] ) {
+		usage();
+	}
+	if ( defined $ARGV[0] && defined $ARGV[1] ) {
+		$CONFIG = $ARGV[0];
+		if ($CONFIG =~ /([^\/]+)$/) {
+			$CFGNAME = $1;
+		}
+		$CMD = $ARGV[1];
+	} elsif ( defined $ARGV[0] ) {
+		$CONFIG = "ldirectord.cf";
+		$CFGNAME = "ldirectord";
+		$CMD = $ARGV[0];
+	}
+	if ( $CMD ne "start" and $CMD ne "stop" and $CMD ne "status"
+			and $CMD ne "restart" and $CMD ne "try-restart"
+			and $CMD ne "reload" and $CMD ne "force-reload") {
+		usage();
+	}
+	if ( -f "@sysconfdir@/ha.d/$CONFIG" ) {
+		$CONFIG = "@sysconfdir@/ha.d/$CONFIG";
+	} elsif ( -f "@sysconfdir@/ha.d/conf/$CONFIG" ) {
+		$CONFIG = "@sysconfdir@/ha.d/conf/$CONFIG";
+	} elsif ( ! -f "$CONFIG" ) {
+		init_error("Config file $CONFIG not found");
+	}
+	read_config();
+	undef @OLDVIRTUAL;
+
+	{
+		my $log_str = "Invoking ldirectord invoked as: $0 ";
+		for my $i (@ARGV) {
+			$log_str .= $i . " ";
+		}
+		ld_log($log_str);
+	}
+
+	my $oldpid;
+	my $filepid;
+	if (open(FILE, "<$RUNPID.$CFGNAME.pid")) {
+		$_ = <FILE>;
+		chomp;
+		$filepid = $_;
+		close(FILE);
+		# Check to make sure this isn't a stale pid file
+		if (open(FILE, "</proc/$filepid/cmdline")) {
+			$_ = <FILE>;
+			if (/ldirectord/) {
+				$oldpid = $filepid;
+			}
+			close(FILE);
+		}
+	}
+	if (defined $oldpid) {
+		if ($CMD eq "start") {
+			ld_exit(0, "Exiting from ldirectord $CMD");
+		} elsif ($CMD eq "stop") {
+			kill 15, $oldpid;
+			ld_exit(0, "Exiting from ldirectord $CMD");
+		} elsif ($CMD eq "restart" or $CMD eq "try-restart") {
+			kill 15, $oldpid;
+			while (-f "$RUNPID.$CFGNAME.pid") {
+				# wait until old pid file is removed
+				sleep 1;
+			}
+			# N.B Fall through
+		} elsif ($CMD eq "reload" or $CMD eq "force-reload") {
+			kill 1, $oldpid;
+			ld_exit(0, "Exiting from ldirectord $CMD");
+		} else { # status
+			print STDERR "ldirectord for $CONFIG is running with pid: $oldpid\n";
+			ld_cmd_children("status", %LD_INSTANCE);
+			ld_log("ldirectord for $CONFIG is running with pid: $oldpid");
+			ld_log("Exiting from ldirectord $CMD");
+			ld_exit(0, "Exiting from ldirectord $CMD");
+		}
+	} else {
+		if ($CMD eq "start" or $CMD eq "restart") {
+			;
+		} elsif ($CMD eq "stop" or $CMD eq "try-restart") {
+			ld_exit(0, "Exiting from ldirectord $CMD");
+		} elsif ($CMD eq "status") {
+			my $status;
+			if (defined $filepid) {
+				print STDERR "ldirectord stale pid file " .
+					"$RUNPID.$CFGNAME.pid for $CONFIG\n";
+				ld_log("ldirectord stale pid file " .
+					"$RUNPID.$CFGNAME.pid for $CONFIG");
+				$status = 1;
+			} else {
+				$status = 3;
+			}
+			print "ldirectord is stopped for $CONFIG\n";
+			ld_exit($status, "Exiting from ldirectord $CMD");
+		} else {
+			ld_log("ldirectord is stopped for $CONFIG");
+			ld_exit(1, "Exiting from ldirectord $CMD");
+		}
+	}
+
+	# Run as daemon
+	if ($SUPERVISED eq "yes" || $opt_d) {
+		&ld_log("Starting $VERSION_STR with pid: $$");
+	} else {
+		&ld_log("Starting $VERSION_STR as daemon");
+		open(FILE, ">$RUNPID.$CFGNAME.pid") ||
+			init_error("Can not open $RUNPID.$CFGNAME.pid");
+		&ld_daemon();
+		print FILE "$$\n";
+		close(FILE);
+	}
+}
+
+sub usage
+{
+	pod2usage(-input => $LDIRECTORD, -exitval => -1);
+}
+
+sub init_error
+{
+	my $msg = shift;
+	chomp($msg);
+	&ld_log("$msg");
+	unless ($opt_d) {
+		print STDERR "$msg\n";
+	}
+	ld_exit(1, "Initialisation Error");
+}
+
+# ld_handler_term
+# If we get a signal then log it and quit
+sub ld_handler_term
+{
+	my ($signal) = (@_);
+
+	if (defined $DAEMON_TERM) {
+		$SIG{'__DIE__'} = "IGNORE";
+		$SIG{"$signal"} = "IGNORE";
+		die("Exit Handler Repeatedly Called\n");
+	}
+	$DAEMON_TERM = $signal;
+	$DAEMON_STATUS = $DAEMON_STATUS_STOPPING;
+}
+
+sub ld_process_term
+{
+	$DAEMON_STATUS = $DAEMON_STATUS_STOPPING;
+	ld_cmd_children("stop", %LD_INSTANCE);
+	ld_stop();
+	&ld_log("Linux Director Daemon terminated on signal: $DAEMON_TERM");
+	&ld_rm_file("$RUNPID.$CFGNAME.pid");
+	&ld_exit(0, "Linux Director Daemon terminated on signal: $DAEMON_TERM");
+}
+
+sub ld_handler_hup
+{
+	$DAEMON_HUP=1;
+}
+
+sub ld_process_hup
+{
+	&ld_log("Reloading Linux Director Daemon config on signal");
+	$DAEMON_HUP = undef;
+	&reread_config();
+}
+
+sub ld_handler_chld
+{
+	$DAEMON_CHLD=1;
+	# NOTE: calling waitpid here would mess up $?
+}
+
+sub ld_process_chld
+{
+	my $i = 0;
+
+	undef $DAEMON_CHLD;
+	while (waitpid(-1, WNOHANG) > 0) {
+		print "child: $i\n";
+		$i++;
+	}
+}
+
+sub check_signal
+{
+	if (defined $DAEMON_TERM) {
+		ld_process_term();
+	}
+	if (defined $DAEMON_HUP) {
+		ld_process_hup();
+	}
+	if (defined $DAEMON_CHLD) {
+		ld_process_chld();
+	}
+}
+
+sub reread_config
+{
+	@OLDVIRTUAL = @VIRTUAL;
+	@VIRTUAL = ();
+	my %OLD_INSTANCE = %LD_INSTANCE;
+	my %RELOAD;
+	my %STOP;
+	my %START;
+	my $child;
+	$DAEMON_STATUS = $DAEMON_STATUS_RELOADING;
+	eval {
+		&read_config();
+
+		foreach $child (keys %LD_INSTANCE) {
+			if (defined $OLD_INSTANCE{$child}) {
+				$RELOAD{$child} = 1;
+			}
+			else {
+				$START{$child} = 1;
+			}
+		}
+
+		foreach $child (keys %OLD_INSTANCE) {
+			if (not defined $LD_INSTANCE{$child}) {
+				$STOP{$child} = 1;
+			}
+		}
+
+		&ld_cmd_children("stop", %STOP);
+		&ld_cmd_children("reload_or_start", %RELOAD);
+		&ld_cmd_children("start", %START);
+
+		foreach my $vid (keys %FORK_CHILDREN) {
+			&ld_log("Killing child $vid (PID=$FORK_CHILDREN{$vid})");
+			kill 15, $FORK_CHILDREN{$vid};
+		}
+
+		&ld_setup();
+		&ld_start();
+	};
+	if ($@) {
+		@VIRTUAL = @OLDVIRTUAL;
+		%LD_INSTANCE = %OLD_INSTANCE;
+	}
+	$DAEMON_STATUS = $DAEMON_STATUS_RUNNING;
+	undef @OLDVIRTUAL;
+}
+
+sub parse_emailalertstatus
+{
+	my ($line, $arg) = (@_);
+
+	my @s = split/\s*,\s*/, $arg;
+	my $none = 0;
+	my $status = 0;
+
+	for my $i (@s) {
+		if ($i eq "none") {
+			$none++;
+		}
+	}
+
+	for my $i (@s) {
+		if ($i eq "none") {
+			next;
+		}
+		elsif ($i eq "all") {
+			$status = $DAEMON_STATUS_ALL;
+		}
+		elsif ($i eq "starting") {
+			$status |= $DAEMON_STATUS_STARTING;
+		}
+		elsif ($i eq "stopping") {
+			$status |= $DAEMON_STATUS_STOPPING;
+		}
+		elsif ($i eq "running") {
+			$status |= $DAEMON_STATUS_RUNNING;
+		}
+		elsif ($i eq "reloading") {
+			$status |= $DAEMON_STATUS_RELOADING;
+		}
+		else {
+			&config_error($line,
+				      "invalid email alert status at: \"$i\"")
+		}
+		if ($none > 0) {
+			&config_error($line, "invalid email alert status: " .
+				      "\"$i\" specified with \"none\"");
+		}
+	}
+	return $status;
+}
+
+sub set_defaults
+{
+	$AUTOCHECK        = "no";
+	$CALLBACK         = undef;
+	$CHECKCOUNT       = 1;
+	$CHECKINTERVAL    = 10;
+	$CHECKTIMEOUT     = -1;
+	$CLEANSTOP	  = "yes";
+	$DEFAULT_CHECKTIMEOUT     = 5;
+	$DEFAULT_NEGOTIATETIMEOUT = 30;
+	$EMAILALERT	  = "";
+	$EMAILALERTFREQ	  = 0;
+	$EMAILALERTFROM   = undef;
+	$EMAILALERTSTATUS = $DAEMON_STATUS_ALL;
+	$FAILURECOUNT     = 1;
+	$FALLBACK         = undef;
+	$FALLBACK6        = undef;
+	$FALLBACKCOMMAND  = undef;
+	$FORKING          = "no";
+	$LDIRLOG          = "/var/log/ldirectord.log";
+	$MAINTDIR         = undef;
+	$NEGOTIATETIMEOUT = -1;
+	$QUIESCENT        = "no";
+	$READDQUIESCENT   = "no";
+	$SUPERVISED       = "no";
+	$SMTP             = undef;
+}
+
+sub read_emailalert
+{
+	my ($line, $addr) = (@_);
+
+	# Strip of enclosing quotes
+	$addr =~ s/^\"([^"]*)\"$/$1/;
+
+	$addr =~ /(.+)/ or &config_error($line, "no email address specified");
+
+	return $addr;
+}
+
+sub read_config
+{
+	undef @VIRTUAL;
+	undef @REAL;
+	undef $CALLBACK;
+	undef %LD_INSTANCE;
+	undef $checksum;
+	# Reset/set global config variables to defaults before parsing the config file.
+	set_defaults();
+	$stattime = 0;
+	my %virtual_seen;
+	open(CFGFILE, "<$CONFIG") or
+		&config_error(0, "can not open file $CONFIG");
+	my $line = 0;
+	my $linedata;
+	while(<CFGFILE>) {
+		$line++;
+		$linedata = $_;
+		outer_loop:
+		if ($linedata =~ /^virtual(6)?\s*=\s*(.*)/) {
+			my $af = defined($1) ? AF_INET6 : AF_INET;
+			my $vattr = $2;
+			my $ip_port = undef;
+			my $fwm = undef;
+			my $virtual_id;
+			my $virtual_line = $line;
+			my $virtual_port;
+			my $fallback_line;
+			my @rsrv_todo;
+			if ($vattr =~ /^(\d+\.\d+\.\d+\.\d+):([0-9A-Za-z-_]+)/ && $af == AF_INET) {
+				$ip_port = "$1:$2";
+				$virtual_port = $2;
+			} elsif ($vattr =~ /^([0-9A-Za-z._+-]+):([0-9A-Za-z-_]+)/) {
+				$ip_port = "$1:$2";
+				$virtual_port = $2;
+			} elsif ($vattr =~ /^(\d+)/){
+				$fwm = $1;
+			} elsif ($vattr =~ /^\[([0-9A-Fa-f:]+)\]:([0-9A-Za-z-_]+)/ && $af == AF_INET) {
+				&config_error($line, "cannot specify an IPv6 address here. please use \"virtual6\" instead.");
+			} elsif ($vattr =~ /^\[([0-9A-Fa-f:]+)\]:([0-9A-Za-z-_]+)/ && $af == AF_INET6) {
+				my $v6addr = $1;
+				my $v6port = $2;
+				if (!inet_pton(AF_INET6,$v6addr)) {
+					&config_error($line,"invalid ipv6 address for virtual server");
+				}
+				$ip_port = "[$v6addr]:$v6port";
+				$virtual_port = $v6port;
+			} else {
+				&config_error($line,
+					"invalid address for virtual server");
+			}
+
+			my (%vsrv, @rsrv);
+			if ($ip_port) {
+				$vsrv{checktype} = "negotiate";
+				$vsrv{protocol} = "tcp";
+				if ($ip_port =~ /:(53|domain)$/) {
+					$vsrv{protocol} = "udp";
+				}
+				$vsrv{port} = $virtual_port;
+			} else {
+				$vsrv{fwm} = $fwm;
+				$vsrv{checktype} = "negotiate";
+				$vsrv{protocol} = "fwm";
+				$vsrv{service} = "none";
+				$vsrv{port} = "0";
+			}
+			$vsrv{addressfamily} = $af;
+			$vsrv{real} = \@rsrv;
+			$vsrv{scheduler} = "wrr";
+			$vsrv{checkcommand} = "/bin/true";
+			$vsrv{request} = "/";
+			$vsrv{receive} = "";
+			$vsrv{login} = "";
+			$vsrv{passwd} = "";
+			$vsrv{database} = "";
+			$vsrv{checktimeout} = -1;
+			$vsrv{checkcount} = -1;
+			$vsrv{negotiatetimeout} = -1;
+			$vsrv{failurecount} = -1;
+			$vsrv{num_connects} = 0;
+			$vsrv{httpmethod} = "GET";
+			$vsrv{secret} = "";
+			push(@VIRTUAL, \%vsrv);
+			while(<CFGFILE>) {
+				$line++;
+				$linedata=$_;
+				if(m/^\s*#/) {
+					next;
+				}
+				s/#.*//;
+				s/\t/    /g;
+				unless (/^ {4,}(.+)/) {
+					last;
+				}
+				my $rcmd = $1;
+				if ($rcmd =~ /^(real(6)?)\s*=\s*(.*)/) {
+					if ($af == AF_INET  &&   defined($2) ||
+					    $af == AF_INET6 && ! defined($2)) {
+					    &config_error($line, join("", ("cannot specify \"$1\" here.  please use \"real", ($af == AF_INET) ?  "" : "6", "\" instead")));
+					}
+					push @rsrv_todo, [$3, $line];
+				} elsif ($rcmd =~ /^request\s*=\s*\"(.*)\"/) {
+					$1 =~ /(.+)/ or &config_error($line, "no request string specified");
+					$vsrv{request} = $1;
+					unless($vsrv{request}=~/^\//){
+						$vsrv{request} = "/" . $vsrv{request};
+					}
+
+				} elsif ($rcmd =~ /^receive\s*=\s*\"(.*)\"/) {
+					$1 =~ /(.+)/ or &config_error($line, "invalid receive string");
+					$vsrv{receive} = $1;
+				} elsif ($rcmd =~ /^checktype\s*=\s*(.*)/){
+					if ($1 =~ /(\d+)/ && $1>=0) {
+						$vsrv{num_connects} = $1;
+						$vsrv{checktype} = "combined";
+					} elsif ( $1 =~ /([\w-]+)/ && ($1 eq "connect" || $1 eq "negotiate" || $1 eq "ping" || $1 eq "off" || $1 eq "on" || $1 eq "external" || $1 eq "external-perl") ) {
+						$vsrv{checktype} = $1;
+					} else {
+						&config_error($line, "checktype must be \"connect\", \"negotiate\", \"on\", \"off\", \"ping\", \"external\", \"external-perl\" or a positive number");
+					}
+				} elsif ($rcmd =~ /^checkcommand\s*=\s*\"(.*)\"/ or $rcmd =~ /^checkcommand\s*=\s*(.*)/){
+					$1 =~ /(.+)/ or &config_error($line, "invalid check command");
+					$vsrv{checkcommand} = $1;
+				} elsif ($rcmd =~ /^checktimeout\s*=\s*(.*)/){
+					$1 =~ /(\d+)/ && $1 or &config_error($line, "invalid check timeout");
+					$vsrv{checktimeout} = $1;
+				} elsif ($rcmd =~ /^connecttimeout\s*=\s*(.*)/){
+					&config_error($line,
+						"connecttimeout directive " .
+						"deprecated in favour of " .
+						"negotiatetimeout");
+				} elsif ($rcmd =~ /^negotiatetimeout\s*=\s*(.*)/){
+					$1 =~ /(\d+)/ && $1 or &config_error($line, "invalid negotiate timeout");
+					$vsrv{negotiatetimeout} = $1;
+				} elsif ($rcmd =~ /^checkcount\s*=\s*(.*)/){
+					$1 =~ /(\d+)/ && $1 or &config_error($line, "invalid check count");
+					$vsrv{checkcount} = $1;
+					&config_warn($line, "checkcount option is deprecated and slated for removal.  please see 'failurecount'");
+				} elsif ($rcmd =~ /^failurecount\s*=\s*(.*)/){
+					$1 =~ /(\d+)/ && $1 or &config_error($line, "invalid failure count");
+					$vsrv{failurecount} = $1;
+				} elsif ($rcmd =~ /^checkinterval\s*=\s*(.*)/){
+					$1 =~ /(\d+)/ && $1 or &config_error($line, "invalid checkinterval");
+					$vsrv{checkinterval} = $1
+				} elsif ($rcmd =~ /^checkport\s*=\s*(.*)/){
+					$1 =~ /(\d+)/ or &config_error($line, "invalid port");
+					( $1 > 0 && $1 < 65536 ) or &config_error($line, "checkport must be in range 1..65536");
+					$vsrv{checkport} = $1;
+				} elsif ($rcmd =~ /^login\s*=\s*\"(.*)\"/) {
+					$1 =~ /(.+)/ or &config_error($line, "invalid login string");
+					$vsrv{login} = $1;
+				} elsif ($rcmd =~ /^passwd\s*=\s*\"(.*)\"/) {
+					$1 =~ /(.+)/ or &config_error($line, "invalid password");
+					$vsrv{passwd} = $1;
+				} elsif ($rcmd =~ /^database\s*=\s*\"(.*)\"/) {
+					$1 =~ /(.+)/ or &config_error($line, "invalid database");
+					$vsrv{database} = $1;
+				} elsif ($rcmd =~ /^secret\s*=\s*\"(.*)\"/) {
+					$1 =~ /(.+)/ or &config_error($line, "invalid secret");
+					$vsrv{secret} = $1;
+				} elsif ($rcmd =~ /^load\s*=\s*\"(.*)\"/) {
+					$1 =~ /(\w+)/ or &config_error($line, "invalid string for load testing");
+					$vsrv{load} = $1;
+				} elsif ($rcmd =~ /^scheduler\s*=\s*(.*)/) {
+					# Intentionally ommit checking the
+					# scheduler against a list of know
+					# schedulers. This is because from
+					# time to time new schedulers are
+					# added. But ldirectord is
+					# maintained distributed
+					# independently of this. Thus
+					# ldirectord needs to be manually
+					# updated/upgraded.  So just accept
+					# any scheduler that matches
+					# [a-z]+. I.e. is syntactically
+					# correct (all schedulers so far
+					# match that pattern). Ipvsadm will
+					# report an error is a scheduler
+					# isn't available / doesn't exist.
+					$1 =~ /([a-z]+)/
+					    or &config_error($line, "invalid scheduler, should be only lowercase letters (a-z)");
+					$vsrv{scheduler} = $1;
+				} elsif ($rcmd =~ /^persistent\s*=\s*(.*)/) {
+					$1 =~ /(\d+)/ or &config_error($line, "invalid persistent timeout");
+					$vsrv{persistent} = $1;
+				} elsif ($rcmd =~ /^netmask\s*=\s*(.*)/) {
+					my $val = $1;
+					if ($vsrv{addressfamily} == AF_INET6) {
+						if ($val !~ /^\d+$/ or ($val < 1 || $val > 128)) {
+							&config_error($line, "invalid netmask: a prefix length between 1 and 128 is required");
+						}
+					} else {
+						if ($val !~ /^\d+\.\d+\.\d+\.\d+$/) {
+							&config_error($line, "invalid netmask: dotted quad notation is required");
+						}
+					}
+					$vsrv{netmask} = $val;
+				} elsif ($rcmd =~ /^protocol\s*=\s*(.*)/) {
+					if ( $1 =~ /(\w+)/ ) {
+						if ( $vsrv{protocol} eq "fwm" ) {
+							if ($1 eq "fwm" ) {
+								; #Do nothing, it is already set
+							} else {
+								&config_error($line, "protocol must be fwm if the virtual service is a fwmark (a number)");
+							}
+						} else {    # tcp or udp
+							if ($1 eq "tcp" || $1 eq "udp") {
+								$vsrv{protocol} = $1;
+							} else {
+								&config_error($line, "protocol must be tcp or udp if the virtual service is an address and port");
+							}
+						}
+					} else {
+						&config_error($line, "invalid protocol");
+					}
+				} elsif ($rcmd =~ /^service\s*=\s*(.*)/) {
+					$1 =~ /(\w+)/ && ($1 eq "dns"	||
+							  $1 eq "ftp"	||
+							  $1 eq "http"	||
+							  $1 eq "https"	||
+							  $1 eq "http_proxy"	||
+							  $1 eq "imap"	||
+							  $1 eq "imaps"	||
+							  $1 eq "ldap"	||
+							  $1 eq "nntp"	||
+							  $1 eq "mysql"	||
+							  $1 eq "none"	||
+							  $1 eq "oracle"||
+							  $1 eq "pop"	||
+							  $1 eq "pops"	||
+							  $1 eq "radius"||
+							  $1 eq "pgsql"	||
+							  $1 eq "sip"	||
+							  $1 eq "smtp"	||
+							  $1 eq "submission"	||
+							  $1 eq "simpletcp")
+					    or &config_error($line,
+							     "service must " .
+							     "be dns, ftp, " .
+							     "http, https, " .
+							     "http_proxy, " .
+							     "imap, imaps, " .
+							     "ldap, nntp, "  .
+							     "mysql, none, " .
+							     "oracle, "      .
+							     "pop, pops, "   .
+							     "radius, "      .
+							     "pgsql, "       .
+							     "simpletcp, "   .
+							     "sip, smtp "    .
+							     "or submission");
+					$vsrv{service} = $1;
+					if($vsrv{service} eq "ftp" and
+							$vsrv{login} eq "") {
+						$vsrv{login} = "anonymous";
+					}
+					elsif($vsrv{service} eq "sip" and
+							$vsrv{login} eq "") {
+						$vsrv{login} = "ldirectord\@$HOSTNAME";
+					}
+					if($vsrv{service} eq "ftp" and
+							$vsrv{passwd} eq "") {
+						$vsrv{passwd} = "ldirectord\@$HOSTNAME";
+					}
+				} elsif ($rcmd =~ /^httpmethod\s*=\s*(.*)/) {
+					$1 =~ /(\w+)/ && (uc($1) eq "GET" || uc($1) eq "HEAD")
+					    or &config_error($line, "httpmethod must be GET or HEAD");
+					$vsrv{httpmethod} = uc($1);
+				} elsif ($rcmd =~ /^virtualhost\s*=\s*(.*)/) {
+					$1 =~ /\"?([^\"]*)\"?/ or
+					&config_error($line, "invalid virtualhost");
+					$vsrv{virtualhost} = $1;
+				} elsif ($rcmd =~ /^(fallback(6)?)\s*=\s*(.*)/) {    # Allow specification of a virtual-specific fallback host
+					if ($af == AF_INET  &&   defined($2) ||
+					    $af == AF_INET6 && ! defined($2)) {
+					    &config_error($line, join("", ("cannot specify \"$1\" here.  please use \"fallback", ($af == AF_INET) ?  "" : "6", "\" instead")));
+					}
+					$fallback_line=$line;
+					$vsrv{fallback} =
+						parse_fallback($line, $3,
+							       \%vsrv);
+				} elsif ($rcmd =~
+				/^fallbackcommand\s*=\s*\"(.*)\"/ or $rcmd =~ /^fallbackcommand\s*=\s*(.*)/) {
+					$1 =~ /(.+)/ or &config_error($line, "invalid fallback command");
+					$vsrv{fallbackcommand} = $1;
+				} elsif ($rcmd =~ /^quiescent\s*=\s*(.*)/) {
+					($1 eq "yes" || $1 eq "no")
+						or &config_error($line, "quiescent must be 'yes' or 'no'");
+					$vsrv{quiescent} = $1;
+				} elsif  ($rcmd =~ /^emailalert\s*=\s*(.*)/) {
+					$vsrv{emailalert} =
+						read_emailalert($line, $1);
+				} elsif  ($rcmd =~ /^emailalertfreq\s*=\s*(\d*)/) {
+					$1 =~ /(\d+)/ or &config_error($line, "invalid email alert frequency");
+					$vsrv{emailalertfreq} = $1;
+				} elsif  ($rcmd =~ /^emailalertstatus\s*=\s*(.*)/) {
+					$vsrv{emailalertstatus} = &parse_emailalertstatus($line, $1);
+				} elsif  ($rcmd =~ /^monitorfile\s*=\s*\"(.*)\"/ or
+					  $rcmd =~ /^monitorfile\s*=\s*(.*)/) {
+					my $monitorfile = $1;
+					unless (open(MONITORFILE, ">>$monitorfile") and close(MONITORFILE)) {
+						&config_error($line, "unable to open monitorfile $monitorfile: $!");
+					}
+					$vsrv{monitorfile} = $monitorfile;
+				} elsif  ($rcmd =~ /^cleanstop\s*=\s*(.*)/) {
+					($1 eq "yes" || $1 eq "no")
+						or &config_error($line, "cleanstop must be 'yes' or 'no'");
+					$vsrv{cleanstop} = $1;
+				} elsif  ($rcmd =~ /^smtp\s*=\s*(.*)/) {
+					$1 =~ /(^([0-9A-Za-z._+-]+))/ or &config_error($line, "invalid SMTP server address");
+					$vsrv{smtp} = $1;
+				} else {
+					&config_error($line, "Unknown command \"$linedata\"");
+				}
+				undef $linedata;
+			}
+			# As the protocol needs to be known to call
+			# getservbyname() all resolution must be
+			# delayed until the protocol is finalised.
+			# That is after the entire configuration
+			# for a virtual service has been parsed.
+
+			&_ld_read_config_fallback_resolve($fallback_line,
+				$vsrv{protocol}, $vsrv{fallback}, $af);
+			&_ld_read_config_virtual_resolve($virtual_line, \%vsrv,
+				$ip_port, $af);
+			&_ld_read_config_real_resolve(\%vsrv, \@rsrv_todo, $af);
+
+			# Check for duplicate now we have all the
+			# information to generate the id
+			$virtual_id = get_virtual_id_str(\%vsrv);
+			if (defined $virtual_seen{$virtual_id}) {
+				&config_error($line,
+					"duplicate virtual server");
+			}
+			$virtual_seen{$virtual_id} = 1;
+
+			unless(defined($linedata)) {
+				last;
+			}
+			#Arggh a goto :(
+			goto outer_loop;
+		}
+		next if ($linedata =~ /^\s*$/ || $linedata =~ /^\s*#/);
+		if ($linedata  =~ /^checktimeout\s*=\s*(.*)/) {
+			($1 =~ /(\d+)/ && $1 && $1>0) or &config_error($line,
+					"invalid check timeout value");
+			$CHECKTIMEOUT = $1;
+		} elsif ($linedata  =~ /^connecttimeout\s*=\s*(.*)/) {
+			&config_error($line,
+					"connecttimeout directive " .
+					"deprecated in favour of " .
+					"negotiatetimeout");
+		} elsif ($linedata  =~ /^negotiatetimeout\s*=\s*(.*)/) {
+			($1 =~ /(\d+)/ && $1 && $1>0) or &config_error($line,
+					"invalid negotiate timeout value");
+			$NEGOTIATETIMEOUT = $1;
+		} elsif ($linedata  =~ /^checkinterval\s*=\s*(.*)/) {
+			$1 =~ /(\d+)/ && $1 or &config_error($line,
+					"invalid check interval value");
+			$CHECKINTERVAL = $1;
+		} elsif ($linedata  =~ /^checkcount\s*=\s*(.*)/) {
+			$1 =~ /(\d+)/ && $1 or &config_error($line,
+					"invalid check count value");
+			$CHECKCOUNT = $1;
+			&config_warn($line, "checkcount option is deprecated and slated for removal.  please see 'failurecount'");
+		} elsif ($linedata  =~ /^failurecount\s*=\s*(.*)/) {
+			$1 =~ /(\d+)/ && $1 or &config_error($line,
+					"invalid failure count value");
+			$FAILURECOUNT = $1;
+		} elsif ($linedata  =~ /^fallback(6)?\s*=\s*(.*)/) {
+			my $af = defined($1) ? AF_INET6 : AF_INET;
+			my $tcp = parse_fallback($line, $2, undef);
+			my $udp = parse_fallback($line, $2, undef);
+			&_ld_read_config_fallback_resolve($line, "tcp", $tcp, $af);
+			&_ld_read_config_fallback_resolve($line, "udp", $udp, $af);
+			if ($af == AF_INET) {
+				$FALLBACK = { "tcp" => $tcp, "udp" => $udp };
+			} else {
+				$FALLBACK6 = { "tcp" => $tcp, "udp" => $udp };
+			}
+		} elsif ($linedata =~ /^fallbackcommand\s*=\s*(.*)/) {
+			$1 =~ /(.+)/ or &config_error($line, "invalid fallback command");
+			$FALLBACKCOMMAND = $1;
+		} elsif ($linedata  =~ /^autoreload\s*=\s*(.*)/) {
+			($1 eq "yes" || $1 eq "no")
+			    or &config_error($line,
+					"autoreload must be 'yes' or 'no'");
+			$AUTOCHECK = $1;
+		} elsif ($linedata  =~ /^callback\s*=\s*\"(.*)\"/) {
+			$CALLBACK = $1;
+		} elsif ($linedata  =~ /^logfile\s*=\s*\"(.*)\"/) {
+			my $tmpLDIRLOG = $LDIRLOG;
+			$LDIRLOG = $1;
+			if (&ld_openlog()) {
+				$LDIRLOG = $tmpLDIRLOG;
+				&config_error($line,
+						"unable to open logfile: $1");
+			}
+		} elsif ($linedata  =~ /^execute\s*=\s*(.*)/) {
+			$LD_INSTANCE{$1} = 1;
+		} elsif ($linedata  =~ /^fork\s*=\s*(.*)/) {
+			($1 eq "yes" || $1 eq "no")
+			    or &config_error($line, "fork must be 'yes' or 'no'");
+			$FORKING = $1;
+		} elsif ($linedata  =~ /^supervised/) {
+			if (($linedata  =~ /^supervised\s*=\s*(.*)/) and
+			    ($1 eq "yes" || $1 eq "no")) {
+				$SUPERVISED = $1;
+			}
+			elsif ($linedata  =~ /^supervised\s*$/) {
+				$SUPERVISED = "yes";
+				&config_warn($line,
+					"please update your config not to " .
+					"use a bare supervised directive");
+			}
+			else {
+				&config_error($line,
+					"supervised must be 'yes' or 'no'");
+			}
+		} elsif ($linedata  =~ /^quiescent\s*=\s*(.*)/) {
+			($1 eq "yes" || $1 eq "no")
+			    or &config_error($line,
+					"quiescent must be 'yes' or 'no'");
+			$QUIESCENT = $1;
+		} elsif ($linedata  =~ /^readdquiescent\s*=\s*(.*)/) {
+			($1 eq "yes" || $1 eq "no")
+			    or &config_error($line,
+					"readdquiescent must be 'yes' or 'no'");
+			$READDQUIESCENT = $1;
+		} elsif  ($linedata  =~ /^emailalert\s*=\s*(.*)/) {
+			$EMAILALERT = read_emailalert($line, $1);
+		} elsif  ($linedata  =~ /^emailalertfreq\s*=\s*(\d*)/) {
+			$1 =~ /(\d+)/ or &config_error($line,
+					"invalid email alert frequency");
+			$EMAILALERTFREQ = $1;
+		} elsif  ($linedata  =~ /^emailalertstatus\s*=\s*(.*)/) {
+			$EMAILALERTSTATUS = &parse_emailalertstatus($line, $1);
+		} elsif  ($linedata  =~ /^emailalertfrom\s*=\s*(.*)/) {
+			$1 =~ /(.+)/ or &config_error($line,
+					"no email from address specified");
+			$EMAILALERTFROM = $1;
+		} elsif  ($linedata  =~ /^cleanstop\s*=\s*(.*)/) {
+			($1 eq "yes" || $1 eq "no")
+			    or &config_error($line, "cleanstop must be 'yes' or 'no'");
+			$CLEANSTOP = $1;
+		} elsif  ($linedata  =~ /^smtp\s*=\s*(.*)/) {
+			$1 =~ /(^([0-9A-Za-z._+-]+))/ or &config_error($line,
+					"invalid SMTP server address");
+			$SMTP = $1;
+		} elsif  ($linedata  =~ /^maintenancedir\s*=\s*(.*)/) {
+			$1 =~ /(.+)/ or &config_error($line,
+					"maintenance directory not specified");
+			$MAINTDIR = $1;
+			-d $MAINTDIR or &config_warn($line,
+					"maintenance directory does not exist");
+		} else {
+			if ($linedata  =~ /^timeout\s*=\s*(.*)/) {
+				&config_error($line,
+						"timeout directive " .
+						"deprecated in favour of " .
+						"checktimeout and " .
+						"negotiatetimeout");
+			}
+			&config_error($line, "Unknown command $linedata ");
+		}
+	}
+	close(CFGFILE);
+
+	# Check for sensible use of checkinterval, warn if it is used in a virtual
+	# service when fork=no
+	if ($FORKING eq 'no') {
+		foreach my $v (@VIRTUAL) {
+			if (defined($$v{checkinterval})) {
+				config_warn(-1, "checkinterval in virtual service ".
+					get_virtual_id_str($v)." ignored when fork=no");
+			}
+		}
+	}
+
+	return(0);
+}
+
+# _ld_read_config_virtual_resolve
+# Note: Should not need to be called directly, but won't do any damage if
+#       you do.
+# Resolve the server (ip address) and port for a virtual service
+# pre: line: Line of configuration file fallback server was read from
+#            Used for debugging messages
+#      vsrv: Virtual Service to resolve server and port of
+#      ip_port: server and port in the form
+#               ip_address|hostname:port|service
+#      af: Address family: AF_INET or AF_INET6
+# post: Take ip_port, resolve it as per ld_gethostservbyname
+#       and set $vsrv->{server} and $vsrv->{port} accordingly.
+#       If $vsrv->{service} is not set, then set according to the value of
+#       $vsrv->{port}
+# return: none
+#        Debugging message will be reported and programme will exit
+#        on error.
+sub _ld_read_config_virtual_resolve
+{
+	my($line, $vsrv, $ip_port, $af)=(@_);
+
+	if($ip_port){
+		$ip_port=&ld_gethostservbyname($ip_port, $vsrv->{protocol}, $af);
+		if ($ip_port =~ /(\[[0-9A-Fa-f:]+\]):(\d+)/) {
+			$vsrv->{server} = $1;
+			$vsrv->{port} = $2;
+		} elsif($ip_port){
+			($vsrv->{server}, $vsrv->{port}) = split /:/, $ip_port;
+		}
+		else {
+			&config_error($line,
+				"invalid address for virtual service");
+		}
+
+		if(!defined($vsrv->{service})){
+			$vsrv->{service} = ld_port_to_service($vsrv->{port});
+		}
+	}
+}
+
+# ld_service_to_port
+# Resolve an ldirectord service name from its port number
+# pre: port: port number of the service
+# return: port name
+#         "none" if the service is unknown
+sub ld_port_to_service
+{
+	my ($port) = (@_);
+
+	if ($port eq 21)	{ return "ftp"; }
+	if ($port eq 25)	{ return "smtp"; }
+	if ($port eq 53)	{ return "dns"; }
+	if ($port eq 80)	{ return "http"; }
+	if ($port eq 110)	{ return "pop"; }
+	if ($port eq 119)	{ return "nntp"; }
+	if ($port eq 143)	{ return "imap"; }
+	if ($port eq 389)	{ return "ldap"; }
+	if ($port eq 443)	{ return "https"; }
+	if ($port eq 587)	{ return "submission"; }
+	if ($port eq 995)	{ return "pops"; }
+	if ($port eq 993)	{ return "imaps"; }
+	if ($port eq 1521)	{ return "oracle"; }
+	if ($port eq 1812)	{ return "radius"; }
+	if ($port eq 3128)	{ return "http_proxy"; }
+	if ($port eq 3306)	{ return "mysql"; }
+	if ($port eq 5060)	{ return "sip"; }
+	if ($port eq 5432)	{ return "pgsql"; }
+
+	return "none";
+}
+
+# ld_service_to_port
+# Resolve the port number from an ldirectord service name
+# pre: service: name of the service
+# return: port number
+#         undef if the service is unknown
+sub ld_service_to_port
+{
+	my ($service) = (@_);
+
+	if ($service eq "ftp")		{ return 21; }
+	if ($service eq "smtp")		{ return 25; }
+	if ($service eq "dns")		{ return 53; }
+	if ($service eq "http")		{ return 80; }
+	if ($service eq "pop")		{ return 110; }
+	if ($service eq "nntp")		{ return 119; }
+	if ($service eq "imap")		{ return 143; }
+	if ($service eq "ldap")		{ return 389; }
+	if ($service eq "https")	{ return 443; }
+	if ($service eq "submission")	{ return 587; }
+	if ($service eq "imaps")	{ return 993; }
+	if ($service eq "pops")		{ return 995; }
+	if ($service eq "oracle")	{ return 1521; }
+	if ($service eq "radius")	{ return 1812; }
+	if ($service eq "http_proxy")	{ return 3128; }
+	if ($service eq "mysql")	{ return 3306; }
+	if ($service eq "sip")		{ return 5060; }
+	if ($service eq "pgsql")	{ return 5432; }
+
+	return undef;
+}
+
+# ld_checkport
+# Resolve the port to connect to for service checks
+# Note: Should only be used inside service checks,
+#       as its not the same as the port of the real server
+# pre: v: virtual service
+#      r: real server
+# return: port number
+#         undef if the service is unknown
+sub ld_checkport
+{
+	my ($v, $r) = (@_);
+
+	if (defined $v->{checkport}) {
+		return $v->{checkport};
+	}
+	if ($r->{port} > 0) {
+		return $r->{port};
+	}
+
+	return ld_service_to_port($v->{service});
+}
+
+# _ld_read_config_fallback_resolve
+# Note: Should not need to be called directly, but won't do any damage if
+#       you do.
+# Resolve the fallback server for a virtual service
+# pre: line: Line of configuration file fallback server was read from
+#            Used for debugging messages
+#      vsrv: Virtual Service to resolve fallback server of
+#      af: Address family: AF_INET or AF_INET6
+# post: Take $vsrv->{fallback}, resolve it as per ld_gethostservbyname
+#       and set $vsrv->{fallback} to the result
+# return: none
+#	Debugging message will be reported and programme will exit
+#	on error.
+sub _ld_read_config_fallback_resolve
+{
+	my($line, $protocol, $fallback, $af)=(@_);
+
+	my ($ipversion, $ipaddress);
+
+	unless($fallback) {
+		return;
+	}
+	if ($af == AF_INET) {
+	 	$ipversion = "IPv4";
+	}
+	elsif ($af == AF_INET6) {
+	 	$ipversion = "IPv6";
+	}
+	else {
+	 	$ipversion = "IP??($af)";
+	}
+	unless ($ipaddress = &ld_gethostbyname($fallback->{server}, $af)) {
+		&config_error($line, "invalid $ipversion address or could not resolve for fallback server: " .
+			      $fallback->{server});
+	}
+	$fallback->{server} = $ipaddress;
+
+	unless($fallback->{"port"}) {
+		return;
+	}
+
+	$fallback->{port} = &ld_getservbyname($fallback->{port}, $protocol) or
+		&config_error($line, "invalid port for fallback server");
+}
+
+# _ld_read_config_real_resolve
+# Note: Should not need to be called directly, but won't do any damage if
+#       you do.
+# Run through the list of real servers read in the configuration file for a
+# virtual server and parse these entries
+# pre: vsrv: Virtual Service to parse real servers for
+#      rsrv_todo: List of real servers read from config but not parsed.
+#                 List is a list of list reference. The first element in
+#                 each list reference is the line read from the
+#                 configuration after "real=". The second element is the
+#                 line number, used for error reporting
+#      af: Address family: AF_INET or AF_INET6
+# post: Run through rsrv_todo and parse real servers
+# return: none
+#	Debugging message will be reported and programme will exit
+#	on error.
+sub _ld_read_config_real_resolve
+{
+	my ($vsrv, $rsrv_todo, $af)=(@_);
+
+	my $i;
+	my $str;
+	my $line;
+	my $ip1;
+	my $ip2;
+	my $port;
+	my $resolved_ip1;
+	my $resolved_ip2;
+	my $resolved_port;
+	my $flags;
+
+	for $i (@$rsrv_todo) {
+		($str, $line)=@$i;
+		$str =~	 /(\d+\.\d+\.\d+\.\d+|[A-Za-z0-9.-]+|\[[0-9A-fa-f:]+\])(->(\d+\.\d+\.\d+\.\d+|[A-Za-z0-9.-]+|\[[0-9A-fa-f:]+\]))?(:(\d+|[A-Za-z0-9-_]+))?\s+(.*)/
+			or &config_error($line,
+				"invalid address for real server" .
+				" (wrong format)");
+		$ip1=$1;
+		$ip2=$3;
+		if(defined($5)){
+			$port=$5;
+		}
+		else {
+			$port="0";
+		}
+		$flags=$6;
+		$resolved_ip1=&ld_gethostbyname($ip1, $af);
+		unless( defined($resolved_ip1) ) {
+			&config_error($line,
+				"invalid address ($ip1) for real server" .
+				" (could not resolve host)");
+		}
+		if( defined($port) ){
+			$resolved_port=&ld_getservbyname($port,"");
+			unless( defined($resolved_port) ){
+				&config_error($line,
+					"invalid port ($port) for real server" .
+					" (could not resolve port)");
+			}
+		}
+		if ( defined ($ip2) ) {
+			$resolved_ip2=&ld_gethostbyname($ip2, $af);
+			unless( defined ($resolved_ip2) ) {
+				&config_error($line,
+					"invalid address ($ip2) for " .
+					"real server" .
+					" (could not resolve end host)");
+			}
+			&add_real_server_range($line, $vsrv, $resolved_ip1,
+				$resolved_ip2, $resolved_port, $flags, $af);
+		} else {
+			&add_real_server($line, $vsrv, $resolved_ip1,
+				$resolved_port, $flags);
+		}
+	}
+}
+
+# add_real_server_range
+# Add a real server for each IP address in a range
+# pre: line: line number real server was read from
+#            Used for debugging information
+#      vsrv: virtual server to add real server to
+#      first: First IP address in range
+#      last: First IP address in range
+#      port: Port of real servers
+#      flags: Flags for real servers. Should be of the form
+#             gate|masq|ipip [<weight>] [">I<request>", "<receive>"]
+#      af: Address family: AF_INET or AF_INET6
+# post: real servers are added to virtual server
+# return: none
+#         Debugging message will be reported and programme will exit
+#         on error.
+sub add_real_server_range
+{
+	my ($line, $vsrv, $first, $last, $port, $flags, $af) = (@_);
+
+	my (@tmp, $first_i, $last_i, $i, $rsrv);
+
+	if ($af == AF_INET) {
+		if ( ($first_i=&ip_to_int($first)) <0 ) {
+			&config_error($line, "Invalid IP address: $first");
+		}
+		if ( ($last_i=&ip_to_int($last)) <0 ) {
+			&config_error($line, "Invalid IP address: $last");
+		}
+
+		if ($first_i>$last_i) {
+			&config_error($line,
+				"Invalid Range: $first-$last: First value must be " .
+				"greater than or equal to the second value");
+		}
+
+		# A for loop didn't seem to want to work
+		$i=$first_i;
+		while ( $i le $last_i ) {
+			&add_real_server($line, $vsrv, &int_to_ip($i), $port, $flags);
+			$i++;
+		}
+	}
+	elsif ($af == AF_INET6) {
+		# not supported yet
+		&config_error($line, "Address range for IPv6 is not supported yet");
+	}
+	else {
+		die "address family must be AF_INET or AF_INET6\n";
+	}
+}
+
+# add_real_server
+# Add a real server to a virtual
+# pre: line: line number real server was read from
+#            Used for debugging information
+#      vsrv: virtual server to add real server to
+#      ip: IP address of real server
+#      port: Port of real server
+#      flags: Flags for real server. Should be of the form
+#             gate|masq|ipip [<weight>] [">I<request>", "<receive>"]
+# post: real server is added to virtual server
+# return: none
+#         Debugging message will be reported and programme will exit
+#         on error.
+sub add_real_server
+{
+	my ($line, $vsrv, $ip, $port, $flags) = (@_);
+
+	my $ref;
+	my $realsrv=0;
+	my $new_rsrv;
+	my $rsrv;
+
+	$new_rsrv = {"server"=>$ip, "port"=>$port};
+
+	$flags =~ /(\w+)(.*)/ && ($1 eq "gate" || $1 eq "masq" || $1 eq "ipip")
+		or &config_error($line,	"forward method must be gate, masq or ipip");
+
+	$new_rsrv->{"forward"} =$1;
+	$flags = $2;
+
+	$rsrv=$vsrv->{"real"};
+
+	if(defined($flags) and $flags =~ /\s+(\d+)(.*)/) {
+		$new_rsrv->{"weight"} = $1;
+		$flags = $2;
+	}
+	else {
+		$new_rsrv->{"weight"} = 1;
+	}
+
+	if(defined($flags) and $flags =~ /\s+\"(.*)\"[, ]\s*\"(.*)\"(.*)/) {
+		$new_rsrv->{"request"} = $1;
+		unless ($new_rsrv->{request}=~/^\//) {
+			$new_rsrv->{request} = "/" . $new_rsrv->{request};
+		}
+		$new_rsrv->{"receive"} = $2;
+		$flags = $3;
+	}
+
+	if (defined($flags) and $flags =~/\S/) {
+		&config_error($line, "Invalid real server line, around "
+			. "\"$flags\"");
+	}
+
+	push(@$rsrv, $new_rsrv);
+
+	my $real    = get_real_id_str($new_rsrv, $vsrv);
+	my $virtual = get_virtual_id_str($vsrv);
+	for my $r (@REAL){
+		if($r->{"real"} eq $real){
+			my $ref=$r->{"virtual"};
+			push(@$ref, $virtual);
+			$realsrv=1;
+			last;
+		}
+	}
+	if($realsrv==0){
+		push(@REAL, { "real"=>$real, "virtual"=>[ $virtual ] });
+	}
+}
+
+# parse_fallback
+# Parse a fallback server
+# pre: line: line number real server was read from
+#      fallback: line read from configuration file
+#                Should be of the form
+#                ip_address|hostname[:port|:service_name] [gate|masq|ipip]
+# post: fallback is parsed
+# return: Reference to hash of the form
+#         { server => blah, forward => blah }
+#         Debugging message will be reported and programme will exit
+#         on error.
+sub parse_fallback
+{
+	my ($line, $fallback, $vsrv) = (@_);
+
+	my $parse_line;
+	my $server;
+	my $port;
+	my $fwd;
+
+	$parse_line = $fallback;
+	if ($parse_line =~ /(\S+)(\s+(\S+))?\s*$/) {
+		# get "ip:port" and a forwarding method
+		$fwd = $3;
+		$parse_line = $1;
+	}
+	if ($parse_line =~ /(:(\d+|[A-Za-z0-9-_]+))?$/) {
+		# get host and port
+		$port=$2;
+		
+		$parse_line =~ s/(:(\d+|[A-Za-z0-9-_]+))?$//;
+		$server = $parse_line;
+	}
+	unless(defined($server)) {
+		&config_error($line, "invalid fallback server: $fallback");
+	}
+
+	if (not defined($port) and defined($vsrv)) {
+		$port = $vsrv->{"port"};
+	}
+
+	if($fwd) {
+		($fwd eq "gate" || $fwd eq "masq" || $fwd eq "ipip")
+		or &config_error($line,
+			"forward method must be gate, masq or ipip");
+	}
+	else {
+		$fwd="gate"
+	}
+
+	return({"server"=>$server, "port"=>$port, "forward"=>$fwd,
+		"weight"=>1});
+}
+
+sub __config_log
+{
+	my ($line, $prefix, $msg) = @_;
+
+	chomp($msg);
+	$msg .= "\n";
+
+	my $msg_prefix = "$prefix [$$]";
+	if ($line > 0) {
+		$msg_prefix .= " reading file $CONFIG at line $line";
+	}
+	$msg = "$msg_prefix: $msg";
+
+	if ($opt_d or $DAEMON_STATUS == $DAEMON_STATUS_STARTING) {
+		print STDERR $msg;
+	}
+	else {
+		&ld_log("$msg");
+	}
+}
+
+sub config_warn
+{
+	my ($line, $msg) = @_;
+
+	__config_log($line, "Warning", $msg);
+}
+
+sub config_error
+{
+	my ($line, $msg) = @_;
+
+	__config_log($line, "Error", $msg);
+	if ($DAEMON_STATUS == $DAEMON_STATUS_STARTING) {
+		&ld_rm_file("$RUNPID.$CFGNAME.pid");
+		&ld_exit(2, "config_error: Configuration Error");
+	} else {
+		die;
+	}
+}
+
+sub ld_setup
+{
+	for my $v (@VIRTUAL) {
+		if ($$v{protocol} eq "tcp") {
+			$$v{proto} = "-t";
+		} elsif ($$v{protocol} eq "udp") {
+			$$v{proto} = "-u";
+		} elsif ($$v{protocol} eq "fwm") {
+			$$v{proto} = "-f";
+		}
+		$$v{flags} = "$$v{proto} " .  &get_virtual_option($v) . " ";
+		$$v{flags} .= "-s $$v{scheduler} " if defined ($$v{scheduler});
+		if (defined $$v{persistent}) {
+			$$v{flags} .= "-p $$v{persistent} ";
+			$$v{flags} .= "-M $$v{netmask} " if defined ($$v{netmask});
+		}
+		my $real = $$v{real};
+		for my $r (@$real) {
+			$$r{forw} = get_forward_flag($$r{forward});
+			my $port=ld_checkport($v, $r);
+
+			my $schema = $$v{service};
+			if ($$v{service} eq 'http_proxy') {
+				$schema = 'http';
+			}
+
+			if (defined $$r{request} && defined $$r{receive}) {
+				my $uri = $$r{request};
+				$uri =~ s/^\///g;
+				if ($$r{request} =~ /$schema:\/\//) {
+					$$r{url} = "$uri";
+				} else {
+					$$r{url} = "$schema:\/\/$$r{server}:$port\/$uri";
+				}
+			} else {
+				my $uri = $$v{request};
+				$uri =~ s/^\///g;
+
+				if ($$v{service} eq 'http_proxy') {
+					$$r{url} = "$uri";
+				} else {
+					$$r{url} = "$schema:\/\/$$r{server}:$port\/$uri";
+				}
+
+				$$r{request} = $$v{request} unless defined $$r{request};
+				$$r{receive} = $$v{receive};
+			}
+			if ($$v{checktype} eq "combined") {
+				$$r{num_connects} = 999999;
+			} else {
+				$$r{num_connects} = -1;
+			}
+		}
+
+		# checktimeout and negotiate timeout are
+		# mutual defaults for each other, so calculate
+		# checktimeout in a temporary variable so as not
+		# to affect the calculation of negotiatetimeout.
+
+		my $checktimeout = $$v{checktimeout};
+		if ($checktimeout < 0) {
+			$checktimeout = $$v{negotiatetimeout};
+		}
+		if ($checktimeout < 0) {
+			$checktimeout = $CHECKTIMEOUT;
+		}
+		if ($checktimeout < 0) {
+			$checktimeout = $NEGOTIATETIMEOUT;
+		}
+		if ($checktimeout < 0) {
+			$checktimeout = $DEFAULT_CHECKTIMEOUT;
+		}
+
+		if ($$v{negotiatetimeout} < 0) {
+			$$v{negotiatetimeout} = $$v{checktimeout};
+		}
+		if ($$v{negotiatetimeout} < 0) {
+			$$v{negotiatetimeout} = $NEGOTIATETIMEOUT;
+		}
+		if ($$v{negotiatetimeout} < 0) {
+			$$v{negotiatetimeout} = $CHECKTIMEOUT;
+		}
+		if ($$v{negotiatetimeout} < 0) {
+			$$v{negotiatetimeout} = $DEFAULT_NEGOTIATETIMEOUT;
+		}
+
+		$$v{checktimeout} = $checktimeout;
+
+		if ($$v{checkcount} < 0) {
+			$$v{checkcount} = $CHECKCOUNT;
+		}
+
+		if ($$v{failurecount} < 0) {
+			$$v{failurecount} = $FAILURECOUNT;
+		}
+	}
+}
+
+# ld_read_ipvsadm
+#
+# Net::FTP seems to set the input record separator ($\) to null
+# putting IO into slurp (whole file at a time, rather than line at a time)
+# mode. Net::FTP does this using local $\, which should mean
+# that the change doesn' effect code here, but it does. It also
+# seems to be impossible to turn it off, by say setting $\ back to '\n'
+# Perhaps there is more to this than meets the eye. Perhaps it's a perl bug.
+# In any case, this should fix the problem.
+#
+# This should not affect pid or config file parsing as they are called
+# before Net::FTP and as this appears to be a bit of a work around,
+# I'd rather use it in as few places as possible
+#
+# Observed with perl v5.8.8 (Debian's perl 5.8.8-6)
+# -- Horms, 17th July 2005
+sub ld_readline
+{
+	my ($fd, $buf) = (@_);
+	my $line;
+
+	# Uncomment the following line to turn off this work around
+	# return readline($fd);
+
+	$line = shift @$buf;
+	if (defined $line) {
+		return $line . "\n";
+	}
+
+	push @$buf, split /\n/, readline($fd);
+
+	$line = shift @$buf;
+	if (defined $line) {
+		return $line . "\n";
+	}
+
+	return undef;
+}
+
+# ld_read_ipvsadm
+# Parses the output of "ipvsadm -L -n" and puts into a structure of
+# the following from:
+#
+# {
+#   (vip_address:vport|fwmark) protocol => {
+#     "scheduler" => scheduler,
+#     "persistent" => timeout,     # May be omitted
+#     "netmask" => netmask,        # May be omitted
+#     "real" => {
+#       rip_address:rport => {
+#         "forward" => forwarding_mechanism,
+#         "weight"  => weight
+#       },
+#       ...
+#     }
+#   },
+#   ...
+# }
+#
+# where:
+#   vip_address: IP address of virtual service
+#   vport: Port of virtual service
+#   fwmark: Firewall Mark of virtual service
+#   scheduler: Scheduler for virtual service
+#   timeout: Timeout for persistency. Omitted if service is not persistent.
+#   nemask: Netmask for persistency. Omitted if service is not persistent.
+#
+#   rip_address: IP address of real server
+#   rport: Port of real server
+#   forwarding_mechanism: Forwarding mechanism for real server.
+#                         One of: gate, ipip, masq.
+#   weight: Weight of real server
+#
+# pre: none
+# post: ipvsadm -L -n is parsed
+# result: reference to sructure detailed above.
+sub ld_read_ipvsadm
+{
+	my %oldsrv;
+	my $real_service;
+	my $fwd;
+	my $buf = [];
+	my $fh;
+	my $line;
+
+	# read status of current ipvsadm -L -n
+	unless(open($fh, "$IPVSADM -L -n 2>&1|")){
+		&ld_exit(1, "Could not run $IPVSADM -L -n: $!");
+	}
+
+	# Skip the first three lines
+	$line = ld_readline($fh, $buf);
+	$line = ld_readline($fh, $buf);
+	$line = ld_readline($fh, $buf);
+
+	while (1) {
+		$line = ld_readline($fh, $buf);
+		if (not defined $line) {
+			last;
+		}
+		if ($line =~ /^(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\[[0-9A-Fa-f:]+\]:\d+|\d+)( IPv6)?\s+(\w+)\s+persistent\s+(\d+)\s+mask\s+(.*)/) {
+			$real_service = &gen_real_service_str($2, $1, $3);
+			$oldsrv{"$real_service"} = {"real"=>{}, "scheduler"=>$4, "persistent"=>$5, "netmask"=>$6};
+		} elsif ($line =~ /^(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\[[0-9A-Fa-f:]+\]:\d+|\d+)( IPv6)?\s+(\w+)\s+persistent\s+(\d+)/) {
+			$real_service = &gen_real_service_str($2, $1, $3);
+			$oldsrv{"$real_service"} = {"real"=>{}, "scheduler"=>$4, "persistent"=>$5};
+		} elsif ($line =~ /^(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\[[0-9A-Fa-f:]+\]:\d+|\d+)( IPv6)?\s+(\w+)/) {
+			$real_service = &gen_real_service_str($2, $1, $3);
+			$oldsrv{"$real_service"} = {"real"=>{}, "scheduler"=>$4};
+		} elsif ($line =~ /^  ->\s+(\d+\.\d+\.\d+\.\d+\:\d+|\[[0-9A-Fa-f:]+\]:\d+)\s+(\w+)\s+(\d+)/) {
+			if (not defined( $real_service)) {
+				&ld_debug(2, "Real server read from ipvsadm " .
+					  "doesn't seem to be inside a " .
+					  "virtual service: \"$line\"\n");
+				next;
+			}
+			if ($2 eq "Route") {
+				$fwd = "gate";
+			} elsif ($2 eq "Tunnel") {
+				$fwd = "ipip";
+			} elsif ($2 eq "Masq") {
+				$fwd = "masq";
+			}
+			$oldsrv{"$real_service"}->{"real"}->{"$1"} = {"forward"=>$fwd, "weight"=>$3};
+		} else {
+			&ld_debug(2, "Unknown line read from ipvsadm: " .
+				  "\"$line\"\n");
+			next;
+		}
+	}
+	close($fh);
+
+	return(\%oldsrv);
+}
+
+sub gen_real_service_str
+{
+	my ($service_address, $protocol, $v6flag) = @_;
+
+	return "$service_address ".lc($protocol).(defined($v6flag) ? "6" : "");
+}
+
+sub get_real_service_str
+{
+	my ($v) = (@_);
+
+	if ($v->{"protocol"} eq "fwm") {
+		return &get_virtual($v) . " "  . $v->{protocol} . (($v->{addressfamily} == AF_INET6) ? "6" : "");
+	}
+	else {
+		return &get_virtual($v) . " "  . $v->{protocol};
+	}
+}
+
+sub ld_start
+{
+	my $oldsrv;
+	my $real_service;
+	my $nv;
+	my $nr;
+	my $server_down = {};
+
+	# read status of current ipvsadm -L -n
+	$oldsrv=&ld_read_ipvsadm();
+
+	# make sure virtual servers are up to date
+	foreach $nv (@VIRTUAL) {
+		my $real_service = &get_real_service_str($nv);
+
+		if (exists($oldsrv->{"$real_service"})) {
+			# service exists, modify it
+			&system_wrapper("$IPVSADM -E $$nv{flags}");
+			&ld_log("Changed virtual server: " . &get_virtual($nv));
+		}
+		else {
+			# no such service, create a new one
+			&system_wrapper("$IPVSADM -A $$nv{flags}");
+			&ld_log("Added virtual server: " . &get_virtual($nv));
+		}
+	}
+
+	# make sure real servers are up to date
+	foreach $nv (@VIRTUAL) {
+		my $nreal = $nv->{real};
+		my $ov = $oldsrv->{&get_real_service_str($nv)};
+		my $or = $ov->{real};
+		my $fallback = fallback_find($nv);
+
+		if (defined($fallback)) {
+			delete($or->{"$fallback->{server}:$fallback->{port}"});
+		}
+
+		for $nr (@$nreal) {
+			my $real_str = "$nr->{server}:$nr->{port}";
+			if (! defined($or->{$real_str}) or
+					$or->{$real_str}->{weight} == 0) {
+				$server_down->{$real_str} = [$nv, $nr];
+				#service_set($nv, $nr, "down", {force => 1});
+			}
+			else {
+				if (defined $server_down->{$real_str}) {
+					delete($server_down->{$real_str});
+				}
+				service_set($nv, $nr, "up", {force => 1});
+			}
+			delete($or->{$real_str});
+		}
+
+		# remove remaining entries for real servers
+		for my $k (keys %$or) {
+			purge_untracked_service($nv, $k, "start");
+			delete($$or{$k});
+		}
+
+		delete($oldsrv->{&get_real_service_str($nv)});
+		&fallback_on($nv);
+	}
+
+	for my $k (keys (%$server_down)) {
+		my $v = $server_down->{$k};	
+		if ($READDQUIESCENT eq "no") {
+			# Ensure that the server is initially added
+			service_set(@$v[0], @$v[1], "up", {force => 1});
+		}
+		# Remove Server
+		service_set(@$v[0], @$v[1], "down", {force => 1});
+		delete($server_down->{$k});
+		#sleep 5;
+	}
+
+	# remove remaining entries for virtual servers
+	foreach $nv (@OLDVIRTUAL) {
+		if (! defined($oldsrv->{&get_real_service_str($nv)})) {
+			next;
+		}
+		purge_virtual($nv, "start");
+	}
+}
+
+sub ld_cmd_children
+{
+	my ($cmd, %children) = (@_);
+	# instantiate other ldirectord, if specified
+	my $child;
+	foreach $child (keys %children) {
+		if ($cmd eq "reload_or_start") {
+			if (&system_wrapper("$LDIRECTORD $child reload")) {
+				&system_wrapper("$LDIRECTORD $child start");
+			}
+		}
+		else {
+			&system_wrapper("$LDIRECTORD $child $cmd");
+		}
+	}
+}
+
+sub ld_stop
+{
+	# Kill children
+	if ($FORKING eq 'yes') {
+		foreach my $virtual_id (keys (%FORK_CHILDREN)) {
+			my $pid = $FORK_CHILDREN{$virtual_id};
+			ld_log("Killing child $virtual_id PID=$pid");
+			kill 15, $pid;
+		}
+	}
+	foreach my $v (@VIRTUAL) {
+		next if ( (! defined($$v{cleanstop}) and $CLEANSTOP eq 'no') or
+			(defined($$v{cleanstop}) and $$v{cleanstop} eq 'no') );
+		my $real = $$v{real};
+		foreach my $r (@$real) {
+			if (defined $$r{virtual_status}) {
+				purge_service($v, $r, "stop");
+			}
+		}
+		purge_virtual($v, "stop");
+	}
+}
+
+sub ld_main
+{
+	# Main failover checking code
+	while (1) {
+		if ($FORKING eq 'yes') {
+			foreach my $v (@VIRTUAL) {
+				my $virtual_id = get_virtual_id_str($v);
+				if (!exists($FORK_CHILDREN{$virtual_id})) {
+					&ld_log("Child not running for $virtual_id, spawning");
+					my $pid = fork;
+					if (!defined($pid)) {
+						&ld_log("fork failed");
+					} elsif ($pid == 0) {
+						run_child($v);
+					} else {
+						$FORK_CHILDREN{get_virtual_id_str($v)} = $pid;
+						&ld_log("Spawned child $virtual_id PID=$pid");
+					}
+				} elsif (waitpid($FORK_CHILDREN{get_virtual_id_str($v)}, WNOHANG)) {
+					delete $FORK_CHILDREN{get_virtual_id_str($v)};
+				}
+			}
+			check_signal();
+			if (!check_cfgfile()) {
+				sleep 1;
+			}
+
+			check_signal();
+
+		} else {
+			my @real_checked;
+			foreach my $v (@VIRTUAL) {
+				my $real = $$v{real};
+				my $virtual_id = get_virtual_id_str($v);
+
+				REAL: foreach my $r (@$real) {
+					my $real_id = get_real_id_str($r, $v);
+					check_signal();
+					foreach my $tmp_id (@real_checked) {
+						if($real_id eq $tmp_id) {
+							&ld_debug(3, "Already checked: real server=$real_id (virtual=$virtual_id)");
+							next REAL;
+						}
+					}
+					_check_real($v, $r);
+					push(@real_checked, $real_id);
+				}
+			}
+			check_signal();
+			if (!check_cfgfile()) {
+				sleep $CHECKINTERVAL;
+			}
+
+			check_signal();
+			ld_emailalert_resend();
+
+			check_signal();
+		}
+	}
+}
+
+sub run_child
+{
+	my $v = shift;
+	# Just exit on signals
+	$SIG{'INT'} = "DEFAULT";
+	$SIG{'QUIT'} = "DEFAULT";
+	$SIG{'ILL'} = "DEFAULT";
+	$SIG{'ABRT'} = "DEFAULT";
+	$SIG{'FPE'} = "DEFAULT";
+	$SIG{'SEGV'} = "DEFAULT";
+	$SIG{'TERM'} = "DEFAULT";
+
+	$SIG{'BUS'} = "DEFAULT";
+	$SIG{'SYS'} = "DEFAULT";
+	$SIG{'XCPU'} = "DEFAULT";
+	$SIG{'XFSZ'} = "DEFAULT";
+
+	$SIG{'IOT'} = "DEFAULT";
+
+	$SIG{'PIPE'} = "IGNORE";
+	$SIG{'HUP'} = sub { exit 1 };
+
+	my $real = $$v{real};
+	my $virtual_id = get_virtual_id_str($v);
+	my $checkinterval = $$v{checkinterval} || $CHECKINTERVAL;
+	$0 = "ldirectord $virtual_id";
+	while (1) {
+		foreach my $r (@$real) {
+			$0 = "ldirectord $virtual_id checking $$r{server}";
+			_check_real($v, $r);
+		}
+		$0 = "ldirectord $virtual_id";
+		sleep $checkinterval;
+		ld_emailalert_resend();
+	}
+}
+
+sub _check_real
+{
+	my $v = shift;
+	my $r = shift;
+
+
+	my $real_id = get_real_id_str($r, $v);
+	my $virtual_id = get_virtual_id_str($v);
+
+	if (_check_real_for_maintenance($r)) {
+		service_set($v, $r, "down", {do_log => 1, force => 1}, "Server in maintenance");
+		return;
+	} elsif ($$v{checktype} eq "negotiate" || $$r{num_connects}>=$$v{num_connects}) {
+		&ld_debug(2, "Checking negotiate: real server=$real_id (virtual=$virtual_id)");
+		if (grep $$v{service} eq $_, ("http", "https", "http_proxy")) {
+			$$r{num_connects} = 0 if (check_http($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "pop") {
+			$$r{num_connects} = 0 if (check_pop($v, $r, 0) == $SERVICE_UP);
+		} elsif ($$v{service} eq "pops") {
+			$$r{num_connects} = 0 if (check_pop($v, $r, 1) == $SERVICE_UP);
+		} elsif ($$v{service} eq "imap") {
+			$$r{num_connects} = 0 if (check_imap($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "imaps") {
+			$$r{num_connects} = 0 if (check_imaps($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "smtp" or $$v{service} eq "submission") {
+			$$r{num_connects} = 0 if (check_smtp($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "ftp") {
+			$$r{num_connects} = 0 if (check_ftp($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "ldap") {
+			$$r{num_connects} = 0 if (check_ldap($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "nntp") {
+			$$r{num_connects} = 0 if (check_nntp($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "dns") {
+			$$r{num_connects} = 0 if (check_dns($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "sip") {
+			$$r{num_connects} = 0 if (check_sip($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "radius") {
+			$$r{num_connects} = 0 if (check_radius($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "mysql") {
+			$$r{num_connects} = 0 if (check_mysql($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "pgsql") {
+			$$r{num_connects} = 0 if (check_pgsql($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "oracle") {
+			$$r{num_connects} = 0 if (check_oracle($v, $r) == $SERVICE_UP);
+		} elsif ($$v{service} eq "simpletcp") {
+			$$r{num_connects} = 0 if (check_simpletcp($v, $r) == $SERVICE_UP);
+		} else {
+			$$r{num_connects} = 0 if (check_none($v, $r) == $SERVICE_UP);
+		}
+	} elsif ($$v{checktype} eq "connect") {
+		if ($$v{protocol} ne "udp") {
+			&ld_debug(2, "Checking connect: real server=$real_id (virtual=$virtual_id)");
+			check_connect($v, $r);
+		}
+		else {
+			&ld_debug(2, "Checking connect (ping): real server=$real_id (virtual=$virtual_id)");
+			check_ping($v, $r);
+		}
+	} elsif ($$v{checktype} eq "ping") {
+		&ld_debug(2, "Checking ping: real server=$real_id (virtual=$virtual_id)");
+		check_ping($v, $r);
+	} elsif ($$v{checktype} eq "external") {
+		&ld_debug(2, "Checking external: real server=$real_id (virtual=$virtual_id)");
+		check_external($v, $r);
+	} elsif ($$v{checktype} eq "external-perl") {
+		&ld_debug(2, "Checking external-perl: real server=$real_id (virtual=$virtual_id)");
+		check_external_perl($v, $r);
+	} elsif ($$v{checktype} eq "off") {
+		&ld_debug(2, "Checking off: No real or fallback servers to be added\n");
+	} elsif ($$v{checktype} eq "on") {
+		&ld_debug(2, "Checking on: Real servers are added without any checks\n");
+		&service_set($v, $r, "up");
+	} elsif ($$v{checktype} eq "combined") {
+		&ld_debug(2, "Checking combined-connect: real server=$real_id (virtual=$virtual_id)");
+		if (check_connect($v, $r) == $SERVICE_UP) {
+			$$r{num_connects}++;
+		} else {
+			$$r{num_connects} = 999999;
+		}
+	}
+}
+
+sub _check_real_for_maintenance
+{
+	my $r = shift;
+
+	return undef if(!$MAINTDIR);
+
+	my $servername = ld_gethostbyaddr($$r{server});
+
+	# Extract just the first component of the full name so we can match short or FQDN names
+	$servername =~ /^([a-z][a-z0-9\-]+)\./;
+	my $servershortname = $1;
+
+	if (-e "$MAINTDIR/$$r{server}:$$r{port}") {
+		&ld_debug(2, "Server maintenance: Found file $$r{server}:$$r{port}");
+		return 1;
+	} elsif (-e "$MAINTDIR/$$r{server}") {
+		&ld_debug(2, "Server maintenance: Found file $$r{server}");
+		return 1;
+	} elsif ($servername && -e "$MAINTDIR/$servername:$$r{port}") {
+		&ld_debug(2, "Server maintenance: Found file $servername:$$r{port}");
+		return 1;
+	} elsif ($servername && -e "$MAINTDIR/$servername") {
+		&ld_debug(2, "Server maintenance: Found file $servername");
+		return 1;
+	} elsif ($servershortname && -e "$MAINTDIR/$servershortname:$$r{port}") {
+		&ld_debug(2, "Server maintenance: Found file $servershortname:$$r{port}");
+		return 1;
+	} elsif ($servershortname && -e "$MAINTDIR/$servershortname") {
+		&ld_debug(2, "Server maintenance: Found file $servershortname");
+		return 1;
+	}
+	return undef;
+}
+
+sub check_http
+{
+	use LWP::UserAgent;
+	use LWP::Debug;
+	if($DEBUG > 2) {
+		LWP::Debug::level('+');
+	}
+	my ($v, $r) = @_;
+
+	$$r{url} =~ /(http|https):\/\/([^:\/]+)(:([^\/]+))?(\/.*)/;
+	my $host = $2;
+	#my $port = $3;
+	my $uri = $4;
+	my $virtualhost = (defined $$v{virtualhost} ? $$v{virtualhost} : $host);
+
+	&ld_debug(2, "check_http: url=\"$$r{url}\" "
+		. "virtualhost=\"$virtualhost\"");
+
+	my $ua = new LWP::UserAgent(ssl_opts => { verify_hostname => 0 });
+
+	my $h = undef;
+	if ($$v{service} eq "http_proxy") {
+		my $port = ld_checkport($v, $r);
+		$ua->proxy("http", "http://$$r{server}:$port/");
+	} else {
+		$h = new HTTP::Headers("Host" => $virtualhost);
+	}
+
+	my $req = new HTTP::Request("$$v{httpmethod}", "$$r{url}", $h);
+	my $res;
+
+	# LWP does not seem to honour timeouts set using $ua->timeout()
+	# for HTTPS. So use an alarm instead. This also has the advantage
+	# of being cumulative timeout, rather than a per send/receive
+	# timeout.
+	eval {
+		# LWP makes unguarded calls to eval
+		# which throw a fatal exception if they fail
+		# Needless to say, this is completely stupid.
+		# Resetting of $SIG{'__DIE__'} is also
+		# needed now that alarm() is used.
+		local $SIG{'__DIE__'} = "DEFAULT";
+		local $SIG{'ALRM'} = sub { die "Timeout Alarm" };
+		&ld_debug(4, "Timeout is $$v{negotiatetimeout}");
+		&ld_debug(2, "Starting Check");
+		alarm $$v{negotiatetimeout};
+
+		&ld_debug(2, "Starting HTTP/HTTPS");
+		$res = $ua->request($req);
+		&ld_debug(2, "Finished HTTP/HTTPS");
+		alarm 0; # Cancel the alarm
+	};
+
+	if (not defined $res) {
+		&ld_debug(2, "check_http: timeout");
+		goto down;
+	}
+
+	if ($$v{service} eq "https") {
+                &ld_debug(2, "SSL-Cipher: " .
+                        ($res->header('Client-SSL-Cipher') || '<not set>'));
+                &ld_debug(2, "SSL-Cert-Subject: " .
+                        ($res->header('Client-SSL-Cert-Subject') || '<not set>'));
+                &ld_debug(2, "SSL-Cert-Issuer: " .
+                        ($res->header('Client-SSL-Cert-Issuer') || '<not set>'));
+	}
+
+	&ld_debug(2, "Return status: " . $res->status_line);
+
+	my $recstr = $$r{receive};
+	if ($res->is_success && (!($recstr =~ /.+/) ||
+				$res->content =~ /$recstr/)) {
+		service_set($v, $r, "up", {do_log => 1}, $res->status_line);
+		&ld_debug(2, "check_http: $$r{url} is up\n");
+		return $SERVICE_UP;
+	}
+
+	my $log_message = $res->is_success ? $res->content : $res->status_line;
+	service_set($v, $r, "down", {do_log => 1}, $log_message);
+
+	&ld_debug(3, "Headers " .  $res->headers->as_string);
+down:
+	&ld_debug(2, "check_http: $$r{url} is down\n");
+	return $SERVICE_DOWN;
+}
+
+sub check_smtp
+{
+	require Net::SMTP;
+	my ($v, $r) = @_;
+	my $port = ld_checkport($v, $r);
+
+	&ld_debug(2, "Checking $$v{service}: server=$$r{server} port=$port");
+
+	my $smtp = new Net::SMTP($$r{server}, Port => $port,
+			Timeout => $$v{negotiatetimeout});
+	if ($smtp) {
+		$smtp->quit;
+		service_set($v, $r, "up", {do_log => 1});
+		return $SERVICE_UP;
+	} else {
+		service_set($v, $r, "down", {do_log => 1});
+		return $SERVICE_DOWN;
+	}
+}
+
+sub check_pop
+{
+	require Mail::POP3Client;
+	my ($v, $r, $ssl) = @_;
+	my $port = ld_checkport($v, $r);
+
+	&ld_debug(2, "Checking pop server=$$r{server} port=$port ssl=$ssl");
+
+	my $pop = new Mail::POP3Client(USER => $$v{login},
+					PASSWORD => $$v{passwd},
+					HOST => $$r{server},
+					USESSL => $ssl,
+					PORT => $port,
+					DEBUG => 0,
+					TIMEOUT => $$v{negotiatetimeout});
+
+	if (!$pop) {
+		service_set($v, $r, "down", {do_log => 1});
+		return $SERVICE_DOWN;
+	}
+
+	if($$v{login} ne "") {
+		my $authres = $pop->login();
+		$pop->close();
+		if (!$authres) {
+			service_set($v, $r, "down", {do_log => 1});
+			return $SERVICE_DOWN;
+		}
+	}
+
+	$pop->close();
+	service_set($v, $r, "up", {do_log => 1});
+	return $SERVICE_UP;
+}
+
+sub check_imap
+{
+	require Net::IMAP::Simple;
+	my ($v, $r) = @_;
+	my $port = ld_checkport($v, $r);
+
+	&ld_debug(2, "Checking imap server=$$r{server} port=$port");
+
+	my $imap = Net::IMAP::Simple->new($$r{server},
+					port => $port,
+					timeout => $$v{negotiatetimeout});
+
+	if (!$imap) {
+		service_set($v, $r, "down", {do_log => 1});
+		return $SERVICE_DOWN;
+	}
+
+	if($$v{login} ne "") {
+		my $authres = $imap->login($$v{login},$$v{passwd});
+		$imap->quit;
+		if (!$authres) {
+			service_set($v, $r, "down", {do_log => 1});
+			return $SERVICE_DOWN;
+		}
+	}
+
+	$imap->quit();
+	service_set($v, $r, "up", {do_log => 1});
+	return $SERVICE_UP;
+}
+
+sub check_imaps
+{
+	require Net::IMAP::Simple::SSL;
+	my ($v, $r) = @_;
+	my $port = ld_checkport($v, $r);
+
+	&ld_debug(2, "Checking imaps server=$$r{server} port=$port");
+
+	my $imaps = Net::IMAP::Simple::SSL->new($$r{server},
+					port => $port,
+					timeout => $$v{negotiatetimeout});
+	if (!$imaps) {
+		service_set($v, $r, "down", {do_log => 1});
+		return $SERVICE_DOWN;
+	}
+
+	if($$v{login} ne "") {
+		my $authres = $imaps->login($$v{login},$$v{passwd});
+		$imaps->quit;
+		if (!$authres) {
+			service_set($v, $r, "down", {do_log => 1});
+			return $SERVICE_DOWN;
+		}
+	}
+
+	$imaps->quit();
+	service_set($v, $r, "up", {do_log => 1});
+	return $SERVICE_UP;
+}
+
+sub check_ldap
+{
+	my ($v, $r) = @_;
+	require Net::LDAP;
+	my $port = ld_checkport($v, $r);
+
+	my $result;
+	my $recstr = $$r{receive};
+
+	&ld_debug(2, "Checking ldap server=$$r{server} port=$port");
+	eval {
+		local $SIG{'__DIE__'} = "DEFAULT";
+		local $SIG{'ALRM'} = sub { die "Timeout Alarm" };
+		&ld_debug(4, "Timeout is $$v{checktimeout}");
+		&ld_debug(2, "Starting Check");
+		alarm $$v{checktimeout};
+
+		my $ldap = Net::LDAP->new("$$r{server}", port => $port,
+					timeout => $$v{negotiatetimeout});
+		if(!$ldap) {
+		    service_set($v, $r, "down", {do_log => 1}, "Connection failed");
+		    &ld_debug(4, "Connection failed");
+		    alarm 0; # Cancel the alarm
+		    return $SERVICE_DOWN;
+		}
+
+		my $mesg;
+		if ($$v{login} && $$v{passwd}) {
+		    $mesg = $ldap->bind($$v{login}, password=>$$v{passwd}) ;
+		}
+		else {
+		    $mesg = $ldap->bind ;
+		}
+		if ($mesg->is_error) {
+		    service_set($v, $r, "down", {do_log => 1}, "Bind failed");
+		    &ld_debug(4, "Bind failed");
+		    alarm 0; # Cancel the alarm
+		    return $SERVICE_DOWN;
+		}
+
+		&ld_debug(4, "Base : " . substr($$r{request},1));
+		$result = $ldap->search (
+		    base	=> substr($$r{request},1) . "",
+		    scope	=> "base",
+		    filter	=> "(objectClass=*)"
+		    );
+
+		alarm 0; # Cancel the alarm
+	};
+
+	if (!defined($result)) {
+		service_set($v, $r, "down", {do_log => 1}, "No answer received");
+                &ld_debug(2, "check timeout alarm");
+                return $SERVICE_DOWN;
+        }
+
+	if($result->count != 1) {
+		service_set($v, $r, "down", {do_log => 1}, "No answer received");
+		&ld_debug(2, "Count failed : " . $result->count);
+		return $SERVICE_DOWN;
+	}
+
+	my $href = $result->as_struct;
+	my @arrayOfDNs  = keys %$href ;
+	if (!($recstr =~ /.+/) || $arrayOfDNs[0] =~ /$recstr/) {
+		service_set($v, $r, "up", {do_log => 1}, "Success");
+		return $SERVICE_UP;
+	} else {
+		service_set($v, $r, "down", {do_log => 1}, "Response mismatch");
+		&ld_debug(4,"Message differs : " . ", " . $$r{receive}
+				. ", " . $arrayOfDNs[0] . ".");
+		return $SERVICE_DOWN;
+	}
+}
+
+sub check_nntp
+{
+	use IO::Socket;
+	use IO::Socket::INET6;
+	use IO::Select;
+	my ($v, $r) = @_;
+	my $sock;
+	my $s;
+	my $buf;
+	my $port = ld_checkport($v, $r);
+	my $status = 1;
+
+	&ld_debug(2, "Checking nntp server=$$r{server} port=$port");
+
+	unless ($sock = IO::Socket::INET6->new(PeerAddr => $$r{server},
+		PeerPort => $port, Proto => 'tcp',
+		TimeOut => $$v{negotiatetimeout})) {
+		service_set($v, $r, "down", {do_log => 1});
+		return $SERVICE_DOWN;
+	}
+	$s = IO::Select->new();
+	$s->add($sock);
+	if (scalar($s->can_read($$v{negotiatetimeout})) == 0) {
+		service_set($v, $r, "down", {do_log => 1});
+	} else {
+		sysread($sock, $buf, 64);
+		if ($buf =~ /^2/) {
+			service_set($v, $r, "up", {do_log => 1});
+			$status = 0;
+		} else {
+			service_set($v, $r, "down", {do_log => 1});
+		}
+	}
+	$s->remove($sock);
+	$sock->close;
+
+	return $status;
+}
+
+sub check_radius
+{
+	require Authen::Radius;
+
+	my ($v, $r) = @_;
+
+	&ld_debug(2, "Checking radius");
+
+	my $port = ld_checkport($v, $r);
+	my $radius;
+	my $result = "";
+
+	eval {
+		local $SIG{'__DIE__'} = "DEFAULT";
+		local $SIG{'ALRM'} = sub { die "Timeout Alarm" };
+		&ld_debug(4, "Timeout is $$v{checktimeout}");
+		&ld_debug(2, "Starting Check");
+		alarm $$v{checktimeout};
+
+		&ld_debug(2, "Starting Radius");
+		$radius = new Authen::Radius(Host => "$$r{server}:$port",
+					     Secret=>$$v{secret},
+					     TimeOut=>$$v{negotiatetimeout},
+					     Errmode=>'die');
+		$result = $radius->check_pwd($$v{login}, $$v{passwd});
+		&ld_debug(2, "Finished Radius");
+		alarm 0; # Cancel the alarm
+	};
+	if ($result eq "") {
+		&service_set($v, $r, "down", {do_log => 1});
+		&ld_debug(3, "Deactivated service $$r{server}:$$r{port}: $@");
+		&ld_debug(3, "Radius Error: ".$radius->get_error);
+		return $SERVICE_DOWN;
+	} else {
+		&service_set($v, $r, "up", {do_log => 1});
+		&ld_debug(3, "Activated service $$r{server}:$$r{port}");
+		return $SERVICE_UP;
+	}
+}
+
+sub check_mysql
+{
+	return check_sql(@_, "mysql", "database");
+}
+
+sub check_pgsql
+{
+	return check_sql(@_, "Pg", "dbname");
+}
+
+sub check_sql_log_errstr
+{
+	my ($prefix, $errstr) = (@_);
+
+	for $_ (split /\n/, $errstr) {
+		&ld_debug(4, "$prefix $_\n");
+	}
+
+}
+
+sub check_oracle
+{
+	return check_sql(@_, "Oracle", "sid");
+}
+
+sub check_sql
+{
+	require DBI;
+	my ($v, $r, $dbd, $dbname) = @_;
+	my $port = ld_checkport($v, $r);
+	my ($dbh, $sth, $query, $rows, $result);
+	$result = $SERVICE_DOWN;
+	$query = $$r{request};
+	$query =~ s#^/##;
+	unless ($$v{login} && $query) {
+		&ld_log("Error: Must specify a login and request string " .
+			"for MySQL, Oracle and PostgreSQL checks. " .
+			"Not adding $$r{server}.\n");
+		goto err_down;
+	}
+	$result=2;   # Set result flag.  Only ok if ends up at zero.
+	&ld_debug(2, "Checking $$v{server} server=$$r{server} port=$port\n");
+	$dbh = DBI->connect("dbi:$dbd:$dbname=$$v{database};" .
+			    "host=$$r{server};port=$port", $$v{login},
+			    $$v{passwd});
+	unless ($dbh) {
+		&ld_debug(2, "Failed to bind to $$r{server} with DBI->errstr\n");
+		check_sql_log_errstr("Failed to bind to $$r{server} with",
+				     DBI->errstr);
+		goto err_down;
+	}
+	$result--;
+	$sth = $dbh->prepare($query);
+	unless ($sth) {
+		&ld_debug(2, "Error preparing statement: $dbh->errstr\n");
+		check_sql_log_errstr("Error preparing statement:",
+				     $dbh->errstr);
+		goto err_disconect;
+	}
+
+	# Test to see if any errors are returned
+	$sth->execute;
+	if ($dbh->err) {
+		&ld_debug(2, "Error executing statement: $dbh->errstr : $dbh->err\n");
+		check_sql_log_errstr("Error executing statement:",
+				     $dbh->errstr, $dbh->err);
+		goto err_finish;
+	}
+
+	# On error "execute" will return undef.
+	#
+	# Assuming you're using 'SELECT' you will get the number of rows
+	# returned from the db when running execute: the 'rows' method is
+	# only used when doing something that is NOT a select.  I cannot
+	# imagine that you would ever want to insert or update from a
+	# regular polling on this system, so we will assume you are using
+	# SELECT here.
+	#
+	# Ideally you will do something like this: 'select * from
+	# director_slave where enabled=1' This way you can have, say, a
+	# MEMORY table in MySQL where you insert a value into a row
+	# (enabled) that says whether or not you want to actually use this
+	# in the pool from ldirector / ipvs, and disable them without
+	# actually turning off your sql server.
+	
+	$sth->execute;
+	if ($dbd eq "Oracle") { $sth->fetchrow_hashref() }
+	unless ($rows = $sth->rows) {
+		check_sql_log_errstr("Error executing statement:",
+				     $dbh->errstr, $dbh->err);
+		goto err_finish;
+	}
+
+	# Actually look to see if there was data returned in this statement,
+	# else disable node
+	if($rows > 0) {
+		goto out;
+	} else {
+		goto err_finish;
+	}
+
+out:
+	$result = $SERVICE_UP;
+err_finish:
+	$sth->finish();
+err_disconnect:
+	$dbh->disconnect();
+err_down:
+	service_set($v, $r, $result == $SERVICE_UP ? "up" : "down", {do_log => 1});
+	return $result;
+}
+
+sub check_connect
+{
+	my ($v, $r) = @_;
+	my $port = ld_checkport($v, $r);
+
+	eval {
+		local $SIG{'__DIE__'} = "DEFAULT";
+		local $SIG{'ALRM'} = sub { die "Timeout Alarm" };
+		&ld_debug(4, "Timeout is $$v{checktimeout}");
+		alarm $$v{checktimeout};
+		my $sock = &ld_open_socket($$r{server}, $port, $$v{protocol});
+		if ($sock) {
+			close($sock);
+		} else {
+			alarm 0; # Cancel the alarm
+			die("Socket Connect Failed");
+		}
+		&ld_debug(3, "Connected to $$r{server} (port $port)");
+		alarm 0; # Cancel the alarm
+	};
+	if ($@) {
+		&service_set($v, $r, "down", {do_log => 1});
+		&ld_debug(3, "Deactivated service $$r{server}:$$r{port}: $@");
+		return $SERVICE_DOWN;
+	} else {
+		&service_set($v, $r, "up", {do_log => 1});
+		&ld_debug(3, "Activated service $$r{server}:$$r{port}");
+		return $SERVICE_UP;
+	}
+}
+
+sub check_external
+{
+	my ($v, $r) = @_;
+	my $v_server;
+
+	if (defined $$v{server}) {
+		$v_server = $$v{server};
+	} else {
+		$v_server = $$v{fwm};
+	}
+
+	my $result = system_timeout($$v{checktimeout},
+				    $$v{checkcommand}, $v_server, $$v{port},
+				    $$r{server}, $$r{port});
+
+	if ($result) {
+		&service_set($v, $r, "down", {do_log => 1});
+		&ld_debug(3, "Deactivated service $$r{server}:$$r{port}: " .
+			  "$@ after calling $$v{checkcommand} with result " .
+			  "$result");
+		return 0;
+	} else {
+		&service_set($v, $r, "up", {do_log => 1});
+		&ld_debug(3, "Activated service $$r{server}:$$r{port}");
+		return 1;
+	}
+}
+
+sub check_external_perl
+{
+	my ($v, $r) = @_;
+	my $result;
+	my $v_server;
+
+	eval {
+		local $SIG{'__DIE__'} = "DEFAULT";
+		local $SIG{'ALRM'} = sub { die "Timeout Alarm" };
+		&ld_debug(4, "Timeout is $$v{checktimeout}");
+		alarm $$v{checktimeout};
+		if (defined $$v{server}) {
+			$v_server = $$v{server};
+		} else {
+			$v_server = $$v{fwm};
+		}
+		my $cmdfunc = $check_external_perl__funcs{$$v{checkcommand}};
+		if (!defined($cmdfunc)) {
+			open(CMDFILE, "<$$v{checkcommand}") || die "cannot open external-perl checkcommand file: $$v{checkcommand}";
+			$cmdfunc = eval("sub { \@ARGV=\@_; " . join("", <CMDFILE>) . " }");
+			close(CMDFILE);
+			$check_external_perl__funcs{$$v{checkcommand}} = $cmdfunc;
+		}
+		no warnings 'redefine';
+		local *CORE::GLOBAL::exit = sub {
+			$result = shift;
+			goto external_exit;
+		};
+		$cmdfunc->($v_server, $$v{port}, $$r{server}, $$r{port});
+		external_exit:
+		alarm 0;
+	};
+	if ($@ or $result != 0) {
+		&service_set($v, $r, "down");
+		&ld_debug(3, "Deactivated service $$r{server}:$$r{port}: " .
+			  "$@ after calling (external-perl) $$v{checkcommand} with result " .
+			  "$result");
+		return 0;
+	} else {
+		&service_set($v, $r, "up");
+		&ld_debug(3, "Activated service $$r{server}:$$r{port}");
+		return 1;
+	}
+}
+
+sub check_sip
+{
+	my ($v, $r) = @_;
+	my $sip_d_port = ld_checkport($v, $r);
+
+	&ld_debug(2, "Checking sip server=$$r{server} port=$sip_d_port");
+
+
+	eval {
+		use Socket;
+
+		local $SIG{'__DIE__'} = "DEFAULT";
+		local $SIG{'ALRM'} = sub { die "Timeout Alarm" };
+		&ld_debug(4, "Timeout is $$v{checktimeout}");
+		alarm $$v{negotiatetimeout};
+
+		my $sock = &ld_open_socket($$r{server}, $sip_d_port,
+					$$v{protocol});
+		unless ($sock) {
+			alarm 0;
+			die("Socket Connect Failed");
+		}
+
+		my ($sip_s_addr_str, $sip_s_port) = &ld_get_addrport($sock);
+
+		&ld_debug(3, "Connected from $sip_s_addr_str:$sip_s_port to " .
+			$$r{server} . ":$sip_d_port");
+
+		select $sock;
+		$|=1;
+		select STDOUT;
+
+		my $request =
+		"OPTIONS sip:" . $$v{login} . " SIP/2.0\r\n" .
+		"Via: SIP/2.0/UDP $sip_s_addr_str:$sip_s_port;" .
+			"branch=z9hG4bKhjhs8ass877\r\n" .
+		"Max-Forwards: 70\r\n" .
+		"To: <sip:" . $$v{login} . ">\r\n" .
+		"From: <sip:" . $$v{login} . ">;tag=1928301774\r\n" .
+		"Call-ID: " . (join "", map { unpack "H*", chr(rand(256)) } 1..8) . "\r\n" .
+		"CSeq: 63104 OPTIONS\r\n" .
+		"Contact: <sip:" . $$v{login} . ">\r\n" .
+		"Accept: application/sdp\r\n" .
+		"Content-Length: 0\r\n\r\n";
+
+		print "Request:\n$request";
+		print $sock $request;
+
+		my $ok;
+		my $reply;
+		while (<$sock>) {
+			chomp;
+			$/="\r";
+			chomp;
+			$/="\n";
+
+			last if ($_ eq "");
+
+			if (!defined $ok) {
+				# Check status
+				$ok = $_;
+				if ($ok !~ m/^SIP\/2.0 200 OK/) {
+					alarm 0; # Cancel the alarm
+					close($sock);
+					die "$ok\n";
+				}
+				next;
+			}
+			$reply .= "$_\n";
+
+			# Add more checks here as desired
+		}
+		alarm 0; # Cancel the alarm
+		close($sock);
+
+		if (!defined $ok) {
+			die "No OK\n";
+		}
+
+		print "Reply:\n$ok\n$reply\n";
+	};
+
+	if ($@) {
+		&service_set($v, $r, "down", {do_log => 1});
+		&ld_debug(3, "Deactivated service $$r{server}:$$r{port}: $@");
+		return $SERVICE_DOWN;
+	} else {
+		&service_set($v, $r, "up", {do_log => 1});
+		&ld_debug(3, "Activated service $$r{server}:$$r{port}");
+		return $SERVICE_UP;
+	}
+}
+
+sub check_simpletcp
+{
+	my ($v, $r) = @_;
+	my $d_port = ld_checkport($v, $r);
+
+	&ld_debug(2, "Checking simpletcp server=$$r{server} port=$d_port");
+
+	eval {
+		use Socket;
+
+		local $SIG{'__DIE__'} = "DEFAULT";
+		local $SIG{'ALRM'} = sub { die "Timeout Alarm" };
+		&ld_debug(4, "Timeout is $$v{checktimeout}");
+		alarm $$v{negotiatetimeout};
+
+		my $sock = &ld_open_socket($$r{server}, $d_port,
+					$$v{protocol});
+		unless ($sock) {
+			alarm 0;
+			die("Socket Connect Failed");
+		}
+
+		my ($s_addr_str, $s_port) = &ld_get_addrport($sock);
+
+		&ld_debug(3, "Connected from $s_addr_str:$s_port to " .
+			$$r{server} . ":$d_port");
+
+		select $sock;
+		$|=1;
+		select STDOUT;
+
+		my $request = substr($$r{request}, 1);
+		$request =~ s/\\n/\n/g ;
+
+		&ld_debug(2, "Checking simpletcp server=$$r{server} port=$d_port request:\n$request");
+		print $sock $request;
+		shutdown($sock, SHUT_WR);
+
+		my $ok;
+		my $reply;
+		while (<$sock>) {
+			&ld_debug(2, "Checking simpletcp server=$$r{server} port=$d_port receive=" . $$r{receive} ." got: $_\n");
+			if ( $_ =~ /$$r{receive}/ ) {
+				$ok = 1;
+				last;
+			}
+		}
+		alarm 0; # Cancel the alarm
+		close($sock);
+
+		if (!defined $ok) {
+			die "No OK\n";
+		}
+	};
+
+	if ($@) {
+		&service_set($v, $r, "down", {do_log => 1});
+		&ld_debug(3, "Deactivated service $$r{server}:$$r{port}: $@");
+		return $SERVICE_DOWN;
+	} else {
+		&service_set($v, $r, "up", {do_log => 1});
+		&ld_debug(3, "Activated service $$r{server}:$$r{port}");
+		return $SERVICE_UP;
+	}
+}
+
+sub check_ftp
+{
+	require Net::FTP;
+	my ($v, $r) = @_;
+	my $ftp;
+	my $memory;
+	my $debug = ($DEBUG > 2) ? 1 : 0;
+	my $port = ld_checkport($v, $r);
+
+	&ld_debug(2, "Checking ftp server=$$r{server} port=$port");
+	&ld_debug(4, "Timeout is $$v{negotiatetimeout}");
+
+	open(TMP,'+>', undef);
+
+	# In some cases Net::FTP dies if there is a timeout
+	eval {
+		unless ($ftp = Net::FTP->new("$$r{server}:$port",
+				Timeout=>$$v{negotiatetimeout},
+				Debug=>$debug)) {
+			die "Could not connect\n";
+		}
+		$ftp->login($$v{login}, $$v{passwd});
+		$ftp->cwd("/");
+		$ftp->binary();
+		$ftp->pasv();
+		$ftp->get("$$r{request}", *TMP);
+		$ftp->quit();
+	};
+	if ($@) {
+		&ld_debug(2, "Warning: $@");
+	}
+
+	seek TMP, 0, 0;
+	local $/;
+	$memory = <TMP>;
+	close TMP;
+
+	if ($memory =~ /$$r{receive}/) {
+		service_set($v, $r, "up", {do_log => 1});
+		return $SERVICE_UP;
+	}
+
+	service_set($v, $r, "down", {do_log => 1});
+	return $SERVICE_DOWN;
+}
+
+sub check_dns
+{
+	my $res;
+	my $query;
+	my $rr;
+	my $request;
+	my $server;
+	my ($v,$r) = @_;
+	{
+		# Net::DNS makes unguarded calls to eval
+		# which throw a fatal exception if they fail
+		# Needless to say, this is completely stupid.
+		local $SIG{'__DIE__'} = "DEFAULT";
+		# When fork=yes we need to ignore the child death
+		local $SIG{'CHLD'} = "IGNORE";
+		require Net::DNS;
+	}
+	$res = new Net::DNS::Resolver;
+	if($DEBUG > 2) {
+		$res->debug(1);
+	}
+
+	$$r{"request"} =~ m/^\/?(.*)/;
+	$request=$1;
+	
+	$server = &ld_strip_brackets($$r{server});
+
+	&ld_debug(2, "Checking dns: request=\"$request\" receive=\""
+		. $$r{"receive"} . "\"\n");
+
+	eval {
+		local $SIG{'__DIE__'} = "DEFAULT";
+		local $SIG{'ALRM'} = sub { die "timeout\n"; };
+		alarm($$v{negotiatetimeout});
+		$res->nameservers($server);
+		if ($$v{"protocol"} eq "tcp") {
+			$res->usevc(1);
+		}
+		$query = $res->search($request);
+		alarm(0);
+	};
+
+	if (@$ eq "timeout\n" or ! $query) {
+		service_set($v, $r, "down", {do_log => 1}, "Connection timed out");
+		return $SERVICE_DOWN;
+	}
+
+	foreach $rr ($query->answer) {
+		if (($rr->type eq "A" and $rr->address eq $$r{"receive"}) or
+		    ($rr->type eq "PTR" and $rr->ptrdname eq $$r{"receive"})) {
+			service_set($v, $r, "up", {do_log => 1}, "Success");
+			return $SERVICE_UP;
+		}
+	}
+
+	service_set($v, $r, "down", {do_log => 1}, "Response mismatch");
+	return $SERVICE_DOWN;
+}
+
+sub check_ping
+{
+	use Net::Ping;
+
+	my ($v,$r) = (@_);
+
+	&ld_debug(2, "Checking ping: " .  "host=\"" .  $$r{server} .
+		"\" checktimeout=\"" . $$v{"checktimeout"} .
+		"\" checkcount=\"" . $$v{"checkcount"} . "\"\n");
+
+	my $p = Net::Ping->new("icmp","1","64");
+	for (my $attempt = 0; $attempt < $$v{"checkcount"}; $attempt++) {
+		if ($p->ping($$r{server}, $$v{"checktimeout"})) {
+			&ld_debug(2, "pong from $$r{server}\n");
+			service_set($v, $r, "up", {do_log => 1});
+			return $SERVICE_UP;
+		}
+		&ld_debug(2, "ping to $$r{server} timed out " .
+					"(attempt " .  ($attempt + 1) . "/" .
+					$$v{"checkcount"} . ")\n");
+	}
+
+	service_set($v, $r, "down");
+	return $SERVICE_DOWN;
+}
+
+# check_none
+# Dummy function to check service if service type is none.
+# Just activates the real server
+sub check_none
+{
+	my ($v, $r) = @_;
+
+	&ld_debug(2, "Checking none");
+
+	service_set($v, $r, "up", {do_log => 1});
+	return $SERVICE_UP;
+}
+
+# service_set
+# Used to bring up and down real servers.
+# This is the function you should call if you want to bring a real
+# server up or down.
+# This function is safe to call regardless of the current state of a
+# real server.
+# Do _not_ call _service_up or _service_down directly.
+# pre: v: virtual that the real service belongs to
+#         Only used to determine the protocol of the service
+#      r: real server to take down
+#      state: up or down
+#             up to bring the real service up
+#             down to bring the real service up
+#      flags: hash with the following (optional) keys:
+#             force => 1  - force setting of the specified state
+#             do_log => 1 - log the state to the monitorfile
+#                           (when called as the result of a check)
+# post: The real server is brought up or down for each virtual service
+#       it belongs to.
+# return: none
+sub service_set
+{
+	my ($v, $r, $state, $flags, $log_msg) = @_;
+
+	my ($real, $virtual, $virt, $now);
+
+	if ($$flags{'do_log'}) {
+		$now = localtime();
+
+		if (!defined($log_msg)) {
+			$log_msg = "-";
+		}
+
+		# URI-escape special log characters ('|' and newlines)
+		$log_msg =~ s/([%|\r\n])/sprintf("%%%.2x", ord($1))/eg;
+	}
+
+	# Find the real server in @REAL
+	foreach $real (@REAL) {
+		if($real->{"real"} eq get_real_id_str($r, $v)) {
+			$virtual = $real->{"virtual"};
+			last;
+		}
+	}
+	return unless (defined($virtual));
+
+	# Check each virtual service for the real server and make
+	# changes as necessary
+	foreach $v (@VIRTUAL){
+		# Use found rather than relying on tmp_id being
+		# set when we leave the foreach loop. There
+		# seems to some weirdness in Perl (5.6.0 on Redhat 7.2)
+		my $found = 0;
+		my $tmp_id;
+		my $virtual_id = get_virtual_id_str($v);
+		my $real_id = get_real_id_str($r, $v);
+		my $log_str = "real server=$real_id" .
+			      " (virtual=$virtual_id)";
+		foreach $tmp_id (@$virtual) {
+			if($virtual_id eq $tmp_id) {
+				$found = 1;
+				last;
+			}
+		}
+		if ($found == 1) {
+			if ($state=~/up/i) {
+				_service_up($v, $r, $$flags{"force"});
+				&ld_debug(2, "Enabled  $log_str");
+			} elsif ($state=~/down/i) {
+				_service_down($v, $r, $$flags{"force"});
+				&ld_debug(2, "Disabled $log_str");
+			}
+
+			if ($$v{"monitorfile"} and $$flags{"do_log"}) {
+				my $real_log_msg = $real_id;
+				$real_log_msg =~ tr/:/ /s;
+				$real_log_msg =~ s/\\//g;
+				unless(
+					open(CHECKLOG, ">>$$v{monitorfile}") and
+					print CHECKLOG "[$now] [$$] $real_log_msg [$state] $log_msg\n" and
+					close(CHECKLOG)
+				) { die("Error writing to monitorfile '$$v{monitorfile}': $!"); }
+			}
+		}
+	}
+}
+
+# _remove_service
+# Remove a real server by either making it quiescent or deleting it
+# Should be called by _service_down or fallback_off
+# I.e. If you want to change the state of a real server call service_set.
+#      If you call this function directly then ldirectord will lose track
+#      of the state of real servers.
+# If the real server exists (which it should) make it quiescent or
+# delete it, depending on the global and per virtual service quiescent flag.
+# If it # doesn't exist, just leave it as it will be added by the
+# _service_up code as appropriate.
+# pre: v: reference to virtual service to with the real server belongs
+#      rservice: service to restore. Of the form server:port for a tcp or
+#                udp service. Of the form fwmark for a fwm service.
+#      rforw: Forwarding mechanism of service. Sould be one of "-g" "-i" or
+#             "-m"
+#      tag: Tag to use for logging. Should be either "real" or "fallback"
+# post: real service is taken up from the respective virtual service
+#       if it is inactive
+# return: none
+sub _remove_service
+{
+	my ($v, $rservice, $rforw, $tag) = (@_);
+
+	my $oldsrv;
+	my $ov;
+	my $or;
+	my $ipvsadm_args;
+	my $log_args;
+	my $virtual_str;
+	my $old_rservice;
+	my $is_quiescent;
+
+	$virtual_str = &get_virtual($v);
+
+	$oldsrv=&ld_read_ipvsadm();
+	$ov=$oldsrv->{&get_real_service_str($v)};
+	if(!defined($ov)){
+		return;
+	}
+
+	if ($tag ne "fallback"
+			and ((defined $$v{quiescent}
+					and $$v{quiescent} eq "yes")
+				or (!defined($$v{quiescent})
+					and $QUIESCENT eq "yes"))){
+		$is_quiescent = "quiescent";
+	}
+
+	$or=$ov->{"real"}->{$rservice};
+
+	# If a virtual service is a IP/port service (not fwmark)
+	# and a real-servers uses a forwarding mechanism other than masq
+	# then the port will always be that of the virtual service.
+	# This includes real-servers that LVS has set to use
+	# the local forwarding mechanism because their IP address
+	# is local. Thus, if $rservice does not exist test
+	# for the same ip address with the virtual servers port.
+	# N.B: This could cause strange things to happen if
+	# there is a clash between two real servers on different ports
+	# that LVS has mapped to being the same thing.
+	if(!defined($or)) {
+		$old_rservice = $rservice;
+		$rservice =~ /(.*):(.*)/;
+		$rservice = $1;
+		$virtual_str =~ /(.*):(.*)/;
+		$rservice .= ":" . $2;
+		$or=$ov->{"real"}->{$rservice};
+		# If this doesn't exist either, use the original service.
+		# Otherwise if masq and quiescence is in use, the
+		# real server is not local, and it has an alternate port to
+		# the virtual server, using the mapped service will
+		# result in a quiescent service being created on the
+		# virtual server's port, which is not wanted.
+		if(!defined($or)) {
+			$rservice = $old_rservice;
+			$old_rservice = undef;
+		}
+	}
+
+	if((!defined($or) and !defined($is_quiescent)) or
+			(defined($is_quiescent) and defined($or) and
+				$or->{"weight"} eq 0 and
+				get_forward_flag($or->{"forward"}) eq $rforw)){
+		return;
+	}
+
+	$ipvsadm_args = "$$v{proto} " . &get_virtual_option($v) . " -r $rservice";
+	$log_args = "$tag server: $rservice ";
+	if(defined($old_rservice)) {
+		$log_args .= "mapped from $old_rservice "
+	}
+	$log_args .= "($virtual_str)";
+
+	my $server_str=$rservice . " " . $virtual_str;
+	my $currenttime=time();
+	if(defined($is_quiescent)) {
+		if (defined($or)) {
+			&system_wrapper("$IPVSADM -e "
+					. "$ipvsadm_args $rforw -w 0");
+			&ld_log("Quiescent $log_args (Weight set to 0)");
+			&ld_emailalert_send("Quiescent $log_args (Weight set to 0)",
+				    $v, $rservice, $currenttime);
+		}
+		elsif ($READDQUIESCENT eq "yes") {
+			&system_wrapper("$IPVSADM -a "
+					. "$ipvsadm_args $rforw -w 0");
+			&ld_log("Readd Quiescent $log_args (Weight set to 0)");
+			&ld_emailalert_send("Quiescent $log_args (Weight set to 0)",
+				    $v, $rservice, $currenttime);
+		}
+	}
+	else {
+		&system_wrapper("$IPVSADM -d $ipvsadm_args");
+		&ld_log("Deleted $log_args");
+		&ld_emailalert_send("Deleted $log_args", $v,
+				    $rservice, $tag eq "fallback" ? 0 : $currenttime);
+	}
+}
+
+# _restore_service
+# Make a retore a real server. The opposite of _quiescent_server.
+# Should be called by _service_up or fallback_on
+# I.e. If you want to change the state of a real server call service_set.
+#      If you call this function directly then ldirectord will lose track
+#      of the state of real servers.
+# If the real server exists (which it should) make it quiescent. If it
+# doesn't exist, just leave it as it will be added by the _service_up code
+# as appropriate.
+# pre: v: reference to virtual service to with the real server belongs
+#      rservice: service to restore. Of the form server:port for a tcp or
+#                udp service. Of the form fwmark for a fwm service.
+#      rforw: Forwarding mechanism of service. Sould be one of "-g" "-i" or
+#             "-m"
+#      rwght: Weight of service. Sold be of the form "<weight>"
+#             e.g. "1"
+#      tag: Tag to use for logging. Should be either "real" or "fallback"
+# post: real service is taken up from the respective virtual service
+#       if it is inactive
+# return: none
+sub _restore_service
+{
+	my ($v, $rservice, $rforw, $rwght, $tag) = (@_);
+
+	my $oldsrv;
+	my $ov;
+	my $or;
+	my $ipvsadm_args;
+	my $log_args;
+
+	$ipvsadm_args = "$$v{proto} " . &get_virtual_option($v)
+			. " -r $rservice $rforw -w $rwght";
+	$log_args = "$tag server: $rservice "
+		    . "(" #. scalar(%{$v->{real_status}})
+		    .  &get_virtual($v) . ")";
+
+	#if the server exists then restore its weight
+	# otherwise add the server
+	$oldsrv=&ld_read_ipvsadm();
+	$ov=$oldsrv->{&get_real_service_str($v)};
+	if(defined($ov)){
+		$or=$ov->{"real"}->{$rservice};
+	}
+	if(defined($or)){
+		unless($or->{"weight"} eq $rwght and
+			get_forward_flag($or->{"forward"}) eq $rforw){
+			&system_wrapper("$IPVSADM -e $ipvsadm_args");
+			&ld_log("Restored $log_args (Weight set to $rwght)");
+			&ld_emailalert_send("Restored $log_args " .
+					    "(Weight set to $rwght)",
+					    $v, $rservice, 0);
+		}
+	}
+	else {
+		&system_wrapper("$IPVSADM -a $ipvsadm_args");
+		&ld_log("Added $log_args (Weight set to $rwght)");
+		&ld_emailalert_send("Added $log_args (Weight set to $rwght)",
+				    $v, $rservice, 0);
+	}
+}
+
+# Check the status of a server
+# Should only be called from _status_up, _status_down,
+# _service_up, or _service_down
+# Returns 1 if the server is up, 0 if down
+sub _status_check
+{
+	my ($v, $r, $is_fallback) = (@_);
+
+	my $virtual_id = get_virtual_id_str($v);
+	my $real_id = get_real_id_str($r, $v);
+
+	if (defined($is_fallback)) {
+		if (defined($v->{real_status}) or
+				(defined($v->{fallback_status}) and
+				$v->{fallback_status}->{"$real_id"})) {
+			return 1;
+		}
+	}
+	else {
+		if (defined ($v->{real_status}) and
+				$v->{real_status}->{"$real_id"}) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+# Set the status of a server as up
+# Should only be called from _service_up or _ld_start
+sub _status_up
+{
+	my ($v, $r, $is_fallback) = (@_);
+
+	my $virtual_id = get_virtual_id_str($v);
+	my $real_id = get_real_id_str($r, $v);
+
+	return undef if(_status_check($v, $r, $is_fallback));
+
+	$r->{virtual_status}->{"$virtual_id"} = 1;
+	if (defined $is_fallback) {
+		$v->{fallback_status}->{"$real_id"} = 1;
+	}
+	else {
+		$v->{real_status}->{"$real_id"} = 1;
+	}
+
+	return 1;
+}
+
+# Set the status of a server as down
+# Should only be called from _service_down or ld_stop
+sub _status_down
+{
+	my ($v, $r, $is_fallback) = (@_);
+
+	my $virtual_id = get_virtual_id_str($v);
+	my $real_id = get_real_id_str($r, $v);
+
+	return undef if (!_status_check($v, $r, $is_fallback));
+
+	if (defined($is_fallback)) {
+		delete $v->{fallback_status}->{"$real_id"};
+		if (! %{$v->{fallback_status}}) {
+			$v->{fallback_status} = undef;
+		}
+	}
+	else {
+		delete $v->{real_status}->{"$real_id"};
+		if (! %{$v->{real_status}}) {
+			$v->{real_status} = undef;
+		}
+	}
+
+	delete $r->{virtual_status}->{"$virtual_id"};
+	if (! %{$r->{virtual_status}}) {
+		$r->{virtual_status} = undef;
+	}
+
+	return 1;
+}
+
+# _service_up
+# Bring a real service up if it is down
+# Should be called by service_set only
+# I.e. If you want to change the state of a real server call service_set.
+#      If you call this function directly then ldirectord will lose track
+#      of the state of real servers.
+# pre: v: reference to virtual service to with the real server belongs
+#      r: reference to the real server to take down
+# post: real service is taken up from the respective virtual service
+#       if it is inactive
+# return: none
+sub _service_up
+{
+	my ($v, $r, $force) = (@_);
+
+	if ($r->{failcount} > 0) {
+		ld_log("Resetting soft failure count: " . $r->{server} . ":" .
+		       $r->{port} . " (" . get_virtual_id_str($v) . ")");
+	}
+
+	$r->{failcount} = 0;
+
+	if (! _status_up($v, $r) and ! defined($force)) {
+		return;
+	}
+
+	&_restore_service($v, $r->{server} . ":" . $r->{port},
+			  $r->{forw}, $r->{weight}, "real");
+	&fallback_off($v);
+}
+
+# _service_down
+# Bring a real service down if it is up
+# Should be called by service_set only
+# I.e. if you want to change the state of a real server call service_set.
+#      If you call this function directly then ldirectord will lose track
+#      of the state of real servers.
+# pre: v: reference to virtual service to with the real server belongs
+#      r: reference to the real server to take down
+# post: real service is taken down from the respective virtual service
+#       if it is active
+# return: none
+sub _service_down
+{
+	my ($v, $r, $force) = @_;
+
+	if (!_status_check($v, $r) and !defined($force)) {
+		return;
+	}
+
+	$r->{failcount}++;
+
+	if (!defined($force) and _status_check($v, $r) and
+	     ($r->{failcount} < $v->{failurecount})) {
+		ld_log("Soft failure real server: " . $r->{server} . ":" .
+		       $r->{port} . " (" . get_virtual_id_str($v) .
+		       ") failure " . $r->{failcount} . "/" . $v->{failurecount});
+		return;
+	}
+
+	_status_down($v, $r);
+
+	&_remove_service($v, $r->{server} . ":" . $r->{port},
+			 $r->{forw}, "real");
+
+	&fallback_on($v);
+}
+
+# fallback_on
+# Turn on the fallback server for a virtual service if it is inactive
+# pre: v: virtual to turn fallback service on for
+# post: fallback server is turned on if it was inactive
+# return: none
+sub fallback_on
+{
+	my ($v, $force) = (@_);
+
+	my $fallback=&fallback_find($v);
+
+	if (defined($fallback) and (_status_up($v, $fallback, "fallback")
+			or defined($force))) {
+		&_restore_service($v, $fallback->{server} . ":" . $fallback->{port},
+				  get_forward_flag($fallback->{forward}),
+				  "1", "fallback");
+	}
+
+	if (!defined ($v->{real_status})) {
+		&do_fallback_command($v, "start");
+	}
+}
+
+# fallback_off
+# Turn off the fallback server for a virtual service if it is active
+# pre: v: virtual to turn fallback service off for
+# post: fallback server is turned off if it was active
+# return: none
+sub fallback_off
+{
+	my ($v, $force) = (@_);
+
+	my $fallback=&fallback_find($v);
+
+	if (defined($fallback) and (_status_down($v, $fallback, "fallback")
+			or defined($force))) {
+		&_remove_service($v, $fallback->{server} . ":" .  $fallback->{port},
+				 get_forward_flag($fallback->{forward}),
+				 "fallback");
+	}
+
+	if (defined ($v->{real_status})) {
+		&do_fallback_command($v, "stop");
+	}
+}
+
+# fallback_find
+# Determine the fallback for a virtual service
+# pre: virtual: reference to a virtual service
+# post: none
+# return: $virtual->{"fallback"} if defined
+#         else $FALLBACK->{$virtual->{"protocol"}} if defined
+#         else undef
+sub fallback_find
+{
+	my ($virtual) = (@_);
+
+	my($global_fallback_ptr);	# fallback pointer
+	my $ipv6p = ($virtual->{addressfamily} == AF_INET6) ? 1 : 0;
+
+	if( defined $virtual->{"fallback"} ) {
+		return($virtual->{"fallback"});
+	} elsif ( not defined($FALLBACK) and not $ipv6p ) {
+		return undef;
+	} elsif ( not defined($FALLBACK6) and $ipv6p ) {
+		return undef;
+	}
+
+	if ($ipv6p) {	# IPv6
+		$global_fallback_ptr = $FALLBACK6;
+	} else {
+		$global_fallback_ptr = $FALLBACK;
+	}
+
+	# If the global fallback has a port, it can be used as is
+	if (defined($global_fallback_ptr->{$virtual->{"protocol"}}->{"port"})) {
+		return $global_fallback_ptr->{$virtual->{"protocol"}};
+	}
+
+	# Else create an anonymous fallback
+	my %anon_fallback = %{$global_fallback_ptr->{$virtual->{"protocol"}}};
+	$anon_fallback{"port"} = $virtual->{"port"};
+
+	return \%anon_fallback;
+}
+
+# fallback_command
+# Execute the fallback command with the given status if it wasn't executed
+# with this status already for the supplied virtual service.
+sub do_fallback_command
+{
+	my ($v, $status) = (@_);
+
+	if (defined $v->{fallbackcommand_status} and $v->{fallbackcommand_status} eq $status) {
+		return;
+	}
+
+	$v->{fallbackcommand_status} = $status;
+
+	if (defined($v->{fallbackcommand})) {
+		&system_wrapper($v->{fallbackcommand} . " " . $status);
+	} elsif (defined($FALLBACKCOMMAND)) {
+		&system_wrapper($FALLBACKCOMMAND . " " . $status);
+	}
+}
+
+# Used during stop, start and reload to remove stale real servers from LVS
+sub purge_untracked_service
+{
+	my ($v, $rservice, $tag) = (@_);
+
+	my $log_arg = "Purged real server ($tag): $rservice (" .
+		      &get_virtual($v) . ")";
+
+	&system_wrapper("$IPVSADM -d $v->{proto} " . &get_virtual_option($v) .
+			" -r $rservice");
+	&ld_log($log_arg);
+	&ld_emailalert_send($log_arg, $v, $rservice, 0);
+}
+
+# Used during stop, start and reload to remove stale real servers from LVS
+sub purge_service
+{
+	my ($v, $r, $tag) = (@_);
+
+	purge_untracked_service($v, "$r->{server}:$r->{port}", $tag);
+	_status_down($v, $r);
+}
+
+# Used during stop, start and reload to remove stale virtual services from LVS
+sub purge_virtual
+{
+	my ($v, $tag) = (@_);
+
+	&system_wrapper("$IPVSADM -D $v->{proto} " .  &get_virtual_option($v));
+	&ld_log("Purged virtual server ($tag): " .  &get_virtual($v));
+}
+
+sub check_cfgfile
+{
+	my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev,
+		$size, $atime, $mtime) = stat($CONFIG);
+	my ($status);
+	return if ($stattime==$mtime);
+	$stattime = $mtime;
+	use Digest::MD5 qw(md5 md5_hex);
+	my $ctx = Digest::MD5->new;
+	unless (open(CFGFILE, "<$CONFIG")) {
+		&config_warn(0, "can not open file $CONFIG for checking");
+		return 0;
+	}
+	$ctx->addfile(*CFGFILE);
+	close(CFGFILE);
+	my $digest = $ctx->hexdigest;
+	if (defined $checksum && $checksum ne $digest) {
+		&ld_log("Configuration file '$CONFIG' has changed on disk");
+		if ($AUTOCHECK eq "yes") {
+			&ld_log(" - reread new configuration");
+			&reread_config();
+		} else {
+			&ld_log(" - ignore new configuration\n");
+		}
+		if (defined($CALLBACK) and -x $CALLBACK) {
+			&system_wrapper("$CALLBACK $CONFIG");
+		}
+		$status = 1;
+	}
+	$checksum = $digest;
+
+	return $status;
+}
+
+# ld_openlog
+# Open logger
+# make log rotation work
+# pre: none
+# post: If logger is a file, it opened and closed again as a test
+#       If logger is syslog, it is opened so it can be used without
+#       needing to be opened again.
+#       Otherwise, nothing is done.
+# return: 0 on success
+#         1 on error
+sub ld_openlog
+{
+	if ($opt_d or $SUPERVISED eq "yes") {
+		# Instantly do nothing
+		return(0);
+	}
+	if( $LDIRLOG =~ /^\/(.*)/ ) {
+		# Open and close the file as a test.
+		# We open the file each time we want to log to it
+		unless (open(LOGFILE, ">>$LDIRLOG") and close(LOGFILE)) {
+			return 1;
+		}
+	}
+	else
+	{
+		# Assume LDIRLOG is a logfacility, log to syslog
+		setlogsock( "unix" );
+		openlog( "ldirectord", "pid", "$LDIRLOG" );
+	}
+	return(0);
+}
+
+# ld_log
+# Log a message.
+# pre: message: Message to write
+# post: message and timetsamp is written to loged
+#       If logger is a file, it is opened and closed again as a
+#       primitive means to make log rotation work
+# return: 0 on success
+#         1 on error
+sub ld_log
+{
+	my ($message) = (@_);
+
+	my $now = localtime();
+
+	&ld_debug(2, $message);
+	chomp $message;
+	if ($opt_d) {
+		print STDERR "$message\n";
+	} elsif ($SUPERVISED eq "yes") {
+		print "[$now] $message\n";
+	} elsif ( $LDIRLOG =~ /^\/(.*)/ ) {
+		unless (open(LOGFILE, ">>$LDIRLOG")
+				and print LOGFILE "[$now|$CFGNAME|$$] $message\n"
+				and close(LOGFILE)) {
+			print STDERR "$message\n";
+			return 1;
+		}
+	}
+	else {
+		# Assume LDIRLOG is a logfacility, log to syslog
+		syslog( "info", "$message" );
+	}
+	return(0);
+}
+
+sub daemon_status_str
+{
+	if ($DAEMON_STATUS == $DAEMON_STATUS_STARTING) {
+		return "starting";
+	}
+	elsif ($DAEMON_STATUS == $DAEMON_STATUS_RUNNING) {
+		return "running";
+	}
+	elsif ($DAEMON_STATUS == $DAEMON_STATUS_STOPPING) {
+		return "stopping";
+	}
+	elsif ($DAEMON_STATUS == $DAEMON_STATUS_RELOADING) {
+		return "reloading";
+	}
+	return "UNKNOWN";
+}
+
+# ld_emailalert_send
+# Send email alerts per virtual server
+# pre: message: Message to email
+# post: message is emailed if emailalert defined for virtualserver
+# return: 0 on success
+#         1 on error
+sub ld_emailalert_send
+{
+	my ($subject, $v, $rserver, $currenttime) = (@_);
+	my $status = 0;
+	my $to_addr;
+	my $frequency;
+	my $virtual_str;
+	my $id;
+	my $statusfilter;
+	my $smtp_server;
+
+	$frequency = defined $v->{emailalertfreq} ?  $v->{emailalertfreq} :
+				$EMAILALERTFREQ;
+
+	$virtual_str = &get_virtual($v);
+	$id = "$rserver ($virtual_str)";
+
+	if ($currenttime == 0 or $frequency == 0) {
+		delete $EMAILSTATUS{"$id"};
+	}
+	else {
+		$EMAILSTATUS{$id}->{v} = $v;
+		$EMAILSTATUS{$id}->{alerttime} = $currenttime;
+	}
+
+	$statusfilter = defined $v->{emailalertstatus} ?
+			$v->{emailalertstatus} : $EMAILALERTSTATUS;
+	if (($DAEMON_STATUS & $statusfilter) == 0) {
+		return 0;
+	}
+
+	$to_addr = defined $v->{emailalert} ? $v->{emailalert} : $EMAILALERT;
+	if ($to_addr eq "") {
+		return 0;
+	}
+
+	$smtp_server = defined $v->{smtp} ? $v->{smtp} :
+				$SMTP;
+
+	&ld_log("emailalert: $subject");
+	if (defined $smtp_server) {
+		$status = &ld_emailalert_net_smtp($smtp_server, $to_addr, $subject);
+	}
+	else {
+		$status = &ld_emailalert_mail_send($to_addr, $subject);
+	}
+
+	return($status);
+}
+
+# ld_emailalert_net_smtp
+# Send email alerts via SMTP server
+# pre: smtp: SMTP server defined
+# post: message is emailed if SMTP server is valid and working
+# return: 0 on success
+#	  1 on error
+sub ld_emailalert_net_smtp
+{
+	my ($smtp_server, $to_addr, $subject) = (@_);
+	my $status = 0;
+
+	use Net::SMTP;
+	use Sys::Hostname;
+
+	my $hostname = hostname;
+
+	my $smtp = Net::SMTP->new($smtp_server);
+
+	if ($smtp) {
+		$smtp->mail("$ENV{USER}\@$hostname");
+		$smtp->to($to_addr);
+		$smtp->data();
+		if($EMAILALERTFROM) {
+			$smtp->datasend("From: $EMAILALERTFROM\n");
+		} else {
+			$smtp->datasend("From: $ENV{USER}\@$hostname\n");
+		}
+		$smtp->datasend("To: $to_addr\n");
+		$smtp->datasend("Subject: $subject\n\n");
+		$smtp->datasend("ldirectord host: $hostname\n" .
+				"Log-Message: $subject\n" .
+				"Daemon-Status: " .
+				&daemon_status_str() . "\n");
+		$smtp->dataend();
+		$smtp->quit;
+	} else {
+		&ld_log("failed to send SMTP email message\n");
+		$status = 1;
+	}
+
+	return($status);
+}
+
+# ld_emailalert_mail_send
+# Send email alerts via Mail::Send
+# pre: smtp: SMTP server not defined
+# post: message is emailed if one of the Mail::Send methods works
+# return: 0 on success
+#	  1 on error
+sub ld_emailalert_mail_send
+{
+	my ($to_addr, $subject) = (@_);
+	my $emailmsg;
+	my $emailfh;
+	my $status = 0;
+
+	use Mail::Send;
+
+	$emailmsg = new Mail::Send Subject=>$subject, To=>$to_addr;
+	$emailmsg->set('From', $EMAILALERTFROM) if ($EMAILALERTFROM);
+	$emailfh = $emailmsg->open;
+	print $emailfh "ldirectord host: " . hostname() . "\n" .
+		       "Log-Message: $subject\n" .
+		       "Daemon-Status: " . &daemon_status_str() . "\n";
+	unless ($emailfh->close) {
+		&ld_log("failed to send email message\n");
+		$status = 1;
+	}
+
+	return($status);
+}
+
+# ld_emailalert_resend
+# Resend email alerts as necessary
+# pre: none
+# post: EMAILSTATUS array is updated and alerts are sent as necessary
+# return: none
+sub ld_emailalert_resend
+{
+	my $currenttime = time();
+	my $es;
+	my $id;
+	my $rserver;
+	my $frequency;
+
+	foreach $id (keys %EMAILSTATUS) {
+		$es = $EMAILSTATUS{$id};
+		$frequency = defined $es->{v}->{emailalertfreq} ?
+					$es->{v}->{emailalertfreq} :
+					$EMAILALERTFREQ;
+		$id =~ m/(.*) /;
+		$rserver = $1;
+		if ($currenttime - $es->{alerttime} < $frequency) {
+			next;
+		}
+		&ld_emailalert_send("Inaccessible real server: $id",
+				    $es->{v}, $rserver, $currenttime);
+	}
+}
+
+# ld_debug
+# Log a message to a STDOUT.
+# pre: priority: priority of message
+#      message: Message to write
+# post: message is written to STDOUT if $DEBUG >= priority
+# return: none
+sub ld_debug
+{
+	my ($priority, $message) = (@_);
+
+	if ( $DEBUG >= $priority ) {
+		chomp $message;
+		print STDERR "DEBUG${priority}: $message\n";
+	}
+}
+
+# system_wrapper
+# Wrapper around system() to log errors
+#
+# WARNING: Do not use alarm() together with this function.  A internal
+# pipe will not be reclaimed (at least with Perl 5.8.8).  This can
+# cause ldirectord to run out of file handles.
+#
+# pre: LIST: arguments to pass to system()
+# post: system() is called and if it returns non-zero a failure
+#       message is logged
+# return: return value of system()
+sub system_wrapper
+{
+	my (@args)=(@_);
+
+	my $status;
+
+	&ld_log("Running system(@args)") if $DEBUG>2;
+	$status = system(@args);
+	if($status != 0) {
+		&ld_log("system(@args) failed: $!");
+	}
+
+	return($status)
+}
+
+# system_timeout
+# Emulate system() with timeout via fork(), exec(), and waitpid() and
+# TERMinate the child on timeout.  Set an alarm() for the timeout.
+#
+# This function does not suffer the deficiencies of system_wrapper()
+# of leaving pipes unreclaimed.  Zombies are reaped by ld_handler_chld
+# and the related code.
+#
+# pre: timeout: timeout in seconds
+#      LIST: arguments to pass to exec()
+# return: >= 0 exit status of the child process
+#          127 exec failed
+#           -1 timeout
+#           -2 fork failed
+sub system_timeout
+{
+	my $timeout = shift;
+	my (@args) = (@_);
+	my $status;
+
+	&ld_log("Running system_timeout($timeout, @args)") if $DEBUG>2;
+
+	my $childpid = fork();
+	if (!defined($childpid)) {
+		&ld_log("fork failed: $!");
+		return(-2);
+        }
+	elsif ($childpid) {
+		# parent
+		eval {
+			local $SIG{'ALRM'} = sub { die "timeout\n"; };
+			alarm $timeout;
+			waitpid($childpid, 0);
+			$status = $? >> 8;
+			# When die()-ing in the SIGALRM handler we
+			# will never reach this point.  Child/Zombie
+			# is left behind.  The grim reaper
+			# (ld_handler_chld + ld_process_chld) will
+			# take care of the zombie.
+		};
+		alarm 0;
+		if ($@) {
+			# timeout
+			if ($@ ne "timeout\n") {
+				# log unexpected errors
+				&ld_log("system_timeout($timeout, @args) " .
+					"unexpected error: $@");
+			}
+			else {
+				&ld_log("system_timeout($timeout, @args) " .
+					"timed out, kill -TERM child");
+			}
+
+			# TERMinate child
+			kill 15, $childpid;
+			return(-1);
+		}
+		else {
+			# did not timeout
+			return($status);
+		}
+	}
+	else {
+		# child
+        	exec(@args) or &ld_exit(127, "exec(@args) failed: $!");
+		die "ld_exit() broken?, stopped";
+        }
+}
+
+# exec_wrapper
+# Wrapper around exec() to log errors
+# pre: LIST: arguments to pass to exec()
+# post: exec() is called and if it returns non-zero a failure
+#       message is logged
+# return: return value of exec() on failure
+#         does not return on success
+sub exec_wrapper
+{
+	my (@args)=(@_);
+
+	my $status;
+
+	&ld_log("Running exec(@args)") if $DEBUG>2;
+	$status = exec(@args) or &ld_log("exec(@args) failed");
+	return($status)
+}
+
+# ld_rm_file
+# Remove a file, symink, or anything that isn't a directory
+# and exists
+# pre: filename: file to delete
+# post: If filename does not exist or is a directory an
+#       error state is reached
+#       Else filename is delete
+#       If $DEBUG >=2 errors are logged
+# return: 0 on success
+#         -1 on error
+sub ld_rm_file
+{
+	my ($filename)=(@_);
+
+	my ($status);
+
+	if(-d "$filename"){
+		&ld_debug(2, "ld_rm_file: $filename is a directory, skipping");
+		return(-1);
+	}
+	if(! -e "$filename"){
+		&ld_debug(2, "ld_rm_file: $filename doesn't exist, skipping");
+		return(-1);
+	}
+	$status = unlink($filename);
+	if($status!=1){
+		&ld_debug(2, "ld_rm_file: Error deleting: $filename: $!");
+	}
+	return(($status==1)?0:-1)
+}
+
+# is_octet
+# See if a number is an octet, that is >=0 and <=255
+# pre: alleged_octet: the octet to test
+# post: alleged_octet is checked to see if it is valid
+# return: 1 if the alleged_octet is an octet
+#         0 otherwise
+sub is_octet
+{
+	my ($alleged_octet)=(@_);
+
+	if($alleged_octet<0){ return 0; }
+	if($alleged_octet>255){ return 0; }
+
+	return(1);
+}
+
+# is_ip
+# Check that a given string is an IP address
+# pre: alleged_ip: string representing ip address
+# post: alleged_ip is checked to see if it is valid
+# return: 1 if alleged_ip is a valid ip address
+#         0 otherwise
+sub is_ip
+{
+	my ($alleged_ip)=(@_);
+
+	if ($alleged_ip =~ /:/) {
+		unless(inet_pton(AF_INET6,$alleged_ip)){ return 0; }
+		return(1);
+	}
+
+	#If we don't have four, . delimited numbers then we have no hope
+	unless($alleged_ip=~m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { return 0; }
+
+	#Each octet mist be >=0 and <=255
+	unless(&is_octet($1)){ return 0; }
+	unless(&is_octet($2)){ return 0; }
+	unless(&is_octet($3)){ return 0; }
+	unless(&is_octet($4)){ return 0; }
+
+	return(1);
+}
+
+# ip_to_int
+# Turn an IP address given as a dotted quad into an integer
+# pre: ip_address: string representing IP address
+# post: post ip_address is converted to an integer
+# return: -1 if an error occurs
+#         integer representation of IP address otherwise
+sub ip_to_int
+{
+	my ($ip_address)=(@_);
+
+	unless(&is_ip($ip_address)){ return(-1); }
+	unless($ip_address=~m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/){ return(-1); }
+
+	return(((((($1<<8)+$2)<<8)+$3)<<8)+$4);
+}
+
+# int_to_ip
+# Turn an IP address given as a dotted quad into an integer
+# pre: ip_address: string representing IP address
+# post: Decimal is converted to a dotted quad
+# return: -1 if an error occurs
+#        integer representation of IP address otherwise
+sub int_to_ip
+{
+	my ($ip_address)=(@_);
+
+	my $result = "";
+
+	return(sprintf(
+		"%d.%d.%d.%d",
+		($ip_address>>24)&255,
+		($ip_address>>16)&255,
+		($ip_address>>8)&255,
+		$ip_address&255
+	));
+}
+
+# get_virtual
+# Get the service for a virtual
+# pre: nv: virtual to get the service for
+# post: none
+# return: fwmark of service if it is a fwm service
+#         ip_address:port otherwise
+sub get_virtual
+{
+	my ($nv) = (@_);
+
+	if ($nv->{"protocol"} eq "fwm"){
+		return $nv->{"fwm"};
+	} else {
+		return $nv->{"server"} . ":" . $nv->{"port"};
+	}
+}
+
+# get_virtual_option
+# Get the ipvsadm option corresponding to a virtual service
+# pre: nv: virtual to get the service for
+# post: none
+# return: fwmark of service if it is a fwm service
+#         fwmark of service + "-6" if it is a fwm service and the address family is AF_INET6
+#         ip_address:port otherwise
+sub get_virtual_option
+{
+	my ($nv) = (@_);
+
+	my ($cmdline) = &get_virtual($nv);
+
+	if ($nv->{"protocol"} eq "fwm" && $nv->{addressfamily} == AF_INET6) {
+		$cmdline .=  " -6";
+	}
+	
+	return $cmdline;
+}
+
+# get_real_id_str
+# Get an id string for a real server
+# pre: r: Real service.
+#      protocol: protocol of the real service
+#                tcp or udp
+#      service: type of service
+# post: none
+# return: Id string for the real server
+sub get_real_id_str
+{
+	my ($r, $v) = (@_);
+
+	my $request = "";
+	my $receive = "";
+	my $checkport = "";
+	my $virtualhost = "";
+	my $check;
+	my $real;
+
+	if(defined($r->{"request"})) {
+		$request = $r->{"request"};
+	}
+	else {
+		$request = $v->{"request"};
+	}
+
+	if(defined($r->{"receive"})) {
+		$receive = $r->{"receive"};
+	}
+	else {
+		$receive = $v->{"receive"};
+	}
+
+	if($v->{"checktype"} eq "negotiate" or
+			$v->{"checktype"} eq "combined") {
+		$check = $v->{"checktype"} . ":" . $v->{"service"};
+	}
+	elsif($v->{"checktype"} eq "external" or
+			$v->{"checktype"} eq "external-perl") {
+		$check = $v->{"checktype"} . ":" . $v->{"checkcommand"};
+	}
+	else {
+		$check = $v->{"checktype"};
+	}
+
+	if(defined($v->{"checkport"})) {
+		$checkport = $v->{"checkport"};
+	}
+
+	if(defined($v->{"virtualhost"})) {
+		$virtualhost = $v->{"virtualhost"};
+	}
+
+	$real    = $check . ":" . $v->{"protocol"} . ":"
+		 . $r->{"server"} . ":" . $r->{"port"} . ":"
+		 . $virtualhost . ":" . $checkport . ":"
+		 . $r->{"weight"} . ":" . $r->{"forward"} . ":"
+		 . quotemeta($request) . ":" . quotemeta($receive);
+}
+
+# get_virtual_id_str
+# Get an id string for a virtual service
+# pre: v: Virtual service
+# post: none
+# return: Id string for the virtual service
+sub get_virtual_id_str
+{
+	my ($v) = (@_);
+
+	if ($v->{"protocol"} eq "fwm") {
+		return $v->{"protocol"} . (($v->{addressfamily} == AF_INET6)?"6":"") . ":" .  &get_virtual($v);
+	}
+	else {
+		return $v->{"protocol"} . ":" .  &get_virtual($v);
+	}
+}
+
+# get_forward_flag
+# Get the ipvsadm flag corresponding to a forwarding mechanism
+# pre: forward: Name of forwarding mechanism. u
+#               Should be one of ipip, masq or gate
+# post: none
+# return: ipvsadm flag corresponding to the forwarding mechanism
+#         " " if $forward is unknown
+sub get_forward_flag
+{
+	my ($forward) = (@_);
+
+	unless(defined($forward)) {
+		return(" ");
+	}
+
+	if ($forward eq "masq") {
+		return("-m");
+	}
+	elsif ($forward eq "gate") {
+		return("-g");
+	}
+	elsif ($forward eq "ipip") {
+		return("-i");
+	}
+
+	return(" ");
+}
+
+# ld_exit
+# Exit and log a message
+# pre: exit_status: Integer exit status to exit with
+#                   0 will be used if parameter is omitted
+#      message: Message to log when exiting. May be omitted
+# post: If exit_status is non-zero or $DEBUG>2 then
+#       message logged.
+#       Programme exits with exit_status
+# return: does not return
+sub ld_exit
+{
+	my ($exit_status, $message)=(@_);
+	unless(defined($exit_status)) { $exit_status=0; }
+	unless(defined($message)) { $message=""; }
+
+	if ($exit_status!=0 or $DEBUG>2) {
+		&ld_log("Exiting with exit_status $exit_status: $message");
+	}
+	exit($exit_status);
+}
+
+# ld_open_socket
+# Open a socket connection
+# pre: remote: IP address as a dotted quad of remote host to connect to
+#      port: port to connect to
+#      protocol: Protocol to use. Should be either "tcp" or "udp"
+# post: A Socket connection is opened to the remote host
+# return: Open socket
+#         undef on error
+sub ld_open_socket
+{
+	my ($remote, $port, $protocol) = @_;
+	my ($iaddr, $paddr, $pro, $result, $pf);
+	local *SOCK;
+
+	$remote = &ld_strip_brackets($remote);
+	if (inet_pton(AF_INET6,$remote)) {
+		$iaddr = inet_pton(AF_INET6,$remote);
+		$paddr = pack_sockaddr_in6($port, $iaddr);
+		$pf = PF_INET6;
+	} else {
+		$iaddr = inet_aton($remote) || die "no host: $remote";
+		$paddr = sockaddr_in($port, $iaddr);
+		$pf = PF_INET;
+	}
+	$pro = getprotobyname($protocol);
+	if ($protocol eq "udp") {
+		socket(SOCK, $pf, SOCK_DGRAM, $pro) || die "socket: $!";
+	}
+	else {
+		socket(SOCK, $pf, SOCK_STREAM, $pro) || die "socket: $!";
+	}
+	$result = connect(SOCK, $paddr);
+	unless ($result) {
+		return undef;
+	}
+	return *SOCK;
+}
+
+# daemon
+# Close and fork to become a daemon.
+#
+# Notes from unix programmer faq
+# http://www.landfield.com/faqs/unix-faq/programmer/faq/
+#
+# Almost none of this is necessary (or advisable) if your daemon is being
+# started by `inetd'.  In that case, stdin, stdout and stderr are all set up
+# for you to refer to the network connection, and the `fork()'s and session
+# manipulation should *not* be done (to avoid confusing `inetd').  Only the
+# `chdir()' step remains useful.
+#
+# Gratuitously over documented, because it can be
+#
+# Written by Horms, horms at verge.net.au for an unrelated project while
+# working for Zip World, http://www.zipworld.com.au/, 1997-1999.
+sub ld_daemon
+{
+	# `fork()' so the parent can exit, this returns control to the command
+	# line or shell invoking your program.  This step is required so that
+	# the new process is guaranteed not to be a process group leader. The
+	# next step, `setsid()', fails if you're a process group leader.
+	&ld_daemon_become_child();
+
+	# setsid()' to become a process group and session group leader. Since a
+	# controlling terminal is associated with a session, and this new
+	# session has not yet acquired a controlling terminal our process now
+	# has no controlling terminal, which is a Good Thing for daemons.
+	if(POSIX::setsid()<0){
+		&ld_exit(1, "ld_daemon: Could not setsid");
+	}
+
+	# fork()' again so the parent, (the session group leader), can exit.
+	# This means that we, as a non-session group leader, can never regain a
+	# controlling terminal.
+	&ld_daemon_become_child();
+
+	# `chdir("/")' to ensure that our process doesn't keep any directory in
+	# use. Failure to do this could make it so that an administrator
+	# couldn't unmount a filesystem, because it was our current directory.
+	if(chdir("/")<0){
+		&ld_exit(1, "ld_daemon: Could not chdir");
+	}
+
+	# `close()' fds 0, 1, and 2. This releases the standard in, out, and
+	# error we inherited from our parent process. We have no way of knowing
+	# where these fds might have been redirected to. Note that many daemons
+	# use `sysconf()' to determine the limit `_SC_OPEN_MAX'.  `_SC_OPEN_MAX'
+	# tells you the maximum open files/process. Then in a loop, the daemon
+	# can close all possible file descriptors. You have to decide if you
+	# need to do this or not.  If you think that there might be
+	# file-descriptors open you should close them, since there's a limit on
+	# number of concurrent file descriptors.
+	close(STDIN);
+	close(STDOUT);
+	close(STDERR);
+
+	# Establish new open descriptors for stdin, stdout and stderr. Even if
+	# you don't plan to use them, it is still a good idea to have them open.
+	# The precise handling of these is a matter of taste; if you have a
+	# logfile, for example, you might wish to open it as stdout or stderr,
+	# and open `/dev/null' as stdin; alternatively, you could open
+	# `/dev/console' as stderr and/or stdout, and `/dev/null' as stdin, or
+	# any other combination that makes sense for your particular daemon.
+	#
+	# This code used to open /dev/console for STDOUT and STDERR,
+	# but that was changed to /dev/null to stop the code hanging in
+	# the case where /dev/console is unavailable for some reason
+	# http://www.osdl.org/developer_bugzilla/show_bug.cgi?id=1180
+	if(open(STDIN, "</dev/null")<0){
+		&ld_exit(1, "ld_daemon: Could not open /dev/null");
+	}
+	if(open(STDOUT, ">>/dev/null")<0){
+		&ld_exit(-1, "ld_daemon: Could not open /dev/null");
+	}
+	if(open(STDERR, ">>/dev/null")<0){
+		&ld_exit(-1, "ld_daemon: Could not open /dev/null");
+	}
+}
+
+# ld_daemon_become_child
+# Fork, kill parent and return child process
+# pre: none
+# post: process forks and parent exits
+#       All process exit with exit status -1 if an error occurs
+# return: parent: exits
+#         child: none  (this is the process that returns)
+# Written by Horms, horms at verge.net.au for an unrelated project while
+# working for Zip World, http://www.zipworld.com.au/, 1997-1999.
+sub ld_daemon_become_child
+{
+	my($status);
+
+	$status = fork();
+
+	if ($status<0){
+		&ld_exit(-1, "ld_daemon_become_child: Could not fork: $!");
+	}
+	if ($status>0){
+		&ld_exit(0,
+			"ld_daemon_become_child: Parent exiting as it should");
+	}
+}
+
+# ld_gethostbyname
+# Wrapper to gethostbyname. Look up the/an IP address of a hostname
+# If an IP address is given is it returned
+# pre: name: Hostname of IP address to lookup
+#      af: Address Family: AF_INET etc..
+# post: gethostbyname is called to find an IP address for $name
+#       This is converted to a string
+# return: IP address
+#         undef on error
+sub ld_gethostbyname
+{
+	my ($name, $af)=(@_);
+
+	if ($name =~ /\[(.*)\]/) {
+		$name = $1;
+	}
+	my @host = getaddrinfo($name, 0, $af);
+	if (!defined($host[3])) {
+		return undef;
+	}
+	my @ret = getnameinfo($host[3], NI_NUMERICHOST | NI_NUMERICSERV);
+	if ($host[0] == AF_INET6) {
+		return "[$ret[0]]";
+	}
+	else {
+		return $ret[0];
+	}
+}
+
+# ld_gethostbyaddr
+# Wrapper to gethostbyaddr. Look up the hostname from an IP address.
+# If no reverse DNS record is found, return undef
+# pre: ip: IP address of host to lookup
+# post: gethostbyaddr is called to find a hostname for IP $ip
+# return: hostname
+#         undef on error
+sub ld_gethostbyaddr
+{
+	my ($ip)=(@_);
+
+	$ip = &ld_strip_brackets($ip);
+	my @host = getaddrinfo($ip,0);
+	if (!defined($host[3])) {
+		return undef;
+	}
+	my @ret = getnameinfo($host[3], NI_NAMEREQD);
+	return undef unless(scalar(@ret) == 2);
+	return $ret[0];
+}
+
+# ld_getservbyname
+# Wrapper for getservbyname. Look up the port for a service name
+# If a port is given it is returned.
+# pre: name: Port or Service name to look up
+# post: if $name is a number
+#         if 0<=$name<=65536 $name is returned
+#         else undef is returned
+#       else getservbyname is called to look up the port for the service
+# return: Port
+#         undef on error
+sub ld_getservbyname
+{
+	my ($name, $protocol)=(@_);
+
+	if($name=~/^[0-9]+$/){
+		return(($name>=0 and $name<65536)?$name:undef);
+	}
+
+	my @serv=getservbyname($name, $protocol);
+
+	return((@serv and defined($serv[2]))?$serv[2]:undef);
+}
+
+# ld_getservhostbyname
+# Wrapper for ld_gethostbyname and ld_getservbyname. Given a server of the
+# form ip_address|hostname[:port|servicename] return ip_address[:port]
+# pre: hostserv: Servver of the form ip_address|hostname[:port|servicename]
+#      protocol: Protocol for service. Should be either "tcp" or "udp"
+#      af: Address Family: AF_INET etc..
+# post: lookups performed as per ld_getservbyname and ld_gethostbyname
+# return: ip_address[:port]
+#         undef on error
+sub ld_gethostservbyname{
+	my ($hostserv, $protocol, $af) = (@_);
+
+	my $ip;
+	my $port;
+	
+	if ($hostserv =~ /(:(\d+|[A-Za-z0-9-_]+))?$/) {
+		$port = $2;
+		$ip = $hostserv;
+		$ip =~ s/(:(\d+|[A-Za-z0-9-_]+))?$//;
+	} else {
+		$ip = $hostserv;
+	}
+	$ip=&ld_gethostbyname($ip, $af)  or return(undef);
+
+	if(defined($port)){
+		$port=&ld_getservbyname($port, $protocol);
+		if (defined($port)) {
+			return("$ip:$port");
+		} else {
+			return(undef);
+		}
+	}
+	return($ip);
+}
+
+# ld_find_cmd_path
+# Find executable in path
+# pre: cmd: command to find
+#      path: ':' delimited paths to check
+#      relative: if set, allow cmd to be a relative path,
+#                which is checked first
+# return: path to command
+#         undef if not found
+sub ld_find_cmd_path
+{
+	my ($cmd, $path, $relative) = (@_);
+
+	if (defined $relative  and $relative and -f "$cmd" ) {
+		return $cmd;
+	}
+	if ($cmd =~ /^\// and -x "$cmd" ) {
+		return $cmd;
+	}
+	if ($cmd =~ /\//) {
+		return undef;
+	}
+
+	for my $p (split /:/, $path) {
+		if ( -x "$p/$cmd" ) {
+			return "$p/$cmd";
+		}
+	}
+	return undef;
+}
+
+# ld_find_cmd_path
+# Find executable in $ENV{'PATH'}
+# pre: cmd: command to find
+#      relative: if set, allow cmd to be a relative path,
+#                which is checked first
+# return: path to command
+#         undef if not found
+sub ld_find_cmd
+{
+	return ld_find_cmd_path($_[0], $ENV{'PATH'}, $_[1]);
+}
+
+# ld_get_addrport
+# Get address string and port number from a given socket.
+# pre: socket
+# return: (address, port)
+#         undef if cannot get
+sub ld_get_addrport
+{
+	my($sock) = @_;
+
+	my ($s_addr_str, $s_port, $s_addr, $len);
+
+	my $s_sockaddr = getsockname($sock);
+	$len = length($s_sockaddr);
+	if ($len == 28) {	# IPv6
+		($s_port, $s_addr) = unpack_sockaddr_in6($s_sockaddr);
+		$s_addr_str = inet_ntop(AF_INET6, $s_addr);
+		$s_addr_str = "[$s_addr_str]";
+	}
+	elsif ($len == 16) {	# IPv4
+		($s_port, $s_addr) = unpack_sockaddr_in($s_sockaddr);
+		$s_addr_str = inet_ntop(AF_INET, $s_addr);
+	}
+	else {
+		die "unexpected length of sockaddr\n";
+	}
+
+	return ($s_addr_str, $s_port);
+}
+
+# ld_strip_brackets
+# Strip brackets in the string
+# pre: string
+# return: string
+sub ld_strip_brackets
+{
+	my($str) = @_;
+
+	$str =~ s/[\[\]]//g;
+
+	return $str;
+}
diff --git a/ldirectord/logrotate.d/Makefile.am b/ldirectord/logrotate.d/Makefile.am
new file mode 100644
index 0000000..87cbdd7
--- /dev/null
+++ b/ldirectord/logrotate.d/Makefile.am
@@ -0,0 +1,26 @@
+#
+# ldirectord: Linux-HA heartbeat code
+#
+# Copyright (C) 2001 Michael Moerz
+#
+# 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              = ldirectord
+
+logrotatedir		= $(sysconfdir)/logrotate.d
+
+logrotate_DATA       	= ldirectord
diff --git a/ldirectord/logrotate.d/ldirectord b/ldirectord/logrotate.d/ldirectord
new file mode 100644
index 0000000..fb05ae8
--- /dev/null
+++ b/ldirectord/logrotate.d/ldirectord
@@ -0,0 +1,3 @@
+/var/log/ldirectord.log {
+    missingok
+}
diff --git a/make/git-version-gen b/make/git-version-gen
new file mode 100755
index 0000000..795a98b
--- /dev/null
+++ b/make/git-version-gen
@@ -0,0 +1,161 @@
+#!/bin/sh
+# Print a version string.
+scriptversion=2010-10-13.20; # UTC
+
+# Copyright (C) 2007-2010 Free Software Foundation, Inc.
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+
+# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
+# It may be run two ways:
+# - from a git repository in which the "git describe" command below
+#   produces useful output (thus requiring at least one signed tag)
+# - from a non-git-repo directory containing a .tarball-version file, which
+#   presumes this script is invoked like "./git-version-gen .tarball-version".
+
+# In order to use intra-version strings in your project, you will need two
+# separate generated version string files:
+#
+# .tarball-version - present only in a distribution tarball, and not in
+#   a checked-out repository.  Created with contents that were learned at
+#   the last time autoconf was run, and used by git-version-gen.  Must not
+#   be present in either $(srcdir) or $(builddir) for git-version-gen to
+#   give accurate answers during normal development with a checked out tree,
+#   but must be present in a tarball when there is no version control system.
+#   Therefore, it cannot be used in any dependencies.  GNUmakefile has
+#   hooks to force a reconfigure at distribution time to get the value
+#   correct, without penalizing normal development with extra reconfigures.
+#
+# .version - present in a checked-out repository and in a distribution
+#   tarball.  Usable in dependencies, particularly for files that don't
+#   want to depend on config.h but do want to track version changes.
+#   Delete this file prior to any autoconf run where you want to rebuild
+#   files to pick up a version string change; and leave it stale to
+#   minimize rebuild time after unrelated changes to configure sources.
+#
+# It is probably wise to add these two files to .gitignore, so that you
+# don't accidentally commit either generated file.
+#
+# Use the following line in your configure.ac, so that $(VERSION) will
+# automatically be up-to-date each time configure is run (and note that
+# since configure.ac no longer includes a version string, Makefile rules
+# should not depend on configure.ac for version updates).
+#
+# AC_INIT([GNU project],
+#         m4_esyscmd([build-aux/git-version-gen .tarball-version]),
+#         [bug-project at example])
+#
+# Then use the following lines in your Makefile.am, so that .version
+# will be present for dependencies, and so that .tarball-version will
+# exist in distribution tarballs.
+#
+# BUILT_SOURCES = $(top_srcdir)/.version
+# $(top_srcdir)/.version:
+#	echo $(VERSION) > $@-t && mv $@-t $@
+# dist-hook:
+#	echo $(VERSION) > $(distdir)/.tarball-version
+
+case $# in
+    1|2) ;;
+    *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version" \
+         '[TAG-NORMALIZATION-SED-SCRIPT]'
+       exit 1;;
+esac
+
+tarball_version_file=$1
+tag_sed_script="${2:-s/x/x/}"
+nl='
+'
+
+# Avoid meddling by environment variable of the same name.
+v=
+
+# First see if there is a tarball-only version file.
+# then try "git describe", then default.
+if test -f $tarball_version_file
+then
+    v=`cat $tarball_version_file` || exit 1
+    case $v in
+	*$nl*) v= ;; # reject multi-line output
+	[0-9]*) ;;
+	*) v= ;;
+    esac
+    test -z "$v" \
+	&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
+fi
+
+if test -n "$v"
+then
+    : # use $v
+# Otherwise, if there is at least one git commit involving the working
+# directory, and "git describe" output looks sensible, use that to
+# derive a version string.
+elif test "`git log -1 --pretty=format:x . 2>&1`" = x \
+    && v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
+	  || git describe --abbrev=4 HEAD 2>/dev/null` \
+    && v=`printf '%s\n' "$v" | sed "$tag_sed_script"` \
+    && case $v in
+	 v[0-9]*) ;;
+	 *) (exit 1) ;;
+       esac
+then
+    # Is this a new git that lists number of commits since the last
+    # tag or the previous older version that did not?
+    #   Newer: v6.10-77-g0f8faeb
+    #   Older: v6.10-g0f8faeb
+    case $v in
+	*-*-*) : git describe is okay three part flavor ;;
+	*-*)
+	    : git describe is older two part flavor
+	    # Recreate the number of commits and rewrite such that the
+	    # result is the same as if we were using the newer version
+	    # of git describe.
+	    vtag=`echo "$v" | sed 's/-.*//'`
+	    numcommits=`git rev-list "$vtag"..HEAD | wc -l`
+	    v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
+	    ;;
+    esac
+
+    # Change the first '-' to a '.', so version-comparing tools work properly.
+    # Remove the "g" in git describe's output string, to save a byte.
+    v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
+else
+    v=UNKNOWN
+fi
+
+v=`echo "$v" |sed 's/^v//'`
+
+# Don't declare a version "dirty" merely because a time stamp has changed.
+git update-index --refresh > /dev/null 2>&1
+
+dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
+case "$dirty" in
+    '') ;;
+    *) # Append the suffix only if there isn't one already.
+	case $v in
+	  *-dirty) ;;
+	  *) v="$v-dirty" ;;
+	esac ;;
+esac
+
+# Omit the trailing newline, so that m4_esyscmd can use the result directly.
+echo "$v" | tr -d "$nl"
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/make/gitlog-to-changelog b/make/gitlog-to-changelog
new file mode 100755
index 0000000..7660af5
--- /dev/null
+++ b/make/gitlog-to-changelog
@@ -0,0 +1,191 @@
+eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
+  & eval 'exec perl -wS "$0" $argv:q'
+    if 0;
+# Convert git log output to ChangeLog format.
+
+my $VERSION = '2009-10-30 13:46'; # UTC
+# The definition above must lie within the first 8 lines in order
+# for the Emacs time-stamp write hook (at end) to update it.
+# If you change this file with Emacs, please let the write hook
+# do its job.  Otherwise, update this string manually.
+
+# Copyright (C) 2008-2010 Free Software Foundation, Inc.
+
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+
+# Written by Jim Meyering
+
+use strict;
+use warnings;
+use Getopt::Long;
+use POSIX qw(strftime);
+
+(my $ME = $0) =~ s|.*/||;
+
+# use File::Coda; # http://meyering.net/code/Coda/
+END {
+  defined fileno STDOUT or return;
+  close STDOUT and return;
+  warn "$ME: failed to close standard output: $!\n";
+  $? ||= 1;
+}
+
+sub usage ($)
+{
+  my ($exit_code) = @_;
+  my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
+  if ($exit_code != 0)
+    {
+      print $STREAM "Try `$ME --help' for more information.\n";
+    }
+  else
+    {
+      print $STREAM <<EOF;
+Usage: $ME [OPTIONS] [ARGS]
+
+Convert git log output to ChangeLog format.  If present, any ARGS
+are passed to "git log".  To avoid ARGS being parsed as options to
+$ME, they may be preceded by '--'.
+
+OPTIONS:
+
+   --since=DATE convert only the logs since DATE;
+                  the default is to convert all log entries.
+   --format=FMT set format string for commit subject and body;
+                  see 'man git-log' for the list of format metacharacters;
+                  the default is '%s%n%b%n'
+
+   --help       display this help and exit
+   --version    output version information and exit
+
+EXAMPLE:
+
+  $ME --since=2008-01-01 > ChangeLog
+  $ME -- -n 5 foo > last-5-commits-to-branch-foo
+
+EOF
+    }
+  exit $exit_code;
+}
+
+# If the string $S is a well-behaved file name, simply return it.
+# If it contains white space, quotes, etc., quote it, and return the new string.
+sub shell_quote($)
+{
+  my ($s) = @_;
+  if ($s =~ m![^\w+/.,-]!)
+    {
+      # Convert each single quote to '\''
+      $s =~ s/\'/\'\\\'\'/g;
+      # Then single quote the string.
+      $s = "'$s'";
+    }
+  return $s;
+}
+
+sub quoted_cmd(@)
+{
+  return join (' ', map {shell_quote $_} @_);
+}
+
+{
+  my $since_date = '1970-01-01 UTC';
+  my $format_string = '%s%n%b%n';
+  GetOptions
+    (
+     help => sub { usage 0 },
+     version => sub { print "$ME version $VERSION\n"; exit },
+     'since=s' => \$since_date,
+     'format=s' => \$format_string,
+    ) or usage 1;
+
+  my @cmd = (qw (git log --log-size), "--since=$since_date",
+             '--pretty=format:%ct  %an  <%ae>%n%n'.$format_string, @ARGV);
+  open PIPE, '-|', @cmd
+    or die ("$ME: failed to run `". quoted_cmd (@cmd) ."': $!\n"
+            . "(Is your Git too old?  Version 1.5.1 or later is required.)\n");
+
+  my $prev_date_line = '';
+  while (1)
+    {
+      defined (my $in = <PIPE>)
+        or last;
+      $in =~ /^log size (\d+)$/
+        or die "$ME:$.: Invalid line (expected log size):\n$in";
+      my $log_nbytes = $1;
+
+      my $log;
+      my $n_read = read PIPE, $log, $log_nbytes;
+      $n_read == $log_nbytes
+        or die "$ME:$.: unexpected EOF\n";
+
+      my @line = split "\n", $log;
+      my $author_line = shift @line;
+      defined $author_line
+        or die "$ME:$.: unexpected EOF\n";
+      $author_line =~ /^(\d+)  (.*>)$/
+        or die "$ME:$.: Invalid line "
+          . "(expected date/author/email):\n$author_line\n";
+
+      my $date_line = sprintf "%s  $2\n", strftime ("%F", localtime ($1));
+      # If this line would be the same as the previous date/name/email
+      # line, then arrange not to print it.
+      if ($date_line ne $prev_date_line)
+        {
+          $prev_date_line eq ''
+            or print "\n";
+          print $date_line;
+        }
+      $prev_date_line = $date_line;
+
+      # Omit "Signed-off-by..." lines.
+      @line = grep !/^Signed-off-by: .*>$/, @line;
+
+      # If there were any lines
+      if (@line == 0)
+        {
+          warn "$ME: warning: empty commit message:\n  $date_line\n";
+        }
+      else
+        {
+          # Remove leading and trailing blank lines.
+          while ($line[0] =~ /^\s*$/) { shift @line; }
+          while ($line[$#line] =~ /^\s*$/) { pop @line; }
+
+          # Prefix each non-empty line with a TAB.
+          @line = map { length $_ ? "\t$_" : '' } @line;
+
+          print "\n", join ("\n", @line), "\n";
+        }
+
+      defined ($in = <PIPE>)
+        or last;
+      $in ne "\n"
+        and die "$ME:$.: unexpected line:\n$in";
+    }
+
+  close PIPE
+    or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n";
+  # FIXME-someday: include $PROCESS_STATUS in the diagnostic
+}
+
+# Local Variables:
+# mode: perl
+# indent-tabs-mode: nil
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "my $VERSION = '"
+# time-stamp-format: "%:y-%02m-%02d %02H:%02M"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "'; # UTC"
+# End:
diff --git a/make/release.mk b/make/release.mk
new file mode 100644
index 0000000..f8cf5b2
--- /dev/null
+++ b/make/release.mk
@@ -0,0 +1,73 @@
+# to build official release tarballs, handle tagging and publish.
+
+# signing key
+gpgsignkey=0x6CE95CA7
+
+project=resource-agents
+
+all: checks setup tag tarballs sha256 sign
+
+checks:
+ifeq (,$(version))
+	@echo ERROR: need to define version=
+	@exit 1
+endif
+	@if [ ! -d .git ]; then \
+		echo This script needs to be executed from top level cluster git tree; \
+		exit 1; \
+	fi
+
+setup: checks
+	./autogen.sh
+	./configure
+	make maintainer-clean
+
+tag: setup ./tag-$(version)
+
+tag-$(version):
+ifeq (,$(release))
+	@echo Building test release $(version), no tagging
+else
+	git tag -a -m "v$(version) release" v$(version) HEAD
+	@touch $@
+endif
+
+tarballs: tag
+	./autogen.sh
+	./configure
+	make distcheck
+
+sha256: tarballs $(project)-$(version).sha256
+
+$(project)-$(version).sha256:
+ifeq (,$(release))
+	@echo Building test release $(version), no sha256
+else
+	sha256sum $(project)-$(version)*tar* | sort -k2 > $@
+endif
+
+sign: sha256 $(project)-$(version).sha256.asc
+
+$(project)-$(version).sha256.asc: $(project)-$(version).sha256
+ifeq (,$(release))
+	@echo Building test release $(version), no sign
+else
+	gpg --default-key $(gpgsignkey) \
+		--detach-sign \
+		--armor \
+		$<
+endif
+
+publish:
+ifeq (,$(release))
+	@echo Building test release $(version), no publishing!
+else
+	git push --tags origin
+	scp $(project)-$(version).* \
+		fedorahosted.org:$(project)
+	@echo Hey you!.. yeah you looking somewhere else!
+	@echo remember to update the wiki and send the email to cluster-devel and linux-cluster
+endif
+
+clean:
+	rm -rf $(project)*.tar.* $(project)*.sha* tag-*
diff --git a/resource-agents.spec.in b/resource-agents.spec.in
new file mode 100644
index 0000000..64557db
--- /dev/null
+++ b/resource-agents.spec.in
@@ -0,0 +1,306 @@
+#
+# All modifications and additions to the file contributed by third parties
+# remain the property of their copyright owners, unless otherwise agreed
+# upon. The license for this file, and modifications and additions to the
+# file, is the same license as for the pristine package itself (unless the
+# license for the pristine package is not an Open Source License, in which
+# case the license is the MIT License). An "Open Source License" is a
+# license that conforms to the Open Source Definition (Version 1.9)
+# published by the Open Source Initiative.
+#
+
+%global rcver @rcver@
+%global alphatag @alphatag@
+%global numcomm @numcomm@
+%global dirty @dirty@
+
+# 
+# Since this spec file supports multiple distributions, ensure we
+# use the correct group for each.
+#
+
+# SSLeay (required by ldirectord)
+%if 0%{?suse_version}
+%global SSLeay perl-Net_SSLeay
+%else
+%global SSLeay perl-Net-SSLeay
+%endif
+
+# determine the ras-set to process based on configure invokation
+%bcond_ at rgmanager@ rgmanager
+%bcond_ at linux-ha@ linuxha
+
+Name:		resource-agents
+Summary:	Open Source HA Reusable Cluster Resource Scripts
+Version:	@version@
+Release:	@specver@%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist}
+License:	GPLv2+ and LGPLv2+
+URL:		https://github.com/ClusterLabs/resource-agents
+%if 0%{?fedora} || 0%{?centos_version} || 0%{?rhel}
+Group:		System Environment/Base
+%else
+Group:		Productivity/Clustering/HA
+%endif
+Source0:	%{name}-%{version}%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}.tar.bz2
+Obsoletes:	heartbeat-resources <= %{version}
+Provides:	heartbeat-resources = %{version}
+
+## Setup/build bits
+BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
+
+# Build dependencies
+BuildRequires: automake autoconf pkgconfig
+BuildRequires: perl python-devel
+BuildRequires: libxslt glib2-devel
+BuildRequires: which
+
+%if 0%{?fedora} || 0%{?centos_version} || 0%{?rhel}
+BuildRequires: cluster-glue-libs-devel
+BuildRequires: docbook-style-xsl docbook-dtds
+%if 0%{?rhel} == 0
+BuildRequires: libnet-devel
+%endif
+%endif
+
+%if 0%{?suse_version}  
+%if 0%{?suse_version} >= 1140
+BuildRequires:  libnet1
+%else
+BuildRequires:  libnet
+%endif
+BuildRequires:  libglue-devel
+BuildRequires:  libxslt docbook_4 docbook-xsl-stylesheets
+%endif
+
+## Runtime deps
+## These apply to rgmanager agents only to guarantee agents
+## are functional
+%if %{with rgmanager}
+# system tools shared by several agents
+Requires: /bin/bash /bin/grep /bin/sed /bin/gawk
+Requires: /bin/ps /usr/bin/pkill /bin/hostname
+Requires: /sbin/fuser
+Requires: /sbin/findfs /bin/mount
+
+# fs.sh
+Requires: /sbin/quotaon /sbin/quotacheck
+Requires: /sbin/fsck
+Requires: /sbin/fsck.ext2 /sbin/fsck.ext3 /sbin/fsck.ext4
+Requires: /sbin/fsck.xfs
+
+# ip.sh
+Requires: /sbin/ip /usr/sbin/ethtool
+Requires: /sbin/rdisc /usr/sbin/arping /bin/ping /bin/ping6
+
+# lvm.sh
+Requires: /sbin/lvm
+
+# netfs.sh
+Requires: /sbin/mount.nfs /sbin/mount.nfs4 /sbin/mount.cifs
+Requires: /usr/sbin/rpc.nfsd /sbin/rpc.statd /usr/sbin/rpc.mountd
+%endif
+
+%description
+A set of scripts to interface with several services to operate in a
+High Availability environment for both Pacemaker and rgmanager
+service managers.
+
+%if %{with linuxha}
+%package -n ldirectord
+License:	GPLv2+
+Summary:	A Monitoring Daemon for Maintaining High Availability Resources
+%if 0%{?fedora} || 0%{?centos_version} || 0%{?rhel}
+Group:		System Environment/Daemons
+%else
+Group:		Productivity/Clustering/HA
+%endif
+Obsoletes:	heartbeat-ldirectord <= %{version}
+Provides:	heartbeat-ldirectord = %{version}
+%if 0%{?fedora} > 18 || 0%{?centos_version} > 6 || 0%{?rhel} > 6
+BuildRequires: perl-podlators
+%endif
+Requires:       %{SSLeay} perl-libwww-perl perl-MailTools
+Requires:       ipvsadm logrotate
+%if 0%{?fedora_version}
+Requires:	perl-Net-IMAP-Simple-SSL
+Requires(post):	/sbin/chkconfig
+Requires(preun):/sbin/chkconfig
+%endif
+
+%description -n ldirectord
+The Linux Director Daemon (ldirectord) was written by Jacob Rief.
+<jacob.rief at tiscover.com>
+
+ldirectord is a stand alone daemon for monitoring the services on real
+servers. Currently, HTTP, HTTPS, and FTP services are supported.
+lditrecord is simple to install and works with the heartbeat code
+(http://www.linux-ha.org/).
+
+See 'ldirectord -h' and linux-ha/doc/ldirectord for more information.
+%endif
+
+%prep
+%if 0%{?suse_version} == 0 && 0%{?fedora} == 0 && 0%{?centos_version} == 0 && 0%{?rhel} == 0
+%{error:Unable to determine the distribution/version. This is generally caused by missing /etc/rpm/macros.dist. Please install the correct build packages or define the required macros manually.}
+exit 1
+%endif
+%setup -q -n %{name}-%{version}%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}
+
+%build
+if [ ! -f configure ]; then
+	./autogen.sh
+fi
+
+%if 0%{?fedora} >= 11 || 0%{?centos_version} > 5 || 0%{?rhel} > 5
+CFLAGS="$(echo '%{optflags}')"
+%global conf_opt_fatal "--enable-fatal-warnings=no"
+%else
+CFLAGS="${CFLAGS} ${RPM_OPT_FLAGS}"
+%global conf_opt_fatal "--enable-fatal-warnings=yes"
+%endif
+
+%if %{with rgmanager}
+%global rasset rgmanager
+%endif
+%if %{with linuxha}
+%global rasset linux-ha
+%endif
+%if %{with rgmanager} && %{with linuxha}
+%global rasset all
+%endif
+
+export CFLAGS
+
+%configure \
+	%{?conf_opt_rsctmpdir:%conf_opt_rsctmpdir} \
+	%{conf_opt_fatal} \
+	--with-pkg-name=%{name} \
+	--with-ras-set=%{rasset}
+
+%if %{defined jobs}
+JFLAGS="$(echo '-j%{jobs}')"
+%else
+JFLAGS="$(echo '%{_smp_mflags}')"
+%endif
+
+make $JFLAGS
+
+%install
+rm -rf %{buildroot}
+make install DESTDIR=%{buildroot}
+
+## tree fixup
+# remove docs (there is only one and they should come from doc sections in files)
+rm -rf %{buildroot}/usr/share/doc/resource-agents
+
+%if %{with linuxha}
+%if 0%{?suse_version}
+test -d %{buildroot}/sbin || mkdir %{buildroot}/sbin
+(
+  cd %{buildroot}/sbin
+  ln -sf /%{_sysconfdir}/init.d/ldirectord rcldirectord 
+) || true
+%endif
+%endif
+
+%clean
+rm -rf %{buildroot}
+
+%files
+%defattr(-,root,root)
+%doc AUTHORS COPYING COPYING.GPLv3 COPYING.LGPL ChangeLog
+%if %{with linuxha}
+%doc doc/README.webapps
+%doc %{_datadir}/%{name}/ra-api-1.dtd
+%endif
+
+%if %{with rgmanager}
+%{_datadir}/cluster
+%{_sbindir}/rhev-check.sh
+%endif
+
+%if %{with linuxha}
+%dir /usr/lib/ocf
+%dir /usr/lib/ocf/resource.d
+%dir /usr/lib/ocf/lib
+
+/usr/lib/ocf/lib/heartbeat
+
+/usr/lib/ocf/resource.d/heartbeat
+%if %{with rgmanager}
+/usr/lib/ocf/resource.d/redhat
+%endif
+
+%dir %{_datadir}/%{name}
+%dir %{_datadir}/%{name}/ocft
+%{_datadir}/%{name}/ocft/configs
+%{_datadir}/%{name}/ocft/caselib
+%{_datadir}/%{name}/ocft/README
+%{_datadir}/%{name}/ocft/README.zh_CN
+
+%{_sbindir}/ocf-tester
+%{_sbindir}/ocft
+%{_sbindir}/sfex_init
+%{_sbindir}/sfex_stat
+
+%{_includedir}/heartbeat
+
+%dir %attr (1755, root, root)	%{_var}/run/resource-agents
+
+%{_mandir}/man7/*.7*
+%{_mandir}/man8/ocf-tester.8*
+%{_mandir}/man8/sfex_init.8*
+
+# For compatability with pre-existing agents
+%dir %{_sysconfdir}/ha.d
+%{_sysconfdir}/ha.d/shellfuncs
+
+%{_libexecdir}/heartbeat
+
+%post -n resource-agents
+if [ $1 = 2 ]; then
+ if [ -d %{_var}/run/heartbeat/rsctmp ]; then
+  cp -fpr %{_var}/run/heartbeat/rsctmp/* %{_var}/run/resource-agents/ 1>/dev/null 2>&1
+  rm -fr %{_var}/run/heartbeat/rsctmp
+ fi
+fi
+%if %{with rgmanager}
+ccs_update_schema > /dev/null 2>&1 ||:
+%endif
+
+%if 0%{?suse_version}
+%preun -n ldirectord
+%stop_on_removal ldirectord
+%postun -n ldirectord
+%insserv_cleanup
+%endif
+
+%if 0%{?fedora}
+%preun -n ldirectord
+/sbin/chkconfig --del ldirectord
+%postun -n ldirectord -p /sbin/ldconfig
+%post -n ldirectord
+/sbin/chkconfig --add ldirectord
+%endif
+
+%files -n ldirectord
+%defattr(-,root,root)
+%{_sbindir}/ldirectord
+%doc ldirectord/ldirectord.cf COPYING
+%{_mandir}/man8/ldirectord.8*
+%config(noreplace) %{_sysconfdir}/logrotate.d/ldirectord
+%dir %{_sysconfdir}/ha.d
+%dir %{_sysconfdir}/ha.d/resource.d
+%{_sysconfdir}/ha.d/resource.d/ldirectord
+%{_sysconfdir}/init.d/ldirectord
+%if 0%{?suse_version}
+/sbin/rcldirectord
+%endif
+%if 0%{?fedora}
+/usr/lib/ocf/resource.d/heartbeat/ldirectord
+%endif
+%endif
+
+%changelog
+* @date@ Autotools generated version <nobody at nowhere.org> - @version at -@specver at -@numcomm at .@alphatag at .@dirty@
+- Autotools generated version
diff --git a/rgmanager/Makefile.am b/rgmanager/Makefile.am
new file mode 100644
index 0000000..5319990
--- /dev/null
+++ b/rgmanager/Makefile.am
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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
+
+SUBDIRS			= src
diff --git a/rgmanager/src/Makefile.am b/rgmanager/src/Makefile.am
new file mode 100644
index 0000000..083c628
--- /dev/null
+++ b/rgmanager/src/Makefile.am
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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
+
+SUBDIRS			= resources
diff --git a/rgmanager/src/resources/ASEHAagent.sh b/rgmanager/src/resources/ASEHAagent.sh
new file mode 100755
index 0000000..ec78ce9
--- /dev/null
+++ b/rgmanager/src/resources/ASEHAagent.sh
@@ -0,0 +1,900 @@
+#!/bin/bash
+
+# 
+# Sybase Availability Agent for Red Hat Cluster v15.0.2 
+# Copyright (C) - 2007
+# Sybase, Inc. All rights reserved.
+#
+# Sybase Availability Agent for Red Hat Cluster v15.0.2 is licensed
+# under the GNU General Public License Version 2.
+#
+# Author(s):
+#    Jian-ping Hui <jphui at sybase.com>
+#
+# Description: Service script for starting/stopping/monitoring \
+#              Sybase Adaptive Server on: \
+#                            Red Hat Enterprise Linux 5 ES \
+#                            Red Hat Enterprise Linux 5 AS
+#
+# NOTES:
+#
+# (1) Before running this script, we assume that user has installed
+#     Sybase ASE 15.0.2 or higher version on the machine. Please
+#     customize your configuration in /etc/cluster/cluster.conf according
+#     to your actual environment. We assume the following files exist before
+#     you start the service:
+#         /$sybase_home/SYBASE.sh
+#         /$sybase_home/$sybase_ase/install/RUN_$server_name
+#
+# (2) You can customize the interval value in the meta-data section if needed:
+#                <action name="start" timeout="300" />
+#                <action name="stop" timeout="300" />
+#                
+#                <!-- Checks to see if it''s mounted in the right place -->
+#                <action name="status"  interval="30" timeout="100" />
+#                <action name="monitor" interval="30" timeout="100" />
+#                
+#                <!--Checks to see if we can read from the mountpoint -->
+#                <action name="status" depth="10" timeout="100" interval="120" />
+#                <action name="monitor" depth="10" timeout="100" interval="120" />
+#                
+#                <action name="meta-data" timeout="5" />
+#                <action name="validate-all" timeout="5" />
+#     The timeout value is not supported by Redhat in RHCS5.0. 
+# 
+# (3) This script should be put under /usr/share/cluster. Its owner should be "root" with 
+#     execution permission.
+#
+
+. /etc/init.d/functions
+. $(dirname $0)/ocf-shellfuncs
+
+PROG=${0}
+
+export LD_POINTER_GUARD=0
+
+#######################################################################################
+# Declare some variables we will use in the script. Please don't change their values. #
+#######################################################################################
+declare login_string=""
+declare RUNSERVER_SCRIPT=$OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ase/install/RUN_$OCF_RESKEY_server_name
+declare CONSOLE_LOG=$OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ase/install/$OCF_RESKEY_server_name.log
+
+##################################################################################################
+# This function will be called by rgmanager to get the meta data of resource agent "ASEHAagent". #
+# NEVER CHANGE ANYTHING IN THIS FUNCTION.
+##################################################################################################
+meta_data()
+{
+	cat <<EOT
+<?xml version="1.0" ?>
+<resource-agent name="ASEHAagent" version="rgmanager 2.0">
+	<version>1.0</version>
+
+	<longdesc lang="en">
+		Sybase ASE Failover Instance
+	</longdesc>
+	<shortdesc lang="en">
+		Sybase ASE Failover Instance
+	</shortdesc>
+
+	<parameters>
+		<parameter name="name" unique="1" primary="1">
+			<longdesc lang="en">
+				Instance name of resource agent "ASEHAagent"
+			</longdesc>
+			<shortdesc lang="en">
+				name
+			</shortdesc>
+			<content type="string" />
+		</parameter>
+
+		<parameter name="sybase_home" required="1">
+			<longdesc lang="en">
+				The home directory of sybase products
+			</longdesc>
+			<shortdesc lang="en">
+				SYBASE home directory
+			</shortdesc>
+			<content type="string" />
+		</parameter>
+
+		<parameter name="sybase_ase" required="1">
+			<longdesc lang="en">
+				The directory name under sybase_home where ASE products are installed
+			</longdesc>
+			<shortdesc lang="en">
+				SYBASE_ASE directory name
+			</shortdesc>
+			<content type="string" default="ASE-15_0" />
+		</parameter>
+
+		<parameter name="sybase_ocs" required="1">
+			<longdesc lang="en">
+				The directory name under sybase_home where OCS products are installed, i.e. ASE-15_0
+			</longdesc>
+			<shortdesc lang="en">
+				SYBASE_OCS directory name
+			</shortdesc>
+			<content type="string" default="OCS-15_0" />
+		</parameter>
+
+		<parameter name="server_name" required="1">
+			<longdesc lang="en">
+				The ASE server name which is configured for the HA service
+			</longdesc>
+			<shortdesc lang="en">
+				ASE server name
+			</shortdesc>
+			<content type="string" />
+		</parameter>
+
+		<parameter name="login_file" required="1">
+			<longdesc lang="en">
+				The full path of login file which contains the login/password pair
+			</longdesc>
+			<shortdesc lang="en">
+				Login file
+			</shortdesc>
+			<content type="string" />
+		</parameter>
+
+		<parameter name="interfaces_file" required="1">
+			<longdesc lang="en">
+				The full path of interfaces file which is used to start/access the ASE server
+			</longdesc>
+			<shortdesc lang="en">
+				Interfaces file
+			</shortdesc>
+			<content type="string" />
+		</parameter>
+
+		<parameter name="sybase_user" required="1">
+			<longdesc lang="en">
+				The user who can run ASE server
+			</longdesc>
+			<shortdesc lang="en">
+				Sybase user
+			</shortdesc>
+			<content type="string" default="sybase" />
+		</parameter>
+
+		<parameter name="shutdown_timeout" required="1">
+			<longdesc lang="en">
+				The maximum seconds to wait for the ASE server to shutdown before killing the process directly
+			</longdesc>
+			<shortdesc>
+				Shutdown timeout value
+			</shortdesc>
+			<content type="integer" default="0" />
+		</parameter>
+
+		<parameter name="start_timeout" required="1">
+			<longdesc lang="en">
+				The maximum seconds to wait for an ASE server to complete before determining that the server had failed to start
+			</longdesc>
+			<shortdesc lang="en">
+				Start timeout value
+			</shortdesc>
+			<content type="integer" default="0" />
+		</parameter>
+
+		<parameter name="deep_probe_timeout" required="1">
+			<longdesc lang="en">
+				The maximum seconds to wait for the response of ASE server before determining that the server had no response while running deep probe
+			</longdesc>
+			<shortdesc lang="en">
+				Deep probe timeout value
+			</shortdesc>
+			<content type="integer" default="0" />
+		</parameter>
+	</parameters>
+	<actions>
+		<action name="start" timeout="300" />
+		<action name="stop" timeout="300" />
+		
+		<!-- Checks to see if it''s mounted in the right place -->
+		<action name="status"  interval="30" timeout="100" />
+		<action name="monitor" interval="30" timeout="100" />
+		
+		<!--Checks to see if we can read from the mountpoint -->
+		<action name="status" depth="10" timeout="100" interval="120" />
+		<action name="monitor" depth="10" timeout="100" interval="120" />
+		
+		<action name="meta-data" timeout="5" />
+		<action name="validate-all" timeout="5" />
+	</actions>
+
+	<special tag="rgmanager">
+	</special>
+</resource-agent>
+EOT
+}
+
+##################################################################################################
+# Function Name: verify_all                                                                      #
+# Parameter: None                                                                                #
+# Return value:                                                                                  #
+#             0               SUCCESS                                                            #
+#             OCF_ERR_ARGS    Parameters are invalid                                             #
+# Description: Do some validation on the user-configurable stuff at the beginning of the script. #
+##################################################################################################
+verify_all() 
+{
+	ocf_log debug "ASEHAagent: Start 'verify_all'"
+
+	# Check if the parameter 'sybase_home' is set.	
+	if [[ -z "$OCF_RESKEY_sybase_home" ]]
+	then
+		ocf_log err "ASEHAagent: The parameter 'sybase_home' is not set."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the parameter 'sybase_home' is a valid path.
+	if [[ ! -d $OCF_RESKEY_sybase_home ]]
+	then
+		ocf_log err "ASEHAagent: The sybase_home '$OCF_RESKEY_sybase_home' doesn't exist."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the script file SYBASE.sh exists
+	if [[ ! -f $OCF_RESKEY_sybase_home/SYBASE.sh ]]
+	then
+		ocf_log err "ASEHAagent: The file $OCF_RESKEY_sybase_home/SYBASE.sh is required to run this script. Failed to run the script."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the parameter 'sybase_ase' is set.
+	if [[ -z "$OCF_RESKEY_sybase_ase" ]] 
+	then
+		ocf_log err "ASEHAagent: The parameter 'sybase_ase' is not set."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the directory /$OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ase exists.
+	if [[ ! -d $OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ase ]]
+	then
+		ocf_log err "ASEHAagent: The directory '$OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ase' doesn't exist."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the parameter 'sybase_ocs' is set.
+	if [[ -z "$OCF_RESKEY_sybase_ocs" ]] 
+	then
+		ocf_log err "ASEHAagent: The parameter 'sybase_ocs' is not set."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the directory /$OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ocs exists.
+	if [[ ! -d $OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ocs ]]
+	then
+		ocf_log err "ASEHAagent: The directory '$OCF_RESKEY_sybase_home/$OCF_RESKEY_sybase_ocs' doesn't exist."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the parameter 'server_name' is set.	
+	if [[ -z "$OCF_RESKEY_server_name" ]]
+	then
+		ocf_log err "ASEHAagent: The parameter 'server_name' is not set."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the Run_server file exists.
+	if [[ ! -f $RUNSERVER_SCRIPT ]]
+	then
+		ocf_log err "ASEHAagent: The file $RUNSERVER_SCRIPT doesn't exist. The sybase directory may be incorrect."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the parameter 'login_file' is set.	
+	if [[ -z "$OCF_RESKEY_login_file" ]]
+	then
+		ocf_log err "ASEHAagent: The parameter 'login_file' is not set."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the login file exist.
+	if [[ ! -f $OCF_RESKEY_login_file ]]
+	then
+		ocf_log err "ASEHAagent: The login file '$OCF_RESKEY_login_file' doesn't exist."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the parameter 'sybase_user' is set
+	if [[ -z "$OCF_RESKEY_sybase_user" ]]
+	then
+		ocf_log err "ASEHAagent: The parameter 'sybase_user' is not set."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the user 'sybase_user' exist
+	id -u $OCF_RESKEY_sybase_user
+	if [[ $? != 0 ]]
+	then
+		ocf_log err "ASEHAagent: The user '$OCF_RESKEY_sybase_user' doesn't exist in the system."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the parameter 'interfaces_file' is set
+	if [[ -z "$OCF_RESKEY_interfaces_file" ]]
+	then
+		ocf_log err "ASEHAagent: The parameter 'interfaces_file' is not set."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the file 'interfaces_file' exists
+	if [[ ! -f $OCF_RESKEY_interfaces_file ]]
+	then
+		ocf_log err "ASEHAagent: The interfaces file '$OCF_RESKEY_interfaces_file' doesn't exist."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the parameter 'shutdown_timeout' is a valid value
+	if [[ $OCF_RESKEY_shutdown_timeout -eq 0 ]]
+	then
+		ocf_log err "ASEHAagent: The parameter 'shutdown_timeout' is not set. Its value cannot be zero."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the parameter 'start_timeout' is a valid value
+	if [[ $OCF_RESKEY_start_timeout -eq 0 ]]
+	then
+		ocf_log err "ASEHAagent: The parameter 'start_timeout' is not set. Its value cannot be zero."
+		return $OCF_ERR_ARGS
+	fi
+
+	# Check if the parameter 'deep_probe_timeout' is a valid value
+	if [[ $OCF_RESKEY_deep_probe_timeout -eq 0 ]]
+	then
+		ocf_log err "ASEHAagent: The parameter 'deep_probe_timeout' is not set. Its value cannot be zero."
+		return $OCF_ERR_ARGS
+	fi
+
+	ocf_log debug "ASEHAagent: End 'verify_all' successfully."
+
+	return 0
+}
+
+################################################################################################################
+# Function name: get_login_string                                                                              #
+# Parameter: None                                                                                              #
+# Return value:                                                                                                #
+#              0    SUCCESS                                                                                    #
+#              1    FAIL                                                                                       #
+# Description: Analyze the login_file to format the login string. This function will set the global variable   #
+#              "login_string". If the login/password is clear text, the "login_string" will become to "-Ulogin #
+#              -Ppassword" if there is no error. If there are any errors in this function, the string          #
+#              "login_string" will be still empty. In current stage, the encrypted string is not supported     #
+#              because "haisql" is not available on this platform.                                             #
+################################################################################################################
+get_login_string()
+{
+	tmpstring=""
+	login_sting=""
+
+	# Read the first column. The valid value will be "normal" or "encrypted". Any other values are invalid.
+	login_type=`head -1 $OCF_RESKEY_login_file | awk '{print $1}'`
+	if [[ $login_type = "normal" ]]
+	then
+		# The login/password pair is saved in clear text.
+		# Abstract the login/password from the line. 
+		tmpstring=`head -1 $OCF_RESKEY_login_file | awk '{print $2}'`
+
+		# Abstract "user" from the string.
+		user=`echo $tmpstring | awk -F'/' '{print $1}'`
+		# Check if the "user" string is NULL. If it is NULL, it means this is not a valid user.
+		if  [[ -z $user ]]
+		then
+			ocf_log err "ASEHAagent: Login username is not specified in the file '$OCF_RESKEY_login_file'"
+			return 1
+		fi
+
+		# Abstract "password" from the string.
+		passwd=`echo $tmpstring | awk -F'/' '{print $2}'`
+
+		# Format the "login_string".
+		login_string="-U$user -P$passwd"
+	else
+		# The login_type is invalid value.
+		ocf_log err "ASEHAagent: Login type specified in the file $OCF_RESKEY_login_file is not 'normal' or 'encrypted' which are only supported values."
+		return 1
+	fi
+
+	# The "login_file" has been analyzed successfully. Now, the value of "login_string" contains the login/password information.
+	return 0
+}
+
+##############################################################################################
+# Function name: ase_start                                                                   #
+# Parameter: None                                                                            #
+# Return value:                                                                              #
+#             0  SUCCESS                                                                     #
+#             1  FAIL                                                                        #
+# Description: This function is used to start the ASE server in primary or secondary server. #
+##############################################################################################
+ase_start()
+{
+	ocf_log debug "ASEHAagent: Start 'ase_start'"
+
+	# Check if the server is running. If yes, return SUCCESS directly. Otherwise, continue the start work.
+	ase_is_running
+	if [[ $? = 0 ]]
+	then
+		# The server is running. 
+		ocf_log info "ASEHAagent: Server is running. Start is success."
+		return 0
+	fi
+
+	# The server is not running. We need to start it.
+	# If the log file existed, delete it.
+	if [[ -f $CONSOLE_LOG ]]
+	then
+		rm -f $CONSOLE_LOG
+	fi
+		
+	ocf_log debug "ASEHAagent: Starting '$OCF_RESKEY_server_name'..."
+
+	# Run runserver script to start the server. Since this script will be run by root and ASE server
+	# needs to be run by another user, we need to change the user to sybase_user first. Then, run
+	# the script to start the server.
+	su $OCF_RESKEY_sybase_user -c ksh << EOF
+		# set required SYBASE environment by running SYBASE.sh.
+		. $OCF_RESKEY_sybase_home/SYBASE.sh
+		# Run the RUNSERVER_SCRIPT to start the server.
+                . $RUNSERVER_SCRIPT > $CONSOLE_LOG 2>&1 &
+EOF
+
+	# Monitor every 1 seconds if the server has
+	# recovered, until RECOVERY_TIMEOUT.
+	t=0
+	while [[ $t -le $OCF_RESKEY_start_timeout ]]
+	do
+		grep -s "Recovery complete." $CONSOLE_LOG > /dev/null 2>&1
+		if [[ $? != 0 ]]
+		then
+			# The server has not completed the recovery. We need to continue to monitor the recovery
+			# process.
+			t=`expr $t + 1`
+		else
+			# The server has completed the recovery.
+			ocf_log info "ASEHAagent: ASE server '$OCF_RESKEY_server_name' started successfully."
+			break
+		fi
+		sleep 1
+	done
+
+	# If $t is larger than start_timeout, it means the ASE server cannot start in given time. Otherwise, it 
+	# means the ASE server has started successfully.
+	if [[ $t -gt $OCF_RESKEY_start_timeout ]]
+	then
+		# The server cannot start in specified time. We think the start is failed.
+		ocf_log err "ASEHAagent: Failed to start ASE server '$OCF_RESKEY_server_name'. Please check the server error log $CONSOLE_LOG for possible problems."
+		return 1
+	fi
+
+	ocf_log debug "ASEHAagent: End 'ase_start' successfully."
+
+	return 0
+}
+
+#############################################################################################
+# Function name: ase_stop                                                                   #
+# Parameter: None                                                                           #
+# Return value:                                                                             #
+#             0  SUCCESS                                                                    #
+#             1  FAIL                                                                       #
+# Description: This function is used to stop the ASE server in primary or secondary server. #
+#############################################################################################
+ase_stop()
+{
+	ocf_log debug "ASEHAagent: Start 'ase_stop'"
+
+	# Check if the ASE server is still running.
+	ase_is_running
+	if [[ $? != 0 ]]
+	then
+		# The ASE server is not running. We need not to shutdown it.
+		ocf_log info "ASEHAagent: The dataserver $OCF_RESKEY_server_name is not running."
+		return 0
+	fi
+
+	# Call get_login_string() to parse the login/password string
+	get_login_string
+	if [[ $? = 1 ]]
+	then
+		# The login account cannot be used. So we will kill the process directly.
+		ocf_log info "ASEHAagent: Cannot parse the login file $OCF_RESKEY_login_file. Kill the processes of ASE directly."
+		# Kill the OS processes immediately.
+		kill_ase 0
+		return $?
+	fi
+
+	# Just in case things are hung, start a process that will wait for the
+	# timeout period, then kill any remaining porcesses.  We'll need to
+	# monitor this process (set -m), so we can terminate it later if it is
+	# not needed.
+	set -m
+	$PROG kill &
+	KILL_PID=$!     # If successful, we will also terminate watchdog process
+
+	# Run "shutdown with nowait" from isql command line to shutdown the server
+	su $OCF_RESKEY_sybase_user -c ksh << EOF
+		# set required SYBASE environment by running SYBASE.sh.
+		. $OCF_RESKEY_sybase_home/SYBASE.sh
+		# Run "shutdown with nowait" to shutdown the server immediately.
+		(echo "use master" ; echo go ; echo "shutdown with nowait"; echo go) | \
+		\$SYBASE/\$SYBASE_OCS/bin/isql $login_string -S$OCF_RESKEY_server_name -I$OCF_RESKEY_interfaces_file  &
+EOF
+
+	sleep 5
+
+	# Check if the server has been shut down successfully
+	t=0
+	while [[ $t -lt $OCF_RESKEY_shutdown_timeout ]]
+	do
+		# Search "ueshutdown: exiting" in the server log. If found, it means the server has been shut down. 
+		# Otherwise, we need to wait.
+		tail $CONSOLE_LOG | grep "ueshutdown: exiting" > /dev/null 2>&1
+		if [[ $? != 0 ]]
+		then
+			# The shutdown is still in processing. Wait...
+			sleep 2
+			t=`expr $t+2`
+		else
+			# The shutdown is success.
+			ocf_log info "ASEHAagent: ASE server '$OCF_RESKEY_server_name' shutdown with isql successfully."
+			break
+		fi
+	done
+
+	# If $t is larger than shutdown_timeout, it means the ASE server cannot be shut down in given time. We need
+	# to wait for the background kill process to kill the OS processes directly.
+	if  [[ $t -ge $OCF_RESKEY_shutdown_timeout ]]
+	then
+		ocf_log err "ASEHAagent: Shutdown of '$OCF_RESKEY_server_name' from isql failed.  Server is either down or unreachable."
+	fi
+
+	# Here, the ASE server has been shut down by isql command or killed by background process. We need to do
+	# further check to make sure all processes have gone away before saying shutdown is complete. This stops the
+	# other node from starting up the package before it has been stopped and the file system has been unmounted.
+	
+	# Get all processes ids from log file
+	declare -a ENGINE_ALL=(`sed -n -e '/engine /s/^.*os pid \([0-9]*\).*online$/\1/p' $CONSOLE_LOG`)
+	typeset -i num_procs=${#ENGINE_ALL[@]}
+
+	# We cannot find any process id from log file. It may be because the log file is corrupted or be deleted.
+	# In this case, we determine the shutdown is failed.
+	if [[ "${ENGINE_ALL[@]}" = "" ]]
+	then
+		ocf_log err "ASEHAagent: Unable to find the process id from $CONSOLE_LOG."
+		ocf_log err "ASEHAagent: Stop ASE server failed."
+		return 1
+	fi
+
+	# Monitor the system processes to make sure all ASE related processes have gone away.
+	while true
+	do
+		# To every engine process, search it in system processes list. If it is not in the
+		# list, it means this process has gone away. Otherwise, we need to wait for it is
+		# killed by background process.
+		for i in ${ENGINE_ALL[@]}
+		do
+			ps -fu $OCF_RESKEY_sybase_user | awk '{print $2}' | grep $i | grep -v grep
+			if [[ $? != 0 ]]
+			then
+				ocf_log debug "ASEHAagent: $i process has stopped."
+				c=0
+				while (( c < $num_procs ))
+				do
+					if [[ ${ENGINE_ALL[$c]} = $i ]]
+					then
+						unset ENGINE_ALL[$c]
+						c=$num_procs
+					fi
+					(( c = c + 1 ))	
+				done
+			fi
+		done
+		
+		# To here, all processes should have gone away. 
+		if [[ ${ENGINE_ALL[@]} = "" ]]
+		then
+			#
+			# Looks like shutdown was successful, so kill the
+			# script to kill any hung processes, which we started earlier.
+			# Check to see if the script is still running.  If jobs
+			# returns that the script is done, then we don't need to kill
+			# it.
+			#
+			job=$(jobs | grep -v Done)
+			if [[ ${job} != "" ]]
+			then
+				ocf_log debug "ASEHAagent: Killing the kill_ase script."
+
+				kill -15 $KILL_PID > /dev/null 2>&1
+			fi
+			break
+	        fi
+		sleep 5
+	done
+
+	ocf_log debug "ASEHAagent: End 'ase_stop'."
+
+	return 0
+}
+
+####################################################################################
+# Function name: ase_is_running                                                    #
+# Parameter: None                                                                  #
+# Return value:                                                                    #
+#             0   ASE server is running                                            #
+#             1   ASE server is not running or there are errors                    #
+# Description: This function is used to check if the ASE server is still running . #
+####################################################################################
+ase_is_running()
+{
+	# If the error log doesn't exist, we can say there is no ASE is running.
+	if [[ ! -f $CONSOLE_LOG ]]
+	then
+		return 1
+	fi
+
+	# The error log file exists. Check if the engine 0 is alive.
+	ENGINE_0=(`sed -n -e '/engine 0/s/^.*os pid \([0-9]*\).*online$/\1/p' $CONSOLE_LOG`)
+	if [[ "$ENGINE_0" = "" ]]
+	then
+		# The engine 0 is down.
+		return 1 
+	else
+		kill -s 0 $ENGINE_0 > /dev/null 2>&1
+		if [[ $? != 0 ]]
+		then
+			# The engine 0 is not running.
+			return 1
+		else
+			# The engine 0 is running.
+			return 0
+		fi
+        fi
+
+	return 1
+}
+
+####################################################################################
+# Function name: kill_ase                                                          #
+# Parameter:                                                                       #
+#             DELAY  The seconds to wait before killing the ASE processes. 0 means #
+#                    kill the ASE processes immediately.                           #
+# Return value: None                                                               #
+#             1   ASE server is not running or there are errors                    #
+# Description: This function is used to check if the ASE server is still running . #
+####################################################################################
+kill_ase()
+{
+	ocf_log debug "ASEHAagent: Start 'kill_ase'."
+
+	DELAY=$1
+
+	# Wait for sometime before sending a kill signal.  
+	t=0
+        while [[ $t -lt $DELAY ]]
+        do
+     		sleep 1
+		t=`expr $t+1`
+        done
+
+	# Get the process ids from log file
+	declare -a ENGINE_ALL=`sed -n -e '/engine /s/^.*os pid \([0-9]*\).*online$/\1/p' $CONSOLE_LOG`
+
+	# If there is no process id found in the log file, we need not to continue.
+	if [[ "${ENGINE_ALL[@]}" = "" ]]
+	then
+		ocf_log err "ASEHAagent: Unable to find the process id from $CONSOLE_LOG."
+		return
+	fi
+
+	# Kill the datasever process(es)
+	for pid in ${ENGINE_ALL[@]}
+	do
+		kill -9 $pid > /dev/null 2>&1
+		if [[ $? != 0 ]]
+		then
+			ocf_log info "ASEHAagent: kill_ase function did NOT find process $pid running."
+		else
+			ocf_log info "ASEHAagent: kill_ase function did find process $pid running.  Sent SIGTERM."
+		fi
+	done
+
+	ocf_log debug "ASEHAagent: End 'kill_ase'."
+}
+
+
+#######################################################################################
+# Function name: terminate                                                            #
+# Parameter: None                                                                     #
+# Return value: Always be 1                                                           #
+# Description: This function is called automatically after this script is terminated. #
+#######################################################################################
+terminate()
+{
+	ocf_log debug "ASEHAagent: This monitor script has been signaled to terminate."
+	exit 1
+}
+
+#####################################################################################
+# Function name: ase_status                                                         #
+# Parameter:                                                                        #
+#             0   Level 0 probe. In this level, we just check if engine 0 is alive  #
+#             10  Level 10 probe. In this level, we need to probe if the ASE server #
+#                 still has response.                                               #              
+# Return value:                                                                     #
+#             0   The server is still alive                                         #
+#             1   The server is down                                                #
+# Description: This function is used to check if the ASE server is still running.   #
+#####################################################################################
+ase_status()
+{
+	ocf_log debug "ASEHAagent: Start 'ase_status'."
+
+	# Step 1: Check if the engine 0 is alive
+	ase_is_running
+	if [[ $? = 1 ]]
+	then
+		# ASE is down. Return fail to rgmanager to trigger the failover process.
+		ocf_log err "ASEHAagent: ASE server is down."
+		return 1
+	fi
+
+	# ASE process is still alive. 
+	# Step2: If this is level 10 probe, We need to check if the ASE server still has response.
+	if [[ $1 -gt 0 ]]
+	then
+		ocf_log debug "ASEHAagent: Need to run deep probe."
+		# Run deep probe
+		deep_probe
+		if [[ $? = 1 ]]
+		then
+			# Deep probe failed. This means the server has been down.
+			ocf_log err "ASEHAagent: Deep probe found the ASE server is down."
+			return 1
+		fi
+	fi
+
+	ocf_log debug "ASEHAagent: End 'ase_status'."
+
+	return 0
+}
+
+####################################################################################
+# Function name: deep_probe                                                        #
+# Parameter: None                                                                  #
+# Return value:                                                                    #
+#             0   ASE server is alive                                              #
+#             1   ASE server is down                                               #
+# Description: This function is used to run deep probe to make sure the ASE server #
+#              still has response.                                                 #
+####################################################################################
+deep_probe()
+{
+	declare -i rv
+	
+	ocf_log debug "ASEHAagent: Start 'deep_probe'."	
+
+	# Declare two temporary files which will be used in this probe.
+	tmpfile1="$(mktemp /tmp/ASEHAagent.1.XXXXXX)"
+	tmpfile2="$(mktemp /tmp/ASEHAagent.2.XXXXXX)"
+	
+	# Get the login_string by analyzing the login_file.
+	get_login_string
+	if [[ $? = 1 ]]
+	then
+		# Login string cannot be fetched. Cannot continue the deep probe.
+		ocf_log err "ASEHAagent: Cannot run the deep probe because of incorrect login file $OCF_RESKEY_login_file. Deep probe failed."
+		return 1
+	fi
+
+	rm -f $tmpfile1
+	rm -f $tmpfile2
+
+	# The login file is correct. We have gotten the login account and password from it.
+	# Run isql command in background.
+	su $OCF_RESKEY_sybase_user -c ksh << EOF
+		# set required SYBASE environment by running SYBASE.sh.
+		. $OCF_RESKEY_sybase_home/SYBASE.sh
+		# Run a very simple SQL statement to make sure the server is still ok. The output will be put to
+		# tmpfile1.
+		(echo "select 1"; echo "go") |
+		\$SYBASE/\$SYBASE_OCS/bin/isql $login_string -S$OCF_RESKEY_server_name -I$OCF_RESKEY_interfaces_file -t $OCF_RESKEY_deep_probe_timeout -e -o$tmpfile1 &
+		# Record the isql command process id to temporary file. If the isql is hung, we need this process id
+                # to kill the hung process.
+		echo \$! > $tmpfile2	
+EOF
+	
+	declare -i t=0
+		
+	# Monitor the output file tmpfile1.
+	while [[ $t -lt $OCF_RESKEY_deep_probe_timeout ]]
+	do
+		# If the SQL statement is executed successfully, we will get the following output:
+		# 1> select 1
+		# 
+		# -----------
+		#           1
+		# 
+		# (1 row affected)
+		# So, we determine if the execution is success by searching the keyword "(1 row affected)".
+		grep "(1 row affected)" $tmpfile1
+		if [[ $? = 0 ]]
+		then
+			ocf_log debug "ASEHAagent: Deep probe sucess."
+			break
+		else
+			sleep 1
+			t=`expr $t+1`
+		fi
+	done	
+
+	# If $t is larger than deep_probe_timeout, it means the isql command line cannot finish in given time.
+	# This means the deep probe failed. We need to kill the isql process manually.
+	if [[ $t -ge $OCF_RESKEY_deep_probe_timeout ]]
+	then
+		ocf_log err "ASEHAagent: Deep probe fail. The dataserver has no response."		
+
+		# Read the process id of isql process from tmpfile2
+		pid=`cat $tmpfile2 | awk '{print $1}'`
+
+		rm -f $tmpfile1
+		rm -f $tmpfile2
+
+		# Kill the isql process directly.
+		kill -9 $pid
+		return 1
+	fi
+
+	rm -f $tmpfile1
+	rm -f $tmpfile2
+
+	ocf_log debug "ASEHAagent: End 'deep_probe'."
+
+	return 0
+}
+
+trap terminate SIGTERM
+
+#############################
+# Do some real work here... #
+#############################
+case $1 in
+	start)
+		verify_all || exit 1
+		ase_start
+		exit $?
+		;;
+	stop)
+		verify_all || exit 1
+		ase_stop
+		exit $?
+		;;
+	status | monitor)
+		verify_all || exit 1
+		ase_status $OCF_CHECK_LEVEL
+		exit $?
+		;;
+	kill)
+		kill_ase $OCF_RESKEY_shutdown_timeout
+		;;
+	meta-data)
+		meta_data
+		exit $?
+		;;
+	validate-all)
+		verify_all
+		exit $?
+		;;
+	*)
+		echo "Usage: $SCRIPT {start|stop|monitor|status|validate-all|meta-data}"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
+exit 0
+
diff --git a/rgmanager/src/resources/Makefile.am b/rgmanager/src/resources/Makefile.am
new file mode 100644
index 0000000..7719f81
--- /dev/null
+++ b/rgmanager/src/resources/Makefile.am
@@ -0,0 +1,117 @@
+#
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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
+
+SUBDIRS			= utils
+
+TARGET			= fs.sh
+
+RESOURCES		= service.sh ip.sh nfsclient.sh nfsexport.sh \
+			  script.sh netfs.sh clusterfs.sh smb.sh \
+			  apache.sh openldap.sh samba.sh mysql.sh \
+			  postgres-8.sh tomcat-5.sh lvm.sh \
+			  vm.sh SAPInstance SAPDatabase named.sh \
+			  ASEHAagent.sh drbd.sh nfsserver.sh \
+			  tomcat-6.sh orainstance.sh oralistener.sh oracledb.sh
+
+METADATA		= apache.metadata openldap.metadata samba.metadata \
+			  mysql.metadata postgres-8.metadata \
+			  tomcat-5.metadata named.metadata lvm.metadata \
+			  drbd.metadata tomcat-6.metadata \
+			  orainstance.metadata oralistener.metadata
+
+HELPERS			= ocf-shellfuncs svclib_nfslock \
+			  lvm_by_lv.sh lvm_by_vg.sh
+
+DTD			= ra-api-1-modified.dtd
+
+XSL			= ra2man.xsl ra2ref.xsl ra2rng.xsl
+
+RESRNG			= resources.rng.head resources.rng.mid resources.rng.tail
+
+EXTRA_DIST		= $(TARGET:=.in) \
+			  $(RESOURCES) \
+			  $(METADATA) \
+			  $(HELPERS) \
+			  $(DTD) \
+			  $(XSL) \
+			  $(RESRNG)
+
+rasdir			= ${CLUSTERDATA}
+
+ras_SCRIPTS		= $(TARGET) \
+			  $(RESOURCES) \
+			  $(HELPERS)
+
+ras_DATA		= $(METADATA)
+
+rngdir			= ${CLUSTERDATA}/relaxng
+
+rng_DATA		= $(DTD) $(XSL) $(RESRNG)
+
+$(TARGET):
+	cat $@.in | sed \
+		-e 's#@''LOGDIR@#${LOGDIR}#g' \
+	> $@.out
+	chmod +x $@.out
+	mv $@.out $@
+
+clean-local:
+	rm -f $(TARGET) resources.rng
+
+ras-validation: $(RESOURCES) $(TARGET) $(DTD)
+	@echo Validating resource agent meta-data
+	@for f in $(RESOURCES); do \
+		echo "   $(abs_srcdir)/$$f "; \
+		bash $(abs_srcdir)/$$f meta-data | xmllint --dtdvalid \
+			$(abs_srcdir)/$(DTD) --noout -; \
+		if [ $$? -ne 0 ]; then exit 1; fi \
+	done
+	@for f in $(TARGET); do \
+		echo "   $(abs_builddir)/$$f "; \
+		bash $(abs_builddir)/$$f  meta-data | xmllint --dtdvalid \
+			$(abs_srcdir)/$(DTD) --noout -; \
+		if [ $$? -ne 0 ]; then exit 1; fi \
+	done
+
+#
+# Schema maintenance.  Run 'make resources.rng' and paste it in to
+# config/tools/xml/cluster.rng.in where it says 'autogenerated'.
+#
+# resources.rng.* should never be distributed by themselves.
+#
+resources.rng: $(RESOURCES) $(TARGET) utils/config-utils.sh
+resources.rng: $(XSL) $(RESRNG)
+	rm -f resources.rng
+	cat resources.rng.head >> resources.rng
+	@echo Generating per-resource RelaxNG information...
+	@for f in $(RESOURCES) $(TARGET); do \
+		echo "    ./$$f"; \
+		bash ./$$f meta-data | xsltproc ra2rng.xsl - >> resources.rng; \
+	done
+	cat resources.rng.mid >> resources.rng
+	@echo Generating per-resource RelaxNG reference information...
+	@for f in $(RESOURCES) $(TARGET); do \
+		echo "    ./$$f"; \
+		bash ./$$f meta-data | xsltproc ra2ref.xsl - >> resources.rng; \
+	done
+	cat resources.rng.tail >> resources.rng
+
+utils/config-utils.sh:
+	make -C utils config-utils.sh
diff --git a/rgmanager/src/resources/SAPDatabase b/rgmanager/src/resources/SAPDatabase
new file mode 100644
index 0000000..b34d67f
--- /dev/null
+++ b/rgmanager/src/resources/SAPDatabase
@@ -0,0 +1,1026 @@
+#!/bin/sh
+#
+# SAPDatabase
+#
+# Description:	Manages any type of SAP supported database instance
+#               as a High-Availability OCF compliant resource.
+#
+# Author:       Alexander Krauth, October 2006
+# Support:      linux at sap.com
+# License:      GNU General Public License (GPL)
+# Copyright:    (c) 2006, 2007 Alexander Krauth
+#
+# An example usage: 
+#      See usage() function below for more details...
+#
+# OCF instance parameters:
+#	OCF_RESKEY_SID
+#       OCF_RESKEY_DIR_EXECUTABLE   (optional, well known directories will be searched by default)
+#       OCF_RESKEY_DBTYPE
+#       OCF_RESKEY_NETSERVICENAME   (optional, non standard name of Oracle Listener)
+#       OCF_RESKEY_DBJ2EE_ONLY      (optional, default is false)
+#       OCF_RESKEY_JAVA_HOME        (optional, only needed if DBJ2EE_ONLY is true and JAVA_HOME enviroment variable is not set)
+#       OCF_RESKEY_STRICT_MONITORING (optional, activate application level monitoring - with Oracle a failover will occur in case of an archiver stuck)
+#       OCF_RESKEY_AUTOMATIC_RECOVER (optional, automatic startup recovery, default is false)
+#       OCF_RESKEY_DIR_BOOTSTRAP    (optional, if non standard J2EE server directory)
+#       OCF_RESKEY_DIR_SECSTORE     (optional, if non standard J2EE secure store directory)
+#       OCF_RESKEY_DB_JARS          (optional, if maintained in bootstrap.properties, mandatory for WebAS Java 7.10)
+#	OCF_RESKEY_PRE_START_USEREXIT	(optional, lists a script which can be executed before the resource is started)
+#	OCF_RESKEY_POST_START_USEREXIT	(optional, lists a script which can be executed after the resource is started)
+#	OCF_RESKEY_PRE_STOP_USEREXIT	(optional, lists a script which can be executed before the resource is stopped)
+#	OCF_RESKEY_POST_STOP_USEREXIT	(optional, lists a script which can be executed after the resource is stopped)
+#
+# ToDo:
+# Remove all the database dependend stuff from the agent and use
+# saphostcontrol daemon as soon as SAP will release it.
+#
+#######################################################################
+# Initialization:
+
+if [ -f $(dirname $0)/.ocf-shellfuncs ]; then
+        . $(dirname $0)/.ocf-shellfuncs
+elif [ -f $(dirname $0)/ocf-shellfuncs ]; then
+        LC_ALL=C
+        LANG=C
+        PATH=/bin:/sbin:/usr/bin:/usr/sbin
+        export LC_ALL LANG PATH
+        . $(dirname $0)/ocf-shellfuncs
+else
+        echo Could not find ocf-shellfuncs!
+        exit 1
+fi
+
+#######################################################################
+
+SH=/bin/sh
+
+usage() {
+  methods=`sapdatabase_methods`
+  methods=`echo $methods | tr ' ' '|'`
+  cat <<-!
+	usage: $0 ($methods)
+
+	$0 manages a SAP database of any type as an HA resource.
+        Currently Oracle, MaxDB and DB/2 UDB are supported.
+        ABAP databases as well as JAVA only databases are supported.
+
+	The 'start' operation starts the instance.
+	The 'stop' operation stops the instance.
+	The 'status' operation reports whether the instance is running
+	The 'monitor' operation reports whether the instance seems to be working
+	The 'recover' operation tries to recover the instance after a crash (instance will be stopped first!)
+	The 'validate-all' operation reports whether the parameters are valid
+	The 'methods' operation reports on the methods $0 supports
+
+	!
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent name="SAPDatabase">
+<version>1.92.1</version>
+
+<longdesc lang="en">
+Resource script for SAP databases. It manages a SAP database of any type as an HA resource.
+</longdesc>
+<shortdesc lang="en">SAP database resource agent</shortdesc>
+
+<parameters>
+ <parameter name="SID" unique="1" required="1" primary="1">
+  <longdesc lang="en">The unique SAP system identifier. e.g. P01</longdesc>
+  <shortdesc lang="en">SAP system ID</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DIR_EXECUTABLE" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find sapstartsrv and sapcontrol.</longdesc>
+  <shortdesc lang="en">path of sapstartsrv and sapcontrol</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DBTYPE" unique="0" required="1">
+  <longdesc lang="en">The name of the database vendor you use. Set either: ORA,DB6,ADA</longdesc>
+  <shortdesc lang="en">database vendor</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="NETSERVICENAME" unique="0" required="0">
+  <longdesc lang="en">The Oracle TNS listener name.</longdesc>
+  <shortdesc lang="en">listener name</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DBJ2EE_ONLY" unique="0" required="0">
+  <longdesc lang="en">If you do not have a ABAP stack installed in the SAP database, set this to TRUE</longdesc>
+  <shortdesc lang="en">only JAVA stack installed</shortdesc>
+  <content type="boolean" default="false"/>
+ </parameter>
+ <parameter name="JAVA_HOME" unique="0" required="0">
+  <longdesc lang="en">This is only needed if the DBJ2EE_ONLY parameter is set to true. Enter the path to the Java SDK which is used by the SAP WebAS Java</longdesc>
+  <shortdesc lang="en">Path to Java SDK</shortdesc>
+  <content type="string" default=""/>
+ </parameter>
+ <parameter name="STRICT_MONITORING" unique="0" required="0">
+  <longdesc lang="en">This controls how the resource agent monitors the database. If set to true, it will use SAP tools to test the connect to the database. Do not use with Oracle, because it will result in unwanted failovers in case of an archiver stuck</longdesc>
+  <shortdesc lang="en">Activates application level monitoring</shortdesc>
+  <content type="boolean" default="false"/>
+ </parameter>
+ <parameter name="AUTOMATIC_RECOVER" unique="0" required="0">
+  <longdesc lang="en">The SAPDatabase resource agent tries to recover a failed start attempt automaticaly one time. This is done by running a forced abort of the RDBMS and/or executing recovery commands.</longdesc>
+  <shortdesc lang="en">Enable or disable automatic startup recovery</shortdesc>
+  <content type="boolean" default="false"/>
+ </parameter>
+ <parameter name="DIR_BOOTSTRAP" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find the J2EE instance bootstrap directory. e.g. /usr/sap/P01/J00/j2ee/cluster/bootstrap</longdesc>
+  <shortdesc lang="en">path to j2ee bootstrap directory</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DIR_SECSTORE" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find the J2EE security store directory. e.g. /usr/sap/P01/SYS/global/security/lib/tools</longdesc>
+  <shortdesc lang="en">path to j2ee secure store directory</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DB_JARS" unique="0" required="0">
+  <longdesc lang="en">The full qualified filename of the jdbc driver for the database connection test. It will be automaticaly read from the bootstrap.properties file in Java engine 6.40 and 7.00. For Java engine 7.10 the parameter is mandatory.</longdesc>
+  <shortdesc lang="en">file name of the jdbc driver</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="PRE_START_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed before this resource gets started.</longdesc>
+  <shortdesc lang="en">path to a pre-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="POST_START_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed after this resource got started.</longdesc>
+  <shortdesc lang="en">path to a post-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="PRE_STOP_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed before this resource gets stopped.</longdesc>
+  <shortdesc lang="en">path to a pre-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="POST_STOP_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed after this resource got stopped.</longdesc>
+  <shortdesc lang="en">path to a post-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="1800" />
+<action name="stop" timeout="1800" />
+<action name="status" depth="0" timeout="60" interval="120" start-delay="180" />
+<action name="monitor" depth="0" timeout="60" interval="120" start-delay="180" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+<action name="methods" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+trap_handler() {
+  rm -f $TEMPFILE
+  exit $OCF_ERR_GENERIC
+}
+
+
+do_exit() {
+  # If we've got a tempfile variable and the tempfile exists...
+  #  ... if the return code is 0 *or* the temp file is empty
+  #    remove it.
+  if [ -n "$TEMPFILE" ] && [ -e "$TEMPFILE" ]; then
+    if [ $1 -eq 0 ] || [ "$(stat -c %s $TEMPFILE)" = "0" ]; then
+      rm -f $TEMPFILE
+    fi
+  fi
+  exit $1
+}
+
+
+#
+# listener_start: Start the given listener
+#
+listener_start() {
+  orasid="ora`echo $SID | tr '[:upper:]' '[:lower:]'`"
+  rc=$OCF_SUCCESS
+  output=`echo "lsnrctl start $NETSERVICENAME" | su - $orasid 2>&1`
+  if [ $? -eq 0 ]
+  then
+    ocf_log info "Oracle Listener $NETSERVICENAME started: $output"
+    rc=$OCF_SUCCESS
+  else
+    ocf_log err "Oracle Listener $NETSERVICENAME start failed: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+  return $rc
+}
+
+#
+# listener_stop: Stop the given listener
+#
+listener_stop() {
+  orasid="ora`echo $SID | tr '[:upper:]' '[:lower:]'`"
+  rc=$OCF_SUCCESS
+  if
+      listener_status
+  then
+      : listener is running, trying to stop it later...
+  else
+      return $OCF_SUCCESS
+  fi
+  output=`echo "lsnrctl stop $NETSERVICENAME" | su - $orasid 2>&1`
+  if [ $? -eq 0 ]
+  then
+    ocf_log info "Oracle Listener $NETSERVICENAME stopped: $output"
+  else
+    ocf_log err "Oracle Listener $NETSERVICENAME stop failed: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+  return $rc
+}
+
+#
+# listener_status: is the given listener running?
+#
+listener_status() {
+  orasid="ora`echo $SID | tr '[:upper:]' '[:lower:]'`"
+  # Note: ps cuts off it's output at column $COLUMNS, so "ps -ef" can not be used here
+  # as the output might be to long.
+  cnt=`ps efo args --user $orasid | grep $NETSERVICENAME | grep -c tnslsnr`
+  if [ $cnt -eq 1 ]
+  then
+    rc=$OCF_SUCCESS
+  else
+    ocf_log info "listener process not running for $NETSERVICENAME for $SID"
+    rc=$OCF_ERR_GENERIC
+  fi
+  return $rc
+}
+
+#
+# x_server_start: Start the given x_server
+#
+x_server_start() {
+  rc=$OCF_SUCCESS
+  output=`echo "x_server start" | su - $sidadm 2>&1`
+  if [ $? -eq 0 ]
+  then
+    ocf_log info "MaxDB x_server start: $output"
+    rc=$OCF_SUCCESS
+  else
+    ocf_log err "MaxDB x_server start failed: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+  return $rc
+}
+
+#
+# x_server_stop: Stop the x_server
+#
+x_server_stop() {
+  rc=$OCF_SUCCESS
+  output=`echo "x_server stop" | su - $sidadm 2>&1`
+  if [ $? -eq 0 ]
+  then
+    ocf_log info "MaxDB x_server stop: $output"
+  else
+    ocf_log err "MaxDB x_server stop failed: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+  return $rc
+}
+
+#
+# x_server_status: is the x_server running?
+#
+x_server_status() {
+  sdbuser=`grep "^SdbOwner" /etc/opt/sdb | awk -F'=' '{print $2}'`
+  # Note: ps cuts off it's output at column $COLUMNS, so "ps -ef" can not be used here
+  # as the output might be to long.
+  cnt=`ps efo args --user $sdbuser | grep -c vserver`
+  if [ $cnt -ge 1 ]
+  then
+    rc=$OCF_SUCCESS
+  else
+    ocf_log info "x_server process not running"
+    rc=$OCF_ERR_GENERIC
+  fi
+  return $rc
+}
+
+#
+# oracle_stop: Stop the Oracle database without any condition
+#
+oracle_stop() {
+echo '#!/bin/sh
+LOG=$HOME/stopdb.log
+date > $LOG
+
+if [ -x "${ORACLE_HOME}/bin/sqlplus" ]
+then
+    SRVMGRDBA_EXE="${ORACLE_HOME}/bin/sqlplus"
+else
+   echo "Can not find executable sqlplus" >> $LOG
+   exit 1
+fi
+
+$SRVMGRDBA_EXE /NOLOG >> $LOG << !
+connect / as sysdba
+shutdown immediate
+exit
+!
+rc=$?
+cat $LOG
+exit $rc' > $TEMPFILE
+
+chmod 700 $TEMPFILE
+chown $sidadm $TEMPFILE
+
+su - $sidadm -c $TEMPFILE
+retcode=$?
+rm -f $TEMPFILE
+
+if [ $retcode -eq 0 ]; then
+  sapdatabase_status
+  if [ $? -ne $OCF_NOT_RUNNING ]; then
+    retcode=1
+  fi
+fi
+
+return $retcode
+}
+
+#
+# maxdb_stop: Stop the MaxDB database without any condition
+#
+maxdb_stop() {
+
+# x_Server must be running to stop database
+x_server_status
+if [ $? -ne $OCF_SUCCESS ]; then x_server_start; fi
+
+if [ $DBJ2EE_ONLY -eq 1 ]; then
+   userkey=c_J2EE
+else
+   userkey=c
+fi
+
+echo "#!/bin/sh
+LOG=\$HOME/stopdb.log
+date > \$LOG
+echo \"Stop database with xuserkey >$userkey<\" >> \$LOG
+dbmcli -U ${userkey} db_offline >> \$LOG 2>&1
+exit \$?" > $TEMPFILE
+
+chmod 700 $TEMPFILE
+chown $sidadm $TEMPFILE
+
+su - $sidadm -c $TEMPFILE
+retcode=$?
+rm -f $TEMPFILE
+
+if [ $retcode -eq 0 ]; then
+  sapdatabase_status
+  if [ $? -ne $OCF_NOT_RUNNING ]; then
+    retcode=1
+  fi
+fi
+
+return $retcode
+}
+
+#
+# db6udb_stop: Stop the DB2/UDB database without any condition
+#
+db6udb_stop() {
+echo '#!/bin/sh
+LOG=$HOME/stopdb.log
+date > $LOG
+echo "Shut down the database" >> $LOG
+$INSTHOME/sqllib/bin/db2 deactivate database $DB2DBDFT |tee -a $LOG  2>&1
+$INSTHOME/sqllib/adm/db2stop force |tee -a $LOG  2>&1
+exit $?' > $TEMPFILE
+
+chmod 700 $TEMPFILE
+chown $sidadm $TEMPFILE
+
+su - $sidadm -c $TEMPFILE
+retcode=$?
+rm -f $TEMPFILE
+
+if [ $retcode -eq 0 ]; then
+  sapdatabase_status
+  if [ $? -ne $OCF_NOT_RUNNING ]; then
+    retcode=1
+  fi
+fi
+
+return $retcode
+}
+
+#
+# oracle_recover: try to clean up oracle after a crash
+#
+oracle_recover() {
+echo '#!/bin/sh
+LOG=$HOME/recover.log
+date > $LOG
+echo "Logfile written by heartbeat SAPDatabase resource agent" >> $LOG
+
+if [ -x "${ORACLE_HOME}/bin/sqlplus" ]
+then
+    SRVMGRDBA_EXE="${ORACLE_HOME}/bin/sqlplus"
+else
+   echo "Can not find executable sqlplus" >> $LOG
+   exit 1
+fi
+
+$SRVMGRDBA_EXE /NOLOG >> $LOG << !
+connect / as sysdba
+shutdown abort
+startup mount
+WHENEVER SQLERROR EXIT SQL.SQLCODE
+WHENEVER OSERROR EXIT FAILURE
+alter database recover automatic database;
+alter database open;
+exit
+!
+rc=$?
+cat $LOG
+exit $rc' > $TEMPFILE
+
+  chmod 700 $TEMPFILE
+  chown $sidadm $TEMPFILE
+
+  su - $sidadm -c $TEMPFILE
+  retcode=$?
+  rm -f $TEMPFILE
+
+  return $retcode
+}
+
+#
+# maxdb_recover: try to clean up MaxDB after a crash
+#
+maxdb_recover() {
+  # x_Server must be running to stop database
+  x_server_status
+  if [ $? -ne $OCF_SUCCESS ]; then x_server_start; fi
+
+  if [ $DBJ2EE_ONLY -eq 1 ]; then
+     userkey=c_J2EE
+  else
+     userkey=c
+  fi
+
+echo "#!/bin/sh
+LOG=\$HOME/recover.log
+date > \$LOG
+echo \"Logfile written by heartbeat SAPDatabase resource agent\" >> \$LOG
+echo \"Cleanup database with xuserkey >$userkey<\" >> \$LOG
+echo \"db_stop\" >> \$LOG 2>&1
+dbmcli -U ${userkey} db_stop >> \$LOG 2>&1
+echo \"db_clear\" >> \$LOG 2>&1
+dbmcli -U ${userkey} db_clear >> \$LOG 2>&1
+echo \"db_online\" >> \$LOG 2>&1
+dbmcli -U ${userkey} db_online >> \$LOG 2>&1
+rc=\$?
+cat \$LOG
+exit \$rc" > $TEMPFILE
+
+  chmod 700 $TEMPFILE
+  chown $sidadm $TEMPFILE
+
+  su - $sidadm -c $TEMPFILE
+  retcode=$?
+  rm -f $TEMPFILE
+
+  return $retcode
+}
+
+#
+# db6udb_recover: try to recover DB/2 after a crash
+#
+db6udb_recover() {
+  db2sid="db2`echo $SID | tr '[:upper:]' '[:lower:]'`"
+
+echo '#!/bin/sh
+LOG=$HOME/recover.log
+date > $LOG
+echo "Logfile written by heartbeat SAPDatabase resource agent" >> $LOG
+$INSTHOME/sqllib/bin/db2_kill >> $LOG  2>&1
+$INSTHOME/sqllib/adm/db2start >> $LOG  2>&1
+$INSTHOME/sqllib/bin/db2 activate database $DB2DBDFT >> $LOG  2>&1
+rc=$?
+cat $LOG
+exit $rc' > $TEMPFILE
+
+  chmod 700 $TEMPFILE
+  chown $db2sid $TEMPFILE
+
+  su - $db2sid -c $TEMPFILE
+  retcode=$?
+  rm -f $TEMPFILE
+
+  return $retcode
+}
+
+#
+# methods: What methods/operations do we support?
+#
+sapdatabase_methods() {
+  cat <<-!
+	start
+	stop
+	status
+	monitor
+	recover
+	validate-all
+	methods
+	meta-data
+	usage
+	!
+}
+
+
+#
+# sapuserexit : Many SAP customers need some additional processes/tools to run their SAP systems.
+#               This specialties do not allow a totally generic SAP cluster resource agent.
+#               Someone should write a resource agent for each additional process you need, if it
+#               is required to monitor that process within the cluster manager. To enable
+#               you to extent this resource agent without developing a new one, this user exit
+#               was introduced.
+#
+sapuserexit() {
+  NAME="$1"
+  VALUE="$2"
+
+  if [ -n "$VALUE" ]
+  then
+    if [ -x "$VALUE" ]
+    then
+      ocf_log info "Calling userexit ${NAME} with customer script file ${VALUE}"
+      eval "$VALUE" > /dev/null 2>&1
+      ocf_log info "Exiting userexit ${NAME} with customer script file ${VALUE}, returncode: $?"
+    else
+      ocf_log warn "Attribute ${NAME} is set to ${VALUE}, but this file is not executable"
+    fi
+  fi
+  return 0
+}
+
+
+#
+# sapdatabase_start : Start the SAP database
+#
+sapdatabase_start() {
+  sapuserexit PRE_START_USEREXIT "$OCF_RESKEY_PRE_START_USEREXIT"
+
+  case $DBTYPE in
+    ADA) x_server_start
+         ;;
+    ORA) listener_start
+         ;;
+  esac
+
+  output=`su - $sidadm -c $SAPSTARTDB`
+  rc=$?
+
+  if [ $DBJ2EE_ONLY -eq 1 ]
+  then
+    sapdatabase_monitor 1
+    rc=$?
+  fi
+
+  if [ $rc -ne 0 -a $OCF_RESKEY_AUTOMATIC_RECOVER -eq 1 ]
+  then
+    ocf_log warn "SAP database $SID start failed: $output"
+    ocf_log warn "Try to recover database $SID"
+
+    output=''
+    sapdatabase_recover
+    rc=$?
+  fi
+
+  if [ $rc -eq 0 ]
+  then
+    ocf_log info "SAP database $SID started: $output"
+    rc=$OCF_SUCCESS
+    sapuserexit POST_START_USEREXIT "$OCF_RESKEY_POST_START_USEREXIT"
+  else
+    ocf_log err "SAP database $SID start failed: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+
+  return $rc
+}
+
+#
+# sapdatabase_stop: Stop the SAP database
+#
+sapdatabase_stop() {
+
+  sapuserexit PRE_STOP_USEREXIT "$OCF_RESKEY_PRE_STOP_USEREXIT"
+
+  # use of the stopdb kernel script is not possible, because there are to may checks in that
+  # script. We want to stop the database regardless of anything.
+  #output=`su - $sidadm -c $SAPSTOPDB`
+
+  case $DBTYPE in
+    ORA) output=`oracle_stop`
+         ;;
+    ADA) output=`maxdb_stop`
+         ;;
+    DB6) output=`db6udb_stop`
+         ;;
+  esac
+
+  if [ $? -eq 0 ]
+  then
+    ocf_log info "SAP database $SID stopped: $output"
+    rc=$OCF_SUCCESS
+  else
+    ocf_log err "SAP database $SID stop failed: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+
+  case $DBTYPE in
+    ORA) listener_stop
+         ;;
+    ADA) x_server_stop
+         ;;
+  esac
+
+  sapuserexit POST_STOP_USEREXIT "$OCF_RESKEY_POST_STOP_USEREXIT"
+
+  return $rc
+}
+
+
+#
+# sapdatabase_monitor: Can the given database instance do anything useful?
+#
+sapdatabase_monitor() {
+  strict=$1
+  rc=$OCF_SUCCESS
+
+  case $DBTYPE in
+    ADA) x_server_status 
+         if [ $? -ne $OCF_SUCCESS ]; then x_server_start; fi
+         ;;
+    ORA) listener_status
+         if [ $? -ne $OCF_SUCCESS ]; then listener_start; fi
+         ;;
+  esac
+
+  if [ $strict -eq 0 ]
+  then
+    sapdatabase_status
+    rc=$?
+  else
+    if [ $DBJ2EE_ONLY -eq 0 ]
+    then
+      output=`echo "$SAPDBCONNECT -d -w /dev/null" | su $sidadm 2>&1`
+      if [ $? -le 4 ]
+      then
+        rc=$OCF_SUCCESS
+      else
+        rc=$OCF_NOT_RUNNING
+      fi
+    else
+      MYCP=""
+      EXECMD=""
+
+      # WebAS Java 6.40+7.00
+      IAIK_JCE="$SECSTORE"/iaik_jce.jar
+      IAIK_JCE_EXPORT="$SECSTORE"/iaik_jce_export.jar
+      EXCEPTION="$BOOTSTRAP"/exception.jar
+      LOGGING="$BOOTSTRAP"/logging.jar
+      OPENSQLSTA="$BOOTSTRAP"/opensqlsta.jar
+      TC_SEC_SECSTOREFS="$BOOTSTRAP"/tc_sec_secstorefs.jar
+      JDDI="$BOOTSTRAP"/../server0/bin/ext/jdbdictionary/jddi.jar
+      ANTLR="$BOOTSTRAP"/../server0/bin/ext/antlr/antlr.jar
+      FRAME="$BOOTSTRAP"/../server0/bin/system/frame.jar
+  
+      # only start jdbcconnect when all jars available
+      if [ -f "$EXCEPTION" -a -f "$LOGGING" -a -f "$OPENSQLSTA" -a -f "$TC_SEC_SECSTOREFS" -a -f "$JDDI" -a -f "$ANTLR" -a -f "$FRAME" -a -f "$SAPDBCONNECT" ]
+      then
+        MYCP=".:$FRAME:$ANTLR:$JDDI:$IAIK_JCE_EXPORT:$IAIK_JCE:$EXCEPTION:$LOGGING:$OPENSQLSTA:$TC_SEC_SECSTOREFS:$DB_JARS:$SAPDBCONNECT" 
+        EXECMD="com.sap.inst.jdbc.connect.JdbcCon -sec $SID:$SID"
+      else
+      # WebAS Java 7.10
+        LAUNCHER=${BOOTSTRAP}/sap.com~tc~bl~offline_launcher~impl.jar
+
+        if [ -f "$DB_JARS" -a -f "$SAPDBCONNECT" -a -f "$LAUNCHER" ]
+        then
+          MYCP="$LAUNCHER"
+          EXECMD="com.sap.engine.offline.OfflineToolStart com.sap.inst.jdbc.connect.JdbcCon ${SAPDBCONNECT}:${SECSTORE}:${DB_JARS}:${BOOTSTRAP} -sec $SID:$SID"
+        fi
+      fi
+
+      if [ -n "$EXECMD" ]
+      then
+        output=`eval ${JAVA_HOME}/bin/java -cp $MYCP $EXECMD`
+        if [ $? -le 0 ]
+        then
+          rc=$OCF_SUCCESS
+        else
+          rc=$OCF_NOT_RUNNING
+        fi
+      else
+        output="Cannot find all jar files needed for database monitoring."
+        rc=$OCF_ERR_GENERIC
+      fi
+    fi
+  fi
+
+  if [ $rc -ne $OCF_SUCCESS ]
+  then
+    ocf_log err "The SAP database $SID ist not running: $output"
+  fi
+  return $rc
+}
+
+
+#
+# sapdatabase_status: Are there any database processes on this host ?
+#
+sapdatabase_status() {
+  case $DBTYPE in
+    ADA) SEARCH="$SID/db/pgm/kernel"
+         SUSER=`grep "^SdbOwner" /etc/opt/sdb | awk -F'=' '{print $2}'`
+         SNUM=2
+         ;;
+    ORA) SEARCH="ora_[a-z][a-z][a-z][a-z]_"
+         SUSER="ora`echo $SID | tr '[:upper:]' '[:lower:]'`"
+         SNUM=4
+         ;;
+    DB6) SEARCH="db2[a-z][a-z][a-z][a-z][a-z]"
+         SUSER="db2`echo $SID | tr '[:upper:]' '[:lower:]'`"
+         SNUM=5
+         ;;
+  esac
+
+  # Note: ps cuts off it's output at column $COLUMNS, so "ps -ef" can not be used here
+  # as the output might be to long.
+  cnt=`ps efo args --user $SUSER 2> /dev/null | grep -c "$SEARCH"`
+  if [ $cnt -ge $SNUM ]
+  then
+    rc=$OCF_SUCCESS
+  else
+    # ocf_log info "Database Instance $SID is not running on `hostname`"
+    rc=$OCF_NOT_RUNNING
+  fi
+  return $rc
+}
+
+
+#
+# sapdatabase_recover:
+#
+sapdatabase_recover() {
+
+  case $DBTYPE in
+    ORA) recoutput=`oracle_recover`
+         ;;
+    ADA) recoutput=`maxdb_recover`
+         ;;
+    DB6) recoutput=`db6udb_recover`
+         ;;
+  esac
+
+  sapdatabase_monitor 1
+  retcode=$?
+
+  if [ $retcode -eq $OCF_SUCCESS ]
+  then
+    ocf_log info "Recover of SAP database $SID was successful: $recoutput"
+  else
+    ocf_log err "Recover of SAP database $SID failed: $recoutput"
+  fi
+
+  return $retcode
+}
+
+
+#
+# sapdatabase_validate: Check the symantic of the input parameters 
+#
+sapdatabase_validate() {
+  rc=$OCF_SUCCESS
+  if [ `echo "$SID" | grep -c '^[A-Z][A-Z0-9][A-Z0-9]$'` -ne 1 ]
+  then
+    ocf_log err "Parsing parameter SID: '$SID' is not a valid system ID!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  case "$DBTYPE" in
+   ORA|ADA|DB6) ;;
+   *) ocf_log err "Parsing parameter DBTYPE: '$DBTYPE' is not a supported database type!"
+      rc=$OCF_ERR_ARGS ;;
+  esac
+
+  return $rc
+}
+
+
+#
+#	'main' starts here...
+#
+
+if
+  ( [ $# -ne 1 ] )
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+# These operations don't require OCF instance parameters to be set
+case "$1" in
+  meta-data)	meta_data
+		exit $OCF_SUCCESS;;
+
+  usage) 	usage
+		exit $OCF_SUCCESS;;
+
+  methods)	sapdatabase_methods
+		exit $?;;
+
+  *);;
+esac
+
+# Set a tempfile and make sure to clean it up again
+TEMPFILE="$(mktemp /tmp/SAPDatabase.tmp.XXXXXX)"
+trap trap_handler INT TERM
+
+# Everything after here must call do_exit to remove temp file
+
+
+US=`id -u -n`
+US=`echo $US`
+if
+  [ $US != root  ]
+then
+  ocf_log err "$0 must be run as root"
+  do_exit $OCF_ERR_PERM
+fi
+
+# mandatory parameter check
+if  [ -z "$OCF_RESKEY_SID" ]; then
+  ocf_log err "Please set OCF_RESKEY_SID to the SAP system id!"
+  do_exit $OCF_ERR_ARGS
+fi
+SID=`echo "$OCF_RESKEY_SID"`
+
+if [ -z "$OCF_RESKEY_DBTYPE" ]; then
+  ocf_log err "Please set OCF_RESKEY_DBTYPE to the database vendor specific tag (ORA,ADA,DB6)!"
+  do_exit $OCF_ERR_ARGS
+fi
+DBTYPE=`echo "$OCF_RESKEY_DBTYPE" | tr '[a-z]' '[A-Z]'`
+
+# optional OCF parameters, we try to guess which directories are correct
+EXESTARTDB="startdb"
+EXESTOPDB="stopdb"
+EXEDBCONNECT="R3trans"
+if [ -z "$OCF_RESKEY_DBJ2EE_ONLY" ]; then
+  DBJ2EE_ONLY=0
+else
+  case "$OCF_RESKEY_DBJ2EE_ONLY" in
+   1|true|TRUE|yes|YES) DBJ2EE_ONLY=1
+                        EXESTARTDB="startj2eedb"
+                        EXESTOPDB="stopj2eedb"
+                        EXEDBCONNECT="jdbcconnect.jar"
+                        ;;
+   0|false|FALSE|no|NO) DBJ2EE_ONLY=0;;
+   *) ocf_log err "Parsing parameter DBJ2EE_ONLY: '$DBJ2EE_ONLY' is not a boolean value!"
+      do_exit $OCF_ERR_ARGS ;;
+  esac
+fi
+
+if [ -z "$OCF_RESKEY_NETSERVICENAME" ]; then
+  case "$DBTYPE" in
+    ORA|ora) NETSERVICENAME="LISTENER";;
+    *)       NETSERVICENAME="";;
+  esac
+else
+  NETSERVICENAME="$OCF_RESKEY_NETSERVICENAME"
+fi
+
+if [ -z "$OCF_RESKEY_STRICT_MONITORING" ]; then
+  OCF_RESKEY_STRICT_MONITORING=0
+else
+  case "$OCF_RESKEY_STRICT_MONITORING" in
+   1|true|TRUE|yes|YES) OCF_RESKEY_STRICT_MONITORING=1;;
+   0|false|FALSE|no|NO) OCF_RESKEY_STRICT_MONITORING=0;;
+   *)  ocf_log err "Parsing parameter STRICT_MONITORING: '$OCF_RESKEY_STRICT_MONITORING' is not a boolean value!"
+       do_exit $OCF_ERR_ARGS ;;
+  esac
+fi
+
+PATHLIST="
+$OCF_RESKEY_DIR_EXECUTABLE
+/usr/sap/$SID/*/exe
+/usr/sap/$SID/SYS/exe/run
+/sapmnt/$SID/exe
+"
+DIR_EXECUTABLE=""
+for EXEPATH in $PATHLIST
+do
+  if [ -x $EXEPATH/$EXESTARTDB -a -x $EXEPATH/$EXESTOPDB -a -x $EXEPATH/$EXEDBCONNECT ]
+  then
+    DIR_EXECUTABLE=$EXEPATH
+    SAPSTARTDB=$EXEPATH/$EXESTARTDB
+    SAPSTOPDB=$EXEPATH/$EXESTOPDB
+    SAPDBCONNECT=$EXEPATH/$EXEDBCONNECT
+    break
+  fi
+done
+if [ -z "$DIR_EXECUTABLE" ]
+then
+  ocf_log warn "Cannot find $EXESTARTDB,$EXESTOPDB and $EXEDBCONNECT executable, please set DIR_EXECUTABLE parameter!"
+  do_exit $OCF_NOT_RUNNING
+fi
+
+if [ $DBJ2EE_ONLY -eq 1 ]
+then
+  if [ -n "$OCF_RESKEY_DIR_BOOTSTRAP" ]
+  then
+    BOOTSTRAP="$OCF_RESKEY_DIR_BOOTSTRAP"
+  else
+    BOOTSTRAP=`echo /usr/sap/$SID/*/j2ee/cluster/bootstrap | head -1`
+  fi
+
+  if [ -n "$OCF_RESKEY_DIR_SECSTORE" ]
+  then
+    SECSTORE="$OCF_RESKEY_DIR_SECSTORE"
+  else
+    SECSTORE=/usr/sap/$SID/SYS/global/security/lib/tools
+  fi
+
+  if [ -n "$OCF_RESKEY_JAVA_HOME" ]
+  then
+    JAVA_HOME="$OCF_RESKEY_JAVA_HOME"
+    PATH=$JAVA_HOME/bin:$PATH
+  else
+    if [ -n "$JAVA_HOME" ]
+    then
+      PATH=$JAVA_HOME/bin:$PATH
+    else
+      ocf_log err "Cannot find JAVA_HOME directory, please set JAVA_HOME parameter!"
+      do_exit $OCF_NOT_RUNNING
+    fi
+  fi
+
+  if [ -n "$OCF_RESKEY_DB_JARS" ]
+  then
+    DB_JARS=$OCF_RESKEY_DB_JARS
+  else
+    if [ -f "$BOOTSTRAP"/bootstrap.properties ]; then
+      DB_JARS=`cat $BOOTSTRAP/bootstrap.properties | grep -i rdbms.driverLocation | sed -e 's/\\\:/:/g' | awk -F= '{print $2}'`
+    fi
+  fi
+fi
+
+if [ -z "$OCF_RESKEY_AUTOMATIC_RECOVER" ]
+then
+  OCF_RESKEY_AUTOMATIC_RECOVER=0
+else
+  case "$OCF_RESKEY_AUTOMATIC_RECOVER" in
+   1|true|TRUE|yes|YES) OCF_RESKEY_AUTOMATIC_RECOVER=1;;
+   0|false|FALSE|no|NO) OCF_RESKEY_AUTOMATIC_RECOVER=0;;
+  esac
+fi
+
+# as root user we need the library path to the SAP kernel to be able to call executables
+if [ `echo $LD_LIBRARY_PATH | grep -c "^$DIR_EXECUTABLE\>"` -eq 0 ]; then
+  LD_LIBRARY_PATH=$DIR_EXECUTABLE${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH
+  export LD_LIBRARY_PATH
+fi
+sidadm="`echo $SID | tr '[:upper:]' '[:lower:]'`adm"
+
+# What kind of method was invoked?
+case "$1" in
+
+  start)	sapdatabase_start
+		do_exit $?;;
+
+  stop)		sapdatabase_stop
+		do_exit $?;;
+
+  monitor)
+          	sapdatabase_monitor $OCF_RESKEY_STRICT_MONITORING
+		do_exit $?;;
+
+  status)
+                sapdatabase_status
+                do_exit $?;;
+
+  recover)      sapdatabase_recover
+                do_exit $?;;
+
+  validate-all)	sapdatabase_validate
+		do_exit $?;;
+
+  *)		sapdatabase_methods
+		do_exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/rgmanager/src/resources/SAPInstance b/rgmanager/src/resources/SAPInstance
new file mode 100644
index 0000000..699796e
--- /dev/null
+++ b/rgmanager/src/resources/SAPInstance
@@ -0,0 +1,630 @@
+#!/bin/sh
+#
+# SAPInstance
+#
+# Description:	Manages a single SAP Instance as a High-Availability
+#		resource. One SAP Instance is defined by one 
+#               SAP Instance-Profile. start/stop handels all services
+#               of the START-Profile, status and monitor care only
+#               about essential services.
+#
+# Author:       Alexander Krauth, June 2006
+# Support:      linux at sap.com
+# License:      GNU General Public License (GPL)
+# Copyright:    (c) 2006, 2007 Alexander Krauth
+#
+# An example usage: 
+#      See usage() function below for more details...
+#
+# OCF instance parameters:
+#	OCF_RESKEY_InstanceName
+#	OCF_RESKEY_DIR_EXECUTABLE   (optional, well known directories will be searched by default)
+#	OCF_RESKEY_DIR_PROFILE      (optional, well known directories will be searched by default)
+#	OCF_RESKEY_START_PROFILE    (optional, well known directories will be searched by default)
+#	OCF_RESKEY_START_WAITTIME   (optional, to solve timing problems during J2EE-Addin start)
+#	OCF_RESKEY_AUTOMATIC_RECOVER    (optional, automatic startup recovery using cleanipc, default is false)
+#	OCF_RESKEY_PRE_START_USEREXIT	(optional, lists a script which can be executed before the resource is started)
+#	OCF_RESKEY_POST_START_USEREXIT	(optional, lists a script which can be executed after the resource is started)
+#	OCF_RESKEY_PRE_STOP_USEREXIT	(optional, lists a script which can be executed before the resource is stopped)
+#	OCF_RESKEY_POST_STOP_USEREXIT	(optional, lists a script which can be executed after the resource is stopped)
+#
+#######################################################################
+# Initialization:
+
+if [ -f $(dirname $0)/.ocf-shellfuncs ]; then
+        . $(dirname $0)/.ocf-shellfuncs
+elif [ -f $(dirname $0)/ocf-shellfuncs ]; then
+        LC_ALL=C
+        LANG=C
+        PATH=/bin:/sbin:/usr/bin:/usr/sbin
+        export LC_ALL LANG PATH
+        . $(dirname $0)/ocf-shellfuncs
+else
+        echo Could not find ocf-shellfuncs!
+        exit 1
+fi
+
+
+#######################################################################
+
+SH=/bin/sh
+
+usage() {
+  methods=`sapinstance_methods`
+  methods=`echo $methods | tr ' ' '|'`
+  cat <<-!
+	usage: $0 ($methods)
+
+	$0 manages a SAP Instance as an HA resource.
+
+	The 'start' operation starts the instance.
+	The 'stop' operation stops the instance.
+	The 'status' operation reports whether the instance is running
+	The 'monitor' operation reports whether the instance seems to be working
+	The 'validate-all' operation reports whether the parameters are valid
+	The 'methods' operation reports on the methods $0 supports
+
+	!
+}
+
+meta_data() {
+	cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent name="SAPInstance">
+<version>1.92.1</version>
+
+<longdesc lang="en">
+Resource script for SAP. It manages a SAP Instance as an HA resource.
+</longdesc>
+<shortdesc lang="en">SAP instance resource agent</shortdesc>
+
+<parameters>
+ <parameter name="InstanceName" unique="1" required="1" primary="1">
+  <longdesc lang="en">The full qualified SAP instance name. e.g. P01_DVEBMGS00_sapp01ci</longdesc>
+  <shortdesc lang="en">instance name: SID_INSTANCE_VIR-HOSTNAME</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DIR_EXECUTABLE" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find sapstartsrv and sapcontrol.</longdesc>
+  <shortdesc lang="en">path of sapstartsrv and sapcontrol</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="DIR_PROFILE" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find the SAP START profile.</longdesc>
+  <shortdesc lang="en">path of start profile</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="START_PROFILE" unique="0" required="0">
+  <longdesc lang="en">The name of the SAP START profile.</longdesc>
+  <shortdesc lang="en">start profile name</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="START_WAITTIME" unique="0" required="0">
+  <longdesc lang="en">After that time in seconds a monitor operation is executed by the resource agent. Does the monitor return SUCCESS, the start is handled as SUCCESS. This is useful to resolve timing problems with e.g. the J2EE-Addin instance.</longdesc>
+  <shortdesc lang="en">Check the successful start after that time (do not wait for J2EE-Addin)</shortdesc>
+  <content type="string" default="3600" />
+ </parameter>
+ <parameter name="AUTOMATIC_RECOVER" unique="0" required="0">
+  <longdesc lang="en">The SAPInstance resource agent tries to recover a failed start attempt automaticaly one time. This is done by killing runing instance processes and executing cleanipc.</longdesc>
+  <shortdesc lang="en">Enable or disable automatic startup recovery</shortdesc>
+  <content type="boolean" default="false"/>
+ </parameter>
+ <parameter name="PRE_START_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed before this resource gets started.</longdesc>
+  <shortdesc lang="en">path to a pre-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="POST_START_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed after this resource got started.</longdesc>
+  <shortdesc lang="en">path to a post-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="PRE_STOP_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed before this resource gets stopped.</longdesc>
+  <shortdesc lang="en">path to a pre-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+ <parameter name="POST_STOP_USEREXIT" unique="0" required="0">
+  <longdesc lang="en">The full qualified path where to find a script or program which should be executed after this resource got stopped.</longdesc>
+  <shortdesc lang="en">path to a post-start script</shortdesc>
+  <content type="string" default="" />
+ </parameter>
+</parameters>
+
+<actions>
+<action name="start" timeout="180" />
+<action name="stop" timeout="240" />
+<action name="status" timeout="60" depth="0" interval="120" start-delay="240" />
+<action name="monitor" depth="0" timeout="60" interval="120" start-delay="240" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+<action name="methods" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+
+#
+# methods: What methods/operations do we support?
+#
+sapinstance_methods() {
+  cat <<-!
+	start
+	stop
+	status
+	monitor
+	validate-all
+	methods
+	meta-data
+	usage
+	!
+}
+
+#
+# setup_limits: If sapstartsrv needs to be started by this resource agent we need to ensure that any resource
+#               limits configured in /usr/sap/sapservices are applied.
+#               Since sapstartsrv is started as root and then it downgrades its privileges by calling setuid() and
+#               setgid() any PAM limits at /etc/security/limits.conf are not applied.
+#               Should sapstartsrv need to be started, we look for values configured at /usr/sap/sapservices (as
+#               per SAP note 1437105) and, if found, we apply them before starting sapstartsrv.
+#               Instance processes are started by sapstartsrv and will inherit resource limits from it.
+#
+setup_limits() {
+  if [ -r $SAPSERVICES ]
+  then
+    descriptors=`grep "^limit.descriptors" $SAPSERVICES | sed -e "s/limit.descriptors=//" `
+    if [ -n $descriptors ]
+    then
+      ocf_log info "found valid open file descriptors limit at ${SAPSERVICES}: ${descriptors}, applying..."
+      eval ulimit -n $descriptors
+    fi
+
+    stacksize=`grep "^limit.stacksize" $SAPSERVICES | sed -e "s/limit.stacksize=//" `
+    if [ -n $stacksize ]
+    then
+      ocf_log info "found valid stack size limit at ${SAPSERVICES}: ${stacksize}, applying..."
+      eval ulimit -s $stacksize
+    fi
+
+    datasize=`grep "^limit.datasize" $SAPSERVICES | sed -e "s/limit.datasize=//" `
+    if [ -n $datasize ]
+    then
+      ocf_log info "found valid process data segment size limit at ${SAPSERVICES}: ${datasize}, applying..."
+      eval ulimit -d $datasize
+    fi
+  fi
+}
+
+#
+# check_sapstartsrv : Before using sapcontrol we make sure that the sapstartsrv is running for the correct instance.
+#                     We cannot use sapinit and the /usr/sap/sapservices file in case of an enquerep instance,
+#                     because then we have two instances with the same instance number.
+#
+check_sapstartsrv() {
+  restart=0
+  runninginst=""
+  chkrc=$OCF_SUCCESS
+
+  output=`$SAPCONTROL -nr $InstanceNr -function ParameterValue INSTANCE_NAME -format script`
+  if [ $? -eq 0 ]
+  then
+    runninginst=`echo "$output" | grep '^0 : ' | cut -d' ' -f3`
+    if [ "$runninginst" != "$InstanceName" ]
+    then 
+      ocf_log warn "sapstartsrv is running for instance $runninginst, that service will be killed"
+      restart=1
+    fi
+  else
+    ocf_log warn "sapstartsrv is not running for instance $SID-$InstanceName, it will be started now"
+    restart=1
+  fi
+
+  if [ -z "$runninginst" ]; then runninginst=$InstanceName; fi
+
+  if [ $restart -eq 1 ]
+  then
+    pkill -9 -f "sapstartsrv.*$runninginst"
+  
+    setup_limits
+    $SAPSTARTSRV pf=$SAPSTARTPROFILE -D -u $sidadm
+
+    # now make sure the daemon has been started and is able to respond
+    srvrc=1
+    while [ $srvrc -eq 1 -a `pgrep -f "sapstartsrv.*$runninginst" | wc -l` -gt 0 ]
+    do
+      sleep 1
+      $SAPCONTROL -nr $InstanceNr -function GetProcessList > /dev/null 2>&1
+      srvrc=$?
+    done
+
+    if [ $srvrc -ne 1 ]
+    then
+      ocf_log info "sapstartsrv for instance $SID-$InstanceName was restarted !"
+      chkrc=$OCF_SUCCESS
+    else
+      ocf_log error "sapstartsrv for instance $SID-$InstanceName could not be started!"
+      chkrc=$OCF_NOT_RUNNING
+    fi
+  fi
+
+  return $chkrc
+}
+
+
+#
+# sapuserexit : Many SAP customers need some additional processes/tools to run their SAP systems.
+#               This specialties do not allow a totally generic SAP cluster resource agent.
+#               Someone should write a resource agent for each additional process you need, if it
+#               is required to monitor that process within the cluster manager. To enable 
+#               you to extent this resource agent without developing a new one, this user exit
+#               was introduced.
+#
+sapuserexit() {
+  NAME="$1"
+  VALUE="$2"
+
+  if [ -n "$VALUE" ]
+  then
+    if [ -x "$VALUE" ]
+    then
+      ocf_log info "Calling userexit ${NAME} with customer script file ${VALUE}"
+      eval "$VALUE" > /dev/null 2>&1
+      ocf_log info "Exiting userexit ${NAME} with customer script file ${VALUE}, returncode: $?"
+    else
+      ocf_log warn "Attribute ${NAME} is set to ${VALUE}, but this file is not executable"
+    fi
+  fi
+  return 0
+}
+
+
+#
+# cleanup_instance : remove resources (processes and shared memory) from a crashed instance)
+#
+cleanup_instance() {
+  pkill -9 -f -U $sidadm $InstanceName
+  $DIR_EXECUTABLE/cleanipc $InstanceNr remove
+  return 0
+}
+
+#
+# sapinstance_start : Start the SAP instance
+#
+sapinstance_start() {
+
+  sapuserexit PRE_START_USEREXIT "$OCF_RESKEY_PRE_START_USEREXIT"
+
+  rc=$OCF_NOT_RUNNING
+  loopcount=0
+  while [ $loopcount -lt 2 ]
+  do
+    loopcount=$(($loopcount + 1))
+
+    check_sapstartsrv
+    output=`$SAPCONTROL -nr $InstanceNr -function Start`
+    rc=$?
+    ocf_log info "Starting SAP Instance $SID-$InstanceName: $output"
+
+    if [ $rc -ne 0 ]
+    then
+      ocf_log err "SAP Instance $SID-$InstanceName start failed."
+      return $OCF_ERR_GENERIC
+    fi
+
+    startrc=1
+    while [ $startrc -gt 0 ]
+    do
+      waittime_start=`date +%s`
+      output=`$SAPCONTROL -nr $InstanceNr -function WaitforStarted $OCF_RESKEY_START_WAITTIME 10`
+      startrc=$?
+      waittime_stop=`date +%s`
+
+      if [ $startrc -ne 0 ]
+      then
+        if [ $(($waittime_stop - $waittime_start)) -ge $OCF_RESKEY_START_WAITTIME ]
+        then
+          sapinstance_monitor NOLOG
+          if [ $? -eq $OCF_SUCCESS ]
+          then
+            output="START_WAITTIME ($OCF_RESKEY_START_WAITTIME) has elapsed, but instance monitor returned SUCCESS. Instance considered running."
+            startrc=0; loopcount=2
+          fi
+        else
+          if [ $loopcount -eq 1 -a $OCF_RESKEY_AUTOMATIC_RECOVER -eq 1 ]
+          then
+            ocf_log warn "SAP Instance $SID-$InstanceName start failed: $output"
+            ocf_log warn "Try to recover $SID-$InstanceName"
+            cleanup_instance
+          else
+            loopcount=2
+          fi
+          startrc=-1
+        fi
+      else
+        loopcount=2
+      fi
+    done
+  done
+
+  if [ $startrc -eq 0 ]
+  then
+    ocf_log info "SAP Instance $SID-$InstanceName started: $output"
+    rc=$OCF_SUCCESS
+    sapuserexit POST_START_USEREXIT "$OCF_RESKEY_POST_START_USEREXIT"
+  else
+    ocf_log err "SAP Instance $SID-$InstanceName start failed: $output"
+    rc=$OCF_NOT_RUNNING
+  fi
+
+  return $rc
+}
+
+
+#
+# sapinstance_recover: Try startup of failed instance by cleaning up resources
+#
+sapinstance_recover() {
+  cleanup_instance
+  sapinstance_start
+  return $?
+}
+
+
+#
+# sapinstance_stop: Stop the SAP instance
+#
+sapinstance_stop() {
+  sapuserexit PRE_STOP_USEREXIT "$OCF_RESKEY_PRE_STOP_USEREXIT"
+
+  check_sapstartsrv
+
+  output=`$SAPCONTROL -nr $InstanceNr -function Stop`
+  if [ $? -eq 0 ]
+  then
+    output=`$SAPCONTROL -nr $InstanceNr -function WaitforStopped 3600 1`
+    if [ $? -eq 0 ]
+    then
+      ocf_log info "SAP Instance $SID-$InstanceName stopped: $output"
+      rc=$OCF_SUCCESS
+    else
+      ocf_log err "SAP Instance $SID-$InstanceName stop failed: $output"
+      rc=$OCF_ERR_GENERIC
+    fi
+  else
+    ocf_log err "SAP Instance $SID-$InstanceName stop failed: $output"
+    rc=$OCF_ERR_GENERIC
+  fi
+
+  sapuserexit POST_STOP_USEREXIT "$OCF_RESKEY_POST_STOP_USEREXIT"
+
+  return $rc
+}
+
+
+#
+# sapinstance_monitor: Can the given SAP instance do anything useful?
+#
+sapinstance_monitor() {
+  MONLOG=$1
+  check_sapstartsrv
+  rc=$?
+
+  if [ $rc -eq $OCF_SUCCESS ]
+  then
+    count=0
+    LOCALHOST=`hostname`
+    output=`$SAPCONTROL -nr $InstanceNr -host $LOCALHOST -function GetProcessList -format script`
+
+    # we have to parse the output, because the returncode doesn't tell anything about the instance status
+    for SERVNO in `echo "$output" | grep '^[0-9] ' | cut -d' ' -f1 | sort -u`
+    do
+      COLOR=`echo "$output" | grep "^$SERVNO dispstatus: " | cut -d' ' -f3`
+      SERVICE=`echo "$output" | grep "^$SERVNO name: " | cut -d' ' -f3`
+      STATE=0
+
+      case $COLOR in
+        GREEN|YELLOW)       STATE=$OCF_SUCCESS;;
+        *)                  STATE=$OCF_NOT_RUNNING;;
+      esac 
+
+      case $SERVICE in
+        disp+work|msg_server|enserver|enrepserver|jcontrol|jstart)
+                      if [ $STATE -eq $OCF_NOT_RUNNING ]
+                      then
+                        if [ "$MONLOG" != "NOLOG" ]
+                        then
+                          ocf_log err "SAP instance service $SERVICE is not running with status $COLOR !"
+                        fi
+                        rc=$STATE
+                      fi
+                      count=1;;
+        *);;
+      esac
+    done
+
+    if [ $count -eq 0 -a $rc -eq $OCF_SUCCESS ]
+    then
+      if [ "$MONLOG" != "NOLOG" ]
+      then
+        ocf_log err "The SAP instance does not run any services which this RA could monitor!"
+      fi
+      rc=$OCF_ERR_ARGS
+    fi
+  fi
+  
+  return $rc
+}
+
+#
+# sapinstance_validate: Check the symantic of the input parameters 
+#
+sapinstance_validate() {
+  rc=$OCF_SUCCESS
+  if [ `echo "$SID" | grep -c '^[A-Z][A-Z0-9][A-Z0-9]$'` -ne 1 ]
+  then
+    ocf_log err "Parsing instance profile name: '$SID' is not a valid system ID!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  if [ `echo "$InstanceName" | grep -c '^[A-Z].*[0-9][0-9]$'` -ne 1 ]
+  then
+    ocf_log err "Parsing instance profile name: '$InstanceName' is not a valid instance name!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  if [ `echo "$InstanceNr" | grep -c '^[0-9][0-9]$'` -ne 1 ]
+  then
+    ocf_log err "Parsing instance profile name: '$InstanceNr' is not a valid instance number!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  if [ `echo "$SAPVIRHOST" | grep -c '^[A-Za-z][A-Za-z0-9_-]*$'` -ne 1 ]
+  then
+    ocf_log err "Parsing instance profile name: '$SAPVIRHOST' is not a valid hostname!"
+    rc=$OCF_ERR_ARGS
+  fi
+
+  return $rc
+}
+
+
+#
+#	'main' starts here...
+#
+
+if
+  ( [ $# -ne 1 ] )
+then
+  usage
+  exit $OCF_ERR_ARGS
+fi
+
+# These operations don't require OCF instance parameters to be set
+case "$1" in
+  meta-data)	meta_data
+		exit $OCF_SUCCESS;;
+
+  usage) 	usage
+		exit $OCF_SUCCESS;;
+
+  methods)	sapinstance_methods
+		exit $?;;
+
+  *);;
+esac
+
+US=`id -u -n`
+US=`echo $US`
+if
+  [ $US != root  ]
+then
+  ocf_log err "$0 must be run as root"
+  exit $OCF_ERR_PERM
+fi
+
+# parameter check
+if  [ -z "$OCF_RESKEY_InstanceName" ]
+then
+  ocf_log err "Please set OCF_RESKEY_InstanceName to the name to the SAP instance profile!"
+  exit $OCF_ERR_ARGS
+fi
+
+SID=`echo "$OCF_RESKEY_InstanceName" | cut -d_ -f1`
+InstanceName=`echo "$OCF_RESKEY_InstanceName" | cut -d_ -f2`
+InstanceNr=`echo "$InstanceName" | sed 's/.*\([0-9][0-9]\)$/\1/'`
+SAPVIRHOST=`echo "$OCF_RESKEY_InstanceName" | cut -d_ -f3`
+
+# optional OCF parameters, we try to guess which directories are correct
+if  [ -z "$OCF_RESKEY_DIR_EXECUTABLE" ]
+then
+  if [ -x /usr/sap/$SID/$InstanceName/exe/sapstartsrv -a -x /usr/sap/$SID/$InstanceName/exe/sapcontrol ]
+  then
+    DIR_EXECUTABLE="/usr/sap/$SID/$InstanceName/exe"
+    SAPSTARTSRV="/usr/sap/$SID/$InstanceName/exe/sapstartsrv"
+    SAPCONTROL="/usr/sap/$SID/$InstanceName/exe/sapcontrol"
+  elif [ -x /usr/sap/$SID/SYS/exe/run/sapstartsrv -a -x /usr/sap/$SID/SYS/exe/run/sapcontrol ]
+  then
+    DIR_EXECUTABLE="/usr/sap/$SID/SYS/exe/run"
+    SAPSTARTSRV="/usr/sap/$SID/SYS/exe/run/sapstartsrv"
+    SAPCONTROL="/usr/sap/$SID/SYS/exe/run/sapcontrol"
+  else
+    ocf_log warn "Cannot find sapstartsrv and sapcontrol executable, please set DIR_EXECUTABLE parameter!"
+    exit $OCF_NOT_RUNNING
+  fi
+else
+  DIR_EXECUTABLE="$OCF_RESKEY_DIR_EXECUTABLE"
+  SAPSTARTSRV="$OCF_RESKEY_DIR_EXECUTABLE/sapstartsrv"
+  SAPCONTROL="$OCF_RESKEY_DIR_EXECUTABLE/sapcontrol"
+fi
+
+if [ -z "$OCF_RESKEY_DIR_PROFILE" ]
+then
+  if [ -d /usr/sap/$SID/SYS/profile/ ]
+  then
+    DIR_PROFILE="/usr/sap/$SID/SYS/profile"
+  else
+    ocf_log warn "Expected /usr/sap/$SID/SYS/profile/ to be a directory, please set DIR_PROFILE parameter!"
+    exit $OCF_NOT_RUNNING
+  fi
+else
+  DIR_PROFILE="$OCF_RESKEY_DIR_PROFILE"
+fi
+
+if [ -z "$OCF_RESKEY_START_PROFILE" ]
+then
+  SAPSTARTPROFILE="$DIR_PROFILE/START_${InstanceName}_${SAPVIRHOST}"
+  if [ ! -r $SAPSTARTPROFILE ]
+  then
+    ocf_log warn "Expected $SAPSTARTPROFILE to be the instance START profile, please set START_PROFILE parameter!"
+    exit $OCF_NOT_RUNNING
+  fi
+else
+  SAPSTARTPROFILE="$OCF_RESKEY_START_PROFILE"
+fi
+
+if [ -z "$OCF_RESKEY_START_WAITTIME" ]
+then
+  OCF_RESKEY_START_WAITTIME=3600
+fi
+
+
+if [ -z "$OCF_RESKEY_AUTOMATIC_RECOVER" ]
+then
+  OCF_RESKEY_AUTOMATIC_RECOVER=0
+else
+  case "$OCF_RESKEY_AUTOMATIC_RECOVER" in
+   1|true|TRUE|yes|YES) OCF_RESKEY_AUTOMATIC_RECOVER=1;;
+   0|false|FALSE|no|NO) OCF_RESKEY_AUTOMATIC_RECOVER=0;;
+  esac
+fi
+
+# as root user we need the library path to the SAP kernel to be able to call sapcontrol
+if [ `echo $LD_LIBRARY_PATH | grep -c "^$DIR_EXECUTABLE\>"` -eq 0 ]; then
+  LD_LIBRARY_PATH=$DIR_EXECUTABLE${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH
+  export LD_LIBRARY_PATH
+fi
+sidadm="`echo $SID | tr '[:upper:]' '[:lower:]'`adm"
+
+SAPSERVICES=/usr/sap/sapservices
+
+# What kind of method was invoked?
+case "$1" in
+
+  start)	sapinstance_start
+		exit $?;;
+
+  stop)		sapinstance_stop
+		exit $?;;
+
+  status|monitor)
+          	sapinstance_monitor
+		exit $?;;
+
+  validate-all)	sapinstance_validate
+		exit $?;;
+
+  *)		sapinstance_methods
+		exit $OCF_ERR_UNIMPLEMENTED;;
+esac
diff --git a/rgmanager/src/resources/apache.metadata b/rgmanager/src/resources/apache.metadata
new file mode 100644
index 0000000..93d5fd8
--- /dev/null
+++ b/rgmanager/src/resources/apache.metadata
@@ -0,0 +1,96 @@
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent version="rgmanager 2.0" name="apache">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines an instance of Apache web server
+    </longdesc>
+    <shortdesc lang="en">
+        Defines an Apache web server
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+	        Define a name for use in <IfDefine name> directive.
+	    </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="server_root">
+            <longdesc lang="en">
+                Define an alternate initial ServerRoot
+            </longdesc>
+            <shortdesc lang="en">
+                Initial ServerRoot
+            </shortdesc>
+	    <content type="string" default="/etc/httpd"/>
+        </parameter>
+
+        <parameter name="config_file">
+            <longdesc lang="en">
+                Define an alternate ServerConfigFile
+            </longdesc>
+            <shortdesc lang="en">
+                Initial ServerConfigFile
+            </shortdesc>
+            <content type="string" default="conf/httpd.conf"/>
+        </parameter>
+
+	<parameter name="httpd_options">
+	    <longdesc lang="en">
+		Other command-line options for httpd
+	    </longdesc>
+	    <shortdesc lang="en">
+		Other command-line options for httpd
+	    </shortdesc>
+	    <content type="string" />
+	</parameter>
+
+	<parameter name="shutdown_wait">
+	    <longdesc lang="en">
+		Wait X seconds for correct end of service shutdown
+	    </longdesc>
+	    <shortdesc lang="en">
+		Wait X seconds for correct end of service shutdown
+	    </shortdesc>
+	    <content type="integer" />
+	</parameter>
+
+        <parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+	    	Inherit the service name.  We need to know
+		the service name in order to determine file
+		systems and IPs for this service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Inherit the service name.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="0"/>
+	<action name="stop" timeout="0"/>
+
+	<!-- Checks to see if it''s mounted in the right place -->
+	<action name="status" interval="1m" timeout="10"/>
+	<action name="monitor" interval="1m" timeout="10"/>
+
+	<!-- Checks to see if we can read from the mountpoint -->
+	<action name="status" depth="10" timeout="30" interval="5m"/>
+	<action name="monitor" depth="10" timeout="30" interval="5m"/>
+
+	<action name="meta-data" timeout="1"/>
+	<action name="validate-all" timeout="1"/>
+    </actions>
+
+    <special tag="rgmanager">
+    </special>
+</resource-agent>
diff --git a/rgmanager/src/resources/apache.sh b/rgmanager/src/resources/apache.sh
new file mode 100755
index 0000000..a428780
--- /dev/null
+++ b/rgmanager/src/resources/apache.sh
@@ -0,0 +1,290 @@
+#!/bin/bash
+
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+export LC_ALL=C
+export LANG=C
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+if [ -x /usr/sbin/httpd ]; then
+	declare APACHE_HTTPD=/usr/sbin/httpd
+elif [ -x /usr/sbin/apache2 ]; then
+	declare APACHE_HTTPD=/usr/sbin/apache2
+fi
+declare APACHE_serverConfigFile
+declare APACHE_pid_file="`generate_name_for_pid_file`"
+declare APACHE_conf_dir="`generate_name_for_conf_dir`"
+declare APACHE_genConfig="$APACHE_conf_dir/httpd.conf"
+
+declare APACHE_parseConfig=$(dirname $0)/utils/httpd-parse-config.pl
+
+apache_serverConfigFile()
+{
+	if $(echo $OCF_RESKEY_config_file | grep -q "^/"); then
+		APACHE_serverConfigFile="$OCF_RESKEY_config_file"
+	else 
+		APACHE_serverConfigFile="$OCF_RESKEY_server_root/$OCF_RESKEY_config_file"
+	fi
+
+	return;
+}
+
+verify_all()
+{
+	clog_service_verify $CLOG_INIT 
+
+	if [ -z "$OCF_RESKEY_name" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid Name Of Service"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_service_name" ]; then
+		clog_service_verify $CLOG_FAILED_NOT_CHILD
+		return $OCF_ERR_ARGS
+	fi
+                                                	
+	if [ -z "$OCF_RESKEY_server_root" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid ServerRoot"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ ! -d "$OCF_RESKEY_server_root" ]; then
+		clog_service_verify $CLOG_FAILED "ServerRoot Directory Is Missing"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_INVALID "$OCF_RESKEY_config_file"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ ! -r "$APACHE_serverConfigFile" ]; then
+		clog_check_file_exist $CLOG_FAILED_NOT_READABLE "$APACHE_serverConfigFile"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$APACHE_pid_file" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid name of PID file"
+		return $OCF_ERR_ARGS
+	fi
+
+	clog_check_syntax $CLOG_INIT "$APACHE_serverConfigFile"
+
+	"$APACHE_HTTPD" -t \
+		-D"$OCF_RESKEY_name" \
+		-d "$OCF_RESKEY_server_root" \
+		-f "$APACHE_serverConfigFile" \
+		$OCF_RESKEY_httpd_options &> /dev/null
+		
+	if [ $? -ne 0 ]; then
+		clog_check_syntax $CLOG_FAILED "$APACHE_serverConfigFile"
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_check_syntax $CLOG_SUCCEED "$APACHE_serverConfigFile"
+
+	return 0
+}
+
+generate_configFile()
+{
+	declare originalConfigFile=$1;
+	declare generatedConfigFile=$2;
+	declare ip_addresses=$3;
+
+	if [ -f "$generatedConfigFile" ]; then
+		sha1_verify "$generatedConfigFile"
+		if [ $? -ne 0 ]; then
+			clog_check_sha1 $CLOG_FAILED
+			return 0
+		fi
+	fi	
+
+	clog_generate_config $CLOG_INIT "$originalConfigFile" "$generatedConfigFile"
+
+	generate_configTemplate "$generatedConfigFile" "$1"
+	cat >> "$generatedConfigFile" << EOT
+# From a cluster perspective, the key fields are:
+#     Listen - must be set to service floating IP address.
+#     ServerRoot - path to the ServerRoot (initial value is set in service conf)
+#
+
+EOT
+
+	IFS_old="$IFS"
+	IFS=$'\n'
+	for i in `"$APACHE_parseConfig" -D"$OCF_RESKEY_name" < "$originalConfigFile" | grep -P '(^Listen)|(^Port)' `; do 
+		port=`echo $i | sed 's/^Listen \(.*\)/\1/;s/^Port \(.*\)/\1/'`;
+		testcond=`echo $port|grep :`
+		if [ $testcond ]; then
+			port=`echo $port|awk -F : '{print $2}'`
+		fi
+		IFS=$' ';
+		for z in $ip_addresses; do
+			if [ "${z//:/}" != "$z" ]; then
+				echo "Listen [$z]:$port" >> "$generatedConfigFile";
+			else
+				echo "Listen $z:$port" >> "$generatedConfigFile";
+			fi
+		done
+		IFS=$'\n';
+	done;
+	IFS="$IFS_old"
+
+	echo "PidFile \"$APACHE_pid_file\"" >> "$generatedConfigFile";
+	echo >> "$generatedConfigFile"
+
+	cat "$originalConfigFile" | sed 's/^Listen/### Listen/;s/^Port/### Port/;s/^PidFile/### PidFile/' | \
+	"$APACHE_parseConfig" -D"$OCF_RESKEY_name" >> "$generatedConfigFile"
+
+	sha1_addToFile "$generatedConfigFile"
+	clog_generate_config $CLOG_SUCCEED "$originalConfigFile" "$generatedConfigFile"
+}
+
+start()
+{
+	if status; then
+		ocf_log info "Starting Service $OCF_RESOURCE_INSTANCE > Already running"
+		return $OCF_SUCCESS
+	fi
+
+	declare ip_addresses
+
+	clog_service_start $CLOG_INIT	
+
+	create_pid_directory
+	create_conf_directory "$APACHE_conf_dir"
+	check_pid_file "$APACHE_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_check_pid $CLOG_FAILED "$APACHE_pid_file"
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_looking_for $CLOG_INIT "IP Addresses"
+
+	get_service_ip_keys "$OCF_RESKEY_service_name"
+	ip_addresses=`build_ip_list`
+
+	if [ -z "$ip_addresses" ]; then
+		clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Addresses"
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_looking_for $CLOG_SUCCEED "IP Addresses"
+
+	generate_configFile "$APACHE_serverConfigFile" "$APACHE_genConfig" "$ip_addresses"
+
+	"$APACHE_HTTPD" \
+		"-D$OCF_RESKEY_name" \
+		-d "$OCF_RESKEY_server_root" \
+		-f "$APACHE_genConfig" \
+		$OCF_RESKEY_httpd_options \
+		-k start
+
+	if [ $? -ne 0 ]; then
+		clog_service_start $CLOG_FAILED		
+		return $OCF_ERR_GENERIC
+	else
+		clog_service_start $CLOG_SUCCEED
+	fi
+
+	return 0;
+}
+
+stop()
+{
+	clog_service_stop $CLOG_INIT
+
+	stop_generic "$APACHE_pid_file" "$OCF_RESKEY_shutdown_wait"
+	
+	if [ $? -ne 0 ]; then
+		clog_service_stop $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_service_stop $CLOG_SUCCEED
+	return 0;
+}
+
+status()
+{
+	clog_service_status $CLOG_INIT
+
+	status_check_pid "$APACHE_pid_file"
+	case $? in
+		$OCF_NOT_RUNNING)
+			clog_service_status $CLOG_FAILED "$APACHE_pid_file"
+			return $OCF_NOT_RUNNING
+			;;
+		0)
+			clog_service_status $CLOG_SUCCEED
+			exit 0
+			;;
+		*)
+			clog_service_status $CLOG_FAILED "$APACHE_pid_file"
+			return $OCF_ERR_GENERIC
+			;;
+	esac
+}
+
+if [ "$1" != "meta-data" ]; then
+	apache_serverConfigFile
+fi;
+		
+case $1 in
+	meta-data)
+		cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+		exit 0
+		;;
+	validate-all|verify-all)
+		verify_all
+		exit $?
+		;;
+	start)
+		verify_all && start
+		exit $?
+		;;
+	stop)
+		verify_all && stop
+		exit $?
+		;;
+	status|monitor)
+		verify_all
+		status
+		exit $?
+		;;
+	restart)
+		verify_all
+		stop
+		start
+		exit $?
+		;;
+	*)
+		echo "Usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
diff --git a/rgmanager/src/resources/clusterfs.sh b/rgmanager/src/resources/clusterfs.sh
new file mode 100755
index 0000000..07fd73b
--- /dev/null
+++ b/rgmanager/src/resources/clusterfs.sh
@@ -0,0 +1,341 @@
+#!/bin/bash
+
+#
+# Cluster File System mount/umount/fsck/etc. agent
+#
+# Copyright (C) 2000 Mission Critical Linux
+# Copyright (C) 2002-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+. $(dirname $0)/utils/fs-lib.sh
+
+do_metadata()
+{
+	cat <<EOT
+<?xml version="1.0" ?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent name="clusterfs" version="rgmanager 2.0">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines a cluster file system mount (i.e. GFS)
+    </longdesc>
+    <shortdesc lang="en">
+        Defines a cluster file system mount.
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+	        Symbolic name for this file system.
+	    </longdesc>
+            <shortdesc lang="en">
+                File System Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="mountpoint" unique="1" required="1">
+	    <longdesc lang="en">
+	        Path in file system heirarchy to mount this file system.
+	    </longdesc>
+            <shortdesc lang="en">
+                Mount Point
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="device" unique="1" required="1">
+	    <longdesc lang="en">
+	        Block device, file system label, or UUID of file system.
+	    </longdesc>
+            <shortdesc lang="en">
+                Device or Label
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="fstype">
+	    <longdesc lang="en">
+	        File system type.  If not specified, mount(8) will attempt to
+		determine the file system type.
+	    </longdesc>
+            <shortdesc lang="en">
+                File system type
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="force_unmount">
+            <longdesc lang="en">
+                If set, the cluster will kill all processes using 
+                this file system when the resource group is 
+                stopped.  Otherwise, the unmount will fail, and
+                the resource group will be restarted.
+            </longdesc>
+            <shortdesc lang="en">
+                Force Unmount
+            </shortdesc>
+	    <content type="boolean"/>
+        </parameter>
+
+	<parameter name="self_fence">
+	    <longdesc lang="en">
+	        If set and unmounting the file system fails, the node will
+		immediately reboot.  Generally, this is used in conjunction
+		with force_unmount support, but it is not required.
+	    </longdesc>
+	    <shortdesc lang="en">
+	        Seppuku Unmount
+	    </shortdesc>
+	    <content type="boolean"/>
+	</parameter>
+
+	<parameter name="fsid">
+	    <longdesc lang="en">
+	    	File system ID for NFS exports.  This can be overridden
+		in individual nfsclient entries.
+	    </longdesc>
+	    <shortdesc lang="en">
+	    	NFS File system ID
+	    </shortdesc>
+	    <content type="string"/>
+	</parameter>
+
+	<parameter name="nfslock" inherit="service%nfslock">
+	    <longdesc lang="en">
+	        If set, the node will try to kill lockd and issue 
+		reclaims across all remaining network interface cards.
+		This happens always, regardless of unmounting failed.
+	    </longdesc>
+	    <shortdesc lang="en">
+	        Enable NFS lock workarounds
+	    </shortdesc>
+	    <content type="boolean"/>
+	</parameter>
+
+	<parameter name="nfsrestart">
+	    <longdesc lang="en">
+		If set and unmounting the file system fails, the node will
+		try to restart nfs daemon and nfs lockd to drop all filesystem
+		references. Use this option as last resource.
+		This option requires force_unmount to be set and it is not
+		compatible with nfsserver resource.
+	    </longdesc>
+	    <shortdesc lang="en">
+		Enable NFS daemon and lockd workaround
+	    </shortdesc>
+	    <content type="boolean"/>
+	</parameter>
+
+        <parameter name="options">
+            <longdesc lang="en">
+                Options used when the file system is mounted.  These
+                are often file-system specific.  See mount(8) and/or
+                mount.gfs2(8) for supported mount options.
+            </longdesc>
+            <shortdesc lang="en">
+                Mount Options
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="use_findmnt">
+            <longdesc lang="en">
+        Use findmnt to determine if and where a filesystem is mounted.
+        Disabling this uses the failback method (should be used if autofs
+        maps are located on network storage (ie. nfs, iscsi, etc).
+            </longdesc>
+            <shortdesc lang="en">
+        Utilize findmnt to detect if and where filesystems are mounted
+            </shortdesc>
+            <content type="boolean"/>
+        </parameter>
+
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="900"/>
+	<action name="stop" timeout="30"/>
+	<!-- Recovery isn't possible; we don't know if resources are using
+	     the file system. -->
+
+	<!-- Checks to see if it's mounted in the right place -->
+	<action name="status" interval="1m" timeout="10"/>
+	<action name="monitor" interval="1m" timeout="10"/>
+
+	<!-- Checks to see if we can read from the mountpoint -->
+	<action name="status" depth="10" timeout="30" interval="5m"/>
+	<action name="monitor" depth="10" timeout="30" interval="5m"/>
+
+	<!-- Checks to see if we can write to the mountpoint (if !ROFS) -->
+	<action name="status" depth="20" timeout="30" interval="10m"/>
+	<action name="monitor" depth="20" timeout="30" interval="10m"/>
+
+	<action name="meta-data" timeout="5"/>
+	<action name="validate-all" timeout="5"/>
+    </actions>
+
+    <special tag="rgmanager">
+    	<child type="fs" start="1" stop="3"/>
+    	<child type="clusterfs" start="1" stop="3"/>
+        <child type="nfsexport" start="3" stop="1"/>
+    </special>
+</resource-agent>
+EOT
+}
+
+
+verify_fstype()
+{
+	# Auto detect?
+	[ -z "$OCF_RESKEY_fstype" ] && return $OCF_SUCCESS
+
+	case $OCF_RESKEY_fstype in
+	gfs|gfs2)
+		return $OCF_SUCCESS
+		;;
+	*)
+		ocf_log err "File system type $OCF_RESKEY_fstype not supported"
+		return $OCF_ERR_ARGS
+		;;
+	esac
+}
+
+
+verify_options()
+{
+	declare -i ret=$OCF_SUCCESS
+
+	#
+	# From mount(8)
+	#
+	for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do
+		case $o in
+		async|atime|auto|defaults|dev|exec|_netdev|noatime)
+			continue
+			;;
+		noauto|nodev|noexec|nosuid|nouser|ro|rw|suid|sync)
+			continue
+			;;
+		dirsync|user|users)
+			continue
+			;;
+		esac
+
+		case $OCF_RESKEY_fstype in
+		gfs)
+			case $o in
+				lockproto=*|locktable=*|hostdata=*)
+					continue;
+					;;
+				localcaching|localflocks|ignore_local_fs)
+					continue;
+					;;
+				num_glockd|acl|suiddir)	
+					continue
+					;;
+			esac
+			;;
+		gfs2)
+			# XXX
+			continue
+			;;
+		esac
+
+
+		ocf_log err "Option $o not supported for $OCF_RESKEY_fstype"
+		ret=$OCF_ERR_ARGS
+	done
+
+	return $ret
+}
+
+
+do_verify()
+{
+	verify_name || return $OCF_ERR_ARGS
+	verify_fstype || return $OCF_ERR_ARGS
+	verify_device || return $OCF_ERR_ARGS
+	verify_mountpoint || return $OCF_ERR_ARGS
+	verify_options || return $OCF_ERR_ARGS
+}
+
+
+do_pre_unmount() {
+	#
+	# Check the rgmanager-supplied reference count if one exists.
+	# If the reference count is <= 1, we can safely proceed
+	#
+	if [ -n "$OCF_RESKEY_RGMANAGER_meta_refcnt" ]; then
+		refs=$OCF_RESKEY_RGMANAGER_meta_refcnt
+		if [ $refs -gt 0 ]; then
+			ocf_log debug "Not unmounting $OCF_RESOURCE_INSTANCE - still in use by $refs other service(s)"
+			return 2
+		fi
+	fi
+
+	if [ -z "$force_umount" ]; then
+		ocf_log debug "Not umounting $dev (clustered file system)"
+		return 2
+	fi
+
+	#
+	# Always do this hackery on clustered file systems.
+	#
+	if [ "$OCF_RESKEY_nfslock" = "yes" ] || \
+	   [ "$OCF_RESKEY_nfslock" = "1" ]; then
+		ocf_log warning "Dropping node-wide NFS locks"
+		mkdir -p $mp/.clumanager/statd
+		pkill -KILL -x lockd
+		# Copy out the notify list; our 
+		# IPs are already torn down
+		if notify_list_store $mp/.clumanager/statd; then
+			notify_list_broadcast $mp/.clumanager/statd
+		fi
+	fi
+
+	# Always invalidate buffers on clusterfs resources
+	clubufflush -f $dev
+
+	return 0
+}
+
+do_force_unmount() {
+	if [ "$OCF_RESKEY_nfsrestart" = "yes" ] || \
+	   [ "$OCF_RESKEY_nfsrestart" = "1" ]; then
+		ocf_log warning "Restarting nfsd/nfslock"
+		nfsexports=$(cat /var/lib/nfs/etab)
+		service nfslock stop
+		service nfs stop
+		service nfs start
+		service nfslock start
+		echo "$nfsexports" | { while read line; do
+			nfsexp=$(echo $line | awk '{print $1}')
+			nfsopts=$(echo $line | sed -e 's#.*(##g' -e 's#).*##g')
+			nfsacl=$(echo $line | awk '{print $2}' | sed -e 's#(.*##g')
+			if [ -n "$nfsopts" ]; then
+				exportfs -i -o "$nfsopts" "$nfsacl":$nfsexp
+			else
+				exportfs -i "$nfsacl":$nfsexp
+			fi
+		done; }
+	fi
+	return 1
+}
+
+main $*
diff --git a/rgmanager/src/resources/drbd.metadata b/rgmanager/src/resources/drbd.metadata
new file mode 100644
index 0000000..30fe122
--- /dev/null
+++ b/rgmanager/src/resources/drbd.metadata
@@ -0,0 +1,51 @@
+<?xml version="1.0" ?>
+<resource-agent version="rgmanager 2.0" name="drbd">
+  <version>1.0</version>
+
+  <longdesc lang="en">
+    This is a DRBD resource. The resource must be configured
+    in the configuration file (/etc/drbd.conf), and the
+    DRBD kernel module must be loaded. 
+  </longdesc>
+
+  <shortdesc lang="en">
+    This is a DRBD resource.
+  </shortdesc>
+
+  <parameters>
+    <parameter name="name" unique="1" primary="1">
+      <longdesc lang="en">
+    Symbolic name for this resource.
+      </longdesc>
+      <shortdesc lang="en">
+    Cluster resource name
+      </shortdesc>
+      <content type="string"/>
+    </parameter>
+    <parameter name="resource" unique="1" required="1">
+      <longdesc lang="en">
+	The DRBD resource name, as specified in /etc/drbd.conf.
+      </longdesc>
+      <shortdesc lang="en">
+	DRBD resource name
+      </shortdesc>
+      <content type="string"/>
+    </parameter>
+  </parameters>
+
+  <actions>
+    <action name="start" timeout="20"/>
+    <action name="stop" timeout="20"/>
+    
+    <!-- Checks to see if the resource is Primary locally -->
+    <action name="status" depth="10" interval="60" timeout="20"/>
+    <action name="monitor" depth="10" interval="60" timeout="20"/>
+    
+    <action name="meta-data" timeout="20"/>
+    <action name="verify-all" timeout="20"/>
+  </actions>
+  
+  <special tag="rgmanager">
+    <attributes maxinstances="1"/>
+  </special>
+</resource-agent>
diff --git a/rgmanager/src/resources/drbd.sh b/rgmanager/src/resources/drbd.sh
new file mode 100755
index 0000000..51f88f7
--- /dev/null
+++ b/rgmanager/src/resources/drbd.sh
@@ -0,0 +1,144 @@
+#!/bin/bash
+#
+#  Copyright LINBIT, 2008
+#
+#  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, 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; see the file COPYING.  If not, write to the
+#  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+#  MA 02139, USA.
+#
+
+#
+# DRBD resource management using the drbdadm utility.
+#
+
+LC_ALL=C
+LANG=C
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export LC_ALL LANG PATH
+
+. $(dirname $0)/ocf-shellfuncs
+
+drbd_verify_all()
+{
+    # Do we have the drbdadm utility?
+    if ! which drbdadm >/dev/null 2>&1 ; then
+	ocf_log error "drbdadm not installed, not found in PATH ($PATH), or not executable."
+	return $OCF_ERR_INSTALLED
+    fi
+
+    # Is drbd loaded?
+    if ! grep drbd /proc/modules >/dev/null 2>&1; then
+	ocf_log error "drbd not found in /proc/modules. Do you need to modprobe?"
+	return $OCF_ERR_INSTALLED
+    fi
+
+    # Do we have the "resource" parameter?
+    if [ -n "$OCF_RESKEY_resource" ]; then
+
+      # Can drbdadm parse the resource name?
+      if ! drbdadm sh-dev $OCF_RESKEY_resource >/dev/null 2>&1; then
+  	ocf_log error "DRBD resource \"$OCF_RESKEY_resource\" not found." 
+  	return $OCF_ERR_CONFIGURED
+      fi
+
+      # Is the backing device a locally available block device?
+      backing_dev=$(drbdadm sh-ll-dev $OCF_RESKEY_resource)
+      if [ ! -b $backing_dev ]; then
+  	ocf_log error "Backing device for DRBD resource \"$OCF_RESKEY_resource\" ($backing_dev) not found or not a block device."
+  	return $OCF_ERR_INSTALLED
+      fi
+
+    fi
+
+    return 0
+}
+
+drbd_status() {
+    role=$(drbdadm role $OCF_RESKEY_resource)
+    case $role in
+	Primary/*)
+	    return $OCF_SUCCESS
+	    ;;
+	Secondary/*)
+	    return $OCF_NOT_RUNNING
+	    ;;
+
+    esac
+    return $OCF_ERR_GENERIC
+}
+
+drbd_promote() {
+    drbdadm primary $OCF_RESKEY_resource || return $?
+}
+
+drbd_demote() {
+    drbdadm secondary $OCF_RESKEY_resource || return $?
+}
+
+
+if [ -z "$OCF_CHECK_LEVEL" ]; then
+	OCF_CHECK_LEVEL=0
+fi
+
+# This one doesn't need to pass the verify check
+case $1 in
+    meta-data)
+	cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'` && exit 0
+	exit $OCF_ERR_GENERIC
+	;;
+esac
+
+# Everything else does
+drbd_verify_all || exit $?
+case $1 in
+    start)
+	if drbd_status; then
+	    ocf_log debug "DRBD resource ${OCF_RESKEY_resource} already configured"
+	    exit 0
+	fi
+	drbd_promote 
+	if [ $? -ne 0 ]; then
+	    exit $OCF_ERR_GENERIC
+	fi
+	
+	exit $?
+	;;
+    stop)
+	if drbd_status; then
+	    drbd_demote
+	    if [ $? -ne 0 ]; then
+		exit $OCF_ERR_GENERIC
+	    fi
+	else
+	    ocf_log debug "DRBD resource ${OCF_RESKEY_resource} is not configured"
+	fi
+	exit 0
+	;;
+    status|monitor)
+	drbd_status
+	exit $?
+	;;
+    restart)
+	$0 stop || exit $OCF_ERR_GENERIC
+	$0 start || exit $OCF_ERR_GENERIC
+	exit 0
+	;;
+    verify-all)
+    	exit 0
+    	;;
+    *)
+	echo "usage: $0 {start|stop|status|monitor|restart|meta-data|verify-all}"
+	exit $OCF_ERR_GENERIC
+	;;
+esac
diff --git a/rgmanager/src/resources/fs.sh.in b/rgmanager/src/resources/fs.sh.in
new file mode 100644
index 0000000..5ece354
--- /dev/null
+++ b/rgmanager/src/resources/fs.sh.in
@@ -0,0 +1,509 @@
+#!/bin/bash
+
+#
+# File system (normal) mount/umount/fsck/etc. agent
+#
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+. $(dirname $0)/utils/fs-lib.sh
+
+do_metadata()
+{
+	cat <<EOT
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent name="fs" version="rgmanager 2.0">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines a standard file system mount (= not a clustered
+	or otherwise shared file system).
+    </longdesc>
+    <shortdesc lang="en">
+        Defines a file system mount.
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+	        Symbolic name for this file system.
+	    </longdesc>
+            <shortdesc lang="en">
+                File System Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="mountpoint" unique="1" required="1">
+	    <longdesc lang="en">
+	        Path in file system heirarchy to mount this file system.
+	    </longdesc>
+            <shortdesc lang="en">
+                Mount Point
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="device" unique="1" required="1">
+	    <longdesc lang="en">
+	        Block device, file system label, or UUID of file system.
+	    </longdesc>
+            <shortdesc lang="en">
+                Device or Label
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="fstype">
+	    <longdesc lang="en">
+	        File system type.  If not specified, mount(8) will attempt to
+		determine the file system type.
+	    </longdesc>
+            <shortdesc lang="en">
+                File system type
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="force_unmount">
+            <longdesc lang="en">
+                If set, the cluster will kill all processes using 
+                this file system when the resource group is 
+                stopped.  Otherwise, the unmount will fail, and
+                the resource group will be restarted.
+            </longdesc>
+            <shortdesc lang="en">
+                Force Unmount
+            </shortdesc>
+	    <content type="boolean"/>
+        </parameter>
+
+        <parameter name="quick_status">
+            <longdesc lang="en">
+		Use quick status checks.  When set to 0 (the default), this
+		agent behaves normally.  When set to 1, this agent will not
+		log errors incurred or perform the file system accessibility
+		check (e.g. it will not try to read from/write to the file
+		system).  You should only set this to 1 if you have lots of
+		file systems on your cluster or you are seeing very high load
+		spikes as a direct result of this agent.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Quick/brief status checks.
+            </shortdesc>
+	    <content type="boolean"/>
+        </parameter>
+
+	<parameter name="self_fence">
+	    <longdesc lang="en">
+	        If set and unmounting the file system fails, the node will
+		immediately reboot.  Generally, this is used in conjunction
+		with force_unmount support, but it is not required.
+	    </longdesc>
+	    <shortdesc lang="en">
+	        Seppuku Unmount
+	    </shortdesc>
+	    <content type="boolean"/>
+	</parameter>
+
+	<parameter name="nfslock" inherit="nfslock">
+	    <longdesc lang="en">
+	        If set and unmounting the file system fails, the node will
+		try to kill lockd and issue reclaims across all remaining
+		network interface cards.
+	    </longdesc>
+	    <shortdesc lang="en">
+	        Enable NFS lock workarounds
+	    </shortdesc>
+	    <content type="boolean"/>
+	</parameter>
+
+	<parameter name="nfsrestart">
+	    <longdesc lang="en">
+		If set and unmounting the file system fails, the node will
+		try to restart nfs daemon and nfs lockd to drop all filesystem
+		references. Use this option as last resource.
+		This option requires force_unmount to be set and it is not
+		compatible with nfsserver resource.
+	    </longdesc>
+	    <shortdesc lang="en">
+		Enable NFS daemon and lockd workaround
+	    </shortdesc>
+	    <content type="boolean"/>
+	</parameter>
+
+	<parameter name="fsid">
+	    <longdesc lang="en">
+	    	File system ID for NFS exports.  This can be overridden
+		in individual nfsclient entries.
+	    </longdesc>
+	    <shortdesc lang="en">
+	    	NFS File system ID
+	    </shortdesc>
+	    <content type="string"/>
+	</parameter>
+
+        <parameter name="force_fsck">
+            <longdesc lang="en">
+                If set, the file system will be checked (even if
+                it is a journalled file system).  This option is
+                ignored for non-journalled file systems such as
+                ext2.
+            </longdesc>
+            <shortdesc lang="en">
+                Force fsck support
+            </shortdesc>
+	    <content type="boolean"/>
+        </parameter>
+
+        <parameter name="options">
+            <longdesc lang="en">
+	    	Options used when the file system is mounted.  These
+		are often file-system specific.  See mount(8) for supported
+		mount options.
+            </longdesc>
+            <shortdesc lang="en">
+                Mount Options
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="use_findmnt">
+            <longdesc lang="en">
+        Use findmnt to determine if and where a filesystem is mounted.
+        Disabling this uses the failback method (should be used if autofs
+        maps are located on network storage (ie. nfs, iscsi, etc).
+            </longdesc>
+            <shortdesc lang="en">
+        Utilize findmnt to detect if and where filesystems are mounted
+            </shortdesc>
+            <content type="boolean"/>
+        </parameter>
+
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="900"/>
+	<action name="stop" timeout="30"/>
+	<!-- Recovery isn't possible; we don't know if resources are using
+	     the file system. -->
+
+	<!-- Checks to see if it's mounted in the right place -->
+	<action name="status" interval="1m" timeout="10"/>
+	<action name="monitor" interval="1m" timeout="10"/>
+
+	<!-- Note: active monitoring is constant and supplants all
+	     check depths -->
+	<!-- Checks to see if we can read from the mountpoint -->
+	<action name="status" depth="10" timeout="30" interval="30"/>
+	<action name="monitor" depth="10" timeout="30" interval="30"/>
+
+	<!-- Checks to see if we can write to the mountpoint (if !ROFS) -->
+	<action name="status" depth="20" timeout="30" interval="1m"/>
+	<action name="monitor" depth="20" timeout="30" interval="1m"/>
+
+	<action name="meta-data" timeout="5"/>
+	<action name="validate-all" timeout="5"/>
+    </actions>
+
+    <special tag="rgmanager">
+	<attributes maxinstances="1"/>
+        <child type="fs" start="1" stop="3"/>
+        <child type="clusterfs" start="1" stop="3"/>
+        <child type="nfsexport" start="3" stop="1"/>
+    </special>
+</resource-agent>
+EOT
+}
+
+
+verify_fstype()
+{
+	# Auto detect?
+	[ -z "$OCF_RESKEY_fstype" ] && return 0
+
+	case $OCF_RESKEY_fstype in
+	ext2|ext3|ext4|btrfs|jfs|xfs|reiserfs|vfat|tmpfs|vxfs)
+		return 0
+		;;
+	*)
+		echo "File system type $OCF_RESKEY_fstype not supported"
+		return $OCF_ERR_ARGS
+		;;
+	esac
+}
+
+
+verify_options()
+{
+	declare -i ret=$OCF_SUCCESS
+	declare o
+
+	#
+	# From mount(8)
+	#
+	for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do
+		case $o in
+		async|atime|auto|defaults|dev|exec|_netdev|noatime)
+			continue
+			;;
+		noauto|nodev|noexec|nosuid|nouser|ro|rw|suid|sync)
+			continue
+			;;
+		dirsync|user|users)
+			continue
+			;;
+		esac
+
+		do_verify_option $OCF_RESKEY_fstype "$o"
+
+		case $OCF_RESKEY_fstype in
+		ext2|ext3|ext4)
+			case $o in
+			bsddf|minixdf|check|check=*|nocheck|debug)
+				continue
+				;;
+			errors=*|grpid|bsdgroups|nogrpid|sysvgroups)
+				continue
+				;;
+			resgid=*|resuid=*|sb=*|grpquota|noquota)
+				continue
+				;;
+			quota|usrquota|nouid32)
+				continue
+				;;
+			esac
+
+			if [ "$OCF_RESKEY_fstype" = "ext3" ] ||
+			   [ "$OCF_RESKEY_fstype" = "ext4" ]; then
+				case $0 in
+				noload|data=*)
+					continue
+					;;
+				esac
+			fi
+			;;
+		vfat)
+			case $o in
+			blocksize=512|blocksize=1024|blocksize=2048)
+				continue
+				;;
+			uid=*|gid=*|umask=*|dmask=*|fmask=*)
+				continue
+				;;
+			check=r*|check=n*|check=s*|codepage=*)
+				continue
+				;;
+			conv=b*|conv=t*|conv=a*|cvf_format=*)
+				continue
+				;;
+			cvf_option=*|debug|fat=12|fat=16|fat=32)
+				continue
+				;;
+			iocharset=*|quiet)
+				continue
+				;;
+			esac
+			;;
+
+		jfs)
+			case $o in
+			conv|hash=rupasov|hash=tea|hash=r5|hash=detect)
+				continue
+				;;
+			hashed_relocation|no_unhashed_relocation)
+				continue
+				;;
+			noborder|nolog|notail|resize=*)
+				continue
+				;;
+			esac
+			;;
+
+		xfs)
+			case $o in
+			biosize=*|dmapi|xdsm|logbufs=*|logbsize=*)
+				continue
+				;;
+			logdev=*|rtdev=*|noalign|noatime)
+				continue
+				;;
+			norecovery|osyncisdsync|quota|userquota)
+				continue
+				;;
+			uqnoenforce|grpquota|gqnoenforce)
+				continue
+				;;
+			sunit=*|swidth=*)
+				continue
+				;;
+			esac
+			;;
+
+		tmpfs)
+			case $o in
+			size=*|nr_blocks=*|mode=*)
+				continue
+				;;
+			esac
+			;;
+		btrfs)
+			# tbd
+			continue
+			;;
+		esac
+
+		echo Option $o not supported for $OCF_RESKEY_fstype
+		ret=$OCF_ERR_ARGS
+	done
+
+	return $ret
+}
+
+
+do_validate()
+{
+	verify_name || return $OCF_ERR_ARGS
+	verify_fstype || return $OCF_ERR_ARGS
+	verify_device || return $OCF_ERR_ARGS
+	verify_mountpoint || return $OCF_ERR_ARGS
+	verify_options || return $OCF_ERR_ARGS
+}
+
+
+do_pre_mount()
+{
+	declare fstype="$OCF_RESKEY_fstype"
+
+	#
+	# Check to determine if we need to fsck the filesystem.
+	#
+	# Note: this code should not indicate in any manner suggested
+	# file systems to use in the cluster.  Known filesystems are
+	# listed here for correct operation.
+	#
+        case "$fstype" in
+        reiserfs) typeset fsck_needed="" ;;
+        ext3)     typeset fsck_needed="" ;;
+        ext4)     typeset fsck_needed="" ;;
+        btrfs)    typeset fsck_needed="" ;;
+        jfs)      typeset fsck_needed="" ;;
+        xfs)      typeset fsck_needed="" ;;
+	vxfs)	  typeset fsck_needed="" ;;
+        ext2)     typeset fsck_needed=yes ;;
+        minix)    typeset fsck_needed=yes ;;
+        vfat)     typeset fsck_needed=yes ;;
+        msdos)    typeset fsck_needed=yes ;;
+	"")       typeset fsck_needed=yes ;;		# assume fsck
+	*)
+		typeset fsck_needed=yes 		# assume fsck
+	     	ocf_log warn "\
+Unknown file system type '$fstype' for device $dev.  Assuming fsck is required."
+		;;
+	esac
+
+
+	#
+	# Fsck the device, if needed.
+	#
+	if [ -n "$fsck_needed" ] || [ "${OCF_RESKEY_force_fsck}" = "yes" ] ||\
+	   [ "${OCF_RESKEY_force_fsck}" = "1" ]; then
+		typeset fsck_log=@LOGDIR@/$(basename $dev).fsck.log
+		ocf_log debug "Running fsck on $dev"
+		fsck -p $dev >> $fsck_log 2>&1
+		ret_val=$?
+		if [ $ret_val -gt 1 ]; then
+			ocf_log err "\
+'fsck -p $dev' failed, error=$ret_val; check $fsck_log for errors"
+			ocf_log debug "Invalidating buffers for $dev"
+			$INVALIDATEBUFFERS -f $dev
+			return $OCF_ERR_GENERIC
+		fi
+		rm -f $fsck_log
+	fi
+
+	return 0
+}
+
+do_post_mount() {
+	#
+	# Create this for the NFS NLM broadcast bit
+	#
+	if [ $NFS_TRICKS -eq 0 ]; then
+		if [ "$OCF_RESKEY_nfslock" = "yes" ] || \
+	   	   [ "$OCF_RESKEY_nfslock" = "1" ]; then
+			mkdir -p "$mp"/.clumanager/statd
+			notify_list_merge "$mp"/.clumanager/statd
+		fi
+	fi
+
+	return 0
+}
+
+
+do_force_unmount() {
+	if [ "$OCF_RESKEY_nfslock" = "yes" ] || \
+	   [ "$OCF_RESKEY_nfslock" = "1" ]; then
+		ocf_log warning "Dropping node-wide NFS locks"
+		pkill -KILL -x lockd
+		mkdir -p "$mp"/.clumanager/statd
+		# Copy out the notify list; our
+		# IPs are already torn down
+		notify_list_store "$mp"/.clumanager/statd
+
+		# Save for post-umount phase
+		export nfslock_reclaim=1
+	fi
+
+	if [ "$OCF_RESKEY_nfsrestart" = "yes" ] || \
+	   [ "$OCF_RESKEY_nfsrestart" = "1" ]; then
+		ocf_log warning "Restarting nfsd/nfslock"
+		nfsexports=$(cat /var/lib/nfs/etab)
+		service nfslock stop
+		service nfs stop
+		service nfs start
+		service nfslock start
+		echo "$nfsexports" | { while read line; do
+			nfsexp=$(echo $line | awk '{print $1}')
+			nfsopts=$(echo $line | sed -e 's#.*(##g' -e 's#).*##g')
+			nfsacl=$(echo $line | awk '{print $2}' | sed -e 's#(.*##g')
+			if [ -n "$nfsopts" ]; then
+				exportfs -i -o "$nfsopts" "$nfsacl":$nfsexp
+			else
+				exportfs -i "$nfsacl":$nfsexp
+			fi
+		done; }
+	fi
+
+	# Proceed with fuser -kvm...
+	return 1
+}
+
+
+do_post_unmount() {
+	if [ "$nfslock_reclaim" = "1" ]; then
+		# If we have this flag set, do a full reclaim broadcast
+		notify_list_broadcast "$mp"/.clumanager/statd
+	fi
+
+	return 0
+}
+
+main $*
diff --git a/rgmanager/src/resources/ip.sh b/rgmanager/src/resources/ip.sh
new file mode 100755
index 0000000..7e19205
--- /dev/null
+++ b/rgmanager/src/resources/ip.sh
@@ -0,0 +1,1027 @@
+#!/bin/bash
+
+#
+# IPv4/IPv6 address management using iproute2 (formerly: ifcfg, ifconfig).
+#
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2012 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+LC_ALL=C
+LANG=C
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export LC_ALL LANG PATH
+
+# Grab nfs lock tricks if available
+export NFS_TRICKS=1
+if [ -f "$(dirname $0)/svclib_nfslock" ]; then
+	. $(dirname $0)/svclib_nfslock
+	NFS_TRICKS=0
+fi
+
+. $(dirname $0)/ocf-shellfuncs
+
+
+meta_data()
+{
+    cat <<EOT
+<?xml version="1.0" ?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent version="rgmanager 2.0" name="ip">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This is an IP address.  Both IPv4 and IPv6 addresses are supported,
+        as well as NIC link monitoring for each IP address.
+    </longdesc>
+    <shortdesc lang="en">
+        This is an IP address.
+    </shortdesc>
+
+    <parameters>
+        <parameter name="address" unique="1" primary="1">
+            <longdesc lang="en">
+                IPv4 or IPv6 address to use as a virtual IP
+                resource.  It may be followed by a slash and a decimal
+                number that encodes the network prefix length.
+            </longdesc>
+
+            <shortdesc lang="en">
+                IP Address
+            </shortdesc>
+
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="family">
+            <longdesc lang="en">
+                IPv4 or IPv6 address protocol family.
+            </longdesc>
+
+            <shortdesc lang="en">
+                Family
+            </shortdesc>
+
+            <!--
+            <val>auto</val>
+            <val>inet</val>
+            <val>inet6</val>
+            -->
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="monitor_link">
+            <longdesc lang="en">
+                Enabling this causes the status check to fail if
+                the link on the NIC to which this IP address is
+                bound is not present.
+            </longdesc>
+            <shortdesc lang="en">
+                Monitor NIC Link
+            </shortdesc>
+            <content type="boolean" default="1"/>
+        </parameter>
+
+	<parameter name="nfslock" inherit="service%nfslock">
+	    <longdesc lang="en">
+	        If set and unmounting the file system fails, the node will
+		try to kill lockd and issue reclaims across all remaining
+		network interface cards.
+	    </longdesc>
+	    <shortdesc lang="en">
+	        Enable NFS lock workarounds
+	    </shortdesc>
+	    <content type="boolean"/>
+	</parameter>
+
+	<parameter name="sleeptime">
+	    <longdesc lang="en">
+		Amount of time to sleep after removing an IP address.
+		Value is specified in seconds. Default value is 10.
+	    </longdesc>
+	    <shortdesc lang="en">
+		Amount of time (seconds) to sleep.
+	    </shortdesc>
+	    <content type="string"/>
+	</parameter>
+
+	<parameter name="disable_rdisc">
+	    <longdesc lang="en">
+	        Disable updating of routing using RDISC protocol and
+	        preserve static routes.
+	    </longdesc>
+	    <shortdesc lang="en">
+	        Disable updating of routing using RDISC protocol
+	    </shortdesc>
+	    <content type="boolean"/>
+	</parameter>
+
+	<parameter name="prefer_interface">
+	    <longdesc lang="en">
+	        The network interface to which the IP address should be added. The interface must already be configured and active. This parameter should be used only when at least two active interfaces have IP addresses on the same subnet and it is desired to have the IP address added to a particular interface.
+	    </longdesc>
+	    <shortdesc lang="en">
+	        Network interface
+	    </shortdesc>
+	    <content type="string"/>
+	</parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="20"/>
+        <action name="stop" timeout="20"/>
+	<!-- No recover action.  If the IP address is not useable, then
+	     resources may or may not depend on it.  If it's been 
+	     deconfigured, resources using it are in a bad state. -->
+
+	<!-- Checks to see if the IP is up and (optionally) the link is
+	     working -->
+        <action name="status" interval="20" timeout="10"/>
+        <action name="monitor" interval="20" timeout="10"/>
+
+	<!-- Checks to see if we can ping the IP address locally -->
+        <action name="status" depth="10" interval="60" timeout="20"/>
+        <action name="monitor" depth="10" interval="60" timeout="20"/>
+
+        <action name="meta-data" timeout="20"/>
+        <action name="validate-all" timeout="20"/>
+    </actions>
+
+    <special tag="rgmanager">
+	<attributes maxinstances="1"/>
+	<child type="nfsclient" forbid="1"/>
+	<child type="nfsexport" forbid="1"/>
+    </special>
+</resource-agent>
+EOT
+}
+
+
+verify_address()
+{
+	# XXX TBD
+	return 0
+}
+
+
+verify_all()
+{
+	# XXX TBD
+	return 0
+}
+
+
+#
+# Expand an IPv6 address.
+#
+ipv6_expand()
+{
+	typeset addr=$1
+	typeset maskbits
+	typeset -i x
+	typeset tempaddr
+	
+	maskbits=${addr/*\//}
+	if [ "$maskbits" = "$addr" ]; then
+		maskbits=""
+	else
+		# chop off mask bits
+		addr=${addr/\/*/}
+	fi
+
+	# grab each hex quad and expand it to 4 digits if it isn't already
+	# leave doublecolon in place for expansion out to the proper number of zeros later
+	tempaddr=""
+	for count in `seq 1 8`; do
+		quad=`echo $addr|awk -v count=$count -F : '{print $count}'`
+		quadlen=${#quad}
+		if [ $quadlen -eq 0 ]; then
+			quad=::
+		elif [ $quadlen -eq 1 ]; then
+			quad=000$quad
+		elif [ $quadlen -eq 2 ]; then
+			quad=00$quad
+		elif [ $quadlen -eq 3 ]; then
+			quad=0$quad
+		fi
+		tempaddr=$tempaddr$quad
+	done
+	addr=$tempaddr
+
+	# use space as placeholder
+	addr=${addr/::/\ }
+
+	# get rid of colons
+	addr=${addr//:/}
+
+	# add in zeroes where the doublecolon was
+	len=$((${#addr}-1))
+	zeroes=
+	while [ $len -lt 32 ]; do
+		zeroes="0$zeroes"
+		((len++))
+	done
+	addr=${addr/\ /$zeroes}
+
+	# probably a better way to do this
+	for (( x=0; x < ${#addr} ; x++)); do
+		naddr=$naddr${addr:x:1}
+
+		if (( x < (${#addr} - 1) && x%4 == 3)); then
+			naddr=$naddr:
+		fi
+	done
+
+	if [ -n "$maskbits" ]; then
+		echo "$naddr/$maskbits"
+		return 0
+	fi
+
+	echo "$naddr"
+	return 0
+}
+
+
+#
+# see if two ipv6 addrs are in the same subnet
+#
+ipv6_same_subnet()
+{
+	declare addrl=$1
+	declare addrr=$2
+	declare m=$3 
+	declare r x llsb rlsb
+
+	if [ $# -lt 2 ]; then
+		ocf_log err "usage: ipv6_same_subnet addr1 addr2 [mask]"
+		return 255
+	fi
+
+	if [ -z "$m" ]; then
+		m=${addrl/*\//}
+
+		[ -n "$m" ] || return 1
+
+	fi
+
+	if [ "${addrr}" != "${addrr/*\//}" ] &&
+	   [ "$m" != "${addrr/*\//}" ]; then
+		return 1
+	fi
+
+	addrl=${addrl/\/*/}
+	if [ ${#addrl} -lt 39 ]; then
+		addrl=$(ipv6_expand $addrl)
+	fi
+
+	addrr=${addrr/\/*/}
+	if [ ${#addrr} -lt 39 ]; then
+		addrr=$(ipv6_expand $addrr)
+	fi
+
+	# Calculate the amount to compare directly
+	x=$(($m/4+$m/16-(($m%4)==0)))
+
+	# and the remaining number of bits
+	r=$(($m%4))
+
+	if [ $r -ne 0 ]; then
+		# If we have any remaining bits, we will need to compare
+		# them later.  Get them now.
+		llsb=`printf "%d" 0x${addrl:$x:1}`
+		rlsb=`printf "%d" 0x${addrr:$x:1}`
+
+		# One less byte to compare directly, please
+		((--x))
+	fi
+	
+	# direct (string comparison) to see if they are equal
+	if [ "${addrl:0:$x}" != "${addrr:0:$x}" ]; then
+		return 1
+	fi
+
+	case $r in
+	0)
+		return 0
+		;;
+	1)	
+		[ $(($llsb & 8)) -eq $(($rlsb & 8)) ]
+		return $?
+		;;
+	2)
+		[ $(($llsb & 12)) -eq $(($rlsb & 12)) ]
+		return $?
+		;;
+	3)
+		[ $(($llsb & 14)) -eq $(($rlsb & 14)) ]
+		return $?
+		;;
+	esac
+
+	return 1
+}
+
+
+ipv4_same_subnet()
+{
+	declare addrl=$1
+	declare addrr=$2
+	declare m=$3 
+	declare r x llsb rlsb
+
+	if [ $# -lt 2 ]; then
+		ocf_log err "usage: ipv4_same_subnet current_addr new_addr [maskbits]"
+		return 255
+	fi
+
+
+	#
+	# Chop the netmask off of the ipaddr:
+	# e.g. 1.2.3.4/22 -> 22
+	#
+	if [ -z "$m" ]; then
+		m=${addrl/*\//}
+		[ -n "$m" ] || return 1
+	fi
+
+	#
+	# Check to see if there was a subnet mask provided on the
+	# new IP address.  If there was one and it does not match
+	# our expected subnet mask, we are done.
+	#
+	if [ "${addrr}" != "${addrr/\/*/}" ] &&
+	   [ "$m" != "${addrr/*\//}" ]; then
+		return 1
+	fi
+
+	#
+	# Chop off subnet bits for good.
+	#
+	addrl=${addrl/\/*/}
+	addrr=${addrr/\/*/}
+
+	#
+	# Remove '.' characters from dotted decimal notation and save
+	# in arrays. i.e.
+	#
+	#	192.168.1.163 -> array[0] = 192
+	#	                 array[1] = 168
+	#	                 array[2] = 1
+	#	                 array[3] = 163
+	#
+
+	let x=0
+	for quad in ${addrl//./\ }; do
+		ip1[((x++))]=$quad
+	done
+
+	x=0
+	for quad in ${addrr//./\ }; do
+		ip2[((x++))]=$quad
+	done
+
+	x=0
+
+	while [ $m -ge 8 ]; do
+		((m-=8))
+		if [ ${ip1[x]} -ne ${ip2[x]} ]; then
+			return 1
+		fi
+		((x++))
+	done
+
+	case $m in
+	0)
+		return 0
+		;;
+	1)	
+		[ $((${ip1[x]} & 128)) -eq $((${ip2[x]} & 128)) ]
+		return $?
+		;;
+	2)
+		[ $((${ip1[x]} & 192)) -eq $((${ip2[x]} & 192)) ]
+		return $?
+		;;
+	3)
+		[ $((${ip1[x]} & 224)) -eq $((${ip2[x]} & 224)) ]
+		return $?
+		;;
+	4)
+		[ $((${ip1[x]} & 240)) -eq $((${ip2[x]} & 240)) ]
+		return $?
+		;;
+	5)
+		[ $((${ip1[x]} & 248)) -eq $((${ip2[x]} & 248)) ]
+		return $?
+		;;
+	6)
+		[ $((${ip1[x]} & 252)) -eq $((${ip2[x]} & 252)) ]
+		return $?
+		;;
+	7)
+		[ $((${ip1[x]} & 254)) -eq $((${ip2[x]} & 254)) ]
+		return $?
+		;;
+	esac
+
+	return 1
+}
+
+
+ipv6_list_interfaces()
+{
+	declare idx dev ifaddr
+	declare ifaddr_exp
+	
+	while read idx dev ifaddr; do
+	    
+		isSlave $dev
+		if [ $? -ne 2 ]; then
+			continue
+		fi
+		
+		idx=${idx/:/}
+		
+		ifaddr_exp=$(ipv6_expand $ifaddr)
+		
+		echo $dev ${ifaddr_exp/\/*/} ${ifaddr_exp/*\//}
+		
+	done < <(/sbin/ip -o -f inet6 addr | awk '{print $1,$2,$4}')
+
+	return 0
+}
+
+
+isSlave()
+{
+	declare intf=$1
+	declare line
+
+	if [ -z "$intf" ]; then
+		ocf_log err "usage: isSlave <I/F>"
+		return $OCF_ERR_ARGS
+	fi
+
+	line=$(/sbin/ip link list dev $intf)
+	if [ $? -ne 0 ]; then
+		ocf_log err "$intf not found"
+		return $OCF_ERR_GENERIC
+	fi
+
+	if [ "$line" = "${line/<*SLAVE*>/}" ]; then
+		return 2
+	fi
+
+	# Yes, it is a slave device.  Ignore.
+	return 0
+}
+
+
+# 
+# Check if interface is in UP state
+#
+interface_up()
+{
+       declare intf=$1
+       
+       if [ -z "$intf" ]; then
+		ocf_log err "usage: interface_up <I/F>"
+		return 1
+       fi
+       
+       line=$(/sbin/ip -o link show up dev $intf 2> /dev/null)
+       [ -z "$line" ] && return 2
+       
+       return 0
+}
+
+
+ethernet_link_up()
+{
+	declare linkstate=$(ethtool $1 | grep "Link detected:" |\
+			    awk '{print $3}')
+	
+	[ -n "$linkstate" ] || return 0
+
+	case $linkstate in
+	yes)
+		return 0
+		;;
+	*)
+		return 1
+		;;
+	esac
+	
+	return 1
+}
+
+
+#
+# Checks the physical link status of an ethernet or bonded interface.
+#
+network_link_up()
+{
+	declare slaves
+	declare intf_arg=$1
+	declare link_up=1		# Assume link down
+	declare intf_test
+
+	if [ -z "$intf_arg" ]; then
+		ocf_log err "usage: network_link_up <intf>"
+		return 1
+	fi
+	
+	ethernet_link_up $intf_arg
+	link_up=$?
+
+	if [ $link_up -eq 0 ]; then
+		ocf_log debug "Link for $intf_arg: Detected"
+	else
+		ocf_log warn "Link for $intf_arg: Not detected"
+	fi
+
+	return $link_up
+}
+
+
+ipv4_list_interfaces()
+{
+	declare idx dev ifaddr
+
+	while read idx dev ifaddr; do
+	        
+		isSlave $dev
+		if [ $? -ne 2 ]; then
+			continue
+		fi
+		
+		idx=${idx/:/}
+		
+		echo $dev ${ifaddr/\/*/} ${ifaddr/*\//}
+		
+	done < <(/sbin/ip -o -f inet addr | awk '{print $1,$2,$4}')
+	
+	return 0
+}
+
+
+#
+# Add an IP address to our interface or remove it.
+#
+ipv6()
+{
+	declare dev maskbits
+	declare addr=$2
+	declare addr_exp=$(ipv6_expand $addr)
+	
+	while read dev ifaddr_exp maskbits; do 
+	        if [ -z "$dev" ]; then
+		        continue
+		fi
+		
+		if [ "$1" = "add" ]; then
+			if [ -n "$OCF_RESKEY_prefer_interface" ] && \
+			   [ "$OCF_RESKEY_prefer_interface" != $dev ]; then
+				continue
+			fi
+			ipv6_same_subnet $ifaddr_exp/$maskbits $addr_exp
+			if [ $? -ne 0 ]; then
+                                continue
+                        fi
+                        interface_up $dev
+                        if [ $? -ne 0 ]; then
+                                continue
+                        fi
+			if [ "$OCF_RESKEY_monitor_link" = "yes" ]; then
+                        	network_link_up $dev
+                        	if [ $? -ne 0 ]; then
+                                	continue
+                        	fi
+			fi
+
+			if [ "${addr/\/*/}" = "${addr}" ]; then
+				addr="$addr/$maskbits"
+			fi
+			ocf_log info "Adding IPv6 address $addr to $dev"
+		fi
+		if [ "$1" = "del" ]; then
+		        if [ "${addr_exp/\/*/}" != "$ifaddr_exp" ]; then
+			        continue
+			fi
+			addr=`/sbin/ip addr list | grep "$addr" | head -n 1 | awk '{print $2}'`
+			ocf_log info "Removing IPv6 address $addr from $dev"
+                fi
+		
+		if [ "$1" = "add" ]; then
+			ocf_log debug "Pinging addr ${addr%%/*} from dev $dev"
+			if ping_check inet6 ${addr%%/*} $dev; then
+				ocf_log err "IPv6 address collision ${addr%%/*}"
+				return 1
+			fi
+		fi
+		/sbin/ip -f inet6 addr $1 dev $dev $addr
+		[ $? -ne 0 ] && return 1
+		
+		#
+		# NDP should take of figuring out our new address.  Plus,
+		# we do not have something (like arping) to do this for ipv6
+		# anyway.
+		# 
+		# RFC 2461, section 7.2.6 states thusly:
+		#
+	   	# Note that because unsolicited Neighbor Advertisements do not
+		# reliably update caches in all nodes (the advertisements might
+		# not be received by all nodes), they should only be viewed as
+		# a performance optimization to quickly update the caches in
+		#  most neighbors. 
+		#
+		
+		# Not sure if this is necessary for ipv6 either.
+		file=$(which rdisc 2>/dev/null)
+		if [ -f "$file" ]; then
+			if [ "$OCF_RESKEY_disable_rdisc" != "yes" ] && \
+			   [ "$OCF_RESKEY_disable_rdisc" != "1" ]; then
+		        	killall -HUP rdisc || rdisc -fs
+			fi
+		fi
+		
+		return 0
+	done < <(ipv6_list_interfaces)
+	
+	return 1
+}
+
+
+#
+# Add an IP address to our interface or remove it.
+#
+ipv4()
+{
+	declare dev ifaddr maskbits
+	declare addr=$2
+	
+	while read dev ifaddr maskbits; do
+	        if [ -z "$dev" ]; then
+		        continue
+		fi
+
+		if [ "$1" = "add" ]; then
+			if [ -n "$OCF_RESKEY_prefer_interface" ] && \
+			   [ "$OCF_RESKEY_prefer_interface" != $dev ]; then
+				continue
+			fi
+		        ipv4_same_subnet $ifaddr/$maskbits $addr
+			if [ $? -ne 0 ]; then
+			        continue
+			fi
+		        interface_up $dev
+			if [ $? -ne 0 ]; then
+			        continue
+			fi
+			if [ "$OCF_RESKEY_monitor_link" = "yes" ]; then
+				network_link_up $dev
+				if [ $? -ne 0 ]; then
+					continue
+				fi
+			fi
+
+			if [ "${addr/\/*/}" = "${addr}" ]; then
+				addr="$addr/$maskbits"
+			fi
+			ocf_log info "Adding IPv4 address $addr to $dev"
+		fi
+		if [ "$1" = "del" ]; then
+			if [ "${addr/\/*/}" != "$ifaddr" ]; then
+			        continue
+			fi
+			addr=`/sbin/ip addr list | grep "$ifaddr/" | head -n 1 | awk '{print $2}'`
+			ocf_log info "Removing IPv4 address $addr from $dev"
+		fi
+		
+		if [ "$1" = "add" ]; then
+			ocf_log debug "Pinging addr ${addr%%/*} from dev $dev"
+			if ping_check inet ${addr%%/*} $dev; then
+				ocf_log err "IPv4 address collision ${addr%%/*}"
+				return 1
+			fi
+		fi
+		/sbin/ip -f inet addr $1 dev $dev $addr
+		[ $? -ne 0 ] && return 1
+		
+        	#
+		# XXX: Following needed? ifconfig:YES, ifcfg:NO, iproute2:???
+        	#
+		if [ "$1" = "add" ]; then
+        		# do that freak arp thing
+		    
+ 		        hwaddr=$(/sbin/ip -o link show $dev)
+			hwaddr=${hwaddr/*link\/ether\ /}
+			hwaddr=${hwaddr/\ \*/}
+			
+			addr=${addr/\/*/}
+			ocf_log debug "Sending gratuitous ARP: $addr $hwaddr"
+			arping -q -c 2 -U -I $dev $addr
+		fi
+		
+		file=$(which rdisc 2>/dev/null)
+		if [ -f "$file" ]; then
+			if [ "$OCF_RESKEY_disable_rdisc" != "yes" ] && \
+			   [ "$OCF_RESKEY_disable_rdisc" != "1" ]; then
+			        killall -HUP rdisc || rdisc -fs
+			fi
+		fi
+		
+		return 0
+	done  < <(ipv4_list_interfaces)
+	
+	return 1
+}
+
+
+#
+# Usage:
+# ping_check <family> <address> [interface]
+#
+ping_check()
+{
+	declare ops="-c 1 -w 2"
+	declare pingcmd=""
+
+	if [ "$1" = "inet6" ]; then
+		pingcmd="ping6"
+	else
+		pingcmd="ping"
+	fi
+
+	if [ -n "$3" ]; then 
+		ops="$ops -I $3"
+	fi
+
+	return $($pingcmd $ops $2 &> /dev/null)
+}
+
+
+# 
+# Usage:
+# check_interface_up <family> <address>
+#
+check_interface_up()
+{
+	declare dev
+	declare addr=${2/\/*/}
+	declare currentAddr caExpanded
+
+	if [ "$1" == "inet6" ]; then
+		addrExpanded=$(ipv6_expand $addr)
+		for currentAddr in `/sbin/ip -f $1 -o addr|awk '{print $4}'`; do
+			caExpanded=$(ipv6_expand $currentAddr)
+			caExpanded=${caExpanded/\/*/}
+			if [ "$addrExpanded" == "$caExpanded" ]; then
+				dev=$(/sbin/ip -f $1 -o addr | grep " ${currentAddr/\/*/}" | awk '{print $2}')
+				break
+			fi
+		done
+	else
+		dev=$(/sbin/ip -f $1 -o addr | grep " $addr/" | awk '{print $2}')
+	fi
+
+	if [ -z "$dev" ]; then
+		return 1
+	fi
+	
+	interface_up $dev
+	return $?
+}
+
+
+# 
+# Usage:
+# address_configured <family> <address>
+#
+address_configured()
+{
+	declare line
+	declare addr
+	declare currentAddr caExpanded
+
+	# Chop off mask bits
+	addr=${2/\/*/}
+
+	if [ "$1" == "inet6" ]; then
+		addrExpanded=$(ipv6_expand $addr)
+		for currentAddr in `/sbin/ip -f $1 -o addr|awk '{print $4}'`; do
+			caExpanded=$(ipv6_expand $currentAddr)
+			caExpanded=${caExpanded/\/*/}
+			if [ "$addrExpanded" == "$caExpanded" ]; then
+				line=$(/sbin/ip -f $1 -o addr | grep " ${currentAddr/\/*/}");
+				break
+			fi
+		done
+	else
+		line=$(/sbin/ip -f $1 -o addr | grep " $addr/")
+	fi
+
+	if [ -z "$line" ]; then
+		return 1
+	fi
+	return 0
+}
+
+
+#
+# Usage:
+# ip_op <family> <operation> <address> [quiet]
+#
+ip_op()
+{
+	declare dev
+	declare rtr
+	declare addr=${3/\/*/}
+	declare caExpanded currentAddr
+
+	if [ "$2" = "status" ]; then
+
+		ocf_log debug "Checking $3, Level $OCF_CHECK_LEVEL"
+	
+		if [ "$1" == "inet6" ]; then
+			addrExpanded=$(ipv6_expand $addr)
+			for currentAddr in `/sbin/ip -f $1 -o addr|awk '{print $4}'`; do
+				caExpanded=$(ipv6_expand $currentAddr)
+				caExpanded=${caExpanded/\/*/}
+				if [ "$addrExpanded" == "$caExpanded" ]; then
+					dev=$(/sbin/ip -f $1 -o addr | grep " ${currentAddr/\/*/}" | awk '{print $2}')
+					break
+				fi
+			done
+		else
+			dev=$(/sbin/ip -f $1 -o addr | grep " $addr/" | awk '{print $2}')
+		fi
+
+		if [ -z "$dev" ]; then
+			ocf_log warn "$3 is not configured"
+			return 1
+		fi
+		ocf_log debug "$3 present on $dev"
+		
+		if [ "$OCF_RESKEY_monitor_link" = "yes" ]; then
+			if ! network_link_up $dev; then
+		        	ocf_log warn "No link on $dev..."
+				return 1
+			fi
+			ocf_log debug "Link detected on $dev"
+		fi
+		
+		[ $OCF_CHECK_LEVEL -lt 10 ] && return 0
+		if ! ping_check $1 $addr $dev; then
+			ocf_log warn "Failed to ping $addr"
+			return 1
+		fi
+		ocf_log debug "Local ping to $addr succeeded"
+		
+		return 0
+	fi
+
+	case $1 in
+	inet)
+		ipv4 $2 $3
+		return $?
+		;;
+	inet6)
+		if [ "$2" = "del" ]; then
+			addrExpanded=$(ipv6_expand $addr)
+			for currentAddr in `/sbin/ip -f $1 -o addr|awk '{print $4}'`; do
+				caExpanded=$(ipv6_expand $currentAddr)
+				caExpanded=${caExpanded/\/*/}
+				if [ "$addrExpanded" == "$caExpanded" ]; then
+					addr6=$(/sbin/ip -f $1 -o addr | grep " ${currentAddr/\/*/}" | awk '{print $4}')
+					ipv6 $2 $addr6
+					return $?
+				fi
+			done
+		fi
+
+		ipv6 $2 $3
+		return $?
+		;;
+	esac
+	return 1
+}
+
+
+case ${OCF_RESKEY_family} in
+inet)
+	;;
+inet6)
+	;;
+*)
+	if [ "${OCF_RESKEY_address//:/}" != "${OCF_RESKEY_address}" ]; then
+		export OCF_RESKEY_family=inet6
+	else
+		export OCF_RESKEY_family=inet
+	fi
+	;;
+esac
+
+# Force ipv6 addresses to lower case
+if [ "$OCF_RESKEY_family" = "inet6" ]; then
+	OCF_RESKEY_address=$(echo $OCF_RESKEY_address | tr '[:upper:]' '[:lower:]')
+fi
+
+if [ -z "$OCF_CHECK_LEVEL" ]; then
+	OCF_CHECK_LEVEL=0
+fi
+
+if [ "${OCF_RESKEY_monitor_link}" = "no" ] ||
+   [ "${OCF_RESKEY_monitor_link}" = "0" ]; then
+        OCF_RESKEY_monitor_link="no"
+else
+        OCF_RESKEY_monitor_link="yes"
+fi
+
+case $1 in
+start)
+	if address_configured ${OCF_RESKEY_family} ${OCF_RESKEY_address}; then
+		ocf_log debug "${OCF_RESKEY_address} already configured"
+		exit 0
+	fi
+	ip_op ${OCF_RESKEY_family} add ${OCF_RESKEY_address}
+	if [ $? -ne 0 ]; then
+		exit $OCF_ERR_GENERIC
+	fi
+
+	if [ $NFS_TRICKS -eq 0 ]; then
+		if [ "$OCF_RESKEY_nfslock" = "yes" ] || \
+	   	   [ "$OCF_RESKEY_nfslock" = "1" ]; then
+			notify_list_broadcast /var/lib/nfs/statd
+		fi
+	fi
+
+	exit $?
+	;;
+stop)
+	if address_configured ${OCF_RESKEY_family} ${OCF_RESKEY_address}; then
+		
+		ip_op ${OCF_RESKEY_family} del ${OCF_RESKEY_address}
+
+		# Make sure it's down
+		if address_configured ${OCF_RESKEY_family} ${OCF_RESKEY_address}; then
+			ocf_log err "Failed to remove ${OCF_RESKEY_address}"
+			exit 1
+		fi
+
+		# XXX Let nfsd/lockd clear their queues; we hope to have a
+		# way to enforce this in the future
+		if [ -z "$OCF_RESKEY_sleeptime" ]; then
+		    sleep 10
+		else
+		    if [ "$OCF_RESKEY_sleeptime" -gt "0" ]; then
+			sleep $OCF_RESKEY_sleeptime
+		    fi
+		fi
+	else
+		ocf_log debug "${OCF_RESKEY_address} is not configured"
+	fi
+	exit 0
+	;;
+status|monitor)
+	ip_op ${OCF_RESKEY_family} status ${OCF_RESKEY_address}
+	[ $? -ne 0 ] && exit $OCF_NOT_RUNNING
+	
+	check_interface_up ${OCF_RESKEY_family} ${OCF_RESKEY_address}
+	exit $?
+	;;
+restart)
+	$0 stop || exit $OCF_ERR_GENERIC
+	$0 start || exit $OCF_ERR_GENERIC
+	exit 0
+	;;
+meta-data)
+	meta_data
+	exit 0
+	;;
+validate-all|verify_all)
+	verify_all
+	exit $?
+	;;
+*)
+	echo "usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+	exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+
+
diff --git a/rgmanager/src/resources/lvm.metadata b/rgmanager/src/resources/lvm.metadata
new file mode 100644
index 0000000..3759063
--- /dev/null
+++ b/rgmanager/src/resources/lvm.metadata
@@ -0,0 +1,86 @@
+<?xml version="1.0" ?>
+<resource-agent name="lvm" version="rgmanager 2.0">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+	This defines a LVM volume group that is ...
+    </longdesc>
+
+    <shortdesc lang="en">
+	LVM Failover script
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+            <longdesc lang="en">
+                Unique name for this LVM resource
+            </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="vg_name" required="1">
+            <longdesc lang="en">
+                Name of the volume group being managed
+            </longdesc>
+            <shortdesc lang="en">
+                Volume group name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="lv_name">
+            <longdesc lang="en">
+                Name of the logical volume being managed.  This
+		parameter is optional if there are more than one
+		logical volumes in the volume group to be managed.
+            </longdesc>
+            <shortdesc lang="en">
+                Logical Volume name (optional).
+            </shortdesc>
+	    <content type="string"/>
+	</parameter>
+
+	<parameter name="self_fence">
+	    <longdesc lang="en">
+		If set and the clean up of the tags fails, the node will
+		immediately reboot.
+	    </longdesc>
+	    <shortdesc lang="en">
+		Fence the node if it is not able to clean up LVM tags
+	    </shortdesc>
+	    <content type="boolean"/>
+	</parameter>
+
+	<parameter name="nfslock" inherit="service%nfslock">
+	    <longdesc lang="en">
+	        If set and unmounting the file system fails, the node will
+		try to kill lockd and issue reclaims across all remaining
+		network interface cards.
+	    </longdesc>
+	    <shortdesc lang="en">
+	        Enable NFS lock workarounds
+	    </shortdesc>
+	    <content type="boolean"/>
+	</parameter>
+
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="5"/>
+	<action name="stop" timeout="5"/>
+
+	<action name="status" timeout="5" interval="1h"/>
+	<action name="monitor" timeout="5" interval="1h"/>
+
+	<action name="meta-data" timeout="5"/>
+	<action name="validate-all" timeout="30"/>
+    </actions>
+
+    <special tag="rgmanager">
+    	<attributes maxinstances="1"/>
+    </special>
+
+</resource-agent>
diff --git a/rgmanager/src/resources/lvm.sh b/rgmanager/src/resources/lvm.sh
new file mode 100755
index 0000000..97ddc52
--- /dev/null
+++ b/rgmanager/src/resources/lvm.sh
@@ -0,0 +1,180 @@
+#!/bin/bash
+
+#
+# LVM Failover Script.
+# NOTE: Changes to /etc/lvm/lvm.conf are required for proper operation.
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+LC_ALL=C
+LANG=C
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export LC_ALL LANG PATH
+
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/member_util.sh
+. $(dirname $0)/lvm_by_lv.sh
+. $(dirname $0)/lvm_by_vg.sh
+
+rv=0
+
+################################################################################
+# ha_lvm_proper_setup_check
+#
+################################################################################
+function ha_lvm_proper_setup_check
+{
+	##
+	# Does the Volume Group exist?
+	#  1) User may have forgotten to create it
+	#  2) User may have misspelled it in the config file
+	##
+	if ! vgs $OCF_RESKEY_vg_name --config 'global{locking_type=0}'>& /dev/null; then
+		ocf_log err "HA LVM: Unable to get volume group attributes for $OCF_RESKEY_vg_name"
+		return $OCF_ERR_GENERIC
+	fi
+
+	##
+	# Are we using the "tagging" or "CLVM" variant?
+	#  The CLVM variant will have the cluster attribute set
+	##
+	if [[ "$(vgs -o attr --noheadings --config 'global{locking_type=0}' $OCF_RESKEY_vg_name 2>/dev/null)" =~ .....c ]]; then
+		# Is clvmd running?
+		if ! ps -C clvmd >& /dev/null; then
+			ocf_log err "HA LVM: $OCF_RESKEY_vg_name has the cluster attribute set, but 'clvmd' is not running"
+			return $OCF_ERR_GENERIC
+		fi
+		return $OCF_SUCCESS
+	fi
+
+	##
+	# The "tagging" variant is being used if we have gotten this far.
+	##
+
+	##
+	# The default for lvm.conf:activation/volume_list is empty,
+	# this must be changed for HA LVM.
+	##
+	if ! lvm dumpconfig activation/volume_list >& /dev/null; then
+		ocf_log err "HA LVM:  Improper setup detected"
+		ocf_log err "* \"volume_list\" not specified in lvm.conf."
+		return $OCF_ERR_GENERIC
+	fi
+
+	##
+	# Machine's cluster node name must be present as
+	# a tag in lvm.conf:activation/volume_list
+	##
+	if ! lvm dumpconfig activation/volume_list | grep $(local_node_name); then
+		ocf_log err "HA LVM:  Improper setup detected"
+		ocf_log err "* @$(local_node_name) missing from \"volume_list\" in lvm.conf"
+		return $OCF_ERR_GENERIC
+	fi
+
+	##
+	# The volume group to be failed over must NOT be in
+	# lvm.conf:activation/volume_list; otherwise, machines
+	# will be able to activate the VG regardless of the tags
+	##
+	if lvm dumpconfig activation/volume_list | grep "\"$OCF_RESKEY_vg_name\""; then
+		ocf_log err "HA LVM:  Improper setup detected"
+		ocf_log err "* $OCF_RESKEY_vg_name found in \"volume_list\" in lvm.conf"
+		return $OCF_ERR_GENERIC
+	fi
+
+	##
+	# Next, we need to ensure that their initrd has been updated
+	# If not, the machine could boot and activate the VG outside
+	# the control of rgmanager
+	##
+	# Fixme: we might be able to perform a better check...
+	if [ "$(find /boot -name *.img -newer /etc/lvm/lvm.conf)" == "" ]; then
+		ocf_log err "HA LVM:  Improper setup detected"
+		ocf_log err "* initrd image needs to be newer than lvm.conf"
+
+		# While dangerous if not done the first time, there are many
+		# cases where we don't simply want to fail here.  Instead,
+		# keep warning until the user remakes the initrd - or has
+		# it done for them by upgrading the kernel.
+		#return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+################################################################################
+# MAIN
+################################################################################
+
+case $1 in
+start)
+	ha_lvm_proper_setup_check || exit 1
+
+	if [ -z "$OCF_RESKEY_lv_name" ]; then
+		vg_start || exit 1
+	else
+		lv_start || exit 1
+	fi
+	;;
+
+status|monitor)
+	ocf_log notice "Getting status"
+
+	if [ -z "$OCF_RESKEY_lv_name" ]; then
+		vg_status
+		exit $?
+	else
+		lv_status
+		exit $?
+	fi
+	;;
+		    
+stop)
+	ha_lvm_proper_setup_check
+
+	if [ -z "$OCF_RESKEY_lv_name" ]; then
+		vg_stop || exit 1
+	else
+		lv_stop || exit 1
+	fi
+	;;
+
+recover|restart)
+	$0 stop || exit $OCF_ERR_GENERIC
+	$0 start || exit $OCF_ERR_GENERIC
+	;;
+
+meta-data)
+	cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+	;;
+
+validate-all|verify-all)
+	if [ -z "$OCF_RESKEY_lv_name" ]; then
+		vg_verify || exit 1
+	else
+		lv_verify || exit 1
+	fi
+	;;
+*)
+	echo "usage: $0 {start|status|monitor|stop|restart|meta-data|validate-all}"
+	exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+
+exit $rv
diff --git a/rgmanager/src/resources/lvm_by_lv.sh b/rgmanager/src/resources/lvm_by_lv.sh
new file mode 100755
index 0000000..366eaec
--- /dev/null
+++ b/rgmanager/src/resources/lvm_by_lv.sh
@@ -0,0 +1,532 @@
+#!/bin/bash
+
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+# lv_verify
+#
+# Verify the parameters passed in
+#
+lv_verify()
+{
+	# Anything to verify?  Perhaps the names?
+	return $OCF_SUCCESS
+}
+
+# lv_owner
+#
+# Returns:
+#    1 == We are the owner
+#    2 == We can claim it
+#    0 == Owned by someone else
+function lv_owner
+{
+        local my_name=$1
+        local owner=$2
+
+        if [ -z "$my_name" ]; then
+                ocf_log err "Unable to determine cluster node name"
+                return 0
+        fi
+
+        if [ -z "$owner" ]; then
+                # No-one owns this LV yet, so we can claim it
+                return 2
+        fi
+
+        if [ $owner != $my_name ]; then
+                if is_node_member_clustat $owner ; then
+                        return 0
+                fi
+                return 2
+        fi
+
+        return 1
+}
+
+steal_tag()
+{
+	local owner=$1
+	local lv_path=$2
+
+        ocf_log notice "Owner of $lv_path is not in the cluster"
+        ocf_log notice "Stealing $lv_path"
+
+        lvchange --deltag $owner $lv_path
+        if [ $? -ne 0 ]; then
+ 	       ocf_log err "Failed to steal $lv_path from $owner"
+               return $OCF_ERR_GENERIC
+        fi
+
+        # Warning --deltag doesn't always result in failure
+        if [ ! -z `lvs -o tags --noheadings $lv_path` ]; then
+        	ocf_log err "Failed to steal $lv_path from $owner."
+         	return $OCF_ERR_GENERIC
+       	fi
+		
+	return $OCF_SUCCESS
+}
+
+restore_transient_failed_pvs()
+{
+	local a=0
+	local -a results
+
+	results=(`pvs -o name,vg_name,attr --noheadings | grep $OCF_RESKEY_vg_name | grep -v 'unknown device'`)
+	while [ ! -z "${results[$a]}" ] ; do
+		if [[ ${results[$(($a + 2))]} =~ ..m ]] &&
+		   [ $OCF_RESKEY_vg_name == ${results[$(($a + 1))]} ]; then
+			ocf_log notice "Attempting to restore missing PV, ${results[$a]} in $OCF_RESKEY_vg_name"
+			vgextend --restoremissing $OCF_RESKEY_vg_name ${results[$a]}
+			if [ $? -ne 0 ]; then
+				ocf_log notice "Failed to restore ${results[$a]}"
+			else
+				ocf_log notice "  ${results[$a]} restored"
+			fi
+		fi
+		a=$(($a + 3))
+	done
+}
+
+# lv_exec_resilient
+#
+# Sometimes, devices can come back.  Their metadata will conflict
+# with the good devices that remain.  This function filters out those
+# failed devices when executing the given command
+#
+# Finishing with vgscan resets the cache/filter
+lv_exec_resilient()
+{
+	declare command=$1
+	declare all_pvs
+
+	ocf_log notice "Making resilient : $command"
+
+	if [ -z "$command" ]; then
+		ocf_log err "lv_exec_resilient: Arguments not supplied"
+		return $OCF_ERR_ARGS
+	fi
+
+	# pvs will print out only those devices that are valid
+	# If a device dies and comes back, it will not appear
+	# in pvs output (but you will get a Warning).
+	all_pvs=(`pvs --noheadings -o pv_name | grep -v Warning`)
+
+	# Now we use those valid devices in a filter which we set up.
+	# The device will then be activated because there are no
+	# metadata conflicts.
+        command=$command" --config devices{filter=["
+	for i in ${all_pvs[*]}; do
+		command=$command'"a|'$i'|",'
+	done
+	command=$command"\"r|.*|\"]}"
+
+	ocf_log notice "Resilient command: $command"
+	if ! $command ; then
+		ocf_log err "lv_exec_resilient failed"
+		vgscan
+		return $OCF_ERR_GENERIC
+	else
+		vgscan
+		return $OCF_SUCCESS
+	fi
+}
+
+# lv_activate_resilient
+#
+# Sometimes, devices can come back.  Their metadata will conflict
+# with the good devices that remain.  We must filter out those
+# failed devices when trying to reactivate
+lv_activate_resilient()
+{
+	declare action=$1
+	declare lv_path=$2
+	declare op="-ay"
+
+	if [ -z "$action" ] || [ -z "$lv_path" ]; then
+		ocf_log err "lv_activate_resilient: Arguments not supplied"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ $action != "start" ]; then
+	        op="-an"
+	elif [[ "$(lvs -o attr --noheadings $lv_path)" =~ r.......p ]] ||
+	     [[ "$(lvs -o attr --noheadings $lv_path)" =~ R.......p ]]; then
+		# We can activate partial RAID LVs and run just fine.
+		ocf_log notice "Attempting activation of partial RAID LV, $lv_path"
+		op="-ay --partial"
+	fi
+
+	if ! lv_exec_resilient "lvchange $op $lv_path" ; then
+		ocf_log err "lv_activate_resilient $action failed on $lv_path"
+		return $OCF_ERR_GENERIC
+	else
+		return $OCF_SUCCESS
+	fi
+}
+
+lv_status_clustered()
+{
+	#
+	# Check if device is active
+	#
+	if [[ ! "$(lvs -o attr --noheadings $lv_path)" =~ ....a. ]]; then
+		return $OCF_NOT_RUNNING
+	fi
+
+	return $OCF_SUCCESS
+}
+
+# lv_status
+#
+# Is the LV active?
+lv_status_single()
+{
+	declare lv_path="$OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+	declare dev="/dev/$lv_path"
+	declare realdev
+	declare owner
+	declare my_name
+
+	#
+	# Check if device is active
+	#
+	if [[ ! "$(lvs -o attr --noheadings $lv_path)" =~ ....a. ]]; then
+		return $OCF_NOT_RUNNING
+	fi
+
+	if [[ "$(vgs -o attr --noheadings $OCF_RESKEY_vg_name)" =~ .....c ]]; then
+		ocf_log notice "$OCF_RESKEY_vg_name is a cluster volume.  Ignoring..."
+		return $OCF_SUCCESS
+	fi
+
+	#
+	# Check if all links/device nodes are present
+	#
+        if [ -h "$dev" ]; then
+		realdev=$(readlink -f $dev)
+		if [ $? -ne 0 ]; then
+			ocf_log err "Failed to follow link, $dev"
+			return $OCF_ERR_ARGS
+		fi
+
+		if [ ! -b $realdev ]; then
+			ocf_log err "Device node for $lv_path is not present"
+			return $OCF_ERR_GENERIC
+		fi
+	else
+	        ocf_log err "Symbolic link for $lv_path is not present"
+		return $OCF_ERR_GENERIC
+	fi
+
+	#
+	# Verify that we are the correct owner
+	#
+	owner=`lvs -o tags --noheadings $lv_path | tr -d ' '`
+	my_name=$(local_node_name)
+	if [ -z "$my_name" ]; then
+		ocf_log err "Unable to determine local machine name"
+
+		# FIXME: I don't really want to fail on 1st offense
+		return $OCF_SUCCESS
+	fi
+
+	if [ -z "$owner" ] || [ "$my_name" != "$owner" ]; then
+		ocf_log err "WARNING: $lv_path should not be active"
+		ocf_log err "WARNING: $my_name does not own $lv_path"
+		ocf_log err "WARNING: Attempting shutdown of $lv_path"
+
+		lv_activate_resilient "stop" $lv_path
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+function lv_status
+{
+	# We pass in the VG name to see of the logical volume is clustered
+	if [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ .....c ]]; then
+		lv_status_clustered
+	else
+		lv_status_single
+	fi
+}
+
+# lv_activate_and_tag
+lv_activate_and_tag()
+{
+	declare action=$1
+	declare tag=$2
+	declare lv_path=$3
+	typeset self_fence=""
+
+	case ${OCF_RESKEY_self_fence} in
+		"yes")          self_fence=1 ;;
+		1)              self_fence=1 ;;
+		*)              self_fence="" ;;
+	esac
+
+	if [ -z "$action" ] || [ -z "$tag" ] || [ -z "$lv_path" ]; then
+		ocf_log err "Supplied args: 1) $action, 2) $tag, 3) $lv_path"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ "$action" == "start" ]; then
+		ocf_log notice "Activating $lv_path"
+		lvchange --addtag $tag $lv_path
+		if [ $? -ne 0 ]; then
+			ocf_log err "Unable to add tag to $lv_path"
+			return $OCF_ERR_GENERIC
+		fi
+
+		if ! lv_activate_resilient $action $lv_path; then
+			ocf_log err "Unable to activate $lv_path"
+			return $OCF_ERR_GENERIC
+		fi
+	else
+		ocf_log notice "Deactivating $lv_path"
+		if ! lv_activate_resilient $action $lv_path; then
+			if [ "$self_fence" ]; then
+				ocf_log err "Unable to deactivate $lv_path: REBOOTING"
+				sync
+				reboot -fn
+			else
+				ocf_log err "Unable to deactivate $lv_path"
+			fi
+			return $OCF_ERR_GENERIC
+		fi
+
+		# Only try to remove tag if it is our tag
+		if [ "`lvs --noheadings -o lv_tags $lv_path | tr -d ' '`" == $tag ]; then
+			ocf_log notice "Removing ownership tag ($tag) from $lv_path"
+			lvchange --deltag $tag $lv_path
+			if [ $? -ne 0 ]; then
+				ocf_log err "Unable to delete tag from $lv_path"
+	
+				# Newer versions of LVM require the missing PVs to
+				# be removed from the VG via a separate call before
+				# the tag can be removed.
+				ocf_log err "Attempting volume group clean-up and retry"
+				vgreduce --removemissing --mirrorsonly --force $OCF_RESKEY_vg_name
+	
+				# Retry tag deletion
+				lvchange --deltag $tag $lv_path
+				if [ $? -ne 0 ]; then
+		                        if [ "$self_fence" ]; then
+		                                ocf_log err "Failed to delete tag from $lv_path: REBOOTING"
+	                	                sync
+	                        	        reboot -fn
+		                        else
+		                                ocf_log err "Failed to delete tag from $lv_path"
+	                	        fi
+	                        	return $OCF_ERR_GENERIC
+				fi
+			fi
+		fi
+	fi
+
+	return $OCF_SUCCESS
+}
+
+# lv_activate
+# $1: start/stop only
+#
+# Basically, if we want to [de]activate an LVM volume,
+# we must own it.  That means that our tag must be on it.
+# This requires a change to /etc/lvm/lvm.conf:
+#	volume_list = [ "root_volume", "@my_hostname" ]
+# where "root_volume" is your root volume group and
+# "my_hostname" is $(local_node_name)
+#
+# If there is a node failure, we may wish to "steal" the
+# LV.  For that, we need to check if the node that owns
+# it is still part of the cluster.  We use the tag to
+# determine who owns the volume then query for their
+# liveness.  If they are dead, we can steal.
+lv_activate()
+{
+	declare lv_path="$OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+	declare owner=`lvs -o tags --noheadings $lv_path | tr -d ' '`
+	declare my_name=$(local_node_name)
+	local owned
+
+	lv_owner $my_name $owner
+	owned=$?
+	if [ $owned -eq 0 ]; then
+		ocf_log info "Someone else owns this logical volume"
+		return $OCF_ERR_GENERIC
+	fi
+
+	# If this is a partial VG, attempt to
+	# restore any transiently failed PVs
+	if [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ ...p ]]; then
+		ocf_log err "Volume group \"$OCF_RESKEY_vg_name\" has PVs marked as missing"
+		restore_transient_failed_pvs
+	fi
+
+	if [ ! -z "$owner" ] && [ $owned -eq 2 ]; then
+		steal_tag $owner $lv_path
+	fi
+
+	if ! lv_activate_and_tag $1 $my_name $lv_path; then
+		ocf_log err "Failed to $1 $lv_path"
+
+		ocf_log notice "Attempting cleanup of $OCF_RESKEY_vg_name"
+
+		if vgreduce --removemissing --mirrorsonly --force --config \
+		    "activation { volume_list = \"$OCF_RESKEY_vg_name\" }" \
+		    $OCF_RESKEY_vg_name; then
+			ocf_log notice "$OCF_RESKEY_vg_name now consistent"
+			owner=`lvs -o tags --noheadings $lv_path | tr -d ' '`
+
+			lv_owner $my_name $owner
+			owned=$?
+			if [ ! -z "$owner" ] && [ $owned -eq 2 ]; then
+				steal_tag $owner $lv_path
+				ret=$?
+				if [ $ret -ne $OCF_SUCCESS ]; then
+					return $ret
+				fi
+			elif [ $owned -eq 0 ]; then
+				ocf_log info "Someone else owns this logical volume"
+				return $OCF_ERR_GENERIC
+			fi
+
+			if ! lv_activate_and_tag $1 $my_name $lv_path; then
+				ocf_log err "Failed second attempt to $1 $lv_path"
+				return $OCF_ERR_GENERIC
+			else
+				ocf_log notice "Second attempt to $1 $lv_path successful"
+				return $OCF_SUCCESS
+			fi
+		else
+			ocf_log err "Failed to $1 $lv_path"
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+	return $OCF_SUCCESS
+}
+
+function lv_start_clustered
+{
+	if lvchange -aey $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name; then
+		return $OCF_SUCCESS
+	fi
+
+	# FAILED exclusive activation:
+	# This can be caused by an LV being active remotely.
+	# Before attempting a repair effort, we should attempt
+	# to deactivate the LV cluster-wide; but only if the LV
+	# is not open.  Otherwise, it is senseless to attempt.
+	if ! [[ "$(lvs -o attr --noheadings $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name)" =~ ....ao ]]; then
+		# We'll wait a small amount of time for some settling before
+		# attempting to deactivate.  Then the deactivate will be
+		# immediately followed by another exclusive activation attempt.
+		sleep 5
+		if ! lvchange -an $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name; then
+			# Someone could have the device open.
+			# We can't do anything about that.
+			ocf_log err "Unable to perform required deactivation of $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name before starting"
+			return $OCF_ERR_GENERIC
+		fi
+
+		if lvchange -aey $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name; then
+			# Second attempt after deactivation was successful, we now
+			# have the lock exclusively
+			return $OCF_SUCCESS
+		fi
+	fi
+
+	# Failed to activate:
+	# This could be due to a device failure (or another machine could
+	# have snuck in between the deactivation/activation).  We don't yet
+	# have a mechanism to check for remote activation, so we will proceed
+	# with repair action.
+	ocf_log err "Failed to activate logical volume, $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+	ocf_log notice "Attempting cleanup of $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+
+	if ! lvconvert --repair --use-policies $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name; then
+		ocf_log err "Failed to cleanup $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+		return $OCF_ERR_GENERIC
+	fi
+
+	if ! lvchange -aey $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name; then
+		ocf_log err "Failed second attempt to activate $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+		return $OCF_ERR_GENERIC
+	fi
+
+	ocf_log notice "Second attempt to activate $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name successful"
+	return $OCF_SUCCESS
+}
+
+function lv_start_single
+{
+	if ! lvs $OCF_RESKEY_vg_name >& /dev/null; then
+		lv_count=0
+	else
+		lv_count=`lvs --noheadings -o name $OCF_RESKEY_vg_name | grep -v _mlog | grep -v _mimage | grep -v nconsistent | wc -l`
+	fi
+	if [ $lv_count -gt 1 ]; then
+		ocf_log err "HA LVM requires Only one logical volume per volume group."
+		ocf_log err "There are currently $lv_count logical volumes in $OCF_RESKEY_vg_name"
+		ocf_log err "Failing HA LVM start of $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name"
+		exit $OCF_ERR_GENERIC
+	fi
+
+	if ! lv_activate start; then
+		return 1
+	fi
+
+	return 0
+}
+
+function lv_start
+{
+	# We pass in the VG name to see of the logical volume is clustered
+	if [[ "$(vgs -o attr --noheadings $OCF_RESKEY_vg_name)" =~ .....c ]]; then
+		lv_start_clustered
+	else
+		lv_start_single
+	fi
+}
+
+function lv_stop_clustered
+{
+	lvchange -aln $OCF_RESKEY_vg_name/$OCF_RESKEY_lv_name
+}
+
+function lv_stop_single
+{
+	if ! lv_activate stop; then
+		return 1
+	fi
+
+	return 0
+}
+
+function lv_stop
+{
+	# We pass in the VG name to see of the logical volume is clustered
+	if [[ "$(vgs -o attr --noheadings $OCF_RESKEY_vg_name)" =~ .....c ]]; then
+		lv_stop_clustered
+	else
+		lv_stop_single
+	fi
+}
diff --git a/rgmanager/src/resources/lvm_by_vg.sh b/rgmanager/src/resources/lvm_by_vg.sh
new file mode 100755
index 0000000..d8a3e31
--- /dev/null
+++ b/rgmanager/src/resources/lvm_by_vg.sh
@@ -0,0 +1,529 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+# vg_owner
+#
+# Returns:
+#    1 == We are the owner
+#    2 == We can claim it
+#    0 == Owned by someone else
+function vg_owner
+{
+	local owner=`vgs -o tags --noheadings $OCF_RESKEY_vg_name | tr -d ' '`
+	local my_name=$(local_node_name)
+
+	if [ -z "$my_name" ]; then
+		ocf_log err "Unable to determine cluster node name"
+		return 0
+	fi
+
+	if [ -z "$owner" ]; then
+		# No-one owns this VG yet, so we can claim it
+		return 2
+	fi
+
+	if [ $owner != $my_name ]; then
+		if is_node_member_clustat $owner ; then
+			ocf_log err "  $owner owns $OCF_RESKEY_vg_name and is still a cluster member"
+			return 0
+		fi
+		return 2
+	fi
+
+	return 1
+}
+
+restore_transient_failed_pvs()
+{
+        local a=0
+        local -a results
+
+        results=(`pvs -o name,vg_name,attr --noheadings | grep $OCF_RESKEY_vg_name | grep -v 'unknown device'`)
+        while [ ! -z "${results[$a]}" ] ; do
+                if [[ ${results[$(($a + 2))]} =~ ..m ]] &&
+                   [ $OCF_RESKEY_vg_name == ${results[$(($a + 1))]} ]; then
+                        ocf_log notice "Attempting to restore missing PV, ${results[$a]} in $OCF_RESKEY_vg_name"
+                        vgextend --restoremissing $OCF_RESKEY_vg_name ${results[$a]}
+                        if [ $? -ne 0 ]; then
+                                ocf_log notice "Failed to restore ${results[$a]}"
+                        else
+                                ocf_log notice "  ${results[$a]} restored"
+                        fi
+                fi
+                a=$(($a + 3))
+        done
+}
+
+function strip_tags
+{
+	local i
+
+	for i in `vgs --noheadings -o tags $OCF_RESKEY_vg_name | sed s/","/" "/g`; do
+		ocf_log info "Stripping tag, $i"
+
+		# LVM version 2.02.98 allows changing tags if PARTIAL
+		vgchange --deltag $i $OCF_RESKEY_vg_name
+	done
+
+	if [ ! -z `vgs -o tags --noheadings $OCF_RESKEY_vg_name | tr -d ' '` ]; then
+		ocf_log err "Failed to remove ownership tags from $OCF_RESKEY_vg_name"
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+function strip_and_add_tag
+{
+	if ! strip_tags; then
+		ocf_log err "Failed to remove tags from volume group, $OCF_RESKEY_vg_name"
+		return $OCF_ERR_GENERIC
+	fi
+
+	vgchange --addtag $(local_node_name) $OCF_RESKEY_vg_name
+	if [ $? -ne 0 ]; then
+		ocf_log err "Failed to add ownership tag to $OCF_RESKEY_vg_name"
+		return $OCF_ERR_GENERIC
+        fi
+
+	ocf_log info "New tag \"$(local_node_name)\" added to $OCF_RESKEY_vg_name"
+
+	return $OCF_SUCCESS
+}
+
+function vg_status_clustered
+{
+	return $OCF_SUCCESS
+}
+
+# vg_status
+#
+# Are all the LVs active?
+function vg_status_single
+{
+	local i
+	local dev
+	local my_name=$(local_node_name)
+
+	#
+	# Check that all LVs are active
+	#
+	for i in `lvs $OCF_RESKEY_vg_name --noheadings -o attr`; do
+		if [[ ! $i =~ ....a. ]]; then
+			return $OCF_NOT_RUNNING
+		fi
+	done
+
+	#
+	# Check if all links/device nodes are present
+	#
+	for i in `lvs $OCF_RESKEY_vg_name --noheadings -o name`; do
+		dev="/dev/$OCF_RESKEY_vg_name/$i"
+
+		if [ -h $dev ]; then
+			realdev=$(readlink -f $dev)
+			if [ $? -ne 0 ]; then
+				ocf_log err "Failed to follow link, $dev"
+				return $OCF_ERR_GENERIC
+			fi
+
+			if [ ! -b $realdev ]; then
+				ocf_log err "Device node for $dev is not present"
+				return $OCF_ERR_GENERIC
+			fi
+		else
+			ocf_log err "Symbolic link for $lv_path is not present"
+			return $OCF_ERR_GENERIC
+		fi
+	done
+
+	#
+	# Verify that we are the correct owner
+	#
+	vg_owner
+	if [ $? -ne 1 ]; then
+		ocf_log err "WARNING: $OCF_RESKEY_vg_name should not be active"
+		ocf_log err "WARNING: $my_name does not own $OCF_RESKEY_vg_name"
+		ocf_log err "WARNING: Attempting shutdown of $OCF_RESKEY_vg_name"
+
+		# FIXME: may need more force to shut this down
+		vgchange -an $OCF_RESKEY_vg_name
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+##
+# Main status function for volume groups
+##
+function vg_status
+{
+	if [[ "$(vgs -o attr --noheadings $OCF_RESKEY_vg_name)" =~ .....c ]]; then
+		vg_status_clustered
+	else
+		vg_status_single
+	fi
+}
+
+function vg_verify
+{
+	# Anything to verify?
+	return $OCF_SUCCESS
+}
+
+function vg_start_clustered
+{
+	local a
+	local results
+	local all_pvs
+	local resilience
+	local try_again=false
+
+	ocf_log info "Starting volume group, $OCF_RESKEY_vg_name"
+
+	if ! vgchange -aey $OCF_RESKEY_vg_name; then
+		try_again=true
+
+		# Failure to activate:
+		# This could be caused by a remotely active LV.  Before
+		# attempting any repair of the VG, we will first attempt
+		# to deactivate the VG cluster-wide.
+		# We must check for open LVs though, since these cannot
+		# be deactivated.  We have no choice but to go one-by-one.
+
+		# Allow for some settling
+		sleep 5
+
+		results=(`lvs -o name,attr --noheadings $OCF_RESKEY_vg_name 2> /dev/null`)
+		a=0
+		while [ ! -z "${results[$a]}" ]; do
+			if [[ ! ${results[$(($a + 1))]} =~ ....ao ]]; then
+				if ! lvchange -an $OCF_RESKEY_vg_name/${results[$a]}; then
+					ocf_log err "Unable to perform required deactivation of $OCF_RESKEY_vg_name before starting"
+					return $OCF_ERR_GENERIC
+				fi
+			fi
+			a=$(($a + 2))
+		done
+	fi
+
+	if $try_again && ! vgchange -aey $OCF_RESKEY_vg_name; then
+		ocf_log err "Failed to activate volume group, $OCF_RESKEY_vg_name"
+		ocf_log notice "Attempting cleanup of $OCF_RESKEY_vg_name"
+
+		if ! vgreduce --removemissing --mirrorsonly --force $OCF_RESKEY_vg_name; then
+			ocf_log err "Failed to make $OCF_RESKEY_vg_name consistent"
+			return $OCF_ERR_GENERIC
+		fi
+
+		if ! vgchange -aey $OCF_RESKEY_vg_name; then
+			ocf_log err "Failed second attempt to activate $OCF_RESKEY_vg_name"
+			return $OCF_ERR_GENERIC
+		fi
+
+		ocf_log notice "Second attempt to activate $OCF_RESKEY_vg_name successful"
+		return $OCF_SUCCESS
+	else
+		# The activation commands succeeded, but did they do anything?
+		# Make sure all the logical volumes are active
+		results=(`lvs -o name,attr --noheadings 2> /dev/null $OCF_RESKEY_vg_name`)
+		a=0
+		while [ ! -z "${results[$a]}" ]; do
+			if [[ ! ${results[$(($a + 1))]} =~ ....a. ]]; then
+				all_pvs=(`pvs --noheadings -o name 2> /dev/null`)
+				resilience=" --config devices{filter=["
+			        for i in ${all_pvs[*]}; do
+			                resilience=$resilience'"a|'$i'|",'
+        			done
+				resilience=$resilience"\"r|.*|\"]}"
+
+				vgchange -aey $OCF_RESKEY_vg_name $resilience
+				break
+			fi
+			a=$(($a + 2))
+		done
+
+		#  We need to check the LVs again if we made the command resilient
+		if [ ! -z "$resilience" ]; then
+			results=(`lvs -o name,attr --noheadings $OCF_RESKEY_vg_name $resilience 2> /dev/null`)
+			a=0
+			while [ ! -z ${results[$a]} ]; do
+				if [[ ! ${results[$(($a + 1))]} =~ ....a. ]]; then
+		                        ocf_log err "Failed to activate $OCF_RESKEY_vg_name"
+                		        return $OCF_ERR_GENERIC
+                		fi
+				a=$(($a + 2))
+			done
+			ocf_log err "Orphan storage device in $OCF_RESKEY_vg_name slowing operations"
+		fi
+	fi
+
+	return $OCF_SUCCESS
+}
+
+function vg_start_single
+{
+	local a
+	local results
+	local all_pvs
+	local resilience
+
+	ocf_log info "Starting volume group, $OCF_RESKEY_vg_name"
+
+	vg_owner
+	case $? in
+	0)
+		ocf_log info "Someone else owns this volume group"
+		return $OCF_ERR_GENERIC
+		;;
+	1)
+		ocf_log info "I own this volume group"
+		;;
+	2)
+		ocf_log info "I can claim this volume group"
+		;;
+	esac
+
+	if ! strip_and_add_tag; then
+		# Errors printed by sub-function
+		return $OCF_ERR_GENERIC
+	fi
+
+	if ! vgchange -ay $OCF_RESKEY_vg_name; then
+		ocf_log err "Failed to activate volume group, $OCF_RESKEY_vg_name"
+		ocf_log err "Attempting activation of logical volumes one-by-one."
+
+		results=(`lvs -o name,attr --noheadings $OCF_RESKEY_vg_name 2> /dev/null`)
+		a=0
+		while [ ! -z ${results[$a]} ]; do
+			if [[ ${results[$(($a + 1))]} =~ r.......p ]] ||
+		   	   [[ ${results[$(($a + 1))]} =~ R.......p ]]; then
+				# Attempt "partial" activation of any RAID LVs
+				ocf_log err "Attempting partial activation of ${OCF_RESKEY_vg_name}/${results[$a]}"
+				if ! lvchange -ay --partial ${OCF_RESKEY_vg_name}/${results[$a]}; then
+					ocf_log err "Failed attempt to activate ${OCF_RESKEY_vg_name}/${results[$a]} in partial mode"
+					return $OCF_ERR_GENERIC
+				fi
+				ocf_log notice "Activation of ${OCF_RESKEY_vg_name}/${results[$a]} in partial mode succeeded"
+			elif [[ ${results[$(($a + 1))]} =~ m.......p ]] ||
+		   	     [[ ${results[$(($a + 1))]} =~ M.......p ]]; then
+				ocf_log err "Attempting repair and activation of ${OCF_RESKEY_vg_name}/${results[$a]}"
+				if ! lvconvert --repair --use-policies ${OCF_RESKEY_vg_name}/${results[$a]}; then
+					ocf_log err "Failed to repair ${OCF_RESKEY_vg_name}/${results[$a]}"
+					return $OCF_ERR_GENERIC
+				fi
+				if ! lvchange -ay ${OCF_RESKEY_vg_name}/${results[$a]}; then
+					ocf_log err "Failed to activate ${OCF_RESKEY_vg_name}/${results[$a]}"
+					return $OCF_ERR_GENERIC
+				fi
+				ocf_log notice "Repair and activation of ${OCF_RESKEY_vg_name}/${results[$a]} succeeded"
+			else
+				ocf_log err "Attempting activation of non-redundant LV ${OCF_RESKEY_vg_name}/${results[$a]}"
+				if ! lvchange -ay ${OCF_RESKEY_vg_name}/${results[$a]}; then
+					ocf_log err "Failed to activate ${OCF_RESKEY_vg_name}/${results[$a]}"
+					return $OCF_ERR_GENERIC
+				fi
+				ocf_log notice "Successfully activated non-redundant LV ${OCF_RESKEY_vg_name}/${results[$a]}"
+			fi
+			a=$(($a + 2))
+		done
+
+		return $OCF_SUCCESS
+	else
+		# The activation commands succeeded, but did they do anything?
+		# Make sure all the logical volumes are active
+		results=(`lvs -o name,attr --noheadings $OCF_RESKEY_vg_name 2> /dev/null`)
+		a=0
+		while [ ! -z ${results[$a]} ]; do
+			if [[ ! ${results[$(($a + 1))]} =~ ....a. ]]; then
+				all_pvs=(`pvs --noheadings -o name 2> /dev/null`)
+				resilience=" --config devices{filter=["
+			        for i in ${all_pvs[*]}; do
+			                resilience=$resilience'"a|'$i'|",'
+        			done
+				resilience=$resilience"\"r|.*|\"]}"
+
+				vgchange -ay $OCF_RESKEY_vg_name $resilience
+				break
+			fi
+			a=$(($a + 2))
+		done
+
+		#  We need to check the LVs again if we made the command resilient
+		if [ ! -z "$resilience" ]; then
+			results=(`lvs -o name,attr --noheadings $OCF_RESKEY_vg_name $resilience 2> /dev/null`)
+			a=0
+			while [ ! -z ${results[$a]} ]; do
+				if [[ ! ${results[$(($a + 1))]} =~ ....a. ]]; then
+		                        ocf_log err "Failed to activate $OCF_RESKEY_vg_name"
+                		        return $OCF_ERR_GENERIC
+                		fi
+				a=$(($a + 2))
+			done
+			ocf_log err "Orphan storage device in $OCF_RESKEY_vg_name slowing operations"
+		fi
+	fi
+
+	return $OCF_SUCCESS
+}
+
+##
+# Main start function for volume groups
+##
+function vg_start
+{
+	local a=0
+	local results
+
+	if [[ $(vgs -o attr --noheadings $OCF_RESKEY_vg_name) =~ ...p ]]; then
+                ocf_log err "Volume group \"$OCF_RESKEY_vg_name\" has PVs marked as missing"
+                restore_transient_failed_pvs
+        fi
+
+	if [[ "$(vgs -o attr --noheadings $OCF_RESKEY_vg_name)" =~ .....c ]]; then
+		vg_start_clustered
+	else
+		vg_start_single
+	fi
+}
+
+function vg_stop_clustered
+{
+	local a
+	local results
+	typeset self_fence=""
+
+	case ${OCF_RESKEY_self_fence} in
+		"yes")          self_fence=1 ;;
+		1)              self_fence=1 ;;
+		*)              self_fence="" ;;
+	esac
+
+	#  Shut down the volume group
+	#  Do we need to make this resilient?
+	a=0
+	while ! vgchange -aln $OCF_RESKEY_vg_name; do
+		a=$(($a + 1))
+		if [ $a -gt 10 ]; then
+			break;
+		fi
+		ocf_log err "Unable to deactivate $OCF_RESKEY_vg_name, retrying($a)"
+		sleep 1
+		which udevadm >& /dev/null && udevadm settle
+	done
+
+	#  Make sure all the logical volumes are inactive
+	active=0
+	results=(`lvs -o name,attr --noheadings $OCF_RESKEY_vg_name 2> /dev/null`)
+	a=0
+	while [ ! -z ${results[$a]} ]; do
+		if [[ ${results[$(($a + 1))]} =~ ....a. ]]; then
+			active=1
+			break
+		fi
+                a=$(($a + 2))
+	done
+
+	# lvs may not show active volumes if all PVs in VG are gone
+	dmsetup table | grep -q "^${OCF_RESKEY_vg_name//-/--}-[^-]"
+	if [ $? -eq 0 ]; then
+		active=1
+	fi
+
+	if [ $active -ne 0 ]; then
+		if [ "$self_fence" ]; then
+			ocf_log err "Unable to deactivate $lv_path REBOOT"
+			sync
+			reboot -fn
+		else
+			ocf_log err "Logical volume $OCF_RESKEY_vg_name/${results[$a]} failed to shutdown"
+		fi
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+function vg_stop_single
+{
+	local a
+	local results
+	typeset self_fence=""
+
+	case ${OCF_RESKEY_self_fence} in
+		"yes")          self_fence=1 ;;
+		1)              self_fence=1 ;;
+		*)              self_fence="" ;;
+	esac
+
+	#  Shut down the volume group
+	#  Do we need to make this resilient?
+	vgchange -an $OCF_RESKEY_vg_name
+
+	#  Make sure all the logical volumes are inactive
+        active=0
+	results=(`lvs -o name,attr --noheadings $OCF_RESKEY_vg_name 2> /dev/null`)
+	a=0
+	while [ ! -z ${results[$a]} ]; do
+		if [[ ${results[$(($a + 1))]} =~ ....a. ]]; then
+			active=1
+			break
+		fi
+	        a=$(($a + 2))
+	done
+
+        # lvs may not show active volumes if all PVs in VG are gone
+        dmsetup table | grep -q "^${OCF_RESKEY_vg_name//-/--}-[^-]"
+        if [ $? -eq 0 ]; then
+                active=1
+        fi
+
+        if [ $active -ne 0 ]; then
+		if [ "$self_fence" ]; then
+			ocf_log err "Unable to deactivate $lv_path REBOOT"
+			sync
+			reboot -fn
+		else
+			ocf_log err "Logical volume $OCF_RESKEY_vg_name/${results[$a]} failed to shutdown"
+		fi
+		return $OCF_ERR_GENERIC
+	fi
+
+	#  Make sure we are the owner before we strip the tags
+	vg_owner
+	if [ $? -ne 0 ]; then
+		strip_tags
+	fi
+
+	return $OCF_SUCCESS
+}
+
+##
+# Main stop function for volume groups
+##
+function vg_stop
+{
+	if [[ "$(vgs -o attr --noheadings $OCF_RESKEY_vg_name)" =~ .....c ]]; then
+		vg_stop_clustered
+	else
+		vg_stop_single
+	fi
+}
diff --git a/rgmanager/src/resources/mysql.metadata b/rgmanager/src/resources/mysql.metadata
new file mode 100644
index 0000000..d3ade15
--- /dev/null
+++ b/rgmanager/src/resources/mysql.metadata
@@ -0,0 +1,107 @@
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent version="rgmanager 2.0" name="mysql">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines an instance of MySQL database server
+    </longdesc>
+    <shortdesc lang="en">
+        Defines a MySQL database server
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+	        Define a name 
+	    </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="config_file">
+            <longdesc lang="en">
+                Define configuration file
+            </longdesc>
+            <shortdesc lang="en">
+                Define configuration file
+            </shortdesc>
+	    <content type="string" default="/etc/my.cnf"/>
+        </parameter>
+
+        <parameter name="listen_address">
+            <longdesc lang="en">
+		Define an IP address for MySQL
+            </longdesc>
+            <shortdesc lang="en">
+		Define an IP address for MySQL server. If the address
+		is not given then first IP address from the service is taken.
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+	<parameter name="mysqld_options">
+		<longdesc lang="en">
+			Other command-line options for mysqld
+		</longdesc>
+		<shortdesc lang="en">
+			Other command-line options for mysqld
+		</shortdesc>
+		<content type="string" />
+	</parameter>
+
+	<parameter name="startup_wait">
+		<longdesc lang="en">
+			Wait X seconds for correct end of service startup
+		</longdesc>
+		<shortdesc lang="en">
+			Wait X seconds for correct end of service startup
+		</shortdesc>
+		<content type="integer" default="30" />
+	</parameter>
+
+	<parameter name="shutdown_wait">
+		<longdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</longdesc>
+		<shortdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</shortdesc>
+		<content type="integer" />
+	</parameter>
+
+        <parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+	    	Inherit the service name.  We need to know
+		the service name in order to determine file
+		systems and IPs for this service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Inherit the service name.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="0"/>
+	<action name="stop" timeout="0"/>
+
+	<!-- Checks to see if it''s mounted in the right place -->
+	<action name="status" interval="1m" timeout="10"/>
+	<action name="monitor" interval="1m" timeout="10"/>
+
+	<!-- Checks to see if we can read from the mountpoint -->
+	<action name="status" depth="10" timeout="30" interval="5m"/>
+	<action name="monitor" depth="10" timeout="30" interval="5m"/>
+
+	<action name="meta-data" timeout="0"/>
+	<action name="validate-all" timeout="0"/>
+    </actions>
+
+    <special tag="rgmanager">
+    </special>
+</resource-agent>
diff --git a/rgmanager/src/resources/mysql.sh b/rgmanager/src/resources/mysql.sh
new file mode 100755
index 0000000..c7a7723
--- /dev/null
+++ b/rgmanager/src/resources/mysql.sh
@@ -0,0 +1,213 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+export LC_ALL=C
+export LANG=C
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+declare MYSQL_MYSQLD=/usr/bin/mysqld_safe
+declare MYSQL_ipAddress
+declare MYSQL_pid_file="`generate_name_for_pid_file`"
+
+verify_all()
+{
+	clog_service_verify $CLOG_INIT
+
+	if [ -z "$OCF_RESKEY_name" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid Name Of Service"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_service_name" ]; then
+		clog_service_verify $CLOG_FAILED_NOT_CHILD
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_INVALID "$OCF_RESKEY_config_file"
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ ! -r "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_NOT_READABLE $OCF_RESKEY_config_file
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$MYSQL_pid_file" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid name of PID file"
+		return $OCF_ERR_ARGS
+	fi
+
+	clog_service_verify $CLOG_SUCCEED
+	return 0
+}
+
+start()
+{
+        if status; then
+                ocf_log info "Starting Service $OCF_RESOURCE_INSTANCE > Already running"
+                return $OCF_SUCCESS
+        fi
+
+	clog_service_start $CLOG_INIT
+
+	create_pid_directory
+	check_pid_file "$MYSQL_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_check_pid $CLOG_FAILED "$MYSQL_pid_file"
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	if [ -n "$OCF_RESKEY_listen_address" ]; then
+		MYSQL_ipAddress="$OCF_RESKEY_listen_address"
+	else
+		clog_looking_for $CLOG_INIT "IP Address"
+
+	        get_service_ip_keys "$OCF_RESKEY_service_name"
+	        ip_addresses=`build_ip_list`
+
+		if [ -n "$ip_addresses" ]; then
+			for i in $ip_addresses; do
+				MYSQL_ipAddress="$i"
+				break;
+			done
+		else
+			clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Address"
+		fi
+	fi
+
+	clog_looking_for $CLOG_SUCCEED "IP Address"
+
+	$MYSQL_MYSQLD --defaults-file="$OCF_RESKEY_config_file" \
+		--pid-file="$MYSQL_pid_file" \
+		--bind-address="$MYSQL_ipAddress" \
+		$OCF_RESKEY_mysqld_options > /dev/null 2>&1 &
+
+	if [ $? -ne 0 ]; then
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	declare i=$OCF_RESKEY_startup_wait
+	while [ "$i" -gt 0 ]; do
+		if [ -f "$MYSQL_pid_file" ]; then
+			break;			
+		fi
+		sleep 1
+		let i=$i-1
+        done
+
+        if [ "$i" -eq 0 ]; then
+		clog_service_start $CLOG_FAILED_TIMEOUT
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_service_start $CLOG_SUCCEED
+
+	return 0;
+}
+
+stop()
+{
+	clog_service_stop $CLOG_INIT
+
+	stop_generic "$MYSQL_pid_file" "$OCF_RESKEY_shutdown_wait"
+	
+	if [ $? -ne 0 ]; then
+		clog_service_stop $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_service_stop $CLOG_SUCCEED
+	return 0;
+}
+
+status()
+{
+	clog_service_status $CLOG_INIT
+
+	status_check_pid "$MYSQL_pid_file"
+	case $? in
+		$OCF_NOT_RUNNING)
+		clog_service_status $CLOG_FAILED "$MYSQL_pid_file"
+		return $OCF_NOT_RUNNING
+		;;
+	0)
+		clog_service_status $CLOG_SUCCEED
+		exit 0
+		;;
+	*)
+		clog_service_status $CLOG_FAILED "$MYSQL_pid_file"
+		return $OCF_ERR_GENERIC
+		;;
+	esac
+
+		
+	if [ $? -ne 0 ]; then
+		clog_service_status $CLOG_FAILED "$MYSQL_pid_file"
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_status $CLOG_SUCCEED
+	return 0
+}
+
+case $1 in
+	meta-data)
+		cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+		exit 0
+		;;
+	validate-all)
+		verify_all
+		exit $?
+		;;
+	start)
+		verify_all && start
+		exit $?
+		;;
+	stop)
+		verify_all && stop
+		exit $?
+		;;
+	status|monitor)
+		verify_all
+		status
+		exit $?
+		;;
+	restart)
+		verify_all
+		stop
+		start
+		exit $?
+		;;
+	*)
+		echo "Usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
diff --git a/rgmanager/src/resources/named.metadata b/rgmanager/src/resources/named.metadata
new file mode 100644
index 0000000..548d03b
--- /dev/null
+++ b/rgmanager/src/resources/named.metadata
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<resource-agent version="rgmanager 2.0" name="named">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines an instance of DNS named server
+    </longdesc>
+    <shortdesc lang="en">
+        Defines an instance of named server
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+	        Specifies a service name for logging and other purposes
+	    </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="config_file">
+            <longdesc lang="en">
+                Define absolute path to configuration file
+            </longdesc>
+            <shortdesc lang="en">
+                Config File
+            </shortdesc>
+	    <content type="string" default="/etc/named.conf"/>
+        </parameter>
+
+        <parameter name="named_sdb">
+            <longdesc lang="en">
+		Simplified Database Backend
+            </longdesc>
+            <shortdesc lang="en">
+		Simplified Database Backend
+            </shortdesc>
+	    <content type="boolean" default="0"/>
+        </parameter>
+
+	<parameter name="named_working_dir">
+		<longdesc lang="en">
+			Other command-line options for named
+		</longdesc>
+		<shortdesc lang="en">
+			Other command-line options for named
+		</shortdesc>
+		<content type="string" default="/var/named" />
+	</parameter>
+
+	<parameter name="named_options">
+		<longdesc lang="en">
+			Other command-line options for named
+		</longdesc>
+		<shortdesc lang="en">
+			Other command-line options for named
+		</shortdesc>
+		<content type="string" />
+	</parameter>
+
+
+	<parameter name="update_source">
+		<longdesc lang="en">
+			Update 'notify-source', 'transfer-source', and 'query-source' to match
+			the cluster ip associated with this service.
+		</longdesc>
+		<shortdesc lang="en">
+			Use cluster ip as source.
+		</shortdesc>
+		<content type="string" />
+	</parameter>
+
+	<parameter name="shutdown_wait">
+		<longdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</longdesc>
+		<shortdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</shortdesc>
+		<content type="integer" default="5" />
+	</parameter>
+
+        <parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+	    	Inherit the service name.  We need to know
+		the service name in order to determine file
+		systems and IPs for this service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Inherit the service name.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="0"/>
+	<action name="stop" timeout="0"/>
+
+	<!-- Checks to see if it''s mounted in the right place -->
+	<action name="status" interval="1m" timeout="10"/>
+	<action name="monitor" interval="1m" timeout="10"/>
+
+	<!-- Checks to see if we can read from the mountpoint -->
+	<action name="status" depth="10" timeout="30" interval="5m"/>
+	<action name="monitor" depth="10" timeout="30" interval="5m"/>
+
+	<action name="meta-data" timeout="0"/>
+	<action name="validate-all" timeout="0"/>
+    </actions>
+
+    <special tag="rgmanager">
+    </special>
+</resource-agent>
diff --git a/rgmanager/src/resources/named.sh b/rgmanager/src/resources/named.sh
new file mode 100755
index 0000000..f73bf89
--- /dev/null
+++ b/rgmanager/src/resources/named.sh
@@ -0,0 +1,215 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+export LC_ALL=C
+export LANG=C
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+declare NAMED_NAMED=/usr/sbin/named
+declare NAMED_pid_file="`generate_name_for_pid_file`"
+declare NAMED_conf_dir="`generate_name_for_conf_dir`"
+declare NAMED_gen_config_file="$NAMED_conf_dir/named.conf"
+declare NAMED_url_list
+declare NAMED_parse_config=$(dirname $0)/utils/named-parse-config.pl
+declare NAMED_update_src="false"
+
+verify_all()
+{
+	clog_service_verify $CLOG_INIT
+
+	if [ -z "$OCF_RESKEY_name" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid Name Of Service"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_service_name" ]; then
+		clog_service_verify $CLOG_FAILED_NOT_CHILD
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_INVALID "$OCF_RESKEY_config_file"
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ ! -r "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_NOT_READABLE $OCF_RESKEY_config_file
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -n "$OCF_RESKEY_update_source" ]; then
+		NAMED_update_src=$OCF_RESKEY_update_source
+	fi
+	clog_service_verify $CLOG_SUCCEED
+		
+	return 0
+}
+
+generate_config_file()
+{
+	declare original_file="$1"
+	declare generated_file="$2"
+	declare ip_address="$3"
+
+	if [ -f "$generated_file" ]; then
+		sha1_verify "$generated_file"
+		if [ $? -ne 0 ]; then
+			clog_check_sha1 $CLOG_FAILED
+			return 0
+		fi
+	fi	
+
+	clog_generate_config $CLOG_INIT "$original_file" "$generated_file"
+
+	generate_configTemplate "$generated_file" "$1"
+	cat "$original_file" | grep -v "^[[:space:]]*listen-on" | \
+		grep -v "^[[:space:]]*pid-file" | \
+		grep -v "^[[:space:]]*directory" >> "$generated_file"
+
+	declare tmp_file=`mktemp -t cluster.XXXXXXXXXX`
+	mv "$generated_file" "$tmp_file"
+
+	"$NAMED_parse_config" "$OCF_RESKEY_named_working_dir" "$NAMED_pid_file" "$ip_address" "$NAMED_update_src"\
+		 < "$tmp_file" > "$generated_file"
+
+	rm "$tmp_file"	
+        sha1_addToFile "$generated_file"
+	clog_generate_config $CLOG_SUCCEED "$original_file" "$generated_file"
+
+	return 0;
+}
+
+start()
+{
+	declare ip_list;
+	
+	clog_service_start $CLOG_INIT
+
+	create_pid_directory
+	create_conf_directory "$NAMED_conf_dir"
+	check_pid_file "$NAMED_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_check_pid $CLOG_FAILED "$NAMED_pid_file"
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	clog_looking_for $CLOG_INIT "IP Addresses"
+
+        get_service_ip_keys "$OCF_RESKEY_service_name"
+        ip_addresses=`build_ip_list`
+
+	if [ -z "$ip_addresses" ]; then
+		clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Addresses"
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_looking_for $CLOG_SUCCEED "IP Addresses"
+
+	ip_list=`echo $ip_addresses | sed 's/ /;/;s/\([[:digit:]]\)$/\1;/' `
+
+	if [ -z "$ip_list" ]; then
+		clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Addresses"
+		return $OCF_ERR_GENERIC
+	fi
+
+	generate_config_file "$OCF_RESKEY_config_file" "$NAMED_gen_config_file" "$ip_list"
+
+	$NAMED_NAMED -c "$NAMED_gen_config_file" $OCF_RESKEY_named_options
+
+	if [ $? -ne 0 ]; then
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_start $CLOG_SUCCEED
+
+	return 0;
+}
+
+stop()
+{
+	clog_service_stop $CLOG_INIT
+
+	stop_generic "$NAMED_pid_file" "$OCF_RESKEY_shutdown_wait"
+	
+	if [ $? -ne 0 ]; then
+		clog_service_stop $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_service_stop $CLOG_SUCCEED
+	return 0;
+}
+
+status()
+{
+	clog_service_status $CLOG_INIT
+
+	status_check_pid "$NAMED_pid_file"
+	if [ $? -ne 0 ]; then
+		clog_service_status $CLOG_FAILED "$NAMED_pid_file"
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_status $CLOG_SUCCEED
+	return 0
+}
+
+case $1 in
+	meta-data)
+		cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+		exit 0
+		;;
+	validate-all)
+		verify_all
+		exit $?
+		;;
+	start)
+		verify_all && start
+		exit $?
+		;;
+	stop)
+		verify_all && stop
+		exit $?
+		;;
+	status|monitor)
+		verify_all
+		status
+		exit $?
+		;;
+	restart)
+		verify_all
+		stop
+		start
+		exit $?
+		;;
+	*)
+		echo "Usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
diff --git a/rgmanager/src/resources/netfs.sh b/rgmanager/src/resources/netfs.sh
new file mode 100755
index 0000000..5dad993
--- /dev/null
+++ b/rgmanager/src/resources/netfs.sh
@@ -0,0 +1,493 @@
+#!/bin/bash
+
+#
+# NFS/CIFS file system mount/umount/etc. agent
+#
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+. $(dirname $0)/utils/fs-lib.sh
+
+do_metadata()
+{
+	cat <<EOT
+<?xml version="1.0" ?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent name="netfs" version="rgmanager 2.0">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines an NFS/CIFS mount for use by cluster services.
+    </longdesc>
+    <shortdesc lang="en">
+        Defines an NFS/CIFS file system mount.
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+	        Symbolic name for this file system.
+	    </longdesc>
+            <shortdesc lang="en">
+                File System Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="mountpoint" unique="1" required="1">
+	    <longdesc lang="en">
+	        Path in file system heirarchy to mount this file system.
+	    </longdesc>
+            <shortdesc lang="en">
+                Mount Point
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="host" required="1">
+	    <longdesc lang="en">
+	    	Server IP address or hostname
+	    </longdesc>
+            <shortdesc lang="en">
+	    	IP or Host
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="export" required="1">
+	    <longdesc lang="en">
+	    	NFS Export directory name or CIFS share
+	    </longdesc>
+            <shortdesc lang="en">
+	    	Export
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="fstype" required="0">
+	    <longdesc lang="en">
+	    	File System type (nfs, nfs4 or cifs)
+	    </longdesc>
+            <shortdesc lang="en">
+	    	File System Type
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="no_unmount" required="0">
+	    <longdesc lang="en">
+	    	Do not unmount the filesystem during a stop or relocation operation
+	    </longdesc>
+            <shortdesc lang="en">
+	    	Skip unmount opration
+            </shortdesc>
+	    <content type="boolean"/>
+        </parameter>
+
+        <parameter name="force_unmount">
+            <longdesc lang="en">
+                If set, the cluster will kill all processes using 
+                this file system when the resource group is 
+                stopped.  Otherwise, the unmount will fail, and
+                the resource group will be restarted.
+            </longdesc>
+            <shortdesc lang="en">
+                Force Unmount
+            </shortdesc>
+	    <content type="boolean"/>
+        </parameter>
+
+        <parameter name="self_fence">
+            <longdesc lang="en">
+                If set and unmounting the file system fails, the node will
+                immediately reboot.  Generally, this is used in conjunction
+                with force_unmount support, but it is not required.
+            </longdesc>
+            <shortdesc lang="en">
+                Seppuku Unmount
+            </shortdesc>
+            <content type="boolean"/>
+        </parameter>
+
+        <parameter name="options">
+            <longdesc lang="en">
+	    	Provides a list of mount options.  If none are specified,
+		the NFS file system is mounted -o sync.
+            </longdesc>
+            <shortdesc lang="en">
+                Mount Options
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="use_findmnt">
+            <longdesc lang="en">
+        Use findmnt to determine if and where a filesystem is mounted.
+        Disabling this uses the failback method (should be used if autofs
+        maps are located on network storage (ie. nfs, iscsi, etc).
+            </longdesc>
+            <shortdesc lang="en">
+        Utilize findmnt to detect if and where filesystems are mounted
+            </shortdesc>
+            <content type="boolean"/>
+        </parameter>
+
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="900"/>
+	<action name="stop" timeout="30"/>
+	<!-- Recovery isn't possible; we don't know if resources are using
+	     the file system. -->
+
+	<!-- Checks to see if it's mounted in the right place -->
+	<action name="status" interval="1m" timeout="10"/>
+	<action name="monitor" interval="1m" timeout="10"/>
+
+	<!-- Checks to see if we can read from the mountpoint -->
+	<action name="status" depth="10" timeout="30" interval="5m"/>
+	<action name="monitor" depth="10" timeout="30" interval="5m"/>
+
+	<!-- Checks to see if we can write to the mountpoint (if !ROFS) -->
+	<action name="status" depth="20" timeout="30" interval="10m"/>
+	<action name="monitor" depth="20" timeout="30" interval="10m"/>
+
+	<action name="meta-data" timeout="5"/>
+	<action name="validate-all" timeout="5"/>
+    </actions>
+
+    <special tag="rgmanager">
+        <child type="nfsexport" forbid="1"/>
+        <child type="nfsclient" forbid="1"/>
+    </special>
+</resource-agent>
+EOT
+}
+
+
+verify_host()
+{
+	if [ -z "$OCF_RESKEY_host" ]; then
+	       ocf_log err "No server hostname or IP address specified."
+	       return 1
+	fi
+
+	host $OCF_RESKEY_host 2>&1 | grep -vq "not found"
+	if [ $? -eq 0 ]; then
+		return 0
+	fi
+
+	ocf_log err "Hostname or IP address \"$OCF_RESKEY_host\" not valid"
+
+	return $OCF_ERR_ARGS
+}
+
+
+verify_fstype()
+{
+	# Auto detect?
+	[ -z "$OCF_RESKEY_fstype" ] && return 0
+
+	case $OCF_RESKEY_fstype in
+	nfs|nfs4|cifs)
+		return 0
+		;;
+	*)
+		ocf_log err "File system type $OCF_RESKEY_fstype not supported"
+		return $OCF_ERR_ARGS
+		;;
+	esac
+}
+
+
+verify_options()
+{
+	declare -i ret=0
+
+	#
+	# From mount(1)
+	#
+	for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do
+		case $o in
+		async|atime|auto|defaults|dev|exec|_netdev|noatime)
+			continue
+			;;
+		noauto|nodev|noexec|nosuid|nouser|ro|rw|suid|sync)
+			continue
+			;;
+		dirsync|user|users)
+			continue
+			;;
+		esac
+
+		case $OCF_RESKEY_fstype in
+		cifs)
+			continue
+			;;
+		nfs|nfs4)
+			case $o in
+			#
+			# NFS / NFS4 common
+			#
+			rsize=*|wsize=*|timeo=*|retrans=*|acregmin=*)
+				continue
+				;;
+			acregmax=*|acdirmin=*|acdirmax=*|actimeo=*)
+				continue
+				;;
+			retry=*|port=*|bg|fg|soft|hard|intr|cto|ac|noac)
+				continue
+				;;
+			esac
+
+			#
+			# NFS v2/v3 only
+			#
+			if [ "$OCF_RESKEY_fstype" = "nfs" ]; then
+				case $o in
+				mountport=*|mounthost=*)
+					continue
+					;;
+				mountprog=*|mountvers=*|nfsprog=*|nfsvers=*)
+					continue
+					;;
+				namelen=*)
+					continue
+					;;
+				tcp|udp|lock|nolock)
+					continue
+					;;
+				esac
+			fi
+
+			#
+			# NFS4 only
+			#
+			if [ "$OCF_RESKEY_fstype" = "nfs4" ]; then
+				case $o in
+				proto=*|clientaddr=*|sec=*)
+					continue
+					;;
+				esac
+			fi
+
+			;;
+		esac
+
+		ocf_log err "Option $o not supported for $OCF_RESKEY_fstype"
+		ret=$OCF_ERR_ARGS
+	done
+
+	return $ret
+}
+
+
+do_validate()
+{
+	verify_name || return $OCF_ERR_ARGS
+	verify_fstype|| return $OCF_ERR_ARGS
+	verify_host || return $OCF_ERR_ARGS
+	verify_mountpoint || return $OCF_ERR_ARGS
+	verify_options || return $OCF_ERR_ARGS
+	# verify_target || return $OCF_ERR_ARGS
+}
+
+
+#
+# Override real_device to use fs-lib's functions for start/stop_filesystem
+#
+real_device() {
+	export REAL_DEVICE="$1"
+}
+
+
+#
+# do_mount - nfs / cifs are mounted differently than blockdevs
+#
+do_mount() {
+	declare opts=""
+	declare mount_options=""
+	declare ret_val
+	declare mp="$OCF_RESKEY_mountpoint"
+
+	#
+	# Get the filesystem type, if specified.
+	#
+	fstype_option=""
+	fstype=${OCF_RESKEY_fstype}
+		case "$fstype" in
+	""|"[ 	]*")
+		fstype=""
+		;;
+	*)	# found it
+		fstype_option="-t $fstype"
+		;;
+	esac
+
+	#
+	# Get the mount options, if they exist.
+	#
+	mount_options=""
+	opts=${OCF_RESKEY_options}
+	case "$opts" in 
+	""|"[ 	]*")
+		opts=""
+		;;
+	*)	# found it
+		mount_options="-o $opts"
+		;;
+	esac
+
+        case $OCF_RESKEY_fstype in
+	nfs|nfs4)
+		mount -t $OCF_RESKEY_fstype $mount_options $OCF_RESKEY_host:"$OCF_RESKEY_export" "$mp"
+		;;
+	cifs)
+		mount -t $OCF_RESKEY_fstype $mount_options //$OCF_RESKEY_host/"$OCF_RESKEY_export" "$mp"
+		;;
+	esac
+
+	ret_val=$?
+	if [ $ret_val -ne 0 ]; then
+		ocf_log err "\
+'mount $fstype_option $mount_options $OCF_RESKEY_host:$OCF_RESKEY_export $mp' failed, error=$ret_val"
+		return 1
+	fi
+	
+	return 0
+}
+
+do_nfs_rpc_check() {
+	# see man nfs TRANSPORT PROTOCOL section for defaults
+	local nfsproto=tcp
+	local nfsmountproto=udp
+
+	# follow the same logic as mount.nfs option parser.
+	# the rightmost option wins over previous ones, so don't break when
+	# we find something.
+
+	for o in $(echo ${OCF_RESKEY_options} | sed -e s/,/\ /g); do
+		if echo $o | grep -q "^proto=" ; then
+			nfsproto="$(echo $o | cut -d "=" -f 2)"
+		fi
+		if echo $o | grep -q "^mountproto=" ; then
+			nfsmountproto="$(echo $o | cut -d "=" -f 2)"
+		fi
+		case $o in
+		tcp)	nfsproto=tcp;;
+		udp)	nfsproto=udp;;
+		rdma)	nfsproto=rdma;;
+		esac
+	done
+
+	ocf_log debug "Testing generic rpc access on server ${OCF_RESKEY_host} with protocol $nfsproto"
+	if ! rpcinfo -T $nfsproto ${OCF_RESKEY_host} > /dev/null 2>&1; then
+		ocf_log alert "RPC server on ${OCF_RESKEY_host} with $nfsproto is not responding"
+		return 1
+	fi
+
+	ocf_log debug "Testing nfs rcp access on server ${OCF_RESKEY_host} with protocol $nfsproto"
+	if ! rpcinfo -T $nfsproto ${OCF_RESKEY_host} nfs > /dev/null 2>&1; then
+		ocf_log alert "NFS server on ${OCF_RESKEY_host} with $nfsproto is not responding"
+		return 1 
+	fi
+
+	if [ "$OCF_RESKEY_fstype" = nfs ]; then
+		ocf_log debug "Testing mountd rpc access on server ${OCF_RESKEY_host} with protocol $nfsmountproto"
+		if ! rpcinfo -T $nfsmountproto ${OCF_RESKEY_host} mountd; then
+			ocf_log alert "MOUNTD server on ${OCF_RESKEY_host} with $nfsmountproto is not responding"
+			return 1
+		fi
+	fi
+
+	return 0
+}
+
+do_pre_unmount() {
+	case $OCF_RESKEY_fstype in
+	nfs|nfs4)
+		if [ "$self_fence" != $YES ]; then
+			ocf_log debug "Skipping pre unmount checks: self_fence is disabled"
+			return 0
+		fi
+
+		is_mounted "$dev" "$mp"
+		case $? in
+		$NO)
+			ocf_log debug "Skipping pre unmount checks: device is not mounted"
+			return 0
+			;;
+		esac
+
+		ocf_log info "pre unmount: checking if nfs server ${OCF_RESKEY_host} is alive"
+		if ! do_nfs_rpc_check; then
+			ocf_log alert "NFS server not responding - REBOOTING"
+			sleep 2
+			reboot -fn
+		fi
+		;;
+	esac
+
+	return 0
+}
+
+do_force_unmount() {
+        case $OCF_RESKEY_fstype in
+	nfs|nfs4)
+		ocf_log warning "Calling 'umount -f $mp'"
+		umount -f "$OCF_RESKEY_mountpoint"
+		return $?
+		;;
+	*)
+		;;
+	esac
+
+	return 1	# Returning 1 lets stop_filesystem do add'l checks
+}
+
+
+populate_defaults()
+{
+	if [ -z "$OCF_RESKEY_fstype" ]; then
+		export OCF_RESKEY_fstype=nfs
+	fi
+
+
+        case $OCF_RESKEY_fstype in
+	nfs|nfs4)
+		export OCF_RESKEY_device="$OCF_RESKEY_host:$OCF_RESKEY_export"
+		if [ -z "$OCF_RESKEY_options" ]; then
+			export OCF_RESKEY_options=sync,soft,noac
+		fi
+		;;
+	cifs)
+		export OCF_RESKEY_device="//$OCF_RESKEY_host/$OCF_RESKEY_export"
+		if [ -z "$OCF_RESKEY_options" ]; then
+			export OCF_RESKEY_options=guest
+		fi
+		;;
+	esac
+}
+
+
+#
+# Main...
+#
+populate_defaults
+main $*
diff --git a/rgmanager/src/resources/nfsclient.sh b/rgmanager/src/resources/nfsclient.sh
new file mode 100755
index 0000000..3d0e3f1
--- /dev/null
+++ b/rgmanager/src/resources/nfsclient.sh
@@ -0,0 +1,471 @@
+#!/bin/bash
+
+#
+# NFS Export Client handler agent script
+#
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+LC_ALL=C
+LANG=C
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export LC_ALL LANG PATH
+
+. $(dirname $0)/ocf-shellfuncs
+
+meta_data()
+{
+	cat <<EOT
+<?xml version="1.0" ?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent version="rgmanager 2.0" name="nfsclient">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines how a machine or group of machines may access
+        an NFS export on the cluster.  IP addresses, IP wildcards,
+	hostnames, hostname wildcards, and netgroups are supported.
+    </longdesc>
+    <shortdesc lang="en">
+        Defines an NFS client.
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" unique="1" primary="1">
+            <longdesc lang="en">
+                This is a symbolic name of a client used to reference
+                it in the resource tree.  This is NOT the same thing
+                as the target option.
+            </longdesc>
+            <shortdesc lang="en">
+                Client Name
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="target" required="1">
+            <longdesc lang="en">
+                This is either a hostname, a wildcard (IP address or
+                hostname based), or a netgroup to which defining a
+                host or hosts to export to.
+            </longdesc>
+            <shortdesc lang="en">
+                Target Hostname, Wildcard, or Netgroup
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="path" inherit="path">
+            <longdesc lang="en">
+                This is the path to export to the target.  This
+                field is generally left blank, as it inherits the
+                path from the parent export.
+            </longdesc>
+            <shortdesc lang="en">
+                Path to Export
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="svcname" inherit="service%name">
+            <longdesc lang="en">
+            </longdesc>
+            <shortdesc lang="en">
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+
+        <parameter name="fsid" inherit="fsid">
+            <longdesc lang="en">
+	    	File system ID inherited from the parent nfsexport/
+		clusterfs/fs resource.  Putting fsid in the options
+		field will override this.
+            </longdesc>
+            <shortdesc lang="en">
+	    	File system ID
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="options">
+            <longdesc lang="en">Defines a list of options for this
+                particular client.  See 'man 5 exports' for a list
+                of available options.
+            </longdesc>
+            <shortdesc lang="en">
+                Export Options
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="allow_recover">
+            <longdesc lang="en">
+		Allows recovery of this NFS client (default = 1) if it
+		disappears from the export list.  If set to 0, the service
+		will be restarted.  This is useful to help preserve export
+		ordering.
+            </longdesc>
+            <shortdesc lang="en">
+		Allow recovery
+            </shortdesc>
+            <content type="boolean"/>
+        </parameter>
+
+	<parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+		Service this NFS export belongs to.  Used for caching
+		exports on a per-service basis.
+            </longdesc>
+            <shortdesc lang="en">
+                Service Name
+            </shortdesc>
+	    <content type="string"/>
+	</parameter>
+
+	<parameter name="use_cache" inherit="service%nfs_client_cache">
+            <longdesc lang="en">
+	   	On systems with large numbers of exports, a performance
+		problem in the exportfs command can cause inordinately long
+		status check times for services with lots of mounted
+		NFS clients.  This occurs because exportfs does DNS queries
+		on all clients in the export list.
+
+		Setting this option to '1' will enable caching of the export
+		list returned from the exportfs command on a per-service
+		basis.  The cache will last for 30 seconds before expiring
+		instead of being generated each time an nfsclient resource
+		is called.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Enable exportfs list caching
+            </shortdesc>
+	    <content type="integer"/>
+	</parameter>
+
+
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="90"/>
+        <action name="stop" timeout="5"/>
+        <action name="recover" timeout="90"/>
+
+	<!-- Checks to see if the export exists in /var/lib/nfs/etab -->
+        <action name="status" timeout="5" interval="1m"/>
+        <action name="monitor" timeout="5" interval="1m"/>
+
+        <action name="meta-data" timeout="5"/>
+        <action name="validate-all" timeout="30"/>
+    </actions>
+
+</resource-agent>
+EOT
+}
+
+
+verify_options()
+{
+	declare o
+	declare -i ret=0
+
+	[ -z "$OCF_RESKEY_options" ] && return 0
+	
+	#
+	# From exports(5)
+	#
+	for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do
+		case $o in
+		fsid=*)
+			ocf_log debug "Using designated $o instead of fsid=$OCF_RESKEY_fsid"
+			unset OCF_RESKEY_fsid
+			;;
+		secure)
+			;;
+		insecure)
+			;;
+		sec=*)
+			;;
+		rw)
+			;;
+		ro)
+			;;
+		async)
+			;;
+		sync)
+			;;
+		wdelay)
+			;;
+		no_wdelay)
+			;;
+		hide)
+			;;
+		nohide)
+			;;
+		subtree_check)
+			;;
+		no_subtree_check)
+			;;
+		secure_locks)
+			;;
+		insecure_locks)
+			;;
+		auth_nlm)
+			;;
+		no_auth_nlm)
+			;;
+		mountpoint=*)
+			;;
+		mp=*)
+			;;
+		root_squash)
+			;;
+		no_root_squash)
+			;;
+		all_squash)
+			;;
+		no_all_squash)
+			;;
+		anonuid=*)
+			;;
+		anongid=*)
+			;;
+		*)
+			ocf_log err "Export Option $o invalid"
+			ret=$OCF_ERR_ARGS
+			;;
+		esac
+	done
+
+	return $ret
+}
+
+
+verify_target()
+{
+	# XXX need to add wildcards, hostname, ip, etc.
+	[ -n "$OCF_RESKEY_target" ] && return 0
+	
+	return $OCF_ERR_ARGS
+}
+
+
+verify_path()
+{
+	if [ -z "$OCF_RESKEY_path" ]; then
+		ocf_log err "No export path specified."
+		return $OCF_ERR_ARGS
+	fi
+
+	OCF_RESKEY_path="${OCF_RESKEY_path%/}"
+
+	[ -d "$OCF_RESKEY_path" ] && return 0
+
+	ocf_log err "$OCF_RESKEY_path is not a directory"
+	
+	return $OCF_ERR_ARGS
+}
+
+
+verify_type()
+{
+	[ -z "$OCF_RESKEY_type" ] && return 0
+	[ "$OCF_RESKEY_type" = "nfs" ] && return 0
+
+	ocf_log err "Export type $OCF_RESKEY_type not supported yet"
+	return $OCF_ERR_ARGS
+}
+
+
+verify_all()
+{
+	declare -i ret=0
+
+	verify_type || ret=$OCF_ERR_ARGS
+	verify_options || ret=$OCF_ERR_ARGS
+	verify_target || ret=$OCF_ERR_ARGS
+	verify_path || ret=$OCF_ERR_ARGS
+
+	return $ret
+}
+
+
+case $1 in
+start)
+	declare option_str
+
+	verify_all || exit $OCF_ERR_ARGS
+
+	#
+	# XXX
+	# Bad: Side-effect of verify_options: unset OCF_RESKEY_fsid if
+	# fsid is specified in the options string.
+	#
+	if [ -z "$OCF_RESKEY_options" ] && [ -n "$OCF_RESKEY_fsid" ]; then
+		option_str="fsid=$OCF_RESKEY_fsid"
+	elif [ -n "$OCF_RESKEY_options" ] && [ -z "$OCF_RESKEY_fsid" ]; then
+		option_str="$OCF_RESKEY_options"
+	elif [ -n "$OCF_RESKEY_fsid" ] && [ -n "$OCF_RESKEY_options" ]; then
+		option_str="fsid=$OCF_RESKEY_fsid,$OCF_RESKEY_options"
+	fi
+
+	if [ -z "$option_str" ]; then
+		ocf_log info "Adding export: ${OCF_RESKEY_target}:${OCF_RESKEY_path}"
+		exportfs -i "${OCF_RESKEY_target}:${OCF_RESKEY_path}"
+		rv=$?
+	else
+		ocf_log info "Adding export: ${OCF_RESKEY_target}:${OCF_RESKEY_path} ($option_str)"
+		exportfs -i -o $option_str "${OCF_RESKEY_target}:${OCF_RESKEY_path}"
+		rv=$?
+	fi
+	;;
+
+stop)
+	verify_all || exit $OCF_ERR_ARGS
+
+	ocf_log info "Removing export: ${OCF_RESKEY_target}:${OCF_RESKEY_path}"
+	exportfs -u "${OCF_RESKEY_target}:${OCF_RESKEY_path}"
+	rv=$?
+	;;
+
+status|monitor)
+	verify_all || exit $OCF_ERR_ARGS
+
+	if [ "${OCF_RESKEY_target}" = "*" ]; then
+		export OCF_RESKEY_target="\<world\>"
+	fi
+
+	#
+	# Status check fix from Birger Wathne:
+	# * Exports longer than 14 chars have line breaks inserted, which
+	#   broke the way the status check worked.
+	#
+        # Status check fix from Craig Lewis: 
+        # * Exports with RegExp metacharacters need to be escaped. 
+        #   These metacharacters are: * ? . 
+        # 
+	export OCF_RESKEY_target_regexp=$(echo $OCF_RESKEY_target | \
+		sed -e 's/*/[*]/g' -e 's/?/[?]/g' -e 's/\./\\./g') 
+
+	declare tmpfn
+	declare time_created time_now
+	declare -i delta=0
+
+	#
+	# Don't let anyone read the cache files.
+	#
+	umask 066
+
+	mkdir -p /var/cache/cluster
+
+	if [ -n "$OCF_RESKEY_service_name" ] && [ "$OCF_RESKEY_use_cache" = "1" ]; then
+
+		#
+		# For large #s of exports, we need to cache the information
+		#
+		tmpfn=/var/cache/cluster/nfsclient-status-cache-$OCF_RESKEY_service_name
+
+		if [ -f "$tmpfn" ]; then
+			time_created=$(stat -c "%Y" $tmpfn)
+			time_now=$(date +"%s")
+			delta=$((time_now-time_created))
+		fi
+		#echo "Cache age = $delta seconds"
+	else
+		delta=100
+		#
+		# Create a different file if this is a separate instance
+		#
+		tmpfn=/var/cache/cluster/nfsclient-status-cache-$$
+	fi
+
+	if ! [ -f "$tmpfn" ] || [ $delta -gt 30 ]; then
+		#echo "Create $tmpfn. Nonexistent / expired / no service name"
+		exportfs -v > $tmpfn
+	fi
+
+        cat $tmpfn | tr -d "\n" | sed -e 's/([^)]*)/\n/g' | grep -Piq \
+		"^${OCF_RESKEY_path}[\t ]+${OCF_RESKEY_target_regexp}"
+	rv=$? 
+
+	if [ $rv -eq 0 ]; then
+		[ "$OCF_RESKEY_use_cache" = "1" ] || rm -f $tmpfn
+		exit 0
+	fi
+
+	declare OCF_RESKEY_target_tmp
+	OCF_RESKEY_target_tmp=$(clufindhostname -i "$OCF_RESKEY_target")
+	if [ $? -ne 0 ]; then
+		OCF_RESKEY_target_tmp=$(clufindhostname -n "$OCF_RESKEY_target")
+		if [ $? -ne 0 ]; then
+			[ "$OCF_RESKEY_use_cache" = "1" ] || rm -f $tmpfn
+			ocf_log err "nfsclient:$OCF_RESKEY_name is missing!"
+			exit 1
+		fi
+	fi
+
+        cat $tmpfn | tr -d "\n" | sed -e 's/([^)]*)/\n/g' | grep -Pq \
+		"^${OCF_RESKEY_path}[\t ]+${OCF_RESKEY_target_tmp}"
+	rv=$? 
+
+	[ "$OCF_RESKEY_use_cache" = "1" ] || rm -f $tmpfn
+	if [ $rv -eq 0 ]; then
+		exit 0
+	fi
+
+	ocf_log err "nfsclient:$OCF_RESKEY_name is missing!"
+	exit $OCF_NOT_RUNNING
+	;;
+
+recover)
+	if [ "$OCF_RESKEY_allow_recover" = "0" ] || \
+	   [ "$OCF_RESKEY_allow_recover" = "no" ] || \
+	   [ "$OCF_RESKEY_allow_recover" = "false" ]; then
+		exit 1
+	fi
+
+	$0 stop || exit 1
+	$0 start || exit 1
+	;;
+
+restart)
+	#
+	# Recover might better be "exportfs -r" - reexport
+	#
+	$0 stop || exit 1
+	$0 start || exit 1
+	;;
+
+meta-data)
+	meta_data
+	exit 0
+	;;
+
+validate-all)
+	verify_all
+	rv=$?
+	;;
+
+*)
+	echo "usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+	rv=$OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+
+exit $rv
diff --git a/rgmanager/src/resources/nfsexport.sh b/rgmanager/src/resources/nfsexport.sh
new file mode 100755
index 0000000..f69eab5
--- /dev/null
+++ b/rgmanager/src/resources/nfsexport.sh
@@ -0,0 +1,256 @@
+#!/bin/bash
+
+#
+# NFS Export Script.  Handles starting/stopping clurmtabd and doing
+# the strange NFS stuff to get it to fail over properly.
+#
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+LC_ALL=C
+LANG=C
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export LC_ALL LANG PATH
+
+. $(dirname $0)/ocf-shellfuncs
+
+
+rmtabpid=""
+nfsop_arg=""
+rv=0
+
+meta_data()
+{
+	cat <<EOT
+<?xml version="1.0" ?>
+<resource-agent name="nfsexport" version="rgmanager 2.0">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines an NFS export path.  Generally, these are
+        defined inline and implicitly; you should not have to 
+        configure one of these.  All of the relevant information
+        is inherited from the parent.
+    </longdesc>
+
+    <shortdesc lang="en">
+        This defines an NFS export.
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+            <longdesc lang="en">
+                Descriptive name for this export.  Generally, only
+                one export is ever defined, and it's called "generic
+                nfs export".
+            </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="device" inherit="device">
+            <longdesc lang="en">
+                If you can see this, your GUI is broken.
+            </longdesc>
+            <shortdesc lang="en">
+                If you can see this, your GUI is broken.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="path" inherit="mountpoint">
+            <longdesc lang="en">
+                If you can see this, your GUI is broken.
+            </longdesc>
+            <shortdesc lang="en">
+                If you can see this, your GUI is broken.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="fsid" inherit="fsid">
+            <longdesc lang="en">
+                If you can see this, your GUI is broken.
+            </longdesc>
+            <shortdesc lang="en">
+                If you can see this, your GUI is broken.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="5"/>
+	<action name="stop" timeout="5"/>
+	<action name="recover" timeout="5"/>
+
+	<!-- NFS Exports really don't do anything except provide a path
+	     for nfs clients.  So, status and monitor are no-ops -->
+	<action name="status" timeout="5" interval="1h"/>
+	<action name="monitor" timeout="5" interval="1h"/>
+
+	<action name="meta-data" timeout="5"/>
+	<action name="validate-all" timeout="30"/>
+    </actions>
+
+    <special tag="rgmanager">
+	<child type="nfsexport" forbid="1"/>
+	<child type="nfsclient"/>
+    </special>
+
+</resource-agent>
+EOT
+}
+
+
+verify_device()
+{
+	if [ -z "$OCF_RESKEY_device" ]; then
+	       ocf_log err "No device or label specified."
+	       return $OCF_ERR_ARGS
+	fi
+
+	[ -b "$OCF_RESKEY_device" ] && return 0
+	[ -b "`findfs $OCF_RESKEY_device`" ] && return 0
+
+	ocf_log err "Device or label \"$OCF_RESKEY_device\" not valid"
+
+	return $OCF_ERR_ARGS
+}
+
+
+verify_path()
+{
+	if [ -z "$OCF_RESKEY_path" ]; then
+		ocf_log err "No export path specified."
+		return $OCF_ERR_ARGS
+	fi
+
+	[ -d "$OCF_RESKEY_path" ] && return 0
+
+	ocf_log err "$OCF_RESKEY_path is not a directory"
+	
+	return $OCF_ERR_ARGS
+}
+
+
+verify_all()
+{
+	declare -i ret=0
+
+	verify_device || ret=$OCF_ERR_ARGS
+	verify_path || ret=$OCF_ERR_ARGS
+
+	return $ret
+}
+
+
+#
+# Check if the NFS daemons are running.
+#
+nfs_daemons_running()
+{
+    declare NFS_DAEMONS="nfsd rpc.mountd rpc.statd"
+
+    for daemon in $NFS_DAEMONS; do
+        ps -ef | grep "$daemon" | grep -v grep >/dev/null 2>&1
+        if [ $? -ne 0 ]; then
+	    ocf_log err \
+            "NFS daemon $daemon is not running."
+	    ocf_log err \
+            "Verify that the NFS service run level script is enabled."
+            return 1
+        fi
+    done
+
+    return 0
+}
+
+
+nfs_check()
+{
+	declare junk
+
+	if nfs_daemons_running; then
+		return 0
+	fi
+
+	#
+	# Don't restart daemons during status check.
+	#
+	if [ "$1" = "status" ]; then
+		return 1;
+	fi
+		
+  	ocf_log err "Restarting NFS daemons"
+	# Note restart does less than stop/start
+	junk=$(/sbin/service nfslock stop)
+	junk=$(/sbin/service nfslock start)
+	junk=$(/sbin/service nfs stop)
+	junk=$(/sbin/service nfs start)
+	sleep 2
+	
+	if ! nfs_daemons_running; then
+		ocf_log err "Failed restarting NFS daemons"
+    		return 1
+	fi
+	ocf_log notice "Successfully restarted NFS daemons"
+}
+
+
+case $1 in
+start)
+	nfs_check start || exit 1
+	rv=0
+	;;
+
+status|monitor)
+	nfs_check status || exit 1
+	rv=0
+	;;
+		    
+stop)
+	nfs_check restart || exit 1
+	rv=0
+	;;
+
+recover|restart)
+	$0 stop || exit $OCF_ERR_GENERIC
+	$0 start || exit $OCF_ERR_GENERIC
+	rv=0
+	;;
+
+meta-data)
+	meta_data
+	rv=0
+	;;
+
+validate-all)
+	verify_all
+	rv=$?
+	;;
+*)
+	echo "usage: $0 {start|status|monitor|stop|recover|restart|meta-data|validate-all}"
+	exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+
+exit $rv
diff --git a/rgmanager/src/resources/nfsserver.sh b/rgmanager/src/resources/nfsserver.sh
new file mode 100755
index 0000000..e2161dc
--- /dev/null
+++ b/rgmanager/src/resources/nfsserver.sh
@@ -0,0 +1,500 @@
+#!/bin/bash
+
+#
+# NFS Server Script.  Handles starting/stopping Servand doing
+# the strange NFS stuff to get it to fail over properly.
+#
+
+LC_ALL=C
+LANG=C
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+V4RECOVERY="/var/lib/nfs/v4recovery"
+PROC_V4RECOVERY="/proc/fs/nfsd/nfsv4recoverydir"
+
+export LC_ALL LANG PATH
+
+. $(dirname $0)/ocf-shellfuncs
+
+# SELinux information
+which restorecon &> /dev/null && selinuxenabled
+export SELINUX_ENABLED=$?
+if [ $SELINUX_ENABLED ]; then
+	export SELINUX_LABEL="$(ls -ldZ /var/lib/nfs/statd | cut -f4 -d' ')"
+fi
+
+
+log_do()
+{
+	ocf_log debug $*
+	$* &> /dev/null
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		ocf_log debug "Failed: $*"
+	fi
+	return $ret
+}
+
+
+meta_data()
+{
+	cat <<EOT
+<?xml version="1.0" ?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent name="nfsserver" version="rgmanager 2.0">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines an NFS server resource.  The NFS server
+	resource is useful for exporting NFSv4 file systems
+	to clients.  Because of the way NFSv4 works, only
+	one NFSv4 resource may exist on a server at a
+	time.  Additionally, it is not possible to use
+	the nfsserver resource when also using local instances
+	of NFS on each cluster node.
+    </longdesc>
+
+    <shortdesc lang="en">
+        This defines an NFS server resource.
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+            <longdesc lang="en">
+                Descriptive name for this server.  Generally, only
+                one server is ever defined per service.
+            </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="path" inherit="mountpoint">
+            <longdesc lang="en">
+	        This is the path you intend to export.  Usually, this is
+		left blank, and the mountpoint of the parent file system
+		is used.  This path is passed to nfsclient resources as
+		the export path when exportfs is called.
+            </longdesc>
+            <shortdesc lang="en">
+	    	This is the path you intend to export.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="nfspath">
+            <longdesc lang="en">
+	        This is the path containing shared NFS information which
+		is used for NFS recovery after a failover.  This
+		is relative to the export path, and defaults to
+		".clumanager/nfs".
+            </longdesc>
+            <shortdesc lang="en">
+	        This is the path containing shared NFS recovery
+		information, relative to the path parameter.
+            </shortdesc>
+	    <content type="string" default=".clumanager/nfs"/>
+        </parameter>
+
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="5"/>
+	<action name="stop" timeout="5"/>
+	<action name="recover" timeout="5"/>
+
+	<action name="status" timeout="5" interval="30"/>
+	<action name="monitor" timeout="5" interval="30"/>
+
+	<action name="meta-data" timeout="5"/>
+	<action name="validate-all" timeout="30"/>
+    </actions>
+
+    <special tag="rgmanager">
+    	<attributes maxinstances="1"/>
+	<child type="nfsexport" forbid="1"/>
+	<child type="nfsserver" forbid="1"/>
+	<child type="nfsclient" start="1" stop="2"/>
+	<child type="ip" start="2" stop="1"/>
+    </special>
+
+</resource-agent>
+EOT
+}
+
+
+verify_path()
+{
+	if [ -z "$OCF_RESKEY_path" ]; then
+		ocf_log err "No server path specified."
+		return $OCF_ERR_ARGS
+	fi
+
+	[ -d "$OCF_RESKEY_path" ] && return 0
+
+	ocf_log err "$OCF_RESKEY_path is not a directory"
+	
+	return $OCF_ERR_ARGS
+}
+
+
+verify_nfspath()
+{
+	if [ -z "$OCF_RESKEY_nfspath" ]; then
+		echo No NFS data path specified.
+		return 1
+	fi
+
+	[ -d "$OCF_RESKEY_path" ] && return 0
+	
+	# xxx do nothing for now.
+	return 0
+}
+
+
+verify_all()
+{
+	verify_path || return 1
+	verify_nfspath || return 1
+
+	return 0
+}
+
+
+nfs_daemons()
+{
+	declare oper
+	declare val
+
+	case $1 in
+	start)
+		ocf_log info "Starting NFS daemons"
+		/etc/init.d/nfs start
+		if [ $? -ne 0 ]; then
+			ocf_log err "Failed to start NFS daemons"
+			return 1
+		fi
+
+		ocf_log debug "NFS daemons are running"
+		return 0
+		;;
+	stop)
+		ocf_log info "Stopping NFS daemons"
+		if ! /etc/init.d/nfs stop; then
+			ocf_log err "Failed to stop NFS daemons"
+			return 1
+		fi
+
+		ocf_log debug "NFS daemons are stopped"
+
+		return 0
+		;;
+	status|monitor)
+		declare recoverydir="$OCF_RESKEY_path/$OCF_RESKEY_nfspath/v4recovery"
+		val=$(cat $PROC_V4RECOVERY)
+
+		[ "$val" = "$recoverydir" ] || ocf_log warning \
+			"NFSv4 recovery directory is $val instead of $recoverydir"
+		/etc/init.d/nfs status
+		if [ $? -eq 0 ]; then
+			ocf_log debug "NFS daemons are running"
+			return 0
+		fi
+		return $OCF_NOT_RUNNING
+		;;
+	esac
+}
+
+
+create_tree()
+{
+	declare fp="$OCF_RESKEY_path/$OCF_RESKEY_nfspath"
+
+	[ -d "$fp" ] || mkdir -p "$fp"
+
+	[ -d "$fp/statd" ] || mkdir -p "$fp/statd"
+	[ -d "$fp/v4recovery" ] || mkdir -p "$fp/v4recovery"
+
+	#
+	# Create our own private copy which we use for notifies.
+	# This way, we can be sure to advertise on possibly multiple
+	# IP addresses.
+	#
+	[ -d "$fp/statd/sm" ] || mkdir -p "$fp/statd/sm"
+	[ -d "$fp/statd/sm.bak" ] || mkdir -p "$fp/statd/sm.bak"
+	[ -d "$fp/statd/sm-ha" ] || mkdir -p "$fp/statd/sm-ha"
+	[ -n "`id -u rpcuser`" -a "`id -g rpcuser`" ] && chown -R rpcuser.rpcuser "$fp/statd"
+
+	# Create if they don't exist
+	[ -f "$fp/etab" ] || touch "$fp/etab"
+	[ -f "$fp/xtab" ] || touch "$fp/xtab"
+	[ -f "$fp/rmtab" ] || touch "$fp/rmtab"
+
+	[ $SELINUX_ENABLED ] && chcon -R "$SELINUX_LABEL" "$fp"
+
+        #
+        # Generate a random state file.  If this ends up being what a client
+        # already has in its list, that's bad, but the chances of this
+        # are small - and relocations should be rare.
+        #
+        dd if=/dev/urandom of=$fp/state bs=1 count=4 &> /dev/null
+	[ -n "`id -u rpcuser`" -a "`id -g rpcuser`" ] && chown rpcuser.rpcuser "$fp/state"
+}
+
+setup_v4recovery()
+{
+	declare recoverydir="$OCF_RESKEY_path/$OCF_RESKEY_nfspath/v4recovery"
+
+	# mounts /proc/fs/nfsd for us
+	lsmod | grep -q nfsd
+	if [ $? -ne 0 ]; then
+		modprobe nfsd
+	fi
+
+	val=$(cat "$PROC_V4RECOVERY")
+
+	# Ensure start-after-start works
+	if [ "$val" = "$recoverydir" ]; then
+		return 0
+	fi
+
+	#
+	# If the value is not default, there may be another
+	# cluster service here already which has replaced
+	# the v4 recovery directory.  In that case,
+	# we must refuse to go any further.
+	#
+	if [ "$val" != "$V4RECOVERY" ]; then
+		ocf_log err "NFSv4 recovery directory has an unexpected value: $val"
+		return 1
+	fi
+
+	#
+	# Redirect nfs v4 recovery dir to shared storage
+	#
+	echo "$recoverydir" > "$PROC_V4RECOVERY"
+	if [ $? -ne 0 ]; then
+		echo "Uh oh... echo failed!?"
+	fi
+
+	val="$(cat $PROC_V4RECOVERY)"
+	if [ "$val" != "$recoverydir" ]; then
+		ocf_log err "Failed to change NFSv4 recovery path"
+		ocf_log err "Wanted: $recoverydir; got $val"
+		return 1
+	fi
+
+	return 0
+}
+
+
+cleanup_v4recovery()
+{
+	#
+	# Restore nfsv4 recovery directory to default
+	#
+	echo "$V4RECOVERY" > "$PROC_V4RECOVERY"
+	return $?
+}
+
+
+is_bound()
+{
+	mount | grep -q "$1 on $2 type none (.*bind.*)"
+	return $?
+}
+
+
+setup_tree()
+{
+	declare fp="$OCF_RESKEY_path/$OCF_RESKEY_nfspath"
+
+	if is_bound $fp/statd /var/lib/nfs/statd; then
+		ocf_log debug "$fp is already bound to /var/lib/nfs/statd"
+		return 0
+	fi
+
+	mount -o bind "$fp/statd" /var/lib/nfs/statd
+	cp -a "$fp"/*tab /var/lib/nfs
+	[ $SELINUX_ENABLED ] && restorecon /var/lib/nfs
+}
+
+
+cleanup_tree()
+{
+	declare fp="$OCF_RESKEY_path/$OCF_RESKEY_nfspath"
+
+	if is_bound "$fp/statd" /var/lib/nfs/statd; then
+		log_do umount /var/lib/nfs/statd || return 1
+	else
+		ocf_log debug "$fp is not bound to /var/lib/nfs/statd"
+	fi
+
+	cp -a /var/lib/nfs/*tab "$fp"
+
+	return 0
+}
+
+start_locking()
+{
+	declare ret
+	[ -x /sbin/rpc.statd ] || return 1
+	
+	#
+	# Synchronize these before starting statd
+	#
+	cp -f /var/lib/nfs/statd/sm-ha/* /var/lib/nfs/statd/sm 2> /dev/null
+	cp -f /var/lib/nfs/statd/sm/* /var/lib/nfs/statd/sm-ha 2> /dev/null
+
+	if pidof rpc.statd &> /dev/null; then
+		ocf_log debug "rpc.statd is already running"
+		return 0
+	fi
+
+	#
+	# Set this resrouce script as the callout program.  We are evil.
+	# In cases where we want to preserve lock information, this is needed
+	# because we can't do the "copy" that we do on the down-state...
+	#
+	ocf_log info "Starting rpc.statd"
+	rm -f /var/run/sm-notify.pid
+	rpc.statd -H $0 -d
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		ocf_log err "Failed to start rpc.statd"
+		return $ret
+	fi
+	touch /var/lock/subsys/nfslock
+	return $ret
+}
+
+
+terminate()
+{
+	declare pids
+	declare i=0
+
+	while : ; do
+		pids=$(pidof $1)
+		[ -z "$pids" ] && return 0
+	 	kill $pids
+		sleep 1
+		((i++))
+		[ $i -gt 3 ] && return 1
+	done
+}
+
+
+killkill()
+{
+	declare pids
+	declare i=0
+
+	while : ; do
+		pids=$(pidof $1)
+		[ -z "$pids" ] && return 0
+	 	kill -9 $pids
+		sleep 1
+		((i++))
+		[ $i -gt 3 ] && return 1
+	done
+}
+
+
+stop_locking()
+{
+	declare ret 
+
+	ocf_log info "Stopping rpc.statd"
+	if terminate rpc.statd; then
+		ocf_log debug "rpc.statd is stopped"
+	else
+		if killkill rpc.statd; then
+			ocf_log debug "rpc.statd is stopped"
+		else
+			ocf_log debug "Failed to stop rpc.statd"
+			return 1
+		fi
+	fi
+}
+
+
+case $1 in
+start)
+	# Check for and source configuration file
+	ocf_log info "Starting NFS Server $OCF_RESKEY_name"
+	create_tree || exit 1
+	setup_tree || exit 1
+	setup_v4recovery || exit 1
+
+	start_locking
+	nfs_daemons start
+	rv=$?
+	if [ $rv -eq 0 ]; then
+		ocf_log info "Started NFS Server $OCF_RESKEY_name"
+		exit 0
+	fi
+
+	ocf_log err "Failed to start NFS Server $OCF_RESKEY_name"
+	exit $rv
+	;;
+
+status|monitor)
+	nfs_daemons status 
+	exit $?
+	;;
+		    
+stop)
+	if ! nfs_daemons stop; then
+		ocf_log err "Failed to stop NFS Server $OCF_RESKEY_name"
+		exit $OCF_ERR_GENERIC
+	fi
+
+	# Copy the current notify list into our private area
+	ocf_log debug "Copying sm files for future notification..."
+	rm -f /var/lib/nfs/statd/sm-ha/* &> /dev/null
+	cp -f /var/lib/nfs/statd/sm/* /var/lib/nfs/statd/sm-ha &> /dev/null
+
+	stop_locking || exit 1
+	cleanup_v4recovery
+	cleanup_tree || exit 1
+	exit 0
+	;;
+
+add-client)
+	ocf_log debug "$0 $1 $2 $3"
+	touch /var/lib/nfs/statd/sm/$2
+	touch /var/lib/nfs/statd/sm-ha/$2
+	exit 0
+	;;
+
+del-client)
+	ocf_log debug "$0 $1 $2 $3"
+	touch /var/lib/nfs/statd/sm/$2
+	rm -f /var/lib/nfs/statd/sm-ha/$2
+	exit 0
+	;;
+
+recover|restart)
+	$0 stop || exit $OCF_ERR_GENERIC
+	$0 start || exit $OCF_ERR_GENERIC
+	exit 0
+	;;
+
+meta-data)
+	meta_data
+	exit 0
+	;;
+
+validate-all)
+	verify_all
+	exit $?
+	;;
+*)
+	echo "usage: $0 {start|stop|status|monitor|restart|recover|add-client|del-client|meta-data|validate-all}"
+	exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+
+exit 0
diff --git a/rgmanager/src/resources/ocf-shellfuncs b/rgmanager/src/resources/ocf-shellfuncs
new file mode 100644
index 0000000..97097f7
--- /dev/null
+++ b/rgmanager/src/resources/ocf-shellfuncs
@@ -0,0 +1,167 @@
+#! /bin/bash
+#
+# 	$Id$
+#
+# 	Common helper functions for the OCF Resource Agents supplied by
+# 	heartbeat.
+#
+# Copyright (C) 2004 SUSE LINUX AG, Lars Marowsky-Bree. All Rights Reserved.
+#
+
+# TODO: Some of this should probably split out into a generic OCF
+# library for shell scripts, but for the time being, we'll just use it
+# ourselves...
+#
+
+# TODO wish-list:
+# - Generic function for evaluating version numbers
+# - Generic function(s) to extract stuff from our own meta-data
+# - Logging function which automatically adds resource identifier etc
+#   prefixes
+# TODO: Move more common functionality for OCF RAs here.
+#
+__SCRIPT_NAME=`basename $0`
+
+# lhh - determine if we're a dumb terminal
+consoletype &> /dev/null
+if [ $? -eq 1 ]; then
+	__SERIAL="yes"
+fi
+
+__LOG_PID=$PPID
+__LOG_NAME=$(basename $(readlink /proc/$PPID/exe))
+
+pretty_echo() {
+	declare pretty
+	declare n=""
+        declare __OCF_PRIO="$1"
+        shift
+        declare __OCF_MSG="$*"
+
+	if [ -n "$__SERIAL" ]; then
+		echo "<$__OCF_PRIO> $__OCF_MSG"
+		return 0
+	fi
+
+	case $__OCF_PRIO in
+	emerg)		pretty="";;
+	alert)		pretty="";;
+        crit|critical)	pretty="";;
+        err|error)	pretty="";;
+        warn|warning)	pretty="";;
+	note|notice)	pretty="";;
+        info)		pretty="";;
+        debug|dbg)	pretty="";;
+        *)		pretty="";;
+	esac
+
+	echo "$n<$pretty$__OCF_PRIO$n> $__OCF_MSG"
+	return 0
+}
+
+__ocf_set_defaults() {
+	__OCF_ACTION="$1"
+
+	# Return to sanity for the agents...
+	unset LANG
+	LC_ALL=C
+	export LC_ALL
+
+	# TODO: Review whether we really should source this. Or rewrite
+	# to match some emerging helper function syntax...? This imports
+	# things which no OCF RA should be using...
+
+	OCF_SUCCESS=0
+	OCF_ERR_GENERIC=1
+	OCF_ERR_ARGS=2
+	OCF_ERR_UNIMPLEMENTED=3
+	OCF_ERR_PERM=4
+	OCF_ERR_INSTALLED=5
+	OCF_ERR_CONFIGURED=6
+	OCF_NOT_RUNNING=7
+
+	if [ -z "$OCF_RESOURCE_TYPE" ]; then
+		: ${OCF_RESOURCE_TYPE:=$__SCRIPT_NAME}
+	fi
+
+	if [ -z "$OCF_RA_VERSION_MAJOR" ]; then
+		: We are being invoked as an init script.
+		: Fill in some things with reasonable values.
+		: ${OCF_RESOURCE_INSTANCE:="default"}
+		return 0
+        fi
+
+	if [ -z "$OCF_ROOT" ]; then
+		OCF_ROOT=$(dirname $0)
+	fi
+	if [ ! -d "$OCF_ROOT" ]; then
+		ocf_log err "OCF_ROOT points to non-directory $OCF_ROOT."
+		exit $OCF_ERR_GENERIC
+	fi
+
+	# TODO: Anything else we should be setting and thus checking?
+        # There is nothing in this script which depends on the version
+	# of the API.  TESTING THIS HERE IS A BUG.  THIS SHOULD BE
+	# tested by the script that's invoked us.  FIXME!!
+	if [ "x$OCF_RA_VERSION_MAJOR" != "x1" ]; then
+		ocf_log err "This script is OCF RA API 1.x compliant only!"
+		exit $OCF_ERR_UNIMPLEMENTED
+	fi
+	# TODO: Should the minor level really be a number and not rather
+	# a list of flags...?
+        # AlanR says -- absolutely not -- a list of flags is good for a list
+	# of implemented features, not a version compiliance
+	# perhaps some future version might have such a list of
+	# flags, but that would be _in addition to_ the minor version number
+	if [ -z "$OCF_RA_VERSION_MINOR" ]; then
+		ocf_log err "No OCF RA minor version set."
+		exit $OCF_ERR_UNIMPLEMENTED
+	fi
+
+	if [ "x$__OCF_ACTION" = "xmeta-data" ]; then
+		OCF_RESOURCE_INSTANCE="undef"
+	fi	
+
+	if [ -z "$OCF_RESOURCE_INSTANCE" ]; then
+		ocf_log err "Need to tell us our resource instance name."
+		exit $OCF_ERR_ARGS
+	fi
+}
+
+
+ocf_log() {
+	# TODO: Revisit and implement internally.
+	if
+          [ $# -lt 2 ]
+        then
+          ocf_log err "Not enough arguments [$#] to ocf_log."
+        fi
+
+        declare __OCF_PRIO="$1"
+	declare -i __OCF_PRIO_N
+
+        shift
+
+        declare __OCF_MSG="$*"
+
+        case "${__OCF_PRIO}" in
+	emerg)		__OCF_PRIO_N=0;; # Not in original ocf-shellfuncs
+	alert)		__OCF_PRIO_N=1;; # Not in original ocf-shellfuncs
+        crit|critical)	__OCF_PRIO_N=2;;
+        err|error)	__OCF_PRIO_N=3;;
+        warn|warning)	__OCF_PRIO_N=4;;
+	note|notice)	__OCF_PRIO_N=5;; # Not in original ocf-shellfuncs
+        info)		__OCF_PRIO_N=6;;
+        debug|dbg)	__OCF_PRIO_N=7;;
+        *)		__OCF_PRIO_N=5;; # Defaults to INFO
+	esac
+
+	pretty_echo $__OCF_PRIO "$__OCF_MSG"
+
+	if [ -z "`which clulog 2> /dev/null`" ]; then
+		return 0
+	fi
+	clulog -m "$OCF_RESOURCE_TYPE" -s $__OCF_PRIO_N "$__OCF_MSG"
+}
+
+__ocf_set_defaults "$@"
diff --git a/rgmanager/src/resources/openldap.metadata b/rgmanager/src/resources/openldap.metadata
new file mode 100644
index 0000000..9bd7193
--- /dev/null
+++ b/rgmanager/src/resources/openldap.metadata
@@ -0,0 +1,98 @@
+<?xml version="1.0"?>
+<resource-agent version="rgmanager 2.0" name="openldap">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines an instance of Open LDAP 
+    </longdesc>
+    <shortdesc lang="en">
+        Defines an Open LDAP server
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+	        Specifies a service name for logging and other purposes
+	    </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="config_file">
+            <longdesc lang="en">
+                Define absolute path to configuration file
+            </longdesc>
+            <shortdesc lang="en">
+                Config File
+            </shortdesc>
+	    <content type="string" default="/etc/openldap/slapd.conf"/>
+        </parameter>
+
+        <parameter name="url_list">
+            <longdesc lang="en">
+               Serve URL list. Default behaviour of URL list is changed and 
+		enhanced. eg. ldap:/// won't bind all IP address on the
+		computer but to all IP addresses in service. Using
+		ldap://0:port/ will bind to all IP addresses for service on
+		given port.
+            </longdesc>
+            <shortdesc lang="en">
+                URL list
+            </shortdesc>
+	    <content type="string" default="ldap:///"/>
+        </parameter>
+
+	<parameter name="slapd_options">
+		<longdesc lang="en">
+			Other command-line options for slapd
+		</longdesc>
+		<shortdesc lang="en">
+			Other command-line options for slapd
+		</shortdesc>
+		<content type="string" />
+	</parameter>
+
+	<parameter name="shutdown_wait">
+		<longdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</longdesc>
+		<shortdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</shortdesc>
+		<content type="integer" />
+	</parameter>
+
+        <parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+	    	Inherit the service name.  We need to know
+		the service name in order to determine file
+		systems and IPs for this service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Inherit the service name.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="0"/>
+	<action name="stop" timeout="0"/>
+
+	<!-- Checks to see if it''s mounted in the right place -->
+	<action name="status" interval="1m" timeout="10"/>
+	<action name="monitor" interval="1m" timeout="10"/>
+
+	<!-- Checks to see if we can read from the mountpoint -->
+	<action name="status" depth="10" timeout="30" interval="5m"/>
+	<action name="monitor" depth="10" timeout="30" interval="5m"/>
+
+	<action name="meta-data" timeout="0"/>
+	<action name="validate-all" timeout="0"/>
+    </actions>
+
+    <special tag="rgmanager">
+    </special>
+</resource-agent>
diff --git a/rgmanager/src/resources/openldap.sh b/rgmanager/src/resources/openldap.sh
new file mode 100755
index 0000000..0df81d2
--- /dev/null
+++ b/rgmanager/src/resources/openldap.sh
@@ -0,0 +1,227 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+export LC_ALL=C
+export LANG=C
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+declare LDAP_SLAPD=/usr/sbin/slapd
+declare LDAP_pid_file="`generate_name_for_pid_file`"
+declare LDAP_conf_dir="`generate_name_for_conf_dir`"
+declare LDAP_gen_config_file="$LDAP_conf_dir/slapd.conf"
+declare LDAP_url_list
+
+verify_all()
+{
+	clog_service_verify $CLOG_INIT
+
+	if [ -z "$OCF_RESKEY_name" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid Name Of Service"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_service_name" ]; then
+		clog_service_verify $CLOG_FAILED_NOT_CHILD
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_INVALID "$OCF_RESKEY_config_file"
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ ! -r "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_NOT_READABLE $OCF_RESKEY_config_file
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	clog_service_verify $CLOG_SUCCEED
+		
+	return 0
+}
+
+generate_url_list()
+{
+	declare ldap_url_source=$1
+	declare ip_addresses=$2
+	declare url_list
+	declare tmp;
+	
+	for u in $ldap_url_source; do 
+		if [[ "$u" =~ ':///' ]]; then
+			for z in $ip_addresses; do
+				tmp=`echo $u | sed "s,://,://$z,"`
+				url_list="$url_list $tmp"
+			done
+		elif [[ "$u" =~ '://0:' ]]; then
+			for z in $ip_addresses; do
+				tmp=`echo $u | sed "s,://0:,://$z:,"`
+				url_list="$url_list $tmp"
+			done
+		else
+			url_list="$url_list $u"
+		fi
+	done
+	
+	echo $url_list
+}
+
+generate_config_file()
+{
+	declare original_file="$1"
+	declare generated_file="$2"
+
+	if [ -f "$generated_file" ]; then
+		sha1_verify "$generated_file"
+		if [ $? -ne 0 ]; then
+			clog_check_sha1 $CLOG_FAILED
+			return 0
+		fi
+	fi	
+
+	clog_generate_config $CLOG_INIT "$original_file" "$generated_file"
+
+	generate_configTemplate "$generated_file" "$1"
+	echo "pidfile \"$LDAP_pid_file\"" >> $generated_file
+	echo >> $generated_file	
+	sed 's/^[[:space:]]*pidfile/### pidfile/i' < "$original_file" >> "$generated_file"
+	
+        sha1_addToFile "$generated_file"
+	clog_generate_config $CLOG_SUCCEED "$original_file" "$generated_file"
+               
+	return 0;
+}
+
+start()
+{
+	clog_service_start $CLOG_INIT
+
+	create_pid_directory
+	create_conf_directory "$LDAP_conf_dir"
+	check_pid_file "$LDAP_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_check_pid $CLOG_FAILED "$LDAP_pid_file"
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	clog_looking_for $CLOG_INIT "IP Addresses"
+
+        get_service_ip_keys "$OCF_RESKEY_service_name"
+        ip_addresses=`build_ip_list`
+
+	if [ -z "$ip_addresses" ]; then
+		clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Addresses"
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_looking_for $CLOG_SUCCEED "IP Addresses"
+
+	LDAP_url_list=`generate_url_list "$OCF_RESKEY_url_list" "$ip_addresses"`
+
+	if [ -z "$LDAP_url_list" ]; then
+		ocf_log error "Generating URL List for $OCF_RESOURCE_INSTANCE > Failed"
+		return $OCF_ERR_GENERIC
+	fi
+
+	generate_config_file "$OCF_RESKEY_config_file" "$LDAP_gen_config_file"
+
+	$LDAP_SLAPD -f "$LDAP_gen_config_file" -n "$OCF_RESOURCE_INSTANCE" \
+		-h "$LDAP_url_list" $OCF_RESKEY_slapd_options
+
+	if [ $? -ne 0 ]; then
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_start $CLOG_SUCCEED
+
+	return 0;
+}
+
+stop()
+{
+	clog_service_stop $CLOG_INIT
+
+	stop_generic "$LDAP_pid_file" "$OCF_RESKEY_shutdown_wait"
+	
+	if [ $? -ne 0 ]; then
+		clog_service_stop $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_service_stop $CLOG_SUCCEED
+	return 0;
+}
+
+status()
+{
+	clog_service_status $CLOG_INIT
+
+	status_check_pid "$LDAP_pid_file"
+	if [ $? -ne 0 ]; then
+		clog_service_status $CLOG_FAILED "$LDAP_pid_file"
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_status $CLOG_SUCCEED
+	return 0
+}
+
+case $1 in
+	meta-data)
+		cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+		exit 0
+		;;
+	validate-all)
+		verify_all
+		exit $?
+		;;
+	start)
+		verify_all && start
+		exit $?
+		;;
+	stop)
+		verify_all && stop
+		exit $?
+		;;
+	status|monitor)
+		verify_all
+		status
+		exit $?
+		;;
+	restart)
+		verify_all
+		stop
+		start
+		exit $?
+		;;
+	*)
+		echo "Usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
diff --git a/rgmanager/src/resources/oracledb.sh b/rgmanager/src/resources/oracledb.sh
new file mode 100644
index 0000000..3ccc47a
--- /dev/null
+++ b/rgmanager/src/resources/oracledb.sh
@@ -0,0 +1,1030 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2013 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+# Author(s):
+#     Hardy Merrill <hmerrill at redhat.com>
+#     Lon Hohberger <lhh at redhat.com>
+#     Michael Moon <Michael dot Moon at oracle.com>
+#     Ryan McCabe <rmccabe at redhat.com>
+#
+# NOTES:
+#
+# (1) You can comment out the LOCKFILE declaration below.  This will prevent
+# the need for this script to access anything outside of the ORACLE_HOME 
+# path.
+#
+# (2) You MUST customize ORACLE_USER, ORACLE_HOME, ORACLE_SID, and
+# ORACLE_HOSTNAME to match your installation if not running from within
+# rgmanager.
+#
+# (3) Do NOT place this script in shared storage; place it in ORACLE_USER's
+# home directory in non-clustered environments and /usr/share/cluster
+# in rgmanager/Red Hat cluster environments.
+#
+# Oracle is a registered trademark of Oracle Corporation.
+# Oracle9i is a trademark of Oracle Corporation.
+# Oracle10g is a trademark of Oracle Corporation.
+# Oracle11g is a trademark of Oracle Corporation.
+# All other trademarks are property of their respective owners.
+#
+
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+. /etc/init.d/functions
+
+declare SCRIPT="`basename $0`"
+declare SCRIPTDIR="`dirname $0`"
+
+[ -n "$OCF_RESKEY_user" ] && ORACLE_USER=$OCF_RESKEY_user
+[ -n "$OCF_RESKEY_home" ] && ORACLE_HOME=$OCF_RESKEY_home
+[ -n "$OCF_RESKEY_name" ] && ORACLE_SID=$OCF_RESKEY_name
+[ -n "$OCF_RESKEY_listener_name" ] && ORACLE_LISTENER=$OCF_RESKEY_listener_name
+[ -n "$OCF_RESKEY_lockfile" ] && LOCKFILE=$OCF_RESKEY_lockfile
+[ -n "$OCF_RESKEY_type" ] && ORACLE_TYPE=$OCF_RESKEY_type
+[ -n "$OCF_RESKEY_vhost" ] && ORACLE_HOSTNAME=$OCF_RESKEY_vhost
+[ -n "$OCF_RESKEY_tns_admin" ] && export TNS_ADMIN=$OCF_RESKEY_tns_admin
+
+######################################################
+# Customize these to match your Oracle installation. #
+######################################################
+#
+# 1. Oracle user.  Must be the same across all cluster members.  In the event
+#    that this script is run by the super-user, it will automatically switch
+#    to the Oracle user and restart.  Oracle needs to run as the Oracle
+#    user, not as root.
+#
+#[ -n "$ORACLE_USER" ] || ORACLE_USER=oracle
+
+#
+# 2. Oracle home.  This is set up during the installation phase of Oracle.
+#    From the perspective of the cluster, this is generally the mount point
+#    you intend to use as the mount point for your Oracle Infrastructure
+#    service.
+#
+#[ -n "$ORACLE_HOME" ] || ORACLE_HOME=/mnt/oracle/home
+
+#
+# 3. This is your SID.  This is set up during oracle installation as well.
+#
+#[ -n "$ORACLE_SID" ] || ORACLE_SID=orcl
+
+#
+# 4. The oracle user probably doesn't have the permission to write to 
+# /var/lock/subsys, so use the user's home directory.
+#
+#[ -n "$LOCKFILE" ] || LOCKFILE="/home/$ORACLE_USER/.oracle-ias.lock"
+[ -n "$LOCKFILE" ] || LOCKFILE="$ORACLE_HOME/.oracle-ias.lock"
+#[ -n "$LOCKFILE" ] || LOCKFILE="/var/lock/subsys/oracle-ias" # Watch privileges
+
+#
+# 5. Type of Oracle Database.  Currently supported: 10g 10g-iAS(untested!)
+#
+[ -n "$ORACLE_TYPE" ] || ORACLE_TYPE="base-em"
+
+#
+# 6. Oracle virtual hostname.  This is the hostname you gave Oracle during
+#    installation.
+#
+#[ -n "$ORACLE_HOSTNAME" ] || ORACLE_HOSTNAME=svc0.foo.test.com
+
+
+
+###########################################################################
+ORACLE_TYPE=`echo $ORACLE_TYPE | tr A-Z a-z`
+export ORACLE_USER ORACLE_HOME ORACLE_SID LOCKFILE ORACLE_TYPE
+export ORACLE_HOSTNAME
+
+
+##########################
+# Set up paths we'll use.  Not all are used by all the different types of
+# Oracle installations
+#
+export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$ORACLE_HOME/opmn/lib
+export PATH=$ORACLE_HOME/bin:$ORACLE_HOME/opmn/bin:$ORACLE_HOME/dcm/bin:$PATH
+
+declare -i	RESTART_RETRIES=0
+declare -r	DB_PROCNAMES="pmon"
+#declare -r	DB_PROCNAMES="pmonXX" # testing
+#declare -r	DB_PROCNAMES="pmon smon dbw0 lgwr"
+
+declare -r	LSNR_PROCNAME="tnslsnr"
+#declare -r	LSNR_PROCNAME="tnslsnrXX" # testing
+
+# clulog will not log messages when run by the oracle user.
+# This is a hack to work around that.
+if [ "`id -u`" = "`id -u $ORACLE_USER`" ]; then
+	ocf_log() {
+		prio=$1
+		shift
+		logger -i -p daemon."$prio" -- "$*"
+	}
+fi
+
+##########################################################
+# (Hopefully) No user-serviceable parts below this line. #
+##########################################################
+meta_data()
+{
+	cat <<EOT
+<?xml version="1.0" ?>
+<resource-agent name="oracledb" version="rgmanager 2.0">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+	Oracle 10g/11g Failover Instance
+    </longdesc>
+    <shortdesc lang="en">
+	Oracle 10g/11g Failover Instance
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+		Instance name (SID) of oracle instance
+	    </longdesc>
+            <shortdesc lang="en">
+		Oracle SID
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="listener_name" unique="1">
+	    <longdesc lang="en">
+		Oracle Listener Instance Name.  If you have multiple 
+		instances of Oracle running, it may be necessary to 
+		have multiple listeners on the same machine with
+		different names.
+	    </longdesc>
+            <shortdesc lang="en">
+		Oracle Listener Instance Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="user" required="1">
+	    <longdesc lang="en">
+		Oracle user name.  This is the user name of the Oracle
+		user which the Oracle AS instance runs as.
+	    </longdesc>
+            <shortdesc lang="en">
+		Oracle User Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="home" required="1">
+	    <longdesc lang="en">
+		This is the Oracle (application, not user) home directory.
+		This is configured when you install Oracle.
+	    </longdesc>
+            <shortdesc lang="en">
+		Oracle Home Directory
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="type" required="0">
+	    <longdesc lang="en">
+		This is the Oracle installation type:
+		base - Database Instance and Listener only
+		base-11g - Oracle11g Database Instance and Listener Only
+		base-em (or 10g) - Database, Listener, Enterprise Manager,
+				   and iSQL*Plus
+		base-em-11g - Database, Listener, Enterprise Manager dbconsole
+		ias (or 10g-ias) - Internet Application Server (Infrastructure)
+	    </longdesc>
+            <shortdesc lang="en">
+		Oracle Installation Type
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="vhost" required="0" unique="1">
+	    <longdesc lang="en">
+	        Virtual Hostname matching the installation hostname of
+		Oracle 10g.  Note that during the start/stop of an oracledb
+		resource, your hostname will temporarily be changed to
+		this hostname.  As such, it is recommended that oracledb
+		resources be instanced as part of an exclusive service only.
+	    </longdesc>
+            <shortdesc lang="en">
+		Virtual Hostname
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="tns_admin" required="0" unique="1">
+	    <longdesc lang="en">
+			Full path to the directory that contains the Oracle
+        listener tnsnames.ora configuration file.  The shell
+        variable TNS_ADMIN is set to the value provided.
+	    </longdesc>
+            <shortdesc lang="en">
+		Full path to the directory containing tnsnames.ora
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="900"/>
+	<action name="stop" timeout="90"/>
+        <action name="recover" timeout="990"/>
+
+	<!-- Checks to see if it's mounted in the right place -->
+	<action name="status" timeout="10"/>
+	<action name="monitor" timeout="10"/>
+
+	<action name="status" depth="10" timeout="30" interval="30"/>
+	<action name="monitor" depth="10" timeout="30" interval="30"/>
+
+	<action name="meta-data" timeout="5"/>
+	<action name="validate-all" timeout="5"/>
+    </actions>
+
+    <special tag="rgmanager">
+	<attributes maxinstances="1"/>
+    </special>
+</resource-agent>
+EOT
+}
+
+#
+# Start Oracle9i/10g/11g (database portion)
+#
+start_db()
+{
+	declare -i rv
+	declare startup_cmd
+	declare startup_stdout
+
+	ocf_log info "Starting Oracle DB $ORACLE_SID"
+
+	# Set up our sqlplus script.  Basically, we're trying to 
+	# capture output in the hopes that it's useful in the case
+	# that something doesn't work properly.
+	startup_cmd="set heading off;\nstartup;\nquit;\n"
+	startup_stdout=$(echo -e "$startup_cmd" | sqlplus -S "/ as sysdba")
+	rv=$?
+
+	# Dump output to syslog for debugging
+	ocf_log debug "[$ORACLE_SID] [$rv] sent $startup_cmd"
+	ocf_log debug "[$ORACLE_SID] [$rv] got $startup_stdout"
+
+	if [ $rv -ne 0 ]; then
+	    ocf_log error "Starting Oracle DB $ORACLE_SID failed, sqlplus returned $rv"
+	    return 1
+	fi
+
+	# If we see:
+	# ORA-.....: failure, we failed
+	# Troubleshooting:
+	#   ORA-00845 - Try rm -f /dev/shm/ora_*
+	#   ORA-01081 - Try echo -e 'shutdown abort;\nquit;'|sqlplus "/ as sysdba"
+	if [[ "$startup_stdout" =~ "ORA-" ]] || [[ "$startup_stdout" =~ "failure" ]]; then
+	    ocf_log error "Starting Oracle DB $ORACLE_SID failed, found errors in stdout"
+	    return 1
+	fi
+
+	ocf_log info "Started Oracle DB $ORACLE_SID successfully"
+	return 0
+}
+
+
+#
+# Stop Oracle (database portion)
+#
+stop_db()
+{
+	declare stop_cmd
+	declare stop_stdout
+	declare -i rv
+	declare how_shutdown="$1"
+
+	if [ -z "$1" ]; then
+		how_shutdown="immediate"
+	fi
+
+	ocf_log info "Stopping Oracle DB $ORACLE_SID $how_shutdown"
+
+	# Setup for Stop ...
+	stop_cmd="set heading off;\nshutdown $how_shutdown;\nquit;\n"
+	stop_stdout=$(echo -e "$stop_cmd" | sqlplus -S "/ as sysdba")
+	rv=$?
+
+	# Log stdout of the stop command
+	ocf_log debug "[$ORACLE_SID] sent stop command $stop_cmd"
+	ocf_log debug "[$ORACLE_SID] got $stop_stdout"
+
+	# sqlplus returned failure. We'll return failed to rhcs
+	if [ $rv -ne 0 ]; then
+	    ocf_log error "Stopping Oracle DB $ORACLE_SID failed, sqlplus returned $rv"
+	    return 1
+	fi
+
+	# If we see 'ORA-' or 'failure' in stdout, we're done.
+	if [[ "$startup_stdout" =~ "ORA-" ]] || [[ "$startup_stdout" =~ "failure" ]]; then
+	    ocf_log error "Stopping Oracle DB $ORACLE_SID failed, errors in stdout"
+	    return 1
+	fi
+
+	ocf_log info "Stopped Oracle DB $ORACLE_SID successfully"
+	return 0
+}
+
+
+#
+# Destroy any remaining processes with refs to $ORACLE_HOME
+#
+force_cleanup()
+{
+	declare pids
+	declare pid
+
+	# Patch from Shane Bradley to fix 471266
+	pids=`ps ax | grep $ORACLE_HOME | grep "ora_.*_${ORACLE_SID}" | grep -v grep | awk '{print $1}'`
+
+	ocf_log error "Not all Oracle processes for $ORACLE_SID exited cleanly, killing"
+
+	for pid in $pids; do
+		kill -9 $pid
+		rv=$?
+		if [ $rv -eq 0 ]; then
+			ocf_log info "Cleanup $ORACLE_SID Killed PID $pid"
+		else
+			ocf_log error "Cleanup $ORACLE_SID Kill PID $pid failed: $rv"
+		fi
+	done
+
+	return 0
+}
+
+
+
+#
+# Wait for oracle processes to exit.  Time out after 60 seconds
+#
+exit_idle()
+{
+	declare -i n=0
+
+	ocf_log debug "Waiting for Oracle processes for $ORACLE_SID to terminate..."
+	while ps ax | grep $ORACLE_HOME | grep "ora_.*_${ORACLE_SID}" | grep -v grep | awk '{print $1}'; do
+		if [ $n -ge 90 ]; then
+			ocf_log debug "Timed out while waiting for Oracle processes for $ORACLE_SID to terminate"
+			force_cleanup
+			return 0
+		fi
+		sleep 1
+		((n++))
+	done
+
+	ocf_log debug "All Oracle processes for $ORACLE_SID have terminated"
+	return 0
+}
+
+
+#
+# Get database background process status.  Restart it if it failed and
+# we have seen the lock file.
+#
+get_db_status()
+{
+	declare -i subsys_lock=$1
+	declare -i i=0
+	declare -i rv=0
+	declare ora_procname
+
+	for procname in $DB_PROCNAMES ; do
+
+		ora_procname="ora_${procname}_${ORACLE_SID}"
+		
+		status $ora_procname
+		if [ $? -eq 0 ] ; then
+			# This one's okay; go to the next one.
+			continue
+		fi
+
+		#
+		# We're not supposed to be running, and we are,
+		# in fact, not running...
+		# XXX only works when monitoring one db process; consider
+		# extending in future.
+		#
+		if [ $subsys_lock -ne 0 ]; then
+			return 3
+		fi
+
+		for (( i=$RESTART_RETRIES ; i; i-- )) ; do
+			# this db process is down - stop and
+			# (re)start all ora_XXXX_$ORACLE_SID processes
+			ocf_log info "Restarting Oracle Database $ORACLE_SID"
+			stop_db immediate
+			if [ $? -ne 0 ] ; then
+				# stop failed - return 1
+				ocf_log error "Error stopping Oracle Database $ORACLE_SID"
+				return 1
+			fi
+
+			start_db
+			if [ $? -eq 0 ] ; then
+				# ora_XXXX_$ORACLE_SID processes started
+				# successfully, so break out of the
+				# stop/start # 'for' loop
+				ocf_log info "Restarted Oracle Database $ORACLE_SID successfully"
+				break
+			fi
+		done
+
+		if [ $i -eq 0 ]; then
+			# stop/start's failed - return 1 (failure)
+			ocf_log error "Failed to restart Oracle Database $ORACLE_SID after $RESTART_RETRIES tries"
+			return 1
+		fi
+	done
+	return 0
+}
+
+
+#
+# Get the status of the Oracle listener process
+#
+get_lsnr_status() 
+{
+	declare -i subsys_lock=$1
+	declare -i rv
+
+	ocf_log debug "Checking status for listener $ORACLE_LISTENER"
+	lsnrctl status $ORACLE_LISTENER >& /dev/null
+	rv=$?
+	if [ $rv -eq 0 ] ; then
+		ocf_log debug "Listener $ORACLE_LISTENER is up"
+		return 0 # Listener is running fine
+	fi
+
+	# We're not supposed to be running, and we are,
+	# in fact, not running.  Return 3
+	if [ $subsys_lock -ne 0 ]; then
+		ocf_log debug "Listener $ORACLE_LISTENER is stopped as expected"
+		return 3
+	fi
+
+	# Listener is NOT running (but should be) - try to restart
+	for (( i=$RESTART_RETRIES ; i; i-- )) ; do
+		ocf_log info "Listener $ORACLE_LISTENER is down, attempting to restart"
+		lsnrctl start $ORACLE_LISTENER >& /dev/null
+		lsnrctl status $ORACLE_LISTENER >& /dev/null
+		if [ $? -eq 0 ] ; then
+			ocf_log info "Listener $ORACLE_LISTENER was restarted successfully"
+			break # Listener was (re)started and is running fine
+		fi
+	done
+
+	if [ $i -eq 0 ]; then
+		# stop/start's failed - return 1 (failure)
+		ocf_log error "Failed to restart listener $ORACLE_LISTENER after $RESTART_RETRIES tries"
+		return 1
+	fi
+
+	lsnrctl_stdout=$(lsnrctl status $ORACLE_LISTENER)
+	rv=$?
+	if [ $rv -ne 0 ] ; then
+		ocf_log error "Starting listener $ORACLE_LISTENER failed: $rv output $lsnrctl_stdout"
+		return 1 # Problem restarting the Listener
+	fi
+
+	ocf_log info "Listener $ORACLE_LISTENER started successfully"
+	return 0 # Success restarting the Listener
+}
+
+
+#
+# usage: get_opmn_proc_status <ias-component> [process-type]
+#
+# Get the status of a specific OPMN-managed process.  If process-type
+# is not specified, assume the process-type is the same as the ias-component.
+# If the lock-file exists (or no lock file is specified), try to restart
+# the given process-type if it is not running.
+#
+get_opmn_proc_status()
+{
+	declare comp=$1
+	declare opmntype=$2
+	declare type_pretty
+	declare _pid _status
+	
+	[ -n "$comp" ] || return 1
+	if [ -z "$opmntype" ]; then
+		opmntype=$comp
+	else
+		type_pretty=" [$opmntype]"
+	fi
+
+	for (( i=$RESTART_RETRIES ; i; i-- )) ; do
+
+		_status=`opmnctl status | grep "^$comp " | grep " $opmntype " | cut -d '|' -f3,4 | sed -e 's/ //g' -e 's/|/ /g'`
+
+		_pid=`echo $_status | cut -f1 -d' '`
+		_status=`echo $_status | cut -f2 -d' '`
+		if [ "${_status}" == "Alive" ] || [ "${_status}" == "Init" ]; then
+			if [ $i -lt $RESTART_RETRIES ] ; then
+				ocf_log info "$comp$type_pretty restarted"
+			fi
+			ocf_log info "$comp$type_pretty (pid $_pid) is running..."
+			break
+		else
+			ocf_log info "$comp$type_pretty is stopped"
+
+			#
+			# Try to restart it, but don't worry if we fail.  OPMN
+			# is supposed to handle restarting these anyway.
+			#
+			# If it's running and you tell OPMN to "start" it,
+			# you will get an error.
+			#
+			# If it's NOT running and you tell OPMN to "restart"
+			# it, you will also get an error.
+			#
+			opmnctl startproc process-type=$opmntype &> /dev/null
+		fi
+	done
+
+	if [ $i -eq 0 ]; then
+		# restarts failed - return 1 (failure)
+		ocf_log error "Failed to restart OPMN process $comp"
+		return 1
+	fi
+
+	return 0
+}
+
+
+#
+# Get the status of the OPMN-managed processes.
+#
+get_opmn_status()
+{
+	declare -i subsys_lock=$1
+	declare -i ct_errors=0
+
+	opmnctl status &> /dev/null
+	if [ $? -eq 2 ]; then
+		#
+		# OPMN not running??
+		#
+		ocf_log info "OPMN is stopped"
+
+		if [ $subsys_lock -eq 0 ]; then
+			#
+			# Don't handle full opmn-restart. XXX
+			#
+			return 1
+		fi
+
+		# That's okay, it's not supposed to be!
+		return 3
+	fi
+
+	#
+	# Print out the PIDs for everyone.
+	#
+	ocf_log info "OPMN is running..."
+	ocf_log info "opmn components:"
+
+	#
+	# Check the OPMN-managed processes
+	#
+	get_opmn_proc_status OID || ((ct_errors++))
+	get_opmn_proc_status HTTP_Server || ((ct_errors++))
+	get_opmn_proc_status OC4J OC4J_SECURITY || ((ct_errors++))
+
+	#
+	# One or more OPMN-managed processes failed and could not be
+	# restarted.
+	#
+	if [ $ct_errors -ne 0 ]; then
+		ocf_log error "$ct_errors errors occurred while restarting OPMN-managed processes"
+		return 1
+	fi
+	return 0
+}
+
+
+#
+# Helps us keep a running status so we know what our ultimate return
+# code will be.  Returns 1 if the $1 and $2 are not equivalent, otherwise
+# returns $1.  The return code is meant to be the next $1 when this is
+# called, so, for example:
+#
+# update_status 0   <-- returns 0
+# update_status $? 0 <-- returns 0
+# update_status $? 3 <-- returns 1 (values different - error condition)
+# update_status $? 1 <-- returns 1 (same, but happen to be error state!)
+#
+# update_status 3
+# update_status $? 3 <-- returns 3
+#
+# (and so forth...)
+#
+update_status()
+{
+	declare -i old_status=$1
+	declare -i new_status=$2
+
+	if [ -z "$2" ]; then
+		return $old_status
+	fi
+
+	if [ $old_status -ne $new_status ]; then
+		return 1
+	fi
+
+	return $old_status
+}
+
+
+#
+# Print an error message to the user and exit.
+#
+oops()
+{
+	ocf_log error "$ORACLE_SID: Fatal: $1 failed validation checks"
+	exit 1
+}
+
+
+#
+# Do some validation on the user-configurable stuff at the beginning of the
+# script.
+#
+validation_checks()
+{
+	ocf_log debug "Validating configuration for $ORACLE_SID"
+
+	#
+	# If the oracle user doesn't exist, we're done.
+	#
+	[ -n "$ORACLE_USER" ] || oops "ORACLE_USER"
+	id -u $ORACLE_USER > /dev/null || oops "ORACLE_USER"
+	id -g $ORACLE_USER > /dev/null || oops "ORACLE_USER"
+
+	#
+	# If the oracle home isn't a directory, we're done
+	#
+	[ -n "$ORACLE_HOME" ] || oops ORACLE_HOME
+	#[ -d "$ORACLE_HOME" ] || oops ORACLE_HOME
+
+	#
+	# If the oracle SID is NULL, we're done
+	#
+	[ -n "$ORACLE_SID" ] || oops ORACLE_SID
+
+	#
+	# If we don't know the type, we're done
+	#
+	if [ "$ORACLE_TYPE" = "base" ]; then
+		# Other names for base
+		ORACLE_TYPE="base"
+	elif [ "$ORACLE_TYPE" = "10g" ] || [ "$ORACLE_TYPE" = "base-em" ]; then
+		ORACLE_TYPE="base-em"
+	elif [ "$ORACLE_TYPE" = "10g-ias" ] || [ "$ORACLE_TYPE" = "ias" ]; then
+		ORACLE_TYPE="ias"
+	elif [ "$ORACLE_TYPE" = "11g" ] || [ "$ORACLE_TYPE" = "base-em-11g" ]; then
+		ORACLE_TYPE="base-em-11g"
+	elif [ "$ORACLE_TYPE" = "base-11g" ]; then
+		ORACLE_TYPE="base-11g"
+	else
+		oops "ORACLE_TYPE $ORACLE_TYPE"
+	fi
+
+	#
+	# If the hostname is zero-length, fix it
+	#
+	[ -n "$ORACLE_HOSTNAME" ] || ORACLE_HOSTNAME=`hostname`
+
+	#
+	# Super user? Automatically change UID and exec as oracle user.
+	# Oracle needs to be run as the Oracle user, not root!
+	#
+	if [ "`id -u`" = "0" ]; then
+		#echo "Restarting $0 as $ORACLE_USER."
+		#
+		# Breaks on RHEL5 
+		# exec sudo -u $ORACLE_USER $0 $*
+		#
+		su $ORACLE_USER -c "$0 $*"
+		exit $?
+	fi
+
+	#
+	# If we're not root and not the Oracle user, we're done.
+	#
+	[ "`id -u`" = "`id -u $ORACLE_USER`" ] || oops "not ORACLE_USER after su"
+	[ "`id -g`" = "`id -g $ORACLE_USER`" ] || oops "not ORACLE_GROUP after su"
+
+	#
+	# Go home.
+	#
+	cd "$ORACLE_HOME"
+
+	ocf_log debug "Validation checks for $ORACLE_SID succeeded"
+	return 0
+}
+
+
+#
+# Start Oracle 9i/10g/11g Application Server Infrastructure
+#
+start_oracle()
+{
+	ocf_log info "Starting service $ORACLE_SID"
+
+	start_db
+	rv=$?
+	if [ $rv -ne 0 ]; then
+		ocf_log error "Starting service $ORACLE_SID failed"
+		return 1
+	fi
+
+	ocf_log info "Starting listener $ORACLE_LISTENER"
+	lsnrctl_stdout=$(lsnrctl start $ORACLE_LISTENER)
+	rv=$?
+	if [ $rv -ne 0 ]; then
+		ocf_log debug "[$ORACLE_SID] Listener $ORACLE_LISTENER start returned $rv output $lsnrctl_stdout"
+		ocf_log error "Starting service $ORACLE_SID failed"
+		return 1
+	fi
+
+	if [ "$ORACLE_TYPE" = "base-em" ]; then
+		ocf_log info "Starting iSQL*Plus for $ORACLE_SID"
+		isqlplusctl start
+		if [ $? -ne 0 ]; then
+			ocf_log error "iSQL*Plus startup for $ORACLE_SID failed"
+			ocf_log error "Starting service $ORACLE_SID failed"
+			return 1
+		else
+			ocf_log info "iSQL*Plus startup for $ORACLE_SID succeeded"
+		fi
+
+		ocf_log info "Starting Oracle EM DB Console for $ORACLE_SID"
+		emctl start dbconsole
+		if [ $? -ne 0 ]; then
+			ocf_log error "Oracle EM DB Console startup for $ORACLE_SID failed"
+			ocf_log error "Starting service $ORACLE_SID failed"
+			return 1
+		else
+			ocf_log info "Oracle EM DB Console startup for $ORACLE_SID succeeded"
+		fi
+	elif [ "$ORACLE_TYPE" = "ias" ]; then
+		ocf_log info "Starting Oracle EM for $ORACLE_SID"
+		emctl start em
+		if [ $? -ne 0 ]; then
+			ocf_log error "Oracle EM startup for $ORACLE_SID failed"
+			ocf_log error "Starting service $ORACLE_SID failed"
+			return 1
+		else
+			ocf_log info "Oracle EM startup for $ORACLE_SID succeeded"
+		fi
+
+		ocf_log info "Starting iAS Infrastructure for $ORACLE_SID"
+		opmnctl startall
+		if [ $? -ne 0 ]; then
+			ocf_log error "iAS Infrastructure startup for $ORACLE_SID failed"
+			ocf_log error "Starting service $ORACLE_SID failed"
+			return 1
+		else
+			ocf_log info "iAS Infrastructure startup for $ORACLE_SID succeeded"
+		fi
+	elif [ "$ORACLE_TYPE" = "base-em-11g" ]; then
+		ocf_log info "Starting Oracle EM DB Console for $ORACLE_SID"
+		emctl start dbconsole
+		if [ $? -ne 0 ]; then
+			ocf_log error "Oracle EM DB Console startup for $ORACLE_SID failed"
+			ocf_log error "Starting service $ORACLE_SID failed"
+			return 1
+		else
+			ocf_log info "Oracle EM DB Console startup for $ORACLE_SID succeeded"
+		fi
+	fi
+
+	if [ -n "$LOCKFILE" ]; then
+		touch "$LOCKFILE"
+	fi
+
+	ocf_log info "Starting service $ORACLE_SID completed successfully"
+	return 0
+}
+
+
+#
+# Stop Oracle 9i/10g/11g Application Server Infrastructure
+#
+stop_oracle()
+{
+	ocf_log info "Stopping service $ORACLE_SID"
+
+	if ! [ -e "$ORACLE_HOME/bin/lsnrctl" ]; then
+		ocf_log error "Oracle Listener Control is not available ($ORACLE_HOME not mounted?)"
+		return 0
+	fi
+
+	if [ "$ORACLE_TYPE" = "base-em" ]; then
+		ocf_log info "Stopping Oracle EM DB Console for $ORACLE_SID"
+		emctl stop dbconsole
+		if [ $? -ne 0 ]; then
+			ocf_log error "Stopping Oracle EM DB Console for $ORACLE_SID failed"
+			ocf_log error "Stopping service $ORACLE_SID failed"
+			return 1
+		else
+			ocf_log info "Stopping Oracle EM DB Console for $ORACLE_SID succeeded"
+		fi
+
+		ocf_log info "Stopping iSQL*Plus for $ORACLE_SID"
+		isqlplusctl stop
+		if [ $? -ne 0 ]; then
+			ocf_log error "Stopping iSQL*Plus for $ORACLE_SID failed"
+			ocf_log error "Stopping service $ORACLE_SID failed"
+			return 1
+		else
+			ocf_log info "Stopping iSQL*Plus for $ORACLE_SID succeeded"
+		fi
+	elif [ "$ORACLE_TYPE" = "ias" ]; then
+		ocf_log info "Stopping iAS Infrastructure for $ORACLE_SID"
+		opmnctl stopall
+		if [ $? -ne 0 ]; then
+			ocf_log error "Stopping iAS Infrastructure for $ORACLE_SID failed"
+			ocf_log error "Stopping service $ORACLE_SID failed"
+			return 1
+		else
+			ocf_log info "Stopping iAS Infrastructure for $ORACLE_SID succeeded"
+		fi
+
+		ocf_log info "Stopping Oracle EM for $ORACLE_SID"
+		emctl stop em
+		if [ $? -ne 0 ]; then
+			ocf_log error "Stopping Oracle EM for $ORACLE_SID failed"
+			ocf_log error "Stopping service $ORACLE_SID failed"
+			return 1
+		else
+			ocf_log info "Stopping Oracle EM for $ORACLE_SID succeeded"
+		fi
+	elif [ "$ORACLE_TYPE" = "base-em-11g" ]; then
+		ocf_log info "Stopping Oracle EM DB Console for $ORACLE_SID"
+		emctl stop dbconsole
+		if [ $? -ne 0 ]; then
+			ocf_log error "Stopping Oracle EM DB Console for $ORACLE_SID failed"
+			ocf_log error "Stopping service $ORACLE_SID failed"
+			return 1
+		else
+			ocf_log info "Stopping Oracle EM DB Console for $ORACLE_SID succeeded"
+		fi
+	fi
+
+	stop_db immediate || stop_db abort
+	if [ $? -ne 0 ]; then
+		ocf_log error "Stopping service $ORACLE_SID failed"
+		return 1
+	fi
+
+	ocf_log info "Stopping listener $ORACLE_LISTENER for $ORACLE_SID"
+	lsnrctl_stdout=$(lsnrctl stop $ORACLE_LISTENER)
+	rv=$?
+	if [ $? -ne 0 ]; then
+		ocf_log error "Listener $ORACLE_LISTENER stop failed for $ORACLE_SID: $rv output $lsnrctl_stdout"
+		# XXX - failure?
+	fi
+
+	exit_idle 
+	if [ $? -ne 0 ]; then
+		ocf_log warning "WARNING: Not all Oracle processes exited cleanly for $ORACLE_SID"
+	fi
+
+	if [ -n "$LOCKFILE" ]; then
+		rm -f "$LOCKFILE"
+	fi
+
+	ocf_log info "Stopping service $ORACLE_SID succeeded"
+	return 0
+}
+
+
+#
+# Find and display the status of iAS infrastructure.
+#
+# This has three parts:
+# (1) Oracle database itself
+# (2) Oracle listener process
+# (3) OPMN and OPMN-managed processes
+#
+# - If all are (cleanly) down, we return 3.  In order for this to happen,
+# $LOCKFILE must not exist.  In this case, we try and restart certain parts
+# of the service - as this may be running in a clustered environment.
+#
+# - If some but not all are running (and, if $LOCKFILE exists, we could not
+# restart the failed portions), we return 1 (ERROR)
+#
+# - If all are running, return 0.  In the "all-running" case, we recreate
+# $LOCKFILE if it does not exist.
+#
+status_oracle()
+{
+	declare -i subsys_lock=1
+	declare -i last 
+
+	ocf_log debug "Checking status for $ORACLE_SID depth $depth"
+
+	#
+	# Check for lock file.  Crude and rudimentary, but it works
+	#
+	if [ -z "$LOCKFILE" ] || [ -f "$LOCKFILE" ]; then
+		subsys_lock=0 
+	fi
+
+	# Check database status
+	get_db_status $subsys_lock
+	update_status $? # Start
+	last=$?
+
+	# Check & report listener status
+	get_lsnr_status $subsys_lock
+	update_status $? $last
+	last=$?
+	
+	if [ "$ORACLE_TYPE" = "base-em" ] || [ "$ORACLE_TYPE" = "base-em-11g" ]; then
+		# XXX Add isqlplus status check?!
+		emctl status dbconsole >&/dev/null
+		update_status $? $last
+		last=$?
+	elif [ "$ORACLE_TYPE" = "ias" ]; then
+		# Check & report opmn / opmn-managed process status
+		get_opmn_status $subsys_lock
+		update_status $? $last
+		last=$?
+	fi
+
+	#
+	# No lock file, but everything's running.  Put the lock
+	# file back. XXX - this kosher?
+	#
+	if [ $last -eq 0 ] && [ $subsys_lock -ne 0 ]; then
+		touch "$LOCKFILE"
+	fi
+
+	ocf_log debug "Status returning $last for $ORACLE_SID"
+	return $last
+}
+
+
+########################
+# Do some real work... #
+########################
+if [ "$1" = "meta-data" ]; then
+	meta_data
+	exit 0
+fi
+
+validation_checks $*
+
+case $1 in
+	start)
+		start_oracle
+		exit $?
+		;;
+	stop)
+		stop_oracle
+		exit $?
+		;;
+	status|monitor)
+		status_oracle
+		exit $?
+		;;
+	restart)
+		$0 stop || exit $?
+		$0 start || exit $?
+		exit 0
+		;;
+	*)
+		echo "usage: $SCRIPT {start|stop|status|restart|meta-data}"
+		exit 1
+		;;
+esac
+exit 0
diff --git a/rgmanager/src/resources/orainstance.metadata b/rgmanager/src/resources/orainstance.metadata
new file mode 100644
index 0000000..b58617b
--- /dev/null
+++ b/rgmanager/src/resources/orainstance.metadata
@@ -0,0 +1,98 @@
+<?xml version="1.0" ?>
+<!-- $Id: orainstance.metadata 58 2009-06-29 05:15:12Z hevirtan $ -->
+
+<!-- Resource metadata for Oracle DB agent -->
+<resource-agent name="orainstance" version="rgmanager 2.0">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+	Oracle 10g Failover Instance
+    </longdesc>
+    <shortdesc lang="en">
+	Oracle 10g Failover Instance
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    	<longdesc lang="en">
+				Instance name (SID) of oracle instance
+	    	</longdesc>
+        	<shortdesc lang="en">
+				Oracle SID
+        	</shortdesc>
+	    	<content type="string"/>
+        </parameter>
+
+        <parameter name="user" required="1">
+	    	<longdesc lang="en">
+				Oracle user name.  This is the user name of the Oracle
+				user which the Oracle instance runs as.
+	    	</longdesc>
+        	<shortdesc lang="en">
+				Oracle User Name
+        	</shortdesc>
+	    	<content type="string"/>
+        </parameter>
+
+        <parameter name="home" required="1">
+	    	<longdesc lang="en">
+				This is the Oracle database home directory.
+				This is configured when you install Oracle.
+	    	</longdesc>
+        	<shortdesc lang="en">
+				Oracle Home Directory
+        	</shortdesc>
+	    	<content type="string"/>
+        </parameter>
+
+        <parameter name="listeners">
+	    	<longdesc lang="en">
+				List of Oracle listeners which will be started with
+				the database instance. Listener names are separated by
+				whitespace. Defaults to empty which disables listeners.
+	    	</longdesc>
+        	<shortdesc lang="en">
+				Oracle listeners
+        	</shortdesc>
+	    	<content type="string" default=""/>
+        </parameter>
+
+        <parameter name="lockfile">
+	    	<longdesc lang="en">
+				Location for lockfile which will be used for checking if
+				the Oracle should be running or not. Defaults to location
+				under /tmp.
+	    	</longdesc>
+        	<shortdesc lang="en">
+				Pathname for lockfile
+        	</shortdesc>
+	    	<content type="string"/>
+        </parameter>
+
+        <parameter name="tns_admin" required="0" unique="1">
+	    <longdesc lang="en">
+			Full path to the directory that contains the Oracle
+        listener tnsnames.ora configuration file.  The shell
+        variable TNS_ADMIN is set to the value provided.
+	    </longdesc>
+            <shortdesc lang="en">
+		Full path to the directory containing tnsnames.ora
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="900"/>
+		<action name="stop" timeout="90"/>
+
+		<!-- Note: status check will also perform recover 
+			 (Oracle DB restart) if the check fails -->
+		<action name="status" timeout="900" interval="1m"/>
+		<action name="monitor" timeout="900" interval="1m"/>
+
+		<action name="meta-data" timeout="0"/>
+		<action name="verify-all" timeout="0"/>
+    </actions>
+
+</resource-agent>
diff --git a/rgmanager/src/resources/orainstance.sh b/rgmanager/src/resources/orainstance.sh
new file mode 100755
index 0000000..9254744
--- /dev/null
+++ b/rgmanager/src/resources/orainstance.sh
@@ -0,0 +1,577 @@
+#!/bin/bash
+#
+# Copyright 2003-2004, 2006-2013 Red Hat, Inc.
+#
+# Author(s):
+#     Hardy Merrill <hmerrill at redhat.com>
+#     Lon Hohberger <lhh at redhat.com>
+#     Michael Moon <Michael dot Moon at oracle.com>
+#     Ryan McCabe <rmccabe at redhat.com>
+#
+# This program is Open Source software.  You may modify and/or redistribute
+# it persuant to the terms of the Open Software License version 2.1, which
+# is available from the following URL and is included herein by reference:
+#
+# 	http://opensource.org/licenses/osl-2.1.php
+#
+# NOTES:
+#
+# (1) You can comment out the LOCKFILE declaration below.  This will prevent
+# the need for this script to access anything outside of the ORACLE_HOME 
+# path.
+#
+# (2) You MUST customize ORACLE_USER, ORACLE_HOME, ORACLE_SID, and
+# ORACLE_HOSTNAME to match your installation if not running from within
+# rgmanager.
+#
+# (3) Do NOT place this script in shared storage; place it in ORACLE_USER's
+# home directory in non-clustered environments and /usr/share/cluster
+# in rgmanager/Red Hat cluster environments.
+#
+# Oracle is a registered trademark of Oracle Corporation.
+# Oracle9i is a trademark of Oracle Corporation.
+# Oracle10g is a trademark of Oracle Corporation.
+# Oracle11g is a trademark of Oracle Corporation.
+# All other trademarks are property of their respective owners.
+#
+#
+# $Id: orainstance.sh 127 2009-08-21 09:17:52Z hevirtan $
+#
+# Original version is distributed with RHCS. The modifications include
+# the following minor changes:
+# - Meta-data moved to a dedicated file
+# - Support for multiple listeners
+# - Disabled EM
+# - SysV init support removed. Only usable with rgmanager
+#
+
+# Grab the global RHCS helper functions
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+. /etc/init.d/functions
+
+declare SCRIPT="`basename $0`"
+declare SCRIPTDIR="`dirname $0`"
+
+# Required parameters from rgmanager
+ORACLE_USER=$OCF_RESKEY_user
+ORACLE_HOME=$OCF_RESKEY_home
+ORACLE_SID=$OCF_RESKEY_name
+[ -n "$OCF_RESKEY_tns_admin" ] && export TNS_ADMIN=$OCF_RESKEY_tns_admin
+
+# Optional parameters with default values
+LISTENERS=$OCF_RESKEY_listeners
+LOCKFILE="$ORACLE_HOME/.orainstance-${ORACLE_SID}.lock"
+[ -n "$OCF_RESKEY_lockfile" ] && LOCKFILE=$OCF_RESKEY_lockfile
+
+export LISTENERS ORACLE_USER ORACLE_HOME ORACLE_SID LOCKFILE
+export LD_LIBRARY_PATH=$ORACLE_HOME/lib
+export PATH=$ORACLE_HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin
+
+declare -i	RESTART_RETRIES=3
+declare -r	DB_PROCNAMES="pmon"
+declare -r	LSNR_PROCNAME="tnslsnr"
+
+# clulog will not log messages when run by the oracle user.
+# This is a hack to work around that.
+if [ "`id -u`" = "`id -u $ORACLE_USER`" ]; then
+	ocf_log() {
+		prio=$1
+		shift
+		logger -i -p daemon."$prio" -- "$*"
+	}
+fi
+
+#
+# Start Oracle (database portion)
+#
+start_db() {
+	declare -i rv
+	declare startup_cmd
+	declare startup_stdout
+
+	ocf_log info "Starting Oracle DB $ORACLE_SID"
+
+	# Set up our sqlplus script.  Basically, we're trying to 
+	# capture output in the hopes that it's useful in the case
+	# that something doesn't work properly.
+	startup_cmd="set heading off;\nstartup;\nquit;\n"
+	startup_stdout=$(echo -e "$startup_cmd" | sqlplus -S "/ as sysdba")
+	rv=$?
+
+	# Dump output to syslog for debugging
+	ocf_log debug "[$ORACLE_SID] [$rv] sent $startup_cmd"
+	ocf_log debug "[$ORACLE_SID] [$rv] got $startup_stdout"
+	
+	if [ $rv -ne 0 ]; then
+		ocf_log error "Starting Oracle DB $ORACLE_SID failed, sqlplus returned $rv"
+		return 1
+	fi
+
+	# If we see:
+	# ORA-.....: failure, we failed
+	# Troubleshooting:
+	#   ORA-00845 - Try rm -f /dev/shm/ora_*
+	#   ORA-01081 - Try echo -e 'shutdown abort;\nquit;'|sqlplus "/ as sysdba"
+	if [[ "$startup_stdout" =~ "ORA-" ]] || [[ "$startup_stdout" =~ "failure" ]]; then
+		ocf_log error "Starting Oracle DB $ORACLE_SID failed, found errors in stdout"
+		return 1
+	fi
+
+	ocf_log info "Started Oracle DB $ORACLE_SID successfully"
+	return 0
+}
+
+
+#
+# Stop Oracle (database portion)
+#
+stop_db() {
+	declare stop_cmd
+	declare stop_stdout
+	declare -i rv
+	declare how_shutdown="$1"
+
+	if [ -z "$1" ]; then
+		how_shutdown="immediate"
+	fi
+
+	ocf_log info "Stopping Oracle DB $ORACLE_SID $how_shutdown"
+
+	ora_procname="ora_${DB_PROCNAMES}_${ORACLE_SID}"
+	status $ora_procname
+	if [ $? -ne 0 ]; then
+		ocf_log debug "no pmon process -- DB $ORACLE_SID already stopped"
+		# No pmon process found, db already down
+		return 0
+	fi
+
+	# Setup for Stop ...
+	stop_cmd="set heading off;\nshutdown $how_shutdown;\nquit;\n"
+	stop_stdout=$(echo -e "$stop_cmd" | sqlplus -S "/ as sysdba")
+	rv=$?
+
+	# Log stdout of the stop command
+	ocf_log debug "[$ORACLE_SID] sent stop command $stop_cmd"
+	ocf_log debug "[$ORACLE_SID] got $stop_stdout"
+	
+	# sqlplus returned failure. We'll return failed to rhcs
+	if [ $rv -ne 0 ]; then
+		ocf_log error "Stopping Oracle DB $ORACLE_SID failed, sqlplus returned $rv"
+		return 1
+	fi
+
+	# If we see 'ORA-' or 'failure' in stdout, we're done.
+	if [[ "$startup_stdout" =~ "ORA-" ]] || [[ "$startup_stdout" =~ "failure" ]]; then
+		ocf_log error "Stopping Oracle DB $ORACLE_SID failed, errors in stdout"
+		return 1
+	fi
+
+	ocf_log info "Stopped Oracle DB $ORACLE_SID successfully"
+	return 0
+}
+
+
+#
+# Destroy any remaining processes with refs to $ORACLE_SID
+#
+force_cleanup() {
+	declare pids
+	declare pid
+
+	ocf_log error "Not all Oracle processes for $ORACLE_SID exited cleanly, killing"
+	
+	pids=`ps ax | grep "ora_.*_${ORACLE_SID}" | grep -v grep | awk '{print $1}'`
+
+	for pid in $pids; do
+		kill -9 $pid
+		rv=$?
+		if [ $rv -eq 0 ]; then
+			ocf_log info "Cleanup $ORACLE_SID Killed PID $pid"
+		else
+			ocf_log error "Cleanup $ORACLE_SID Kill PID $pid failed: $rv"
+		fi
+	done
+
+	return 0
+}
+
+
+#
+# Wait for oracle processes to exit.  Time out after 60 seconds
+#
+exit_idle() {
+	declare -i n=0
+	
+	ocf_log debug "Waiting for Oracle processes for $ORACLE_SID to terminate..."
+	while ps ax | grep $ORACLE_SID | grep -q -v $LSNR_PROCNAME | grep -q -v grep; do
+		if [ $n -ge 90 ]; then
+			ocf_log debug "Timed out while waiting for Oracle processes for $ORACLE_SID to terminate"
+			force_cleanup
+			return 0
+		fi
+		sleep 1
+		((n++))
+	done
+
+	ocf_log debug "All Oracle processes for $ORACLE_SID have terminated"
+	return 0
+}
+
+
+#
+# Get database background process status.  Restart it if it failed and
+# we have seen the lock file.
+#
+get_db_status() {
+	declare -i subsys_lock=$1
+	declare -i i=0
+	declare -i rv=0
+	declare ora_procname
+
+	ocf_log debug "Checking status of DB $ORACLE_SID"
+
+	for procname in $DB_PROCNAMES ; do
+		ora_procname="ora_${procname}_${ORACLE_SID}"
+		
+		status $ora_procname
+		if [ $? -eq 0 ] ; then
+			# This one's okay; go to the next one.
+			continue
+		fi
+
+		# We're not supposed to be running, and we are,
+		# in fact, not running...
+		if [ $subsys_lock -ne 0 ]; then
+			ocf_log debug "DB $ORACLE_SID is already stopped"
+			return 3
+		fi
+
+		for (( i=$RESTART_RETRIES ; i; i-- )) ; do
+			# this db process is down - stop and
+			# (re)start all ora_XXXX_$ORACLE_SID processes
+			ocf_log info "Restarting Oracle Database $ORACLE_SID"
+			stop_db
+
+			start_db
+			if [ $? -eq 0 ] ; then
+				# ora_XXXX_$ORACLE_SID processes started
+				# successfully, so break out of the
+				# stop/start # 'for' loop
+				ocf_log info "Restarted Oracle DB $ORACLE_SID successfully"
+				break
+			fi
+		done
+
+		if [ $i -eq 0 ]; then
+			# stop/start's failed - return 1 (failure)
+			ocf_log error "Failed to restart Oracle DB $ORACLE_SID after $RESTART_RETRIES tries"
+			return 1
+		fi
+	done
+
+	ocf_log debug "Checking status of DB $ORACLE_SID success"
+	return 0
+}
+
+
+#
+# Get the status of the Oracle listener process
+#
+get_lsnr_status() {
+	declare -i subsys_lock=$1
+	declare -i rv
+	declare -r LISTENER=$3
+
+	ocf_log debug "Checking status for listener $LISTENER"
+	lsnrctl status "$LISTENER" >& /dev/null
+	rv=$?
+	if [ $rv -eq 0 ] ; then
+		ocf_log debug "Listener $LISTENER is up"
+		return 0 # Listener is running fine
+	fi
+
+	# We're not supposed to be running, and we are,
+	# in fact, not running.  Return 3
+	if [ $subsys_lock -ne 0 ]; then
+		ocf_log debug "Listener $LISTENER is stopped as expected"
+		return 3
+	fi
+
+	# Listener is NOT running (but should be) - try to restart
+	for (( i=$RESTART_RETRIES ; i; i-- )) ; do
+		ocf_log info "Listener $LISTENER is down, attempting to restart"
+		lsnrctl start "$LISTENER" >& /dev/null
+		lsnrctl status "$LISTENER" >& /dev/null
+		if [ $? -eq 0 ]; then
+			ocf_log info "Listener $LISTENER was restarted successfully"
+			break # Listener was (re)started and is running fine
+		fi
+	done
+
+	if [ $i -eq 0 ]; then
+		# stop/start's failed - return 1 (failure)
+		ocf_log error "Failed to restart listener $LISTENER after $RESTART_RETRIES tries"
+		return 1
+	fi
+
+	lsnrctl_stdout=$(lsnrctl status "$LISTENER")
+	rv=$?
+	if [ $rv -ne 0 ] ; then
+		ocf_log error "Starting listener $LISTENER failed: $rv output $lsnrctl_stdout"
+		return 1 # Problem restarting the Listener
+	fi
+
+	ocf_log info "Listener $LISTENER started successfully"
+	return 0 # Success restarting the Listener
+}
+
+
+#
+# Helps us keep a running status so we know what our ultimate return
+# code will be.  Returns 1 if the $1 and $2 are not equivalent, otherwise
+# returns $1.  The return code is meant to be the next $1 when this is
+# called, so, for example:
+#
+# update_status 0   <-- returns 0
+# update_status $? 0 <-- returns 0
+# update_status $? 3 <-- returns 1 (values different - error condition)
+# update_status $? 1 <-- returns 1 (same, but happen to be error state!)
+#
+# update_status 3
+# update_status $? 3 <-- returns 3
+#
+# (and so forth...)
+#
+update_status() {
+	declare -i old_status=$1
+	declare -i new_status=$2
+
+	if [ -z "$2" ]; then
+		return $old_status
+	fi
+
+	if [ $old_status -ne $new_status ]; then
+		ocf_log error "Error: $old_status vs $new_status for $ORACLE_SID - returning 1"
+		return 1
+	fi
+
+	return $old_status
+}
+
+
+#
+# Print an error message to the user and exit.
+#
+oops() {
+	ocf_log error "$ORACLE_SID: Fatal: $1 failed validation checks"
+	exit 1
+}
+
+
+#
+# Do some validation on the user-configurable stuff at the beginning of the
+# script.
+#
+validation_checks() {
+	ocf_log debug "Validating configuration for $ORACLE_SID"
+
+	# If the oracle user doesn't exist, we're done.
+	[ -n "$ORACLE_USER" ] || oops "ORACLE_USER"
+	id -u $ORACLE_USER > /dev/null || oops "ORACLE_USER"
+	id -g $ORACLE_USER > /dev/null || oops "ORACLE_GROUP"
+
+	# If the oracle home isn't a directory, we're done
+	[ -n "$ORACLE_HOME" ] || oops "ORACLE_HOME"
+
+	# If the oracle SID is NULL, we're done
+	[ -n "$ORACLE_SID" ] || oops "ORACLE_SID"
+
+	# Super user? Automatically change UID and exec as oracle user.
+	# Oracle needs to be run as the Oracle user, not root!
+	if [ "`id -u`" = "0" ]; then
+		su $ORACLE_USER -c "$0 $*"
+		exit $?
+	fi
+
+	# If we're not root and not the Oracle user, we're done.
+	[ "`id -u`" = "`id -u $ORACLE_USER`" ] || oops "not ORACLE_USER after su"
+	[ "`id -g`" = "`id -g $ORACLE_USER`" ] || oops "not ORACLE_GROUP after su"
+
+	# Go home.
+	cd "$ORACLE_HOME"
+
+	ocf_log debug "Validation checks for $ORACLE_SID succeeded"
+	return 0
+}
+
+
+#
+# Start Oracle
+#
+start_oracle() {
+	ocf_log info "Starting service $ORACLE_SID"
+
+	start_db
+	rv=$?
+	if [ $rv -ne 0 ]; then
+		ocf_log error "Starting service $ORACLE_SID failed"
+		return 1
+	fi
+
+	for LISTENER in ${LISTENERS}; do
+		ocf_log info "Starting listener $LISTENER"
+		lsnrctl_stdout=$(lsnrctl start "$LISTENER")
+		rv=$?
+		if [ $rv -ne 0 ]; then
+			ocf_log debug "[$ORACLE_SID] Listener $LISTENER start returned $rv output $lsnrctl_stdout"
+			ocf_log error "Starting service $ORACLE_SID failed"
+			return 1
+		fi
+	done
+
+	if [ -n "$LOCKFILE" ]; then
+		touch "$LOCKFILE"
+	fi
+
+	ocf_log info "Starting service $ORACLE_SID completed successfully"
+	return 0
+}
+
+
+#
+# Stop Oracle
+#
+stop_oracle() {
+	ocf_log info "Stopping service $ORACLE_SID"
+
+	if ! [ -e "$ORACLE_HOME/bin/lsnrctl" ]; then
+		ocf_log error "Oracle Listener Control is not available ($ORACLE_HOME not mounted?)"
+		# XXX should this return 1?
+		return 0
+	fi
+
+	stop_db || stop_db abort
+	if [ $? -ne 0 ]; then
+		ocf_log error "Unable to stop DB for $ORACLE_SID"
+		return 1
+	fi
+
+	for LISTENER in ${LISTENERS}; do
+		ocf_log info "Stopping listener $LISTENER for $ORACLE_SID"
+		lsnrctl_stdout=$(lsnrctl stop "$LISTENER")
+		rv=$?
+		if [ $? -ne 0 ]; then
+			ocf_log error "Listener $LISTENER stop failed for $ORACLE_SID: $rv output $lsnrctl_stdout"
+			# XXX - failure?
+		fi
+	done
+
+	exit_idle
+
+	if [ $? -ne 0 ]; then
+		ocf_log error "WARNING: Not all Oracle processes exited cleanly for $ORACLE_SID"
+		# XXX - failure?
+	fi
+
+	if [ -n "$LOCKFILE" ]; then
+		rm -f "$LOCKFILE"
+	fi
+
+	ocf_log info "Stopping service $ORACLE_SID succeeded"
+	return 0
+}
+
+
+#
+# Find and display the status of iAS infrastructure.
+#
+# This has three parts:
+# (1) Oracle database itself
+# (2) Oracle listener process
+# (3) OPMN and OPMN-managed processes
+#
+# - If all are (cleanly) down, we return 3.  In order for this to happen,
+# $LOCKFILE must not exist.  In this case, we try and restart certain parts
+# of the service - as this may be running in a clustered environment.
+#
+# - If some but not all are running (and, if $LOCKFILE exists, we could not
+# restart the failed portions), we return 1 (ERROR)
+#
+# - If all are running, return 0.  In the "all-running" case, we recreate
+# $LOCKFILE if it does not exist.
+#
+status_oracle() {
+	declare -i subsys_lock=1
+	declare -i last 
+	declare -i depth=$1
+
+	ocf_log debug "Checking status for $ORACLE_SID depth $depth"
+
+	# Check for lock file. Crude and rudimentary, but it works
+	if [ -z "$LOCKFILE" ] || [ -f "$LOCKFILE" ]; then
+		subsys_lock=0 
+	fi
+
+	# Check database status
+	get_db_status $subsys_lock $depth
+	update_status $? # Start
+	last=$?
+
+	# Check & report listener status
+	for LISTENER in ${LISTENERS}; do
+		get_lsnr_status $subsys_lock $depth "$LISTENER"
+		update_status $? $last
+		last=$?
+	done
+	
+	# No lock file, but everything's running.  Put the lock
+	# file back. XXX - this kosher?
+	if [ $last -eq 0 ] && [ $subsys_lock -ne 0 ]; then
+		touch "$LOCKFILE"
+	fi
+
+	ocf_log debug "Status returning $last for $ORACLE_SID"
+	return $last
+}
+
+
+########################
+# Do some real work... #
+########################
+
+case $1 in
+	meta-data)
+		cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+		exit 0
+		;;
+	start)
+		validation_checks $*
+		start_oracle
+		exit $?
+		;;
+	stop)
+		validation_checks $*
+		stop_oracle
+		exit $?
+		;;
+	status|monitor)
+		validation_checks $*
+		status_oracle $OCF_CHECK_LEVEL
+		exit $?
+		;;
+	restart)
+		$0 stop || exit $?
+		$0 start || exit $?
+		exit 0
+		;;
+	*)
+		echo "usage: $SCRIPT {start|stop|restart|status|monitor|meta-data}"
+		exit 1
+		;;
+esac
+
+exit 0
diff --git a/rgmanager/src/resources/oralistener.metadata b/rgmanager/src/resources/oralistener.metadata
new file mode 100644
index 0000000..0ed04a6
--- /dev/null
+++ b/rgmanager/src/resources/oralistener.metadata
@@ -0,0 +1,73 @@
+<?xml version="1.0" ?>
+<!-- $Id: oralistener.metadata 61 2009-06-29 10:01:49Z hevirtan $ -->
+
+<!-- Resource metadata for Oracle listener agent -->
+<resource-agent name="oralistener" version="rgmanager 2.0">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+	Oracle 10g Listener Instance
+    </longdesc>
+    <shortdesc lang="en">
+	Oracle 10g Listener Instance
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    	<longdesc lang="en">
+				Listener name
+	    	</longdesc>
+        	<shortdesc lang="en">
+				Listener name
+        	</shortdesc>
+	    	<content type="string"/>
+        </parameter>
+
+        <parameter name="user" required="1">
+	    	<longdesc lang="en">
+				Oracle user name.  This is the user name of the Oracle
+				user which the Oracle instance runs as.
+	    	</longdesc>
+        	<shortdesc lang="en">
+				Oracle User Name
+        	</shortdesc>
+	    	<content type="string"/>
+        </parameter>
+
+        <parameter name="home" required="1">
+	    	<longdesc lang="en">
+				This is the Oracle database home directory.
+				This is configured when you install Oracle.
+	    	</longdesc>
+        	<shortdesc lang="en">
+				Oracle Home Directory
+        	</shortdesc>
+	    	<content type="string"/>
+        </parameter>
+
+        <parameter name="tns_admin" required="0" unique="1">
+	    <longdesc lang="en">
+			Full path to the directory that contains the Oracle
+        listener tnsnames.ora configuration file.  The shell
+        variable TNS_ADMIN is set to the value provided.
+	    </longdesc>
+            <shortdesc lang="en">
+		Full path to the directory containing tnsnames.ora
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="90"/>
+		<action name="stop" timeout="30"/>
+		<!-- <action name="recover" timeout="90"/> -->
+
+		<action name="status" timeout="90" interval="5m"/>
+		<action name="monitor" timeout="90" interval="5m"/>
+
+		<action name="meta-data" timeout="0"/>
+		<action name="verify-all" timeout="0"/>
+    </actions>
+
+</resource-agent>
diff --git a/rgmanager/src/resources/oralistener.sh b/rgmanager/src/resources/oralistener.sh
new file mode 100755
index 0000000..90808ed
--- /dev/null
+++ b/rgmanager/src/resources/oralistener.sh
@@ -0,0 +1,191 @@
+#!/bin/bash
+#
+# Red Hat Cluster Suite resource agent for controlling Oracle 10g
+# listener instances. This script will start, stop and monitor running
+# listeners.
+#
+# start:    Will start given listener instance
+#
+# stop:     Will stop given listener instance
+#
+# monitor:  Will check that the listener is OK by calling lsnrctl status
+#
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2013 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+# Grab the global RHCS helper functions
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+declare -i	RESTART_RETRIES=3
+
+ORACLE_USER=$OCF_RESKEY_user
+ORACLE_HOME=$OCF_RESKEY_home
+LISTENER=$OCF_RESKEY_name
+[ -n "$OCF_RESKEY_tns_admin" ] && export TNS_ADMIN=$OCF_RESKEY_tns_admin
+
+LC_ALL=C
+LANG=C
+PATH=$ORACLE_HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin
+export LC_ALL LANG PATH ORACLE_USER ORACLE_HOME
+
+# clulog will not log messages when run by the oracle user.
+# This is a hack to work around that.
+if [ "`id -u`" = "`id -u $ORACLE_USER`" ]; then
+	ocf_log() {
+		prio=$1
+		shift
+		logger -i -p daemon."$prio" -- "$*"
+	}
+fi
+
+verify_all() {
+	ocf_log debug "Validating configuration for $LISTENER"
+
+	if [ -z "$OCF_RESKEY_name" ]; then
+		ocf_log error "Validation for $LISTENER failed: Invalid name of service (listener name)"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_home" ]; then
+		ocf_log error "Validation for $LISTENER failed: No Oracle home specified."
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_user" ]; then
+		ocf_log error "Validation for $LISTENER failed: No Oracle username specified."
+		return $OCF_ERR_ARGS
+	fi
+ 
+	# Super user? Automatically change UID and exec as oracle user.
+	# Oracle needs to be run as the Oracle user, not root!
+	if [ "`id -u`" = "0" ]; then
+		su $OCF_RESKEY_user -c "$0 $*"
+		exit $?
+	fi
+
+	# Make sure the lsnrctl binary is in our $PATH
+	if [ ! -x $(which lsnrctl) ]; then
+		ocf_log error "Validation for $LISTENER failed: Unable to locate lsnrctl command from path! ($PATH)"
+		return $OCF_ERR_GENERIC
+	fi
+
+	ocf_log debug "Validation checks for $LISTENER succeeded"
+	return 0
+}
+
+start() {
+	ocf_log info "Starting listener $LISTENER"
+	lsnrctl_stdout=$(lsnrctl start "$LISTENER")
+	if [ $? -ne 0 ]; then
+		ocf_log error "start listener $LISTENER failed $lsnrctl_stdout"
+		return $OCF_ERR_GENERIC
+	fi
+
+	ocf_log info "Listener $LISTENER started successfully"
+	return 0
+}
+ 
+stop() {
+	ocf_log info "Stopping listener $LISTENER"
+
+	lsnrctl_stdout=$(lsnrctl stop "$LISTENER")
+	if [ $? -ne 0 ]; then
+		ocf_log debug "stop listener $LISTENER failed $lsnrctl_stdout"
+		return $OCF_ERR_GENERIC
+	fi
+
+	ocf_log info "Listener $LISTENER stopped successfully"
+	return 0
+}
+ 
+monitor() {
+	declare -i depth=$1
+
+	ocf_log debug "Checking status for listener $LISTENER depth $depth"
+	lsnrctl status "$LISTENER" >& /dev/null
+	if [ $? -ne 0 ]; then
+		ocf_log error "Listener $LISTENER not running"
+		return $OCF_ERR_GENERIC
+	fi
+
+	ocf_log debug "Listener $LISTENER is up"
+	return 0 # Listener is running fine
+}
+
+recover() {
+	ocf_log debug "Recovering listener $LISTENER"
+
+	for (( i=$RESTART_RETRIES ; i; i-- )); do
+		start
+		if [ $? -eq 0 ] ; then
+			ocf_log debug "Restarted listener $LISTENER successfully"
+			break
+		fi
+	done
+
+	if [ $i -eq 0 ]; then
+		# stop/start's failed - return 1 (failure)
+		ocf_log debug "Failed to restart listener $LISTENER after $RESTART_RETRIES tries"
+		return 1
+	fi
+
+	status
+	if [ $? -ne 0 ] ; then
+		ocf_log debug "Failed to restart listener $LISTENER"
+		return 1 # Problem restarting the Listener
+	fi
+
+	ocf_log debug "Restarted listener $LISTENER successfully"
+	return 0 # Success restarting the Listener
+}
+
+case $1 in
+	meta-data)
+		cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+		exit 0
+		;;
+	verify-all)
+		verify_all $*
+		exit $?
+		;;
+	start)
+		verify_all $* && start
+		exit $?
+		;;
+	stop)
+		verify_all $* && stop
+		exit $?
+		;;
+	recover)
+		verify_all $* && recover
+		exit $?
+		;;
+	status|monitor)
+		verify_all $*
+		monitor $OCF_CHECK_LEVEL
+		exit $?
+		;;
+	*)
+		echo "Usage: $0 {start|stop|recover|monitor|status|meta-data|verify-all}"
+		exit $OCF_ERR_GENERIC
+		;;
+esac
diff --git a/rgmanager/src/resources/postgres-8.metadata b/rgmanager/src/resources/postgres-8.metadata
new file mode 100644
index 0000000..7b05d31
--- /dev/null
+++ b/rgmanager/src/resources/postgres-8.metadata
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<resource-agent version="rgmanager 2.0" name="postgres-8">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines an instance of PostgreSQL server
+    </longdesc>
+    <shortdesc lang="en">
+        Defines a PostgreSQL server
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+	        Specifies a service name for logging and other purposes
+	    </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="config_file">
+            <longdesc lang="en">
+                Define absolute path to configuration file
+            </longdesc>
+            <shortdesc lang="en">
+                Config File
+            </shortdesc>
+	    <content type="string" default="/var/lib/pgsql/data/postgresql.conf"/>
+        </parameter>
+
+	<parameter name="postmaster_user">
+		<longdesc lang="en">
+			User who runs the database server because it can't be
+			run by root.
+		</longdesc>
+		<shortdesc lang="en">
+			User who runs the database server
+		</shortdesc>
+		<content type="string" default="postgres" />
+	</parameter>
+
+	<parameter name="postmaster_options">
+		<longdesc lang="en">
+			Other command-line options for postmaster
+		</longdesc>
+		<shortdesc lang="en">
+			Other command-line options for postmaster
+		</shortdesc>
+		<content type="string" default="-D /var/lib/pgsql/data"/>
+	</parameter>
+
+	<parameter name="shutdown_wait">
+		<longdesc lang="en">
+			Wait X seconds for correct end of service shutdown. 
+			This option is ignored in current release.
+		</longdesc>
+		<shortdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+			This option is ignored in current release.
+		</shortdesc>
+		<content type="integer" />
+	</parameter>
+
+        <parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+	    	Inherit the service name.  We need to know
+		the service name in order to determine file
+		systems and IPs for this service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Inherit the service name.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="30"/>
+	<action name="stop" timeout="30"/>
+
+	<!-- Checks to see if it''s mounted in the right place -->
+	<action name="status" interval="1m" timeout="10"/>
+	<action name="monitor" interval="1m" timeout="10"/>
+
+	<!-- Checks to see if we can read from the mountpoint -->
+	<action name="status" depth="10" timeout="30" interval="5m"/>
+	<action name="monitor" depth="10" timeout="30" interval="5m"/>
+
+	<action name="meta-data" timeout="0"/>
+	<action name="validate-all" timeout="0"/>
+    </actions>
+
+    <special tag="rgmanager">
+    </special>
+</resource-agent>
diff --git a/rgmanager/src/resources/postgres-8.sh b/rgmanager/src/resources/postgres-8.sh
new file mode 100755
index 0000000..023a5e5
--- /dev/null
+++ b/rgmanager/src/resources/postgres-8.sh
@@ -0,0 +1,233 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+export LC_ALL=C
+export LANG=C
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+declare PSQL_POSTMASTER="/usr/bin/postmaster"
+declare PSQL_CTL="/usr/bin/pg_ctl"
+declare PSQL_pid_file="`generate_name_for_pid_file`"
+declare PSQL_conf_dir="`generate_name_for_conf_dir`"
+declare PSQL_gen_config_file="$PSQL_conf_dir/postgresql.conf"
+declare PSQL_kill_timeout="5"
+declare PSQL_stop_timeout="15"
+declare PSQL_wait_after_start="2"
+
+verify_all()
+{
+	clog_service_verify $CLOG_INIT
+
+	if [ -z "$OCF_RESKEY_name" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid Name Of Service"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_service_name" ]; then
+		clog_service_verify $CLOG_FAILED_NOT_CHILD
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_INVALID "$OCF_RESKEY_config_file"
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ ! -r "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_NOT_READABLE $OCF_RESKEY_config_file
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_postmaster_user" ]; then
+		clog_servicer_verify $CLOG_FAILED "Invalid User"
+		return $OCF_ERR_ARGS
+	fi
+
+	clog_service_verify $CLOG_SUCCEED
+		
+	return 0
+}
+
+generate_config_file()
+{
+	declare original_file="$1"
+	declare generated_file="$2"
+	declare ip_addressess="$3"
+	
+	declare ip_comma="";
+
+	if [ -f "$generated_file" ]; then
+		sha1_verify "$generated_file"
+		if [ $? -ne 0 ]; then
+			clog_check_sha1 $CLOG_FAILED
+			return 0
+		fi
+	fi	
+
+	clog_generate_config $CLOG_INIT "$original_file" "$generated_file"
+
+	declare x=1
+	for i in $ip_addressess; do
+		i=`echo $i | sed -e 's/\/.*$//'`
+		if [ $x -eq 1 ]; then
+			x=0
+			ip_comma=$i
+		else
+			ip_comma=$ip_comma,$i
+		fi 
+	done
+
+	generate_configTemplate "$generated_file" "$1"
+	echo "external_pid_file = '$PSQL_pid_file'" >> "$generated_file"
+	echo "listen_addresses = '$ip_comma'" >> "$generated_file"
+
+	echo >> "$generated_file"	
+	sed 's/^[[:space:]]*external_pid_file/### external_pid_file/i;s/^[[:space:]]*listen_addresses/### listen_addresses/i' < "$original_file" >> "$generated_file"
+	
+        sha1_addToFile "$generated_file"
+	clog_generate_config $CLOG_SUCCEED "$original_file" "$generated_file"
+               
+	return 0;
+}
+
+start()
+{
+	declare pguser_group
+	clog_service_start $CLOG_INIT
+
+	create_pid_directory
+	create_conf_directory "$PSQL_conf_dir"
+	check_pid_file "$PSQL_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_check_pid $CLOG_FAILED "$PSQL_pid_file"
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	#
+	# Create an empty PID file for the postgres user and
+	# change it to be owned by the postgres user so that
+	# postmaster doesn't complain.
+	#
+	pguser_group=`groups $OCF_RESKEY_postmaster_user | cut -f1 -d ' '`
+	touch $PSQL_pid_file
+	chown $OCF_RESKEY_postmaster_user.$pguser_group $PSQL_pid_file
+
+	clog_looking_for $CLOG_INIT "IP Addresses"
+
+        get_service_ip_keys "$OCF_RESKEY_service_name"
+        ip_addresses=`build_ip_list`
+
+	if [ -z "$ip_addresses" ]; then
+		clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Addresses"
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_looking_for $CLOG_SUCCEED "IP Addresses"
+
+	generate_config_file "$OCF_RESKEY_config_file" "$PSQL_gen_config_file" "$ip_addresses"
+
+	su - "$OCF_RESKEY_postmaster_user" -c "$PSQL_POSTMASTER -c config_file=\"$PSQL_gen_config_file\" \
+		$OCF_RESKEY_postmaster_options" &> /dev/null &
+
+	# We need to sleep for a second to allow pg_ctl to detect that we've started.
+	sleep $PSQL_wait_after_start
+	# We need to fetch "-D /path/to/pgsql/data" from $OCF_RESKEY_postmaster_options
+	su - "$OCF_RESKEY_postmaster_user" -c "$PSQL_CTL status $OCF_RESKEY_postmaster_options" &> /dev/null
+
+	if [ $? -ne 0 ]; then
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_start $CLOG_SUCCEED
+	return 0;
+}
+
+stop()
+{
+	clog_service_stop $CLOG_INIT
+
+	## Send -INT to close connections and stop.  -QUIT is used if -INT signal does not stop process.
+	stop_generic_sigkill "$PSQL_pid_file" "$PSQL_stop_timeout" "$PSQL_kill_timeout" "-INT"
+	if [ $? -ne 0 ]; then
+		clog_service_stop $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_service_stop $CLOG_SUCCEED
+	return 0;
+}
+
+status()
+{
+	clog_service_status $CLOG_INIT
+
+	status_check_pid "$PSQL_pid_file"
+	if [ $? -ne 0 ]; then
+		clog_service_status $CLOG_FAILED "$PSQL_pid_file"
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_status $CLOG_SUCCEED
+	return 0
+}
+
+case $1 in
+	meta-data)
+		cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+		exit 0
+		;;
+	validate-all)
+		verify_all
+		exit $?
+		;;
+	start)
+		verify_all && start
+		exit $?
+		;;
+	stop)
+		verify_all && stop
+		exit $?
+		;;
+	status|monitor)
+		verify_all
+		status
+		exit $?
+		;;
+	restart)
+		verify_all
+		stop
+		start
+		exit $?
+		;;
+	*)
+		echo "Usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
diff --git a/rgmanager/src/resources/ra-api-1-modified.dtd b/rgmanager/src/resources/ra-api-1-modified.dtd
new file mode 100644
index 0000000..67eb94d
--- /dev/null
+++ b/rgmanager/src/resources/ra-api-1-modified.dtd
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<!-- This is based on the RA-API-1.0 DTD from:
+     http://www.opencf.org/cgi-bin/viewcvs.cgi/specs/ra/ra-api-1.dtd
+
+     There are additions for rgmanager.  These additions should be
+     ignored by other RMs.
+ -->
+
+<!ELEMENT resource-agent (version,longdesc,shortdesc,parameters,actions,special*) >
+<!ATTLIST resource-agent
+	name	CDATA	#REQUIRED
+	version CDATA   #IMPLIED>
+
+<!ELEMENT version (#PCDATA)>
+
+<!ELEMENT parameters (parameter*)>
+
+<!ELEMENT actions (action*)>
+
+<!-- Primary and required are for rgmanager use. -->
+<!ELEMENT parameter (longdesc+,shortdesc+,content)>
+<!ATTLIST parameter
+	name	CDATA	#REQUIRED
+	primary (1|0)   "0"
+	required (1|0)	"0"
+	inherit CDATA	""
+	unique	(1|0)	"0"
+	reconfig (1|0)  "0">
+
+<!ELEMENT longdesc ANY>
+<!ATTLIST longdesc
+	lang	NMTOKEN	#IMPLIED>
+
+<!ELEMENT shortdesc ANY>
+<!ATTLIST shortdesc
+	lang	NMTOKEN	#IMPLIED>
+
+<!ELEMENT content EMPTY>
+<!ATTLIST content
+	type	(string|integer|boolean)	#REQUIRED
+	default CDATA	#IMPLIED>
+
+<!ELEMENT action EMPTY>
+<!ATTLIST action
+	name	(start|stop|recover|status|reconfig|monitor|reload|meta-data|validate-all|verify-all|migrate|methods)	#REQUIRED
+	timeout		CDATA	#REQUIRED
+	interval 	CDATA	#IMPLIED
+	start-delay 	CDATA	#IMPLIED
+	depth		CDATA	#IMPLIED>
+
+<!-- Special tag list for rgmanager -->
+<!ELEMENT special (attributes*, child*)>
+<!ATTLIST special
+	tag	CDATA	#REQUIRED>
+
+<!ELEMENT attributes EMPTY>
+<!ATTLIST attributes
+	maxinstances CDATA "0"
+	init_on_add CDATA "0"
+	destroy_on_delete CDATA "0">
+
+<!ELEMENT child EMPTY>
+<!ATTLIST child
+	type CDATA #REQUIRED
+	forbid (1|0) "0"
+	start CDATA "100"
+	stop CDATA "0">
diff --git a/rgmanager/src/resources/ra2man.xsl b/rgmanager/src/resources/ra2man.xsl
new file mode 100644
index 0000000..095a7b3
--- /dev/null
+++ b/rgmanager/src/resources/ra2man.xsl
@@ -0,0 +1,158 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text" indent="no"/>
+
+<xsl:template match="parameter">
+.TP
+.B <xsl:value-of select="@name"/><xsl:text>
+</xsl:text>
+<xsl:value-of select="normalize-space(longdesc)"/><xsl:text>
+</xsl:text>
+<xsl:if test="@primary = 1">This is the defining attribute for the <b><xsl:value-of select="/resource-agent/@name"/></b> resource type, and will be shown in logs.
+</xsl:if>
+<xsl:if test="@unique = 1 or @primary = 1">No other instances of the 
+.B <xsl:value-of select="/resource-agent/@name"/>
+resource may have the same value for the 
+.B <xsl:value-of select="@name"/>
+parameter.
+</xsl:if>
+<xsl:if test="@required = 1 or @primary = 1">This parameter is required; the resource manager will ignore specification of a resource without this parameter.</xsl:if>
+<xsl:if test="@reconfig = 1">You may safely change this attribute on the fly; doing so will not cause a restart of the resource or its children.
+</xsl:if>
+Content: <xsl:value-of select="content/@type"/><xsl:text>
+</xsl:text>
+<xsl:if test="content/@default">Default Value: <xsl:value-of select="content/@default"/>
+</xsl:if>
+</xsl:template>
+
+<xsl:template match="action">
+.TP
+\fB<xsl:value-of select="@name"/>\fp<xsl:if test="@timeout"> (timeout: <xsl:value-of select="@timeout"/>) </xsl:if>
+<xsl:choose>
+<xsl:when test="@name = 'start'">
+This starts the resource.
+</xsl:when>
+<xsl:when test="@name = 'stop'">
+This stops the resource.
+</xsl:when>
+<xsl:when test="@name = 'monitor'">
+<xsl:if test="@depth">
+Depth <xsl:value-of select="@depth"/>.
+</xsl:if>
+This checks the status of the resource.  This is specified in the OCF Resource Agent API, but not LSB compliant.  This is synonymous with
+.B status
+on some resource managers.
+</xsl:when>
+<xsl:when test="@name = 'validate-all'">
+Given (minimally) all required parameters to start or check the status of the resource, validate that those parameters are correct as much as possible.
+</xsl:when>
+<xsl:when test="@name = 'meta-data'">
+Display the XML metadata describing this resource.
+</xsl:when>
+<xsl:when test="@name = 'reload'">Reconfigure the resource in-place with the new given parameters.
+</xsl:when>
+<xsl:when test="@name = 'recover'">
+Attempt to recover the resource in-place without affecting dependencies.  If this fails, the resource manager will try more forceful recovery (such as stop-start).
+</xsl:when>
+<!-- known non-OCF stuff -->
+<xsl:when test="@name = 'status'">
+<xsl:if test="@depth">Depth <xsl:value-of select="@depth"/>.
+</xsl:if>
+This checks the status of the resource.  This is LSB compliant, but not specified by the OCF Resource Agent API.  This is synonymous with
+.B monitor
+on some resource managers.
+</xsl:when>
+<xsl:when test="@name = 'reconfig'">
+Reconfigure the resource in-place with the new given parameters.
+</xsl:when>
+<xsl:when test="@name = 'verify-all'">
+Given (minimally) all required parameters to start or check the status of the resource, validate that those parameters are correct as much as possible.  This is a misinterpretation of the 
+.B validate-all
+action, and should be fixed.  Please report a bug.
+</xsl:when>
+<xsl:when test="@name = 'promote'">
+If this resource was the slave instance of the
+resource, promote it to master status.
+</xsl:when>
+<xsl:when test="@name = 'demote'">
+If this resource was the master instance of the
+resource, demote it to slave status.
+</xsl:when>
+<xsl:when test="@name = 'migrate'">
+Migrate this resource to another node in the cluster.
+</xsl:when>
+<!-- Ehhh -->
+<xsl:otherwise>
+The operational behavior of this is not known.
+</xsl:otherwise>
+</xsl:choose>
+</xsl:template>
+
+<xsl:template match="child">
+.PP
+<xsl:value-of select="@type"/> -
+Started at level <xsl:value-of select="@start"/>.
+Stopped at level <xsl:value-of select="@stop"/>.
+</xsl:template>
+<xsl:template match="/resource-agent">.TH RESOURCE_AGENT 8 2009-01-20 "<xsl:value-of select="@name"/> (Resource Agent)"
+.SH
+<xsl:value-of select="@name"/>
+Cluster Resource Agent
+
+.SH DESCRIPTION
+<xsl:value-of select="normalize-space(longdesc)"/>
+
+.SH PARAMETERS
+<xsl:apply-templates select="parameters"/>
+
+.SH RGMANAGER INTERNAL PARAMETERS
+.TP
+.B __enforce_timeouts
+If set to 1, an operation exceeding the defined timeout will be considered
+a failure of that operation.  Note that fail-to-stop is critical, and causes
+a service to enter the failed state.
+
+.TP
+.B __independent_subtree
+If set to 1, failure of a status operation of this resource or any of its
+children will be considered non-fatal unless a restart of this resource and
+all of its children also fails.
+
+.SH ACTIONS
+<xsl:apply-templates select="actions"/>
+
+.SH RGMANAGER NOTES
+<xsl:if test="special/@tag = 'rgmanager'">
+<xsl:if test="special/attributes/@maxinstances">
+.PP
+An instatnce of this resource defined in the
+.B <resources>
+section of
+.B cluster.conf
+can be referenced in the resource
+tree at most <xsl:value-of select="special/attributes/@maxinstances"/>
+time(s).  All subsequent references to this resource will be ignored.
+</xsl:if>
+<xsl:if test="special/attributes/@root">
+.PP
+This is the root resource class.  Other resource 
+types must be attached as children to this resource
+class.
+</xsl:if>
+<xsl:if test="special/child/@type">
+.PP
+Known Child Types:
+<xsl:apply-templates select="special"/>
+</xsl:if>
+</xsl:if>
+.SH REFERENCES
+.PP
+http://www.opencf.org/cgi-bin/viewcvs.cgi/specs/ra/resource-agent-api.txt?rev=HEAD - The Open Cluster Framework Resource Agent Application Programming Interface draft version 1.0
+
+.PP
+http://www.linux-foundation.org/spec/refspecs/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html - Linux Standards Base v3.1.0 - Init Script Actions
+
+.PP
+http://sources.redhat.com/cluster/wiki/RGManager - Linux-cluster Resource Group Manager information
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/rgmanager/src/resources/ra2ref.xsl b/rgmanager/src/resources/ra2ref.xsl
new file mode 100644
index 0000000..6e61073
--- /dev/null
+++ b/rgmanager/src/resources/ra2ref.xsl
@@ -0,0 +1,10 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text" indent="yes"/>
+<xsl:template name="capitalize">
+	<xsl:param name="value"/>
+	<xsl:variable name="normalized" select="translate($value, '_abcdefghijklmnopqrstuvwrxyz', '-ABCDEFGHIJKLMNOPQRSTUVWRXYZ')"/>
+	<xsl:value-of select="$normalized"/>
+</xsl:template>
+<xsl:template match="/resource-agent">
+        <ref name="<xsl:call-template name="capitalize"><xsl:with-param name="value" select="@name"/></xsl:call-template>"/></xsl:template>
+</xsl:stylesheet>
diff --git a/rgmanager/src/resources/ra2rng.xsl b/rgmanager/src/resources/ra2rng.xsl
new file mode 100644
index 0000000..e53595e
--- /dev/null
+++ b/rgmanager/src/resources/ra2rng.xsl
@@ -0,0 +1,330 @@
+<xsl:stylesheet version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:int="__internal__"
+    exclude-result-prefixes="int">
+    <xsl:output method="text" indent="no"/>
+
+<xsl:param name="init-indent" select="'  '"/>
+<xsl:param name="indent" select="'  '"/>
+
+
+<!--
+  helpers
+  -->
+
+<int:common-optional-parameters>
+    <int:parameter name="__independent_subtree">
+        <int:shortdesc>
+            Treat this and all children as an independent subtree.
+        </int:shortdesc>
+    </int:parameter>
+    <int:parameter name="__enforce_timeouts">
+        <int:shortdesc>
+            Consider a timeout for operations as fatal.
+        </int:shortdesc>
+    </int:parameter>
+    <int:parameter name="__max_failures">
+        <int:shortdesc>
+            Maximum number of failures before returning a failure to
+            a status check.
+        </int:shortdesc>
+    </int:parameter>
+    <int:parameter name="__failure_expire_time">
+        <int:shortdesc>
+            Amount of time before a failure is forgotten.
+        </int:shortdesc>
+    </int:parameter>
+    <int:parameter name="__max_restarts">
+        <int:shortdesc>
+            Maximum number restarts for an independent subtree before
+            giving up.
+        </int:shortdesc>
+    </int:parameter>
+    <int:parameter name="__restart_expire_time">
+        <int:shortdesc>
+            Amount of time before a failure is forgotten for
+            an independent subtree.
+        </int:shortdesc>
+    </int:parameter>
+</int:common-optional-parameters>
+
+<xsl:variable name="SP" select="' '"/>
+<xsl:variable name="NL" select="'&#xA;'"/>
+<xsl:variable name="NLNL" select="'&#xA;&#xA;'"/>
+<xsl:variable name="Q" select="'"'"/>
+<xsl:variable name="TS" select="'<'"/>
+<xsl:variable name="TSc" select="'</'"/>
+<xsl:variable name="TE" select="'>'"/>
+<xsl:variable name="TEc" select="'/>'"/>
+
+<xsl:template name="comment">
+    <xsl:param name="text" select="''"/>
+    <xsl:param name="indent" select="''"/>
+    <xsl:if test="$indent != 'none'">
+        <xsl:value-of select="concat($init-indent, $indent)"/>
+    </xsl:if>
+    <xsl:value-of select="concat($TS, '!-- ', $text, ' --',$TE)"/>
+</xsl:template>
+
+<xsl:template name="tag-start">
+    <xsl:param name="name"/>
+    <xsl:param name="attrs" select="''"/>
+    <xsl:param name="indent" select="''"/>
+    <xsl:if test="$indent != 'none'">
+        <xsl:value-of select="concat($init-indent, $indent)"/>
+    </xsl:if>
+    <xsl:value-of select="concat($TS, $name)"/>
+    <xsl:if test="$attrs != ''">
+        <xsl:value-of select="concat($SP, $attrs)"/>
+    </xsl:if>
+    <xsl:value-of select="$TE"/>
+</xsl:template>
+
+<xsl:template name="tag-end">
+    <xsl:param name="name"/>
+    <xsl:param name="attrs" select="''"/>
+    <xsl:param name="indent" select="''"/>
+    <xsl:if test="$indent != 'none'">
+        <xsl:value-of select="concat($init-indent, $indent)"/>
+    </xsl:if>
+    <xsl:value-of select="concat($TSc, $name)"/>
+    <xsl:if test="$attrs != ''">
+        <xsl:value-of select="concat($SP, $attrs)"/>
+    </xsl:if>
+    <xsl:value-of select="$TE"/>
+</xsl:template>
+
+<xsl:template name="tag-self">
+    <xsl:param name="name"/>
+    <xsl:param name="attrs" select="''"/>
+    <xsl:param name="indent" select="''"/>
+    <xsl:if test="$indent != 'none'">
+        <xsl:value-of select="concat($init-indent, $indent)"/>
+    </xsl:if>
+    <xsl:value-of select="concat($TS, $name)"/>
+    <xsl:if test="$attrs != ''">
+        <xsl:value-of select="concat($SP, $attrs)"/>
+    </xsl:if>
+    <xsl:value-of select="$TEc"/>
+</xsl:template>
+
+<xsl:template name="capitalize">
+    <xsl:param name="value"/>
+    <xsl:value-of select="translate($value,
+                                    '_abcdefghijklmnopqrstuvwrxyz',
+                                    '-ABCDEFGHIJKLMNOPQRSTUVWRXYZ')"/>
+</xsl:template>
+
+
+<!--
+  proceed
+  -->
+
+<xsl:template match="/resource-agent">
+    <xsl:value-of select="$NL"/>
+
+    <!-- define name=... (start) -->
+    <xsl:variable name="capitalized">
+        <xsl:call-template name="capitalize">
+            <xsl:with-param name="value" select="@name"/>
+        </xsl:call-template>
+    </xsl:variable>
+    <xsl:call-template name="tag-start">
+        <xsl:with-param name="name" select="'define'"/>
+        <xsl:with-param name="attrs" select="concat(
+            'name=', $Q, $capitalized, $Q)"/>
+    </xsl:call-template>
+    <xsl:value-of select="$NL"/>
+
+        <!-- element name=... rha:description=... (start) -->
+        <xsl:call-template name="tag-start">
+            <xsl:with-param name="name" select="'element'"/>
+            <xsl:with-param name="attrs" select="concat(
+                'name=',            $Q, @name,                      $Q, $SP,
+                'rha:description=', $Q, normalize-space(shortdesc), $Q)"/>
+            <xsl:with-param name="indent" select="$indent"/>
+        </xsl:call-template>
+        <xsl:value-of select="$NL"/>
+
+            <!-- choice (start) -->
+            <xsl:call-template name="tag-start">
+                <xsl:with-param name="name" select="'choice'"/>
+                <xsl:with-param name="indent" select="concat($indent, $indent)"/>
+            </xsl:call-template>
+            <xsl:value-of select="$NL"/>
+
+                <!-- group (start) -->
+                <xsl:call-template name="tag-start">
+                    <xsl:with-param name="name" select="'group'"/>
+                    <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                 $indent)"/>
+                </xsl:call-template>
+                <xsl:value-of select="$NL"/>
+
+                    <!-- (comment) -->
+                    <xsl:call-template name="comment">
+                        <xsl:with-param name="text">
+                            <xsl:text>rgmanager specific stuff</xsl:text>
+                        </xsl:with-param>
+                        <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                     $indent, $indent)"/>
+                    </xsl:call-template>
+                    <xsl:value-of select="$NL"/>
+
+                    <!-- attribute name="ref" -->
+                    <xsl:call-template name="tag-self">
+                        <xsl:with-param name="name" select="'attribute'"/>
+                        <xsl:with-param name="attrs" select="concat(
+                            'name=',            $Q, 'ref',                    $Q, $SP,
+                            'rha:description=', $Q, 'Reference to existing ',
+                                                    @name, ' resource in ',
+                                                    'the resources section.', $Q)"/>
+                        <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                     $indent, $indent)"/>
+                    </xsl:call-template>
+                    <xsl:value-of select="$NL"/>
+
+                <!-- group (end) -->
+                <xsl:call-template name="tag-end">
+                    <xsl:with-param name="name" select="'group'"/>
+                    <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                 $indent)"/>
+                </xsl:call-template>
+                <xsl:value-of select="$NL"/>
+
+                <!-- group (start) -->
+                <xsl:call-template name="tag-start">
+                    <xsl:with-param name="name" select="'group'"/>
+                    <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                 $indent)"/>
+                </xsl:call-template>
+                <xsl:value-of select="$NL"/>
+
+                <xsl:for-each select="parameters/parameter">
+                    <xsl:choose>
+                        <xsl:when test="@required = '1' or @primary = '1'">
+                            <!-- attribute name=... rha:description=... -->
+                            <xsl:call-template name="tag-self">
+                                <xsl:with-param name="name" select="'attribute'"/>
+                                <xsl:with-param name="attrs" select="concat(
+                                    'name=',            $Q, @name,                      $Q, $SP,
+                                    'rha:description=', $Q, normalize-space(shortdesc), $Q)"/>
+                                <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                             $indent, $indent)"/>
+                            </xsl:call-template>
+                            <xsl:value-of select="$NL"/>
+                        </xsl:when>
+                        <xsl:otherwise>
+                            <!-- optional (start) -->
+                            <xsl:call-template name="tag-start">
+                                <xsl:with-param name="name" select="'optional'"/>
+                                <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                             $indent, $indent)"/>
+                            </xsl:call-template>
+                            <xsl:value-of select="$NL"/>
+
+                                <!-- attribute name=... rha:description=... -->
+                                <xsl:call-template name="tag-self">
+                                    <xsl:with-param name="name" select="'attribute'"/>
+                                    <xsl:with-param name="attrs" select="concat(
+                                        'name=',            $Q, @name,                      $Q, $SP,
+                                        'rha:description=', $Q, normalize-space(shortdesc), $Q)"/>
+                                    <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                                 $indent, $indent,
+                                                                                 $indent)"/>
+                                </xsl:call-template>
+                                <xsl:value-of select="$NL"/>
+
+                            <!-- optional (end) -->
+                            <xsl:call-template name="tag-end">
+                                <xsl:with-param name="name" select="'optional'"/>
+                                <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                             $indent, $indent)"/>
+                            </xsl:call-template>
+                            <xsl:value-of select="$NL"/>
+                        </xsl:otherwise>
+                    </xsl:choose>
+                </xsl:for-each>
+
+                <!-- group (end) -->
+                <xsl:call-template name="tag-end">
+                    <xsl:with-param name="name" select="'group'"/>
+                    <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                 $indent)"/>
+                </xsl:call-template>
+                <xsl:value-of select="$NL"/>
+
+            <!-- choice (end) -->
+            <xsl:call-template name="tag-end">
+                <xsl:with-param name="name" select="'choice'"/>
+                <xsl:with-param name="indent" select="concat($indent, $indent)"/>
+            </xsl:call-template>
+            <xsl:value-of select="$NL"/>
+
+            <xsl:for-each select="document('')/*/int:common-optional-parameters/int:parameter">
+                <!-- optional (start) -->
+                <xsl:call-template name="tag-start">
+                    <xsl:with-param name="name" select="'optional'"/>
+                    <xsl:with-param name="indent" select="concat($indent, $indent)"/>
+                </xsl:call-template>
+                <xsl:value-of select="$NL"/>
+
+                    <!-- attribute name=... rha:description=... -->
+                    <xsl:call-template name="tag-self">
+                        <xsl:with-param name="name" select="'attribute'"/>
+                        <xsl:with-param name="attrs" select="concat(
+                            'name=',            $Q, @name,                          $Q, $SP,
+                            'rha:description=', $Q, normalize-space(int:shortdesc), $Q)"/>
+                        <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                     $indent)"/>
+                    </xsl:call-template>
+                    <xsl:value-of select="$NL"/>
+
+                <!-- optional (end) -->
+                <xsl:call-template name="tag-end">
+                    <xsl:with-param name="name" select="'optional'"/>
+                    <xsl:with-param name="indent" select="concat($indent, $indent)"/>
+                </xsl:call-template>
+                <xsl:value-of select="$NL"/>
+            </xsl:for-each>
+
+            <!-- optional (start) -->
+            <xsl:call-template name="tag-start">
+                <xsl:with-param name="name" select="'optional'"/>
+                <xsl:with-param name="indent" select="concat($indent, $indent)"/>
+            </xsl:call-template>
+            <xsl:value-of select="$NL"/>
+
+                <!-- ref name="CHILDREN" -->
+                <xsl:call-template name="tag-self">
+                    <xsl:with-param name="name" select="'ref'"/>
+                    <xsl:with-param name="attrs" select="concat(
+                        'name=', $Q, 'CHILDREN', $Q)"/>
+                    <xsl:with-param name="indent" select="concat($indent, $indent,
+                                                                 $indent)"/>
+                </xsl:call-template>
+                <xsl:value-of select="$NL"/>
+
+            <!-- optional (end) -->
+            <xsl:call-template name="tag-end">
+                <xsl:with-param name="name" select="'optional'"/>
+                <xsl:with-param name="indent" select="concat($indent, $indent)"/>
+            </xsl:call-template>
+            <xsl:value-of select="$NL"/>
+
+        <!-- element (end) -->
+        <xsl:call-template name="tag-end">
+            <xsl:with-param name="name" select="'element'"/>
+            <xsl:with-param name="indent" select="$indent"/>
+        </xsl:call-template>
+        <xsl:value-of select="$NL"/>
+
+    <!-- define (end) -->
+    <xsl:call-template name="tag-end">
+        <xsl:with-param name="name" select="'define'"/>
+    </xsl:call-template>
+    <xsl:value-of select="$NLNL"/>
+
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/rgmanager/src/resources/resources.rng.head b/rgmanager/src/resources/resources.rng.head
new file mode 100644
index 0000000..49db15b
--- /dev/null
+++ b/rgmanager/src/resources/resources.rng.head
@@ -0,0 +1 @@
+<!-- Autogenerated resources definitions -->
diff --git a/rgmanager/src/resources/resources.rng.mid b/rgmanager/src/resources/resources.rng.mid
new file mode 100644
index 0000000..cc2dff3
--- /dev/null
+++ b/rgmanager/src/resources/resources.rng.mid
@@ -0,0 +1,3 @@
+  <define name="CHILDREN">
+    <zeroOrMore>
+     <choice>
diff --git a/rgmanager/src/resources/resources.rng.tail b/rgmanager/src/resources/resources.rng.tail
new file mode 100644
index 0000000..4434631
--- /dev/null
+++ b/rgmanager/src/resources/resources.rng.tail
@@ -0,0 +1,23 @@
+
+      <ref name="RESOURCEACTION"/>
+     </choice>
+    </zeroOrMore>
+  </define>
+
+  <define name="RESOURCEACTION">
+   <zeroOrMore>
+    <element name="action" rha:description="Overrides resource action timings for a resource instance.">
+     <attribute name="name" rha:description="Name of resource action (start, stop, status, etc.)."/>
+     <optional>
+      <attribute name="depth" rha:description="Status check depth (resource agent dependent; * = all depths)."/>
+     </optional>
+     <optional>
+      <attribute name="interval" rha:description="Status check interval."/>
+     </optional>
+     <optional>
+      <attribute name="timeout" rha:description="Action timeout.  Meaningless unless __enforce_timeouts is set for this resource."/>
+     </optional>
+    </element>
+   </zeroOrMore>
+  </define>
+<!-- End autogenerated resources definitions -->
diff --git a/rgmanager/src/resources/samba.metadata b/rgmanager/src/resources/samba.metadata
new file mode 100644
index 0000000..1e03fcd
--- /dev/null
+++ b/rgmanager/src/resources/samba.metadata
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+<resource-agent version="rgmanager 2.0" name="samba">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+    	Dynamic smbd/nmbd resource agent
+    </longdesc>
+    <shortdesc lang="en">
+    	Dynamic smbd/nmbd resource agent
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" unique="1" primary="1">
+            <longdesc lang="en">
+                Samba Symbolic Name.
+            </longdesc>
+            <shortdesc lang="en">
+                Samba Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="config_file">
+            <longdesc lang="en">
+                Define absolute path to configuration file
+            </longdesc>
+            <shortdesc lang="en">
+                Config File
+            </shortdesc>
+	    <content type="string" default="/etc/samba/smb.conf"/>
+        </parameter>
+
+	<parameter name="smbd_options">
+		<longdesc lang="en">
+			Other command-line options for smbd
+		</longdesc>
+		<shortdesc lang="en">
+			Other command-line options for smbd
+		</shortdesc>
+		<content type="string" />
+	</parameter>
+
+	<parameter name="nmbd_options">
+		<longdesc lang="en">
+			Other command-line options for nmbd
+		</longdesc>
+		<shortdesc lang="en">
+			Other command-line options for nmbd
+		</shortdesc>
+		<content type="string" />
+	</parameter>
+
+	<parameter name="shutdown_wait">
+		<longdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</longdesc>
+		<shortdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</shortdesc>
+		<content type="integer" />
+	</parameter>
+
+        <parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+	    	Inherit the service name.  We need to know
+		the service name in order to determine file
+		systems and IPs for this smb service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Inherit the service name.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="0"/>
+        <action name="stop" timeout="0"/>
+
+	<!-- This is just a wrapper for LSB init scripts, so monitor
+	     and status can't have a timeout, nor do they do any extra
+	     work regardless of the depth -->
+        <action name="status" interval="30s" timeout="0"/>
+        <action name="monitor" interval="30s" timeout="0"/>
+
+        <action name="meta-data" timeout="0"/>
+        <action name="validate-all" timeout="0"/>
+    </actions>
+</resource-agent>
diff --git a/rgmanager/src/resources/samba.sh b/rgmanager/src/resources/samba.sh
new file mode 100755
index 0000000..d4d0736
--- /dev/null
+++ b/rgmanager/src/resources/samba.sh
@@ -0,0 +1,241 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+export LC_ALL=C
+export LANG=C
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+declare SAMBA_SMBD=/usr/sbin/smbd
+declare SAMBA_NMBD=/usr/sbin/nmbd
+declare SAMBA_pid_dir="`generate_name_for_pid_dir`"
+declare SAMBA_conf_dir="`generate_name_for_conf_dir`"
+declare SAMBA_smbd_pid_file="$SAMBA_pid_dir/smbd-smb.conf.pid"
+declare SAMBA_nmbd_pid_file="$SAMBA_pid_dir/nmbd-smb.conf.pid"
+declare SAMBA_gen_config_file="$SAMBA_conf_dir/smb.conf"
+
+verify_all()
+{
+	clog_service_verify $CLOG_INIT
+
+	if [ -z "$OCF_RESKEY_name" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid Name Of Service"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_service_name" ]; then
+		clog_service_verify $CLOG_FAILED_NOT_CHILD
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_INVALID "$OCF_RESKEY_config_file"
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ ! -r "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_NOT_READABLE $OCF_RESKEY_config_file
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	clog_service_verify $CLOG_SUCCEED
+		
+	return 0
+}
+
+generate_config_file()
+{
+	declare original_file="$1"
+	declare generated_file="$2"
+	declare ip_addresses="$3"
+
+	if [ -f "$generated_file" ]; then
+		sha1_verify "$generated_file"
+		if [ $? -ne 0 ]; then
+			clog_check_sha1 $CLOG_FAILED
+			return 0
+		fi
+	fi	
+
+	clog_generate_config $CLOG_INIT "$original_file" "$generated_file"
+
+	generate_configTemplate "$generated_file" "$1"
+
+	echo "pid directory = \"$SAMBA_pid_dir\"" >> "$generated_file"
+	echo "interfaces = $ip_addresses" >> "$generated_file"
+	echo "bind interfaces only = Yes" >> "$generated_file"
+	echo "netbios name = ${OCF_RESKEY_name/ /_}" >> "$generated_file"
+	echo >> "$generated_file"	
+	sed 's/^[[:space:]]*pid directory/### pid directory/i;s/^[[:space:]]*interfaces/### interfaces/i;s/^[[:space:]]*bind interfaces only/### bind interfaces only/i;s/^[[:space:]]*netbios name/### netbios name/i' \
+	     < "$original_file" >> "$generated_file"
+	
+        sha1_addToFile "$generated_file"
+	clog_generate_config $CLOG_SUCCEED "$original_file" "$generated_file"
+               
+	return 0;
+}
+
+start()
+{
+	clog_service_start $CLOG_INIT
+
+	create_pid_directory
+	mkdir -p "$SAMBA_pid_dir"
+	create_conf_directory "$SAMBA_conf_dir"
+	check_pid_file "$SAMBA_smbd_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_check_pid $CLOG_FAILED "$SAMBA_smbd_pid_file"
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	check_pid_file "$SAMBA_nmbd_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_check_pid $CLOG_FAILED "$SAMBA_nmbd_pid_file"
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_looking_for $CLOG_INIT "IP Addresses"
+
+        get_service_ip_keys "$OCF_RESKEY_service_name"
+        ip_addresses=`build_ip_list`
+
+	if [ -z "$ip_addresses" ]; then
+		clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Addresses"
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_looking_for $CLOG_SUCCEED "IP Addresses"
+
+	generate_config_file "$OCF_RESKEY_config_file" "$SAMBA_gen_config_file" "$ip_addresses"
+
+	$SAMBA_SMBD -D -s "$SAMBA_gen_config_file" $OCF_RESKEY_smbd_options
+
+	if [ $? -ne 0 ]; then
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	$SAMBA_NMBD -D -s "$SAMBA_gen_config_file" $OCF_RESKEY_nmbd_options	
+
+	if [ $? -ne 0 ]; then
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	 
+	clog_service_start $CLOG_SUCCEED
+
+	return 0;
+}
+
+stop()
+{
+	clog_service_stop $CLOG_INIT
+
+	stop_generic "$SAMBA_smbd_pid_file" "$OCF_RESKEY_shutdown_wait"
+	
+	if [ $? -ne 0 ]; then
+		clog_service_stop $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	stop_generic "$SAMBA_nmbd_pid_file"
+	
+	if [ $? -ne 0 ]; then
+		clog_service_stop $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	if [ -e "$SAMBA_smbd_pid_file" ]; then
+		rm -f "$SAMBA_smbd_pid_file"
+	fi
+
+	if [ -e "$SAMBA_nmbd_pid_file" ]; then
+		rm -f "$SAMBA_nmbd_pid_file"
+	fi
+	
+	clog_service_stop $CLOG_SUCCEED
+	return 0;
+}
+
+status()
+{
+	clog_service_status $CLOG_INIT
+
+	status_check_pid "$SAMBA_smbd_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_service_status $CLOG_FAILED "$SAMBA_smbd_pid_file"
+		return $OCF_ERR_GENERIC
+	fi
+
+	status_check_pid "$SAMBA_nmbd_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_service_status $CLOG_FAILED "$SAMBA_nmbd_pid_file"
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_status $CLOG_SUCCEED
+	return 0
+}
+
+case $1 in
+	meta-data)
+		cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+		exit 0
+		;;
+	validate-all)
+		verify_all
+		exit $?
+		;;
+	start)
+		verify_all && start
+		exit $?
+		;;
+	stop)
+		verify_all && stop
+		exit $?
+		;;
+	status|monitor)
+		verify_all
+		status
+		exit $?
+		;;
+	restart)
+		verify_all
+		stop
+		start
+		exit $?
+		;;
+	*)
+		echo "Usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
diff --git a/rgmanager/src/resources/script.sh b/rgmanager/src/resources/script.sh
new file mode 100755
index 0000000..fa3b412
--- /dev/null
+++ b/rgmanager/src/resources/script.sh
@@ -0,0 +1,171 @@
+#!/bin/bash
+
+#
+# Script to handle a non-OCF script (e.g. a normal init-script)
+#
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+LC_ALL=C
+LANG=C
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export LC_ALL LANG PATH
+
+. $(dirname $0)/ocf-shellfuncs
+
+meta_data()
+{
+    cat <<EOT
+<?xml version="1.0"?>
+<resource-agent version="rgmanager 2.0" name="script">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        The script resource allows a standard LSB-compliant init script
+	to be used to start a clustered service.
+    </longdesc>
+    <shortdesc lang="en">
+        LSB-compliant init script as a clustered resource.
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" unique="1" primary="1">
+            <longdesc lang="en">
+                Name
+            </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="file" unique="1" required="1">
+            <longdesc lang="en">
+                Path to script
+            </longdesc>
+            <shortdesc lang="en">
+                Path to script
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+	    	Inherit the service name, in case the
+		script wants to know this information.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Inherit the service name.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="0"/>
+        <action name="stop" timeout="0"/>
+
+	<!-- This is just a wrapper for LSB init scripts, so monitor
+	     and status can't have a timeout, nor do they do any extra
+	     work regardless of the depth -->
+        <action name="status" interval="30s" timeout="0"/>
+        <action name="monitor" interval="30s" timeout="0"/>
+
+        <action name="meta-data" timeout="0"/>
+        <action name="validate-all" timeout="0"/>
+    </actions>
+</resource-agent>
+EOT
+}
+
+validate_all()
+{
+	if [ -z "${OCF_RESKEY_file}" ]; then
+		ocf_log err "No file provided"
+		return $OCF_ERR_ARGS      # Invalid Argument
+	fi
+
+	if ! [ -e "${OCF_RESKEY_file}" ]; then
+		ocf_log err "${OCF_RESKEY_file} does not exist"
+		return $OCF_ERR_INSTALLED # Program not installed
+	fi
+
+	if [ -b "${OCF_RESKEY_file}" ]; then
+		ocf_log err "${OCF_RESKEY_file} is a block device"
+		return $OCF_ERR_ARGS      # Invalid Argument
+	fi
+
+	if [ -d "${OCF_RESKEY_file}" ]; then
+		ocf_log err "${OCF_RESKEY_file} is a directory"
+		return $OCF_ERR_ARGS      # Invalid Argument
+	fi
+
+	if [ -c "${OCF_RESKEY_file}" ]; then
+		ocf_log err "${OCF_RESKEY_file} is a character device"
+		return $OCF_ERR_ARGS      # Invalid Argument
+	fi
+
+	if [ -p "${OCF_RESKEY_file}" ]; then
+		ocf_log err "${OCF_RESKEY_file} is a named pipe"
+		return $OCF_ERR_ARGS      # Invalid Argument
+	fi
+
+	if [ -S "${OCF_RESKEY_file}" ]; then
+		ocf_log err "${OCF_RESKEY_file} is a socket"
+		return $OCF_ERR_ARGS      # Invalid Argument
+	fi
+
+	if ! [ -s "${OCF_RESKEY_file}" ]; then
+		ocf_log err "${OCF_RESKEY_file} is empty"
+		return $OCF_ERR_GENERIC   # ???
+	fi
+
+	if ! [ -x "${OCF_RESKEY_file}" ]; then
+		ocf_log err "${OCF_RESKEY_file} is not executable"
+		return $OCF_ERR_PERM
+	fi
+
+	return 0
+}
+
+case $1 in
+	meta-data)
+		meta_data
+		exit 0
+		;;
+	validate-all)
+		validate_all
+		exit $?
+		;;
+	*)
+		;;
+esac
+
+
+validate_all || exit $?
+
+# Execute the script
+ocf_log info "Executing ${OCF_RESKEY_file} $1"
+${OCF_RESKEY_file} $1
+
+declare -i rv=$?
+if [ $rv -ne 0 ]; then
+	ocf_log err "script:$OCF_RESKEY_name: $1 of $OCF_RESKEY_file failed (returned $rv)"
+	exit $OCF_ERR_GENERIC
+fi
diff --git a/rgmanager/src/resources/service.sh b/rgmanager/src/resources/service.sh
new file mode 100755
index 0000000..9b6ccc9
--- /dev/null
+++ b/rgmanager/src/resources/service.sh
@@ -0,0 +1,300 @@
+#!/bin/bash
+
+#
+# Dummy OCF script for resource group
+#
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+# Grab nfs lock tricks if available
+export NFS_TRICKS=1
+if [ -f "$(dirname $0)/svclib_nfslock" ]; then
+	. $(dirname $0)/svclib_nfslock
+	NFS_TRICKS=0
+fi
+
+meta_data()
+{
+    cat <<EOT
+<?xml version="1.0"?>
+<resource-agent version="rgmanager 2.0" name="service">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines a collection of resources, known as a resource
+        group or cluster service.
+    </longdesc>
+    <shortdesc lang="en">
+        Defines a service (resource group).
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" unique="1" required="1" primary="1">
+            <longdesc lang="en">
+                This is the name of the resource group.
+            </longdesc>
+            <shortdesc lang="en">
+                Name.
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+    
+        <parameter name="domain" reconfig="1">
+            <longdesc lang="en">
+                Failover domains define lists of cluster members
+                to try in the event that a resource group fails.
+            </longdesc>
+            <shortdesc lang="en">
+                Failover domain.
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="autostart" reconfig="1">
+            <longdesc lang="en">
+	    	If set to yes, this resource group will automatically be started
+		after the cluster forms a quorum.  If set to no, this resource
+		group will start in the 'disabled' state after the cluster forms
+		a quorum.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Automatic start after quorum formation
+            </shortdesc>
+            <content type="boolean" default="1"/>
+        </parameter>
+
+        <parameter name="exclusive" reconfig="1">
+            <longdesc lang="en">
+	    	If set, this resource group will only relocate to
+		nodes which have no other resource groups running in the
+		event of a failure.  If no empty nodes are available,
+		this resource group will not be restarted after a failure.
+		Additionally, resource groups will not automatically
+		relocate to the node running this resource group.  This
+		option can be overridden by manual start and/or relocate
+		operations.
+            </longdesc>
+            <shortdesc lang="en">
+	        Exclusive service.
+            </shortdesc>
+            <content type="boolean" default="0"/>
+        </parameter>
+
+	<parameter name="nfslock">
+	    <longdesc lang="en">
+	    	Enable NFS lock workarounds.  When used with a compatible
+		HA-callout program like clunfslock, this could be used
+		to provide NFS lock failover, but at significant cost to
+		other services on the machine.  This requires a compatible
+		version of nfs-utils and manual configuration of rpc.statd;
+		see 'man rpc.statd' to see if your version supports
+		the -H parameter.
+	    </longdesc>
+	    <shortdesc lang="en">
+	        Enable NFS lock workarounds.
+	    </shortdesc>
+	    <content type="boolean" default="0"/>
+	</parameter>
+
+	<parameter name="nfs_client_cache">
+            <longdesc lang="en">
+	   	On systems with large numbers of exports, a performance
+		problem in the exportfs command can cause inordinately long
+		status check times for services with lots of mounted
+		NFS clients.  This occurs because exportfs does DNS queries
+		on all clients in the export list.
+
+		Setting this option to '1' will enable caching of the export
+		list returned from the exportfs command on a per-service
+		basis.  The cache will last for 30 seconds before expiring
+		instead of being generated each time an nfsclient resource
+		is called.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Enable exportfs list caching (performance).
+            </shortdesc>
+	    <content type="integer" default="0"/>
+	</parameter>
+
+                
+        <parameter name="recovery" reconfig="1">
+            <longdesc lang="en">
+	        This currently has three possible options: "restart" tries
+		to restart failed parts of this resource group locally before
+		attempting to relocate (default); "relocate" does not bother
+		trying to restart the service locally; "disable" disables
+		the resource group if any component fails.  Note that
+		any resource with a valid "recover" operation which can be
+		recovered without a restart will be.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Failure recovery policy (restart, relocate, or disable).
+            </shortdesc>
+            <content type="string" default="restart"/>
+        </parameter>
+
+        <parameter name="depend">
+            <longdesc lang="en">
+		Service dependency; will not start without the specified
+		service running.
+            </longdesc>
+            <shortdesc lang="en">
+		Top-level service this depends on, in service:name format.
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="depend_mode">
+            <longdesc lang="en">
+		Service dependency mode.
+		hard - This service is stopped/started if its dependency
+		       is stopped/started
+		soft - This service only depends on the other service for
+		       initial startip.  If the other service stops, this
+		       service is not stopped.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Service dependency mode (soft or hard).
+            </shortdesc>
+            <content type="string" default="hard"/>
+        </parameter>
+
+        <parameter name="max_restarts">
+            <longdesc lang="en">
+	    	Maximum restarts for this service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Maximum restarts for this service.
+            </shortdesc>
+            <content type="string" default="0"/>
+        </parameter>
+
+        <parameter name="restart_expire_time">
+            <longdesc lang="en">
+	    	Restart expiration time.  A restart is forgotten
+		after this time.  When combined with the max_restarts
+		option, this lets administrators specify a threshold
+		for when to fail over services.  If max_restarts
+		is exceeded in this given expiration time, the service
+		is relocated instead of restarted again.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Restart expiration time; amount of time before a restart
+		is forgotten.
+            </shortdesc>
+            <content type="string" default="0"/>
+        </parameter>
+
+	<parameter name="priority">
+	    <longdesc lang="en">
+		Priority for the service.  In a failover scenario, this
+		indicates the ordering of the service (1 is processed
+		first, 2 is processed second, etc.).  This overrides the
+		order presented in cluster.conf.  This option only has
+		an effect if central processing within rgmanager is turned
+		on.
+	    </longdesc>
+	    <shortdesc lang="en">
+		Service priority.
+	    </shortdesc>
+	    <content type="integer" default="0"/>
+	</parameter>
+
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="5"/>
+        <action name="stop" timeout="5"/>
+	
+	<!-- No-ops.  Groups are abstract resource types. 
+        <action name="status" timeout="5" interval="1h"/>
+        <action name="monitor" timeout="5" interval="1h"/>
+ -->
+
+        <action name="reconfig" timeout="5"/>
+        <action name="recover" timeout="5"/>
+        <action name="reload" timeout="5"/>
+        <action name="meta-data" timeout="5"/>
+        <action name="validate-all" timeout="5"/>
+    </actions>
+    
+    <special tag="rgmanager">
+        <attributes maxinstances="1"/>
+        <child type="lvm" start="1" stop="9"/>
+        <child type="fs" start="2" stop="8"/>
+        <child type="clusterfs" start="3" stop="7"/>
+        <child type="netfs" start="4" stop="6"/>
+	<child type="nfsexport" start="5" stop="5"/>
+
+	<child type="nfsclient" start="6" stop="4"/>
+
+        <child type="ip" start="7" stop="2"/>
+        <child type="smb" start="8" stop="3"/>
+        <child type="script" start="9" stop="1"/>
+    </special>
+</resource-agent>
+EOT
+}
+
+
+#
+# A Resource group is abstract, but the OCF RA API doesn't allow for abstract
+# resources, so here it is.
+#
+case $1 in
+	start)
+		#
+		# XXX If this is set, we kill lockd.  If there is no
+		# child IP address, then clients will NOT get the reclaim
+		# notification.
+		#
+		if [ $NFS_TRICKS -eq 0 ]; then
+			if [ "$OCF_RESKEY_nfslock" = "yes" ] || \
+	   		   [ "$OCF_RESKEY_nfslock" = "1" ]; then
+				pkill -KILL -x lockd
+			fi
+		fi
+		exit 0
+		;;
+	stop)
+		exit 0
+		;;
+	recover|restart)
+		exit 0
+		;;
+	status|monitor)
+		exit 0
+		;;
+	reload)
+		exit 0
+		;;
+	meta-data)
+		meta_data
+		exit 0
+		;;
+	validate-all)
+		exit 0
+		;;
+	reconfig)
+		exit 0
+		;;
+	*)
+		exit 0
+		;;
+esac
diff --git a/rgmanager/src/resources/smb.sh b/rgmanager/src/resources/smb.sh
new file mode 100755
index 0000000..edb99ce
--- /dev/null
+++ b/rgmanager/src/resources/smb.sh
@@ -0,0 +1,698 @@
+#!/bin/bash
+
+#
+# Script to manage a Samba file-sharing service component.
+# Unline NFS, this should be placed at the top level of a service
+# because it will try to gather information necessary to run the
+# smbd/nmbd daemons at run-time from the service structure.
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+# Author(s):
+#  Lon Hohberger (lhh at redhat.com)
+#  Tim Burke (tburke at redhat.com)
+#
+
+LC_ALL=C
+LANG=C
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export LC_ALL LANG PATH
+
+#
+# Definitions!
+#
+declare SAMBA_CONFIG_DIR=/etc/samba
+declare SMBD_COMMAND=/usr/sbin/smbd
+declare NMBD_COMMAND=/usr/sbin/nmbd
+declare KILLALL_COMMAND=/usr/bin/killall
+declare SAMBA_PID_DIR=/var/run/samba
+declare SAMBA_LOCK_DIR=/var/cache/samba
+
+#
+# gross globals
+#
+declare -a ipkeys
+declare -a fskeys
+
+# Don't change please :)
+_FAIL=255
+
+. $(dirname $0)/ocf-shellfuncs
+
+meta_data()
+{
+    cat <<EOT
+<?xml version="1.0"?>
+<resource-agent version="rgmanager 2.0" name="smb">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+    	Dynamic smbd/nmbd resource agent
+    </longdesc>
+    <shortdesc lang="en">
+    	Dynamic smbd/nmbd resource agent
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" unique="1" primary="1">
+            <longdesc lang="en">
+                Samba Symbolic Name.  This name will
+		correspond to /etc/samba/smb.conf.NAME
+            </longdesc>
+            <shortdesc lang="en">
+                Samba Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="workgroup">
+            <longdesc lang="en">
+	    	Workgroup name
+            </longdesc>
+            <shortdesc lang="en">
+	    	Workgroup name
+            </shortdesc>
+	    <content type="string" default="LINUXCLUSTER"/>
+        </parameter>
+
+        <parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+	    	Inherit the service name.  We need to know
+		the service name in order to determine file
+		systems and IPs for this smb service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Inherit the service name.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="0"/>
+        <action name="stop" timeout="0"/>
+
+	<!-- This is just a wrapper for LSB init scripts, so monitor
+	     and status can't have a timeout, nor do they do any extra
+	     work regardless of the depth -->
+        <action name="status" interval="30s" timeout="0"/>
+        <action name="monitor" interval="30s" timeout="0"/>
+
+        <action name="meta-data" timeout="0"/>
+        <action name="validate-all" timeout="0"/>
+    </actions>
+</resource-agent>
+EOT
+}
+
+
+#
+# Usage: ccs_get key
+#
+ccs_get()
+{
+	declare outp
+	declare key
+
+	[ -n "$1" ] || return $_FAIL
+
+	key="$*"
+
+	outp=$(ccs_tool query "$key" 2>&1)
+	if [ $? -ne 0 ]; then
+		if [ "$outp" = "${outp/No data available/}" ] || [ "$outp" = "${outp/Operation not permitted/}" ]; then
+			ocf_log err "$outp ($key)"
+			return $_FAIL
+		fi
+
+		# no real error, just no data available
+		return 0
+	fi
+
+	echo $outp
+
+	return 0
+}
+
+
+#
+# Build a list of service IP keys; traverse refs if necessary
+#
+get_service_ip_keys()
+{
+	declare svc=$1
+	declare -i x y=0
+	declare outp
+	declare key
+
+	#
+	# Find service-local IP keys
+	#
+	x=1
+	while : ; do
+		key="/cluster/rm/service[@name=\"$svc\"]/ip[$x]"
+
+		#
+		# Try direct method
+		#
+		outp=$(ccs_get "$key/@address")
+		if [ $? -ne 0 ]; then
+			return 1
+		fi
+
+		#
+		# Try by reference
+		#
+		if [ -z "$outp" ]; then
+			outp=$(ccs_get "$key/@ref")
+			if [ $? -ne 0 ]; then
+				return 1
+			fi
+			key="/cluster/rm/resources/ip[@address=\"$outp\"]"
+		fi
+
+		if [ -z "$outp" ]; then
+			break
+		fi
+
+		#ocf_log debug "IP $outp found @ $key"
+
+		ipkeys[$y]="$key"
+
+		((y++))
+		((x++))
+	done
+
+	ocf_log debug "$y IP addresses found for $svc/$OCF_RESKEY_name"
+
+	return 0
+}
+
+
+#
+# Build a list of service fs keys, traverse refs if necessary
+#
+get_service_fs_keys()
+{
+	declare svc=$1
+	declare -i x y=0
+	declare outp
+	declare key
+
+	#
+	# Find service-local IP keys
+	#
+	x=1
+	while : ; do
+		key="/cluster/rm/service[@name=\"$svc\"]/fs[$x]"
+
+		#
+		# Try direct method
+		#
+		outp=$(ccs_get "$key/@name")
+		if [ $? -ne 0 ]; then
+			return 1
+		fi
+
+		#
+		# Try by reference
+		#
+		if [ -z "$outp" ]; then
+			outp=$(ccs_get "$key/@ref")
+			if [ $? -ne 0 ]; then
+				return 1
+			fi
+			key="/cluster/rm/resources/fs[@name=\"$outp\"]"
+		fi
+
+		if [ -z "$outp" ]; then
+			break
+		fi
+
+		#ocf_log debug "filesystem $outp found @ $key"
+
+		fskeys[$y]="$key"
+
+		((y++))
+		((x++))
+	done
+
+	ocf_log debug "$y filesystems found for $svc/$OCF_RESKEY_name"
+
+	return 0
+}
+
+
+build_ip_list()
+{
+	declare ipaddrs ipaddr
+	declare -i x=0
+
+	while [ -n "${ipkeys[$x]}" ]; do
+		ipaddr=$(ccs_get "${ipkeys[$x]}/@address")
+		if [ -z "$ipaddr" ]; then
+			break
+		fi
+
+		ipaddrs="$ipaddrs $ipaddr"
+
+		((x++))
+	done
+
+	echo $ipaddrs
+}
+
+
+add_sha1()
+{
+	declare sha1line="# rgmanager-sha1 $(sha1sum "$1")"
+	echo $sha1line >> "$1"
+}
+
+
+verify_sha1()
+{
+	declare tmpfile="$(mktemp /tmp/smb-$OCF_RESKEY_name.tmp.XXXXXX)"
+	declare current exp
+
+	exp=$(grep "^# rgmanager-sha1.*$1" "$1" | head -1)
+	if [ -z "$exp" ]; then
+		# No sha1 line.  We're done.
+		ocf_log debug "No SHA1 info in $1"
+		return 1
+	fi
+
+	#
+	# Find expected sha1 and expected file name
+	#
+	exp=${exp/*sha1 /}
+	exp=${exp/ */}
+
+	grep -v "^# rgmanager-sha1" "$1" > "$tmpfile"
+	current=$(sha1sum "$tmpfile")
+	current=${current/ */}
+
+	rm -f "$tmpfile"
+
+	if [ "$current" = "$exp" ]; then
+		ocf_log debug "SHA1 sum matches for $1"
+		return 0
+	fi
+	ocf_log debug "SHA1 sum does not match for $1"
+	return 1
+}
+
+
+add_fs_entries()
+{
+	declare conf="$1"
+	declare sharename
+	declare sharepath key
+
+	declare -i x=0
+
+	while [ -n "${fskeys[$x]}" ]; do
+		key="${fskeys[$x]}/@name"
+
+		sharename=$(ccs_get "$key")
+		if [ -z "$sharename" ]; then
+			break
+		fi
+
+		key="${fskeys[$x]}/@mountpoint"
+		sharepath=$(ccs_get "$key")
+		if [ -z "$sharepath" ]; then
+			break
+		fi
+
+		cat >> "$conf" <<EODEV
+[$sharename]
+	comment = Auto-generated $sharename share
+	# Hide the secret cluster files
+	veto files = /.clumanager/.rgmanager/
+	browsable = yes
+	writable = no
+	public = yes
+	path = $sharepath
+
+EODEV
+
+		((x++))
+	done
+}
+
+
+#
+# Generate the samba configuration if neede for this service.
+#
+gen_smb_conf()
+{
+	declare conf="$1"
+	declare lvl="debug"
+
+	if [ -f "$conf" ]; then
+		verify_sha1 "$conf"
+		if [ $? -ne 0 ]; then
+			ocf_log debug "Config file changed; skipping"
+			return 0
+		fi
+	else
+		lvl="info"
+	fi
+
+	ocf_log $lvl "Creating $conf"
+
+	get_service_ip_keys "$OCF_RESKEY_service_name"
+	get_service_fs_keys "$OCF_RESKEY_service_name"
+
+	cat > "$conf" <<EOT
+#
+# "$conf"
+#
+# This template configuration wass automatically generated, and will
+# be automatically regenerated if removed.  Please modify this file to
+# speficy subdirectories and/or client access permissions.
+#
+# Once this file has been altered, automatic re-generation will stop.
+# Remember to copy this file to all other cluster members after making
+# changes, or your SMB service will not operate correctly.
+#
+# From a cluster perspective, the key fields are:
+#     lock directory - must be unique per samba service.
+#     bind interfaces only - must be present set to yes.
+#     interfaces - must be set to service floating IP address.
+#     path - must be the service mountpoint or subdirectory thereof.
+#
+
+[global]
+        workgroup = $OCF_RESKEY_workgroup
+        pid directory = /var/run/samba/$OCF_RESKEY_name
+        lock directory = /var/cache/samba/$OCF_RESKEY_name
+	log file = /var/log/samba/%m.log
+	#private dir = /var/
+	encrypt passwords = yes
+	bind interfaces only = yes
+	netbios name = ${OCF_RESKEY_name/ /_}
+
+	#
+	# Interfaces are based on ip resources at the top level of
+	# "$OCF_RESKEY_service_name"; IPv6 addresses may or may not
+	# work correctly.
+	#
+	interfaces = $(build_ip_list)
+
+#
+# Shares based on fs resources at the top level of "$OCF_RESKEY_service_name"
+#
+EOT
+	add_fs_entries "$conf"
+	add_sha1 "$conf"
+
+	return 0
+}
+
+
+#
+# Kill off the specified PID
+# (from clumanager 1.0.x/1.2.x)
+#
+# Killing off the samba daemons was miserable to implement, merely
+# because killall doesn't distinguish by program commandline.
+# Consequently I had to implement these routines to selectively pick 'em off.
+#
+# Kills of either the {smbd|nmbd} which is running and was started with
+# the specified argument.  Can't use `killall` to do this because it
+# doesn't allow you to distinguish which process to kill based on any
+# of the program arguments.
+#
+# This routine is also called on "status" checks.  In this case it doesn't
+# actually kill anything.
+#
+# Parameters:
+#       daemonName - daemon name, can be either smbd or nmbd
+#       command - [stop|start|status]
+#       arg     - argument passed to daemon.  In this case its not the
+#                 full set of program args, rather its really just the
+#                 samba config file.
+#
+# Returns: 0 - success (or the daemon isn't currently running)
+#          1 - failure
+#
+kill_daemon_by_arg()
+{
+    	declare daemonName=$1
+	declare action=$2
+	declare arg=$3
+	# Create a unique temporary file to stash off intermediate results
+	declare tmpfile_str=/tmp/sambapids.XXXXXX
+	declare tmpfile
+	declare ret
+
+	tmpfile=$(mktemp $tmpfile_str); ret_val=$?
+
+	if [ -z "$tmpfile" ]; then
+		ocf_log err "kill_daemon_by_arg: Can't create tmp file"
+		return $_FAIL
+	fi
+
+	# Mumble, need to strip off the /etc/samba portion, otherwise the
+	# grep pattern matching will fail.
+	declare confFile="$(basename $arg)"
+
+	# First generate a list of candidate pids.
+	pidof $daemonName > $tmpfile
+	if [ $? -ne 0 ]; then
+		ocf_log debug "kill_daemon_by_arg: no pids for $daemonName"
+		rm -f $tmpfile
+		case "$action" in
+		'stop')
+			return 0
+		;;
+		'status')
+			return $_FAIL
+		;;
+		esac
+		return 0
+	fi
+
+	# If you don't find any matching daemons for a "stop" operation, thats
+	# considered success; whereas for "status" inquiries its a failure.
+	case "$action" in
+	'stop')
+		ret=0
+	;;
+	'status')
+		ret=$_FAIL
+	;;
+	esac
+	#
+	# At this point tmpfile contains a set of pids for the corresponding
+	# {smbd|nmbd}.  Now look though this candidate set of pids and compare
+	# the program arguments (samba config file name).  This distinguishes
+	# which ones should be killed off.
+	#
+	declare daemonPid=""
+	for daemonPid in $(cat $tmpfile); do
+		declare commandLine=$(cat /proc/$daemonPid/cmdline)
+		declare confBase="$(basename $commandLine)"
+		if [ "$confBase" = "$confFile" ]; then
+			case "$action" in
+			'status')
+				rm -f $tmpfile
+				return 0
+			;;
+			esac
+			kill_daemon_pid $daemonPid
+			if [ $? -ne 0 ]; then
+				ret=$_FAIL
+				ocf_log err \
+				"kill_daemon_by_arg: kill_daemon_pid $daemonPid failed"
+			else
+				ocf_log debug \
+				 "kill_daemon_by_arg: kill_daemon_pid $daemonPid success"
+			fi
+		fi
+	done
+	rm -f $tmpfile
+	return $ret
+}
+
+
+#
+# Kill off the specified PID
+# (from clumanager 1.0.x/1.2.x)
+#
+kill_daemon_pid()
+{
+	declare pid=$1
+	declare retval=0
+
+
+	kill -TERM $pid
+	if [ $? -eq 0 ]; then
+		ocf_log debug "Samba: successfully killed $pid"
+	else
+		ocf_log debug "Samba: failed to kill $pid"
+		retval=$_FAIL
+	fi
+	return $retval
+}
+
+
+share_start_stop()
+{
+	declare command=$1
+	declare conf="$SAMBA_CONFIG_DIR/smb.conf.$OCF_RESKEY_name"
+	declare smbd_command
+	declare nmbd_command
+	declare netbios_name
+	
+	#
+	# Specify daemon options
+	# -D = spawn off as separate daemon
+	# -s = the following arg specifies the config file
+	#
+	declare smbd_options="-D -s"
+	declare nmbd_options="-D -s"
+
+	if [ "$command" = "start" ]; then
+		gen_smb_conf "$conf"
+	else 
+		if ! [ -f "$conf" ]; then
+			ocf_log warn "\"$conf\" missing during $command"
+		fi
+	fi
+
+	#
+	# On clusters with multiple samba shares, we need to ensure (as much
+	# as possible) that each service is advertised as a separate netbios
+	# name.
+	#
+	# Generally, the admin sets this in smb.conf.NAME - but since
+	# it is not required, we need another option.  Consequently, we use
+	# smb instance name (which must be unique)
+	#
+	if [ -f "$conf" ]; then
+		grep -qe "^\([[:space:]]\+n\|n\)etbios[[:space:]]\+name[[:space:]]*=[[:space:]]*[[:alnum:]]\+" "$conf"
+		if [ $? -ne 0 ]; then
+
+			netbios_name=$OCF_RESKEY_name
+
+			ocf_log notice "Using $netbios_name as NetBIOS name (service $OCF_RESKEY_service_name)"
+			nmbd_options=" -n $netbios_name $nmbd_options"
+		fi
+	fi
+
+	case $command in
+	start)
+		ocf_log info "Starting Samba instance \"$OCF_RESKEY_name\""
+		mkdir -p "$SAMBA_PID_DIR/$OCF_RESKEY_name"
+		mkdir -p "$SAMBA_LOCK_DIR/$OCF_RESKEY_name"
+
+		[ -f "$SMBD_COMMAND" ] || exit $OCF_ERR_INSTALLED
+		[ -f "$NMBD_COMMAND" ] || exit $OCF_ERR_INSTALLED
+
+		# Kick off the per-service smbd
+		$SMBD_COMMAND $smbd_options "$conf"
+		ret_val=$?
+		if [ $ret_val -ne 0 ]; then
+			ocf_log err "Samba service failed: $SMBD_COMMAND $smbd_options \"$conf\""
+			return $_FAIL
+		fi
+		ocf_log debug "Samba service succeeded: $SMBD_COMMAND $smbd_options \"$conf\""
+
+		# Kick off the per-service nmbd
+		$NMBD_COMMAND $nmbd_options "$conf"
+		ret_val=$?
+		if [ $ret_val -ne 0 ]; then
+			ocf_log err "Samba service failed: $NMBD_COMMAND $nmbd_options \"$conf\""
+			return $_FAIL
+		fi
+		ocf_log debug "Samba service succeeded: $NMBD_COMMAND $nmbd_options \"$conf\""
+	;;
+	stop)
+		ocf_log info "Stopping Samba instance \"$OCF_RESKEY_name\""
+
+       		kill_daemon_by_arg "nmbd" $command "$conf"
+       		kill_daemon_by_arg "smbd" $command "$conf"
+       		if [ "$SAMBA_PID_DIR/$OCF_RESKEY_name" != "/" ]; then
+       			pushd "$SAMBA_PID_DIR" &> /dev/null
+       			rm -rf "$OCF_RESKEY_name"
+	       		popd &> /dev/null
+		fi
+		if [ "$SAMBA_LOCK_DIR/$OCF_RESKEY_name" != "/" ]; then
+     			pushd "$SAMBA_LOCK_DIR" &> /dev/null
+			rm -rf "$OCF_RESKEY_name"
+			popd &> /dev/null
+		fi
+	;;
+	status)
+		ocf_log debug "Checking Samba instance \"$OCF_RESKEY_name\""
+		kill_daemon_by_arg "nmbd" $command "$conf"
+		if [ $? -ne 0 ]; then
+			ocf_log err \
+			"share_start_stop: nmbd for service $svc_name died!"
+			return $_FAIL
+		fi
+		kill_daemon_by_arg "smbd" $command "$conf"
+		if [ $? -ne 0 ]; then
+			ocf_log err \
+		"share_start_stop: nmbd for service $svc_name died!"
+			return $_FAIL
+		fi
+	;;
+	esac
+}
+
+
+verify_all()
+{
+	[ -z "$OCF_RESKEY_workgroup" ] && export OCF_RESKEY_workgroup="LINUXCLUSTER"
+	[ -n "${OCF_RESKEY_name}" ] || exit $OCF_ERR_ARGS      # Invalid Argument
+	if [ -z "${OCF_RESKEY_service_name}" ]; then
+		ocf_log ERR "Samba service ${OCF_RESKEY_name} is not the child of a service"
+		exit $OCF_ERR_ARGS
+	fi
+}
+
+case $1 in
+	meta-data)
+		meta_data
+		exit 0
+	;;
+	start|stop)
+		verify_all
+		share_start_stop $1
+		exit $?
+	;;
+	status|monitor)
+		verify_all
+		share_start_stop status
+		exit $?
+	;;
+	validate-all)
+		verify_all
+		echo "Yer radio's workin', driver!"
+		exit 0
+	;;
+	*)
+		echo "usage: $0 {start|stop|status|monitor|meta-data|validate-all}"
+		exit $OCF_ERR_UNIMPLEMENTED
+	;;
+esac
+
diff --git a/rgmanager/src/resources/svclib_nfslock b/rgmanager/src/resources/svclib_nfslock
new file mode 100644
index 0000000..bc06269
--- /dev/null
+++ b/rgmanager/src/resources/svclib_nfslock
@@ -0,0 +1,281 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+# Do reclaim-broadcasts when we kill lockd during shutdown/startup
+# of a cluster service.
+#
+# Exported functions:
+#
+#  notify_list_store
+#  notify_list_merge
+#  notify_list_broadcast
+#
+
+#
+# Usage:
+# statd_notify <directory> <hostname|ip>
+#
+# Copy out a list from <directory>, merge them with the system nfs lock
+# list, and send them out as <hostname|ip> after generating a random
+# state (needed so clients will reclaim their locks)
+#
+nfslock_statd_notify()
+{
+	declare tmpdir
+	declare nl_dir=$1
+	declare nl_ip=$2
+	declare command		# Work around bugs in rpc.statd
+	declare pid_xxx		# Work around bugs in rpc.statd
+	declare owner
+
+	[ -z "$lockd_pid" ] && return 0
+	if ! [ -d $nl_dir ]; then
+		return 0
+	fi
+
+	if [ -z "`ls $nl_dir/sm/* 2> /dev/null`" ]; then
+		ocf_log debug "No hosts to notify"
+		return 0
+	fi
+	
+	tmpdir=$(mktemp -d /tmp/statd-$2.XXXXXX)
+
+	# Ok, copy the HA directory to something we can use.
+       	mkdir -p $tmpdir/sm
+	
+	# Copy in our specified entries
+	cp -f $nl_dir/sm/* $tmpdir/sm
+
+	# Copy in our global entries
+	# XXX This might be what we just copied.
+
+	if [ -d "/var/lib/nfs/statd/sm" ]; then
+		owner=$(ls -dl /var/lib/nfs/statd/sm | awk '{print $3"."$4}')
+		cp -f /var/lib/nfs/statd/sm/* $tmpdir/sm
+	elif [ -d "/var/lib/nfs/sm" ]; then
+		owner=$(ls -dl /var/lib/nfs/statd/sm | awk '{print $3"."$4}')
+		cp -f /var/lib/nfs/sm/* $tmpdir/sm
+	fi
+
+	#
+	# Generate a random state file.  If this ends up being what a client
+	# already has in its list, that's bad, but the chances of this
+	# are small - and relocations should be rare.
+	#
+	dd if=/dev/urandom of=$tmpdir/state bs=1 count=4 &> /dev/null
+
+	#
+	# Make sure we set permissions, or statd will not like it.
+	#
+	chown -R $owner $tmpdir
+
+	#
+	# Tell rpc.statd to notify clients.  Don't go into background, 
+	# because statd is buggy and won't exit like it's supposed to after
+	# sending the notifications out.
+	#
+	ocf_log info "Sending reclaim notifications via $nl_ip"
+	command="rpc.statd -NFP $tmpdir -n $nl_ip"
+	eval $command 2>&1 &
+	sleep 3 # XXX - the instance of rpc.statd we just spawned is supposed
+	        # to exit after it finishes notifying clients.
+	        # rpc.statd spawned which is still running handles the actual
+	        # new SM_MON requests... we hope 3 seconds is enough time
+	        # to get all the SM_NOTIFY messages out.  rpc.statd = bugged
+	#
+	# clean up
+	#
+	pid_xxx=`ps auwwx | grep "$command" | grep -v grep | awk '{print $2}'`
+	kill $pid_xxx
+	rm -rf $tmpdir
+
+	return 0
+}
+
+
+#
+# Copy of isSlave from svclib_ip and/or ip.sh
+#
+nfslock_isSlave()
+{
+        declare intf=$1
+        declare line
+
+        if [ -z "$intf" ]; then
+                ocf_log err "usage: isSlave <I/F>"
+                return 1
+        fi
+
+        line=$(/sbin/ip link list dev $intf)
+        if [ $? -ne 0 ]; then
+                ocf_log err "$intf not found"
+                return 1
+        fi
+
+        if [ "$line" = "${line/<*SLAVE*>/}" ]; then
+                return 2
+        fi
+
+        # Yes, it is a slave device.  Ignore.
+        return 0
+}
+
+
+#
+# Get all the IPs on the system except loopback IPs
+#
+nfslock_ip_address_list()
+{
+        declare idx dev family ifaddr
+
+        while read idx dev family ifaddr; do
+
+		if [ "$family" != "inet" ] && [ "$family" != "inet6" ]; then
+			continue
+		fi
+
+		if [ "$dev" = "lo" ]; then
+			# Ignore loopback
+			continue
+		fi
+
+                nfslock_isSlave $dev
+                if [ $? -ne 2 ]; then
+                        continue
+                fi
+
+                idx=${idx/:/}
+
+                echo $dev $family ${ifaddr/\/*/} ${ifaddr/*\//}
+
+        done < <(/sbin/ip -o addr list | awk '{print $1,$2,$3,$4}')
+
+        return 0
+}
+	
+
+#
+# Usage: broadcast_notify <state_directory>
+#
+# Send the contents of <state_directory> out via all IPs on the system.
+#
+notify_list_broadcast()
+{
+        declare dev family addr maskbits ip_name
+	declare lockd_pid=$(pidof lockd)
+	declare nl_dir=$1
+
+	# First of all, send lockd a SIGKILL.  We hope nfsd is running.
+	# If it is, this will cause lockd to reset the grace period for
+	# lock reclaiming.
+	if [ -n "$lockd_pid" ]; then
+		ocf_log info "Asking lockd to drop locks (pid $lockd_pid)"
+		kill -9 $lockd_pid
+	else
+		ocf_log warning "lockd not running; cannot notify clients"
+		return 1
+	fi
+	
+        while read dev family addr maskbits; do
+		if [ "$family" != "inet" ]; then
+			continue
+		fi
+
+		ip_name=$(clufindhostname -i $addr)
+		if [ -z "$ip_name" ]; then
+			nfslock_statd_notify $nl_dir $addr
+		else
+			nfslock_statd_notify $nl_dir $ip_name
+		fi
+
+	done < <(nfslock_ip_address_list)
+}
+
+
+#
+# Store the lock monitor list from rpc.statd - do this during a teardown
+# after the IP addresses of a service have been taken offline.  Note that
+# this should be done by HA-callout programs, but this feature is not in
+# RHEL3. 
+#
+notify_list_store()
+{
+	declare nl_dir=$1
+	declare owner
+
+	mkdir -p $nl_dir/sm
+
+	if [ -d "/var/lib/nfs/statd/sm" ]; then
+	        if [ -z "`ls /var/lib/nfs/statd/sm/* 2> /dev/null`" ]; then
+			return 1
+			# nothing to do!
+		fi
+
+		owner=$(ls -dl /var/lib/nfs/statd/sm | awk '{print $3"."$4}')
+		cp -Rdpf /var/lib/nfs/statd/sm/* $nl_dir/sm
+		chown -R $owner $nl_dir
+		return 0
+	elif [ -d "/var/lib/nfs/sm" ]; then
+	        if [ -z "`ls /var/lib/nfs/sm/* 2> /dev/null`" ]; then
+			return 1
+			# nothing to do!
+		fi
+
+		owner=$(ls -dl /var/lib/nfs/sm | awk '{print $3"."$4}')
+		cp -Rdpf /var/lib/nfs/sm/* $nl_dir/sm
+		chown -R $owner $nl_dir
+		return 0
+	fi
+
+	return 1
+}
+
+
+#
+# Merge the contents of <nl_dir>/sm with the system-wide list
+# Make sure ownership is right, or statd will hiccup.  This should not
+# actually ever be needed because statd will, upon getting a SM_MON
+# request, create all the entries in this list.  It's mostly for
+# housekeeping for next time we relocate the service.
+#
+notify_list_merge()
+{
+	declare nl_dir=$1
+	declare owner
+
+	if [ -z "`ls $nl_dir/* 2> /dev/null`" ]; then
+		return 1
+	fi
+
+	if [ -d "/var/lib/nfs/statd/sm" ]; then
+		owner=$(ls -dl /var/lib/nfs/statd/sm | awk '{print $3"."$4}')
+ 		cp -Rdpf $nl_dir/sm/* /var/lib/nfs/statd/sm
+		chown -R $owner $nl_dir
+		return 0
+	elif [ -d "/var/lib/nfs/sm" ]; then
+		owner=$(ls -dl /var/lib/nfs/sm | awk '{print $3"."$4}')
+ 		cp -Rdpf $nl_dir/sm/* /var/lib/nfs/sm
+		chown -R $owner $nl_dir
+		return 0
+	fi
+
+	return 1
+}
+
diff --git a/rgmanager/src/resources/tomcat-5.metadata b/rgmanager/src/resources/tomcat-5.metadata
new file mode 100644
index 0000000..021bef7
--- /dev/null
+++ b/rgmanager/src/resources/tomcat-5.metadata
@@ -0,0 +1,104 @@
+<?xml version="1.0"?>
+<resource-agent version="rgmanager 2.0" name="tomcat-5">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines an instance of Tomcat server
+    </longdesc>
+    <shortdesc lang="en">
+        Defines a Tomcat server
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+	        Specifies a service name for logging and other purposes
+	    </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="config_file">
+            <longdesc lang="en">
+                Define absolute path to configuration file
+            </longdesc>
+            <shortdesc lang="en">
+                Config File
+            </shortdesc>
+	    <content type="string" default="/etc/tomcat5/tomcat5.conf"/>
+        </parameter>
+
+	<parameter name="tomcat_user">
+		<longdesc lang="en">
+			User who runs the Tomcat server
+		</longdesc>
+		<shortdesc lang="en">
+			User who runs the Tomcat server
+		</shortdesc>
+		<content type="string" default="tomcat" />
+	</parameter>
+
+	<parameter name="catalina_options">
+		<longdesc lang="en">
+			Other command-line options for Catalina
+		</longdesc>
+		<shortdesc lang="en">
+			Other command-line options for Catalina
+		</shortdesc>
+		<content type="string" />
+	</parameter>
+
+	<parameter name="catalina_base">
+		<longdesc lang="en">
+			Cataliny base directory
+		</longdesc>
+		<shortdesc lang="en">
+			Catalina base directory (differs for each service)
+		</shortdesc>
+		<content type="string" default="/usr/share/tomcat5" />
+	</parameter>
+
+	<parameter name="shutdown_wait">
+		<longdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</longdesc>
+		<shortdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</shortdesc>
+		<content type="integer" default="30" />
+	</parameter>
+
+        <parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+	    	Inherit the service name.  We need to know
+		the service name in order to determine file
+		systems and IPs for this service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Inherit the service name.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="0"/>
+	<action name="stop" timeout="0"/>
+
+	<!-- Checks to see if it''s mounted in the right place -->
+	<action name="status" interval="1m" timeout="10"/>
+	<action name="monitor" interval="1m" timeout="10"/>
+
+	<!-- Checks to see if we can read from the mountpoint -->
+	<action name="status" depth="10" timeout="30" interval="5m"/>
+	<action name="monitor" depth="10" timeout="30" interval="5m"/>
+
+	<action name="meta-data" timeout="0"/>
+	<action name="validate-all" timeout="0"/>
+    </actions>
+
+    <special tag="rgmanager">
+    </special>
+</resource-agent>
diff --git a/rgmanager/src/resources/tomcat-5.sh b/rgmanager/src/resources/tomcat-5.sh
new file mode 100755
index 0000000..814da0f
--- /dev/null
+++ b/rgmanager/src/resources/tomcat-5.sh
@@ -0,0 +1,274 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+export LC_ALL=C
+export LANG=C
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+declare TOMCAT_TOMCAT=/usr/bin/dtomcat5
+declare TOMCAT_RELINK=/usr/share/tomcat5/bin/relink
+declare TOMCAT_pid_file="`generate_name_for_pid_file`"
+declare TOMCAT_conf_dir="`generate_name_for_conf_dir`/conf"
+declare TOMCAT_gen_config_file="$TOMCAT_conf_dir/server.xml"
+declare TOMCAT_gen_catalina_base="`generate_name_for_conf_dir`"
+
+declare JAVA_HOME
+declare CATALINA_HOME
+declare CATALINA_BASE
+declare CATALINA_TMPDIR
+declare CLASSPATH
+declare TOMCAT_USER
+##
+
+verify_all()
+{
+	clog_service_verify $CLOG_INIT
+
+	if [ -z "$OCF_RESKEY_name" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid Name Of Service"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_service_name" ]; then
+		clog_service_verify $CLOG_FAILED_NOT_CHILD
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_INVALID "$OCF_RESKEY_config_file"
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ ! -r "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_NOT_READABLE $OCF_RESKEY_config_file
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	. "$OCF_RESKEY_config_file"
+	
+	if [ $? -ne 0 ]; then
+		clog_service_verify $CLOG_FAILED "Error In The File \"$OCF_RESKEY_config_file\""
+		return $OCF_ERR_ARGS
+	fi 
+
+	if [ -z "$JAVA_HOME" ]; then
+		clog_service_verify $CLOG_FAILED "JAVA_HOME Not Specified In ${OCF_RESKEY_config_file}"
+		return $OCF_ERR_ARGS;
+	fi	
+
+	if [ ! -d "$JAVA_HOME" ]; then
+		clog_service_verify $CLOG_FAILED "JAVA_HOME Does Not Exist"
+		return $OCF_ERR_ARGS;
+	fi
+
+	if [ -z "$JAVA_ENDORSED_DIRS" ]; then
+		clog_service_verify $CLOG_FAILED "JAVA_ENDORSED_DIRS Not Specified In ${OCF_RESKEY_config_file}"
+		return $OCF_ERR_ARGS;
+	fi	
+
+	if [ ! -d "$JAVA_ENDORSED_DIRS" ]; then
+		clog_service_verify $CLOG_FAILED "JAVA_ENDORSED_DIRS Does Not Exist"
+		return $OCF_ERR_ARGS;
+	fi
+
+	if [ -z "$CATALINA_HOME" ]; then
+		clog_service_verify $CLOG_FAILED "CATALINA_HOME Not Specified In ${OCF_RESKEY_config_file}"
+		return $OCF_ERR_ARGS;
+	fi	
+
+	if [ ! -d "$CATALINA_HOME" ]; then
+		clog_service_verify $CLOG_FAILED "CATALINA_HOME Does Not Exist"
+		return $OCF_ERR_ARGS;
+	fi
+
+	if [ -z "$CATALINA_TMPDIR" ]; then
+		clog_service_verify $CLOG_FAILED "CATALINA_TMPDIR Not Specified In ${OCF_RESKEY_config_file}"
+		return $OCF_ERR_ARGS;
+	fi	
+
+	if [ ! -d "$CATALINA_TMPDIR" ]; then
+		clog_service_verify $CLOG_FAILED "CATALINA_TMPDIR Does Not Exist"
+		return $OCF_ERR_ARGS;
+	fi
+
+	if [ -z "$TOMCAT_USER" ]; then
+		clog_service_verify $CLOG_FAILED "TOMCAT_USER Does Not Exist"
+		return $OCF_ERR_ARGS;
+	fi
+
+	clog_service_verify $CLOG_SUCCEED
+		
+	return 0
+}
+
+generate_config_file()
+{
+	declare original_file="$1"
+	declare generated_file="$2"
+	declare ip_addresses="$3"
+
+	if [ -f "$generated_file" ]; then
+		sha1_verify "$generated_file"
+		if [ $? -ne 0 ]; then
+			clog_check_sha1 $CLOG_FAILED
+			return 0
+		fi
+	fi	
+
+	clog_generate_config $CLOG_INIT "$original_file" "$generated_file"
+
+	generate_configTemplateXML "$generated_file" "$original_file"
+	$(dirname $0)/utils/tomcat-parse-config.pl $ip_addresses < "$original_file" >> "$generated_file"
+
+        sha1_addToFileXML "$generated_file"
+	clog_generate_config $CLOG_SUCCEED "$original_file" "$generated_file"
+               
+	return 0;
+}
+
+start()
+{
+	clog_service_start $CLOG_INIT
+
+	create_pid_directory
+	create_conf_directory "$TOMCAT_conf_dir"
+	check_pid_file "$TOMCAT_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_check_pid $CLOG_FAILED "$TOMCAT_pid_file"
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	clog_looking_for $CLOG_INIT "IP Addresses"
+
+        get_service_ip_keys "$OCF_RESKEY_service_name"
+        ip_addresses=`build_ip_list`
+
+	if [ -z "$ip_addresses" ]; then
+		clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Addresses"
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_looking_for $CLOG_SUCCEED "IP Addresses"
+	generate_config_file "$OCF_RESKEY_catalina_base/conf/server.xml" "$TOMCAT_gen_config_file" "$ip_addresses"
+	ln -s "$OCF_RESKEY_catalina_base"/* "$TOMCAT_gen_catalina_base" &> /dev/null
+	ln -s "$OCF_RESKEY_catalina_base"/conf/* "$TOMCAT_gen_catalina_base"/conf &> /dev/null
+	
+	CLASSPATH="$JAVA_HOME"/lib/tools.jar:"$CATALINA_HOME"/bin/bootstrap.jar:"$CATALINA_HOME"/bin/commons-logging-api.jar:`/usr/bin/build-classpath mx4j/mx4j-impl`:`/usr/bin/build-classpath mx4j/mx4j-jmx`
+
+	su "$TOMCAT_USER"  -c " \"$JAVA_HOME/bin/java\" $JAVA_OPTS $OCF_RESKEY_catalina_options \
+		-Djava.endorsed.dirs=\"$JAVA_ENDORSED_DIRS\" -classpath \"$CLASSPATH\" \
+		-Dcatalina.base=\"$TOMCAT_gen_catalina_base\" \
+		-Dcatalina.home=\"$CATALINA_HOME\" \
+		-Djava.io.tmpdir=\"$CATALINA_TMPDIR\" \
+		org.apache.catalina.startup.Bootstrap \"$@\" start " \
+		>> "$TOMCAT_gen_catalina_base"/logs/catalina.out 2>&1 &
+	                                                
+
+	if [ $? -ne 0 ]; then
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	if [ -z "$!" ]; then
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	
+	echo $! > "$TOMCAT_pid_file"
+
+	clog_service_start $CLOG_SUCCEED
+
+	return 0;
+}
+
+stop()
+{
+	clog_service_stop $CLOG_INIT
+
+	stop_generic "$TOMCAT_pid_file" "$OCF_RESKEY_shutdown_wait"
+	
+	if [ $? -ne 0 ]; then
+		clog_service_stop $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+        if [ -e "$TOMCAT_pid_file" ]; then
+		rm -f "$TOMCAT_pid_file"
+	fi
+                                
+	clog_service_stop $CLOG_SUCCEED
+	return 0;
+}
+
+status()
+{
+	clog_service_status $CLOG_INIT
+
+	status_check_pid "$TOMCAT_pid_file"
+	if [ $? -ne 0 ]; then
+		clog_service_status $CLOG_FAILED "$TOMCAT_pid_file"
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_status $CLOG_SUCCEED
+	return 0
+}
+
+case $1 in
+	meta-data)
+		cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+		exit 0
+		;;
+	validate-all)
+		verify_all
+		exit $?
+		;;
+	start)
+		verify_all && start
+		exit $?
+		;;
+	stop)
+		verify_all && stop
+		exit $?
+		;;
+	status|monitor)
+		verify_all
+		status
+		exit $?
+		;;
+	restart)
+		verify_all
+		stop
+		start
+		exit $?
+		;;
+	*)
+		echo "Usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
diff --git a/rgmanager/src/resources/tomcat-6.metadata b/rgmanager/src/resources/tomcat-6.metadata
new file mode 100644
index 0000000..493e0d5
--- /dev/null
+++ b/rgmanager/src/resources/tomcat-6.metadata
@@ -0,0 +1,74 @@
+<?xml version="1.0"?>
+<resource-agent version="rgmanager 2.0" name="tomcat-6">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+        This defines an instance of Tomcat server
+    </longdesc>
+    <shortdesc lang="en">
+        Defines a Tomcat server
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+	    <longdesc lang="en">
+	        Specifies a service name for logging and other purposes
+	    </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+
+        <parameter name="config_file">
+            <longdesc lang="en">
+                Define absolute path to configuration file
+            </longdesc>
+            <shortdesc lang="en">
+                Config File
+            </shortdesc>
+	    <content type="string" default="/etc/tomcat6/tomcat6.conf"/>
+        </parameter>
+
+	<parameter name="shutdown_wait">
+		<longdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</longdesc>
+		<shortdesc lang="en">
+			Wait X seconds for correct end of service shutdown
+		</shortdesc>
+		<content type="integer" default="30" />
+	</parameter>
+
+        <parameter name="service_name" inherit="service%name">
+            <longdesc lang="en">
+	    	Inherit the service name.  We need to know
+		the service name in order to determine file
+		systems and IPs for this service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Inherit the service name.
+            </shortdesc>
+	    <content type="string"/>
+        </parameter>
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="0"/>
+	<action name="stop" timeout="0"/>
+
+	<!-- Checks to see if it''s mounted in the right place -->
+	<action name="status" interval="1m" timeout="10"/>
+	<action name="monitor" interval="1m" timeout="10"/>
+
+	<!-- Checks to see if we can read from the mountpoint -->
+	<action name="status" depth="10" timeout="30" interval="5m"/>
+	<action name="monitor" depth="10" timeout="30" interval="5m"/>
+
+	<action name="meta-data" timeout="0"/>
+	<action name="validate-all" timeout="0"/>
+    </actions>
+
+    <special tag="rgmanager">
+    </special>
+</resource-agent>
diff --git a/rgmanager/src/resources/tomcat-6.sh b/rgmanager/src/resources/tomcat-6.sh
new file mode 100755
index 0000000..879e1ec
--- /dev/null
+++ b/rgmanager/src/resources/tomcat-6.sh
@@ -0,0 +1,250 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+export LC_ALL=C
+export LANG=C
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+. $(dirname $0)/ocf-shellfuncs
+. $(dirname $0)/utils/config-utils.sh
+. $(dirname $0)/utils/messages.sh
+. $(dirname $0)/utils/ra-skelet.sh
+
+declare TOMCAT_pid_file="`generate_name_for_pid_file`"
+declare TOMCAT_conf_dir="`generate_name_for_conf_dir`/conf"
+declare TOMCAT_gen_config_file="$TOMCAT_conf_dir/server.xml"
+declare TOMCAT_gen_catalina_base="`generate_name_for_conf_dir`"
+
+declare CATALINA_HOME
+declare CATALINA_BASE
+declare CATALINA_TMPDIR
+declare CLASSPATH
+declare TOMCAT_USER
+##
+
+verify_all()
+{
+	clog_service_verify $CLOG_INIT
+
+	if [ -z "$OCF_RESKEY_name" ]; then
+		clog_service_verify $CLOG_FAILED "Invalid Name Of Service"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_service_name" ]; then
+		clog_service_verify $CLOG_FAILED_NOT_CHILD
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -z "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_INVALID "$OCF_RESKEY_config_file"
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ ! -r "$OCF_RESKEY_config_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_NOT_READABLE $OCF_RESKEY_config_file
+		clog_service_verify $CLOG_FAILED
+		return $OCF_ERR_ARGS
+	fi
+
+	. "$OCF_RESKEY_config_file"
+
+	if [ $? -ne 0 ]; then
+		clog_service_verify $CLOG_FAILED "Error In The File \"$OCF_RESKEY_config_file\""
+		return $OCF_ERR_ARGS
+	fi 
+
+	if [ -z "$CATALINA_HOME" ]; then
+		clog_service_verify $CLOG_FAILED "CATALINA_HOME Not Specified In ${OCF_RESKEY_config_file}"
+		return $OCF_ERR_ARGS;
+	fi	
+
+	if [ ! -d "$CATALINA_HOME" ]; then
+		clog_service_verify $CLOG_FAILED "CATALINA_HOME Does Not Exist"
+		return $OCF_ERR_ARGS;
+	fi
+
+	if [ -z "$CATALINA_TMPDIR" ]; then
+		clog_service_verify $CLOG_FAILED "CATALINA_TMPDIR Not Specified In ${OCF_RESKEY_config_file}"
+		return $OCF_ERR_ARGS;
+	fi	
+
+	if [ ! -d "$CATALINA_TMPDIR" ]; then
+		clog_service_verify $CLOG_FAILED "CATALINA_TMPDIR Does Not Exist"
+		return $OCF_ERR_ARGS;
+	fi
+
+	if [ -z "$TOMCAT_USER" ]; then
+		clog_service_verify $CLOG_FAILED "TOMCAT_USER Does Not Exist"
+		return $OCF_ERR_ARGS;
+	fi
+
+	clog_service_verify $CLOG_SUCCEED
+		
+	return 0
+}
+
+generate_config_file()
+{
+	declare original_file="$1"
+	declare generated_file="$2"
+	declare ip_addresses="$3"
+
+	if [ -f "$generated_file" ]; then
+		sha1_verify "$generated_file"
+		if [ $? -ne 0 ]; then
+			clog_check_sha1 $CLOG_FAILED
+			return 0
+		fi
+	fi	
+
+	clog_generate_config $CLOG_INIT "$original_file" "$generated_file"
+
+	$(dirname $0)/utils/tomcat-parse-config.pl $ip_addresses < "$original_file" > "$generated_file"
+
+        sha1_addToFileXML "$generated_file"
+	clog_generate_config $CLOG_SUCCEED "$original_file" "$generated_file"
+               
+	return 0;
+}
+
+start()
+{
+	clog_service_start $CLOG_INIT
+
+	create_conf_directory "$TOMCAT_conf_dir"
+	check_pid_file "$TOMCAT_pid_file"
+
+	if [ $? -ne 0 ]; then
+		clog_check_pid $CLOG_FAILED "$TOMCAT_pid_file"
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+	clog_looking_for $CLOG_INIT "IP Addresses"
+
+        get_service_ip_keys "$OCF_RESKEY_service_name"
+        ip_addresses=`build_ip_list`
+
+	if [ -z "$ip_addresses" ]; then
+		clog_looking_for $CLOG_FAILED_NOT_FOUND "IP Addresses"
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_looking_for $CLOG_SUCCEED "IP Addresses"
+
+	. "$OCF_RESKEY_config_file"
+
+	create_pid_directory "$TOMCAT_USER"
+
+	generate_config_file "$CATALINA_BASE/conf/server.xml" "$TOMCAT_gen_config_file" "$ip_addresses"
+	rm -f "$TOMCAT_gen_catalina_base/conf/tomcat6.conf"
+	( cat $OCF_RESKEY_config_file | grep -v 'CATALINA_PID=' | grep -v 'CATALINA_BASE='; echo CATALINA_BASE="$TOMCAT_gen_catalina_base"; echo CATALINA_PID="$TOMCAT_pid_file") > "$TOMCAT_gen_catalina_base/conf/tomcat6.conf" 
+	ln -s "$CATALINA_BASE"/* "$TOMCAT_gen_catalina_base" &> /dev/null
+	ln -s "$CATALINA_BASE"/conf/* "$TOMCAT_gen_catalina_base"/conf &> /dev/null
+	
+	export TOMCAT_CFG="$TOMCAT_gen_catalina_base/conf/tomcat6.conf"
+
+	tomcat6_options="$tomcat6_options $(
+				 awk '!/^#/ && !/^$/ { ORS=" "; print "export ", $0, ";" }' \
+				 $TOMCAT_CFG
+			 )"
+
+	eval "$tomcat6_options"
+
+	/bin/su -s /bin/sh $TOMCAT_USER -c "/usr/sbin/tomcat6 start"
+
+	if [ $? -ne 0 ]; then
+		clog_service_start $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_start $CLOG_SUCCEED
+
+	return 0;
+}
+
+stop()
+{
+	clog_service_stop $CLOG_INIT
+
+	stop_generic "$TOMCAT_pid_file" "$OCF_RESKEY_shutdown_wait"
+	
+	if [ $? -ne 0 ]; then
+		clog_service_stop $CLOG_FAILED
+		return $OCF_ERR_GENERIC
+	fi
+
+        if [ -e "$TOMCAT_pid_file" ]; then
+		rm -f "$TOMCAT_pid_file"
+	fi
+                                
+	clog_service_stop $CLOG_SUCCEED
+	return 0;
+}
+
+status()
+{
+	clog_service_status $CLOG_INIT
+
+	status_check_pid "$TOMCAT_pid_file"
+	if [ $? -ne 0 ]; then
+		clog_service_status $CLOG_FAILED "$TOMCAT_pid_file"
+		return $OCF_ERR_GENERIC
+	fi
+
+	clog_service_status $CLOG_SUCCEED
+	return 0
+}
+
+case $1 in
+	meta-data)
+		cat `echo $0 | sed 's/^\(.*\)\.sh$/\1.metadata/'`
+		exit 0
+		;;
+	validate-all)
+		verify_all
+		exit $?
+		;;
+	start)
+		verify_all && start
+		exit $?
+		;;
+	stop)
+		verify_all 
+		stop
+		exit $?
+		;;
+	status|monitor)
+		verify_all
+		status
+		exit $?
+		;;
+	restart)
+		verify_all
+		stop
+		start
+		exit $?
+		;;
+	*)
+		echo "Usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+esac
diff --git a/rgmanager/src/resources/utils/Makefile.am b/rgmanager/src/resources/utils/Makefile.am
new file mode 100644
index 0000000..48b0b6a
--- /dev/null
+++ b/rgmanager/src/resources/utils/Makefile.am
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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
+
+commonscripts		= fs-lib.sh \
+			  httpd-parse-config.pl \
+			  member_util.sh \
+			  messages.sh \
+			  named-parse-config.pl \
+			  ra-skelet.sh \
+			  tomcat-parse-config.pl \
+			  config-utils.sh
+
+EXTRA_DIST		= $(commonscripts) \
+			  rhev-check.sh
+
+sbin_SCRIPTS		= rhev-check.sh
+
+rasutilsdir		= ${CLUSTERDATA}/utils
+
+rasutils_SCRIPTS	= $(commonscripts)
diff --git a/rgmanager/src/resources/utils/config-utils.sh b/rgmanager/src/resources/utils/config-utils.sh
new file mode 100644
index 0000000..68ac859
--- /dev/null
+++ b/rgmanager/src/resources/utils/config-utils.sh
@@ -0,0 +1,295 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+declare RA_COMMON_pid_dir=/var/run/cluster
+declare RA_COMMON_conf_dir=/etc/cluster
+
+declare -i FAIL=255
+declare -a ip_keys
+
+generate_configTemplate()
+{
+	cat > "$1" << EOT
+#
+# "$1" was created from the "$2"
+#
+# This template configuration was automatically generated, and will be
+# automatically regenerated if removed. Once this file has been altered,
+# automatic re-generation will stop. Remember to copy this file to all 
+# other cluster members after making changes, or your service will not 
+# operate correctly.
+#
+EOT
+}
+
+generate_configTemplateXML()
+{
+	cat > "$1" << EOT
+<!--
+  "$1" was created from the "$2"
+
+  This template configuration was automatically generated, and will be
+  automatically regenerated if removed. Once this file has been altered,
+  automatic re-generation will stop. Remember to copy this file to all 
+  other cluster members after making changes, or your service will not 
+  operate correctly.
+-->
+EOT
+}
+
+sha1_addToFile()
+{
+        declare sha1line="# rgmanager-sha1 $(sha1sum "$1")"
+        echo $sha1line >> "$1"
+}
+
+sha1_addToFileXML()
+{
+        declare sha1line="<!--# rgmanager-sha1 $(sha1sum "$1")-->"
+        echo $sha1line >> "$1"
+}
+
+sha1_verify()
+{
+	declare sha1_new sha1_old
+	declare oldFile=$1
+
+	ocf_log debug "Checking: SHA1 checksum of config file $oldFile"
+
+	sha1_new=`cat "$oldFile" | grep -v "# rgmanager-sha1" | sha1sum | sed 's/^\([a-z0-9]\+\) .*$/\1/'`
+ 	sha1_old=`tail -n 1 "$oldFile" | sed 's/^\(<!--\)\?# rgmanager-sha1 \(.*\)$/\2/' | sed 's/^\([a-z0-9]\+\) .*$/\1/'`
+
+	if [ "$sha1_new" = "$sha1_old" ]; then
+	        ocf_log debug "Checking: SHA1 checksum > succeed"
+		return 0;
+	else
+		ocf_log debug "Checking: SHA1 checksum > failed - file changed"
+		return 1;
+	fi
+}
+
+#
+# Usage: ccs_get key
+#
+ccs_get()
+{
+	declare outp
+	declare key
+
+	[ -n "$1" ] || return $FAIL
+
+	key="$*"
+
+	outp=$(ccs_tool query "$key" 2>&1)
+	if [ $? -ne 0 ]; then
+		if [[ "$outp" =~ "Query failed: Invalid argument" ]]; then
+			# This usually means that element does not exist
+			# e.g. when checking for IP address 
+			return 0;
+		fi
+
+		if [ "$outp" = "${outp/No data available/}" ] || [ "$outp" = "${outp/Operation not permitted/}" ]; then
+			ocf_log err "$outp ($key)"
+			return $FAIL
+		fi
+
+		# no real error, just no data available
+		return 0
+	fi
+
+	echo $outp
+
+	return 0
+}
+
+#
+# Build a list of service IP keys; traverse refs if necessary
+# Usage: get_service_ip_keys desc serviceName
+#
+get_service_ip_keys()
+{
+	declare svc=$1
+	declare -i x y=0
+	declare outp
+	declare key
+
+	#
+	# Find service-local IP keys
+	#
+	x=1
+	while : ; do
+		key="/cluster/rm/service[@name=\"$svc\"]/ip[$x]"
+
+		#
+		# Try direct method
+		#
+		outp=$(ccs_get "$key/@address")
+		if [ $? -ne 0 ]; then
+			return 1
+		fi
+
+		#
+		# Try by reference
+		#
+		if [ -z "$outp" ]; then
+			outp=$(ccs_get "$key/@ref")
+			if [ $? -ne 0 ]; then
+				return 1
+			fi
+			key="/cluster/rm/resources/ip[@address=\"$outp\"]"
+		fi
+
+		if [ -z "$outp" ]; then
+			break
+		fi
+
+		#ocf_log debug "IP $outp found @ $key"
+
+		ip_keys[$y]="$key"
+
+		((y++))
+		((x++))
+	done
+
+	ocf_log debug "$y IP addresses found for $svc/$OCF_RESKEY_name"
+
+	return 0
+}
+
+build_ip_list()
+{
+        declare ipaddrs ipaddr
+        declare -i x=0
+                        
+        while [ -n "${ip_keys[$x]}" ]; do
+              ipaddr=$(ccs_get "${ip_keys[$x]}/@address")
+              if [ -z "$ipaddr" ]; then
+                                   break
+              fi
+
+	      # remove netmask
+	      iponly=`echo $ipaddr | sed 's/\/.*//'`
+              ipaddrs="$ipaddrs $iponly"
+             ((x++))
+        done
+
+        echo $ipaddrs
+}
+
+generate_name_for_pid_file()
+{
+	declare filename=$(basename $0)
+	
+	echo "$RA_COMMON_pid_dir/$(basename $0 | sed 's/^\(.*\)\..*/\1/')/$OCF_RESOURCE_INSTANCE.pid"
+	
+	return 0;
+}
+
+generate_name_for_pid_dir()
+{
+	declare filename=$(basename $0)
+	
+	echo "$RA_COMMON_pid_dir/$(basename $0 | sed 's/^\(.*\)\..*/\1/')/$OCF_RESOURCE_INSTANCE"
+	
+	return 0;
+}
+
+generate_name_for_conf_dir()
+{
+	declare filename=$(basename $0)
+
+	echo "$RA_COMMON_conf_dir/$(basename $0 | sed 's/^\(.*\)\..*/\1/')/$OCF_RESOURCE_INSTANCE"
+	
+	return 0;
+}
+
+#
+# Usage: create_pid_directory [username]
+#
+create_pid_directory()
+{
+	declare program_name="$(basename $0 | sed 's/^\(.*\)\..*/\1/')"
+	declare dirname="$RA_COMMON_pid_dir/$program_name"
+	declare username="$1"
+
+	if [ -d "$dirname" ]; then
+		return 0;
+	fi
+	
+	chmod 711 "$RA_COMMON_pid_dir"
+	mkdir -p "$dirname"
+	
+	if [ "$program_name" = "mysql" ]; then
+		if [ -n "$username" ]; then
+			chown "${username}.root" "$dirname"
+		else
+			chown mysql.root "$dirname"
+		fi
+	elif [ "$program_name" = "tomcat-5" -o "$program_name" = "tomcat-6" ]; then
+		if [ -n "$username" ]; then
+			chown "${username}.root" "$dirname"
+		else
+			chown tomcat.root "$dirname"
+		fi
+	fi
+
+	return 0;
+}
+
+create_conf_directory()
+{
+	declare dirname="$1"
+
+	if [ -d "$dirname" ]; then
+		return 0;
+	fi
+	
+	mkdir -p "$dirname"
+	
+	return 0;
+}
+
+check_pid_file() {
+	declare pid_file="$1"
+
+	if [ -z "$pid_file" ]; then
+		return 1;
+	fi
+
+	if [ ! -e "$pid_file" ]; then
+		return 0;
+	fi
+
+	## if PID file is empty then it should be safe to remove it
+	read pid < "$pid_file"
+	if [ -z "$pid" ]; then
+		rm $pid_file
+		ocf_log debug "PID File \"$pid_file\" Was Removed - Zero length";
+		return 0;
+	fi
+
+	if [ ! -d /proc/`cat "$pid_file"` ]; then	
+		rm "$pid_file"
+		ocf_log debug "PID File \"$pid_file\" Was Removed - PID Does Not Exist";
+		return 0;
+	fi
+
+	return 1;
+}
diff --git a/rgmanager/src/resources/utils/fs-lib.sh b/rgmanager/src/resources/utils/fs-lib.sh
new file mode 100644
index 0000000..2697ed2
--- /dev/null
+++ b/rgmanager/src/resources/utils/fs-lib.sh
@@ -0,0 +1,1195 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+#
+# File system common functions
+#
+
+LC_ALL=C
+LANG=C
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+export LC_ALL LANG PATH
+
+# Private return codes
+FAIL=2
+NO=1
+YES=0
+YES_STR="yes"
+
+[ -z "$OCF_RESOURCE_INSTANCE" ] && export OCF_RESOURCE_INSTANCE="filesystem:$OCF_RESKEY_name"
+
+#
+# Using a global to contain the return value saves
+# clone() operations.  This is important to reduce
+# resource consumption during status checks.
+#
+# There is no way to return a string from a function
+# in bash without cloning the process, which is exactly
+# what we are trying to avoid.  So, we have to resort
+# to using a dedicated global variables.
+declare REAL_DEVICE
+declare STRIP_SLASHES=""
+declare FINDMNT_OUTPUT=""
+
+#
+# Stub ocf_log function for when we are using
+# quick_status, since ocf_log generally forks (and
+# sourcing ocf-shellfuncs forks -a lot-).
+#
+ocf_log()
+{
+	echo $*
+}
+
+#
+# Assume NFS_TRICKS are not available until we are
+# proved otherwise.
+#
+export NFS_TRICKS=1
+
+#
+# Quick status doesn't fork() or clone() when using
+# device files directly.  (i.e. not symlinks, LABEL= or
+# UUID=
+#
+if [ "$1" = "status" -o "$1" = "monitor" ] &&
+   [ "$OCF_RESKEY_quick_status" = "1" ]; then
+	echo Using Quick Status
+
+	# XXX maybe we can make ocf-shellfuncs have a 'quick' mode too?
+	export OCF_SUCCESS=0
+	export OCF_ERR_GENERIC=1
+else
+	#
+	# Grab nfs lock tricks if available
+	#
+	if [ -f "$(dirname $0)/svclib_nfslock" ]; then
+		. $(dirname $0)/svclib_nfslock
+		NFS_TRICKS=0
+	fi
+
+	. $(dirname $0)/ocf-shellfuncs
+fi
+
+
+verify_name()
+{
+	if [ -z "$OCF_RESKEY_name" ]; then
+		ocf_log err "No file system name specified."
+		return $OCF_ERR_ARGS
+	fi
+	return $OCF_SUCCESS
+}
+
+
+verify_mountpoint()
+{
+	if [ -z "$OCF_RESKEY_mountpoint" ]; then
+		ocf_log err "No mount point specified."
+		return $OCF_ERR_ARGS
+	fi
+
+	if ! [ -e "$OCF_RESKEY_mountpoint" ]; then
+		ocf_log info "Mount point $OCF_RESKEY_mountpoint will be "\
+				"created at mount time."
+		return $OCF_SUCCESS
+	fi
+
+	[ -d "$OCF_RESKEY_mountpoint" ] && return $OCF_SUCCESS
+
+	ocf_log err "$OCF_RESKEY_mountpoint exists but is not a directory."
+
+	return $OCF_ERR_ARGS
+}
+
+
+#
+# This used to be called using $(...), but doing this causes bash
+# to set up a pipe and clone().  So, the output of this function is
+# stored in the global variable REAL_DEVICE, declared previously.
+#
+real_device()
+{
+	declare dev="$1"
+	declare realdev
+
+	REAL_DEVICE=""
+
+	[ -z "$dev" ] && return $OCF_ERR_ARGS
+
+	# Oops, we have a link.  Sorry, this is going to fork.
+	if [ -h "$dev" ]; then
+		realdev=$(readlink -f $dev)
+		if [ $? -ne 0 ]; then
+			return $OCF_ERR_ARGS
+		fi
+		REAL_DEVICE="$realdev"
+		return $OCF_SUCCESS
+	fi
+
+	# If our provided blockdev is a device, we are done
+	if [ -b "$dev" ]; then
+		REAL_DEVICE="$dev"
+		return $OCF_SUCCESS
+	fi
+
+	# It's not a link, it's not a block device.  If it also
+	# does not match UUID= or LABEL=, then findfs is not
+	# going to find anything useful, so we should quit now.
+	if [ "${dev/UUID=/}" = "$dev" ] &&
+	   [ "${dev/LABEL=/}" = "$dev" ]; then
+		return $OCF_ERR_GENERIC
+	fi
+
+	# When using LABEL= or UUID=, we can't save a fork.
+	realdev=$(findfs "$dev" 2> /dev/null)
+	if [ -n "$realdev" ] && [ -b "$realdev" ]; then
+		REAL_DEVICE="$realdev"
+		return $OCF_SUCCESS
+	fi
+
+	return $OCF_ERR_GENERIC
+}
+
+
+verify_device()
+{
+	declare realdev
+
+	if [ -z "$OCF_RESKEY_device" ]; then
+	       ocf_log err "No device or label specified."
+	       return $OCF_ERR_ARGS
+	fi
+
+	real_device "$OCF_RESKEY_device"
+	realdev="$REAL_DEVICE"
+	if [ -n "$realdev" ]; then
+		if [ "$realdev" != "$OCF_RESKEY_device" ]; then
+			ocf_log info "Specified $OCF_RESKEY_device maps to $realdev"
+		fi
+		return $OCF_SUCCESS
+	fi
+
+	ocf_log err "Device or label \"$OCF_RESKEY_device\" not valid"
+
+	return $OCF_ERR_ARGS
+}
+
+##
+# Tries to use findmnt util to return list
+# of mountpoints for a device
+#
+# Global variables are used to reduce forking when capturing stdout.
+#
+# Return values
+# 0 - device mount points found, mountpoint list returned to FINDMNT_OUTPUT global variable
+# 1 - device mount not found
+# 2 - findmnt tool isn't found or can not be used
+#
+##
+try_findmnt()
+{
+	FINDMNT_OUTPUT=""
+
+	case $OCF_RESKEY_use_findmnt in
+	0|false|no|off)
+		return 2 ;;
+	*)
+		: ;;
+	esac
+
+	which findmnt > /dev/null 2>&1
+	if [ $? -eq 0 ]; then
+		FINDMNT_OUTPUT=$(findmnt -o TARGET --noheadings $1)
+		if [ $? -ne 0 ]; then
+			# workaround mount helpers inconsistency that still
+			# add / on the device entry in /proc/mounts
+			FINDMNT_OUTPUT=$(findmnt -o TARGET --noheadings $1/)
+			if [ $? -ne 0 ]; then
+				return 1
+			else
+				return 0
+			fi
+		else
+			return 0
+		fi
+	fi
+
+	return 2
+}
+
+##
+# Returns result in global variable to reduce forking
+##
+strip_trailing_slashes()
+{
+	local tmp=$1
+	while [ "${tmp#${tmp%?}}" = "/" ]
+	do
+		tmp="${tmp%/}"
+	done
+
+	STRIP_SLASHES="$tmp"
+}
+
+#
+# kill_procs_using_mount mount_point [signal]
+# 
+# Kill any processes using the specified mountpoint, using the optional 
+# specified signal. This is used in place of fuser to avoid it becoming
+# blocked while following symlinks to an unresponsive file system.  
+# Defaults to SIGKILL if no signal specified. 
+# 
+kill_procs_using_mount () {
+	declare mp
+	declare procs
+
+	if [ $# -lt 1 -o -z "$1" ]; then
+		ocf_log err "Usage: kill_procs_using_mount mount_point [signal]"
+		return $FAIL
+	fi
+
+	strip_trailing_slashes "$1"
+	mp="$STRIP_SLASHES"
+
+	if [ -z "$mp" ]; then
+		ocf_log err "Usage: kill_procs_using_mount mount_point [signal]"
+		return $FAIL
+	fi
+
+	# anything held open in mount point after the slash
+	procs=$(find /proc/[0-9]*/ -type l -lname "${mp}/*" -or -lname "${mp}" 2>/dev/null | awk -F/ '{print $3}' | uniq)
+
+	for pid in $procs; do
+		if [ -n "$2" ]; then
+			kill -s $2 $pid
+		else
+			kill -s KILL $pid
+		fi	
+	done
+
+	return $SUCCESS
+}
+
+#
+# mount_in_use device mount_point
+#
+# Check to see if either the device or mount point are in use anywhere on
+# the system.  It is not required that the device be mounted on the named
+# moint point, just if either are in use.
+#
+mount_in_use () {
+	declare mp tmp_mp
+	declare tmp_type
+	declare dev tmp_dev
+	declare junkb junkc junkd
+	declare res=$FAIL
+	declare findmnt_res=2
+
+	if [ $# -ne 2 ]; then
+		ocf_log err "Usage: mount_in_use device mount_point".
+		return $FAIL
+	fi
+
+	dev="$1"
+	mp="$2"
+
+	# First try and find out if the device has a mount point by
+	# attempting to use the findmnt tool. It is much faster than
+	# iterating through /proc/mounts
+	try_findmnt $dev
+	findmnt_res=$?
+	if [ $findmnt_res -eq 0 ]; then
+		case $OCF_RESKEY_fstype in
+		cifs|nfs|nfs4)
+			# -r means to include '/' character and not treat it as escape character
+			while read -r tmp_mp
+			do
+				if [ "$tmp_mp" = "$mp" ]; then
+					return $YES
+				fi
+			done < <(echo $FINDMNT_OUTPUT)
+			;;
+		*)
+			return $YES
+			;;
+		esac
+	fi
+
+	while read -r tmp_dev tmp_mp tmp_type junkb junkc junkd; do
+
+		if [ "$tmp_type" = "autofs" ]; then
+			continue
+		fi 
+
+		# Does the device match? We might have already tried findmnt
+		# which is why this could get skipped
+		if [ $findmnt_res -eq 2 ]; then
+			if [ "${tmp_dev:0:1}" != "-" ]; then
+				# XXX fork/clone warning XXX
+				tmp_dev="$(printf "$tmp_dev")"
+			fi
+
+			strip_trailing_slashes "$tmp_dev"
+			tmp_dev="$STRIP_SLASHES"
+			if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then
+				case $OCF_RESKEY_fstype in
+				cifs|nfs|nfs4)
+					;;
+				*)
+					return $YES
+					;;
+				esac
+			fi
+		fi
+
+		# Mountpoint from /proc/mounts containing spaces will
+		# have spaces represented in octal.  printf takes care
+		# of this for us.
+		tmp_mp="$(printf "$tmp_mp")"
+
+		if [ -n "$tmp_mp" -a "$tmp_mp" = "$mp" ]; then
+			return $YES
+		fi
+	done < <(cat /proc/mounts)
+
+	return $NO
+}
+
+##
+# Returns whether or not the device is mounted.
+# If the mountpoint does not match the one provided, the
+# mount point found is printed to stdout.
+##
+real_mountpoint()
+{
+	declare dev=$1
+	declare mp=$2
+	declare ret=$NO
+	declare tmp_mp
+	declare tmp_dev
+	declare tmp_type
+	declare found=1
+	declare poss_mp=""
+
+	try_findmnt $dev
+	case $? in
+	0)  #findmnt found mount points, loop through them to find a match
+
+		# -r means to include '/' character and not treat it as escape character
+		while read -r tmp_mp
+		do
+			ret=$YES
+			if [ "$tmp_mp" != "$mp" ]; then
+				poss_mp=$tmp_mp
+			else
+				found=0
+				break
+			fi
+		done < <(echo $FINDMNT_OUTPUT)
+		;;
+	1)
+		# findmnt found no mount points for the device
+		return $NO
+		;;
+	2)  # findmnt tool could not be used.
+		# Using slow method reading /proc/mounts dir.
+		while read -r tmp_dev tmp_mp tmp_type junk_b junk_c junk_d
+		do
+			if [ "$tmp_type" = "autofs" ]; then
+				continue
+			fi 
+
+			if [ "${tmp_dev:0:1}" != "-" ]; then
+				# XXX fork/clone warning XXX
+				tmp_dev="$(printf "$tmp_dev")"
+			fi
+
+			# CIFS mounts can sometimes have trailing slashes
+			# in their first field in /proc/mounts, so strip them.
+			strip_trailing_slashes "$tmp_dev"
+			tmp_dev="$STRIP_SLASHES"
+			real_device "$tmp_dev"
+			tmp_dev="$REAL_DEVICE"
+
+			# XXX fork/clone warning XXX
+			# Mountpoint from /proc/mounts containing spaces will
+			# have spaces represented in octal.  printf takes care
+			# of this for us.
+			tmp_mp="$(printf "$tmp_mp")"
+
+			if [ -n "$tmp_dev" -a "$tmp_dev" = "$dev" ]; then
+				ret=$YES
+				#
+				# Check to see if its mounted in the right
+				# place
+				#
+				if [ -n "$tmp_mp" ]; then
+					if [ "$tmp_mp" != "$mp" ]; then
+						poss_mp=$tmp_mp
+					else
+						found=0
+						break
+					fi
+				fi
+			fi
+		done < <(cat /proc/mounts)
+	esac
+
+	if [ $found -ne 0 ]; then
+		echo "$poss_mp"
+	fi
+	return $ret
+}
+
+#
+# is_mounted device mount_point
+#
+# Check to see if the device is mounted.  Print a warning if its not
+# mounted on the directory we expect it to be mounted on.
+#
+is_mounted () {
+
+	declare mp
+	declare dev
+	declare ret=$FAIL
+	declare poss_mp
+
+	if [ $# -ne 2 ]; then
+		ocf_log err "Usage: is_mounted device mount_point"
+		return $FAIL
+	fi
+
+	real_device "$1"
+	dev="$REAL_DEVICE"
+	if [ -z "$dev" ]; then
+		ocf_log err "$OCF_RESOURCE_INSTANCE: is_mounted: Could not match $1 with a real device"
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ -h "$2" ]; then
+		mp="$(readlink -f $2)"
+	else
+		mp="$2"
+	fi
+
+	# This bash glyph simply removes a trailing slash
+	# if one exists.  /a/b/ -> /a/b; /a/b -> /a/b.
+	mp="${mp%/}"
+
+	poss_mp=$(real_mountpoint "$dev" "$mp")
+	ret=$?
+
+	if [ $ret -eq $YES ] && [ -n "$poss_mp" ]; then
+		# if we made it here, then the device is mounted, but not where
+		# we expected it to be
+		case $OCF_RESKEY_fstype in
+		  cifs|nfs|nfs4)
+		    ret=$NO
+		    ;;
+		  *)
+		    ocf_log warn "Device $dev is mounted on $poss_mp instead of $mp"
+		    ;;
+		esac
+	fi
+
+
+	return $ret
+}
+
+
+#
+# is_alive mount_point
+#
+# Check to see if mount_point is alive (testing read/write)
+#
+is_alive()
+{
+	declare errcode
+	declare mount_point="$1"
+	declare file
+	declare rw
+
+	if [ $# -ne 1 ]; then
+	        ocf_log err "Usage: is_alive mount_point"
+		return $FAIL
+	fi
+
+	[ -z "$OCF_CHECK_LEVEL" ] && export OCF_CHECK_LEVEL=0
+
+	test -d "$mount_point"
+	if [ $? -ne 0 ]; then
+		ocf_log err "${OCF_RESOURCE_INSTANCE}: is_alive: $mount_point is not a directory"
+		return $FAIL
+	fi
+
+	[ $OCF_CHECK_LEVEL -lt 10 ] && return $YES
+
+	# depth 10 test (read test)
+	ls "$mount_point" > /dev/null 2> /dev/null
+	errcode=$?
+	if [ $errcode -ne 0 ]; then
+		ocf_log err "${OCF_RESOURCE_INSTANCE}: is_alive: failed read test on [$mount_point]. Return code: $errcode"
+		return $NO
+	fi
+
+	[ $OCF_CHECK_LEVEL -lt 20 ] && return $YES
+
+	# depth 20 check (write test)
+	rw=$YES
+	for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do
+                if [ "$o" = "ro" ]; then
+		        rw=$NO
+                fi
+	done
+	if [ $rw -eq $YES ]; then
+		file=$(mktemp "$mount_point/.check_writable.$(hostname).XXXXXX")
+		if [ ! -e $file ]; then
+			ocf_log err "${OCF_RESOURCE_INSTANCE}: is_alive: failed write test on [$mount_point]. Return code: $errcode"
+			return $NO
+		fi
+		rm -f $file > /dev/null 2> /dev/null
+	fi
+
+	return $YES
+}
+
+
+#
+# Decide which quota options are enabled and return a string
+# which we can pass to quotaon
+#
+quota_opts()
+{
+	declare quotaopts=""
+	declare opts="$1"
+	declare mopt
+
+	for mopt in `echo $opts | sed -e s/,/\ /g`; do
+		case $mopt in
+		quota)
+			quotaopts="gu"
+			break
+			;;
+		usrquota)
+			quotaopts="u$quotaopts"
+			continue
+			;;
+		grpquota)
+			quotaopts="g$quotaopts"
+			continue
+			;;
+		noquota)
+			quotaopts=""
+			return 0
+			;;
+		esac
+	done
+
+	echo $quotaopts
+	return 0
+}
+
+
+
+#
+# Enable quotas on the mount point if the user requested them
+#
+enable_fs_quotas()
+{
+	declare -i need_check=0
+	declare -i rv
+	declare quotaopts=""
+	declare mopt
+	declare opts="$1"
+	declare mp="$2"
+
+	if ! type quotaon &> /dev/null; then
+		ocf_log err "quotaon not found in $PATH"
+		return $OCF_ERR_GENERIC
+	fi
+
+	quotaopts=$(quota_opts $opts)
+	[ -z "$quotaopts" ] && return 0
+
+	ocf_log debug "quotaopts = $quotaopts"
+
+	# Ok, create quota files if they don't exist
+	for f in quota.user aquota.user quota.group aquota.group; do
+		if ! [ -f "$mp/$f" ]; then
+			ocf_log info "$mp/$f was missing - creating"
+			touch "$mp/$f"
+			chmod 600 "$mp/$f"
+			need_check=1
+		fi
+	done
+
+	if [ $need_check -eq 1 ]; then
+		ocf_log info "Checking quota info in $mp"
+		quotacheck -$quotaopts "$mp"
+	fi
+
+	ocf_log info "Enabling Quotas on $mp"
+	ocf_log debug "quotaon -$quotaopts \"$mp\""
+	quotaon -$quotaopts "$mp"
+	rv=$?
+	if [ $rv -ne 0 ]; then
+		# Just a warning
+		ocf_log warn "Unable to turn on quotas for $mp; return = $rv"
+	fi
+
+	return $rv
+}
+
+
+# Agent-specific actions to take before mounting
+# (if required).  Typically things like fsck.
+do_pre_mount() {
+	return 0
+}
+
+# Default mount handler - for block devices
+#
+do_mount() {
+	declare dev="$1"
+	declare mp="$2"
+	declare mount_options=""
+	declare fstype_option=""
+	declare fstype
+
+	#
+	# Get the filesystem type, if specified.
+	#
+	fstype_option=""
+	fstype=${OCF_RESKEY_fstype}
+	case "$fstype" in
+	""|"[ 	]*")
+		fstype=""
+		;;
+	*)	# found it
+		fstype_option="-t $fstype"
+		;;
+	esac
+
+	#
+	# Get the mount options, if they exist.
+	#
+	mount_options=""
+	opts=${OCF_RESKEY_options}
+	case "$opts" in
+	""|"[ 	]*")
+		opts=""
+		;;
+	*)	# found it
+		mount_options="-o $opts"
+		;;
+	esac
+
+	#
+	# Mount the device
+	#
+	ocf_log info "mounting $dev on $mp"
+	ocf_log err "mount $fstype_option $mount_options $dev $mp"
+	mount $fstype_option $mount_options "$dev" "$mp"
+	ret_val=$?
+	if [ $ret_val -ne 0 ]; then
+		ocf_log err "\
+'mount $fstype_option $mount_options $dev $mp' failed, error=$ret_val"
+		return 1
+	fi
+
+	return 0
+}
+
+
+# Agent-specific actions to take after mounting
+# (if required).
+do_post_mount() {
+	return 0
+}
+
+
+# Agent-specific actions to take before unmounting
+# (if required)
+do_pre_unmount() {
+	return 0
+}
+
+
+# Agent-specific actions to take after umount succeeds
+# (if required)
+do_post_unmount() {
+	return 0
+}
+
+
+# Agent-specific force unmount logic, if required
+# return = nonzero if successful, or 0 if unsuccessful
+# (unsuccessful = try harder)
+do_force_unmount() {
+	return 1
+}
+
+
+#
+# start_filesystem
+#
+start_filesystem() {
+	declare -i ret_val=$OCF_SUCCESS
+	declare mp="${OCF_RESKEY_mountpoint}"
+	declare dev=""			# device
+	declare fstype=""
+	declare opts=""
+	declare mount_options=""
+
+	#
+	# Check if mount point was specified.  If not, no need to continue.
+	#
+	case "$mp" in
+	""|"[ 	]*")		# nothing to mount
+		return $OCF_SUCCESS
+		;;
+	/*)			# found it
+		;;
+	*)			# invalid format
+			ocf_log err \
+"start_filesystem: Invalid mount point format (must begin with a '/'): \'$mp\'"
+		return $OCF_ERR_ARGS
+		;;
+	esac
+
+	#
+	# Get the device
+	#
+	real_device "$OCF_RESKEY_device"
+	dev="$REAL_DEVICE"
+	if [ -z "$dev" ]; then
+			ocf_log err "\
+start_filesystem: Could not match $OCF_RESKEY_device with a real device"
+			return $OCF_ERR_ARGS
+	fi
+
+	#
+	# Ensure we've got a valid directory
+	#
+	if [ -e "$mp" ]; then
+		if ! [ -d "$mp" ]; then
+			ocf_log err"\
+start_filesystem: Mount point $mp exists but is not a directory"
+			return $OCF_ERR_ARGS
+		fi
+	else
+		ocf_log err "\
+start_filesystem: Creating mount point $mp for device $dev"
+		mkdir -p "$mp"
+		ret_val=$?
+		if [ $ret_val -ne 0 ]; then
+			ocf_log err "\
+start_filesystem: Unable to create $mp.  Error code: $ret_val"
+			return $OCF_ERR_GENERIC
+		fi
+	fi
+
+	#
+	# See if the device is already mounted.
+	#
+	is_mounted "$dev" "$mp"
+	case $? in
+	$YES)		# already mounted
+		ocf_log debug "$dev already mounted"
+		return $OCF_SUCCESS
+		;;
+	$NO)		# not mounted, continue
+		;;
+	*)
+		return $FAIL
+		;;
+	esac
+
+
+	#
+	# Make sure that neither the device nor the mount point are mounted
+	# (i.e. they may be mounted in a different location).  The'mount_in_use'
+	# function checks to see if either the device or mount point are in
+	# use somewhere else on the system.
+	#
+	mount_in_use "$dev" "$mp"
+	case $? in
+	$YES)		# uh oh, someone is using the device or mount point
+		ocf_log err "\
+Cannot mount $dev on $mp, the device or mount point is already in use!"
+		return $FAIL
+		;;
+	$NO)		# good, no one else is using it
+		;;
+	$FAIL)
+		return $FAIL
+		;;
+	*)
+		ocf_log err "Unknown return from mount_in_use"
+		return $FAIL
+		;;
+	esac
+
+	do_pre_mount
+	case $? in
+	0)
+		;;
+	1)
+		return $OCF_ERR_GENERIC
+		;;
+	2)
+		return $OCF_SUCCESS
+		;;
+	esac
+
+	do_mount "$dev" "$mp"
+	case $? in
+	0)
+		;;
+	1)
+		return $OCF_ERR_GENERIC
+		;;
+	2)
+		return $OCF_SUCCESS
+		;;
+	esac
+
+	do_post_mount
+	case $? in
+	0)
+		;;
+	1)
+		return $OCF_ERR_GENERIC
+		;;
+	2)
+		return $OCF_SUCCESS
+		;;
+	esac
+
+	enable_fs_quotas "$opts" "$mp"
+
+	return $OCF_SUCCESS
+}
+
+
+#
+# stop_filesystem - unmount a file system; calls out to
+#
+stop_filesystem() {
+	declare -i ret_val=0
+	declare -i try
+	declare -i sleep_time=5		# time between each umount failure
+	declare umount_failed=""
+	declare force_umount=""
+	declare self_fence=""
+	declare quotaopts=""
+
+	#
+	# Get the mount point, if it exists.  If not, no need to continue.
+	#
+	mp=${OCF_RESKEY_mountpoint}
+	case "$mp" in
+	""|"[ 	]*")		# nothing to mount
+		return $OCF_SUCCESS
+		;;
+	/*)			# found it
+		;;
+	*)		# invalid format
+			ocf_log err \
+"stop_filesystem: Invalid mount point format (must begin with a '/'): \'$mp\'"
+		return $FAIL
+		;;
+	esac
+
+	#
+	# Get the device
+	#
+	real_device "$OCF_RESKEY_device"
+	dev="$REAL_DEVICE"
+	if [ -z "$dev" ]; then
+			ocf_log err "\
+stop: Could not match $OCF_RESKEY_device with a real device"
+			return $OCF_ERR_INSTALLED
+	fi
+
+	#
+	# Get the force unmount setting if there is a mount point.
+	#
+	case ${OCF_RESKEY_force_unmount} in
+        $YES_STR)	force_umount=$YES ;;
+	on)		force_umount=$YES ;;
+	true)		force_umount=$YES ;;
+	1)		force_umount=$YES ;;
+        *)		force_umount="" ;;
+	esac
+
+	#
+	# self_fence _MUST_ be initialized before calling do_pre_unmount
+	# The netfs agent depends on the self_fence variable.
+	#
+	case ${OCF_RESKEY_self_fence} in
+        $YES_STR)	self_fence=$YES ;;
+	on)		self_fence=$YES ;;
+	true)		self_fence=$YES ;;
+	1)		self_fence=$YES ;;
+        *)		self_fence="" ;;
+	esac
+
+	do_pre_unmount
+	case $? in
+	0)
+		;;
+	1)
+		return $OCF_ERR_GENERIC
+		;;
+	2)
+		return $OCF_SUCCESS
+		;;
+	esac
+
+	#
+	# Preparations: sync, turn off quotas
+	#
+	sync
+
+	quotaopts=$(quota_opts $OCF_RESKEY_options)
+	if [ -n "$quotaopts" ]; then
+		ocf_log debug "Turning off quotas for $mp"
+		quotaoff -$quotaopts "$mp" &> /dev/null
+	fi
+
+	#
+	# Unmount the device.
+	#
+	for try in 1 2 3; do
+		if [ $try -ne 1 ]; then
+			sleep $sleep_time
+		fi
+
+		is_mounted "$dev" "$mp"
+		case $? in
+		$NO)
+			ocf_log info "$dev is not mounted"
+			umount_failed=
+			break
+			;;
+		$YES)	# fallthrough
+			;;
+		*)
+			return $FAIL
+			;;
+		esac
+
+		case ${OCF_RESKEY_no_unmount} in
+			yes|YES|true|TRUE|YES|on|ON|1)
+				ocf_log debug "Skipping umount on stop because of 'no_unmount' option"
+				return $OCF_SUCCESS
+				;;
+			*) : ;;
+		esac
+
+		ocf_log info "unmounting $mp"
+		umount "$mp"
+		ret_val=$?
+		# some versions of umount will exit with status 16 iff
+		# the umount(2) succeeded but /etc/mtab could not be written.
+		if  [ $ret_val -eq 0 -o $ret_val -eq 16 ]; then
+			umount_failed=
+			break
+		fi
+
+		ocf_log debug "umount failed: $ret_val"
+		umount_failed=yes
+
+		if [ -z "$force_umount" ]; then
+			continue
+		fi
+
+		# Force unmount: try #1: send SIGTERM
+		if [ $try -eq 1 ]; then
+			# Try fs-specific force unmount, if provided
+			do_force_unmount
+			if [ $? -eq 0 ]; then
+				# if this succeeds, we should be done
+				continue
+			fi
+
+			ocf_log warning "Sending SIGTERM to processes on $mp"
+			kill_procs_using_mount "$mp" "TERM"
+			continue
+		else
+			ocf_log warning "Sending SIGKILL to processes on $mp"
+			kill_procs_using_mount "$mp"
+
+			if [ $? -eq 0 ]; then
+				# someone is still accessing the mount, We've already sent
+				# SIGTERM, now we've sent SIGKILL and are trying umount again.
+				continue
+			fi
+			# mount has failed, and no one is accessing it.  There's
+			# nothing left for us to try.
+			break
+		fi
+	done # for
+
+	do_post_unmount
+	case $? in
+	0)
+		;;
+	1)
+		return $OCF_ERR_GENERIC
+		;;
+	2)
+		return $OCF_SUCCESS
+		;;
+	esac
+
+	if [ -n "$umount_failed" ]; then
+		ocf_log err "'umount $mp' failed, error=$ret_val"
+
+		if [ "$self_fence" ]; then
+			ocf_log alert "umount failed - REBOOTING"
+			sync
+			reboot -fn
+		fi
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $OCF_SUCCESS
+}
+
+
+do_start() {
+	declare tries=0
+	declare rv
+
+	while [ $tries -lt 3 ]; do
+		start_filesystem
+		rv=$?
+		if [ $rv -eq 0 ]; then
+			return 0
+		fi
+
+		((tries++))
+		sleep 3
+	done
+	return $rv
+}
+
+
+do_stop() {
+	stop_filesystem
+	return $?
+}
+
+
+do_monitor() {
+	ocf_log debug "Checking fs \"$OCF_RESKEY_name\", Level $OCF_CHECK_LEVEL"
+
+	#
+	# Get the device
+	#
+	real_device "$OCF_RESKEY_device"
+	dev="$REAL_DEVICE"
+	if [ -z "$dev" ]; then
+			ocf_log err "\
+start_filesystem: Could not match $OCF_RESKEY_device with a real device"
+			return $OCF_NOT_RUNNING
+	fi
+
+	is_mounted "$dev" "${OCF_RESKEY_mountpoint}"
+
+	if [ $? -ne $YES ]; then
+		ocf_log err "${OCF_RESOURCE_INSTANCE}: ${OCF_RESKEY_device} is not mounted on ${OCF_RESKEY_mountpoint}"
+		return $OCF_NOT_RUNNING
+	fi
+
+	if [ "$OCF_RESKEY_quick_status" = "1" ]; then
+		return 0
+	fi
+
+	is_alive "${OCF_RESKEY_mountpoint}"
+	[ $? -eq $YES ] && return 0
+
+	ocf_log err "fs:${OCF_RESKEY_name}: Mount point is not accessible!"
+	return $OCF_ERR_GENERIC
+}
+
+
+do_restart() {
+	stop_filesystem
+	if [ $? -ne 0 ]; then
+		return $OCF_ERR_GENERIC
+	fi
+
+	start_filesystem
+	if [ $? -ne 0 ]; then
+		return $OCF_ERR_GENERIC
+	fi
+
+	return 0
+}
+
+
+# MUST BE OVERRIDDEN
+do_metadata() {
+	return 1
+}
+
+
+do_validate() {
+	return 1
+}
+
+
+main() {
+	case $1 in
+	start)
+		do_start
+		exit $?
+		;;
+	stop)
+		do_stop
+		exit $?
+		;;
+	status|monitor)
+		do_monitor
+		exit $?
+		;;
+	restart)
+		do_restart
+		exit $?
+		;;
+	meta-data)
+		do_metadata
+		exit $?
+		;;
+	validate-all)
+		do_validate
+		;;
+	*)
+		echo "usage: $0 {start|stop|status|monitor|restart|meta-data|validate-all}"
+		exit $OCF_ERR_UNIMPLEMENTED
+		;;
+	esac
+	exit 0
+}
+
diff --git a/rgmanager/src/resources/utils/httpd-parse-config.pl b/rgmanager/src/resources/utils/httpd-parse-config.pl
new file mode 100755
index 0000000..5b643f6
--- /dev/null
+++ b/rgmanager/src/resources/utils/httpd-parse-config.pl
@@ -0,0 +1,83 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+##
+##  This script removes <IfDefine foo> sections from the
+##  Apache httpd.conf file. This is quite useful because we
+##  don't have any direct access to the parsed configuration
+##  file of the httpd server.
+##
+##  Usage: ./httpd-parse-config.pl -Dfoo1 -Dfoo2 < httpd.conf
+##         where fooX are defines as passed to the httpd server
+##
+##  Note:  All whitespace characters at the beginning and end 
+##         of lines are removed.
+##
+use strict;
+
+my @defines = ();
+## Default behaviour is to show all lines when we are not
+## in the <IfDefine foo> sections.
+my @show = (1);
+
+sub testIfDefine($) {
+	my $param = $1;
+	my $positiveTest = 1;
+	if ($param =~ /^!(.*)$/) {
+		$param = $1;
+		$positiveTest = 0;
+	}
+
+	foreach my $def (@defines) {
+		if ($def eq $param) {
+			return $positiveTest;
+		}
+	}
+
+	return (1-$positiveTest);	
+}
+
+foreach my $arg (@ARGV) {
+	if ($arg =~ /^-D(.*)$/) {
+		push(@defines, $1);
+	}
+}
+
+## Parse config file and remove IfDefine sections 
+while (my $line = <STDIN>) {
+	chomp($line);
+	$line =~ s/^\s*(.*?)\s*$/$1/;
+	if ($line =~ /<IfDefine (.*)>/) {
+		if (testIfDefine($1) == 1) {
+			if ($show[$#show] == 1) {
+				push (@show, 1);
+			} else {
+				push (@show, 0);
+			}
+		} else {
+			push (@show, 0);
+		}
+	} elsif ($line =~ /<\/IfDefine>/) {
+		pop(@show);
+	} elsif ($show[$#show] == 1) {
+		print $line, "\n";
+	}
+}
+
diff --git a/rgmanager/src/resources/utils/member_util.sh b/rgmanager/src/resources/utils/member_util.sh
new file mode 100644
index 0000000..02fba77
--- /dev/null
+++ b/rgmanager/src/resources/utils/member_util.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+#
+# Use corosync-quorumtool to figure out if the specified node is a member
+# of the cluster.  Returns 1 if not a member, and
+# 0 if the node is happily running.
+#
+# Tested on RHEL6 and F17  Note that the old version of this function utilized
+# clustat, which had introspection in to the configuration.
+# If a node was not found, the old version would return '2', but the only
+# consumer of this function never cared about that value.
+#
+is_node_member_clustat()
+{
+	# Still having a tag while (a) online but (b) not running pacemaker 
+	# (e.g. crm_node) or rgmanager not considered adequate for things like
+	# the LVM agent - so we use corosync-quorumtool instead.  The function
+	# name really should be changed.
+	#
+	# corosync 1.4.1 output looks like:
+	#
+	#  # corosync-quorumtool  -l
+	#  Nodeid     Name
+	#     1   rhel6-1
+	#     2   rhel6-2
+	#
+	# corosync 2.0.1 output looks like:
+	#  # corosync-quorumtool -l
+	#
+	#  Membership information
+	#  ----------------------
+	#      Nodeid      Votes Name
+	#           1          1 rhel7-1.priv.redhat.com
+	#           2          1 rhel7-2.priv.redhat.com
+	#
+	corosync-quorumtool -l | grep -v "^Nodeid" | grep -i " $1\$" &> /dev/null
+	return $?
+}
+
+
+#
+# Print the local node name to stdout
+# Returns 0 if could be found, 1 if not
+# Tested on RHEL6 (cman) and Fedora 17 (corosync/pacemaker)
+#
+local_node_name()
+{
+	local node nid localid
+
+	if which magma_tool &> /dev/null; then
+		# Use magma_tool, if available.
+		line=$(magma_tool localname | grep "^Local")
+
+		if [ -n "$line" ]; then
+			echo ${line/* = /}
+			return 0
+		fi
+	fi
+
+	if which cman_tool &> /dev/null; then
+		# Use cman_tool
+
+		line=$(cman_tool status | grep -i "Node name: $1")
+		[ -n "$line" ] || return 1
+		echo ${line/*name: /}
+		return 0
+	fi
+
+	if ! which crm_node &> /dev/null; then
+		# no crm_node? :(
+		return 2
+	fi
+
+	localid=$(crm_node -i)
+	while read nid node; do
+		if [ "$nid" = "$localid" ]; then
+			echo $node
+			return 0
+		fi
+	done < <(crm_node -l)
+
+	return 1
+}
+
diff --git a/rgmanager/src/resources/utils/messages.sh b/rgmanager/src/resources/utils/messages.sh
new file mode 100644
index 0000000..0f8d7ff
--- /dev/null
+++ b/rgmanager/src/resources/utils/messages.sh
@@ -0,0 +1,269 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+declare CLOG_INIT=100
+declare CLOG_SUCCEED=200
+declare CLOG_SUCCEED_KILL=201
+
+declare CLOG_FAILED=400
+declare CLOG_FAILED_TIMEOUT=401
+declare CLOG_FAILED_NOT_FOUND=403
+declare CLOG_FAILED_INVALID=404
+declare CLOG_FAILED_NOT_READABLE=405
+declare CLOG_FAILED_KILL=406
+
+##
+## Usage:
+##	clog_service_start %operation%
+##
+clog_service_start()
+{
+	case $1 in
+		$CLOG_INIT)
+			ocf_log info "Starting Service $OCF_RESOURCE_INSTANCE"
+			;;
+		$CLOG_SUCCEED)
+			ocf_log debug "Starting Service $OCF_RESOURCE_INSTANCE > Succeed"
+			;;
+		$CLOG_FAILED)
+			ocf_log error "Starting Service $OCF_RESOURCE_INSTANCE > Failed"
+			;;
+		$CLOG_FAILED_TIMEOUT)
+			ocf_log error "Starting Service $OCF_RESOURCE_INSTANCE > Failed - Timeout Error"
+			;;
+	esac
+	return 0
+}
+
+##
+## Usage:
+##	clog_service_stop %operation%
+##
+clog_service_stop()
+{
+	case $1 in
+		$CLOG_INIT)
+			ocf_log info "Stopping Service $OCF_RESOURCE_INSTANCE"
+			;;
+		$CLOG_SUCCEED)
+			ocf_log info "Stopping Service $OCF_RESOURCE_INSTANCE > Succeed"
+			;;
+		$CLOG_SUCCEED_KILL)
+			ocf_log info "Killing Service $OCF_RESOURCE_INSTANCE > Succeed"
+			;;
+		$CLOG_FAILED)
+			ocf_log error "Stopping Service $OCF_RESOURCE_INSTANCE > Failed"
+			;;
+		$CLOG_FAILED_NOT_STOPPED)
+			ocf_log error "Stopping Service $OCF_RESOURCE_INSTANCE > Failed - Application Is Still Running"
+			;;
+		$CLOG_FAILED_KILL)
+			ocf_log error "Killing Service $OCF_RESOURCE_INSTANCE > Failed"
+			;;
+	esac
+	return 0
+}
+
+##
+## Usage:
+##	clog_service_status %operation%
+##
+clog_service_status()
+{
+	case $1 in
+		$CLOG_INIT)
+			ocf_log debug "Monitoring Service $OCF_RESOURCE_INSTANCE"
+			;;
+		$CLOG_SUCCEED)
+			ocf_log debug "Monitoring Service $OCF_RESOURCE_INSTANCE > Service Is Running"
+			;;
+		$CLOG_FAILED)
+			ocf_log error "Monitoring Service $OCF_RESOURCE_INSTANCE > Service Is Not Running"
+			;;
+		$CLOG_FAILED_NOT_FOUND)
+			ocf_log error "Monitoring Service $OCF_RESOURCE_INSTANCE > Service Is Not Running - PID File Not Found"
+			;;
+	esac
+	return 0
+}
+
+##
+## Usage:
+##	clog_service_verify %operation%
+##	clog_service_verify $CLOG_FAILED %reason%
+##
+clog_service_verify()
+{
+	case $1 in
+		$CLOG_INIT)
+			ocf_log debug "Verifying Configuration Of $OCF_RESOURCE_INSTANCE"
+			;;
+		$CLOG_SUCCEED)
+			ocf_log debug "Verifying Configuration Of $OCF_RESOURCE_INSTANCE > Succeed"
+			;;
+		$CLOG_FAILED_NOT_CHILD)
+			ocf_log error "Service $OCF_RESOURCE_INSTANCE Is Not A Child Of A Service"
+			;;
+		$CLOG_FAILED)
+			if [ "x$2" = "x" ]; then
+				ocf_log error "Verifying Configuration Of $OCF_RESOURCE_INSTANCE > Failed"
+			else
+				ocf_log error "Verifying Configuration Of $OCF_RESOURCE_INSTANCE > Failed - $2"
+			fi
+			;;
+	esac
+	return 0
+}
+
+
+##
+## Usage:
+##	clog_check_sha1 %operation% %filename%
+##
+clog_check_sha1()
+{
+	case $1 in
+		$CLOG_INIT)
+			ocf_log debug "Checking SHA1 Checksum Of File $1"
+			;;
+		$CLOG_SUCCEED)
+			ocf_log debug "Checking SHA1 Checksum Of File > Succeed"
+			;;
+		$CLOG_FAILED)
+			ocf_log debug "Checking SHA1 Checksum Of File > Failed - File Changed"
+			;;
+	esac
+	return 0;
+} 
+
+##
+## Usage:
+##	clog_check_file_exist %operation% %filename%
+##
+clog_check_file_exist()
+{
+	case $1 in
+		$CLOG_INIT)
+			ocf_log debug "Checking Existence Of File $2"
+			;;
+		$CLOG_SUCCEED)
+			ocf_log debug "Checking Existence Of File $2 > Succeed"
+			;;
+		$CLOG_FAILED)
+			ocf_log error "Checking Existence Of File $2 [$OCF_RESOURCE_INSTANCE] > Failed"
+			;;
+		$CLOG_FAILED_INVALID)
+			ocf_log error "Checking Existence Of File $2 [$OCF_RESOURCE_INSTANCE] > Failed - Invalid Argument"
+			;;
+		$CLOG_FAILED_NOT_FOUND)
+			ocf_log error "Checking Existence Of File $2 [$OCF_RESOURCE_INSTANCE] > Failed - File Doesn't Exist"
+			;;
+		$CLOG_FAILED_NOT_READABLE)
+			ocf_log error "Checking Existence Of File $2 [$OCF_RESOURCE_INSTANCE] > Failed - File Is Not Readable"
+			;;
+	esac
+	return 0;
+} 
+
+##
+## Usage:
+##	clog_check_pid %operation% %filename%
+##
+clog_check_pid()
+{
+	case $1 in
+		$CLOG_INIT)
+			ocf_log debug "Checking Non-Existence Of PID File $2"
+			return 0
+			;;
+		$CLOG_SUCCEED)
+			ocf_log debug "Checking Non-Existence of PID File $2 > Succeed"
+			;;
+		$CLOG_FAILED)
+			ocf_log error "Checking Non-Existence of PID File $2 [$OCF_RESOURCE_INSTANCE] > Failed - PID File Exists For $OCF_RESOURCE_INSTANCE"
+			;;
+	esac
+	return 0;
+}
+
+##
+## Usage:
+##	clog_check_syntax %operation% %filename%
+##
+clog_check_syntax()
+{
+	case $1 in
+		$CLOG_INIT)
+			ocf_log debug "Checking Syntax Of The File $2"
+			;;
+		$CLOG_SUCCEED)
+			ocf_log debug "Checking Syntax Of The File $2 > Succeed"
+			;;
+		$CLOG_FAILED)
+			ocf_log error "Checking Syntax Of The File $2 [$OCF_RESOURCE_INSTANCE] > Failed"
+			;;		
+	esac
+	return 0;
+}
+
+##
+## Usage:
+##	clog_generate_config %operation% %old filename% %new filename%
+##
+clog_generate_config()
+{
+	case $1 in
+		$CLOG_INIT)
+			ocf_log debug "Generating New Config File $3 From $2"
+			;;
+		$CLOG_SUCCEED)
+			ocf_log debug "Generating New Config File $3 From $2 > Succeed"
+			;;
+		$CLOG_FAILED)
+			ocf_log error "Generating New Config File $3 From $2 [$OCF_RESOURCE_INSTANCE] > Failed"
+			;;		
+	esac
+	return 0;
+}
+
+##
+## Usage:
+##	clog_looking_for %operation% %resource%
+##	clog_looking_for %operation% "IP Addresses"
+##	clog_looking_for %operation% "Filesystems"
+##
+clog_looking_for()
+{
+	case $1 in
+		$CLOG_INIT)
+			ocf_log debug "Looking For $2"
+			;;
+		$CLOG_SUCCEED)
+			ocf_log debug "Looking For $2 > Succeed - $3 $2 Found"
+			;;
+		$CLOG_FAILED)
+			ocf_log error "Looking For $2 [$OCF_RESOURCE_INSTANCE] > Failed"
+			;;		
+		$CLOG_FAILED_NOT_FOUND)
+			ocf_log error "Looking For $2 [$OCF_RESOURCE_INSTANCE] > Failed - No $2 Found"
+			;;		
+	esac
+	return 0;
+}
diff --git a/rgmanager/src/resources/utils/named-parse-config.pl b/rgmanager/src/resources/utils/named-parse-config.pl
new file mode 100644
index 0000000..a941a60
--- /dev/null
+++ b/rgmanager/src/resources/utils/named-parse-config.pl
@@ -0,0 +1,49 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+##
+##  Parse named.conf (from STDIN) and add options from cluster.conf
+##  
+##  ./named-parse-config.pl "directory" "pid-file" "listen-on" "set source <true | false>"
+##
+use strict;
+
+if ($#ARGV < 3) {
+	die ("Not enough arguments");
+}
+
+while (my $line = <STDIN>) {
+	chomp($line);
+	$line =~ s/(.*?)\s*$/$1/;
+	if ($line =~ /^\s*options\s+\{/) {
+		print $line, "\n";
+		print "\tdirectory \"$ARGV[0]\";\n";
+		print "\tpid-file \"$ARGV[1]\";\n";
+		print "\tlisten-on { $ARGV[2] };\n";
+		if ($ARGV[3] =~ "1|true|TRUE|yes|YES|on|ON") {
+			print "\tnotify-source $ARGV[2];\n";
+			print "\ttransfer-source $ARGV[2];\n";
+			print "\tquery-source $ARGV[2];\n";
+		}
+	} else {
+		print $line, "\n";
+	}
+}
+
diff --git a/rgmanager/src/resources/utils/ra-skelet.sh b/rgmanager/src/resources/utils/ra-skelet.sh
new file mode 100644
index 0000000..cdee5c4
--- /dev/null
+++ b/rgmanager/src/resources/utils/ra-skelet.sh
@@ -0,0 +1,156 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+status_check_pid()
+{
+	declare pid_file="$1"
+
+	if [ -z "$pid_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_INVALID "$pid_file"
+		return $OCF_ERR_GENERIC
+	fi
+
+	if [ ! -e "$pid_file" ]; then
+		clog_check_file_exist $CLOG_FAILED "$pid_file"
+		return $OCF_NOT_RUNNING
+	fi
+
+	read pid < "$pid_file"
+	
+	if [ -z "$pid" ]; then
+		return $OCF_ERR_GENERIC
+	fi
+	
+	if [ ! -d /proc/$pid ]; then
+		return $OCF_ERR_GENERIC
+	fi	
+
+	return 0
+}
+
+stop_generic()
+{
+	declare pid_file="$1"
+	declare stop_timeout="$2"
+	declare stop_sig="$3"
+	declare pid;
+	declare count=0;
+
+	if [ -z "$stop_sig" ]; then
+		stop_sig="-TERM"
+	fi
+
+	if [ ! -e "$pid_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_NOT_FOUND "$pid_file"
+		# In stop-after-stop situation there is no PID file but
+		# it will be nice to check for it in stop-after-start
+		# look at bug #449394
+		return 0
+	fi
+
+	if [ -z "$stop_timeout" ]; then
+		stop_timeout=20
+	fi
+
+	read pid < "$pid_file"
+
+	# @todo: PID file empty -> error?
+	if [ -z "$pid" ]; then
+		return 0;
+	fi
+
+	# @todo: PID is not running -> error?
+	if [ ! -d "/proc/$pid" ]; then
+		return 0;
+	fi
+
+	kill $stop_sig "$pid"
+
+	if [ $? -ne 0 ]; then
+		return $OCF_ERR_GENERIC
+	fi
+
+	until [ `ps --pid "$pid" &> /dev/null; echo $?` = '1' ] || [ $count -gt $stop_timeout ]
+	do
+		sleep 1
+		let count=$count+1
+	done
+
+	if [ $count -gt $stop_timeout ]; then
+		clog_service_stop $CLOG_FAILED_NOT_STOPPED
+		return $OCF_ERR_GENERIC
+	fi
+	
+	return 0;
+}
+
+stop_generic_sigkill() {
+	# Use stop_generic (kill -TERM) and if application did not stop
+	# correctly then use kill -QUIT and check if it was killed
+	declare pid_file="$1"
+	declare stop_timeout="$2"
+	declare kill_timeout="$3"
+	declare stop_sig="$4"
+	declare pid
+
+	if [ -z "$stop_sig" ]; then
+		stop_sig="-TERM"
+	fi
+	## If stop_timeout is equal to zero then we do not want
+	## to give -TERM signal at all.
+	if [ $stop_timeout -ne 0 ]; then
+		stop_generic "$pid_file" "$stop_timeout" "$stop_sig"
+		if [ $? -eq 0 ]; then
+			return 0;
+		fi
+	fi
+	
+	if [ ! -e "$pid_file" ]; then
+		clog_check_file_exist $CLOG_FAILED_NOT_FOUND "$pid_file"
+		# In stop-after-stop situation there is no PID file but
+		# it will be nice to check for it in stop-after-start
+		# look at bug #449394
+		return 0
+	fi
+	read pid < "$pid_file"
+
+	if [ -z "$pid" ]; then
+		return 0;
+	fi
+
+	if [ ! -d "/proc/$pid" ]; then
+		return 0;
+	fi
+
+	kill -QUIT "$pid"
+	if [ $? -ne 0 ]; then
+		return $OCF_GENERIC_ERROR
+	fi
+	
+	sleep "$kill_timeout"
+	ps --pid "$pid" &> /dev/null
+	if [ $? -eq 0 ]; then
+		clog_service_stop $CLOG_FAILED_KILL
+		return $OCF_ERR_GENERIC
+	fi
+	
+	clog_service_stop $CLOG_SUCCEED_KILL
+	return 0
+}
diff --git a/rgmanager/src/resources/utils/rhev-check.sh b/rgmanager/src/resources/utils/rhev-check.sh
new file mode 100644
index 0000000..0529c31
--- /dev/null
+++ b/rgmanager/src/resources/utils/rhev-check.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+MYNAME=`basename $0`
+
+do_log()
+{
+	declare severity=$1
+
+	shift
+	echo "<$severity> $*"
+	clulog -s $severity "$*"
+}
+
+if [ -z "$1" ]; then
+	do_log 4 No host specified.
+	exit 1
+fi
+
+do_log 6 "Checking RHEV status on $1"
+
+tries=3
+http_code=
+
+while [ $tries -gt 0 ]; do
+
+	# Record start/end times so we can calculate the difference
+	start_time=$(date +%s)
+	http_code="$(curl -m 10 -sk https://$1/RHEVManagerWeb/HealthStatus.aspx -D - | head -1 | cut -f2 -d' ')"
+
+	if [ "$http_code" = "200" ]; then
+		exit 0
+	fi
+
+	# Reduce sleep time if the attempt took a noticeable amount
+	# of time.
+	end_time=$(date +%s)
+	delta=$(((end_time - start_time)))
+	sleep_time=$(((90 - delta)))
+
+	((tries-=1))
+
+	# if we're going to retry and we have a nonzero sleep time,
+	# go to sleep.
+	if [ $tries -gt 0 ] && [ $sleep_time -gt 0 ]; then
+		sleep $sleep_time
+	fi
+done
+
+if [ -n "$http_code" ]; then
+	do_log 3 "RHEV Status check on $1 failed; last HTTP code: $http_code"
+else
+	do_log 3 "RHEV Status check on $1 failed"
+fi
+
+exit 1
diff --git a/rgmanager/src/resources/utils/tomcat-parse-config.pl b/rgmanager/src/resources/utils/tomcat-parse-config.pl
new file mode 100644
index 0000000..7c9badf
--- /dev/null
+++ b/rgmanager/src/resources/utils/tomcat-parse-config.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+##
+##  This script replace IP addresses on which tomcat server
+##  should listen. Tomcat can't listen on every IP because that 
+##  way we can run only on instance. 
+##
+##  Usage: ./tomcat-parse-config.pl ip1 ip2 < /etc/tomcat/server.xml
+##         where ipXX defines an IP address [eg. 127.0.0.1 134.45.11.1]
+##
+##
+use strict;
+
+while (my $line = <STDIN>) {
+	chomp ($line);
+
+	if ($line =~ /(.*?)<Connector (.*)/) {
+		my $tmp = $2;
+		my $content = "<Connector ";
+		my $start = $1;
+		my $rest = "";
+
+		while (($tmp =~ />/) == 0) {
+			$content .= $tmp . "\n";
+			$tmp = <STDIN>;
+			chomp($tmp);
+		}
+
+		if ($tmp =~ /(.*?)>(.*)/) {
+			$content .= $1 . ">\n";
+			$rest = $2;
+			chomp($rest);
+		}
+		
+		print $start;
+		foreach my $arg (@ARGV) {
+			$content =~ s/\s+address=".*?"/ /;
+			$content =~ s/Connector /Connector address="$arg" /;
+			print $content;
+		}
+		print $rest;
+	} else {
+		print $line,"\n";
+	}
+}
diff --git a/rgmanager/src/resources/vm.sh b/rgmanager/src/resources/vm.sh
new file mode 100755
index 0000000..7c8ba9a
--- /dev/null
+++ b/rgmanager/src/resources/vm.sh
@@ -0,0 +1,1109 @@
+#!/bin/bash
+#
+# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
+# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
+#
+# 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.
+#
+
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+
+export PATH
+
+. $(dirname $0)/ocf-shellfuncs || exit 1
+
+#
+# Virtual Machine start/stop script (requires the virsh command)
+#
+
+# Indeterminate state: xend/libvirtd is down.
+export OCF_APP_ERR_INDETERMINATE=150
+
+meta_data()
+{
+    cat <<EOT
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd">
+<resource-agent version="rgmanager 2.0" name="vm">
+    <version>1.0</version>
+
+    <longdesc lang="en">
+	Defines a Virtual Machine
+    </longdesc>
+    <shortdesc lang="en">
+        Defines a Virtual Machine
+    </shortdesc>
+
+    <parameters>
+        <parameter name="name" primary="1">
+            <longdesc lang="en">
+                This is the name of the virtual machine.
+            </longdesc>
+            <shortdesc lang="en">
+                Name
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+    
+        <parameter name="domain" reconfig="1">
+            <longdesc lang="en">
+                Failover domains define lists of cluster members
+                to try in the event that the host of the virtual machine
+		fails.
+            </longdesc>
+            <shortdesc lang="en">
+                Cluster failover Domain
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="autostart" reconfig="1">
+            <longdesc lang="en">
+	    	If set to yes, this resource group will automatically be started
+		after the cluster forms a quorum.  If set to no, this virtual
+		machine will start in the 'disabled' state after the cluster
+		forms a quorum.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Automatic start after quorum formation
+            </shortdesc>
+            <content type="boolean" default="1"/>
+        </parameter>
+
+        <parameter name="exclusive" reconfig="1">
+            <longdesc lang="en">
+	    	If set, this resource group will only relocate to
+		nodes which have no other resource groups running in the
+		event of a failure.  If no empty nodes are available,
+		this resource group will not be restarted after a failure.
+		Additionally, resource groups will not automatically
+		relocate to the node running this resource group.  This
+		option can be overridden by manual start and/or relocate
+		operations.
+            </longdesc>
+            <shortdesc lang="en">
+	        Exclusive resource group
+            </shortdesc>
+            <content type="boolean" default="0"/>
+        </parameter>
+
+        <parameter name="recovery" reconfig="1">
+            <longdesc lang="en">
+	        This currently has three possible options: "restart" tries
+		to restart this virtual machine locally before
+		attempting to relocate (default); "relocate" does not bother
+		trying to restart the VM locally; "disable" disables
+		the VM if it fails.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Failure recovery policy
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+       <parameter name="migration_mapping" reconfig="1">
+           <longdesc lang="en">
+               Mapping of the hostname of a target cluster member to a different hostname
+           </longdesc>
+           <shortdesc lang="en">
+               memberhost:targethost,memberhost:targethost ..
+           </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+	<parameter name="use_virsh">
+	    <longdesc lang="en">
+	    	Force use of virsh instead of xm on Xen machines.
+	    </longdesc>
+	    <shortdesc lang="en">
+	    	If set to 1, vm.sh will use the virsh command to manage
+		virtual machines instead of xm.  This is required when
+		using non-Xen virtual machines (e.g. qemu / KVM).
+	    </shortdesc>
+            <content type="integer" default=""/>
+        </parameter>
+
+	<parameter name="xmlfile">
+	    <longdesc lang="en">
+	    	Full path to libvirt XML file describing the domain.
+	    </longdesc>
+	    <shortdesc lang="en">
+	    	Full path to libvirt XML file describing the domain.
+	    </shortdesc>
+            <content type="string"/>
+	</parameter>
+
+	<parameter name="migrate">
+	    <longdesc lang="en">
+	    	Migration type (live or pause, default = live).
+	    </longdesc>
+	    <shortdesc lang="en">
+	    	Migration type (live or pause, default = live).
+	    </shortdesc>
+            <content type="string" default="live"/>
+        </parameter>
+
+	<parameter name="tunnelled">
+	    <longdesc lang="en">
+	    	Tunnel data over ssh to securely migrate virtual machines.
+	    </longdesc>
+	    <shortdesc lang="en">
+	    	Tunnel data over ssh to securely migrate virtual machines.
+	    </shortdesc>
+            <content type="string" default=""/>
+        </parameter>
+
+	<parameter name="path">
+	    <longdesc lang="en">
+		Path specification vm.sh will search for the specified
+ 		VM configuration file.  /path1:/path2:...
+	    </longdesc>
+	    <shortdesc lang="en">
+		Path to virtual machine configuration files.
+ 	    </shortdesc>
+	    <content type="string"/>
+ 	</parameter>
+
+	<parameter name="snapshot">
+	    <longdesc lang="en">
+	    	Path to the snapshot directory where the virtual machine
+		image will be stored.
+	    </longdesc>
+	    <shortdesc lang="en">
+	    	Path to the snapshot directory where the virtual machine
+		image will be stored.
+	    </shortdesc>
+            <content type="string" default=""/>
+        </parameter>
+
+        <parameter name="depend">
+            <longdesc lang="en">
+		Service dependency; will not start without the specified
+		service running.
+            </longdesc>
+            <shortdesc lang="en">
+		Top-level service this depends on, in service:name format.
+            </shortdesc>
+            <content type="string"/>
+        </parameter>
+
+        <parameter name="depend_mode">
+            <longdesc lang="en">
+		Service dependency mode.
+		hard - This service is stopped/started if its dependency
+		       is stopped/started
+		soft - This service only depends on the other service for
+		       initial startip.  If the other service stops, this
+		       service is not stopped.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Service dependency mode (soft or hard).
+            </shortdesc>
+            <content type="string" default="hard"/>
+        </parameter>
+
+        <parameter name="max_restarts" reconfig="1">
+            <longdesc lang="en">
+	    	Maximum restarts for this service.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Maximum restarts for this service.
+            </shortdesc>
+            <content type="string" default="0"/>
+        </parameter>
+
+        <parameter name="restart_expire_time" reconfig="1">
+            <longdesc lang="en">
+	    	Restart expiration time.  A restart is forgotten
+		after this time.  When combined with the max_restarts
+		option, this lets administrators specify a threshold
+		for when to fail over services.  If max_restarts
+		is exceeded in this given expiration time, the service
+		is relocated instead of restarted again.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Restart expiration time; amount of time before a restart
+		is forgotten.
+            </shortdesc>
+            <content type="string" default="0"/>
+        </parameter>
+
+        <parameter name="status_program" reconfig="1">
+            <longdesc lang="en">
+	    	Ordinarily, only the presence/health of a virtual machine
+		is checked.  If specified, the status_program value is
+		executed during a depth 10 check.  The intent of this 
+		program is to ascertain the status of critical services
+		within a virtual machine.
+            </longdesc>
+            <shortdesc lang="en">
+	    	Additional status check program
+            </shortdesc>
+            <content type="string" default=""/>
+        </parameter>
+
+	<parameter name="hypervisor">
+            <longdesc lang="en">
+		Specify hypervisor tricks to use.  Default = auto.
+		Other supported options are xen and qemu.
+            </longdesc>
+            <shortdesc lang="en">
+		Hypervisor
+            </shortdesc >
+	    <content type="string" default="auto"/>
+	</parameter>
+
+	<parameter name="hypervisor_uri">
+            <longdesc lang="en">
+		Hypervisor URI.  Generally, this is keyed off of the
+		hypervisor and does not need to be set.
+            </longdesc>
+            <shortdesc lang="en">
+		Hypervisor URI (normally automatic).
+            </shortdesc >
+	    <content type="string" default="auto" />
+	</parameter>
+
+	<parameter name="migration_uri">
+            <longdesc lang="en">
+		Migration URI.  Generally, this is keyed off of the
+		hypervisor and does not need to be set.
+            </longdesc>
+            <shortdesc lang="en">
+		Migration URI (normally automatic).
+            </shortdesc >
+	    <content type="string" default="auto" />
+	</parameter>
+
+    </parameters>
+
+    <actions>
+        <action name="start" timeout="300"/>
+        <action name="stop" timeout="120"/>
+	
+        <action name="status" timeout="10" interval="30"/>
+        <action name="monitor" timeout="10" interval="30"/>
+
+	<!-- depth 10 calls the status_program -->
+        <action name="status" depth="10" timeout="20" interval="60"/>
+        <action name="monitor" depth="10" timeout="20" interval="60"/>
+
+	<!-- reconfigure - reconfigure with new OCF parameters.
+	     NOT OCF COMPATIBLE AT ALL -->
+	<action name="reconfig" timeout="10"/>
+
+	<action name="migrate" timeout="10m"/>
+
+        <action name="meta-data" timeout="5"/>
+        <action name="validate-all" timeout="5"/>
+
+    </actions>
+    
+    <special tag="rgmanager">
+    	<!-- Destroy_on_delete / init_on_add are currently only
+	     supported for migratory resources (no children
+	     and the 'migrate' action; see above.  Do not try this
+	     with normal services -->
+        <attributes maxinstances="1" destroy_on_delete="0" init_on_add="0"/>
+    </special>
+</resource-agent>
+EOT
+}
+
+
+build_virsh_cmdline()
+{
+	declare cmdline=""
+	declare operation=$1
+
+	if [ -n "$OCF_RESKEY_hypervisor_uri" ]; then
+		cmdline="$cmdline -c $OCF_RESKEY_hypervisor_uri"
+	fi
+
+	cmdline="$cmdline $operation $OCF_RESKEY_name"
+		
+	echo $cmdline
+}
+
+
+# this is only used on startup
+build_xm_cmdline()
+{
+	declare operation=$1
+	#
+	# Virtual domains should never restart themselves when 
+	# controlled externally; the external monitoring app
+	# should.
+	#
+	declare cmdline="on_shutdown=\"destroy\" on_reboot=\"destroy\" on_crash=\"destroy\""
+
+	if [ -n "$OCF_RESKEY_path" ]; then
+		operation="$operation --path=\"$OCF_RESKEY_path\""
+	fi
+
+	if [ -n "$OCF_RESKEY_name" ]; then
+		cmdline="$operation $OCF_RESKEY_name $cmdline"
+	fi
+
+	echo $cmdline
+}
+
+
+do_xm_start()
+{
+	# Use /dev/null for the configuration file, if xmdefconfig
+	# doesn't exist...
+	#
+	declare cmdline
+
+	echo -n "Virtual machine $OCF_RESKEY_name is "
+	do_status && return 0
+
+	cmdline="`build_xm_cmdline create`"
+
+	ocf_log debug "xm $cmdline"
+
+	eval xm $cmdline
+	return $?
+}
+
+
+get_timeout()
+{
+	declare -i default_timeout=60
+	declare -i tout=60
+
+	if [ -n "$OCF_RESKEY_RGMANAGER_meta_timeout" ]; then
+		tout=$OCF_RESKEY_RGMANAGER_meta_timeout
+	elif [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
+		tout=$OCF_RESKEY_CRM_meta_timeout
+	fi
+
+	if [ $tout -eq 0 ]; then
+		echo $default_timeout
+		return 0
+	fi
+	if [ $tout -lt 0 ]; then
+		echo $default_timeout
+		return 0
+	fi
+
+	echo $tout
+	return 0
+}
+
+
+#
+# Start a virtual machine given the parameters from
+# the environment.
+#
+do_virsh_start()
+{
+	declare cmdline
+	declare snapshotimage
+
+	echo -n "Virtual machine $OCF_RESKEY_name is "
+	do_status && return 0
+
+	snapshotimage="$OCF_RESKEY_snapshot/$OCF_RESKEY_name"
+
+        if [ -n "$OCF_RESKEY_snapshot" -a -f "$snapshotimage" ]; then
+		eval virsh restore $snapshotimage
+		if [ $? -eq 0 ]; then
+			rm -f $snapshotimage
+			return 0
+		fi
+		return 1
+	fi
+
+	if [ -n "$OCF_RESKEY_xmlfile" -a -f "$OCF_RESKEY_xmlfile" ]; then
+		# TODO: try to use build_virsh_cmdline for the hypervisor_uri
+		cmdline="virsh create $OCF_RESKEY_xmlfile"
+	else
+		cmdline="virsh $(build_virsh_cmdline start)"
+	fi
+
+	ocf_log debug "$cmdline"
+
+	$cmdline
+	return $?
+}
+
+
+do_xm_stop()
+{
+	declare -i timeout=60
+	declare -i ret=1
+	declare st
+
+	for op in $*; do
+		echo "CMD: xm $op $OCF_RESKEY_name"
+		xm $op $OCF_RESKEY_name
+
+		timeout=60
+		while [ $timeout -gt 0 ]; do
+			sleep 5
+			((timeout -= 5))
+			do_status&>/dev/null || return 0
+			while read dom state; do
+				#
+				# State is "stopped".  Kill it.
+				#
+				if [ "$dom" != "$OCF_RESKEY_name" ]; then
+					continue
+				fi
+				if [ "$state" != "---s-" ]; then
+					continue
+				fi
+				xm destroy $OCF_RESKEY_name
+			done < <(xm list | awk '{print $1, $5}')
+		done
+	done
+
+	return 1
+}
+
+
+#
+# Stop a VM.  Try to shut it down.  Wait a bit, and if it
+# doesn't shut down, destroy it.
+#
+do_virsh_stop()
+{
+	declare -i timeout=$(get_timeout)
+	declare -i ret=1
+	declare state
+
+	state=$(do_status)
+	[ $? -eq 0 ] || return 0
+
+	if [ -n "$OCF_RESKEY_snapshot" ]; then
+		virsh save $OCF_RESKEY_name "$OCF_RESKEY_snapshot/$OCF_RESKEY_name"
+	fi
+
+	for op in $*; do
+		echo virsh $op $OCF_RESKEY_name ...
+		virsh $op $OCF_RESKEY_name
+
+		timeout=$(get_timeout)
+		while [ $timeout -gt 0 ]; do
+			sleep 5
+			((timeout -= 5))
+			state=$(do_status)
+			[ $? -eq 0 ] || return 0
+
+			if [ "$state" = "paused" ]; then
+				virsh destroy $OCF_RESKEY_name
+			fi
+		done
+	done
+
+	return 1
+}
+
+
+do_start()
+{
+	if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
+		do_virsh_start $*
+		return $?
+	fi
+
+	do_xm_start $*
+	return $?
+}
+
+
+do_stop()
+{
+	declare domstate rv
+
+	domstate=$(do_status)
+	rv=$?
+	ocf_log debug "Virtual machine $OCF_RESKEY_name is $domstate"
+	if [ $rv -eq $OCF_APP_ERR_INDETERMINATE ]; then
+		ocf_log crit "xend/libvirtd is dead; cannot stop $OCF_RESKEY_name"
+		return 1
+	fi
+
+	if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
+		do_virsh_stop $*
+		return $?
+	fi
+
+	do_xm_stop $*
+	return $?
+}
+
+
+#
+# Reconfigure a running VM.
+#
+reconfigure()
+{
+	return 0
+}
+
+
+xm_status()
+{
+	service xend status &> /dev/null
+	if [ $? -ne 0 ]; then 
+		# if xend died
+		echo indeterminate
+		return $OCF_APP_ERR_INDETERMINATE
+	fi
+
+	xm list $OCF_RESKEY_name &> /dev/null
+	if [ $? -eq 0 ]; then
+		echo "running"
+		return 0
+	fi
+	xm list migrating-$OCF_RESKEY_name &> /dev/null
+	if [ $? -eq 0 ]; then
+		echo "running"
+		return 0
+	fi
+	echo "not running"
+	return $OCF_NOT_RUNNING
+}
+
+
+virsh_status()
+{
+	declare state pid
+
+	if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then
+		service xend status &> /dev/null
+		if [ $? -ne 0 ]; then 
+			echo indeterminate
+			return $OCF_APP_ERR_INDETERMINATE
+		fi
+	fi
+
+	#
+	# libvirtd is required when using virsh even though
+	# not specifically when also using Xen.  This is because
+	# libvirtd is required for migration.
+	#
+	pid=$(pidof libvirtd)
+	if [ -z "$pid" ]; then 
+		echo indeterminate
+		return $OCF_APP_ERR_INDETERMINATE
+	fi
+
+	state=$(virsh domstate $OCF_RESKEY_name)
+
+	echo $state
+
+	if [ "$state" = "running" ] || [ "$state" = "paused" ] || [ "$state" = "no state" ] || 
+	   [ "$state" = "idle" ]; then
+		return 0
+	fi
+
+	if [ "$state" = "shut off" ]; then
+		return $OCF_NOT_RUNNING
+	fi
+
+	return $OCF_ERR_GENERIC
+}
+
+
+#
+# Simple status check: Find the VM in the list of running
+# VMs
+#
+do_status()
+{
+	if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
+		virsh_status
+		return $?
+	fi
+
+	xm_status
+	return $?
+}
+
+
+#
+# virsh "path" attribute support
+#
+check_config_file()
+{
+	declare path=$1
+
+	if [ -f "$path/$OCF_RESKEY_name" ]; then
+		echo $path/$OCF_RESKEY_name
+		return 2
+	elif [ -f "$path/$OCF_RESKEY_name.xml" ]; then
+		echo $path/$OCF_RESKEY_name.xml
+		return 2
+	fi
+
+	return 0
+}
+
+
+parse_input()
+{
+	declare delim=$1
+	declare input=$2
+	declare func=$3
+	declare inp
+	declare value
+
+	while [ -n "$input" ]; do
+		value=${input/$delim*/}
+		if [ -n "$value" ]; then
+			eval $func $value
+			if [ $? -eq 2 ]; then
+				return 0
+			fi
+		fi
+		inp=${input/$value$delim/}
+		if [ "$input" = "$inp" ]; then
+			inp=${input/$value/}
+		fi
+		input=$inp
+	done
+}
+
+
+search_config_path()
+{
+	declare config_file=$(parse_input ":" "$OCF_RESKEY_path" check_config_file)
+
+	if [ -n "$config_file" ]; then
+		export OCF_RESKEY_xmlfile=$config_file
+		return 0
+	fi
+
+	return 1
+}
+
+
+choose_management_tool()
+{
+	declare -i is_xml
+
+	#
+	# Don't override user value for use_virsh if one is given
+	#
+	if [ -n "$OCF_RESKEY_use_virsh" ]; then
+		return 0
+	fi
+
+	which xmllint &> /dev/null
+	if [ $? -ne 0 ]; then
+		ocf_log warning "Could not find xmllint; assuming virsh mode"
+		export OCF_RESKEY_use_virsh=1
+		unset OCF_RESKEY_path
+		return 0
+	fi
+
+	xmllint $OCF_RESKEY_xmlfile &> /dev/null
+	is_xml=$?
+
+	if [ $is_xml -eq 0 ]; then
+		ocf_log debug "$OCF_RESKEY_xmlfile is XML; using virsh"
+		export OCF_RESKEY_use_virsh=1
+		unset OCF_RESKEY_path
+	else
+		ocf_log debug "$OCF_RESKEY_xmlfile is not XML; using xm"
+		export OCF_RESKEY_use_virsh=0
+		unset OCF_RESKEY_xmlfile
+	fi
+
+	return 0
+}
+
+
+
+validate_all()
+{
+	if [ "$(id -u)" != "0" ]; then
+	       ocf_log err "Cannot control VMs. as non-root user."
+	       return 1
+	fi
+
+	#
+	# If someone selects a hypervisor, honor it.
+	# Otherwise, ask virsh what the hypervisor is.
+	#
+	if [ -z "$OCF_RESKEY_hypervisor" ] ||
+	   [ "$OCF_RESKEY_hypervisor" = "auto" ]; then
+		export OCF_RESKEY_hypervisor="`virsh version | grep \"Running hypervisor:\" | awk '{print $3}' | tr A-Z a-z`"
+		if [ -z "$OCF_RESKEY_hypervisor" ]; then
+			ocf_log err "Could not determine Hypervisor"
+			return $OCF_ERR_ARGS
+		fi
+		echo Hypervisor: $OCF_RESKEY_hypervisor 
+	fi
+
+	#
+	# Xen hypervisor only for when use_virsh = 0.
+	#
+	if [ "$OCF_RESKEY_use_virsh" = "0" ]; then
+		if [ "$OCF_RESKEY_hypervisor" != "xen" ]; then
+			ocf_log err "Cannot use $OCF_RESKEY_hypervisor hypervisor without using virsh"
+			return $OCF_ERR_ARGS
+		fi
+
+		if [ -n "$OCF_RESKEY_xmlfile" ]; then
+			ocf_log err "Cannot use xmlfile if use_virsh is set to 0"
+			return $OCF_ERR_ARGS
+		fi
+	else
+
+		#
+		# Virsh path support.
+		#
+		if [ -n "$OCF_RESKEY_path" ] &&
+		   [ "$OCF_RESKEY_path" != "/etc/xen" ]; then
+			if [ -n "$OCF_RESKEY_xmlfile" ]; then
+				ocf_log warning "Using $OCF_RESKEY_xmlfile instead of searching $OCF_RESKEY_path"
+			else
+				search_config_path
+				if [ $? -ne 0 ]; then
+					ocf_log warning "Could not find $OCF_RESKEY_name or $OCF_RESKEY_name.xml in search path $OCF_RESKEY_path"
+					unset OCF_RESKEY_xmlfile
+				else
+					ocf_log debug "Using $OCF_RESKEY_xmlfile"
+				fi
+				choose_management_tool
+			fi
+		else
+			export OCF_RESKEY_use_virsh=1
+		fi
+	fi
+
+	if [ "$OCF_RESKEY_use_virsh" = "0" ]; then
+
+		echo "Management tool: xm"
+		which xm &> /dev/null
+		if [ $? -ne 0 ]; then
+			ocf_log err "Cannot find 'xm'; is it installed?"
+			return $OCF_ERR_INSTALLED
+		fi
+
+		if [ "$OCF_RESKEY_hypervisor" != "xen" ]; then
+			ocf_log err "Cannot use $OCF_RESKEY_hypervisor hypervisor without using virsh"
+			return $OCF_ERR_ARGS
+		fi
+	else
+		echo "Management tool: virsh"
+		which virsh &> /dev/null
+		if [ $? -ne 0 ]; then
+			ocf_log err "Cannot find 'virsh'; is it installed?"
+			return $OCF_ERR_INSTALLED
+		fi
+	fi
+
+	#
+	# Set the hypervisor URI
+	#
+	if [ -z "$OCF_RESKEY_hypervisor_uri" -o "$OCF_RESKEY_hypervisor_uri" = "auto" ] &&
+	   [ "$OCF_RESKEY_use_virsh" = "1" ]; then
+
+		# Virsh makes it easier to do this.  Really.
+		if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
+			OCF_RESKEY_hypervisor_uri="qemu:///system"
+		fi
+
+		# I just need to believe in it more.
+		if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then
+			OCF_RESKEY_hypervisor_uri="xen:///"
+		fi
+
+		echo Hypervisor URI: $OCF_RESKEY_hypervisor_uri
+	fi
+
+	#
+	# Set the migration URI
+	#
+	if [ -z "$OCF_RESKEY_migration_uri" -o "$OCF_RESKEY_migration_uri" = "auto" ] &&
+	   [ "$OCF_RESKEY_use_virsh" = "1" ]; then
+
+		# Virsh makes it easier to do this.  Really.
+		if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
+			export OCF_RESKEY_migration_uri="qemu+ssh://%s/system"
+		fi
+
+		# I just need to believe in it more.
+		if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then
+			export OCF_RESKEY_migration_uri="xenmigr://%s/"
+		fi
+
+		[ -n "$OCF_RESKEY_migration_uri" ] && echo Migration URI format: $(printf $OCF_RESKEY_migration_uri target_host)
+	fi
+
+	if [ -z "$OCF_RESKEY_name" ]; then
+		echo No domain name specified
+		return $OCF_ERR_ARGS
+	fi
+
+	if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
+		export migrateuriopt="tcp:%s"
+	fi
+
+	#virsh list --all | awk '{print $2}' | grep -q "^$OCF_RESKEY_name\$"
+	return $?
+}
+
+
+virsh_migrate()
+{
+	declare target=$1
+	declare rv=1
+
+	#
+	# Xen and qemu have different migration mechanisms
+	#
+	if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then 
+		cmd="virsh migrate $migrate_opt $OCF_RESKEY_name $OCF_RESKEY_hypervisor_uri $(printf $OCF_RESKEY_migration_uri $target)"
+		ocf_log debug "$cmd"
+		
+		err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]})
+		rv=$?
+	elif [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
+		if [ -z "$tunnelled_opt" ]; then
+			cmd="virsh migrate $tunnelled_opt $migrate_opt $OCF_RESKEY_name $(printf $OCF_RESKEY_migration_uri $target) $(printf $migrateuriopt $target)"
+		else
+			cmd="virsh migrate $tunnelled_opt $migrate_opt $OCF_RESKEY_name $(printf $OCF_RESKEY_migration_uri $target)"
+		fi
+		ocf_log debug "$cmd"
+		
+		err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]})
+		rv=$?
+	fi
+
+	if [ $rv -ne 0 ]; then
+		ocf_log err "Migrate $OCF_RESKEY_name to $target failed:"
+		ocf_log err "$err"
+
+		if [ "$err" != "${err/does not exist/}" ]; then
+			return $OCF_ERR_CONFIGURED
+		fi
+		if [ "$err" != "${err/Domain not found/}" ]; then
+			return $OCF_ERR_CONFIGURED
+		fi
+
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $rv
+}
+
+
+#
+# XM migrate
+#
+xm_migrate()
+{
+	declare target=$1
+	declare errstr rv migrate_opt cmd
+
+	rv=1
+
+	if [ "$OCF_RESKEY_migrate" = "live" ]; then
+		migrate_opt="-l"
+	fi
+
+	# migrate() function  sets target using migration_mapping;
+	# no need to do it here anymore
+	cmd="xm migrate $migrate_opt $OCF_RESKEY_name $target"
+	ocf_log debug "$cmd"
+
+	err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]})
+	rv=$?
+
+	if [ $rv -ne 0 ]; then
+		ocf_log err "Migrate $OCF_RESKEY_name to $target failed:"
+		ocf_log err "$err"
+
+		if [ "$err" != "${err/does not exist/}" ]; then
+			return $OCF_NOT_RUNNING
+		fi
+		if [ "$err" != "${err/Connection refused/}" ]; then
+			return $OCF_ERR_CONFIGURED
+		fi
+
+		return $OCF_ERR_GENERIC
+	fi
+
+	return $?
+}
+
+# 
+# Virsh migrate
+#
+migrate()
+{
+	declare target=$1
+	declare rv migrate_opt
+	declare tunnelled_opt
+
+	if [ "$OCF_RESKEY_migrate" = "live" ]; then
+		migrate_opt="--live"
+	fi
+
+	case "$OCF_RESKEY_tunnelled" in
+		yes|true|1|YES|TRUE|on|ON)
+			tunnelled_opt="--tunnelled --p2p"
+		;;
+	esac
+
+	# Patch from Marcelo Azevedo to migrate over private
+	# LANs instead of public LANs
+        if [ -n "$OCF_RESKEY_migration_mapping" ] ; then
+                target=${OCF_RESKEY_migration_mapping#*$target:} target=${target%%,*}
+        fi
+
+	if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
+		virsh_migrate $target
+		rv=$?
+	else
+		xm_migrate $target
+		rv=$?
+	fi
+
+	return $rv
+}
+
+
+wait_start()
+{
+	declare -i timeout_remaining=$(get_timeout)
+	declare -i start_time
+	declare -i end_time
+	declare -i delta
+	declare -i sleep_time
+
+	if [ -z "$OCF_RESKEY_status_program" ]; then
+		return 0
+	fi
+
+	while [ $timeout_remaining -gt 0 ]; do
+		start_time=$(date +%s)
+		bash -c "$OCF_RESKEY_status_program"
+		if [ $? -eq 0 ]; then
+			return 0
+		fi
+		end_time=$(date +%s)
+		delta=$(((end_time - start_time)))
+		sleep_time=$(((5 - delta)))
+
+		((timeout_remaining -= $delta))
+		if [ $sleep_time -gt 0 ]; then
+			sleep $sleep_time
+			((timeout_remaining -= $sleep_time))
+		fi
+	done
+
+	ocf_log err "Start of $OCF_RESOURCE_INSTANCE has failed"
+	ocf_log err "Timeout exceeded while waiting for \"$OCF_RESKEY_status_program\""
+
+	return 1
+}
+
+#
+#
+#
+
+case $1 in
+	start)
+		validate_all || exit $OCF_ERR_ARGS
+		do_start
+		rv=$?
+		if [ $rv -ne 0 ]; then
+			exit $rv
+		fi
+
+		wait_start
+		exit $?
+		;;
+	stop)
+		validate_all || exit $OCF_ERR_ARGS
+		do_stop shutdown destroy
+		exit $?
+		;;
+	kill)
+		validate_all || exit $OCF_ERR_ARGS
+		do_stop destroy
+		exit $?
+		;;
+	recover|restart)
+		exit 0
+		;;
+	status|monitor)
+		validate_all || exit $OCF_ERR_ARGS
+		echo -n "Virtual machine $OCF_RESKEY_name is "
+		do_status
+		rv=$?
+		if [ $rv -ne 0 ]; then
+			exit $rv
+		fi
+		[ -z "$OCF_RESKEY_status_program" ] && exit 0
+		[ -z "$OCF_CHECK_LEVEL" ] && exit 0
+		[ $OCF_CHECK_LEVEL -lt 10 ] && exit 0
+
+		bash -c "$OCF_RESKEY_status_program" &> /dev/null
+		exit $?
+		;;
+	migrate)
+		validate_all || exit $OCF_ERR_ARGS
+		migrate $2 # Send VM to this node
+		rv=$?
+		if [ $rv -eq $OCF_ERR_GENERIC ]; then
+			# Catch-all: If migration failed with
+			# an unhandled error, do a status check
+			# to see if the VM is really dead.
+			#
+			# If the VM is still in good health, return
+			# a value to rgmanager to indicate the 
+			# non-critical error
+			#
+			# OCF states that codes 150-199 are reserved
+			# for application use, so we'll use 150
+			#
+			do_status > /dev/null
+			if [ $? -eq 0 ]; then
+				rv=150
+			fi
+		fi
+		exit $rv
+		;;
+	reload)
+		exit 0
+		;;
+	reconfig)
+		validate_all || exit $OCF_ERR_ARGS
+		echo "$0 RECONFIGURING $OCF_RESKEY_memory"
+		reconfigure
+		exit $?
+		;;
+	meta-data)
+		meta_data
+		exit 0
+		;;
+	validate-all)
+		validate_all
+		exit $?
+		;;
+	*)
+		echo "usage: $0 {start|stop|restart|status|reload|reconfig|meta-data|validate-all}"
+		exit 1
+		;;
+esac
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..1186967
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,75 @@
+#
+# heartbeat: Linux-HA heartbeat code
+#
+# Copyright (C) 2001 Michael Moerz
+#
+# 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
+
+SUBDIRS			= ocft
+
+AM_CPPFLAGS		= -I$(top_builddir)/include -I$(top_srcdir)/include
+
+halibdir		= $(libexecdir)/heartbeat
+
+EXTRA_DIST		= ocf-tester.8 sfex_init.8
+
+sbin_PROGRAMS		= 
+sbin_SCRIPTS		= ocf-tester
+halib_PROGRAMS		= findif
+
+man8_MANS		= ocf-tester.8
+
+if BUILD_SFEX
+halib_PROGRAMS		+= sfex_daemon
+sbin_PROGRAMS		+= sfex_init sfex_stat
+man8_MANS		+= sfex_init.8
+endif
+
+if USE_LIBNET
+halib_PROGRAMS		+= send_arp
+send_arp_SOURCES	= send_arp.libnet.c
+send_arp_CFLAGS		= @LIBNETDEFINES@
+send_arp_LDADD		= $(GLIBLIB) -lplumb @LIBNETLIBS@
+else
+
+if SENDARP_LINUX
+halib_PROGRAMS		+= send_arp
+send_arp_SOURCES	= send_arp.linux.c
+endif
+
+endif
+
+sfex_daemon_SOURCES	= sfex_daemon.c sfex.h sfex_lib.c sfex_lib.h
+sfex_daemon_CFLAGS	= -D_GNU_SOURCE
+sfex_daemon_LDADD	= $(GLIBLIB) -lplumb -lplumbgpl
+
+sfex_init_SOURCES	= sfex_init.c sfex.h sfex_lib.c sfex_lib.h
+sfex_init_CFLAGS	= -D_GNU_SOURCE
+sfex_init_LDADD		= $(GLIBLIB) -lplumb -lplumbgpl
+
+sfex_stat_SOURCES	= sfex_stat.c sfex.h sfex_lib.c sfex_lib.h
+sfex_stat_CFLAGS	= -D_GNU_SOURCE
+sfex_stat_LDADD		= $(GLIBLIB) -lplumb -lplumbgpl
+
+findif_SOURCES		= findif.c
+
+if BUILD_TICKLE
+halib_PROGRAMS		+= tickle_tcp
+tickle_tcp_SOURCES	= tickle_tcp.c
+endif
+
+.PHONY: install-exec-hook
diff --git a/tools/README.sfex b/tools/README.sfex
new file mode 100644
index 0000000..ff850d1
--- /dev/null
+++ b/tools/README.sfex
@@ -0,0 +1,336 @@
+Shared Disk File EXclusiveness Control Program version 1.3
+OCF Resource Agent for Heartbeat v2
+FOR USE IN LINUX 2.6 KERNEL OPERATING SYSTEM ENVIRONMENTS ONLY. 
+
+Copyright (c) 2007 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+
+Note: Before using this information and the product it supports, 
+read the general information in section 4.0 "Trademarks and Notices" 
+in this document.
+
+Last Update Date:  10/10/2007
+
+
+=======================================================================
+CONTENTS
+--------
+1.0  Overview
+2.0  Installation and Setup Instructions
+3.0  Configuration Information
+4.0  Trademarks and Notices
+5.0  Disclaimer
+
+=======================================================================
+
+1.0   Overview
+--------------
+Shared Disk File EXclusiveness Control Program, called "SF-EX" for short, 
+can prevent a destruction of data on shared disk file system due to 
+Split-Brain.
+
+=======================================================================
+
+1.1  Limitations
+---------------------
+This program is tested on the following environment.
+
+	Heartbeat 2.1.2-2
+	Red Hat Enterprise Linux ES release 4 (Nahant Update 5) EM64T
+
+=======================================================================
+
+2.0   Installation and Setup Instructions
+-----------------------------------------
+
+	2.1.1 Prerequisites
+		SF-EX is released as a source-code package in the format
+		of a gunzip compressed tar file. To unpack the source
+		package, type the following command in the Linux console
+		window:
+		
+		$ tar zxf sfex-1.3.tar.gz
+
+		The source files will uncompress to the "sf-ex-x.x"
+            	directory. 
+
+	2.1.3 Build and Installation
+
+		Change unpacked directory first.
+
+		$ cd sfex-1.3
+
+		Type the following command in the Linux console window:
+		Press Enter after each command.
+		
+		$ ./configure
+		$ make
+		$ su
+		(you need root's password)
+		# make install
+
+		"make install" will copy the modules to /usr/lib64/heartbeat
+
+		NOTE: "make install" should be done on all nodes
+		which Heartbeat would run.
+
+		NOTE: in case of 32bit system
+		If you want to run SF-EX on 32bit system, the modules
+		should be setup on /usr/lib/heartbeat.
+		Use the following configure option on 32bit system.
+
+		$ ./configure --with-lib-dir=/usr/lib/heartbeat
+
+	2.1.3 Initialization of a device
+		Before running SF-EX, one device should be initialized
+		as below.
+		
+		sfex_init [-b <blocksize>] [-n <numlocks>] <device>
+
+		Example:
+		# /usr/lib/heartbeat/sfex_init -b 512 -n 10 /dev/sdb1
+
+		Initialized device is going to be used as a control area
+		for SF-EX.
+		See 3.2.2, if further information is necessary.
+
+	2.1.4 Access without O_DIRECT
+		If you are planning to access a device without using
+		O_DIRECT, the following option is available.
+
+		Example:
+		$ ./configure -enable-directio=no
+
+		Default value for --enable-directio is "yes".
+
+=======================================================================
+
+3.0 Configuration Information
+-----------------------------
+
+3.1 Configuration Settings
+--------------------------
+
+	3.1.1 Edit your cib.xml
+		The following example shows a typical configuration
+		for SF-EX and Filesystem.
+		
+	3.1.2 Example for cib.xml
+		
+		/dev/sda1	control area for SF-EX
+		/dev/sda2	Filesystem
+
+--- skip ---
+<resources>
+ <group id="grp">
+  <primitive id="prmEx" class="ocf" type="sfex" provider="heartbeat">
+   <operations>
+    <op id="ex_start"   name="start"   timeout="180s" on_fail="fence"/>
+    <op id="ex_monitor" name="monitor" timeout="60s"  on_fail="fence" interval="10s" />
+    <op id="ex_stop"    name="stop"    timeout="60s"  on_fail="fence"/>
+   </operations>
+   <instance_attributes id="atrEx">
+    <attributes>
+     <nvpair id="dsk" name="device"            value="/dev/sda1"/>
+     <nvpair id="idx" name="index"             value="1"/>
+     <nvpair id="clt" name="collision_timeout" value="1"/>
+     <nvpair id="lct" name="lock_timeout"      value="70"/>
+     <nvpair id="mnt" name="monitor_interval"  value="10"/>
+     <nvpair id="fck" name="fsck"              value="/sbin/fsck -p /dev/sdb2"/>
+     <nvpair id="fcm" name="fsck_mode"         value="check"/>
+     <nvpair id="hlt" name="halt"              value="/sbin/halt -f -n -p"/>
+    </attributes>
+   </instance_attributes>
+  </primitive>
+  <primitive id="prmFs" class="ocf" type="Filesystem" provider="heartbeat">
+   <operations>
+    <op id="fs_start"   name="start"   timeout="60s"  on_fail="fence"/>
+    <op id="fs_monitor" name="monitor" timeout="60s"  on_fail="fence" interval="10s" />
+    <op id="fs_stop"    name="stop"    timeout="60s"  on_fail="fence"/>
+   </operations>
+   <instance_attributes id="atrFs">
+    <attributes>
+     <nvpair id="dev"  name="device"           value="/dev/sdb2"/>
+     <nvpair id="dir"  name="directory"        value="/mnt/shared-disk"/>
+     <nvpair id="fst"  name="fstype"           value="ext3"/>
+    </attributes>
+   </instance_attributes>
+  </primitive>
+ </group>
+</resources>
+--- skip ---
+
+
+3.2 Outline of each module
+--------------------------
+	3.2.1 sfex
+		Resource Agent script for Heartbeat.
+
+	3.2.2 sfex_init
+		sfex_init [-b <blocksize>] [-n <numlocks>] <device>
+
+		-b <blocksize> --- The size of the block is specified 
+		by the number of bytes. In general, to prevent a partial 
+		writing to the disk, the size of block is set to 512 
+		bytes etc. 
+		Note a set value because this value is used also for 
+		the alignment adjustment in the input-output buffer in 
+		the program when direct I/O is used(When you specify 
+		 --enable-directio option for configure script). 
+		(In Linux kernel 2.6, "direct I/O " does not work if this 
+		value is not a multiple of 512.) Default is 512 bytes.
+
+		-n <numlocks> --- The number of storing lock data is 
+		specified by integer of one or more. When you want to 
+		control two or more resources by one meta-data, you set 
+		the value of two or more to numlocks. A necessary disk 
+		area for meta data are (blocksize*(1+numlocks))bytes. 
+		Default is 1.
+
+		<device> --- This is file path which stored mata-data. 
+		It is usually expressed in "/dev/...", because it is 
+		partition on the shared disk.
+
+		exit code --- 
+		0 - Normal end. 
+		3 - Error occurs while 	processing it. 
+    		    The content of the error is displayed into stderr. 
+		4 - The mistake is found in the command line parameter.
+
+	3.2.3 sfex_stat
+		sfex_stat [-i <index>] <device>
+
+		-i <index> --- The index is number of the resource that 
+		display the lock. This number is specified by the integer 
+		of one or more. When two or more resources are exclusively 
+		controlled by one meta-data, this option is used. 
+		Default is 1.
+
+		<device> --- This is file path which stored mata-data. 
+		It is usually expressed in "/dev/...", because it is 
+		partition on the shared disk.
+
+		exit code --- 
+		0 - Normal end. Own node is holding lock. 
+		2 - Normal end. Own node does not hold a lock. 
+		3 - Error occurs while processing it. 
+		    The content of the error is displayed into stderr. 
+		4 - The mistake is found in the command line parameter.
+
+	3.2.4 sfex_lock
+		sfex_lock 
+			[-i <index>] 
+			[-c <collision_timeout>] 
+			[-t <lock_timeout>] 
+			<device>
+
+		-i <index> --- The index is number of the resource that 
+		acquire the lock. This number is specified by the integer 
+		of one or more. When two or more resources are exclusively 
+		controlled by one meta-data, this option is used. 
+		Default is 1.
+
+		-c <collision_timeout> --- The waiting time to detect 
+		the collision of the lock with other nodes is specified. 
+		Time that is very longer than "once synchronous read from 
+		device which stored meta-data + once 
+		synchronous write" is specified usually. Default is 1 second.
+		This value need not be changed by using this option usually.  
+		Because it is not thought to take one second or more to 
+		synchronous read and write.
+
+		-t <lock_timeout> --- This specifies the validity term 
+		of lock. The unit is a second. This timer prevents the 
+		resource being locked for a long time when node crashes 
+		with the lock acquired. Therefore, the lock holding node 
+		must update lock data at intervals that are shorter than 
+		this timer. The sfex_update command is used for updating 
+		lock. Default is 60 seconds.
+
+		<device> --- This is file path which stored mata-data. 
+		It is usually expressed in "/dev/...", because it is 
+		partition on the shared disk.
+
+		exit code --- 
+		0 - Acquire a lock from unlock status. 
+		1 - Acquire a lock from lock timeout status. 
+		2 - Lock acquisition failed. 
+		3 - Error occurs while processing it. The content of the 
+		    error is displayed into stderr. 
+		4 - The mistake is found in the command line parameter.
+
+	3.2.5 sfex_unlock
+		sfex_unlock [-i <index>] <device>
+
+		-i <index> --- The index is number of the resource that 
+		releases the lock. This number is specified by the integer 
+		of one or more. When two or more resources are exclusively 
+		controlled by one meta-data, this option is used. 
+		Default is 1.
+
+		<device> --- This is file path which stored mata-data. 
+		It is usually expressed in "/dev/...", because it is 
+		partition on the shared disk.
+
+		exit code --- 
+		0 - Lock release success. 
+		1 - Lock release done already. 
+		    The lock has already been acquired by other nodes. 
+		3 - Error occurs while processing it. 
+		    The content of the error is displayed into stderr. 
+		4 - The mistake is found in the command line parameter.
+
+	3.2.6 sfex_update
+		sfex_update [-i <index>] <device>
+
+		-i <index> --- The index is number of the resource that 
+		update the lock. This number is specified by the integer 
+		of one or more. When two or more resources are exclusively 
+		controlled by one meta-data, this option is used.
+		Default is 1.
+
+		<device> --- This is file path which stored mata-data. 
+		It is usually expressed in "/dev/...", because it is 
+		partition on the shared disk.
+
+		exit code --- 
+		0 - Lock update success. 
+		2 - Lock update failed. 
+		    The lock is acquired by other nodes. 
+		3 - Error occurs while processing it. 
+		    The content of the error is displayed into stderr. 
+		4 - The mistake is found in the command line parameter.
+
+=======================================================================
+
+4.0   Trademarks and Notices
+----------------------------
+
+	Heartbeat is a registered trademark of The High Availability 
+        Linux Project.
+
+	Linux is a registered trademark of Linus Torvalds.
+
+	Other company, product, and service names may be 
+	trademarks or service marks of others.
+
+=======================================================================
+
+5.0   Disclaimer
+----------------
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+	CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+	MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND 
+	PARTICULARLY THE NON-INFRINGEMENT OF ANY THIRD PARTY'S 
+	INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. IN NO EVENT 
+	SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 
+	DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+	OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+	OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
+	USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
+	DAMAGE.
+
diff --git a/tools/findif.c b/tools/findif.c
new file mode 100644
index 0000000..86c9711
--- /dev/null
+++ b/tools/findif.c
@@ -0,0 +1,842 @@
+/*
+ * findif.c:	Finds an interface which can route a given address
+ *
+ *	It's really simple to write in C, but hard to write in the shell...
+ *
+ *	This code is dependent on IPV4 addressing conventions...
+ *		Sorry.
+ *
+ * Copyright (C) 2000 Alan Robertson <alanr at unix.sh>
+ * Copyright (C) 2001 Matt Soffen <matt at soffen.com>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ *
+ ***********************************************************
+ *
+ *	All our arguments come through the environment as OCF
+ *	environment variables as below:
+ *
+ *	OCF_RESKEY_ip
+ *	OCF_RESKEY_broadcast
+ *	OCF_RESKEY_nic
+ *	OCF_RESKEY_cidr_netmask
+ *
+ *	If the CIDR netmask is omitted, we choose the netmask associated with
+ *	the route we selected.
+ *
+ *	If the broadcast address was omitted, we assume the highest address
+ *	in the subnet.
+ *
+ *	If the interface is omitted, we choose the interface associated with
+ *	the route we selected.
+ *
+ *
+ *	See http://www.doom.net/docs/netmask.html for a table explaining
+ *	CIDR address format and their relationship to life, the universe
+ *	and everything.
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#ifdef __linux__
+#undef __OPTIMIZE__
+/*
+ * This gets rid of some silly -Wtraditional warnings on Linux
+ * because the netinet header has some slightly funky constants
+ * in it.
+ */
+#endif /* __linux__ */
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <agent_config.h>
+#include <config.h>
+
+#define DEBUG 0
+#define	EOS			'\0'
+#define	PROCROUTE	"/proc/net/route"
+#define ROUTEPARM	"-n get"
+
+#ifndef HAVE_STRNLEN
+/* Any system that don't provide strnlen() only has itself to blame */
+#define strnlen(str, max) strlen(str)
+#endif
+
+/*
+ * "route -n get iii.jjj.kkk.lll" can, on Solaris at least,
+ * return the word "default" as the value from "mask" and "dest",
+ * typically if the host is remote, reached over a default route. 
+ * We should probably treat such a mask as "0.0.0.0".
+ *
+ * Define "MASK_DEFAULT_TO_ZERO" to enable this interpretation.
+ *
+ * This is better for Solaris and is probably suitable (or irrelevant)
+ * for others OSes also.  But if it breaks another OS, then reduce the
+ * "hash-if 1" below to exclude that OS. 
+ * (David Lee, Jan 2006)
+ */
+#if 1
+# define MASK_DEFAULT_TO_ZERO
+#endif
+
+static int OutputInCIDR=0;
+
+
+/*
+ * Different OSes offer different mechnisms to obtain this information.
+ * Not all this can be determined at configure-time; need a run-time element.
+ *
+ * typedef ... SearchRoute ...:
+ *	For routines that interface on these mechanisms.
+ *	Return code:
+ *		<0:	mechanism invalid, so try next mechanism
+ *		0:	mechanism worked: good answer
+ *		>0:	mechanism worked: bad answer
+ *	On non-zero, errmsg may have been filled with an error message
+ */
+typedef int SearchRoute (char *address, struct in_addr *in
+,        struct in_addr *addr_out, char *best_if, size_t best_iflen
+,        unsigned long *best_netmask, char *errmsg
+,	int errmsglen);
+
+static SearchRoute SearchUsingProcRoute;
+static SearchRoute SearchUsingRouteCmd;
+
+static SearchRoute *search_mechs[] = {
+	&SearchUsingProcRoute,
+	&SearchUsingRouteCmd,
+	NULL
+};
+
+void GetAddress (char **address, char **netmaskbits
+,	 char **bcast_arg, char **if_specified);
+
+int ConvertNetmaskBitsToInt(char *netmaskbits);
+
+void ValidateNetmaskBits(int bits, unsigned long *netmask);
+
+int ValidateIFName (const char *ifname, struct ifreq *ifr);
+
+int netmask_bits (unsigned long netmask);
+
+char * get_first_loopback_netdev(char * ifname);
+int is_loopback_interface(char * ifname);
+char * get_ifname(char * buf, char * ifname);
+
+int ConvertQuadToInt(char *dest);
+
+static const char *cmdname = "findif";
+#define OCF_SUCCESS             0
+#define OCF_ERR_GENERIC         1
+#define OCF_ERR_ARGS            2
+#define OCF_ERR_UNIMPLEMENTED   3
+#define OCF_ERR_PERM            4
+#define OCF_ERR_INSTALLED       5
+#define OCF_ERR_CONFIGURED      6
+#define OCF_NOT_RUNNING         7
+void usage(int ec);
+
+#define PATH_PROC_NET_DEV "/proc/net/dev"
+#define DELIM	'/'
+#define	BAD_BROADCAST	(0L)
+#define	MAXSTR	128
+
+static int
+SearchUsingProcRoute (char *address, struct in_addr *in
+, 	struct in_addr *addr_out, char *best_if, size_t best_iflen
+,	unsigned long *best_netmask
+,	char *errmsg, int errmsglen)
+{
+	unsigned long	flags, refcnt, use, gw, mask;
+	unsigned long   dest;
+	long		metric = LONG_MAX;
+	long		best_metric = LONG_MAX;
+	int		rc = OCF_SUCCESS;
+	
+	char	buf[2048];
+	char	interface[MAXSTR];
+	FILE *routefd = NULL;
+
+	if ((routefd = fopen(PROCROUTE, "r")) == NULL) {
+		snprintf(errmsg, errmsglen
+		,	"Cannot open %s for reading"
+		,	PROCROUTE);
+		rc = OCF_ERR_GENERIC; goto out;
+	}
+
+	/* Skip first (header) line */
+	if (fgets(buf, sizeof(buf), routefd) == NULL) {
+		snprintf(errmsg, errmsglen
+		,	"Cannot skip first line from %s"
+		,	PROCROUTE);
+		rc = OCF_ERR_GENERIC; goto out;
+	}
+	*best_netmask = 0;
+	while (fgets(buf, sizeof(buf), routefd) != NULL) {
+		if (sscanf(buf, "%[^\t]\t%lx%lx%lx%lx%lx%lx%lx"
+		,	interface, &dest, &gw, &flags, &refcnt, &use
+		,	&metric, &mask)
+		!= 8) {
+			snprintf(errmsg, errmsglen, "Bad line in %s: %s"
+			,	PROCROUTE, buf);
+			rc = OCF_ERR_GENERIC; goto out;
+		}
+		if ( (in->s_addr&mask) == (in_addr_t)(dest&mask)
+		&&	metric <= best_metric && mask >= *best_netmask) {
+			best_metric = metric;
+			*best_netmask = mask;
+			strncpy(best_if, interface, best_iflen);
+		}
+	}
+
+	if (best_metric == LONG_MAX) {
+		snprintf(errmsg, errmsglen, "No route to %s\n", address);
+		rc = OCF_ERR_GENERIC; 
+	}
+
+  out:
+	if (routefd) {
+		fclose(routefd);
+	}
+
+	return(rc);
+}
+
+static int
+SearchUsingRouteCmd (char *address, struct in_addr *in
+,	struct in_addr *addr_out, char *best_if, size_t best_iflen
+,	unsigned long *best_netmask
+,	char *errmsg, int errmsglen)
+{
+	char	mask[20];
+	char	routecmd[MAXSTR];
+	int	best_metric = INT_MAX;	
+	char	buf[2048];
+	char	interface[MAXSTR];
+	char  *cp, *sp;
+	int done = 0;
+	FILE *routefd = NULL;
+	uint32_t maskbits;
+
+	
+	/* Open route and get the information */
+	snprintf (routecmd, sizeof(routecmd), "%s %s %s"
+	,	ROUTE, ROUTEPARM, address);
+	routefd = popen (routecmd, "r");
+	if (routefd == NULL)
+		return (OCF_ERR_GENERIC);
+	mask[0] = EOS;
+	interface[0] = EOS;
+
+
+	while ((done < 3) && fgets(buf, sizeof(buf), routefd)) {
+		int buflen = strnlen(buf, sizeof(buf));
+		/*cp = buf;*/
+
+		sp = buf + buflen;
+		while (sp!=buf && isspace((int)*(sp-1))) {
+			--sp;
+		}
+		*sp = EOS;
+
+		if (strstr (buf, "mask:")) {
+			/*strsep(&cp, ":");cp++;*/
+			strtok(buf, ":");
+			cp = strtok(NULL, ":");
+			if (cp) {
+				cp++;
+				strncpy(mask, cp, sizeof(mask));
+				done++;
+			}
+		}
+
+		if (strstr (buf, "interface:")) {
+			/*strsep(&cp, ":");cp++;*/
+			strtok(buf, ":");
+			cp = strtok(NULL, ":");
+			if (cp) {
+				cp++;
+				strncpy(interface, cp, sizeof(interface));
+				done++;
+			}
+		}
+	}
+	fclose(routefd);
+
+	/*
+	 * Check to see if mask isn't available.  It may not be
+	 *	returned if multiple IP's are defined.
+	 *	use 255.255.255.255 for mask then
+	 */
+	/* I'm pretty sure this is the wrong behavior...
+	 * I think the right behavior is to declare an error and give up.
+	 * The admin didn't define his routes correctly.  Fix them.
+	 * It's useless to take over an IP address with no way to
+	 * return packets to the originator.  Without the right subnet
+	 * mask, you can't reply to any packets you receive.
+	 */
+	if (strnlen(mask, sizeof(mask)) == 0) {
+		strncpy (mask, "255.255.255.255", sizeof(mask));
+	}
+
+	/*
+	 * Solaris (at least) can return the word "default" for mask and dest.
+	 * For the moment, let's interpret this as:
+	 *	mask: 0.0.0.0
+	 * This was manifesting itself under "BasicSanityCheck", which tries
+	 * to use a remote IP number; these typically use the "default" route.
+	 * Better schemes are warmly invited...
+	 */
+#ifdef MASK_DEFAULT_TO_ZERO
+	if (strncmp(mask, "default", sizeof("default")) == 0) {
+		strncpy (mask, "0.0.0.0", sizeof(mask));
+	}
+#endif
+
+	if (inet_pton(AF_INET, mask, &maskbits) <= 0) {
+		snprintf(errmsg, errmsglen,
+		  "mask [%s] not valid.", mask);
+		return(OCF_ERR_CONFIGURED);
+	}
+
+	if (inet_pton(AF_INET, address, addr_out) <= 0) {
+		snprintf(errmsg, errmsglen
+		,	"IP address [%s] not valid.", address);
+		return(OCF_ERR_CONFIGURED);
+	}
+
+	if ((in->s_addr & maskbits) == (addr_out->s_addr & maskbits)) {
+		if (interface[0] == EOS) {
+			snprintf(errmsg, errmsglen, "No interface found.");
+			return(OCF_ERR_GENERIC);
+		}
+		best_metric = 0;
+		*best_netmask = maskbits;
+		strncpy(best_if, interface, best_iflen);
+	}
+
+	if (best_metric == INT_MAX) {
+		snprintf(errmsg, errmsglen, "No route to %s\n", address);
+		return(OCF_ERR_GENERIC);
+	}
+
+	return (OCF_SUCCESS);
+}
+
+/*
+ * Getaddress gets all its real parameters from the OCF environment
+ * variables that its callers already use.
+ */
+void
+GetAddress (char **address, char **netmaskbits
+,	 char **bcast_arg, char **if_specified)
+{
+	/*
+	 *	Here are out input environment variables:
+	 *
+	 *	OCF_RESKEY_ip		ip address
+	 *	OCF_RESKEY_cidr_netmask netmask of interface
+	 *	OCF_RESKEY_broadcast	broadcast address for interface
+	 *	OCF_RESKEY_nic		interface to assign to
+	 *
+	 */
+	*address = getenv("OCF_RESKEY_ip");
+	*netmaskbits = getenv("OCF_RESKEY_cidr_netmask");
+	if (*netmaskbits == NULL || **netmaskbits == EOS) {
+		*netmaskbits = getenv("OCF_RESKEY_netmask");
+	}
+	*bcast_arg = getenv("OCF_RESKEY_broadcast");
+	*if_specified = getenv("OCF_RESKEY_nic");
+}
+
+int
+ConvertNetmaskBitsToInt(char *netmaskbits)
+{
+	size_t	nmblen = strnlen(netmaskbits, 3);
+
+	/* Maximum netmask is 32 */
+
+	if (nmblen > 2 || nmblen == 0
+	||	(strspn(netmaskbits, "0123456789") != nmblen))
+		return -1;
+	else
+		return atoi(netmaskbits);
+}
+
+void
+ValidateNetmaskBits(int bits, unsigned long *netmask)
+{
+	/* Maximum netmask is 32 */
+
+	if (bits < 1 || bits > 32) {
+		fprintf(stderr
+		,	"Invalid netmask specification [%d]"
+		,	bits);
+		usage(OCF_ERR_CONFIGURED);
+		/*not reached */
+	}
+
+	bits = 32 - bits;
+	*netmask = (1L<<(bits))-1L;
+	*netmask = ((~(*netmask))&0xffffffffUL);
+	*netmask = htonl(*netmask);
+}
+
+int
+ValidateIFName(const char *ifname, struct ifreq *ifr) 
+{
+ 	int skfd = -1;
+	char *colonptr;
+
+ 	if ( (skfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ) {
+ 		fprintf(stderr, "%s\n", strerror(errno));
+ 		return -2;
+ 	}
+ 
+	strncpy(ifr->ifr_name, ifname, IFNAMSIZ);
+
+	/* Contain a ":"?  Probably an error, but treat as warning at present */
+	if ((colonptr = strchr(ifname, ':')) != NULL) {
+		fprintf(stderr, "%s: warning: name may be invalid\n",
+		  ifr->ifr_name);
+	}
+ 
+ 	if (ioctl(skfd, SIOCGIFFLAGS, ifr) < 0) {
+ 		fprintf(stderr, "%s: unknown interface: %s\n"
+ 			, ifr->ifr_name, strerror(errno));
+ 		close(skfd);
+		/* return -1 only if ifname is known to be invalid */
+		return -1;
+ 	}
+ 	close(skfd);
+ 	return 0;
+} 
+
+int
+netmask_bits(unsigned long netmask)
+{
+	int	j;
+
+	netmask = netmask & 0xFFFFFFFFUL;
+
+	for (j=0; j <= 32; ++j) {
+		if ((netmask >> j)&0x1) {
+			break;
+		}
+	}
+
+	return 32 - j;
+}
+
+char * 
+get_first_loopback_netdev(char * output)
+{
+	char buf[512];
+	FILE * fd = NULL;
+	char *rc = NULL;
+	
+	if (!output) {
+		fprintf(stderr, "output buf is a null pointer.\n");
+		goto out;
+	}
+
+	fd = fopen(PATH_PROC_NET_DEV, "r");
+	if (!fd) {
+		fprintf(stderr, "Warning: cannot open %s (%s).\n",
+			PATH_PROC_NET_DEV, strerror(errno)); 
+		goto out;
+	}
+
+	/* Skip the first two lines */
+	if (!fgets(buf, sizeof(buf), fd) || !fgets(buf, sizeof(buf), fd)) {
+		fprintf(stderr, "Warning: cannot read header from %s.\n",
+			PATH_PROC_NET_DEV);
+		goto out;
+	}
+
+	while (fgets(buf, sizeof(buf), fd)) {
+		char name[IFNAMSIZ];
+		if (NULL == get_ifname(buf, name)) {
+			/* Maybe somethin is wrong, anyway continue */
+			continue;
+		}
+		if (is_loopback_interface(name)) {
+			strncpy(output, name, IFNAMSIZ);
+			rc = output;
+			goto out;
+		}
+	}
+
+out:
+	if (fd) {
+		fclose(fd);
+	}
+	return rc;
+}
+
+int
+is_loopback_interface(char * ifname)
+{
+	struct ifreq ifr;
+	memset(&ifr, 0, sizeof(ifr));
+	if (ValidateIFName(ifname, &ifr) < 0)
+		return 0;
+
+	if (ifr.ifr_flags & IFF_LOOPBACK) {
+		/* this is a loopback device. */
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+char *
+get_ifname(char * buf, char * ifname)
+{
+	char * start, * end, * buf_border;	
+
+	buf_border = buf + strnlen(buf, 512);
+
+	start = buf; 
+	while (isspace((int) *start) && (start != buf_border)) {
+		start++;
+	}
+	end = start;
+	while ((*end != ':') && (end != buf_border)) {
+		end++;	
+	}
+
+	if ( start == buf_border || end == buf_border ) {
+		/* Over the border of buf */ 
+		return NULL;
+	}
+
+	*end = '\0';
+	strncpy(ifname, start, IFNAMSIZ);
+	
+	return ifname;
+}
+
+int ConvertQuadToInt(char *dest)
+{
+	struct in_addr ad;
+
+	if (inet_pton(AF_INET, dest, &ad) <= 0)
+		return -1;
+
+	return netmask_bits(ntohl(ad.s_addr));
+}
+
+int
+main(int argc, char ** argv) {
+
+	char *	address = NULL;
+	char *	bcast_arg = NULL;
+	char *	netmaskbits = NULL;
+	struct in_addr	in;
+	struct in_addr	addr_out;
+	unsigned long	netmask = 0;
+	char	best_if[MAXSTR];
+	char *	if_specified = NULL;
+	struct ifreq	ifr;
+	unsigned long	best_netmask = UINT_MAX;
+	int		argerrs	= 0;
+	int		nmbits;
+
+	cmdname=argv[0];
+
+
+	memset(&addr_out, 0, sizeof(addr_out));
+	memset(&in, 0, sizeof(in));
+	memset(&ifr, 0, sizeof(ifr));
+
+	switch (argc) {
+	case 1:	/* No -C argument */
+		break;
+	case 2: /* Hopefully a -C argument */
+		if (strncmp(argv[1], "-C", sizeof("-C")) != 0) {
+			argerrs=1;
+		}
+		OutputInCIDR=1;
+		break;
+	default:
+		argerrs=1;
+		break;
+	}
+	if (argerrs) {
+		usage(OCF_ERR_ARGS);
+		/* not reached */
+		return(1);
+	}
+
+	GetAddress (&address, &netmaskbits, &bcast_arg
+	,	 &if_specified);
+	if (address == NULL || *address == EOS) {
+		fprintf(stderr, "ERROR: IP address parameter is mandatory.");
+		usage(OCF_ERR_CONFIGURED);
+		/* not reached */
+	}
+
+	/* Is the IP address we're supposed to find valid? */
+	 
+	if (inet_pton(AF_INET, address, (void *)&in) <= 0) {
+		fprintf(stderr, "IP address [%s] not valid.", address);
+		usage(OCF_ERR_CONFIGURED);
+		/* not reached */
+	}
+
+	if (netmaskbits != NULL && *netmaskbits != EOS) {
+		if (strchr(netmaskbits, '.') != NULL) {
+			nmbits = ConvertQuadToInt(netmaskbits);
+			fprintf(stderr, "Converted dotted-quad netmask to CIDR as: %d\n", nmbits);
+		}else{
+			nmbits = ConvertNetmaskBitsToInt(netmaskbits);
+		}
+
+		if (nmbits < 0) {
+			fprintf(stderr, "Invalid netmask specification"
+			" [%s]", netmaskbits);
+			usage(OCF_ERR_CONFIGURED);
+			/*not reached */
+		}
+
+		/* Validate the netmaskbits field */
+		ValidateNetmaskBits (nmbits, &netmask);
+	}
+
+
+	if (if_specified != NULL && *if_specified != EOS) {
+		if(ValidateIFName(if_specified, &ifr) < 0) {
+			usage(OCF_ERR_CONFIGURED);
+			/* not reached */
+		}
+		strncpy(best_if, if_specified, sizeof(best_if));
+		*(best_if + sizeof(best_if) - 1) = '\0';
+	}else{
+		SearchRoute **sr = search_mechs;
+		char errmsg[MAXSTR] = "No valid mechanisms";
+		int rc = OCF_ERR_GENERIC;
+
+		strcpy(best_if, "UNKNOWN");
+
+		while (*sr) {
+			errmsg[0] = '\0';
+			rc = (*sr) (address, &in, &addr_out, best_if
+			,	sizeof(best_if)
+			,	&best_netmask, errmsg, sizeof(errmsg));
+			if (!rc) {		/* Mechanism worked */
+				break;
+			}
+			sr++;
+		}
+		if (rc != 0) {	/* No route, or all mechanisms failed */
+			if (*errmsg) {
+				fprintf(stderr, "%s", errmsg);
+			}
+			return(rc);
+		}
+	}
+
+	if (netmaskbits) {
+		best_netmask = netmask;
+	}else if (best_netmask == 0L) {
+		/*
+		   On some distributions, there is no loopback related route
+		   item, this leads to the error here.
+		   My fix may be not good enough, please FIXME
+		 */
+		if (0 == strncmp(address, "127", 3)) {
+			if (NULL != get_first_loopback_netdev(best_if)) {
+				best_netmask = 0x000000ff;
+			} else {
+				fprintf(stderr, "No loopback interface found.\n");
+				return(OCF_ERR_GENERIC);
+			}
+		} else {
+			fprintf(stderr
+			,	"ERROR: Cannot use default route w/o netmask [%s]\n"
+			,	 address);
+			return(OCF_ERR_GENERIC);
+		}
+	}
+
+	/* Did they tell us the broadcast address? */
+
+	if (bcast_arg && *bcast_arg != EOS) {
+		/* Yes, they gave us a broadcast address.
+		 * It at least should be a valid IP address
+		 */
+ 		struct in_addr bcast_addr;
+ 		if (inet_pton(AF_INET, bcast_arg, (void *)&bcast_addr) <= 0) {
+ 			fprintf(stderr, "Invalid broadcast address [%s].", bcast_arg);
+ 			usage(OCF_ERR_CONFIGURED);
+			/* not reached */
+ 		}
+
+		best_netmask = htonl(best_netmask);
+		if (!OutputInCIDR) {
+			printf("%s\tnetmask %d.%d.%d.%d\tbroadcast %s\n"
+			,	best_if
+                	,       (int)((best_netmask>>24) & 0xff)
+                	,       (int)((best_netmask>>16) & 0xff)
+                	,       (int)((best_netmask>>8) & 0xff)
+                	,       (int)(best_netmask & 0xff)
+			,	bcast_arg);
+		}else{
+			printf("%s\tnetmask %d\tbroadcast %s\n"
+			,	best_if
+			,	netmask_bits(best_netmask)
+			,	bcast_arg);
+		}
+	}else{
+		/* No, we use a common broadcast address convention */
+		unsigned long	def_bcast;
+
+			/* Common broadcast address */
+		def_bcast = (in.s_addr | (~best_netmask));
+#if DEBUG
+		fprintf(stderr, "best_netmask = %08lx, def_bcast = %08lx\n"
+		,	best_netmask,  def_bcast);
+#endif
+
+		/* Make things a bit more machine-independent */
+		best_netmask = htonl(best_netmask);
+		def_bcast = htonl(def_bcast);
+		if (!OutputInCIDR) {
+			printf("%s\tnetmask %d.%d.%d.%d\tbroadcast %d.%d.%d.%d\n"
+			,       best_if
+			,       (int)((best_netmask>>24) & 0xff)
+			,       (int)((best_netmask>>16) & 0xff)
+			,       (int)((best_netmask>>8) & 0xff)
+			,       (int)(best_netmask & 0xff)
+			,       (int)((def_bcast>>24) & 0xff)
+			,       (int)((def_bcast>>16) & 0xff)
+			,       (int)((def_bcast>>8) & 0xff)
+			,       (int)(def_bcast & 0xff));
+		}else{
+			printf("%s\tnetmask %d\tbroadcast %d.%d.%d.%d\n"
+			,       best_if
+			,	netmask_bits(best_netmask)
+			,       (int)((def_bcast>>24) & 0xff)
+			,       (int)((def_bcast>>16) & 0xff)
+			,       (int)((def_bcast>>8) & 0xff)
+			,       (int)(def_bcast & 0xff));
+		}
+	}
+	return(0);
+}
+
+void
+usage(int ec)
+{
+	fprintf(stderr, "\n"
+		"%s version 2.99.1 Copyright Alan Robertson\n"
+		"\n"
+		"Usage: %s [-C]\n"
+		"Options:\n"
+		"    -C: Output netmask as the number of bits rather "
+			"than as 4 octets.\n"
+		"Environment variables:\n"
+		"OCF_RESKEY_ip		 ip address (mandatory!)\n"
+		"OCF_RESKEY_cidr_netmask netmask of interface\n"
+		"OCF_RESKEY_broadcast	 broadcast address for interface\n"
+		"OCF_RESKEY_nic		 interface to assign to\n"
+	,	cmdname, cmdname);
+	exit(ec);
+}
+
+/*
+Iface	Destination	Gateway 	Flags	RefCnt	Use	Metric	Mask		MTU	Window	IRTT                                                       
+eth0	33D60987	00000000	0005	0	0	0	FFFFFFFF	0	0	0                                                                               
+eth0	00D60987	00000000	0001	0	0	0	00FFFFFF	0	0	0                                                                               
+lo	0000007F	00000000	0001	0	0	0	000000FF	0	0	0                                                                                 
+eth0	00000000	FED60987	0003	0	0	0	00000000	0	0	0                                                                               
+
+netstat -rn outpug from RedHat Linux 6.0
+Kernel IP routing table
+Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
+192.168.85.2    0.0.0.0         255.255.255.255 UH        0 0          0 eth1
+10.0.0.2        0.0.0.0         255.255.255.255 UH        0 0          0 eth2
+208.132.134.61  0.0.0.0         255.255.255.255 UH        0 0          0 eth0
+208.132.134.32  0.0.0.0         255.255.255.224 U         0 0          0 eth0
+192.168.85.0    0.0.0.0         255.255.255.0   U         0 0          0 eth1
+10.0.0.0        0.0.0.0         255.255.255.0   U         0 0          0 eth2
+127.0.0.0       0.0.0.0         255.0.0.0       U         0 0          0 lo
+0.0.0.0         208.132.134.33  0.0.0.0         UG        0 0          0 eth0
+
+|--------------------------------------------------------------------------------
+netstat -rn output from FreeBSD 3.3
+Routing tables
+
+Internet:
+Destination        Gateway            Flags     Refs     Use     Netif Expire
+default            209.61.94.161      UGSc        3        8      pn0
+192.168            link#1             UC          0        0      xl0
+192.168.0.2        0:60:8:a4:91:fd    UHLW        0       38      lo0
+192.168.0.255      ff:ff:ff:ff:ff:ff  UHLWb       1     7877      xl0
+209.61.94.160/29   link#2             UC          0        0      pn0
+209.61.94.161      0:a0:cc:26:c2:ea   UHLW        6    17265      pn0   1105
+209.61.94.162      0:a0:cc:27:1c:fb   UHLW        1      568      pn0   1098
+209.61.94.163      0:a0:cc:29:1f:86   UHLW        0     4749      pn0   1095
+209.61.94.166      0:a0:cc:27:2d:e1   UHLW        0       12      lo0
+209.61.94.167      ff:ff:ff:ff:ff:ff  UHLWb       0    10578      pn0
+
+|--------------------------------------------------------------------------------
+netstat -rn output from FreeBSD 4.2
+Routing tables
+
+Internet:
+Destination        Gateway            Flags     Refs     Use     Netif Expire
+default            64.65.195.1        UGSc        1       11      dc0
+64.65.195/24       link#1             UC          0        0      dc0 =>
+64.65.195.1        0:3:42:3b:0:dd     UHLW        2        0      dc0   1131
+64.65.195.184      0:a0:cc:29:1f:86   UHLW        2    18098      dc0   1119
+64.65.195.194      0:a0:cc:27:2d:e1   UHLW        3   335161      dc0    943
+64.65.195.200      52:54:0:db:33:b3   UHLW        0       13      dc0    406
+64.65.195.255      ff:ff:ff:ff:ff:ff  UHLWb       1      584      dc0
+127.0.0.1          127.0.0.1          UH          0        0      lo0
+192.168/16         link#2             UC          0        0      vx0 =>
+192.168.0.1        0:20:af:e2:f0:36   UHLW        0        2      lo0
+192.168.255.255    ff:ff:ff:ff:ff:ff  UHLWb       0        1      vx0
+
+Internet6:
+Destination                       Gateway                       Flags      Netif Expire
+::1                               ::1                           UH          lo0
+fe80::%dc0/64                     link#1                        UC          dc0
+fe80::%vx0/64                     link#2                        UC          vx0
+fe80::%lo0/64                     fe80::1%lo0                   Uc          lo0
+ff01::/32                         ::1                           U           lo0
+ff02::%dc0/32                     link#1                        UC          dc0
+ff02::%vx0/32                     link#2                        UC          vx0
+ff02::%lo0/32                     fe80::1%lo0                   UC          lo0
+*/
+
diff --git a/tools/ocf-tester.8 b/tools/ocf-tester.8
new file mode 100644
index 0000000..850ec0b
--- /dev/null
+++ b/tools/ocf-tester.8
@@ -0,0 +1,56 @@
+.TH OCF-TESTER "8" "January 2012" "Tool for testing if a cluster resource is OCF compliant" "System Administration Utilities"
+.SH NAME
+ocf-tester \- Part of the Linux-HA project
+.SH SYNOPSIS
+.B ocf-tester
+[\fI-LhvqdX\fR] \fI-n resource_name \fR[\fI-o name=value\fR]\fI* /full/path/to/resource/agent\fR
+.SH DESCRIPTION
+Tool for testing if a cluster resource is OCF compliant
+.SH OPTIONS
+.TP
+\fB\-h\fR
+This text
+.TP
+\fB\-v\fR
+Be verbose while testing
+.TP
+\fB\-q\fR
+Be quiet while testing
+.TP
+\fB\-d\fR
+Turn on RA debugging
+.TP
+\fB\-n\fR name
+Name of the resource
+.TP
+\fB\-o\fR name=value
+Name and value of any parameters required by the agent
+.TP
+\fB\-L\fR
+Use lrmadmin/lrmd for tests
+.PP
+Usage: ocf\-tester [\-Lh] \fB\-n\fR resource_name [\-o name=value]* /full/path/to/resource/agent
+.TP
+\fB\-h\fR
+This text
+.TP
+\fB\-v\fR
+Be verbose while testing
+.TP
+\fB\-q\fR
+Be quiet while testing
+.TP
+\fB\-d\fR
+Turn on RA debugging
+.TP
+\fB\-X\fR
+Turn on RA tracing (expect large output)
+.TP
+\fB\-n\fR name
+Name of the resource
+.TP
+\fB\-o\fR name=value
+Name and value of any parameters required by the agent
+.TP
+\fB\-L\fR
+Use lrmadmin/lrmd for tests
diff --git a/tools/ocf-tester.in b/tools/ocf-tester.in
new file mode 100755
index 0000000..ae2c4a9
--- /dev/null
+++ b/tools/ocf-tester.in
@@ -0,0 +1,432 @@
+#!/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
+DATADIR=@datadir@
+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
+
+info() {
+    [ "$quiet" -eq 1 ] && return
+    echo "$*"
+}
+debug() {
+    [ "$verbose" -eq 0 ] && return
+    echo "$*"
+}
+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 [-LhvqdX] -n resource_name [-o name=value]* /full/path/to/resource/agent"
+    echo ""
+    echo "Options:"
+    echo "  -h       		This text"
+    echo "  -v       		Be verbose while testing"
+    echo "  -q       		Be quiet while testing"
+    echo "  -d       		Turn on RA debugging"
+    echo "  -X       		Turn on RA tracing (expect large output)"
+    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
+    local targetrc matched
+
+    if [ $# = 0 ]; then
+	exit_code=0
+    else
+	exit_code=$1; shift
+    fi
+
+    for targetrc in `echo $target | tr ':' ' '`; do
+        [ $rc -eq $targetrc ] && matched=1
+    done
+    if [ "$matched" != 1 ]; 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
+quiet=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;;
+	-d) export HA_debug=1; shift;;
+	-X) export OCF_TRACE_RA=1; verbose=1; shift;;
+	-q) quiet=1; shift;;
+	-?|--help) usage 0;;
+	--version) echo "@PACKAGE_VERSION@"; exit 0;;
+	-*) 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)" >&2
+	usage 1
+    fi
+fi
+
+if [ "x" = "x$OCF_RESOURCE_INSTANCE" ]; then
+    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" >&2
+    usage 1
+fi
+installed_rc=5
+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" >&2
+		exit 1
+	}
+	trap '
+		[ "$lrmd_started" = 1 ] && $LRMD -k
+	' EXIT
+	add_resource || {
+		echo "failed to add resource to lrmd" >&2
+		exit 1
+	}
+fi
+
+lrm_test_command() {
+	action="$1"
+	msg="$2"
+	debug "$msg"
+	exec_resource $action "$lrm_ra_args"
+}
+
+test_permissions() {
+    action=meta-data
+    debug ${1:-"Testing permissions with uid nobody"}
+    su nobody -s /bin/sh $agent $action > /dev/null
+}
+
+test_metadata() {
+    action=meta-data
+    msg=${1:-"Testing: $action"}
+    debug $msg
+    $agent $action | (cd $DATADIR/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; $agent $action 2>&1 > /dev/null"
+    if [ $verbose -eq 0 ]; then
+	command_output=`$agent $action 2>&1`
+    else
+    	debug $msg
+	$agent $action
+    fi
+    rc=$?
+    #echo rc: $rc
+    return $rc
+}
+
+# Begin tests
+info "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
+
+ra_args="export $ra_args"
+eval $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:$installed_rc "The initial probe for a stopped resource should return $stopped_rc or $installed_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"
+
+OCF_RESKEY_CRM_meta_interval=0
+test_command monitor
+assert $? 0 "Probing an active resource should return 0"
+OCF_RESKEY_CRM_meta_interval=20000
+
+test_command notify
+rc=$?
+if [ $rc -eq 3 ]; then
+    info "* 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
+    info "* Your agent does not support the demote action (optional)"
+fi
+
+test_command promote "Checking for promote action"
+if [ $? -eq 3 ]; then
+    has_promote=0
+    info "* 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
+    info "* 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
+    info "* Your agent does not support the migrate action (optional)"
+fi
+
+test_command reload "Checking for reload action"
+if [ $? -eq 3 ]; then
+    info "* Your agent does not support the reload action (optional)"
+fi
+
+if [ $num_errors -gt 0 ]; then
+    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/ChangeLog b/tools/ocft/ChangeLog
new file mode 100644
index 0000000..8b00210
--- /dev/null
+++ b/tools/ocft/ChangeLog
@@ -0,0 +1,57 @@
+0.43:
+	- Add an option 'Agent' in 'CONFIG'
+	- Fix a bug about remote shell.
+	- Add top level option 'VARIABLE'.
+	- Add top level option 'CLEANUP-AGENT'.
+	- Rename Var & Unvar to Env & Unenv.
+	- Fix a bug about agent installation.
+	- Modified configs of agent according the new syntax.
+0.42:
+	- Fix a bug about agent installation.
+	- The tests stop early if the basic functionality it not there.
+	- Fix a bug about 'config parser'.
+	- Keep the resource stat between the runs to avoid there are multiple stop/start per run.
+	- Add a function with warning output.
+	- Adjust the sequence of cases running.
+	- Change the default timeout.
+	- Replace the crm_master command in Agent scripts, it is no use in testing, 
+	  because the agent runs in local when test.
+	- Support drbd testing if the configuration is correct.
+	- Fix a 'Include' bug.
+	- Fix a bug about configuration of 'mysql'.
+0.41:
+	- Fixed a remote shell bug.
+	- Improved 'Include' option, now it supports remote shell, invoked just like 'Include at ip_address'.
+	- Show line number, if syntax error occurs in config file.
+	- Add a 'AgentRoot' sub-option.
+	- Fix a bug with config parsing.
+	- Rename ACTION "run" to "test".
+	- Add a simple output mode for "test" ACTION.
+	- Add a verbose ouput mode for "help" ACTION.
+	- The output will be recorded to log file.
+	- Add double stop and double start to tests.
+	- Exit with 1 if test script failed.
+	- The output of agents will be exposed if the test fails.
+	- Run zypper with -q
+	- Use 127.0.0.x(and lo for interface) for agents IP*
+0.4:
+	- Add a 'CASE-BLOCK' top option, it can be included by 'CASE'
+	- Add a 'SETUP-AGENT' top option, you can initialize agents before testing.  
+	- Add a 'Include' sub-option.
+	- Add a 'Unvar' sub-option.
+	- Rename 'GLOBAL' to 'CONFIG'.
+	- Modify a part of syntax.
+	- Imporve the 'InstallPackage' option, now it supports SUSE, Redhat and Debian.
+	- Add README & README.zh_CN.
+0.3:
+	- All statements in CASE can be executed by remote shell.
+0.2:
+	- Implement options: BashAtExit, GLOBAL, HangTimeout, InstallPackage.
+	- Delete option: Name.
+	- Modify a part of syntax.
+	- Fix some bugs.
+	- Print testing message in human readable format.
+	- Improve 'make' and 'run' option.
+	- Add 'clean' option.
+0.1:
+	- Implement options: CASE, Bash, Run, Var, Name.
diff --git a/tools/ocft/Filesystem b/tools/ocft/Filesystem
new file mode 100644
index 0000000..75203d7
--- /dev/null
+++ b/tools/ocft/Filesystem
@@ -0,0 +1,110 @@
+# Filesystem
+# by dejan at suse.de on 
+# Tue Feb 15 18:50:04 CET 2011
+
+CONFIG
+	Agent Filesystem
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	HangTimeout 20
+
+VARIABLE
+	OCFT_fs=/var/run/resource-agents/ocft-Filesystem-fs
+	OCFT_loop=/dev/loop7
+	OCFT_dir=/var/run/resource-agents/ocft-Filesystem-mnt
+
+SETUP-AGENT
+	losetup $OCFT_loop 2>/dev/null && exit 1
+	rmdir $OCFT_dir 2>/dev/null || true
+	mkdir $OCFT_dir
+	dd if=/dev/zero of=$OCFT_fs bs=1 count=0 seek=16M 2>/dev/null
+	mke2fs -j -Fq -m 0 $OCFT_fs
+	losetup $OCFT_loop $OCFT_fs
+
+CLEANUP-AGENT
+	rmdir $OCFT_dir
+	rm $OCFT_fs
+	losetup -d $OCFT_loop
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_device=$OCFT_loop
+	Env OCF_RESKEY_fstype=ext3
+	Env OCF_RESKEY_directory=$OCFT_dir
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: invalid 'OCF_RESKEY_device'"
+	Include prepare
+	Env OCF_RESKEY_device=/dev/no_such_device
+	AgentRun start OCF_ERR_INSTALLED
+
+CASE "check base env: unset 'OCF_RESKEY_device'"
+	Include prepare
+	Unenv OCF_RESKEY_device
+	AgentRun start OCF_ERR_CONFIGURED
+
+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 "monitor when running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor when not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "monitor depth 10 when running"
+	Include prepare
+	AgentRun start
+	Env OCF_CHECK_LEVEL=10
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor depth 20 with running"
+	Include prepare
+	AgentRun start
+	Env OCF_CHECK_LEVEL=20
+	AgentRun monitor OCF_SUCCESS
+
+CASE "start insert failure (remove device)"
+	Include prepare
+	Bash losetup -d $OCFT_loop
+	BashAtExit losetup $OCFT_loop $OCFT_fs
+	AgentRun start OCF_ERR_GENERIC
+
+CASE "monitor depth 20 insert failure (r/o fs)"
+	Include prepare
+	AgentRun start
+	Bash mount -o remount,ro $OCFT_dir
+	BashAtExit mount -o remount,rw $OCFT_dir
+	Env OCF_CHECK_LEVEL=20
+	AgentRun monitor OCF_ERR_GENERIC
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
+
diff --git a/tools/ocft/IPaddr2 b/tools/ocft/IPaddr2
new file mode 100644
index 0000000..1cf81bf
--- /dev/null
+++ b/tools/ocft/IPaddr2
@@ -0,0 +1,137 @@
+# IPaddr2
+
+CONFIG
+	Agent IPaddr2
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	HangTimeout 20
+
+SETUP-AGENT
+	ip addr add 192.168.144.1/24 dev eth0 brd 192.168.144.255
+
+CLEANUP-AGENT
+	ip addr del 192.168.144.1/24 dev eth0
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_ip=192.168.144.2
+
+CASE-BLOCK check_iflabel_assigned
+	Bash ip -4 -o addr show eth0 | grep -w 192.168.144.2/24 | grep -w eth0:iflabel >/dev/null # checking iflabel was assigned correctly
+
+CASE-BLOCK check_iflabel_removed
+	Bash ! ip -4 -o addr show eth0 | grep -w 192.168.144.2/24 | grep -w eth0:iflabel >/dev/null # checking iflabel was removed correctly
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: unset 'OCF_RESKEY_ip'"
+	Include prepare
+	Unenv OCF_RESKEY_ip
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: set invalid 'OCF_RESKEY_ip'"
+	Include prepare
+	Env OCF_RESKEY_ip=not_ip_address
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: set 'OCF_RESKEY_cidr_netmask'"
+	Include prepare
+	Env OCF_RESKEY_cidr_netmask=24
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: set invalid 'OCF_RESKEY_cidr_netmask'"
+	Include prepare
+	Env OCF_RESKEY_cidr_netmask=not_netmask
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: set 'OCF_RESKEY_broadcast'"
+	Include prepare
+	Env OCF_RESKEY_broadcast=192.168.144.255
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: set invalid 'OCF_RESKEY_broadcast'"
+	Include prepare
+	Env OCF_RESKEY_broadcast=not_broadcast
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: set 'OCF_RESKEY_nic'"
+	Include prepare
+	Env OCF_RESKEY_nic=eth0
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: set invalid 'OCF_RESKEY_nic'"
+	Include prepare
+	Env OCF_RESKEY_nic=not_nic
+	AgentRun start OCF_ERR_CONFIGURED
+	AgentRun validate-all OCF_ERR_CONFIGURED
+
+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 "monitor with running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor with not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
+
+CASE "Attachment to loopback interface"
+	Env OCF_RESKEY_ip=127.0.0.3
+	AgentRun start OCF_SUCCESS
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+
+CASE "check additional env: set 'OCF_RESKEY_iflabel'"
+	Include prepare
+	Env OCF_RESKEY_nic=eth0
+	Env OCF_RESKEY_iflabel=iflabel
+	AgentRun start OCF_SUCCESS
+	Include check_iflabel_assigned
+	AgentRun stop OCF_SUCCESS
+	Include check_iflabel_removed
+
+# This is deprecated but still supported for the compatibility.
+CASE "check additional env: specify iflabel in 'OCF_RESKEY_nic'"
+	Include prepare
+	Env OCF_RESKEY_nic=eth0:iflabel
+	AgentRun start OCF_SUCCESS
+	Include check_iflabel_assigned
+	AgentRun stop OCF_SUCCESS
+	Include check_iflabel_removed
+
+# monitor should return OCF_ERR_GENERIC rather than OCF_ERR_CONFIGURED
+# when the specified OCF_RESKEY_nic is disappeard by a failure.
+# This has been changed as of 3.9.6.
+CASE "monitor failure when 'OCF_RESKEY_nic' is disappeared"
+	Include prepare
+	Env OCF_RESKEY_nic=ethDisappear
+	Env OCF_RESKEY_CRM_meta_interval=10 # not in probe
+	AgentRun monitor OCF_ERR_GENERIC
diff --git a/tools/ocft/IPaddr2v4 b/tools/ocft/IPaddr2v4
new file mode 100644
index 0000000..4d37168
--- /dev/null
+++ b/tools/ocft/IPaddr2v4
@@ -0,0 +1,323 @@
+# IPaddr2v4
+
+# Note: This test case uses two NICs(eth0, eth1) and
+# 	a IPv4 address prefix (192.168.144.0/24).
+#	Adjust them according to your environment at VARIABLE section if needed.
+
+CONFIG
+	Agent IPaddr2
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	HangTimeout 20
+
+VARIABLE
+	OCFT_target_ip=192.168.144.2
+	OCFT_target_nic=eth0
+	OCFT_target_prefix=24
+	OCFT_target_netaddr=192.168.144.1/$OCFT_target_prefix
+	OCFT_target_brd=192.168.144.255
+	OCFT_wrong_ip=192.168.120.1
+	OCFT_force_nic=eth1
+	OCFT_force_prefix=16
+	OCFT_force_prefix2=28
+	OCFT_force_brd=192.168.255.255
+
+SETUP-AGENT
+	ip addr add $OCFT_target_netaddr dev $OCFT_target_nic brd $OCFT_target_brd
+
+CLEANUP-AGENT
+	ip addr del $OCFT_target_netaddr dev $OCFT_target_nic
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_ip=$OCFT_target_ip
+	Env OCFT_check_ip=$OCFT_target_ip
+	Env OCFT_check_prefix=$OCFT_target_prefix
+	Env OCFT_check_nic=$OCFT_target_nic
+
+CASE-BLOCK check_ip_assigned
+	Bash ip -4 -o addr show $OCFT_check_nic | grep -w $OCFT_check_ip/$OCFT_check_prefix >/dev/null # checking if the IPv4 address was assigned correctly
+
+CASE-BLOCK check_ip_removed
+	Bash ! ip -4 -o addr show $OCFT_check_nic | grep -w $OCFT_check_ip/$OCFT_check_prefix >/dev/null # checking if the IPv4 address was removed correctly
+
+CASE-BLOCK base_ip_assigned
+	Bash ip addr add $OCFT_target_netaddr dev $OCFT_target_nic brd $OCFT_target_brd
+
+CASE-BLOCK base_ip_removed
+	Bash ip addr del $OCFT_target_netaddr dev $OCFT_target_nic
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+# CASE No.0
+#
+CASE "normal start"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+
+# CASE No.1
+#
+CASE "normal stop"
+	Include prepare
+	AgentRun start
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.2
+#
+CASE "double start"
+	Include prepare
+	AgentRun start
+	AgentRun start OCF_SUCCESS
+
+# CASE No.3
+#
+CASE "double stop"
+	Include prepare
+	AgentRun stop OCF_SUCCESS
+
+# CASE No.4
+#
+CASE "monitor with running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+# CASE No.5
+#
+CASE "monitor with not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+# CASE No.6
+# Note: this result is different from IPaddr2 in 3.9.3.
+#  IPaddr2 succeeds if the ip matched based on the netmask of the subnet
+#  or fails if it did not match to any.
+# Recommended to always specify both nic, cidr_netmask, and broadcast when you needed.
+# IPaddr2 in 3.9.3 was using a wrong subnet mask (constant of 32) in this case.
+#
+CASE "params with nic, no cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_target_nic
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.7
+#
+CASE "params with nic, cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_target_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_target_prefix
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.8
+#
+CASE "error params with wrong ip"
+	Include prepare
+	Env OCF_RESKEY_ip=$OCFT_wrong_ip
+	AgentRun start OCF_ERR_GENERIC
+
+# CASE No.9
+# Note: this result is different from IPaddr2 in 3.9.3.
+# IPaddr2 fails when it could not determine the correct subnet mask.
+# When it could not get base ip, it becomes the error.
+# Recommended to always specify both nic, cidr_netmask, and broadcast when you needed.
+# IPaddr2 in 3.9.3 was using a wrong subnet mask (constant of 32) in this case.
+#
+CASE "params with force nic"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCFT_check_nic=$OCFT_force_nic
+	AgentRun start OCF_ERR_GENERIC
+	Include check_ip_removed
+	Unenv OCF_RESKEY_nic
+
+# CASE No.10
+# Note: this result is different from IPaddr2 in 3.9.3.
+# IPaddr2 fails when it could not determine the broadcast.
+# Recommended to always specify both nic, cidr_netmask, and broadcast when you needed.
+# IPaddr2 in 3.9.3 succeeded but it's considered ambiguous.
+#
+CASE "params with force cidr_netmask (base netmask > assigned netmask)"
+	Include prepare
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix
+	Env OCFT_check_prefix=$OCFT_force_prefix
+	AgentRun start OCF_ERR_GENERIC
+	Include check_ip_removed
+
+# CASE No.11
+# Note: this result is different from IPaddr2 in 3.9.3.
+# IPaddr2 succeeds but the broadcast is not set.
+# This is because findif.sh can not calculate a broadcast from a netmask.
+# Recommended to always specify both nic, cidr_netmask, and broadcast when you needed.
+# IPaddr2 in 3.9.3 succeeded with using a calculated broadcast.
+#
+CASE "force to use the specified nic and cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix
+	Env OCFT_check_nic=$OCFT_force_nic
+	Env OCFT_check_prefix=$OCFT_force_prefix
+	AgentRun start OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+	Unenv OCF_RESKEY_cidr_netmask
+
+
+# CASE No.12
+# Note: this result is different from IPaddr2 in 3.9.3.
+# IPaddr2 fails when it could not determine the correct subnet mask.
+# When it could not get base ip, it becomes the error.
+# Recommended to always specify both nic, cidr_netmask, and broadcast when you needed.
+# IPaddr2 in 3.9.3 was using a wrong subnet mask (constant of 32) in this case.
+#
+CASE "error params with wrong ip and nic (not exist base_ip)"
+	Include prepare
+	Include base_ip_removed
+	Env OCF_RESKEY_nic=$OCFT_target_nic
+	Env OCFT_check_nic=$OCFT_target_nic
+	AgentRun start OCF_ERR_GENERIC
+	Include check_ip_removed
+	Include base_ip_assigned
+
+# CASE No.13
+#
+CASE "params with cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_cidr_netmask=$OCFT_target_prefix
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.14
+# Note: this result is different from IPaddr2 in 3.9.3.
+# IPaddr2 does not override the broadcast by cidr_netmask.
+# Recommended to always specify both nic, cidr_netmask, and broadcast when you needed.
+# IPaddr2 in 3.9.3 overrode the broadcast calculated by cidr_netmask.
+#
+CASE "params with force cidr_netmask (base netmask < assigned netmask)"
+	Include prepare
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix2
+	Env OCFT_check_prefix=$OCFT_force_prefix2
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.15
+# Note: this result is different from IPaddr2 in 3.9.3.
+# IPaddr2 fails when it could not determine the broadcast.
+# Recommended to always specify both nic, cidr_netmask, and broadcast when you needed.
+# IPaddr2 in 3.9.3 succeeded but it's considered ambiguous.
+#
+CASE "error params with wrong ip and cidr_netmask (not exist base_ip)"
+	Include prepare
+	Include base_ip_removed
+	Env OCF_RESKEY_cidr_netmask=$OCFT_target_prefix
+	AgentRun start OCF_ERR_GENERIC
+	Include base_ip_assigned
+
+# CASE No.16
+# Note: this result is different from IPaddr2 in 3.9.3.
+# IPaddr2 succeeds but the broadcast is not set.
+# This is because findif.sh can not calculate a broadcast from a netmask.
+# Recommended to always specify both nic, cidr_netmask, and broadcast when you needed.
+# IPaddr2 in 3.9.3 succeeded with using a calculated broadcast.
+#
+CASE "force to use the specified nic and cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix2
+	Env OCFT_check_prefix=$OCFT_force_prefix2
+	Env OCFT_check_nic=$OCFT_force_nic
+	AgentRun start OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.17
+# Note: this result is different from IPaddr2 in 3.9.3.
+# IPaddr2 succeeds but the broadcast is not set.
+# This is because findif.sh can not calculate a broadcast from a netmask.
+# Recommended to always specify both nic, cidr_netmask, and broadcast when you needed.
+# IPaddr2 in 3.9.3 succeeded with using a calculated broadcast.
+#
+CASE "force to use the specified nic and cidr_netmask (not exist base_ip)"
+	Include prepare
+	Include base_ip_removed
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix2
+	Env OCFT_check_prefix=$OCFT_force_prefix2
+	Env OCFT_check_nic=$OCFT_force_nic
+	AgentRun start OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Unenv OCF_RESKEY_nic
+	Unenv OCF_RESKEY_cidr_netmask
+	Include base_ip_assigned
+
+# CASE No.18
+#
+CASE "params with broadcast, no nic, no cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_broadcast=$OCFT_force_brd
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.19
+#
+CASE "params with broadcast, no nic, no cidr_netmask"
+	Include prepare
+	Include base_ip_removed
+	Env OCF_RESKEY_broadcast=$OCFT_force_brd
+	AgentRun start OCF_ERR_GENERIC
+	Include base_ip_assigned
+
+# CASE No.20
+#
+CASE "force to use the specified nic and cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix
+	Env OCF_RESKEY_broadcast=$OCFT_force_brd
+	Env OCFT_check_nic=$OCFT_force_nic
+	Env OCFT_check_prefix=$OCFT_force_prefix
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+	Unenv OCF_RESKEY_cidr_netmask
+
+# CASE No.21
+#
+CASE "force to use the specified nic and cidr_netmask"
+	Include prepare
+	Include base_ip_removed
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix2
+	Env OCF_RESKEY_broadcast=$OCFT_target_brd
+	Env OCFT_check_nic=$OCFT_force_nic
+	Env OCFT_check_prefix=$OCFT_force_prefix2
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+	Include base_ip_assigned
+
diff --git a/tools/ocft/IPaddr2v6 b/tools/ocft/IPaddr2v6
new file mode 100644
index 0000000..d24d890
--- /dev/null
+++ b/tools/ocft/IPaddr2v6
@@ -0,0 +1,250 @@
+# IPaddr2v6
+
+# Note: This test case uses two NICs(eth0, eth1) and
+# 	a IPv6 address prefix (2001:db8::/32, RFC3849).
+#	Adjust them according to your environment at VARIABLE section if needed.
+
+CONFIG
+	Agent IPaddr2
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	HangTimeout 20
+
+VARIABLE
+	OCFT_target_ip=2001:db8:1234::2
+	OCFT_target_nic=eth0
+	OCFT_target_prefix=64
+	OCFT_target_netaddr=2001:db8:1234::1/$OCFT_target_prefix
+	OCFT_target_linklocal=fe80::2
+	OCFT_wrong_ip=2001:db8:5678::2
+	OCFT_force_nic=eth1
+	OCFT_force_prefix=80
+	OCFT_force_prefix2=48
+
+SETUP-AGENT
+	ip addr add $OCFT_target_netaddr dev $OCFT_target_nic
+
+CLEANUP-AGENT
+	ip addr del $OCFT_target_netaddr dev $OCFT_target_nic
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_ip=$OCFT_target_ip
+	Env OCFT_check_ip=$OCFT_target_ip
+	Env OCFT_check_prefix=$OCFT_target_prefix
+	Env OCFT_check_nic=$OCFT_target_nic
+
+CASE-BLOCK check_ip_assigned
+	Bash ip -6 -o addr show $OCFT_check_nic | grep -w $OCFT_check_ip/$OCFT_check_prefix >/dev/null # checking if the IPv6 address was assigned correctly
+
+CASE-BLOCK check_ip_removed
+	Bash ! ip -6 -o addr show $OCFT_check_nic | grep -w $OCFT_check_ip/$OCFT_check_prefix >/dev/null # checking if the IPv6 address was removed correctly
+
+CASE-BLOCK base_ip_assigned
+	Bash ip addr add $OCFT_target_netaddr dev $OCFT_target_nic
+
+CASE-BLOCK base_ip_removed
+	Bash ip addr del $OCFT_target_netaddr dev $OCFT_target_nic
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+# CASE No.0
+#
+CASE "normal start"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+
+# CASE No.1
+#
+CASE "normal stop"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.2
+#
+CASE "double start"
+	Include prepare
+	AgentRun start
+	AgentRun start OCF_SUCCESS
+
+# CASE No.3
+#
+CASE "double stop"
+	Include prepare
+	AgentRun stop OCF_SUCCESS
+
+# CASE No.4
+#
+CASE "monitor with running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+# CASE No.5
+#
+CASE "monitor with not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+# CASE No.6
+#
+CASE "error params with wrong ip"
+	Include prepare
+	Env OCF_RESKEY_ip=$OCFT_wrong_ip
+	AgentRun start OCF_ERR_GENERIC
+
+# CASE No.7
+#
+CASE "error params with no nic for a link-local IPv6 address"
+	Include prepare
+	Env OCF_RESKEY_ip=$OCFT_target_linklocal
+	Env OCFT_check_ip=$OCFT_target_linklocal
+	# nic is mandatory for a link-local address
+	AgentRun start OCF_ERR_CONFIGURED
+
+# CASE No.8
+#
+CASE "params with nic, no cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_target_nic
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.9
+#
+CASE "normal usage for a link-local IPv6 address, params with nic"
+	Include prepare
+	Env OCF_RESKEY_ip=$OCFT_target_linklocal
+	Env OCFT_check_ip=$OCFT_target_linklocal
+	# nic is mandatory for a link-local address
+	Env OCF_RESKEY_nic=$OCFT_target_nic
+	Env OCFT_check_nic=$OCFT_target_nic
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.10
+#
+CASE "error params with wrong ip and nic (not exist base_ip)"
+	Include prepare
+	Include base_ip_removed
+	Env OCF_RESKEY_nic=$OCFT_target_nic
+	Env OCFT_check_nic=$OCFT_target_nic
+	AgentRun start OCF_ERR_GENERIC
+	Include check_ip_removed
+	Include base_ip_assigned
+
+# CASE No.11
+#
+CASE "params with force nic"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCFT_check_nic=$OCFT_force_nic
+	AgentRun start OCF_ERR_GENERIC
+	Include check_ip_removed
+	Unenv OCF_RESKEY_nic
+
+# CASE No.12
+#
+CASE "params with force cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_cidr_netmask=$OCFT_target_prefix
+	Env OCFT_check_prefix=$OCFT_target_prefix
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.13
+#
+CASE "params with force cidr_netmask (base netmask < assigned netmask)"
+	Include prepare
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix
+	Env OCFT_check_prefix=$OCFT_force_prefix
+	AgentRun start OCF_ERR_GENERIC
+	Include check_ip_removed
+
+# CASE No.14
+#
+CASE "params with force cidr_netmask (base netmask > assigned netmask)"
+	Include prepare
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix2
+	Env OCFT_check_prefix=$OCFT_force_prefix2
+	AgentRun start OCF_ERR_GENERIC
+	Include check_ip_removed
+
+# CASE No.15
+#
+CASE "params with cidr_netmask"
+	Include prepare
+	Include base_ip_removed
+	Env OCF_RESKEY_cidr_netmask=$OCFT_target_prefix
+	Env OCFT_check_prefix=$OCFT_target_prefix
+	AgentRun start OCF_ERR_GENERIC
+	Include base_ip_assigned
+
+# CASE No.16
+#
+CASE "params with nic, cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_target_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_target_prefix
+	Env OCFT_check_nic=$OCFT_target_nic
+	Env OCFT_check_prefix=$OCFT_target_prefix
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.17
+#
+CASE "force to use the specified nic and cidr_netmask (base netmask < assigned netmask)"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix
+	Env OCFT_check_nic=$OCFT_force_nic
+	Env OCFT_check_prefix=$OCFT_force_prefix
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.18
+#  This use case is now valid. It was not allowed until v3.9.2.
+#
+CASE "force to use the specified nic and cidr_netmask (base netmask > assigned netmask)"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix2
+	Env OCFT_check_nic=$OCFT_force_nic
+	Env OCFT_check_prefix=$OCFT_force_prefix2
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+# CASE No.19
+#
+CASE "force to use the specified nic and cidr_netmask (base netmask > assigned netmask)"
+	Include prepare
+	Include base_ip_removed
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix2
+	Env OCFT_check_nic=$OCFT_force_nic
+	Env OCFT_check_prefix=$OCFT_force_prefix2
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+	Include base_ip_assigned
+
diff --git a/tools/ocft/IPsrcaddr b/tools/ocft/IPsrcaddr
new file mode 100644
index 0000000..d95142e
--- /dev/null
+++ b/tools/ocft/IPsrcaddr
@@ -0,0 +1,63 @@
+# IPsrcaddr
+
+CONFIG
+	Agent IPsrcaddr
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage iproute2
+	HangTimeout 20
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_ipaddress= # put here your IP
+	Env OCF_RESKEY_cidr_netmask= # and the netmask
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: unset 'OCF_RESKEY_ipaddress'"
+	Include prepare
+	Unenv OCF_RESKEY_ipaddress
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: set invalid 'OCF_RESKEY_ipaddress'"
+	Include prepare
+	Env OCF_RESKEY_ipaddress=not_ip_address
+	AgentRun start OCF_ERR_CONFIGURED
+
+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 "monitor with running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor with not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
diff --git a/tools/ocft/IPv6addr b/tools/ocft/IPv6addr
new file mode 100644
index 0000000..36a9642
--- /dev/null
+++ b/tools/ocft/IPv6addr
@@ -0,0 +1,150 @@
+# IPv6addr
+
+# Note: This test case uses two NICs(eth0, eth1) and
+# 	a IPv6 address prefix (2001:db8::/32, RFC3849).
+#	Adjust them according to your environment at VARIABLE section if needed.
+
+CONFIG
+	Agent IPv6addr
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	HangTimeout 20
+
+VARIABLE
+	OCFT_target_ipv6addr=2001:db8:1234::2
+	OCFT_target_nic=eth0
+	OCFT_target_prefix=64
+	OCFT_target_netaddr=2001:db8:1234::1/$OCFT_target_prefix
+	OCFT_target_linklocal=fe80::2
+	OCFT_wrong_ipv6addr=2001:db8:5678::2
+	OCFT_force_nic=eth1
+	OCFT_force_prefix=80
+
+SETUP-AGENT
+	ip addr add $OCFT_target_netaddr dev $OCFT_target_nic
+
+CLEANUP-AGENT
+	ip addr del $OCFT_target_netaddr dev $OCFT_target_nic
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_ipv6addr=$OCFT_target_ipv6addr
+	Env OCFT_check_ipv6addr=$OCFT_target_ipv6addr
+	Env OCFT_check_prefix=$OCFT_target_prefix
+	Env OCFT_check_nic=$OCFT_target_nic
+
+CASE-BLOCK check_ip_assigned
+	Bash ip -6 -o addr show $OCFT_check_nic | grep -w $OCFT_check_ipv6addr/$OCFT_check_prefix >/dev/null # checking if the IPv6 address was assigned correctly
+
+CASE-BLOCK check_ip_removed
+	Bash ! ip -6 -o addr show $OCFT_check_nic | grep -w $OCFT_check_ipv6addr/$OCFT_check_prefix >/dev/null # checking if the IPv6 address was removed correctly
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+
+CASE "normal start"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+
+CASE "normal stop"
+	Include prepare
+	AgentRun start
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+CASE "double start"
+	Include prepare
+	AgentRun start
+	AgentRun start OCF_SUCCESS
+
+CASE "double stop"
+	Include prepare
+	AgentRun stop OCF_SUCCESS
+
+CASE "monitor with running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor with not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "params with nic, no cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_target_nic
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+CASE "params with nic, cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_target_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_target_prefix
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+CASE "normal usage for a link-local IPv6 address"
+	Include prepare
+	Env OCF_RESKEY_ipv6addr=$OCFT_target_linklocal
+	Env OCFT_check_ipv6addr=$OCFT_target_linklocal
+	# nic is mandatory for a link-local address
+	Env OCF_RESKEY_nic=$OCFT_target_nic
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
+
+CASE "error start for a link-local IPv6 address when no nic"
+	Include prepare
+	Env OCF_RESKEY_ipv6addr=$OCFT_target_linklocal
+	# nic is mandatory for a link-local address
+	Unenv OCF_RESKEY_nic
+	AgentRun start OCF_ERR_GENERIC
+	Include check_ip_removed
+
+CASE "error params with wrong ipv6addr"
+	Include prepare
+	Env OCF_RESKEY_ipv6addr=$OCFT_wrong_ipv6addr
+	AgentRun start OCF_ERR_GENERIC
+
+# Note: this result is different from IPaddr2/findif
+#  IPaddr2 succeeds if the ip matched based on the netmask of the subnet
+#  or fails if it did not match to any.
+# Recommended to always specify both nic and cidr_netmask when you needed.
+CASE "error params with wrong cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix
+	AgentRun start OCF_ERR_GENERIC
+
+# Note: this result is different from IPaddr2/findif
+#  IPaddr2 succeeds but it uses /32 as a guessed cidr_netmask which
+#  does not seem to be expected.
+# Recommended to always specify both nic and cidr_netmask when you needed.
+CASE "error params with wrong nic"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	AgentRun start OCF_ERR_GENERIC
+
+# Note: This use case is now valid. It was not allowed until v3.9.2.
+CASE "force to use the specified nic and cidr_netmask"
+	Include prepare
+	Env OCF_RESKEY_nic=$OCFT_force_nic
+	Env OCF_RESKEY_cidr_netmask=$OCFT_force_prefix
+	Env OCFT_check_nic=$OCFT_force_nic
+	Env OCFT_check_prefix=$OCFT_force_prefix
+	AgentRun start OCF_SUCCESS
+	Include check_ip_assigned
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop OCF_SUCCESS
+	Include check_ip_removed
diff --git a/tools/ocft/LVM b/tools/ocft/LVM
new file mode 100644
index 0000000..4bd2b22
--- /dev/null
+++ b/tools/ocft/LVM
@@ -0,0 +1,86 @@
+# LVM
+# by dejan at suse.de on 
+# Wed Feb 16 13:15:01 CET 2011
+
+CONFIG
+	Agent LVM
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	HangTimeout 20
+
+VARIABLE
+	OCFT_pv=/var/run/resource-agents/ocft-LVM-pv
+	OCFT_vg=ocft-vg
+	OCFT_lv=ocft-lv
+	OCFT_loop=/dev/loop7
+
+SETUP-AGENT
+	losetup $OCFT_loop 2>/dev/null && exit 1
+	dd if=/dev/zero of=$OCFT_pv bs=1 count=0 seek=16M 2>/dev/null
+	losetup $OCFT_loop $OCFT_pv
+	pvcreate $OCFT_loop
+	vgcreate -s 4K $OCFT_vg $OCFT_loop
+	lvcreate -n $OCFT_lv -L 600K $OCFT_vg
+
+CLEANUP-AGENT
+	vgchange -an $OCFT_vg
+	lvremove -f /dev/$OCFT_vg/$OCFT_lv
+	vgremove -f $OCFT_vg
+	pvremove $OCFT_loop
+	losetup -d $OCFT_loop
+	rm $OCFT_pv
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_volgrpname=$OCFT_vg
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: invalid 'OCF_RESKEY_volgrpname'"
+	Include prepare
+	Env OCF_RESKEY_volgrpname=/dev/no_such_device
+	AgentRun start OCF_ERR_GENERIC
+
+CASE "check base env: unset 'OCF_RESKEY_volgrpname'"
+	Include prepare
+	Unenv OCF_RESKEY_volgrpname
+	AgentRun start OCF_ERR_CONFIGURED
+
+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 "monitor when running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor when not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
+
diff --git a/tools/ocft/MailTo b/tools/ocft/MailTo
new file mode 100644
index 0000000..8754035
--- /dev/null
+++ b/tools/ocft/MailTo
@@ -0,0 +1,57 @@
+# MailTo
+
+CONFIG
+	Agent MailTo
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage mailx
+	HangTimeout 20
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_email=root at localhost
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: unset 'OCF_RESKEY_email'"
+	Include prepare
+	Unenv OCF_RESKEY_email
+	AgentRun start OCF_ERR_CONFIGURED
+
+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 "monitor with running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor with not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
diff --git a/tools/ocft/Makefile.am b/tools/ocft/Makefile.am
new file mode 100644
index 0000000..2374531
--- /dev/null
+++ b/tools/ocft/Makefile.am
@@ -0,0 +1,56 @@
+# Author: John Shi
+# jshi at suse.de
+# 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		= $(ocftcfgs_DATA) $(ocft_DATA)
+
+sbin_SCRIPTS		= ocft
+
+ocftcfgsdir		= $(datadir)/$(PACKAGE_NAME)/ocft/configs
+ocftcfgs_DATA      =  apache  	\
+			 IPaddr2	\
+			 IPaddr2v4	\
+			 IPaddr2v6	\
+			 IPv6addr	\
+			 Filesystem	\
+			 LVM	\
+		       	 Raid1	\
+			 IPsrcaddr  	\
+			 MailTo		\
+			 jboss	\
+		       	 mysql		\
+		       	 mysql-proxy		\
+		       	 pgsql		\
+		       	 db2		\
+		       	 oracle		\
+		       	 drbd.linbit		\
+		       	 exportfs	\
+		       	 nfsserver	\
+		       	 portblock	\
+		       	 iscsi	\
+		       	 named	\
+		       	 postfix	\
+			 tomcat	\
+		       	 Xinetd	\
+			 SendArp
+
+ocftdir			= $(datadir)/$(PACKAGE_NAME)/ocft
+ocft_DATA		= README	\
+			  README.zh_CN	\
+			  caselib
+
diff --git a/tools/ocft/README.in b/tools/ocft/README.in
new file mode 100644
index 0000000..c837fcc
--- /dev/null
+++ b/tools/ocft/README.in
@@ -0,0 +1,147 @@
+INTRODUCTION & DESIGN
+~~~~~~~~~~~~~~~~~~~~~
+
+  - Ocft is a testing tool for resource agents. Instead of the policy of HA,
+    it mainly concerns whether resource agents run correct locally. It can 
+    design types of complicated environments to test the reliability of 
+    resource agents. Precisely, it is to display whether resource agents can 
+    return to correct or expected value. The advantage of the tool provides 
+    us with competence to design conditions which can be recorded or reproduced. 
+    Hence it is useful to debuggers.
+
+* Components
+    ** Test case generator (@sbindir@/ocft)
+      - Turning configuration files of test case to executable scripts.
+
+    ** Configuration file  (@datadir@/@PACKAGE_NAME@/ocft/configs/)
+      - Every configuration file directs only one resource agent and share the same 
+        name with resource agent but contains more test cases.
+
+    ** The testing script  (/var/lib/@PACKAGE_NAME@/ocft/cases/)
+      - After the generator reads configuration files and generates many testing 
+        scripts and the script is underway, the test begins.
+
+* How to customize the environment of testing
+  - Ocft designs the running conditions through two ways, one is changing the 
+    environment variables of resource agents (it is the interface left by OCF itself), 
+    the other is modifying the OS environment of resource agents, such as altering 
+    the permission of some key file or IP address of the machine.
+
+* How to test
+  - Firstly, you need to sketch the all complex and uncommon environments against 
+    a certain resource agent and keep in mind what consequences may be caused by 
+    these uncommon environments. 
+    Secondly, write the designed conditions and foreknown consequences into 
+    configuration files, and then run the generator to translate the test case to 
+    executable scripts. 
+    Finally, you need running these scripts to observe the output and learn 
+    the running status of each test case, which will compares the predicated result 
+    with the actual one. If they differ, you will be able to find the bugs of the 
+    resource agent.
+  - All of the output with test will be recorded into the log files, you can find them
+    in /var/lib/@PACKAGE_NAME@/ocft/cases/logs.
+
+
+HOW TO WRITE CONFIGURATION FILE
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+  - There are only 6 top level options that are all spelled by capital letters and "-". 
+    Every top level option contains sub-options that they are initials.
+
+* 'CONFIG' (top level option)
+  - Grammar: CONFIG
+  - The design in this option is global and influences every test case.
+
+    ** 'Agent' (sub-option)
+      - Grammar: Agent AGENT_NAME
+      - The agent name you want to test.
+
+    ** 'AgentRoot' (sub-option)
+      - Grammar: AgentRoot /usr/lib/ocf/resource.d/xxx
+      - A few agents will go to "linbit" or "pacemaker" directory, if you define this option,
+        ocft will use it to replace the default directory "heartbeat".
+
+    ** 'InstallPackage' (sub-option)
+      - Grammar: InstallPackage package [package2 [...]]
+      - It will test whether the system have installed the service of the resource agent. 
+        If not, it will download from Internet and have it installed automatically.
+
+    ** 'HangTimeout' (sub-option)
+      - Grammar: HangTimeout secs
+      - If you alter some key options, some resource agents will get puzzled and stop, 
+        which will influence the running of the following test case.  Hence timeout setting is 
+        needed, if the resource agent stops timeout, the scripts will kill this resource agent.
+
+* 'VARIABLE' (top level option)
+  - Garmmar: 
+      VARIABLE
+          VAR1=value1
+          VAR2=value2
+          ...
+  - Define the global variable here, the variables can be visited everywhere, they can be referenced
+    using $VAR_NAME. Note, the variables in VARIABLE are different from 'Env VAR1=value1', 'Env' can
+    affect the activity of agent, but the variables in VARIABLE just be shared with top level option.
+
+* 'SETUP-AGENT' (top level option)
+  - Grammar: 
+      SETUP-AGENT
+          bash scripts...
+	  ...
+  - Some of Agents may need to be initialized before testing, you can do it here with bash script. 
+
+* 'CLEANUP-AGENT' (top level option)
+  - Garmmar:
+      CLEANUP-AGENT
+          bash scripts...
+          ...
+  - If SETUP-AGENT set, usually you might be use this option do some cleaning work after test.
+
+* 'CASE' & 'CASE-BLOCK' (top level option)
+  - Grammar: CASE "description" & CASE-BLOCK macro_name
+  - Usually, the conditions you designed are more than one and a few 'CASE "..."' will 
+    appear in configuration file. It is worth noting that the following sub-options 
+    have 2 spellings:
+    One is general, where shell affects the local environment; the other is special, 
+    where each options added "@ipaddr". It can remotely execute shell codes. In other words,
+    it is to execute the shell codes from a remote host, which is meaningful when a resource
+    agent needs 2 hosts. This remote shell is not a remote execution only through "ssh", but
+    running a remote shell in the background while the test case is running. The remote shell
+    runs in the background till the end and saves the results during the process. That is to
+    say, you can alternatively carry out local and remote shell code segments. 
+    The "CASE-BLOCK" option is a macro definer, the statements in "CASE-BLOCK" will be inserted 
+    into "CASE" if you "Include" the "macro_name".
+
+    ** 'Env' (sub-option)
+      - Grammar: Env VARIABLE=value
+      - It is to set up an environment variable of the resource agent. They usually appear to 
+        be OCF_RESKEY_xxx. One point is to be noted is there is no blank by both sides of "=".
+
+    ** 'Unenv' (sub-option)
+      - Grammer: Unenv VARIABLE [VARIABLE2 [...]]
+      - Remove the environment variable.
+
+    ** 'Include' (sub-option)
+      - Garmmer: Include macro_name
+      - It will be replaced by statements in 'macro_name', of course, you should define the 
+        content of 'macro_name' with 'CASE-BLOCK' first.
+
+    ** 'Bash' (sub-option)
+      - Grammar: Bash bash_codes
+      - This option is to set up the environment of OS, where you can insert BASH code to 
+        customize the system randomly. Note, do not cause unrecoverable consequences to the 
+        system.
+
+    ** 'BashAtExit' (sub-option)
+      - Grammar: BashAtExit bash_codes
+      - This option is to recover the OS environment in order to run another test case 
+        correctly. Of cause you can use 'Bash' option to recover it. However, if mistakes occur 
+        in the process, the script will quit directly instead of running your recovery codes. 
+        If it happens, you ought to use BashAtExit which can restore the system environment 
+        before you quit.
+
+    ** 'AgentRun' (sub-option)
+      - Grammar: AgentRun cmd [ret_value]
+      - This option is to run resource agent. "cmd" is the parameter of the resource agent, 
+        such as "start, status, stop ...". The second parameter is optional. It will compare the 
+        actual returned value with the expected value when the script has run recourse agent. 
+        If differs, bugs will be found.
diff --git a/tools/ocft/README.zh_CN.in b/tools/ocft/README.zh_CN.in
new file mode 100644
index 0000000..5138cf1
--- /dev/null
+++ b/tools/ocft/README.zh_CN.in
@@ -0,0 +1,124 @@
+1 介绍和设计
+ocft是一个测试resource agents的工具。它并不关注HA的策略,而是关注resource agents
+是否正常运行在本机。他能对resource agents设计各种复杂环境,来考验resource agnets
+是否能正常应对,也就是看resouce agents是否能返回正确的或者说我们所期望的值。
+这个工具给我们带来的好处就是我们可以集中的批量的来设计环境,而且这种环境是可被我们
+记录、重现的,对Debug人员来说是很有用的。
+
+1.1 组成
+1.1.1 解释器 (@sbindir@/ocft)
+将test case配置文件转换成可执行的测试脚本。
+
+1.1.2 配置文件 (@datadir@/@PACKAGE_NAME@/ocft/configs/)
+每一个configuration file只针对一个resouce agent,配置文件名与resouce agent名相同,
+但是它可以容纳很多test case。
+
+1.1.3 测试脚本 (/var/lib/@PACKAGE_NAME@/ocft/cases/)
+由generator读取configuration file生成测试脚本,直接运行此脚本就可以开始测试了。
+
+1.2 如何定制环境
+ocft 通过两种手段来设计resouce agents的运行环境,一是更改resouce agents的环境变量,
+当然这是ocf本身就留给我们的接口。二是更改resource agents所处的系统环境,
+比如更改某个关键文件的权限,更改本机ip地址等等...
+
+1.3 如何进行测试
+首先你需要针对某个resource agent在脑中勾画各种复杂且异常的环境,并且你能清楚预知
+这些异常环境会给resource agent带来什么结果,然后将这些设计好的环境和你预知的结果
+都写入配置文件,然后运行generator,将你刚写的test case转换成可执行的脚本。最后运行
+这些脚本,观察它们的输出,你可以清楚看到每个test case运行状况,他会比较你的预知结
+果和resource agent的实际结果,如果不一样,说明你找到resource agent的bug了。
+所有的测试输出都会被记录到日志文件中,你可以在 /var/lib/@PACKAGE_NAME@/ocft/cases/logs
+中找到他们.
+
+2 配置
+只有6个top level option,它们是由大写字母和'-'构成的,每个top level option都有若干sub-option,
+它们是首字母大写。
+
+2.1 'CONFIG' 选项
+语法:CONFIG
+此option中的设计是全局的,对每个test case都有所影响。
+
+2.1.1 'Agent' 选项
+语法:Agent AGENT_NAME
+你要测试的Agent的名字。
+
+2.1.2 'AgentRoot' 选项
+语法:AgentRoot /usr/lib/ocf/resource.d/xxx
+一些agent将会被移到 "pacemaker" 或 "linbit" 目录,如果你定义了这个选项,ocft将会用它来
+替代默认的目录"heartbeat"。
+
+2.1.3 'InstallPackage' 选项
+语法:InstallPackage package [package2 [...]]
+他会检测系统是否安装了此resource agent的service,如果没有安装,会自动从网络进行安装。
+package_name是某个resouce agent在操作系统中必须安装的包。
+
+2.1.4 'HangTimeout' 选项
+语法:HangTimeout secs 
+如果你更改了一些很关键的东西,有些resouce agent会不知所措,停在那里不动,那么就会影响
+到后面test case的运行,所以你需要设定超时,如果一旦resouce agent停在那超时了,脚本会
+杀死这个resouce agent。
+
+2.2 'VARIABLE' 选项
+语法:
+VARIABLE
+	VAR1=value1
+	VAR2=value2
+        ...
+在此定义全局变量,这些变量可以用于配置文件中的任何地方,引用时在变量名前加上$。请注意,这些
+变量不同于Env定义的变量,Env是定义环境变量,可以改变agent的行为,而这些变量只是用于配置文件中
+共享。
+
+2.3 'SETUP-AGENT' 选项
+语法:
+SETUP-AGENT
+	bash scripts...
+	...
+一些Agent在测试前可能需要初始化,你可以用bash脚本在这初始化。
+
+2.4 'CLEANUP-AGENT' 选项
+语法:
+CLEANUP-AGENT
+	bash scripts...
+	...
+如果之前定义了SETUP-AGENT, 你可能还需要此选项在测试完后来作一些清除。
+
+2.5 'CASE' & 'CASE-BLOCK' 选项
+语法:CASE "description" & CASE-BLOCK macro_name
+通常你设计的环境不止一个,那么配置文件中应该会出现许多 'CASE "..."',值得注意的是,以下子
+选项每个都有两种写法,一是普通写法,产生的shell代码对本地产生作用,二是特殊写法,就是在每
+个选项后加上 "@ipaddr",他可以远程执行shell代码,也就是控制远程机器执行你给的shell代码,
+这对需要两台机器以上的resouce agent很有用的,这个远程shell并非简单的用ssh去远程执行,而是在
+test case生存期内,后台运行一个远程shell,他始终在后台运行并且保存你的中间结果,也就是说你
+可以交替执行本地shell代码段和远程shell代码段。
+'CASE-BLOCK'选项是一个宏定义器,它定义的内容将会被插入到"CASE"内容中。
+
+2.5.1 'Env' 选项
+语法:Env VARIABLE=value
+这是设置resouce agent的环境变量,他们通常是OCF_RESKEY_xxx,注意=号两边不要有空格。
+
+2.5.2 'Unenv' 选项
+语法:Unenv VARIABLE
+此选项用于删除环境变量。
+
+2.5.3 'Include' 选项
+语法:Include macro_name
+此选项将会被宏"macro_name"的内容所替代,当然,你得预先用"CASE-BLOCK"来定义宏"macro_name"
+的内容。
+
+2.5.4 'Bash' 选项
+语法:Bash bash_codes
+此选项是用来设置os的环境,你可以嵌入bash代码来对系统作任意设置,不过要注意不要对系统造成
+不可恢复的后果就行了。
+
+2.5.5 'BashAtExit' 选项
+语法:BashAtExit bash_codes
+此选项是用来恢复os的环境,以便另一个test case能正常运行,当然你也可以直接用'Bash'选项来
+恢复,但是如果脚本在执行过程中产生某些错误,那么脚本会直接退出,而不会去执行你的恢复代码,
+那么你就要用到BashAtExit,他能在你退出前去恢复系统环境。
+
+2.5.6 'AgentRun' 选项
+语法:AgentRun cmd [ret_value]
+此option会去运行resouce agent,'cmd' 就是resouce agent的参数,如 start,status,stop ...
+第二个参数是可选的,它是你对系统环境作出特殊设定以后,你预计resouce agent会返回的值,
+如果给出此参数,那么脚本会在运行resouce agent后,会比较此时的返回值和你预期的返回值,
+如果不一致,那么说明找到bug了。
diff --git a/tools/ocft/Raid1 b/tools/ocft/Raid1
new file mode 100644
index 0000000..1c239c8
--- /dev/null
+++ b/tools/ocft/Raid1
@@ -0,0 +1,146 @@
+# Raid1
+# by dejan at suse.de on 
+# Fri Aug 24 17:01:40 CEST 2012
+
+CONFIG
+	Agent Raid1
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage mdadm
+	HangTimeout 20
+
+VARIABLE
+	OCFT_disk0=/var/run/resource-agents/ocft-Raid1-disk0
+	OCFT_disk1=/var/run/resource-agents/ocft-Raid1-disk1
+	OCFT_disk2=/var/run/resource-agents/ocft-Raid1-disk2
+	OCFT_disk3=/var/run/resource-agents/ocft-Raid1-disk3
+	OCFT_raidconf=/var/run/resource-agents/ocft-mdadm.conf
+	OCFT_raiddev=/dev/md8
+	OCFT_raiddev2=/dev/md9
+	OCFT_loop0=/dev/loop6
+	OCFT_loop1=/dev/loop7
+	OCFT_loop2=/dev/loop4
+	OCFT_loop3=/dev/loop5
+
+SETUP-AGENT
+	losetup $OCFT_loop0 2>/dev/null && exit 1
+	losetup $OCFT_loop1 2>/dev/null && exit 1
+	losetup $OCFT_loop2 2>/dev/null && exit 1
+	losetup $OCFT_loop3 2>/dev/null && exit 1
+	dd if=/dev/zero of=$OCFT_disk0 bs=1 count=0 seek=16M 2>/dev/null
+	dd if=/dev/zero of=$OCFT_disk1 bs=1 count=0 seek=16M 2>/dev/null
+	dd if=/dev/zero of=$OCFT_disk2 bs=1 count=0 seek=16M 2>/dev/null
+	dd if=/dev/zero of=$OCFT_disk3 bs=1 count=0 seek=16M 2>/dev/null
+	losetup $OCFT_loop0 $OCFT_disk0
+	losetup $OCFT_loop1 $OCFT_disk1
+	losetup $OCFT_loop2 $OCFT_disk2
+	losetup $OCFT_loop3 $OCFT_disk3
+	mdadm --create $OCFT_raiddev -l 0 --raid-devices=2 $OCFT_loop0 $OCFT_loop1
+	mdadm --create $OCFT_raiddev2 -l 0 --raid-devices=2 $OCFT_loop2 $OCFT_loop3
+	echo DEVICE $OCFT_loop0 $OCFT_loop1 > $OCFT_raidconf
+	echo DEVICE $OCFT_loop2 $OCFT_loop3 >> $OCFT_raidconf
+	echo ARRAY $OCFT_raiddev devices=$OCFT_loop0,$OCFT_loop1 >> $OCFT_raidconf
+	echo ARRAY $OCFT_raiddev2 devices=$OCFT_loop2,$OCFT_loop3 >> $OCFT_raidconf
+
+CLEANUP-AGENT
+	mdadm --zero-superblock $OCFT_loop0
+	mdadm --zero-superblock $OCFT_loop1
+	mdadm --zero-superblock $OCFT_loop2
+	mdadm --zero-superblock $OCFT_loop3
+	mdadm --remove $OCFT_raiddev 2>/dev/null
+	mdadm --remove $OCFT_raiddev2 2>/dev/null
+	losetup -d $OCFT_loop0
+	losetup -d $OCFT_loop1
+	losetup -d $OCFT_loop2
+	losetup -d $OCFT_loop3
+	rm $OCFT_disk0 $OCFT_disk1 $OCFT_raidconf
+	rm $OCFT_disk2 $OCFT_disk3
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_raidconf=$OCFT_raidconf
+	Env OCF_RESKEY_raiddev=$OCFT_raiddev
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE-BLOCK prepare_auto
+	Include required_args
+	Env OCF_RESKEY_raiddev="auto"
+	Include default_status
+
+CASE-BLOCK prepare_multiple
+	Include required_args
+	Env OCF_RESKEY_raiddev="$OCFT_raiddev $OCFT_raiddev2"
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: invalid 'OCF_RESKEY_raiddev'"
+	Include prepare
+	Env OCF_RESKEY_raiddev=/dev/no_such_device
+	AgentRun start OCF_ERR_GENERIC
+
+CASE "check base env: unset 'OCF_RESKEY_raiddev'"
+	Include prepare
+	Unenv OCF_RESKEY_raiddev
+	AgentRun start OCF_ERR_CONFIGURED
+
+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 "monitor when running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor when not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "normal start (auto)"
+	Include prepare_auto
+	AgentRun start OCF_SUCCESS
+	AgentRun monitor OCF_SUCCESS
+
+CASE "normal stop (auto)"
+	Include prepare_auto
+	AgentRun start
+	AgentRun stop OCF_SUCCESS
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "normal start (multiple)"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+	AgentRun monitor OCF_SUCCESS
+
+CASE "normal stop (multiple)"
+	Include prepare
+	Env OCF_RESKEY_raiddev="$OCFT_raiddev $OCFT_raiddev2"
+	AgentRun start
+	AgentRun stop OCF_SUCCESS
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
+
diff --git a/tools/ocft/SendArp b/tools/ocft/SendArp
new file mode 100644
index 0000000..7880388
--- /dev/null
+++ b/tools/ocft/SendArp
@@ -0,0 +1,74 @@
+# SendArp
+
+CONFIG
+	Agent SendArp
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage resource-agents
+	HangTimeout 15
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_ip=127.0.0.1
+	Env OCF_RESKEY_nic=lo
+	Env OCF_RESKEY_background=false
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: unset 'OCF_RESKEY_ip'"
+	Include prepare
+	Unenv OCF_RESKEY_ip
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: set invalid 'OCF_RESKEY_ip'"
+	Include prepare
+	Env OCF_RESKEY_ip=not_ip_address
+	AgentRun start OCF_ERR_GENERIC
+
+CASE "check base env: unset 'OCF_RESKEY_nic'"
+	Include prepare
+	Unenv OCF_RESKEY_nic
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: set invalid 'OCF_RESKEY_nic'"
+	Include prepare
+	Env OCF_RESKEY_nic=not_nic
+	AgentRun start OCF_ERR_GENERIC
+
+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 "monitor with running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor with not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
diff --git a/tools/ocft/Xinetd b/tools/ocft/Xinetd
new file mode 100644
index 0000000..ba9c85c
--- /dev/null
+++ b/tools/ocft/Xinetd
@@ -0,0 +1,56 @@
+# Xinetd
+
+CONFIG
+	Agent Xinetd
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage xinetd
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_service=discard
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: unset 'OCF_RESKEY_protocol'"
+	Include prepare
+	Unenv OCF_RESKEY_service
+	AgentRun start OCF_ERR_CONFIGURED
+
+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 "monitor with running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor with not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
diff --git a/tools/ocft/apache b/tools/ocft/apache
new file mode 100644
index 0000000..e939044
--- /dev/null
+++ b/tools/ocft/apache
@@ -0,0 +1,63 @@
+# apache
+# make sure that your apache configuration loads mod_status
+
+CONFIG
+	Agent apache
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage apache2
+        HangTimeout 20
+
+SETUP-AGENT
+	/etc/init.d/apache2 start
+	/etc/init.d/apache2 stop
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: set non-existing OCF_RESKEY_statusurl"
+	Include prepare
+	Env OCF_RESKEY_statusurl="yoyoyoyo"
+	AgentRun start OCF_ERR_GENERIC
+
+CASE "check base env: set non-existing OCF_RESKEY_configfile"
+	Include prepare
+	Env OCF_RESKEY_configfile="/yoyoyoyo/nosuchfile"
+	AgentRun start OCF_ERR_INSTALLED
+
+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 "running monitor"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "not running monitor"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
diff --git a/tools/ocft/caselib.in b/tools/ocft/caselib.in
new file mode 100644
index 0000000..8c8a45a
--- /dev/null
+++ b/tools/ocft/caselib.in
@@ -0,0 +1,294 @@
+#
+# Copyright (c) 2010-2011 Novell Inc, John Shi
+#           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.
+
+
+quit()
+{
+  local ret
+  ret="$1"
+
+  while [ $__OCFT__atexit_num -gt 0 ]; do
+    atexit$__OCFT__atexit_num
+    let __OCFT__atexit_num--
+  done
+
+  rm -rf $__OCFT__fakebin
+
+  exit $ret
+}
+
+agent_install()
+{
+  local pkg
+
+  if [ $# -eq 0 ]; then
+    return 0
+  fi
+
+  for pkg in "$@"; do
+    if [ -e /etc/SuSE-release ]; then
+      if ! rpm -ql "$pkg" >/dev/null 2>&1; then
+        echo "${__OCFT__showhost}Installing $pkg ..."
+        zypper -q install -y "$pkg" >/dev/null 2>&1
+        if ! rpm -ql "$pkg" >/dev/null 2>&1; then
+          echo
+          echo "${__OCFT__showhost}ERROR: Install '$pkg' failed."
+          quit 2
+        fi
+        echo "done"
+        echo
+      fi
+    elif [ -e /etc/debian_version ]; then
+      if ! dpkg -L "$pkg" >/dev/null 2>&1; then
+        echo "${__OCFT__showhost}Installing $pkg ..."
+        apt-get -y install "$pkg" >/dev/null 2>&1
+        if ! dpkg -L "$pkg" >/dev/null 2>&1; then
+          echo
+          echo "${__OCFT__showhost}ERROR: Install '$pkg' failed."
+          quit 2
+        fi
+        echo "done"
+        echo
+      fi
+    elif [ -e /etc/redhat-release ]; then
+      if ! rpm -ql "$pkg" >/dev/null 2>&1; then
+        echo "${__OCFT__showhost}Installing $pkg ..."
+        yum -y install "$pkg" >/dev/null 2>&1
+        if ! rpm -ql "$pkg" >/dev/null 2>&1; then
+          echo
+          echo "${__OCFT__showhost}ERROR: Install '$pkg' failed."
+          quit 2
+        fi
+        echo "done"
+        echo
+      fi
+    else
+      echo "${__OCFT__showhost}ERROR: Cannot detect your OS type."
+      quit 2
+    fi
+  done
+}
+
+agent_run()
+{
+  local agent cmd timeout pid i ret aroot
+  agent="$1"
+  cmd="$2"
+  timeout="$3"
+
+  aroot=${__OCFT__MYROOT:-$__OCFT__AGENT_ROOT}
+
+  setsid $aroot/$agent $cmd >/tmp/.ocft_runlog 2>&1 &
+  pid=$!
+
+  i=0
+  while [ $i -lt $timeout ]; do
+    if [ ! -e /proc/$pid ]; then
+      break
+    fi
+    sleep 1
+    let i++
+  done
+
+  if [ $i -ge $timeout ]; then
+    kill -SIGTERM -$pid >/dev/null 2>&1
+    sleep 3
+    kill -SIGKILL -$pid >/dev/null 2>&1
+    echo -n "${__OCFT__showhost}ERROR: The agent was hanging, killed it, "
+    echo "maybe you damaged the agent or system's environment, see details below:"
+    cat /tmp/.ocft_runlog
+    echo
+    quit 1
+  fi
+
+  wait $pid
+}
+
+check_success()
+{
+  local ret msg
+  ret="$1"
+  msg="$2"
+
+  if [ $ret -ne 0 ]; then
+    echo "${__OCFT__showhost}ERROR: '${msg}' failed, the return code is ${ret}."
+    quit 1
+  fi
+}
+
+__maxfd()
+{
+  (echo 0; ls -1 /proc/$$/fd) | sort -rn | head -1
+}
+
+__getfd()
+{
+  local host rw fd file
+  host="$1"
+  rw="$2"
+
+  for fd in /proc/$$/fd/*; do
+    file=$(basename "$(readlink $fd)")
+    if [ "$file" = "${host}_$rw" ]; then
+      basename $fd
+      break
+    fi
+  done
+}
+
+backbash_start()
+{
+  local host fd rfd wfd
+  host="$1"
+
+  if [ ! -d "$__OCFT__CASES_DIR" ]; then
+    echo "${__OCFT__showhost}ERROR: Could not found Directory: ${__OCFT__CASES_DIR}."
+    quit 1
+  fi
+
+  if lsof $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w >/dev/null 2>&1; then
+    echo "${__OCFT__showhost}ERROR: Connection exist with $host."
+    quit 1
+  fi
+  if [ ! -p "$__OCFT__CASES_DIR/${host}_r" ] || [ ! -p "$__OCFT__CASES_DIR/${host}_w" ]; then
+    rm -f $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w
+    if ! mkfifo $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w >/dev/null 2>&1; then
+      echo "${__OCFT__showhost}ERROR: Could not create pipe file: $__OCFT__CASES_DIR/${host}_*."
+      quit 1
+    fi
+  fi
+
+  ssh root@$host '/bin/bash 2>&1
+                  sed "s/00/001/g" /tmp/.backbash-log
+                  echo 000
+                  echo 1' >$__OCFT__CASES_DIR/${host}_r <$__OCFT__CASES_DIR/${host}_w &
+
+  fd=$(__maxfd)
+  rfd=$(expr $fd + 1)
+  wfd=$(expr $fd + 2)
+  eval "exec ${rfd}<$__OCFT__CASES_DIR/${host}_r ${wfd}>$__OCFT__CASES_DIR/${host}_w"
+}
+
+backbash()
+{
+  local host rfd wfd ret
+  host="$1"
+
+  rfd=$(__getfd $host r)
+  wfd=$(__getfd $host w)
+
+  if [ -z "$rfd" -o -z "$wfd" ]; then
+    echo "${__OCFT__showhost}ERROR: Could not found connection with $host."
+  fi
+
+  cat >&$wfd <<EOF
+{
+true
+EOF
+  cat >&$wfd
+  cat >&$wfd <<EOF
+
+} >&/tmp/.backbash-log
+sed 's/00/001/g' /tmp/.backbash-log
+echo 000
+echo 0
+EOF
+  if [ $? -ne 0 ]; then
+    echo "${__OCFT__showhost}ERROR: Broken connection with $host."
+    quit 1
+  fi
+
+  awk -vlive=2 '{
+    if (sub(/000$/, "")) {
+      if ($0 != "") {
+        gsub("001", "00");
+        printf("%s", $0);
+      }
+      getline live;
+      exit;
+    }
+    gsub("001", "00");
+    print;
+  } END {
+    exit(live);
+  }' <&$rfd
+  case $? in
+      1)
+        quit 1
+        ;;
+      2)
+        echo "${__OCFT__showhost}ERROR: Broken connection with $host."
+        quit 1
+        ;;
+  esac
+}
+
+backbash_stop()
+{
+  local host rfd wfd
+  host="$1"
+
+  wfd=$(__getfd $host w)
+  if [ -n "$wfd" ]; then
+    cat >&$wfd <<<'quit 0'
+  fi
+  rm -f $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w
+}
+
+
+export OCF_ROOT=@OCF_ROOT_DIR@
+export OCF_LIB=@OCF_LIB_DIR@/heartbeat
+__OCFT__AGENT_ROOT=@OCF_RA_DIR@/heartbeat
+__OCFT__CASES_DIR=/var/lib/@PACKAGE_NAME@/ocft/cases
+
+__OCFT__atexit_num=0
+
+if [ $EUID -ne 0 ]; then
+  echo "${__OCFT__showhost}ERROR: '$0' needs to be run by root."
+  quit 3
+fi
+
+__OCFT__fakebin=./fakebin
+
+mkdir -p $__OCFT__fakebin >/dev/null 2>&1 &&
+ln -sf /bin/true $__OCFT__fakebin/crm_master >/dev/null 2>&1 &&
+ln -sf /bin/true $__OCFT__fakebin/crm_mon >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+  echo "${__OCFT__showhost}ERROR: initialize 'fakebin' failed."
+  quit 3
+fi
+export HA_SBIN_DIR=$__OCFT__fakebin
+
+. $OCF_LIB/ocf-returncodes || {
+  echo "${__OCFT__showhost}ERROR: $OCF_LIB/ocf-returncodes not found."
+  quit 3
+}
+
+while read __OCFT__line; do
+  if [ -n "$__OCFT__line" ]; then
+    __OCFT__retn=${__OCFT__line%%=*}
+    __OCFT__reti=$(eval echo \$$__OCFT__retn)
+    __OCFT__retval[__OCFT__reti]=$__OCFT__retn
+  fi
+done <<<"$(sed 's/#.*//' $OCF_LIB/ocf-returncodes)"
+
diff --git a/tools/ocft/db2 b/tools/ocft/db2
new file mode 100644
index 0000000..7013a99
--- /dev/null
+++ b/tools/ocft/db2
@@ -0,0 +1,164 @@
+# 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
+	Agent db2
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+        HangTimeout 40
+
+SETUP-AGENT
+        # nothing
+
+CASE-BLOCK set_testenv
+        Env OCFT_instance=db2inst1
+        Env OCFT_db=ocft
+
+CASE-BLOCK crm_setting
+        Env OCF_RESKEY_instance=$OCFT_instance
+	Env 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
+	Env 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
+        Env OCF_RESKEY_instance=no_such
+        Env 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
+        Env 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
+        Env 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
diff --git a/tools/ocft/drbd.linbit b/tools/ocft/drbd.linbit
new file mode 100644
index 0000000..4cc5519
--- /dev/null
+++ b/tools/ocft/drbd.linbit
@@ -0,0 +1,183 @@
+# linbit: drbd
+
+CONFIG
+	Agent drbd
+	AgentRoot /usr/lib/ocf/resource.d/linbit
+	InstallPackage drbd
+        HangTimeout 20
+
+VARIABLE
+	DRBDCONF=/tmp/ocft_drbd_tmp.conf
+
+        # should be this machine's hostname/ip, please modify it by yourself.
+	NAME_1=HOSTNAME1
+	IP_1=IP_ADDRESS1
+
+        # the block device just for test, please modify it by yourself.
+	DISK_1=/dev/DEVICE1
+
+	PORT_1=5735
+	DEVICE_1=/dev/drbd0
+ 
+        ####################################################################
+
+        # please modify it by yourself.
+	NAME_2=HOSTNAME2
+	IP_2=IP_ADDRESS2
+
+        # the block device just for test, please modify it by yourself.
+	DISK_2=/dev/DEVICE2
+
+	PORT_2=5735
+	DEVICE_2=/dev/drbd0
+
+
+
+SETUP-AGENT
+	cat >$DRBDCONF <<EOF
+	global {
+	   usage-count no;
+	}
+	
+	resource ocft0 {
+	   protocol C;
+	   disk {
+	      on-io-error detach;
+	   }
+	   on $NAME_1 {
+	      device    $DEVICE_1;
+	      address   $IP_1:$PORT_1;
+	      meta-disk internal;
+	      disk      $DISK_1;
+	   }
+	   on $NAME_2 {
+	      device    $DEVICE_2;
+	      address   $IP_2:$PORT_2;
+	      meta-disk internal;
+	      disk      $DISK_2;
+	   }
+	}
+EOF
+	HOST=$(uname -n)
+	DRBDADM="drbdadm -c $DRBDCONF"
+
+	# prepare
+	modprobe drbd $(drbdadm sh-mod-parms)
+	$DRBDADM down ocft0
+
+	# create meta data block if necessary
+	$DRBDADM dump-md ocft0 >/dev/null 2>&1
+	if [ $? -eq 255 ]; then
+		$DRBDADM create-md ocft0
+	fi
+
+	# start drbd
+	$DRBDADM up ocft0
+
+	# UpToDate
+	if [ "$HOST" = "$NAME_1" ]; then
+		$DRBDADM wait-connect ocft0
+		echo "drbd Syncing .."
+		$DRBDADM primary --force ocft0
+		while true; do
+			CSTATE=$($DRBDADM cstate ocft0)
+			DSTATE=$($DRBDADM dstate ocft0)
+			if [ "$CSTATE" = "Connected" -a "$DSTATE" = "UpToDate/UpToDate" ]; then
+				break
+			else
+				sleep 3
+			fi
+		done
+		echo "done"
+	fi
+
+CLEANUP-AGENT
+	drbdadm -c $DRBDCONF down ocft0
+	rm -f $DRBDCONF
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_drbdconf=$DRBDCONF
+	Env OCF_RESKEY_drbd_resource=ocft0
+	Env OCF_RESKEY_CRM_meta_notify=true
+	Env OCF_RESKEY_CRM_meta_clone_max=2
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include required_args
+	AgentRun validate-all OCF_SUCCESS
+
+CASE "normal start"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "normal stop"
+	Include prepare
+	AgentRun start
+	AgentRun stop OCF_SUCCESS
+
+CASE "wrong path of config file"
+	Include prepare
+	Env OCF_RESKEY_drbdconf=no_such_file
+	AgentRun start OCF_ERR_INSTALLED
+
+CASE "wrong resource name"
+	Include prepare
+	Env OCF_RESKEY_drbd_resource=no_such_src
+	# OCF_RESKEY_drbd_resource is a required parameter in agent meta-data, 
+	# if wrong, I think the agent should return OCF_ERR_CONFIGURED.
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "double start"
+	Include prepare
+	AgentRun start
+	AgentRun start OCF_SUCCESS
+
+CASE "double stop"
+	Include prepare
+	AgentRun stop OCF_SUCCESS
+
+CASE "running monitor"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "not running monitor"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "Primary/Secondary monitor"
+	Include prepare
+	AgentRun start
+	AgentRun promote
+	AgentRun monitor OCF_RUNNING_MASTER
+	AgentRun demote
+	AgentRun monitor OCF_SUCCESS
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
+
+CASE "try to 'promote' in single-primary mode"
+	Include prepare
+	Include@$IP_2 prepare
+
+        # start drbd 
+	AgentRun start
+	AgentRun@$IP_2 start
+
+	# promote local drbd first
+	AgentRun promote OCF_SUCCESS
+
+        # demote local drbd prepare for remote drbd promote
+	AgentRun demote
+	# remote drbd promote
+	AgentRun@$IP_2 promote OCF_SUCCESS
+
+	# promote fails, because remote drbd promote first.
+	AgentRun promote OCF_ERR_GENERIC
diff --git a/tools/ocft/exportfs b/tools/ocft/exportfs
new file mode 100644
index 0000000..c83520d
--- /dev/null
+++ b/tools/ocft/exportfs
@@ -0,0 +1,74 @@
+# exportfs
+#
+#
+
+CONFIG
+	Agent exportfs
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+        HangTimeout 40
+
+SETUP-AGENT
+        # nothing
+
+CASE-BLOCK set_testenv
+        Env OCF_RESKEY_directory=/usr
+        Env OCF_RESKEY_fsid=105
+        Env OCF_RESKEY_clientspec="*"
+	Env OCF_RESKEY_CRM_meta_timeout=30000
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+        Include set_testenv
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: no 'OCF_RESKEY_fsid'"
+	Include prepare
+	Env OCF_RESKEY_fsid=
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: invalid 'OCF_RESKEY_directory'"
+	Include prepare
+	Env OCF_RESKEY_directory=/no_such
+	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 "stop with no env"
+	Include prepare
+	Env OCF_RESKEY_directory=/no_such
+	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
diff --git a/tools/ocft/iscsi b/tools/ocft/iscsi
new file mode 100644
index 0000000..c1325a1
--- /dev/null
+++ b/tools/ocft/iscsi
@@ -0,0 +1,82 @@
+# iscsi
+
+CONFIG
+	Agent iscsi
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage open-iscsi
+	InstallPackage iscsitarget
+	HangTimeout 20
+
+VARIABLE
+	OCFT_disk=/var/run/resource-agents/ocft-iscsi
+	OCFT_target="iqn.2011-03.ocft.localhost:disk0"
+	OCFT_portal="127.0.0.1:3260"
+
+SETUP-AGENT
+	dd if=/dev/zero of=$OCFT_disk bs=1024k count=1 2>/dev/null
+	echo Target $OCFT_target >> /etc/ietd.conf
+	echo "        Lun 0 Path=$OCFT_disk,Type=fileio" >> /etc/ietd.conf
+	/etc/init.d/iscsitarget start
+	/etc/init.d/open-iscsi start
+	/etc/init.d/iscsitarget restart
+
+CLEANUP-AGENT
+	rm -f $OCFT_disk
+	sed -i "/^Target $OCFT_target/,+1d" /etc/ietd.conf
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_portal=$OCFT_portal
+	Env OCF_RESKEY_target=$OCFT_target
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: invalid 'OCF_RESKEY_portal'"
+	Include prepare
+	Unenv OCF_RESKEY_portal
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: unset 'OCF_RESKEY_target'"
+	Include prepare
+	Unenv OCF_RESKEY_target
+	AgentRun start OCF_ERR_CONFIGURED
+
+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 "monitor when running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor when not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
+
diff --git a/tools/ocft/jboss b/tools/ocft/jboss
new file mode 100644
index 0000000..bc99d8f
--- /dev/null
+++ b/tools/ocft/jboss
@@ -0,0 +1,83 @@
+# jboss
+#
+# NOTE: Clean up $jboss_home/standalone/log before running this test
+#       otherwise creating the pid/log files may fail
+#       in the test case with a different user.
+
+CONFIG
+	Agent jboss
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	HangTimeout 120
+
+# Note : Change setting by a version of JBoss.
+#
+VARIABLE
+	# JBoss5 Environment require
+#	jboss_version=5
+#	jboss_home=/opt/jboss5/current
+#	java_home=/usr/lib/jvm/java-1.6.0-openjdk.x86_64
+#	user=jboss5
+	# JBoss6 Environment require
+	jboss_version=6
+	jboss_home=/opt/jboss6/current
+	java_home=/usr/lib/jvm/java-1.7.0-openjdk.x86_64
+	user=jboss6
+
+CASE-BLOCK required_args_jboss
+	Env OCF_RESKEY_jboss_home=${jboss_home}
+	Env OCF_RESKEY_java_home=${java_home}
+	Env OCF_RESKEY_jboss_version=${jboss_version}
+	Env OCF_RESKEY_user=${user}
+
+CASE-BLOCK args_clear
+	Unenv OCF_RESKEY_jboss_home
+	Unenv OCF_RESKEY_java_home
+	Unenv OCF_RESKEY_jboss_version
+	Unenv OCF_RESKEY_user
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare_jboss
+	Include required_args_jboss
+	Include default_status
+
+# Test CASE
+#
+CASE "normal start jboss require_args (user:user)"
+	Include prepare_jboss
+	AgentRun start OCF_SUCCESS
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop  OCF_SUCCESS
+	AgentRun monitor OCF_NOT_RUNNING
+	Include args_clear
+
+CASE "normal start jboss require_args (user:root)"
+	Include prepare_jboss
+	Unenv OCF_RESKEY_user
+	AgentRun start OCF_SUCCESS
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop  OCF_SUCCESS
+	AgentRun monitor OCF_NOT_RUNNING
+	Include args_clear
+
+CASE "error start jboss no jboss_home"
+	Include prepare_jboss
+	Unenv OCF_RESKEY_jboss_home
+	AgentRun start OCF_ERR_INSTALLED
+	Include args_clear
+
+CASE "error start jboss no java_home"
+	Include prepare_jboss
+	Unenv OCF_RESKEY_java_home
+	AgentRun start OCF_ERR_INSTALLED
+	Include args_clear
+
+CASE "error start jboss no java command"
+	Include prepare_jboss
+	Env OCF_RESKEY_java_home=/var
+	AgentRun start OCF_ERR_INSTALLED
+	AgentRun stop OCF_SUCCESS
+	AgentRun monitor OCF_NOT_RUNNING
+	Include args_clear
+
diff --git a/tools/ocft/mysql b/tools/ocft/mysql
new file mode 100644
index 0000000..27fcb58
--- /dev/null
+++ b/tools/ocft/mysql
@@ -0,0 +1,77 @@
+# mysql
+
+CONFIG
+	Agent mysql
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage mysql
+        HangTimeout 20
+
+SETUP-AGENT
+	/etc/init.d/mysql start
+	/etc/init.d/mysql stop
+
+CASE-BLOCK crm_setting
+	Env OCF_RESKEY_CRM_meta_timeout=15000
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include crm_setting
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: invalid 'OCF_RESKEY_binary'"
+	Include prepare
+	Env OCF_RESKEY_binary=no_such
+	AgentRun start OCF_ERR_INSTALLED
+
+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 "running monitor"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "not running monitor"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "check lib file"
+	Include prepare
+	Bash chmod u-w /var/lib/mysql
+	BashAtExit chmod u+w /var/lib/mysql
+	AgentRun start OCF_ERR_PERM
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
+
+CASE "non-existent user"
+	Include prepare
+	Env OCF_RESKEY_user=no_user
+	AgentRun start OCF_ERR_INSTALLED
+
+CASE "invalid user"
+	Include prepare
+	Env OCF_RESKEY_user=nobody
+	AgentRun start OCF_ERR_PERM
diff --git a/tools/ocft/mysql-proxy b/tools/ocft/mysql-proxy
new file mode 100644
index 0000000..e16d52b
--- /dev/null
+++ b/tools/ocft/mysql-proxy
@@ -0,0 +1,83 @@
+# mysql-proxy
+# by r.bhatia at ipax.at
+#
+# test cases (to implement):
+#
+# * /usr/sbin/ocf-tester -n mp -o binary="/usr/sbin/mysql-proxy" -o defaults_file="" -o parameters="--proxy-skip-profiling" \
+#       -o admin_address="127.0.0.1:4041" -o admin_username="root" -o admin_password="la" -o admin_lua_script="/usr/lib/mysql-proxy/lua/admin.lua" \
+#       -o proxy_backend_addresses="192.168.100.200:42006" -o proxy_address="/var/run/mysqld/mysqld.sock" /usr/lib/ocf/resource.d/heartbeat/mysql-proxy
+#
+# * OCF_CHECK_LEVEL 20 check
+
+CONFIG
+	Agent mysql-proxy
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat/
+	InstallPackage mysql-proxy
+	HangTimeout 20
+
+SETUP-AGENT
+	# nothing
+
+CASE-BLOCK crm_setting
+	Env OCF_RESKEY_CRM_meta_timeout=15000
+	Env OCF_RESKEY_binary=/tmp/mysql-proxy
+	Env OCF_RESKEY_admin_username=root
+	Env OCF_RESKEY_admin_password=test123
+	Env OCF_RESKEY_admin_lua_script=/usr/lib/mysql-proxy/lua/admin.lua
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Bash [ ! -x /tmp/mysql-proxy ] && ln -s `which mysql-proxy` /tmp/mysql-proxy || true
+	Include crm_setting
+
+CASE-BLOCK teardown
+	AgentRun stop
+	BashAtExit rm -f /tmp/mysql-proxy
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+	Include teardown
+
+CASE "check base env: invalid 'OCF_RESKEY_binary'"
+	Include prepare
+	Env OCF_RESKEY_binary=no_such
+	AgentRun start OCF_ERR_INSTALLED
+	BashAtExit rm -f /tmp/mysql-proxy
+
+CASE "normal start"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+	Include teardown
+
+CASE "normal stop"
+	Include prepare
+	AgentRun start
+	AgentRun stop OCF_SUCCESS
+	Include teardown
+
+CASE "double start"
+	Include prepare
+	AgentRun start
+	AgentRun start OCF_SUCCESS
+	Include teardown
+
+CASE "double stop"
+	Include prepare
+	AgentRun stop OCF_SUCCESS
+
+CASE "running monitor"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+	Include teardown
+
+CASE "not running monitor"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
diff --git a/tools/ocft/named b/tools/ocft/named
new file mode 100644
index 0000000..90a4351
--- /dev/null
+++ b/tools/ocft/named
@@ -0,0 +1,69 @@
+#named
+
+# To work properly this test requires that standard bind and bin-utils
+# packages installed.
+
+CONFIG
+	Agent named
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage bind
+	InstallPackage bind-utils
+
+SETUP-AGENT
+	/etc/init.d/named start
+	/etc/init.d/named stop
+
+CASE-BLOCK crm_setting
+        Env OCF_RESKEY_CRM_meta_timeout=15000
+
+CASE-BLOCK default_status
+        AgentRun stop
+
+CASE-BLOCK prepare
+        Include crm_setting
+        Include default_status
+
+CASE "check base env"
+        Include prepare
+        AgentRun start OCF_SUCCESS
+
+CASE "check base env: invalid 'OCF_RESKEY_named'"
+        Include prepare
+        Env OCF_RESKEY_named=no_such
+        AgentRun start OCF_ERR_INSTALLED
+
+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 "running monitor"
+        Include prepare
+        AgentRun start
+        AgentRun monitor OCF_SUCCESS
+
+CASE "not running monitor"
+        Include prepare
+        AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+        Include prepare
+        AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
+
+CASE "non-existent user"
+        Include prepare
+        Env OCF_RESKEY_named_user=no_user
+        AgentRun start OCF_ERR_INSTALLED
diff --git a/tools/ocft/nfsserver b/tools/ocft/nfsserver
new file mode 100644
index 0000000..cd73164
--- /dev/null
+++ b/tools/ocft/nfsserver
@@ -0,0 +1,75 @@
+# nfsserver
+
+CONFIG
+	Agent nfsserver
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage nfs-kernel-server
+	HangTimeout 20
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_nfs_init_script=/etc/init.d/nfsserver
+	Env OCF_RESKEY_nfs_ip=127.0.0.1
+	Env OCF_RESKEY_nfs_shared_infodir=/var/lib/nfs
+	Env OCF_RESKEY_nfs_notify_cmd=/usr/sbin/sm-notify
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: invalid 'OCF_RESKEY_nfs_init_script'"
+	Include prepare
+	Env OCF_RESKEY_nfs_init_script=no_such_script
+	AgentRun start OCF_ERR_INSTALLED
+
+CASE "check base env: unset 'OCF_RESKEY_nfs_ip'"
+	Include prepare
+	Unenv OCF_RESKEY_nfs_ip
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: unset 'OCF_RESKEY_nfs_shared_infodir'"
+	Include prepare
+	Unenv OCF_RESKEY_nfs_shared_infodir
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: invalid 'OCF_RESKEY_nfs_notify_cmd'"
+	Include prepare
+	Env OCF_RESKEY_nfs_notify_cmd=no_such_program
+	AgentRun start OCF_ERR_INSTALLED
+
+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 "monitor with running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor with not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
diff --git a/tools/ocft/ocft.in b/tools/ocft/ocft.in
new file mode 100644
index 0000000..957a8fc
--- /dev/null
+++ b/tools/ocft/ocft.in
@@ -0,0 +1,865 @@
+#!/bin/bash
+
+# Copyright (c) 2010-2013 Novell Inc, John Shi
+#           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.
+
+die()
+{
+  local str
+  str="$1"
+
+  echo "ERROR: $str" >&2
+  exit 1
+}
+
+warn()
+{
+  local str
+  str="$1"
+
+  echo "WARNING: $str" >&2
+}
+
+parse_die()
+{
+  local str
+  str="$1"
+
+  agent_parse_finish
+  die "${agent}: line ${line_num}: ${str}"
+}
+
+# add quotes to string for Here Documents
+add_quotes()
+{
+  local typ str a b
+  typ="$1"
+  str="$2"
+
+  case "$typ" in
+    1) a=\'; b=\";;
+    2) a=\"; b=\';;
+  esac
+
+  echo "$str" | sed "s/$a/$a$b$a$b$a/g; 1 s/^/$a/; $ s/$/$a/"
+}
+
+# split strings
+explode()
+{
+  local str
+  str="$1"
+
+  echo "$str" | awk -F'"' '{
+    if (NF > 0 && NF%2 == 0)
+      exit(1);
+    for (i=1; i<=NF; i++) {
+      if (i%2 == 0)
+        print $i;
+      else {
+        len = split($i, str, /[ \t]+/);
+        for (j=1; j<=len; j++) {
+          sb = sub(/#.*/, "", str[j]);
+          if (str[j] != "")
+            print str[j];
+          if (sb)
+            exit(0);
+        }
+      }
+    }
+  }'
+}
+
+# phase 1: parse the string to 'command' and 'argument collection'.
+line2trunk()
+{
+  trunk[0]="${line%%[[:blank:]]*}"
+  trunk[1]="${line#*[[:blank:]]}"
+}
+
+# phase 2: split the argument collection.
+trunk2branch()
+{
+  local IFS
+
+  # Some of statements need one parameter at least.
+  if [ "$line" = "${trunk[0]}" ]; then
+    parse_die "missing parameter."
+  fi
+
+  IFS=$'\n'
+  branch=($(explode "${trunk[1]}"))
+  if [ $? -ne 0 ]; then
+    parse_die "missing '\"'."
+  fi
+}
+
+preparse_cfg()
+{
+  local agent line trunk branch macro num host
+  agent="$1"
+
+  if [ ! -r "$opt_cfgsdir/$agent" ]; then
+    die "${agent}: configuration file not found."
+  fi
+
+  line_num=0
+  while read -r line; do
+    let line_num++
+    num=" $line_num"
+
+    case "$line" in
+      ""|\#*) continue;;
+    esac
+
+    line2trunk
+    case "${trunk[0]}" in
+      CASE-BLOCK)
+        trunk2branch
+        macro="$CASES_DIR/${agent}_macro.${branch[0]}"
+        continue
+        ;;
+      Include|Include@*)
+        host=$(echo "${trunk[0]}" | awk -F@ '{print $2}')
+        trunk2branch
+        if [ ! -r "$CASES_DIR/${agent}_macro.${branch[0]}" ]; then
+          parse_die "Macro '${branch[0]}' not found."
+        fi
+        if [ -n "$host" ]; then
+          line="$(sed -e 's/^\([^[:blank:]]*\)@[^[:blank:]]*/\1/' -e "s/^[^[:blank:]]*/&@$host/" "$CASES_DIR/${agent}_macro.${branch[0]}")"
+        else
+          line="$(<"$CASES_DIR/${agent}_macro.${branch[0]}")"
+        fi
+        num=
+        ;;
+      *[!A-Z-]*)
+        :
+        ;;
+      *)
+        macro=
+        ;;
+    esac
+
+    if [ -n "$macro" ]; then
+      echo "$line$num" >>"$macro"
+    else
+      echo "$line$num" >>"$CASES_DIR/${agent}_preparse"
+    fi
+  done <"$opt_cfgsdir/$agent"
+}
+
+case_parse_finish()
+{
+  local host
+
+  if [ -n "$sh" ]; then
+    cat >>$sh <<EOF
+if [ -n "\$__OCFT__VERBOSE" ]; then
+  echo
+fi
+# Cleanup and exit
+EOF
+    for host in $hosts; do
+      echo "backbash_stop $host" >>$sh
+    done
+    echo "quit 0" >>$sh
+  fi
+
+  atexit_num=0
+  hosts=
+  sh=
+}
+
+init_cfg_vars()
+{
+  cfg_agent=
+  cfg_agent_root=
+  cfg_install_package=()
+  cfg_hang_timeout=20
+}
+
+agent_parse_finish()
+{
+  local suf
+
+  for suf in preparse setup cleanup var hosts; do
+    rm -f $CASES_DIR/${agent}_$suf
+  done
+  rm -f $CASES_DIR/${agent}_macro.*
+  init_cfg_vars
+}
+
+need_make()
+{
+  local src_time obj_time
+
+  if [ ! -f "$CASES_DIR/0_${agent}.sh" ]; then
+    return 0
+  fi
+
+  src_time=$(stat -c '%Y' "$opt_cfgsdir/$agent")
+  obj_time=$(stat -c '%Y' "$CASES_DIR/0_${agent}.sh")
+
+  test $src_time -ge $obj_time
+}
+
+parse_cfg()
+{
+  local agents i line stat sh trunk branch atexit_num host hosts
+
+  if [ $# -eq 0 ]; then
+    agents=($opt_cfgsdir/*)
+  else
+    agents=("$@")
+  fi
+
+  for agent in "${agents[@]}"; do
+    agent="$(basename "$agent")"
+
+    if ! need_make; then
+      continue
+    fi
+
+    agent_obj_clean $agent
+    agent_parse_finish
+
+    i=0
+
+    echo "Making '$agent': "
+    preparse_cfg "$agent"
+    while read -r line; do
+      line_num="${line##* }"
+      line="${line% *}"
+      line2trunk
+
+      # state switch
+      case "${trunk[0]}" in
+        CONFIG)
+          case_parse_finish
+          stat=1
+          continue
+          ;;
+        VARIABLE)
+          case_parse_finish
+          stat=2
+          continue
+          ;;
+	SETUP-AGENT)
+          case_parse_finish
+          stat=3
+          continue
+          ;;
+	CLEANUP-AGENT)
+          case_parse_finish
+          stat=4
+          continue
+          ;;
+        CASE)
+          case_parse_finish
+          trunk2branch
+          echo "    - case ${i}: ${branch[0]}"
+          sh="$CASES_DIR/${i}_${agent}.sh"
+          cat >$sh <<EOF
+#!/bin/bash
+
+# Agent:   $cfg_agent
+# Summary: ${branch[0]}
+
+. $OCFT_DIR/caselib || {
+  echo "ERROR: '$OCFT_DIR/caselib' not found."
+  exit 2
+}
+
+$(test -r $CASES_DIR/${agent}_var && cat $CASES_DIR/${agent}_var)
+
+__OCFT__MYROOT="$cfg_agent_root"
+
+$(test -n "$cfg_install_package" && echo "agent_install ${cfg_install_package[@]}")
+
+if [ -n "\$__OCFT__VERBOSE" ]; then
+  echo -e $(add_quotes 1 "Starting '\\033[33m${agent}\\033[0m' case $i '\\033[33m${branch[0]}\\033[0m':")
+else
+  echo -n "${agent}: ${branch[0]} - "
+fi
+EOF
+          chmod a+x $sh
+
+          let i++
+          stat=5
+          continue
+          ;;
+      esac
+
+      case "$stat" in
+        1)
+          case "${trunk[0]}" in
+            Agent)
+              trunk2branch
+              cfg_agent="${branch[0]}"
+              ;;
+            AgentRoot)
+              trunk2branch
+              cfg_agent_root="${branch[0]}"
+              ;;
+            InstallPackage)
+              trunk2branch
+              cfg_install_package=(${cfg_install_package[@]} ${branch[@]})
+              ;;
+            HangTimeout)
+              trunk2branch
+              if ! echo "${branch[0]}" | grep -qxE '[0-9]+'; then
+                parse_die "numeric argument required."
+              fi
+              cfg_hang_timeout="${branch[0]}"
+              ;;
+            *)
+              parse_die "unimplemented statement: ${trunk[0]}"
+              ;;
+          esac
+          ;;
+        2)
+          if echo "$line" | grep -q '^__OCFT__'; then
+            parse_die "reserved key word '__OCFT__'."
+          fi
+          echo "declare $line" >>$CASES_DIR/${agent}_var
+          ;;
+        3)
+          echo "$line" >>$CASES_DIR/${agent}_setup
+          ;;
+        4)
+          echo "$line" >>$CASES_DIR/${agent}_cleanup
+          ;;
+        5)
+          host=$(echo ${trunk[0]} | awk -F@ '{print $2}')
+          if [ -n "$host" ]; then
+            if ! echo "$hosts" | grep -q "$host"; then
+              echo "$host" >>$CASES_DIR/${agent}_hosts
+              hosts=$hosts$'\n'$host
+              cat >>$sh <<EOF
+# Initialize remote shell
+backbash_start $host
+backbash $host <<CMD
+__OCFT__VERBOSE=\$__OCFT__VERBOSE
+CMD
+backbash $host <$OCFT_DIR/caselib
+backbash $host <<'CMD'
+$(test -r $CASES_DIR/${agent}_var && cat $CASES_DIR/${agent}_var)
+
+__OCFT__MYROOT="$cfg_agent_root"
+__OCFT__showhost="${host}: "
+
+$(test -n "$cfg_install_package" && echo "agent_install ${cfg_install_package[@]}")
+CMD
+EOF
+            fi
+          fi
+
+          echo "
+# CASE statement: $line" >>$sh
+
+          if [ -n "$host" ]; then
+            echo "backbash $host <<'CMD'" >>$sh
+          fi
+
+          case "${trunk[0]}" in
+            Env|Env@*)
+              cat >>$sh <<EOF
+if [ -n "\$__OCFT__VERBOSE" ]; then
+  echo $(add_quotes 2 "    \${__OCFT__showhost}Setting agent environment:    export ${trunk[1]}")
+fi
+export ${trunk[1]}
+check_success \$? $(add_quotes 1 "export ${trunk[1]}")
+EOF
+              ;;
+            Unenv|Unenv@*)
+              cat >>$sh <<EOF
+if [ -n "\$__OCFT__VERBOSE" ]; then
+  echo $(add_quotes 2 "    \${__OCFT__showhost}Removing agent environment:   unset ${trunk[1]}")
+fi
+unset ${trunk[1]}
+check_success \$? $(add_quotes 1 "unset ${trunk[1]}")
+EOF
+              ;;
+            AgentRun|AgentRun@*)
+              trunk2branch
+              if [ -z "${branch[1]}" ]; then
+                if [ "${branch[0]}" = "start" ]; then
+                  cat >>$sh <<EOF
+agent_run $(add_quotes 1 "$cfg_agent") monitor $cfg_hang_timeout
+__OCFT__rc=\$?
+
+if [ \$__OCFT__rc -eq \$OCF_SUCCESS -o \$__OCFT__rc -eq \$OCF_RUNNING_MASTER ]; then
+  : #The status I want, so I can do nothing.
+elif [ \$__OCFT__rc -eq \$OCF_NOT_RUNNING ]; then
+  if [ -n "\$__OCFT__VERBOSE" ]; then
+    echo $(add_quotes 2 "    \${__OCFT__showhost}Running agent:                ./$cfg_agent ${branch[0]}")
+  fi
+  agent_run $(add_quotes 1 "$cfg_agent") start $cfg_hang_timeout
+  check_success \$? $(add_quotes 1 "./$cfg_agent ${branch[0]}")
+else
+  check_success \$__OCFT__rc $(add_quotes 1 "./$cfg_agent monitor")
+fi
+EOF
+                elif [ "${branch[0]}" = "stop" ]; then
+                  cat >>$sh <<EOF
+agent_run $(add_quotes 1 "$cfg_agent") monitor $cfg_hang_timeout
+__OCFT__rc=\$?
+
+if [ \$__OCFT__rc -eq \$OCF_NOT_RUNNING ]; then
+  : #The status I want, so I can do nothing.
+elif [ \$__OCFT__rc -eq \$OCF_SUCCESS -o \$__OCFT__rc -eq \$OCF_RUNNING_MASTER ]; then
+  if [ -n "\$__OCFT__VERBOSE" ]; then
+    echo $(add_quotes 2 "    \${__OCFT__showhost}Running agent:                ./$cfg_agent ${branch[0]}")
+  fi
+  agent_run $(add_quotes 1 "$cfg_agent") stop $cfg_hang_timeout
+  check_success \$? $(add_quotes 1 "./$cfg_agent ${branch[0]}")
+else
+  check_success \$__OCFT__rc $(add_quotes 1 "./$cfg_agent monitor")
+fi
+EOF
+                elif [ "${branch[0]}" = "monitor" ]; then
+                  cat >>$sh <<EOF
+if [ -n "\$__OCFT__VERBOSE" ]; then
+  echo $(add_quotes 2 "    \${__OCFT__showhost}Running agent:                ./$cfg_agent ${branch[0]}")
+fi
+agent_run $(add_quotes 1 "$cfg_agent") $(add_quotes 1 "${branch[0]}") $cfg_hang_timeout
+EOF
+                else
+                  cat >>$sh <<EOF
+if [ -n "\$__OCFT__VERBOSE" ]; then
+  echo $(add_quotes 2 "    \${__OCFT__showhost}Running agent:                ./$cfg_agent ${branch[0]}")
+fi
+agent_run $(add_quotes 1 "$cfg_agent") $(add_quotes 1 "${branch[0]}") $cfg_hang_timeout
+check_success \$? $(add_quotes 1 "./$cfg_agent ${branch[0]}")
+EOF
+                fi
+              else
+                cat >>$sh <<EOF
+test -n $(add_quotes 2 "\$${branch[1]}")
+check_success \$? $(add_quotes 1 "test -n \"\$${branch[1]}\"")
+if [ -n "\$__OCFT__VERBOSE" ]; then
+  echo $(add_quotes 2 "    \${__OCFT__showhost}Running agent:                ./$cfg_agent ${branch[0]}")
+fi
+agent_run $(add_quotes 1 "$cfg_agent") $(add_quotes 1 "${branch[0]}") $cfg_hang_timeout
+__OCFT__ret=\$?
+if [ -n "\$__OCFT__VERBOSE" ]; then
+  echo -n "    \${__OCFT__showhost}Checking return value:"
+fi
+if [ -n "\${__OCFT__retval[__OCFT__ret]}" ]; then
+  __OCFT__retstr="\${__OCFT__retval[__OCFT__ret]}"
+else
+  __OCFT__retstr=\$__OCFT__ret
+fi
+if [ \$__OCFT__ret -eq \$${branch[1]} ]; then
+  if [ -n "\$__OCFT__VERBOSE" ]; then
+    echo -e $(add_quotes 2 "        \\033[32mOK\\033[0m. The return value '\\033[34m\$__OCFT__retstr\\033[0m' == '\\033[34m${branch[1]}\\033[0m'")
+  else
+    echo -e "\\033[32mOK\\033[0m."
+  fi
+else
+  if [ -n "\$__OCFT__VERBOSE" ]; then
+    echo -en $(add_quotes 2 "        \\033[31mFAILED\\033[0m. The return value '\\033[34m\$__OCFT__retstr\\033[0m' != '\\033[34m${branch[1]}\\033[0m'. ")
+  else
+    echo -en "\\033[31mFAILED\\033[0m. Agent returns unexpected value: '\$__OCFT__retstr'. "
+  fi
+  echo "See details below:"
+  cat /tmp/.ocft_runlog
+  echo
+  quit 1
+fi
+EOF
+              fi
+              ;;
+            Bash|Bash@*)
+              cat >>$sh <<EOF
+if [ -n "\$__OCFT__VERBOSE" ]; then
+  echo $(add_quotes 2 "    \${__OCFT__showhost}Setting system environment:   ${trunk[1]}")
+fi
+${trunk[1]}
+check_success \$? $(add_quotes 1 "${trunk[1]}")
+EOF
+              ;;
+            BashAtExit|BashAtExit@*)
+              let atexit_num++
+              cat >>$sh <<EOF
+atexit${atexit_num}()
+{
+  if [ -n "\$__OCFT__VERBOSE" ]; then
+    echo $(add_quotes 2 "    \${__OCFT__showhost}Setting system environment:   ${trunk[1]}")
+  fi
+  ${trunk[1]}
+}
+let __OCFT__atexit_num++
+EOF
+              ;;
+            *)
+              parse_die "unimplemented statement: ${trunk[0]}"
+              ;;
+          esac
+          if [ -n "$host" ]; then
+            echo 'CMD' >>$sh
+          fi
+          ;;
+        *)
+          parse_die "unimplemented statement: ${trunk[0]}"
+          ;;
+      esac
+    done <$CASES_DIR/${agent}_preparse
+
+    if [ -r "$CASES_DIR/${agent}_setup" ]; then
+      cat >$CASES_DIR/setup_${agent}.sh <<EOF
+#!/bin/bash
+
+# Agent:   $cfg_agent
+# Summary: SETUP before test
+
+echo "Initializing '$cfg_agent' ..."
+
+. $OCFT_DIR/caselib || {
+  echo "ERROR: '$OCFT_DIR/caselib' not found."
+  exit 2
+}
+
+$(test -r "$CASES_DIR/${agent}_var" && cat $CASES_DIR/${agent}_var)
+$(test -n "$cfg_install_package" && echo "agent_install ${cfg_install_package[@]}")
+
+EOF
+      for host in $(test -r $CASES_DIR/${agent}_hosts && cat $CASES_DIR/${agent}_hosts); do
+        cat >>$CASES_DIR/setup_${agent}.sh <<EOF
+# Initialize remote shell
+backbash_start $host
+backbash $host <<CMD
+__OCFT__VERBOSE=\$__OCFT__VERBOSE
+CMD
+backbash $host <$OCFT_DIR/caselib
+backbash $host <<'CMD'
+$(test -r "$CASES_DIR/${agent}_var" && cat $CASES_DIR/${agent}_var)
+
+__OCFT__MYROOT="$cfg_agent_root"
+__OCFT__showhost="${host}: "
+
+$(test -n "$cfg_install_package" && echo "agent_install ${cfg_install_package[@]}")
+
+$(cat $CASES_DIR/${agent}_setup)
+check_success \$? "SETUP-AGENT"
+CMD
+backbash_stop $host 
+EOF
+      done
+      cat >>$CASES_DIR/setup_${agent}.sh <<EOF
+$(cat $CASES_DIR/${agent}_setup)
+check_success \$? "SETUP-AGENT"
+
+echo "Done."
+echo
+quit 0
+EOF
+      chmod a+x $CASES_DIR/setup_${agent}.sh
+    fi
+
+    if [ -r "$CASES_DIR/${agent}_cleanup" ]; then
+      cat >$CASES_DIR/cleanup_${agent}.sh <<EOF
+#!/bin/bash
+
+# Agent:   $cfg_agent
+# Summary: CLEANUP after test
+
+echo "Cleaning '$cfg_agent' ..."
+
+. $OCFT_DIR/caselib || {
+  echo "ERROR: '$OCFT_DIR/caselib' not found."
+  exit 2
+}
+
+$(test -r "$CASES_DIR/${agent}_var" && cat $CASES_DIR/${agent}_var)
+$(test -n "$cfg_install_package" && echo "agent_install ${cfg_install_package[@]}")
+
+$(cat $CASES_DIR/${agent}_cleanup)
+check_success \$? "CLEANUP-AGENT"
+
+EOF
+      for host in $(test -r $CASES_DIR/${agent}_hosts && cat $CASES_DIR/${agent}_hosts); do
+        cat >>$CASES_DIR/cleanup_${agent}.sh <<EOF
+# Initialize remote shell
+backbash_start $host
+backbash $host <<CMD
+__OCFT__VERBOSE=\$__OCFT__VERBOSE
+CMD
+backbash $host <$OCFT_DIR/caselib
+backbash $host <<'CMD'
+$(test -r "$CASES_DIR/${agent}_var" && cat $CASES_DIR/${agent}_var)
+
+__OCFT__MYROOT="$cfg_agent_root"
+__OCFT__showhost="${host}: "
+
+$(test -n "$cfg_install_package" && echo "agent_install ${cfg_install_package[@]}")
+
+$(cat $CASES_DIR/${agent}_cleanup)
+check_success \$? "CLEANUP-AGENT"
+CMD
+backbash_stop $host 
+EOF
+      done
+      cat >>$CASES_DIR/cleanup_${agent}.sh <<EOF
+echo "Done."
+echo
+quit 0
+EOF
+      chmod a+x $CASES_DIR/cleanup_${agent}.sh
+    fi
+    case_parse_finish
+    agent_parse_finish
+
+  done
+}
+
+start_test()
+{
+  local sh shs testsh agents line ret
+
+  if ! cd $CASES_DIR >/dev/null 2>&1; then
+    die "cases directory not found."
+  fi
+
+  if [ ! -d logs ]; then
+    mkdir logs
+  fi
+
+  export __OCFT__VERBOSE=$opt_verbose
+
+  if [ $# -eq 0 ]; then
+    agents=($(ls -1 *.sh 2>/dev/null | sed 's/.*_\([^_]*\)\.sh$/\1/' | sort | uniq))
+  else
+    agents=("$@")
+  fi
+
+  for shs in "${agents[@]}"; do
+    if [ -z "$opt_incremental" ]; then
+      testsh="setup_${shs}.sh
+              $(ls -1 [0-9]*_${shs}.sh 2>/dev/null | sort -n)
+              cleanup_${shs}.sh"
+    else
+      testsh="setup_${shs}.sh
+              $(ls -1 [0-9]*_${shs}.retest 2>/dev/null | sed 's/retest$/sh/' | sort -n)
+              cleanup_${shs}.sh"
+    fi
+
+    for sh in $testsh; do
+      if [ -r "$sh" ]; then
+        ./$sh
+        ret=$?
+
+        case "$sh" in
+          setup*)
+              if [ $ret -ne 0 ]; then
+                warn "SETUP failed, break all tests of '$shs'."
+                break
+              fi
+              ;;
+          cleanup*)
+              if [ $ret -ne 0 ]; then
+                warn "CLEANUP failed."
+              fi
+              ;;
+          [0-9]*)
+              case $ret in
+                3) die "core function failed, break all tests." ;;
+                2) warn "core function failed, break all tests of '$shs'."; break ;;
+                1) touch ${sh%.*}.retest ;;
+                0) rm -f ${sh%.*}.retest ;;
+              esac
+              ;;
+        esac
+      fi
+    done 2>&1 | while read -r line; do
+      echo "$line"
+      echo "$(date '+%F %T'): $line" | cat -A |
+      sed -r 's/\^\[\[[0-9]+m|\^I|.$//g' >>logs/$shs.log
+    done
+  done
+}
+
+agent_clean()
+{
+  local typ ra
+  typ=$1
+  
+  shift
+
+  if [ $# -eq 0 ]; then
+    rm -f $CASES_DIR/*.$typ
+  else
+    for ra in "$@"; do
+      rm -f $CASES_DIR/*_${ra}.$typ
+    done
+  fi
+}
+
+agent_retest_clean()
+{
+  agent_clean retest "$@"
+}
+
+agent_obj_clean()
+{
+  agent_clean sh "$@"
+}
+
+usage()
+{
+  cat <<EOF
+$0 ACTION [OPTION] [agent1 [agent2] [...]]
+ACTIONs include:
+     make [-d dir]   Generate the testing shell scripts.
+                       -d  The directory that contains 
+		           configuration of cases.
+     test [-v|-i]    Execute the testing shell scripts.
+                       -v  Verbose output mode.
+                       -i  Incremental mode, skip case 
+                           which succeeded. If cleaning 
+                           the status of incremental mode
+                           is needed, try to '$0 clean RA_NAME'.
+     clean           Delete the testing shell scripts.
+     help [-v]       Show this help and exit.
+                       -v  Show HOWTO and exit.
+Version 0.44
+See '$OCFT_DIR/README' for detail.
+EOF
+}
+
+howto()
+{
+  cat <<EOF
+HOW TO USE THIS TOOL
+
+  - Ocft is a testing tool for resource agents. Instead of the policy of HA,
+    it mainly concerns whether resource agents run correct locally. It can 
+    design types of complicated environments to test the reliability of 
+    resource agents. Precisely, it is to display whether resource agents can 
+    return to correct or expected value. The advantage of the tool provides 
+    us with competence to design conditions which can be recorded or reproduced. 
+    Hence it is useful to debuggers.
+
+* Components
+    ** Test case generator (/usr/sbin/ocft)
+      - Turning configuration files of test case to executable scripts.
+
+    ** Configuration file  ($CONFIGS_DIR/)
+      - Every configuration file directs only one resource agent and share the same 
+        name with resource agent but contains more test cases.
+
+    ** The testing script  ($CASES_DIR/)
+      - After the generator reads configuration files and generates many testing 
+        scripts and the script is underway, the test begins.
+
+* How to customize the environment of testing
+  - Ocft designs the running conditions through two ways, one is changing the 
+    environment variables of resource agents (it is the interface left by OCF itself), 
+    the other is modifying the OS environment of resource agents, such as altering 
+    the permission of some key file or IP address of the machine.
+
+* How to test
+  - Firstly, you need to sketch the all complex and uncommon environments against 
+    a certain resource agent and keep in mind what consequences may be caused by 
+    these uncommon environments. 
+    Secondly, write the designed conditions and foreknown consequences into 
+    configuration files, and then run the generator to translate the test case to 
+    executable scripts. 
+    Finally, you need running these scripts to observe the output and learn 
+    the running status of each test case, which will compares the predicated result 
+    with the actual one. If they differ, you will be able to find the bugs of the 
+    resource agent.
+  - All of the output with test will be recorded into the log files, you can find them
+    in $CASES_DIR/logs.
+EOF
+}
+
+
+export LANG=C
+
+# system variable
+OCFT_DIR=@datadir@/@PACKAGE_NAME@/ocft
+CONFIGS_DIR=@datadir@/@PACKAGE_NAME@/ocft/configs
+CASES_DIR=/var/lib/@PACKAGE_NAME@/ocft/cases
+
+# global variable
+agent=
+line_num=
+
+# default configuration
+init_cfg_vars
+
+# default option
+opt_verbose=
+opt_incremental=
+opt_cfgsdir=$CONFIGS_DIR
+
+command="$1"
+shift
+
+case "$command" in
+  make)
+    if [ "$1" = "-d" ]; then
+      if [ ! -d "$2" ]; then
+        usage
+        exit 1
+      fi
+      opt_cfgsdir="$2"
+      shift 2
+    fi
+    if [ ! -d "$CASES_DIR" ]; then
+      mkdir -p "$CASES_DIR" || die "Can not create directory: ${CASES_DIR}."
+    fi
+    parse_cfg "$@"
+    ;;
+  test)
+    for v in 1 2; do
+      case "$1" in
+        -v)
+          opt_verbose=1
+          shift
+          ;;
+        -i)
+          opt_incremental=1
+          shift
+          ;;
+      esac
+    done
+    start_test "$@"
+    ;;
+  clean)
+    agent_obj_clean "$@"
+    agent_retest_clean "$@"
+    ;;
+  help)
+    if [ "$1" = "-v" ]; then
+      howto
+    else
+      usage
+    fi
+    exit 0
+    ;;
+  *)
+    usage
+    exit 1
+    ;;
+esac
diff --git a/tools/ocft/oracle b/tools/ocft/oracle
new file mode 100644
index 0000000..6f145c7
--- /dev/null
+++ b/tools/ocft/oracle
@@ -0,0 +1,81 @@
+# oracle
+# (based on db2)
+#
+# Created on an SLE11SP2 running oracle 11g
+# database sid is orcl
+# adapt this in set_testenv below
+# TODO: need oracle expert to break it, then test it
+#
+
+CONFIG
+	Agent oracle
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+        HangTimeout 40
+
+SETUP-AGENT
+        # nothing
+
+CASE-BLOCK set_testenv
+        Env OCFT_sid=orcl
+
+CASE-BLOCK crm_setting
+        Env OCF_RESKEY_sid=$OCFT_sid
+	Env 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: no 'OCF_RESKEY_sid'"
+	Include prepare
+	Env OCF_RESKEY_sid=
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: invalid 'OCF_RESKEY_home'"
+	Include prepare
+	Env OCF_RESKEY_home=/no_such
+	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 "try different ipcrm method"
+        Include prepare
+        Env OCF_RESKEY_ipcrm=none
+        AgentRun start OCF_SUCCESS
diff --git a/tools/ocft/pgsql b/tools/ocft/pgsql
new file mode 100644
index 0000000..9944b09
--- /dev/null
+++ b/tools/ocft/pgsql
@@ -0,0 +1,71 @@
+# pgsql
+
+CONFIG
+	Agent pgsql
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage postgresql-server
+        HangTimeout 20
+
+SETUP-AGENT
+	/etc/init.d/postgresql start
+	/etc/init.d/postgresql stop
+
+CASE-BLOCK crm_setting
+        Env OCF_RESKEY_CRM_meta_timeout=15000
+
+CASE-BLOCK default_status
+        AgentRun stop
+
+CASE-BLOCK prepare
+        Include crm_setting
+        Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: invalid 'OCF_RESKEY_pgctl'"
+	Include prepare
+	Env OCF_RESKEY_pgctl=no_such
+	AgentRun start OCF_ERR_INSTALLED
+
+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 "running monitor"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "not running monitor"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
+
+CASE "non-existent user"
+	Include prepare
+	Env OCF_RESKEY_pgdba=no_user
+	AgentRun start OCF_ERR_INSTALLED
+
+CASE "invalid user"
+	Include prepare
+	Env OCF_RESKEY_pgdba=nobody
+	AgentRun start OCF_ERR_PERM
diff --git a/tools/ocft/portblock b/tools/ocft/portblock
new file mode 100644
index 0000000..3475c63
--- /dev/null
+++ b/tools/ocft/portblock
@@ -0,0 +1,69 @@
+# portblock
+
+CONFIG
+	Agent portblock
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage iptables
+	HangTimeout 15
+
+CASE-BLOCK required_args
+	Env OCF_RESKEY_protocol=tcp
+	Env OCF_RESKEY_portno=80
+	Env OCF_RESKEY_action=block
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include required_args
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: unset 'OCF_RESKEY_protocol'"
+	Include prepare
+	Unenv OCF_RESKEY_protocol
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: unset 'OCF_RESKEY_portno'"
+	Include prepare
+	Unenv OCF_RESKEY_portno
+	AgentRun start OCF_ERR_CONFIGURED
+
+CASE "check base env: unset 'OCF_RESKEY_action'"
+	Include prepare
+	Unenv OCF_RESKEY_action
+	AgentRun start OCF_ERR_CONFIGURED
+
+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 "monitor with running"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "monitor with not running"
+	Include prepare
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
diff --git a/tools/ocft/postfix b/tools/ocft/postfix
new file mode 100644
index 0000000..f17e968
--- /dev/null
+++ b/tools/ocft/postfix
@@ -0,0 +1,102 @@
+# postfix
+# by r.bhatia at ipax.at
+# 
+# test cases (to implement):
+# 
+# * /usr/sbin/ocf-tester -n post1 /usr/lib/ocf/resource.d/heartbeat/postfix; echo $? -> DONE
+# * /usr/sbin/ocf-tester -n post2 -o binary="/usr/sbin/postfix" \
+#       -o config_dir="" /usr/lib/ocf/resource.d/heartbeat/postfix; echo $? -> DONE
+# * /usr/sbin/ocf-tester -n post3 -o binary="/usr/sbin/postfix" \
+#       -o config_dir="/etc/postfix" /usr/lib/ocf/resource.d/heartbeat/postfix; echo $? -> DONE
+# * /usr/sbin/ocf-tester -n post4 -o binary="/usr/sbin/postfix" \
+#       -o config_dir="/root/postfix/" /usr/lib/ocf/resource.d/heartbeat/postfix; echo $?
+
+CONFIG
+	Agent postfix
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	InstallPackage postfix
+	HangTimeout 20
+
+SETUP-AGENT
+	# nothing
+
+CASE-BLOCK crm_setting
+	Env OCF_RESKEY_CRM_meta_timeout=15000
+	Env OCF_RESKEY_CRM_meta_interval=10000
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare
+	Include crm_setting
+	Include default_status
+
+CASE "check base env"
+	Include prepare
+	AgentRun start OCF_SUCCESS
+
+CASE "check base env: invalid 'OCF_RESKEY_binary'"
+	Include prepare
+	Env OCF_RESKEY_binary=no_such
+	AgentRun start OCF_ERR_INSTALLED
+
+CASE "check base env: invalid 'OCF_RESKEY_config_dir'"
+	Include prepare
+	Env OCF_RESKEY_config_dir=no_such
+	AgentRun start OCF_ERR_INSTALLED
+
+CASE "check base env: 'OCF_RESKEY_binary'"
+	Include prepare
+	Env OCF_RESKEY_binary=/usr/sbin/postfix
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "check base env: 'OCF_RESKEY_config_dir' without trailing slash"
+	Include prepare
+	Env OCF_RESKEY_config_dir="/etc/postfix"
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "check base env: 'OCF_RESKEY_config_dir' with trailing slash"
+	Include prepare
+	Env OCF_RESKEY_config_dir="/etc/postfix/"
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+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 "monitor a running resource"
+	Include prepare
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "(initial) probe a stopped resource"
+	Include prepare
+	Env OCF_RESKEY_CRM_meta_interval=0
+	AgentRun monitor OCF_NOT_RUNNING
+
+CASE "(re-)probe a running resource"
+	Include prepare
+	Env OCF_RESKEY_CRM_meta_interval=0
+	AgentRun start
+	AgentRun monitor OCF_SUCCESS
+
+CASE "unimplemented command"
+	Include prepare
+	AgentRun no_cmd OCF_ERR_UNIMPLEMENTED
diff --git a/tools/ocft/tomcat b/tools/ocft/tomcat
new file mode 100644
index 0000000..56adf86
--- /dev/null
+++ b/tools/ocft/tomcat
@@ -0,0 +1,73 @@
+# tomcat
+#
+# NOTE: Clean up $catalina_home/logs before running this test
+#       otherwise creating the pid/log files may fail
+#       in the test case with a different user.
+
+CONFIG
+	Agent tomcat
+	AgentRoot /usr/lib/ocf/resource.d/heartbeat
+	HangTimeout 120
+
+VARIABLE
+	# Adjust accrding to your configuration
+	catalina_home=/opt/tomcat7
+	tomcat_user=tomcat7
+	java_home=/usr/lib/jvm/java-1.6.0-openjdk.x86_64
+
+CASE-BLOCK required_args_tomcat
+	Env OCF_RESKEY_catalina_home=${catalina_home}
+	Env OCF_RESKEY_tomcat_user=${tomcat_user}
+	Env OCF_RESKEY_java_home=${java_home}
+
+CASE-BLOCK args_clear
+	Unenv OCF_RESKEY_catalina_home
+	Unenv OCF_RESKEY_tomcat_user
+	Unenv OCF_RESKEY_java_home
+
+CASE-BLOCK default_status
+	AgentRun stop
+
+CASE-BLOCK prepare_tomcat
+	Include required_args_tomcat
+	Include default_status
+
+# Test CASE
+#
+CASE "normal start tomcat require_args (user:user)"
+	Include prepare_tomcat
+	AgentRun start OCF_SUCCESS
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop  OCF_SUCCESS
+	AgentRun monitor OCF_NOT_RUNNING
+	Include args_clear
+
+CASE "normal start tomcat require_args (user:root)"
+	Include prepare_tomcat
+	Unenv OCF_RESKEY_tomcat_user
+	AgentRun start OCF_SUCCESS
+	AgentRun monitor OCF_SUCCESS
+	AgentRun stop  OCF_SUCCESS
+	AgentRun monitor OCF_NOT_RUNNING
+	Include args_clear
+
+CASE "error start tomcat no catalina_home"
+	Include prepare_tomcat
+	Unenv OCF_RESKEY_catalina_home
+	AgentRun start OCF_ERR_INSTALLED
+	Include args_clear
+
+CASE "error start tomcat no java_home"
+	Include prepare_tomcat
+	Unenv OCF_RESKEY_java_home
+	AgentRun start OCF_ERR_INSTALLED
+	Include args_clear
+
+CASE "error start tomcat no java command"
+	Include prepare_tomcat
+	Env OCF_RESKEY_java_home=/var
+	AgentRun start OCF_ERR_INSTALLED
+	AgentRun stop OCF_SUCCESS
+	AgentRun monitor OCF_NOT_RUNNING
+	Include args_clear
+
diff --git a/tools/send_arp.libnet.c b/tools/send_arp.libnet.c
new file mode 100644
index 0000000..12fe7f1
--- /dev/null
+++ b/tools/send_arp.libnet.c
@@ -0,0 +1,758 @@
+/* 
+ * send_arp
+ * 
+ * This program sends out one ARP packet with source/target IP and Ethernet
+ * hardware addresses suuplied by the user.  It uses the libnet libary from
+ * Packet Factory (http://www.packetfactory.net/libnet/ ). It has been tested
+ * on Linux, FreeBSD, and on Solaris.
+ * 
+ * This inspired by the sample application supplied by Packet Factory.
+
+ * Matt Soffen
+
+ * Copyright (C) 2001 Matt Soffen <matt at soffen.com>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* Needs to be defined before any other includes, otherwise some system
+ * headers do not behave as expected! Major black magic... */
+#undef _GNU_SOURCE  /* in case it was defined on the command line */
+#define _GNU_SOURCE
+
+#include <config.h>
+#include <sys/param.h>
+
+#define USE_GNU
+#if defined(ANSI_ONLY) && !defined(inline)
+#	define inline	/* nothing */
+#endif
+
+#include <limits.h>
+#include <libnet.h>
+#include <libgen.h>
+#include <clplumbing/timers.h>
+#include <clplumbing/cl_signal.h>
+#include <clplumbing/cl_log.h>
+
+#ifdef HAVE_LIBNET_1_0_API
+#	define	LTYPE	struct libnet_link_int
+	static u_char *mk_packet(u_int32_t ip, u_char *device, u_char *macaddr, u_char *broadcast, u_char *netmask, u_short arptype);
+	static int send_arp(struct libnet_link_int *l, u_char *device, u_char *buf);
+#endif
+#ifdef HAVE_LIBNET_1_1_API
+#	define	LTYPE	libnet_t
+	static libnet_t *mk_packet(libnet_t* lntag, u_int32_t ip, u_char *device, u_char macaddr[6], u_char *broadcast, u_char *netmask, u_short arptype);
+	int send_arp(libnet_t* lntag);
+#endif
+
+#define PIDDIR       HA_VARRUNDIR "/" PACKAGE
+#define PIDFILE_BASE PIDDIR "/send_arp-"
+
+static char print_usage[]={
+"send_arp: sends out custom ARP packet.\n"
+"  usage: send_arp [-i repeatinterval-ms] [-r repeatcount] [-p pidfile] \\\n"
+"              device src_ip_addr src_hw_addr broadcast_ip_addr netmask\n"
+"\n"
+"  where:\n"
+"    repeatinterval-ms: timing, in milliseconds of sending arp packets\n"
+"      For each ARP announcement requested, a pair of ARP packets is sent,\n"
+"      an ARP request, and an ARP reply. This is becuse some systems\n"
+"      ignore one or the other, and this combination gives the greatest\n"
+"      chance of success.\n"
+"\n"
+"      Each time an ARP is sent, if another ARP will be sent then\n"
+"      the code sleeps for half of repeatinterval-ms.\n"
+"\n"
+"    repeatcount: how many pairs of ARP packets to send.\n"
+"                 See above for why pairs are sent\n"
+"\n"
+"    pidfile: pid file to use\n"
+"\n"
+"    device: netowrk interace to use\n"
+"\n"
+"    src_ip_addr: source ip address\n"
+"\n"
+"    src_hw_addr: source hardware address.\n"
+"                 If \"auto\" then the address of device\n"
+"\n"
+"    broadcast_ip_addr: ignored\n"
+"\n"
+"    netmask: ignored\n"
+};
+
+static const char * SENDARPNAME = "send_arp";
+
+static void convert_macaddr (u_char *macaddr, u_char enet_src[6]);
+static int get_hw_addr(char *device, u_char mac[6]);
+int write_pid_file(const char *pidfilename);
+int create_pid_directory(const char *piddirectory);
+
+#define AUTO_MAC_ADDR "auto"
+
+
+#ifndef LIBNET_ERRBUF_SIZE
+#	define LIBNET_ERRBUF_SIZE 256
+#endif
+
+
+/* 
+ * For use logd, should keep identical with the same const variables defined
+ * in heartbeat.h.
+ */
+#define ENV_PREFIX "HA_"
+#define KEY_LOGDAEMON   "use_logd"
+
+static void
+byebye(int nsig)
+{
+	(void)nsig;
+	/* Avoid an "error exit" log message if we're killed */
+	exit(0);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+	int	c = -1;
+	char	errbuf[LIBNET_ERRBUF_SIZE];
+	char*	device;
+	char*	ipaddr;
+	char*	macaddr;
+	char*	broadcast;
+	char*	netmask;
+	u_int32_t	ip;
+	u_char  src_mac[6];
+	int	repeatcount = 1;
+	int	j;
+	long	msinterval = 1000;
+	int	flag;
+	char    pidfilenamebuf[64];
+	char    *pidfilename = NULL;
+
+#ifdef HAVE_LIBNET_1_0_API
+	LTYPE*	l;
+	u_char *request, *reply;
+#elif defined(HAVE_LIBNET_1_1_API)
+	LTYPE *request, *reply;
+#endif
+
+	CL_SIGNAL(SIGTERM, byebye);
+	CL_SIGINTERRUPT(SIGTERM, 1);
+
+        cl_log_set_entity(SENDARPNAME);
+        cl_log_enable_stderr(TRUE);
+        cl_log_set_facility(LOG_USER);
+	cl_inherit_logging_environment(0);
+
+	while ((flag = getopt(argc, argv, "i:r:p:")) != EOF) {
+		switch(flag) {
+
+		case 'i':	msinterval= atol(optarg);
+				break;
+
+		case 'r':	repeatcount= atoi(optarg);
+				break;
+
+		case 'p':	pidfilename= optarg;
+				break;
+
+		default:	fprintf(stderr, "%s\n\n", print_usage);
+				return 1;
+				break;
+		}
+	}
+	if (argc-optind != 5) {
+		fprintf(stderr, "%s\n\n", print_usage);
+		return 1;
+	}
+
+	/*
+	 *	argv[optind+1] DEVICE		dc0,eth0:0,hme0:0,
+	 *	argv[optind+2] IP		192.168.195.186
+	 *	argv[optind+3] MAC ADDR		00a0cc34a878
+	 *	argv[optind+4] BROADCAST	192.168.195.186
+	 *	argv[optind+5] NETMASK		ffffffffffff
+	 */
+
+	device    = argv[optind];
+	ipaddr    = argv[optind+1];
+	macaddr   = argv[optind+2];
+	broadcast = argv[optind+3];
+	netmask   = argv[optind+4];
+
+	if (!pidfilename) {
+		if (snprintf(pidfilenamebuf, sizeof(pidfilenamebuf), "%s%s", 
+					PIDFILE_BASE, ipaddr) >= 
+				(int)sizeof(pidfilenamebuf)) {
+			cl_log(LOG_INFO, "Pid file truncated");
+			return EXIT_FAILURE;
+		}
+		pidfilename = pidfilenamebuf;
+	}
+
+	if(write_pid_file(pidfilename) < 0) {
+		return EXIT_FAILURE;
+	}
+
+	if (!strcasecmp(macaddr, AUTO_MAC_ADDR)) {
+		if (get_hw_addr(device, src_mac) < 0) {
+			 cl_log(LOG_ERR, "Cannot find mac address for %s",
+					 device);
+			 unlink(pidfilename);
+			 return EXIT_FAILURE;
+		}
+	}
+	else {
+		convert_macaddr((unsigned char *)macaddr, src_mac);
+	}
+
+/*
+ * We need to send both a broadcast ARP request as well as the ARP response we
+ * were already sending.  All the interesting research work for this fix was
+ * done by Masaki Hasegawa <masaki-h at pp.iij4u.or.jp> and his colleagues.
+ */
+
+#if defined(HAVE_LIBNET_1_0_API)
+#ifdef ON_DARWIN
+	if ((ip = libnet_name_resolve((unsigned char*)ipaddr, 1)) == -1UL) {
+#else
+	if ((ip = libnet_name_resolve(ipaddr, 1)) == -1UL) {
+#endif
+		cl_log(LOG_ERR, "Cannot resolve IP address [%s]", ipaddr);
+		unlink(pidfilename);
+		return EXIT_FAILURE;
+	}
+
+	l = libnet_open_link_interface(device, errbuf);
+	if (!l) {
+		cl_log(LOG_ERR, "libnet_open_link_interface on %s: %s"
+		,	device, errbuf);
+		unlink(pidfilename);
+		return EXIT_FAILURE;
+	}
+	request = mk_packet(ip, (unsigned char*)device, src_mac
+		, (unsigned char*)broadcast, (unsigned char*)netmask
+		, ARPOP_REQUEST);
+	reply = mk_packet(ip, (unsigned char*)device, src_mac
+		, (unsigned char *)broadcast
+		, (unsigned char *)netmask, ARPOP_REPLY);
+	if (!request || !reply) {
+		cl_log(LOG_ERR, "could not create packets");
+		unlink(pidfilename);
+		return EXIT_FAILURE;
+	}
+	for (j=0; j < repeatcount; ++j) {
+		c = send_arp(l, (unsigned char*)device, request);
+		if (c < 0) {
+			break;
+		}
+		mssleep(msinterval / 2);
+		c = send_arp(l, (unsigned char*)device, reply);
+		if (c < 0) {
+			break;
+		}
+		if (j != repeatcount-1) {
+			mssleep(msinterval / 2);
+		}
+	}
+#elif defined(HAVE_LIBNET_1_1_API)
+	if ((request=libnet_init(LIBNET_LINK, device, errbuf)) == NULL) {
+		cl_log(LOG_ERR, "libnet_init failure on %s: %s", device, errbuf);
+		unlink(pidfilename);
+		return EXIT_FAILURE;
+	}
+	if ((reply=libnet_init(LIBNET_LINK, device, errbuf)) == NULL) {
+		cl_log(LOG_ERR, "libnet_init failure on %s: %s", device, errbuf);
+		unlink(pidfilename);
+		return EXIT_FAILURE;
+	}
+	if ((signed)(ip = libnet_name2addr4(request, ipaddr, 1)) == -1) {
+		cl_log(LOG_ERR, "Cannot resolve IP address [%s]", ipaddr);
+		unlink(pidfilename);
+		return EXIT_FAILURE;
+	}
+	request = mk_packet(request, ip, (unsigned char*)device, src_mac
+		, (unsigned char*)broadcast, (unsigned char*)netmask
+		, ARPOP_REQUEST);
+	reply = mk_packet(reply, ip, (unsigned char*)device, src_mac
+		, (unsigned char *)broadcast
+		, (unsigned char *)netmask, ARPOP_REPLY);
+	if (!request || !reply) {
+		cl_log(LOG_ERR, "could not create packets");
+		unlink(pidfilename);
+		return EXIT_FAILURE;
+	}
+	for (j=0; j < repeatcount; ++j) {
+		c = send_arp(request);
+		if (c < 0) {
+			break;
+		}
+		mssleep(msinterval / 2);
+		c = send_arp(reply);
+		if (c < 0) {
+			break;
+		}
+		if (j != repeatcount-1) {
+			mssleep(msinterval / 2);
+		}
+	}
+#else
+#	error "Must have LIBNET API version defined."
+#endif
+
+	unlink(pidfilename);
+	return c < 0  ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+
+void
+convert_macaddr (u_char *macaddr, u_char enet_src[6])
+{
+	int i, pos;
+	u_char bits[3];
+
+	pos = 0;
+	for (i = 0; i < 6; i++) {
+		/* Inserted to allow old-style MAC addresses */
+		if (*macaddr == ':') {
+			pos++;
+		}
+		bits[0] = macaddr[pos++];
+		bits[1] = macaddr[pos++];
+		bits[2] = '\0';
+
+		enet_src[i] = strtol((const char *)bits, (char **)NULL, 16);
+	}
+
+}
+
+#ifdef HAVE_LIBNET_1_0_API
+int
+get_hw_addr(char *device, u_char mac[6])
+{
+	struct ether_addr	*mac_address;
+	struct libnet_link_int  *network;
+	char                    err_buf[LIBNET_ERRBUF_SIZE];
+
+	network = libnet_open_link_interface(device, err_buf);
+	if (!network) {
+		fprintf(stderr, "libnet_open_link_interface: %s\n", err_buf);
+		return -1;
+	}
+
+	mac_address = libnet_get_hwaddr(network, device, err_buf);
+	if (!mac_address) {
+		fprintf(stderr, "libnet_get_hwaddr: %s\n", err_buf);
+		return -1;
+	}
+
+	memcpy(mac, mac_address->ether_addr_octet, 6);
+
+	return 0;
+}
+#endif
+
+#ifdef HAVE_LIBNET_1_1_API
+int
+get_hw_addr(char *device, u_char mac[6])
+{
+	struct libnet_ether_addr	*mac_address;
+	libnet_t		*ln;
+	char			err_buf[LIBNET_ERRBUF_SIZE];
+
+	ln = libnet_init(LIBNET_LINK, device, err_buf);
+	if (!ln) {
+		fprintf(stderr, "libnet_open_link_interface: %s\n", err_buf);
+		return -1;
+	}
+
+	mac_address = libnet_get_hwaddr(ln);
+	if (!mac_address) {
+		fprintf(stderr,  "libnet_get_hwaddr: %s\n", err_buf);
+		return -1;
+	}
+
+	memcpy(mac, mac_address->ether_addr_octet, 6);
+
+	return 0;
+}
+#endif
+
+
+/*
+ * Notes on send_arp() behaviour. Horms, 15th June 2004
+ *
+ * 1. Target Hardware Address
+ *    (In the ARP portion of the packet)
+ *
+ *    a) ARP Reply
+ *
+ *       Set to the MAC address we want associated with the VIP,
+ *       as per RFC2002 (4.6).
+ *
+ *       Previously set to ff:ff:ff:ff:ff:ff
+ *
+ *    b) ARP Request
+ *
+ *       Set to 00:00:00:00:00:00. According to RFC2002 (4.6)
+ *       this value is not used in an ARP request, so the value should
+ *       not matter. However, I observed that typically (always?) this value
+ *       is set to 00:00:00:00:00:00. It seems harmless enough to follow
+ *       this trend.
+ *
+ *       Previously set to ff:ff:ff:ff:ff:ff
+ *
+ *  2. Source Hardware Address
+ *     (Ethernet Header, not in the ARP portion of the packet)
+ *
+ *     Set to the MAC address of the interface that the packet is being
+ *     sent to. Actually, due to the way that send_arp is called this would
+ *     usually (always?) be the case anyway. Although this value should not
+ *     really matter, it seems sensible to set the source address to where
+ *     the packet is really coming from.  The other obvious choice would be
+ *     the MAC address that is being associated for the VIP. Which was the
+ *     previous values.  Again, these are typically the same thing.
+ *
+ *     Previously set to MAC address being associated with the VIP
+ */
+
+#ifdef HAVE_LIBNET_1_0_API
+u_char *
+mk_packet(u_int32_t ip, u_char *device, u_char *macaddr, u_char *broadcast, u_char *netmask, u_short arptype)
+{
+	u_char *buf;
+	u_char *target_mac;
+	u_char device_mac[6];
+	u_char bcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	u_char zero_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+
+	if (libnet_init_packet(LIBNET_ARP_H + LIBNET_ETH_H, &buf) == -1) {
+	cl_log(LOG_ERR, "libnet_init_packet memory:");
+		return NULL;
+	}
+
+	/* Convert ASCII Mac Address to 6 Hex Digits. */
+
+	/* Ethernet header */
+	if (get_hw_addr((char*)device, device_mac) < 0) {
+		cl_log(LOG_ERR, "Cannot find mac address for %s",
+				device);
+		return NULL;
+	}
+
+	if (libnet_build_ethernet(bcast_mac, device_mac, ETHERTYPE_ARP, NULL, 0
+	,	buf) == -1) {
+		cl_log(LOG_ERR, "libnet_build_ethernet failed:");
+		libnet_destroy_packet(&buf);
+		return NULL;
+	}
+
+	if (arptype == ARPOP_REQUEST) {
+		target_mac = zero_mac;
+	}
+	else if (arptype == ARPOP_REPLY) {
+		target_mac = macaddr;
+	}
+	else {
+		cl_log(LOG_ERR, "unknown arptype");
+		return NULL;
+	}
+
+	/*
+	 *  ARP header
+	 */
+	if (libnet_build_arp(ARPHRD_ETHER,	/* Hardware address type */
+		ETHERTYPE_IP,			/* Protocol address type */
+		6,				/* Hardware address length */
+		4,				/* Protocol address length */
+		arptype,			/* ARP operation */
+		macaddr,			/* Source hardware addr */
+		(u_char *)&ip,			/* Target hardware addr */
+		target_mac,			/* Destination hw addr */
+		(u_char *)&ip,			/* Target protocol address */
+		NULL,				/* Payload */
+		0,				/* Payload length */
+		buf + LIBNET_ETH_H) == -1) {
+	        cl_log(LOG_ERR, "libnet_build_arp failed:");
+		libnet_destroy_packet(&buf);
+		return NULL;
+	}
+	return buf;
+}
+#endif /* HAVE_LIBNET_1_0_API */
+
+
+
+
+#ifdef HAVE_LIBNET_1_1_API
+libnet_t*
+mk_packet(libnet_t* lntag, u_int32_t ip, u_char *device, u_char macaddr[6], u_char *broadcast, u_char *netmask, u_short arptype)
+{
+	u_char *target_mac;
+	u_char device_mac[6];
+	u_char bcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	u_char zero_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+	if (arptype == ARPOP_REQUEST) {
+		target_mac = zero_mac;
+	}
+	else if (arptype == ARPOP_REPLY) {
+		target_mac = macaddr;
+	}
+	else {
+		cl_log(LOG_ERR, "unkonwn arptype:");
+		return NULL;
+	}
+
+	/*
+	 *  ARP header
+	 */
+	if (libnet_build_arp(ARPHRD_ETHER,	/* hardware address type */
+		ETHERTYPE_IP,	/* protocol address type */
+		6,		/* Hardware address length */
+		4,		/* protocol address length */
+		arptype,	/* ARP operation type */
+		macaddr,	/* sender Hardware address */
+		(u_int8_t *)&ip,	/* sender protocol address */
+		target_mac,	/* target hardware address */
+		(u_int8_t *)&ip,	/* target protocol address */
+		NULL,		/* Payload */
+		0,		/* Length of payload */
+		lntag,		/* libnet context pointer */
+		0		/* packet id */
+	) == -1 ) {
+		cl_log(LOG_ERR, "libnet_build_arp failed:");
+		return NULL;
+	}
+
+	/* Ethernet header */
+	if (get_hw_addr((char *)device, device_mac) < 0) {
+		cl_log(LOG_ERR, "Cannot find mac address for %s",
+				device);
+		return NULL;
+	}
+
+	if (libnet_build_ethernet(bcast_mac, device_mac, ETHERTYPE_ARP, NULL, 0
+	,	lntag, 0) == -1 ) {
+		cl_log(LOG_ERR, "libnet_build_ethernet failed:");
+		return NULL;
+	}
+	return lntag;
+}
+#endif /* HAVE_LIBNET_1_1_API */
+
+#ifdef HAVE_LIBNET_1_0_API
+int
+send_arp(struct libnet_link_int *l, u_char *device, u_char *buf)
+{
+	int n;
+
+	n = libnet_write_link_layer(l, (char*)device, buf, LIBNET_ARP_H + LIBNET_ETH_H);
+	if (n == -1) {
+		cl_log(LOG_ERR, "libnet_write_link_layer failed");
+	}
+	return (n);
+}
+#endif /* HAVE_LIBNET_1_0_API */
+
+#ifdef HAVE_LIBNET_1_1_API
+int
+send_arp(libnet_t* lntag)
+{
+	int n;
+
+	n = libnet_write(lntag);
+	if (n == -1) {
+		cl_log(LOG_ERR, "libnet_write failed");
+	}
+	return (n);
+}
+#endif /* HAVE_LIBNET_1_1_API */
+
+
+int
+create_pid_directory(const char *pidfilename)  
+{
+	int	status;
+	struct stat stat_buf;
+	char    *pidfilename_cpy;
+	char    *dir;
+
+	pidfilename_cpy = strdup(pidfilename);
+	if (!pidfilename_cpy) {
+		cl_log(LOG_INFO, "Memory allocation failure: %s\n",
+				strerror(errno));
+		return -1;
+	}
+	
+	dir = dirname(pidfilename_cpy);
+
+	status = stat(dir, &stat_buf); 
+
+	if (status < 0 && errno != ENOENT && errno != ENOTDIR) {
+		cl_log(LOG_INFO, "Could not stat pid-file directory "
+				"[%s]: %s", dir, strerror(errno));
+		free(pidfilename_cpy);
+		return -1;
+	}
+	
+	if (status >= 0) {
+		if (S_ISDIR(stat_buf.st_mode)) {
+			return 0;
+		}
+		cl_log(LOG_INFO, "Pid-File directory exists but is "
+				"not a directory [%s]", dir);
+		free(pidfilename_cpy);
+		return -1;
+        }
+
+	if (mkdir(dir, S_IRUSR|S_IWUSR|S_IXUSR | S_IRGRP|S_IXGRP) < 0) {
+		/* Did someone else make it while we were trying ? */
+		if (errno == EEXIST && stat(dir, &stat_buf) >= 0
+		&&	S_ISDIR(stat_buf.st_mode)) {
+			return 0;
+		}
+		cl_log(LOG_INFO, "Could not create pid-file directory "
+				"[%s]: %s", dir, strerror(errno));
+		free(pidfilename_cpy);
+		return -1;
+	}
+
+	free(pidfilename_cpy);
+	return 0;
+}
+
+
+int
+write_pid_file(const char *pidfilename)  
+{
+
+	int     	pidfilefd;
+	char    	pidbuf[11];
+	unsigned long   pid;
+	ssize_t 	bytes;
+
+	if (*pidfilename != '/') {
+		cl_log(LOG_INFO, "Invalid pid-file name, must begin with a "
+				"'/' [%s]\n", pidfilename);
+		return -1;
+	}
+
+	if (create_pid_directory(pidfilename) < 0) {
+		return -1;
+	}
+
+	while (1) {
+		pidfilefd = open(pidfilename, O_CREAT|O_EXCL|O_RDWR, 
+				S_IRUSR|S_IWUSR);
+		if (pidfilefd < 0) {
+			if (errno != EEXIST) { /* Old PID file */
+				cl_log(LOG_INFO, "Could not open pid-file "
+						"[%s]: %s", pidfilename, 
+						strerror(errno));
+				return -1;
+			}
+		}
+		else {
+			break;
+		}
+
+		pidfilefd = open(pidfilename, O_RDONLY, S_IRUSR|S_IWUSR);
+		if (pidfilefd < 0) {
+			cl_log(LOG_INFO, "Could not open pid-file " 
+					"[%s]: %s", pidfilename, 
+					strerror(errno));
+			return -1;
+		}
+
+		while (1) {
+			bytes = read(pidfilefd, pidbuf, sizeof(pidbuf)-1);
+			if (bytes < 0) {
+				if (errno == EINTR) {
+					continue;
+				}
+				cl_log(LOG_INFO, "Could not read pid-file " 
+						"[%s]: %s", pidfilename, 
+						strerror(errno));
+				return -1;
+			}
+			pidbuf[bytes] = '\0';
+			break;
+		}
+
+		if(unlink(pidfilename) < 0) {
+			cl_log(LOG_INFO, "Could not delete pid-file "
+	 				"[%s]: %s", pidfilename, 
+					strerror(errno));
+			return -1;
+		}
+
+		if (!bytes) {
+			cl_log(LOG_INFO, "Invalid pid in pid-file "
+	 				"[%s]: %s", pidfilename, 
+					strerror(errno));
+			return -1;
+		}
+
+		close(pidfilefd);
+
+		pid = strtoul(pidbuf, NULL, 10);
+		if (pid == ULONG_MAX && errno == ERANGE) {
+			cl_log(LOG_INFO, "Invalid pid in pid-file "
+	 				"[%s]: %s", pidfilename, 
+					strerror(errno));
+			return -1;
+		}
+
+		if (kill(pid, SIGKILL) < 0 && errno != ESRCH) {
+			cl_log(LOG_INFO, "Error killing old proccess [%lu] "
+	 				"from pid-file [%s]: %s", pid,
+					pidfilename, strerror(errno));
+			return -1;
+		}
+
+		cl_log(LOG_INFO, "Killed old send_arp process [%lu]\n",
+				pid);
+	}
+
+	if (snprintf(pidbuf, sizeof(pidbuf), "%u"
+	,	getpid()) >= (int)sizeof(pidbuf)) {
+		cl_log(LOG_INFO, "Pid too long for buffer [%u]", getpid());
+		return -1;
+	}
+
+	while (1) {
+		bytes = write(pidfilefd, pidbuf, strlen(pidbuf));
+		if (bytes != (ssize_t)strlen(pidbuf)) {
+			if (bytes < 0 && errno == EINTR) {
+				continue;
+			}
+			cl_log(LOG_INFO, "Could not write pid-file "
+					"[%s]: %s", pidfilename,
+					strerror(errno));
+			return -1;
+		}
+		break;
+	}
+
+	close(pidfilefd);
+
+	return 0;
+}
+
+
diff --git a/tools/send_arp.linux.c b/tools/send_arp.linux.c
new file mode 100644
index 0000000..e1c1960
--- /dev/null
+++ b/tools/send_arp.linux.c
@@ -0,0 +1,577 @@
+/*
+ * arping.c
+ *
+ *		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.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet at ms2.inr.ac.ru>
+ */
+
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <linux/sockios.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/signal.h>
+#include <sys/ioctl.h>
+#include <linux/if.h>
+#include <linux/if_packet.h>
+#include <linux/if_ether.h>
+#include <net/if_arp.h>
+#include <sys/uio.h>
+
+#include <netdb.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+static void usage(void) __attribute__((noreturn));
+
+static int quit_on_reply;
+static char *device;
+static int ifindex;
+static char *source;
+static struct in_addr src, dst;
+static char *target;
+static int dad = 0, unsolicited = 0, advert = 0;
+static int quiet = 0;
+static int count = -1;
+static int timeout = 0;
+static int unicasting = 0;
+static int s = 0;
+static int broadcast_only = 0;
+
+static struct sockaddr_ll me;
+static struct sockaddr_ll he;
+
+static struct timeval start, last;
+
+static int sent, brd_sent;
+static int received, brd_recv, req_recv;
+
+#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \
+			   ((tv1).tv_usec-(tv2).tv_usec)/1000 )
+
+static void print_hex(unsigned char *p, int len);
+static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM);
+static void set_signal(int signo, void (*handler)(void));
+static int send_pack(int s, struct in_addr src, struct in_addr dst,
+	      struct sockaddr_ll *ME, struct sockaddr_ll *HE);
+static void finish(void);
+static void catcher(void);
+
+void usage(void)
+{
+	fprintf(stderr,
+		"Usage: arping [-fqbDUAV] [-c count] [-w timeout] [-I device] [-s source] destination\n"
+		"  -f : quit on first reply\n"
+		"  -q : be quiet\n"
+		"  -b : keep broadcasting, don't go unicast\n"
+		"  -D : duplicate address detection mode\n"
+		"  -U : Unsolicited ARP mode, update your neighbours\n"
+		"  -A : ARP answer mode, update your neighbours\n"
+		"  -V : print version and exit\n"
+		"  -c count : how many packets to send\n"
+		"  -w timeout : how long to wait for a reply\n"
+		"  -I device : which ethernet device to use (eth0)\n"
+		"  -s source : source ip address\n"
+		"  destination : ask for what ip address\n"
+		);
+	exit(2);
+}
+
+void set_signal(int signo, void (*handler)(void))
+{
+	struct sigaction sa;
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = (void (*)(int))handler;
+	sa.sa_flags = SA_RESTART;
+	sigaction(signo, &sa, NULL);
+}
+
+int send_pack(int s, struct in_addr src, struct in_addr dst,
+	      struct sockaddr_ll *ME, struct sockaddr_ll *HE)
+{
+	int err;
+	struct timeval now;
+	unsigned char buf[256];
+	struct arphdr *ah = (struct arphdr*)buf;
+	unsigned char *p = (unsigned char *)(ah+1);
+
+	ah->ar_hrd = htons(ME->sll_hatype);
+	if (ah->ar_hrd == htons(ARPHRD_FDDI))
+		ah->ar_hrd = htons(ARPHRD_ETHER);
+	ah->ar_pro = htons(ETH_P_IP);
+	ah->ar_hln = ME->sll_halen;
+	ah->ar_pln = 4;
+	ah->ar_op  = advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);
+
+	memcpy(p, &ME->sll_addr, ah->ar_hln);
+	p+=ME->sll_halen;
+
+	memcpy(p, &src, 4);
+	p+=4;
+
+	if (advert)
+		memcpy(p, &ME->sll_addr, ah->ar_hln);
+	else
+		memcpy(p, &HE->sll_addr, ah->ar_hln);
+	p+=ah->ar_hln;
+
+	memcpy(p, &dst, 4);
+	p+=4;
+
+	gettimeofday(&now, NULL);
+	err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, sizeof(*HE));
+	if (err == p-buf) {
+		last = now;
+		sent++;
+		if (!unicasting)
+			brd_sent++;
+	}
+	return err;
+}
+
+void finish(void)
+{
+	if (!quiet) {
+		printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent);
+		printf("Received %d response(s)", received);
+		if (brd_recv || req_recv) {
+			printf(" (");
+			if (req_recv)
+				printf("%d request(s)", req_recv);
+			if (brd_recv)
+				printf("%s%d broadcast(s)",
+				       req_recv ? ", " : "",
+				       brd_recv);
+			printf(")");
+		}
+		printf("\n");
+		fflush(stdout);
+	}
+
+	if (dad) {
+	    fflush(stdout);
+	    exit(!!received);
+	}
+	
+	if (unsolicited)
+		exit(0);
+
+	fflush(stdout);
+	exit(!received);
+}
+
+void catcher(void)
+{
+	struct timeval tv;
+
+	gettimeofday(&tv, NULL);
+
+	if (start.tv_sec==0)
+		start = tv;
+
+	if (count-- == 0 || (timeout && MS_TDIFF(tv,start) > timeout*1000 + 500))
+		finish();
+
+	if (last.tv_sec==0 || MS_TDIFF(tv,last) > 500) {
+		send_pack(s, src, dst, &me, &he);
+		if (count == 0 && unsolicited)
+			finish();
+	}
+	alarm(1);
+}
+
+void print_hex(unsigned char *p, int len)
+{
+	int i;
+	for (i=0; i<len; i++) {
+		printf("%02X", p[i]);
+		if (i != len-1)
+			printf(":");
+	}
+}
+
+int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
+{
+	struct timeval tv;
+	struct arphdr *ah = (struct arphdr*)buf;
+	unsigned char *p = (unsigned char *)(ah+1);
+	struct in_addr src_ip, dst_ip;
+
+	gettimeofday(&tv, NULL);
+
+	/* Filter out wild packets */
+	if (FROM->sll_pkttype != PACKET_HOST &&
+	    FROM->sll_pkttype != PACKET_BROADCAST &&
+	    FROM->sll_pkttype != PACKET_MULTICAST)
+		return 0;
+
+	/* Only these types are recognised */
+	if (ah->ar_op != htons(ARPOP_REQUEST) &&
+	    ah->ar_op != htons(ARPOP_REPLY))
+		return 0;
+
+	/* ARPHRD check and this darned FDDI hack here :-( */
+	if (ah->ar_hrd != htons(FROM->sll_hatype) &&
+	    (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER)))
+		return 0;
+
+	/* Protocol must be IP. */
+	if (ah->ar_pro != htons(ETH_P_IP))
+		return 0;
+	if (ah->ar_pln != 4)
+		return 0;
+	if (ah->ar_hln != me.sll_halen)
+		return 0;
+	if (len < sizeof(*ah) + 2*(4 + ah->ar_hln))
+		return 0;
+	memcpy(&src_ip, p+ah->ar_hln, 4);
+	memcpy(&dst_ip, p+ah->ar_hln+4+ah->ar_hln, 4);
+	if (!dad) {
+		if (src_ip.s_addr != dst.s_addr)
+			return 0;
+		if (src.s_addr != dst_ip.s_addr)
+			return 0;
+		if (memcmp(p+ah->ar_hln+4, &me.sll_addr, ah->ar_hln))
+			return 0;
+	} else {
+		/* DAD packet was:
+		   src_ip = 0 (or some src)
+		   src_hw = ME
+		   dst_ip = tested address
+		   dst_hw = <unspec>
+
+		   We fail, if receive request/reply with:
+		   src_ip = tested_address
+		   src_hw != ME
+		   if src_ip in request was not zero, check
+		   also that it matches to dst_ip, otherwise
+		   dst_ip/dst_hw do not matter.
+		 */
+		if (src_ip.s_addr != dst.s_addr)
+			return 0;
+		if (memcmp(p, &me.sll_addr, me.sll_halen) == 0)
+			return 0;
+		if (src.s_addr && src.s_addr != dst_ip.s_addr)
+			return 0;
+	}
+	if (!quiet) {
+		int s_printed = 0;
+		printf("%s ", FROM->sll_pkttype==PACKET_HOST ? "Unicast" : "Broadcast");
+		printf("%s from ", ah->ar_op == htons(ARPOP_REPLY) ? "reply" : "request");
+		printf("%s [", inet_ntoa(src_ip));
+		print_hex(p, ah->ar_hln);
+		printf("] ");
+		if (dst_ip.s_addr != src.s_addr) {
+			printf("for %s ", inet_ntoa(dst_ip));
+			s_printed = 1;
+		}
+		if (memcmp(p+ah->ar_hln+4, me.sll_addr, ah->ar_hln)) {
+			if (!s_printed)
+				printf("for ");
+			printf("[");
+			print_hex(p+ah->ar_hln+4, ah->ar_hln);
+			printf("]");
+		}
+		if (last.tv_sec) {
+			long usecs = (tv.tv_sec-last.tv_sec) * 1000000 +
+				tv.tv_usec-last.tv_usec;
+			long msecs = (usecs+500)/1000;
+			usecs -= msecs*1000 - 500;
+			printf(" %ld.%03ldms\n", msecs, usecs);
+		} else {
+			printf(" UNSOLICITED?\n");
+		}
+		fflush(stdout);
+	}
+	received++;
+	if (FROM->sll_pkttype != PACKET_HOST)
+		brd_recv++;
+	if (ah->ar_op == htons(ARPOP_REQUEST))
+		req_recv++;
+	if (quit_on_reply)
+		finish();
+	if(!broadcast_only) {
+		memcpy(he.sll_addr, p, me.sll_halen);
+		unicasting=1;
+	}
+	return 1;
+}
+
+#include <signal.h>
+
+static void byebye(int nsig)
+{
+    /* Avoid an "error exit" log message if we're killed */
+    nsig = 0;
+    exit(nsig);
+}
+
+int
+main(int argc, char **argv)
+{
+	int socket_errno;
+	int ch;
+	uid_t uid = getuid();
+	int hb_mode = 0;
+
+	signal(SIGTERM, byebye);
+	signal(SIGPIPE, byebye);
+	
+	device = strdup("eth0");
+	
+	s = socket(PF_PACKET, SOCK_DGRAM, 0);
+	socket_errno = errno;
+
+	if (setuid(uid)) {
+		perror("arping: setuid");
+		exit(-1);
+	}
+
+	while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:Vr:i:p:")) != EOF) {
+		switch(ch) {
+		case 'b':
+			broadcast_only=1;
+			break;
+		case 'D':
+			dad++;
+			quit_on_reply=1;
+			break;
+		case 'U':
+			unsolicited++;
+			break;
+		case 'A':
+			advert++;
+			unsolicited++;
+			break;
+		case 'q':
+			quiet++;
+			break;
+		case 'r': /* send_arp.libnet compatibility option */
+			hb_mode = 1;
+			/* fall-through */
+		case 'c':
+			count = atoi(optarg);
+			break;
+		case 'w':
+			timeout = atoi(optarg);
+			break;
+		case 'I':
+			device = optarg;
+			break;
+		case 'f':
+			quit_on_reply=1;
+			break;
+		case 's':
+			source = optarg;
+			break;
+		case 'V':
+			printf("send_arp utility\n");
+			exit(0);
+		case 'p':
+		case 'i':
+		    hb_mode = 1;
+		    /* send_arp.libnet compatibility options, ignore */
+		    break;
+		case 'h':
+		case '?':
+		default:
+			usage();
+		}
+	}
+
+	if(hb_mode) {
+	    /* send_arp.libnet compatibility mode */
+	    if (argc - optind != 5) {
+		usage();
+		return 1;
+	    }
+	    /*
+	     *	argv[optind+1] DEVICE		dc0,eth0:0,hme0:0,
+	     *	argv[optind+2] IP		192.168.195.186
+	     *	argv[optind+3] MAC ADDR		00a0cc34a878
+	     *	argv[optind+4] BROADCAST	192.168.195.186
+	     *	argv[optind+5] NETMASK		ffffffffffff
+	     */
+
+	    unsolicited = 1;
+	    device = argv[optind];
+	    target = argv[optind+1];
+
+	} else {
+	    argc -= optind;
+	    argv += optind;
+	    if (argc != 1)
+		usage();
+
+	    target = *argv;
+	}
+	
+	if (device == NULL) {
+		fprintf(stderr, "arping: device (option -I) is required\n");
+		usage();
+	}
+
+	if (s < 0) {
+		errno = socket_errno;
+		perror("arping: socket");
+		exit(2);
+	}
+
+	if (1) {
+		struct ifreq ifr;
+		memset(&ifr, 0, sizeof(ifr));
+		strncpy(ifr.ifr_name, device, IFNAMSIZ-1);
+		if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
+			fprintf(stderr, "arping: unknown iface %s\n", device);
+			exit(2);
+		}
+		ifindex = ifr.ifr_ifindex;
+
+		if (ioctl(s, SIOCGIFFLAGS, (char*)&ifr)) {
+			perror("ioctl(SIOCGIFFLAGS)");
+			exit(2);
+		}
+		if (!(ifr.ifr_flags&IFF_UP)) {
+			if (!quiet)
+				printf("Interface \"%s\" is down\n", device);
+			exit(2);
+		}
+		if (ifr.ifr_flags&(IFF_NOARP|IFF_LOOPBACK)) {
+			if (!quiet)
+				printf("Interface \"%s\" is not ARPable\n", device);
+			exit(dad?0:2);
+		}
+	}
+
+	if (inet_aton(target, &dst) != 1) {
+		struct hostent *hp;
+		hp = gethostbyname2(target, AF_INET);
+		if (!hp) {
+			fprintf(stderr, "arping: unknown host %s\n", target);
+			exit(2);
+		}
+		memcpy(&dst, hp->h_addr, 4);
+	}
+
+	if (source && inet_aton(source, &src) != 1) {
+		fprintf(stderr, "arping: invalid source %s\n", source);
+		exit(2);
+	}
+
+	if (!dad && unsolicited && src.s_addr == 0)
+		src = dst;
+
+	if (!dad || src.s_addr) {
+		struct sockaddr_in saddr;
+		int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+		if (probe_fd < 0) {
+			perror("socket");
+			exit(2);
+		}
+		if (device) {
+			if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1)
+				perror("WARNING: interface is ignored");
+		}
+		memset(&saddr, 0, sizeof(saddr));
+		saddr.sin_family = AF_INET;
+		if (src.s_addr) {
+			saddr.sin_addr = src;
+			if (bind(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
+				perror("bind");
+				exit(2);
+			}
+		} else if (!dad) {
+			int on = 1;
+			socklen_t alen = sizeof(saddr);
+
+			saddr.sin_port = htons(1025);
+			saddr.sin_addr = dst;
+
+			if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char*)&on, sizeof(on)) == -1)
+				perror("WARNING: setsockopt(SO_DONTROUTE)");
+			if (connect(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
+				perror("connect");
+				exit(2);
+			}
+			if (getsockname(probe_fd, (struct sockaddr*)&saddr, &alen) == -1) {
+				perror("getsockname");
+				exit(2);
+			}
+			src = saddr.sin_addr;
+		}
+		close(probe_fd);
+	};
+
+	me.sll_family = AF_PACKET;
+	me.sll_ifindex = ifindex;
+	me.sll_protocol = htons(ETH_P_ARP);
+	if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {
+		perror("bind");
+		exit(2);
+	}
+
+	if (1) {
+		socklen_t alen = sizeof(me);
+		if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) {
+			perror("getsockname");
+			exit(2);
+		}
+	}
+	if (me.sll_halen == 0) {
+		if (!quiet)
+			printf("Interface \"%s\" is not ARPable (no ll address)\n", device);
+		exit(dad?0:2);
+	}
+
+	he = me;
+	memset(he.sll_addr, -1, he.sll_halen);
+
+	if (!quiet) {
+		printf("ARPING %s ", inet_ntoa(dst));
+		printf("from %s %s\n",  inet_ntoa(src), device ? : "");
+	}
+
+	if (!src.s_addr && !dad) {
+		fprintf(stderr, "arping: no source address in not-DAD mode\n");
+		exit(2);
+	}
+
+	set_signal(SIGINT, finish);
+	set_signal(SIGALRM, catcher);
+
+	catcher();
+
+	while(1) {
+		sigset_t sset, osset;
+		unsigned char packet[4096];
+		struct sockaddr_ll from;
+		socklen_t alen = sizeof(from);
+		int cc;
+
+		if ((cc = recvfrom(s, packet, sizeof(packet), 0,
+				   (struct sockaddr *)&from, &alen)) < 0) {
+			perror("arping: recvfrom");
+			continue;
+		}
+		sigemptyset(&sset);
+		sigaddset(&sset, SIGALRM);
+		sigaddset(&sset, SIGINT);
+		sigprocmask(SIG_BLOCK, &sset, &osset);
+		recv_pack(packet, cc, &from);
+		sigprocmask(SIG_SETMASK, &osset, NULL);
+	}
+}
+
+
diff --git a/tools/sfex.h b/tools/sfex.h
new file mode 100644
index 0000000..3795c29
--- /dev/null
+++ b/tools/sfex.h
@@ -0,0 +1,176 @@
+/*-------------------------------------------------------------------------
+ *
+ * Shared Disk File EXclusiveness Control Program(SF-EX)
+ *
+ * sfex.h --- Primary include file for SF-EX *.c files.
+ *
+ * Copyright (c) 2007 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+ * 
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  
+ * 02110-1301, USA.
+ *  
+ * $Id$
+ *
+ *-------------------------------------------------------------------------*/
+
+#ifndef SFEX_H
+#define SFEX_H
+
+#include <clplumbing/cl_log.h>
+#include <clplumbing/coredumps.h>
+#include <clplumbing/realtime.h>
+
+#include <stdint.h>
+
+/*  version, revision */
+/*   These numbers are integer and, max number is 999. 
+     If these numbers change, version numbers in the configure.ac
+     (AC_INIT, AM_INIT_AUTOMAKE) must change together.
+ */
+#define SFEX_VERSION 1
+#define SFEX_REVISION 3
+
+#if 0
+#ifndef TRUE
+#  define TRUE 1
+#endif
+#ifndef FALSE
+#  define FALSE 0
+#endif
+#ifndef MIN
+#  define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#  define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+#endif
+
+/* for Linux >= 2.6, the alignment should be 512
+   for Linux < 2.6, the alignment should be sysconf(_SC_PAGESIZE)
+   we default to _SC_PAGESIZE
+ */
+#define SFEX_ODIRECT_ALIGNMENT sysconf(_SC_PAGESIZE)
+
+/*
+ * sfex_controldata --- control data
+ *
+ * This is allocated the head of sfex mata-data area. 
+ *
+ * magic number --- 4 bytes. This is fixed in {0x01, 0x1f, 0x71, 0x7f}.
+ *
+ * version number --- 4 bytes. This is printable integer number and 
+ * range is from 0 to 999. This must be left-justify, null(0x00) padding, and 
+ * make a last byte null.
+ *
+ * revision number --- 4 bytes. This is printable integer number and 
+ * range is from 0 to 999. This must be left-justify, null(0x00) padding, and 
+ * make a last byte null.
+ *
+ * blocksize --- 8bytes. This is printable integer number and range is from 
+ * 512 to 9999999. This must be left-justify, null(0x00) padding, and make a 
+ * last byte null. This is a size of control data and lock data(one lock data
+ * size when there are plural), and it is shown by number of bytes. 
+ * For avoiding partial writing, usually block size is set 512 byte etc.
+ * If you use direct I/O(if you spacificate --enable-directio for configure 
+ * script), note that this value is used for input and output buffer alignment.
+ * (In the Linux kernel 2.6, if this value is not 512 multibles, direct I/O 
+ * does not work)
+ 
+ * number of locks  --- 4 bytes. This is printable integer number and range 
+ * is from 1 to 999. This must be left-justify, null(0x00) padding, and make 
+ * a last byte null. This is the number of locks following this control data.
+ *
+ * padding --- The size of this member depend on blocksize. It is adjusted so 
+ * that the whole of the control data including this padding area becomes 
+ * blocksize.  The contents of padding area are all 0x00.
+ */
+typedef struct sfex_controldata {
+  char magic[4];		/*  magic number */
+  int version;			/*  version number */
+  int revision;			/*  revision number */
+  size_t blocksize;		/*  block size */
+  int numlocks;			/*  number of locks */
+} sfex_controldata;
+
+typedef struct sfex_controldata_ondisk {
+  uint8_t magic[4];
+  uint8_t version[4];
+  uint8_t revision[4];
+  uint8_t blocksize[8];
+  uint8_t numlocks[4];
+} sfex_controldata_ondisk;
+
+/*
+ * sfex_lockdata --- lock data
+ *
+ * This data(number is sfex_controldata.numlocks) are allocated behind of 
+ * sfex_controldata in the sfex meta-data area. The meaning of each member 
+ * and the storage method to mata data area are following;
+ *
+ * lock status --- 1 byte. printable character. Content is either one of 
+ * following;
+ *  SFEX_STATUS_UNLOCK: It show the status that no node locks.
+ *  SFEX_STATUS_LOCK: It show the status that nodename node is holding lock.
+ *  (But there is an exception. Refer to explanation of "count" member.)
+ *
+ * increment counter --- 4 bytes. This is printable integer number and range 
+ * is from 1 to 999. This must be left-justify, null(0x00) padding, and make 
+ * a last byte null. The node holding a lock increments this counter  
+ * periodically. If this counter does not increment for a certain period of 
+ * time, we consider that the lock is invalid. If it overflow, return to 0. 
+ * Initial value is 0.
+ *
+ * node name --- 256bytes. This is printable string. This must be left-justify, 
+ * null(0x00) padding, and make a last byte null. This is node name that update 
+ * lock data last. The node name must be same to get uname(2). Initial values 
+ * are white spaces.
+ *
+ * padding --- The size of this member depend on blocksize. It is adjusted so 
+ * that the whole of the control data including this padding area becomes 
+ * blocksize.  The contents of padding area are all 0x00.
+ */
+typedef struct sfex_lockdata {
+  char status;				/* status of lock */
+  int count;				/* increment counter */
+  char nodename[256];		/* node name */
+} sfex_lockdata;
+
+typedef struct sfex_lockdata_ondisk {
+	uint8_t status;
+	uint8_t count[4];
+	uint8_t nodename[256];
+} sfex_lockdata_ondisk;
+
+/* character for lock status. This is used in sfex_lockdata.status */
+#define SFEX_STATUS_UNLOCK 'u' /* unlock */
+#define SFEX_STATUS_LOCK 'l'	/* lock */
+
+/* features of each member of control data and lock data */
+#define SFEX_MAGIC "SFEX"
+#define SFEX_MIN_NUMLOCKS 1
+#define SFEX_MAX_NUMLOCKS 999
+#define SFEX_MIN_COUNT 0
+#define SFEX_MAX_COUNT 999
+#define SFEX_MAX_NODENAME (sizeof(((sfex_lockdata *)0)->nodename) - 1)
+
+/* update macro for increment counter */
+#define SFEX_NEXT_COUNT(c) (c >= SFEX_MAX_COUNT ? c - SFEX_MAX_COUNT : c + 1)
+
+/* extern variables */
+extern const char *progname;
+extern char *nodename;
+extern unsigned long sector_size;
+
+#endif /* SFEX_H */
diff --git a/tools/sfex_daemon.c b/tools/sfex_daemon.c
new file mode 100644
index 0000000..516c101
--- /dev/null
+++ b/tools/sfex_daemon.c
@@ -0,0 +1,345 @@
+#include <config.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <limits.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include "sfex.h"
+#include "sfex_lib.h"
+
+#if HAVE_GLUE_CONFIG_H
+#include <glue_config.h> /* for HA_LOG_FACILITY */
+#endif
+
+static int sysrq_fd;
+static int lock_index = 1;        /* default 1st lock */
+static time_t collision_timeout = 1; /* default 1 sec */
+static time_t lock_timeout = 60; /* default 60 sec */
+time_t unlock_timeout = 60;
+static time_t monitor_interval = 10;
+
+static sfex_controldata cdata;
+static sfex_lockdata ldata;
+static sfex_lockdata ldata_new;
+
+static const char *device;
+const char *progname;
+char *nodename;
+static const char *rsc_id = "sfex";
+
+static void usage(FILE *dist) {
+	  fprintf(dist, "usage: %s [-i <index>] [-c <collision_timeout>] [-t <lock_timeout>] <device>\n", progname);
+}
+
+static void acquire_lock(void)
+{
+	if (read_lockdata(&cdata, &ldata, lock_index) == -1) {
+		cl_log(LOG_ERR, "read_lockdata failed in acquire_lock\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if ((ldata.status == SFEX_STATUS_LOCK) && (strncmp(nodename, (const char*)(ldata.nodename), sizeof(ldata.nodename)))) {
+		unsigned int t = lock_timeout;
+		while (t > 0)
+			t = sleep(t);
+		read_lockdata(&cdata, &ldata_new, lock_index);
+		if (ldata.count != ldata_new.count) {
+			cl_log(LOG_ERR, "can\'t acquire lock: the lock's already hold by some other node.\n");
+			exit(2);
+		}
+	}
+
+	/* The lock acquisition is possible because it was not updated. */
+	ldata.status = SFEX_STATUS_LOCK;
+	ldata.count = SFEX_NEXT_COUNT(ldata.count);
+	strncpy((char*)(ldata.nodename), nodename, sizeof(ldata.nodename));
+	if (write_lockdata(&cdata, &ldata, lock_index) == -1) {
+		cl_log(LOG_ERR, "write_lockdata failed\n");
+		exit(EXIT_FAILURE);
+	}
+
+	/* detect the collision of lock */
+	/* The collision occurs when two or more nodes do the reservation 
+	   processing of the lock at the same time. It waits for collision_timeout 
+	   seconds to detect this,and whether the superscription of lock data by 
+	   another node is done is checked. If the superscription was done by 
+	   another node, the lock acquisition with the own node is given up.  
+	 */
+	{
+		unsigned int t = collision_timeout;
+		while (t > 0)
+			t = sleep(t);
+		if (read_lockdata(&cdata, &ldata_new, lock_index) == -1) {
+			cl_log(LOG_ERR, "read_lockdata failed in collision detection\n");
+		}
+		if (strncmp((char*)(ldata.nodename), (const char*)(ldata_new.nodename), sizeof(ldata.nodename))) {
+			cl_log(LOG_ERR, "can\'t acquire lock: collision detected in the air.\n");
+			exit(2);
+		}
+	}
+
+	/* extension of lock */
+	/* Validly time of the lock is extended. It is because of spending at 
+	   the collision_timeout seconds to detect the collision. */
+	ldata.count = SFEX_NEXT_COUNT(ldata.count);
+	if (write_lockdata(&cdata, &ldata, lock_index) == -1) {
+		cl_log(LOG_ERR, "write_lockdata failed in extension of lock\n");
+		exit(EXIT_FAILURE);
+	}
+	cl_log(LOG_INFO, "lock acquired\n");
+}
+
+static void error_todo (void)
+{
+	if (fork() == 0) {
+		cl_log(LOG_INFO, "Execute \"crm_resource -F -r %s -H %s\" command\n", rsc_id, nodename);
+		execl("/usr/sbin/crm_resource", "crm_resource", "-F", "-r", rsc_id, "-H", nodename, NULL);
+	} else {
+		exit(EXIT_FAILURE);
+	}
+}
+
+static void failure_todo(void)
+{
+#ifdef SFEX_TESTING	
+	exit(EXIT_FAILURE);
+#else
+	/*execl("/usr/sbin/crm_resource", "crm_resource", "-F", "-r", rsc_id, "-H", nodename, NULL); */
+	int ret;
+
+	cl_log(LOG_INFO, "Force reboot node %s\n", nodename);
+	ret = write(sysrq_fd, "b\n", 2);
+	if (ret == -1) {
+		cl_log(LOG_ERR, "%s\n", strerror(errno));
+	}
+	close(sysrq_fd);
+	exit(EXIT_FAILURE);
+#endif
+}
+
+static void update_lock(void)
+{
+	/* read lock data */
+	if (read_lockdata(&cdata, &ldata, lock_index) == -1) {
+		cl_log(LOG_ERR, "read_lockdata failed in update_lock\n");
+		error_todo();
+		exit(EXIT_FAILURE);
+	}
+
+	/* check current lock status */
+	/* if own node is not locking, lock update is failed */
+	if (ldata.status != SFEX_STATUS_LOCK || strncmp((const char*)(ldata.nodename), nodename, sizeof(ldata.nodename))) {
+		cl_log(LOG_ERR, "can't update lock.\n");
+		failure_todo();
+		exit(EXIT_FAILURE); 
+	}
+
+	/* lock update */
+	ldata.count = SFEX_NEXT_COUNT(ldata.count);
+	if (write_lockdata(&cdata, &ldata, lock_index) == -1) {
+		cl_log(LOG_ERR, "write_lockdata failed in update_lock\n");
+		error_todo();
+		exit(EXIT_FAILURE);
+	}
+}
+
+static void release_lock(void)
+{
+	/* The only thing I care about in release_lock(), is to terminate the process */
+	   
+	/* read lock data */
+	if (read_lockdata(&cdata, &ldata, lock_index) == -1) {
+		cl_log(LOG_ERR, "read_lockdata failed in release_lock\n");
+		exit(EXIT_FAILURE);
+	}
+
+	/* check current lock status */
+	/* if own node is not locking, we judge that lock has been released already */
+	if (ldata.status != SFEX_STATUS_LOCK || strncmp((const char*)(ldata.nodename), nodename, sizeof(ldata.nodename))) {
+		cl_log(LOG_ERR, "lock was already released.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	/* lock release */
+	ldata.status = SFEX_STATUS_UNLOCK;
+	if (write_lockdata(&cdata, &ldata, lock_index) == -1) {
+	    /*FIXME: We are going to self-stop */
+		cl_log(LOG_ERR, "write_lockdata failed in release_lock\n");
+		exit(EXIT_FAILURE);
+	}
+	cl_log(LOG_INFO, "lock released\n");
+}
+
+static void quit_handler(int signo, siginfo_t *info, void *context)
+{
+	cl_log(LOG_INFO, "quit_handler called. now releasing lock\n");
+	release_lock();
+	cl_log(LOG_INFO, "Shutdown sfex_daemon with EXIT_SUCCESS\n");
+	exit(EXIT_SUCCESS);
+}
+
+int main(int argc, char *argv[])
+{	
+
+	int ret;
+
+	progname = get_progname(argv[0]);
+	nodename = get_nodename();
+
+	cl_log_set_entity(progname);
+	cl_log_set_facility(HA_LOG_FACILITY);
+	cl_inherit_logging_environment(0);
+
+	/* read command line option */
+	opterr = 0;
+	while (1) {
+		int c = getopt(argc, argv, "hi:c:t:m:n:r:");
+		if (c == -1)
+			break;
+		switch (c) {
+			case 'h':           /* help*/
+				usage(stdout);
+				exit(EXIT_SUCCESS);
+			case 'i':           /* -i <index> */
+				{
+					unsigned long l = strtoul(optarg, NULL, 10);
+					if (l < SFEX_MIN_NUMLOCKS || l > SFEX_MAX_NUMLOCKS) {
+						cl_log(LOG_ERR, 
+								"index %s is out of range or invalid. it must be integer value between %lu and %lu.\n",
+								optarg,
+								(unsigned long)SFEX_MIN_NUMLOCKS,
+								(unsigned long)SFEX_MAX_NUMLOCKS);
+						exit(4);
+					}
+					lock_index = l;
+				}
+				break;
+			case 'c':           /* -c <collision_timeout> */
+				{
+					unsigned long l = strtoul(optarg, NULL, 10);
+					if (l < 1 || l > INT_MAX) {
+						cl_log(LOG_ERR, 
+								"collision_timeout %s is out of range or invalid. it must be integer value between %lu and %lu.\n",
+								optarg,
+								(unsigned long)1,
+								(unsigned long)INT_MAX);
+						exit(4);
+					}
+					collision_timeout = l;
+				}
+				break;
+			case 'm':  			/* -m <monitor_interval> */
+				{
+					unsigned long l = strtoul(optarg, NULL, 10);
+					if (l < 1 || l > INT_MAX) {
+						cl_log(LOG_ERR, 
+								"monitor_interval %s is out of range or invalid. it must be integer value between %lu and %lu.\n",
+								optarg,
+								(unsigned long)1,
+								(unsigned long)INT_MAX);
+						exit(4);
+					}
+					monitor_interval = l;
+				}
+				break;	
+			case 't':           /* -t <lock_timeout> */
+				{
+					unsigned long l = strtoul(optarg, NULL, 10);
+					if (l < 1 || l > INT_MAX) {
+						cl_log(LOG_ERR, 
+								"lock_timeout %s is out of range or invalid. it must be integer value between %lu and %lu.\n",
+								optarg,
+								(unsigned long)1,
+								(unsigned long)INT_MAX);
+						exit(4);
+					}
+					lock_timeout = l;
+				}
+				break;
+			case 'n':
+				{
+					free(nodename);
+					if (strlen(optarg) > SFEX_MAX_NODENAME) {
+						cl_log(LOG_ERR, "nodename %s is too long. must be less than %d byte.\n",
+								optarg,
+								(unsigned int)SFEX_MAX_NODENAME);
+						exit(EXIT_FAILURE);
+					}
+					nodename = strdup(optarg);
+				}	
+				break;
+			case 'r':
+				{
+					rsc_id = strdup(optarg);
+				}
+				break;
+			case '?':           /* error */
+				usage(stderr);
+				exit(4);
+		}
+	}
+	/* check parameter except the option */
+	if (optind >= argc) {
+		cl_log(LOG_ERR, "no device specified.\n");
+		usage(stderr);
+		exit(EXIT_FAILURE);
+	} else if (optind + 1 < argc) {
+		cl_log(LOG_ERR, "too many arguments.\n");
+		usage(stderr);
+		exit(EXIT_FAILURE);
+	}
+	device = argv[optind];
+
+	prepare_lock(device);
+#if !SFEX_TESTING
+	sysrq_fd = open("/proc/sysrq-trigger", O_WRONLY);
+	if (sysrq_fd == -1) {
+		cl_log(LOG_ERR, "failed to open /proc/sysrq-trigger due to %s\n", strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+#endif
+
+	ret = lock_index_check(&cdata, lock_index);
+	if (ret == -1)
+		exit(EXIT_FAILURE);
+
+	{
+		struct sigaction sig_act;
+		sigemptyset (&sig_act.sa_mask);
+		sig_act.sa_flags = SA_SIGINFO;
+
+		sig_act.sa_sigaction = quit_handler;
+		ret = sigaction(SIGTERM, &sig_act, NULL);
+		if (ret == -1) {
+			cl_log(LOG_ERR, "sigaction failed\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	cl_log(LOG_INFO, "Starting SFeX Daemon...\n");
+	
+	/* acquire lock first.*/
+	acquire_lock();
+
+	if (daemon(0, 1) != 0) {
+		cl_perror("%s::%d: daemon() failed.", __FUNCTION__, __LINE__);
+		release_lock();
+		exit(EXIT_FAILURE);
+	}
+
+	cl_make_realtime(-1, -1, 128, 128);
+	
+	cl_log(LOG_INFO, "SFeX Daemon started.\n");
+	while (1) {
+		sleep (monitor_interval);
+		update_lock();
+	}
+}
diff --git a/tools/sfex_init.8 b/tools/sfex_init.8
new file mode 100644
index 0000000..bdcf8b9
--- /dev/null
+++ b/tools/sfex_init.8
@@ -0,0 +1,19 @@
+.TH SFEX_INIT "8" "May 2010" "sfex_init 1.0.3" "System Administration Utilities"
+.SH NAME
+sfex_init \- Part of the Linux-HA project
+.SH SYNOPSIS
+.B sfex_init
+[\fI-Lh\fR] \fR[\fI-n numlocks\fR]\fI device
+.SH DESCRIPTION
+Initialize Shared Disk File EXclusiveness Control Program (SF-EX) meta-data.
+.SH OPTIONS
+.TP
+\fB\-n\fR numlocks
+The number of storing lock data is specified by integer 
+of one or more. When you want to control two or more resources by one 
+meta-data, you set the value of two or more to numlocks.
+Default is 1.
+.TP
+\fBdevice\fR
+This is file path which stored meta-data.
+It is usually expressed in "/dev/...", because it is partition on the shared disk.
diff --git a/tools/sfex_init.c b/tools/sfex_init.c
new file mode 100644
index 0000000..fed24dd
--- /dev/null
+++ b/tools/sfex_init.c
@@ -0,0 +1,177 @@
+/*-------------------------------------------------------------------------
+ *
+ * Shared Disk File EXclusiveness Control Program(SF-EX)
+ *
+ * sfex_init.c --- Initialize SF-EX meta-data.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  
+ * 02110-1301, USA.
+ *
+ * Copyright (c) 2007 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+ *
+ * $Id$
+ *
+ *-------------------------------------------------------------------------
+ *
+ * sfex_init [-b <blocksize>] [-n <numlocks>] <device>
+ *
+ * -b <blocksize> --- The size of the block is specified by the number of 
+ * bytes. In general, to prevent a partial writing to the disk, the size 
+ * of block is set to 512 bytes etc. 
+ * Note a set value because this value is used also for the alignment 
+ * adjustment in the input-output buffer in the program when direct I/O 
+ * is used(When you specify --enable-directio option for configure script). 
+ * (In Linux kernel 2.6, "direct I/O " does not work if this value is not 
+ * a multiple of 512.) Default is 512 bytes.
+ *
+ * -n <numlocks> --- The number of storing lock data is specified by integer 
+ * of one or more. When you want to control two or more resources by one 
+ * meta-data, you set the value of two or more to numlocks. A necessary disk 
+ * area for meta data are (blocksize*(1+numlocks))bytes. Default is 1.
+ *
+ * <device> --- This is file path which stored meta-data. It is usually 
+ * expressed in "/dev/...", because it is partition on the shared disk.
+ *
+ * exit code --- 0 - Normal end. 3 - Error occurs while processing it. 
+ * The content of the error is displayed into stderr. 4 - The mistake is 
+ * found in the command line parameter.
+ *
+ *-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "sfex.h"
+#include "sfex_lib.h"
+
+const char *progname;
+char *nodename;
+
+/*
+ * usage --- display command line syntax
+ *
+ * display command line syntax. By the purpose, it can specify destination 
+ * stream. stdout or stderr is set usually.
+ *
+ * dist --- destination stream of the command line syntax, such as stderr.
+ *
+ * return value --- void
+ */
+static void usage(FILE *dist) {
+  fprintf(dist, "usage: %s [-n <numlocks>] <device>\n", progname);
+}
+
+/*
+ * main --- main function
+ *
+ * entry point of sfex_init command.
+ *
+ * exit code --- 0 - Normal end. 3 - Error occurs while processing it. 
+ * The content of the error is displayed into stderr. 4 - The mistake is 
+ * found in the command line parameter.
+ */
+int
+main(int argc, char *argv[]) {
+  sfex_controldata cdata;
+  sfex_lockdata ldata;
+
+  /* command line parameter */
+  int numlocks = 1;		/* default 1 locks  */
+  const char *device;
+
+  /*
+   *  startup process
+   */
+
+  /* get a program name */
+  progname = get_progname(argv[0]);
+
+  /* enable the cl_log output from the sfex library */
+  cl_log_set_entity(progname);
+  /* The cl_log is output only to the standard error output */
+  cl_log_enable_stderr(TRUE);
+
+  /* read command line option */
+  opterr = 0;
+  while (1) {
+    int c = getopt(argc, argv, "hn:");
+    if (c == -1)
+      break;
+    switch (c) {
+    case 'h':			/* help */
+      usage(stdout);
+      exit(0);
+    case 'n':			/* -n <numlocks> */
+      {
+	unsigned long l = strtoul(optarg, NULL, 10);
+	if (l < SFEX_MIN_NUMLOCKS || l > SFEX_MAX_NUMLOCKS) {
+	  fprintf(stderr,
+		  "%s: ERROR: numlocks %s is out of range or invalid. it must be integer value between %lu and %lu.\n",
+		  progname, optarg,
+		  (unsigned long)SFEX_MIN_NUMLOCKS,
+		  (unsigned long)SFEX_MAX_NUMLOCKS);
+	  exit(4);
+	}
+	numlocks = l;
+      }
+      break;
+    case '?':			/* error */
+      usage(stderr);
+      exit(4);
+    }
+  }
+
+  /* check parameter except the option */
+  if (optind >= argc) {
+    fprintf(stderr, "%s: ERROR: no device specified.\n", progname);
+    usage(stderr);
+    exit(4);
+  } else if (optind + 1 < argc) {
+    fprintf(stderr, "%s: ERROR: too many arguments.\n", progname);
+    usage(stderr);
+    exit(4);
+  }
+  device = argv[optind];
+
+  prepare_lock(device);
+
+  /* main processes start */
+
+  /* get a node name */
+  nodename = get_nodename();
+
+  /* create and control data and lock data */
+  init_controldata(&cdata, sector_size, numlocks);
+  init_lockdata(&ldata);
+
+  /* write out control data and lock data */
+  write_controldata(&cdata);
+  {
+    int index;
+    for (index = 1; index <= numlocks; index++)
+      if (write_lockdata(&cdata, &ldata, index) == -1) {
+        fprintf(stderr, "%s: ERROR: cannot write lock data (index=%d).\n",
+                progname, index);
+        exit(3);
+      }
+  }
+
+  exit(0);
+}
diff --git a/tools/sfex_lib.c b/tools/sfex_lib.c
new file mode 100644
index 0000000..47ce0d7
--- /dev/null
+++ b/tools/sfex_lib.c
@@ -0,0 +1,474 @@
+/*-------------------------------------------------------------------------
+ * 
+ * Shared Disk File EXclusiveness Control Program(SF-EX)
+ *
+ * sfex_lib.c --- Libraries for other SF-EX modules.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  
+ * 02110-1301, USA.
+ *
+ * Copyright (c) 2007 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+ *
+ * $Id$
+ *
+ *-------------------------------------------------------------------------*/
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#include <syslog.h>
+#include <linux/fs.h>
+
+#include "sfex.h"
+#include "sfex_lib.h"
+
+static void *locked_mem;
+static int dev_fd;
+unsigned long sector_size = 0;
+
+int
+prepare_lock (const char *device)
+{
+  int sec_tmp = 0;
+
+  do {
+    dev_fd = open (device, O_RDWR | O_DIRECT | O_SYNC);
+    if (dev_fd == -1) {
+      if (errno == EINTR || errno == EAGAIN)
+	continue;
+      cl_log(LOG_ERR, "can't open device %s: %s\n",
+		    device, strerror (errno));
+      exit (3);
+    }
+    break;
+  }
+  while (1);
+
+  ioctl(dev_fd, BLKSSZGET, &sec_tmp);
+  sector_size = (unsigned long)sec_tmp;
+  if (sector_size == 0) {
+	  cl_log(LOG_ERR, "Get sector size failed: %s\n", strerror(errno));
+	  exit(EXIT_FAILURE);
+  }
+
+  if (posix_memalign
+      ((void **) (&locked_mem), SFEX_ODIRECT_ALIGNMENT,
+       sector_size) != 0) {
+    cl_log(LOG_ERR, "Failed to allocate aligned memory\n");
+    exit (3);
+  }
+  memset (locked_mem, 0, sector_size);
+
+  return 0;
+}
+
+/*
+ * get_progname --- a program name
+ *
+ * We get program name from directory path. It does not include delimiter 
+ * characters. Return value is pointer that point string of program name. 
+ * We assume delimiter is '/'.
+ */
+const char *
+get_progname (const char *argv0)
+{
+  char *p;
+
+  p = strrchr (argv0, '/');
+  if (p)
+    return p + 1;
+  else
+    return argv0;
+}
+
+/*
+ * get_nodename --- get a node name(hostname)
+ *
+ * We get a node name by using uname(2) and return pointer of it.
+ * The error checks are done in this function. The caller does not have 
+ * to check return value.
+ */
+char *
+get_nodename (void)
+{
+  struct utsname u;
+  char *n;
+
+  if (uname (&u)) {
+    cl_log(LOG_ERR, "%s\n", strerror (errno));
+    exit (3);
+  }
+  if (strlen (u.nodename) > SFEX_MAX_NODENAME) {
+    cl_log(LOG_ERR,
+      "nodename %s is too long. must be less than %lu byte.\n",
+       u.nodename, (unsigned long)SFEX_MAX_NODENAME);
+    exit (3);
+  }
+  n = strdup (&u.nodename[0]);
+  if (!n) {
+    cl_log(LOG_ERR, "%s\n", strerror (errno));
+    exit (3);
+  }
+  return n;
+}
+
+/*
+ * init_controldata --- initialize control data
+ *
+ * We initialize each member of sfex_controldata structure.
+ */
+void
+init_controldata (sfex_controldata * cdata, size_t blocksize, int numlocks)
+{
+  memcpy (cdata->magic, SFEX_MAGIC, sizeof (cdata->magic));
+  cdata->version = SFEX_VERSION;
+  cdata->revision = SFEX_REVISION;
+  cdata->blocksize = blocksize;
+  cdata->numlocks = numlocks;
+}
+
+/*
+ * init_lockdata --- initialize lock data
+ *
+ * We initialize each member of sfex_lockdata structure.
+ */
+void
+init_lockdata (sfex_lockdata * ldata)
+{
+  ldata->status = SFEX_STATUS_UNLOCK;
+  ldata->count = 0;
+  ldata->nodename[0] = 0;
+}
+
+/*
+ * write_controldata --- write control data into file
+ *
+ * We write sfex_controldata struct into file. We open a file with 
+ * synchronization mode and write out control data.
+ *
+ * cdata --- pointer of control data
+ *
+ * device --- name of target file
+ */
+void
+write_controldata (const sfex_controldata * cdata)
+{
+  sfex_controldata_ondisk *block;
+  int fd;
+
+  block = (sfex_controldata_ondisk *) (locked_mem);
+
+  /* We write control data into the buffer with given format. */
+  /* We write the offset value of each field of the control data directly.
+   * Because a point using this value is limited to two places, we do not 
+   * use macro. If you change the following offset values, you must change 
+   * values in the read_controldata() function.
+   */
+  memset (block, 0, cdata->blocksize);
+  memcpy (block->magic, cdata->magic, sizeof (block->magic));
+  snprintf ((char *) (block->version), sizeof (block->version), "%d",
+	    cdata->version);
+  snprintf ((char *) (block->revision), sizeof (block->revision), "%d",
+	    cdata->revision);
+  snprintf ((char *) (block->blocksize), sizeof (block->blocksize), "%u",
+	    (unsigned)cdata->blocksize);
+  snprintf ((char *) (block->numlocks), sizeof (block->numlocks), "%d",
+	    cdata->numlocks);
+
+  fd = dev_fd;
+  if (lseek (fd, 0, SEEK_SET) == -1) {
+    cl_log(LOG_ERR, "can't seek file pointer: %s\n",
+		  strerror (errno));
+    exit (3);
+  }
+
+  /* write buffer into a file  */
+  do {
+	  ssize_t s = write (fd, block, cdata->blocksize);
+	  if (s == -1) {
+		  if (errno == EINTR || errno == EAGAIN)
+			  continue;
+		  cl_log(LOG_ERR, "can't write meta-data: %s\n",
+				strerror (errno));
+		  exit (3);
+	  }
+	  else
+		  break;
+  }
+  while (1);
+}
+
+/*
+ * write_lockdata --- write lock data into file
+ *
+ * We write sfex_lockdata into file and seek file pointer to the given
+ * position of lock data.
+ *
+ * cdata --- pointer for control data
+ *
+ * ldata --- pointer for lock data
+ *
+ * device --- file name for write
+ *
+ * index --- index number for lock data. 1 origine.
+ */
+int
+write_lockdata (const sfex_controldata * cdata, const sfex_lockdata * ldata,
+		int index)
+{
+  sfex_lockdata_ondisk *block;
+  int fd;
+
+  block = (sfex_lockdata_ondisk *) locked_mem;
+  /* We write lock data into buffer with given format */
+  /* We write the offset value of each field of the control data directly.
+   * Because a point using this value is limited to two places, we do not 
+   * use macro. If you chage the following offset values, you must change 
+   * values in the read_lockdata() function.
+   */
+  memset (block, 0, cdata->blocksize);
+  block->status = ldata->status;
+  snprintf ((char *) (block->count), sizeof (block->count), "%d",
+	    ldata->count);
+  snprintf ((char *) (block->nodename), sizeof (block->nodename), "%s",
+	    ldata->nodename);
+
+  fd = dev_fd;
+
+  /* seek a file pointer to given position */
+  if (lseek (fd, cdata->blocksize * index, SEEK_SET) == -1) {
+    cl_log(LOG_ERR, "can't seek file pointer: %s\n",
+		  strerror (errno));
+    return -1;
+  }
+
+  /* write buffer into file */
+  do {
+    ssize_t s = write (fd, block, cdata->blocksize);
+    if (s == -1) {
+      if (errno == EINTR || errno == EAGAIN)
+	continue;
+      cl_log(LOG_ERR, "can't write meta-data: %s\n",
+		    strerror (errno));
+      return -1;
+    }
+    else if (s != cdata->blocksize) {
+      /* if writing atomically failed, this process is error */
+      cl_log(LOG_ERR, "can't write meta-data atomically.\n");
+      return -1;
+    }
+    break;
+  }
+  while (1);
+  return 0;
+}
+
+/*
+ * read_controldata --- read control data from file
+ *
+ * read sfex_controldata structure from file.
+ *
+ * cdata --- pointer for control data
+ *
+ * device --- file name for reading
+ */
+int
+read_controldata (sfex_controldata * cdata)
+{
+  sfex_controldata_ondisk *block;
+
+  block = (sfex_controldata_ondisk *) (locked_mem);
+
+  if (lseek (dev_fd, 0, SEEK_SET) == -1) {
+    cl_log(LOG_ERR, "can't seek file pointer: %s\n",
+		  strerror (errno));
+    return -1;
+  }
+
+  /* read data from file */
+  do {
+	  ssize_t s = read (dev_fd, block, sector_size);
+	  if (s == -1) {
+		  if (errno == EINTR || errno == EAGAIN)
+			  continue;
+		  cl_log(LOG_ERR,
+			  "can't read controldata meta-data: %s\n",
+			   strerror (errno));
+		  return -1;
+	  }
+	  else
+		  break;
+  } while (1);
+
+  /* read control data from buffer */
+  /* 1. check the magic number.  2. check null terminator of each field 
+     3. check the version number.  4. Unmuch of revision number is allowed  */
+  /* We write the offset value of each field of the control data directly.
+   * Because a point using this value is limited to two places, we do not 
+   * use macro. If you chage the following offset values, you must change 
+   * values in the write_controldata() function.
+   */
+  memcpy (cdata->magic, block->magic, 4);
+  if (memcmp (cdata->magic, SFEX_MAGIC, sizeof (cdata->magic))) {
+    cl_log(LOG_ERR, "magic number mismatched. %c%c%c%c <-> %s\n", block->magic[0], block->magic[1], block->magic[2], block->magic[3], SFEX_MAGIC);
+    return -1;
+  }
+  if (block->version[sizeof (block->version)-1]
+      || block->revision[sizeof (block->revision)-1]
+      || block->blocksize[sizeof (block->blocksize)-1]
+      || block->numlocks[sizeof (block->numlocks)-1]) {
+    cl_log(LOG_ERR, "control data format error.\n");
+    return -1;
+  }
+  cdata->version = atoi ((char *) (block->version));
+  if (cdata->version != SFEX_VERSION) {
+    cl_log(LOG_ERR,
+      "version number mismatched. program is %d, data is %d.\n",
+       SFEX_VERSION, cdata->version);
+    return -1;
+  }
+  cdata->revision = atoi ((char *) (block->revision));
+  cdata->blocksize = atoi ((char *) (block->blocksize));
+  cdata->numlocks = atoi ((char *) (block->numlocks));
+
+  return 0;
+}
+
+/*
+ * read_lockdata --- read lock data from file
+ *
+ * read sfex_lockdata from file and seek file pointer to head position of the 
+ * file.
+ *
+ * cdata --- pointer for control data
+ *
+ * ldata --- pointer for lock data. Read lock data are stored into this 
+ * pointed area.
+ *
+ * device --- file name of source file
+ *
+ * index --- index number. 1 origin.
+ */
+int
+read_lockdata (const sfex_controldata * cdata, sfex_lockdata * ldata,
+	       int index)
+{
+  sfex_lockdata_ondisk *block;
+  int fd;
+
+  block = (sfex_lockdata_ondisk *) (locked_mem);
+
+  fd = dev_fd;
+
+  /* seek a file pointer to given position */
+  if (lseek (fd, cdata->blocksize * index, SEEK_SET) == -1) {
+    cl_log(LOG_ERR, "can't seek file pointer: %s\n",
+		  strerror (errno));
+    return -1;
+  }
+
+  /* read from file */
+  do {
+    ssize_t s = read (fd, block, cdata->blocksize);
+    if (s == -1) {
+      if (errno == EINTR || errno == EAGAIN)
+	continue;
+      cl_log(LOG_ERR, "can't read lockdata meta-data: %s\n",
+		    strerror (errno));
+      return -1;
+    }
+    else if (s != cdata->blocksize) {
+      cl_log(LOG_ERR, "can't read meta-data atomically.\n");
+      return -1;
+    }
+    break;
+  }
+  while (1);
+
+  /* read control data form buffer */
+  /* 1. check null terminator of each field 2. check the status */
+  /* We write the offset value of each field of the control data directly.
+   * Because a point using this value is limited to two places, we do not 
+   * use macro. If you chage the following offset values, you must change 
+   * values in the write_lockdata() function.
+   */
+  if (block->count[sizeof(block->count)-1] || block->nodename[sizeof(block->nodename)-1]) {
+    cl_log(LOG_ERR, "lock data format error.\n");
+    return -1;
+  }
+  ldata->status = block->status;
+  if (ldata->status != SFEX_STATUS_UNLOCK
+      && ldata->status != SFEX_STATUS_LOCK) {
+    cl_log(LOG_ERR, "lock data format error.\n");
+    return -1;
+  }
+  ldata->count = atoi ((char *) (block->count));
+  strncpy ((char *) (ldata->nodename), (const char *) (block->nodename), sizeof(block->nodename));
+
+#ifdef SFEX_DEBUG
+  cl_log(LOG_INFO, "status: %c\n", ldata->status);
+  cl_log(LOG_INFO, "count: %d\n", ldata->count);
+  cl_log(LOG_INFO, "nodename: %s\n", ldata->nodename);
+#endif
+  return 0;
+}
+
+/*
+ * lock_index_check --- check the value of index
+ *
+ * The lock_index_check function checks whether the value of index exceeds
+ * the number of lock data on the shared disk.
+ *
+ * cdata --- pointer for control data
+ *
+ * index --- index number
+ */
+int
+lock_index_check(sfex_controldata * cdata, int index)
+{
+        if (read_controldata(cdata) == -1) {
+                cl_log(LOG_ERR, "%s\n", "read_controldata failed in lock_index_check");
+                return -1;
+        }
+#ifdef SFEX_DEBUG
+        cl_log(LOG_INFO, "version: %d\n", cdata->version);
+        cl_log(LOG_INFO, "revision: %d\n", cdata->revision);
+        cl_log(LOG_INFO, "blocksize: %d\n", cdata->blocksize);
+        cl_log(LOG_INFO, "numlocks: %d\n", cdata->numlocks);
+#endif
+
+        if (index > cdata->numlocks) {
+                cl_log(LOG_ERR, "index %d is too large. %d locks are stored.\n",
+                                index, cdata->numlocks);
+                return -1;
+        }
+
+        if (cdata->blocksize != sector_size) {
+                cl_log(LOG_ERR, "sector_size is not the same as the blocksize.\n");
+                return -1;
+        }
+        return 0;
+}
diff --git a/tools/sfex_lib.h b/tools/sfex_lib.h
new file mode 100644
index 0000000..f71281f
--- /dev/null
+++ b/tools/sfex_lib.h
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------
+ *
+ * Shared Disk File EXclusiveness Control Program(SF-EX)
+ *
+ * sfex_lib.h --- Prototypes for lib.c.
+ * 
+ * Copyright (c) 2007 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+ * 
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  
+ * 02110-1301, USA.
+ * 
+ * $Id$
+ *
+ *-------------------------------------------------------------------------*/
+
+#ifndef LIB_H
+#define LIB_H
+
+const char *get_progname(const char *argv0);
+char *get_nodename(void);
+void init_controldata(sfex_controldata *cdata, size_t blocksize, int numlocks);
+void init_lockdata(sfex_lockdata *ldata);
+void write_controldata(const sfex_controldata *cdata);
+int write_lockdata(const sfex_controldata *cdata, const sfex_lockdata *ldata, int index);
+int read_controldata(sfex_controldata *cdata);
+int read_lockdata(const sfex_controldata *cdata, sfex_lockdata *ldata, int index);
+int prepare_lock(const char *device);
+int lock_index_check(sfex_controldata * cdata, int index);
+
+#endif /* LIB_H */
diff --git a/tools/sfex_stat.c b/tools/sfex_stat.c
new file mode 100644
index 0000000..8be679c
--- /dev/null
+++ b/tools/sfex_stat.c
@@ -0,0 +1,218 @@
+/*-------------------------------------------------------------------------
+ *
+ * Shared Disk File EXclusiveness Control Program(SF-EX)
+ *
+ * sfex_stat.c --- Display lock status. This is a part of the SF-EX.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  
+ * 02110-1301, USA.
+ *
+ * Copyright (c) 2007 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+ *
+ * $Id$
+ *
+ *-------------------------------------------------------------------------
+ *
+ * sfex_stat [-i <index>] <device>
+ *
+ * -i <index> --- The index is number of the resource that display the lock.
+ * This number is specified by the integer of one or more. When two or more 
+ * resources are exclusively controlled by one meta-data, this option is used. 
+ * Default is 1.
+ *
+ * <device> --- This is file path which stored meta-data. It is usually 
+ * expressed in "/dev/...", because it is partition on the shared disk.
+ *
+ * exit code --- 0 - Normal end. Own node is holding lock. 2 - Normal 
+ * end. Own node does not hold a lock. 3 - Error occurs while processing 
+ * it. The content of the error is displayed into stderr. 4 - The mistake 
+ * is found in the command line parameter.
+ *
+ *-------------------------------------------------------------------------*/
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#if HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+#include "sfex.h"
+#include "sfex_lib.h"
+
+const char *progname;
+char *nodename;
+
+void print_controldata(const sfex_controldata *cdata);
+void print_lockdata(const sfex_lockdata *ldata, int index);
+
+/*
+ * print_controldata --- print sfex control data to the display
+ *
+ * print sfex_controldata to the display.
+ *
+ * cdata --- pointer for control data
+ */
+void
+print_controldata(const sfex_controldata *cdata)
+{
+  printf("control data:\n");
+  printf("  magic: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+         cdata->magic[0], cdata->magic[1], cdata->magic[2], cdata->magic[3]);
+  printf("  version: %d\n", cdata->version);
+  printf("  revision: %d\n", cdata->revision);
+  printf("  blocksize: %d\n", (int)cdata->blocksize);
+  printf("  numlocks: %d\n", cdata->numlocks);
+}
+
+/*
+ * print_lockdata --- print sfex lock data to the display
+ *
+ * print sfex_lockdata to the display.
+ *
+ * ldata --- pointer for lock data
+ *
+ * index --- index number
+ */
+void
+print_lockdata(const sfex_lockdata *ldata, int index)
+{
+  printf("lock data #%d:\n", index);
+  printf("  status: %s\n", ldata->status == SFEX_STATUS_UNLOCK ? "unlock" : "lock");
+  printf("  count: %d\n", ldata->count);
+  printf("  nodename: %s\n",ldata->nodename);
+}
+
+/*
+ * usage --- display command line syntax
+ *
+ * display command line syntax. By the purpose, it can specify destination 
+ * stream. stdout or stderr is set usually.
+ *
+ * dist --- destination stream of the command line syntax, such as stderr.
+ *
+ * retrun value --- void
+ */
+static void usage(FILE *dist) {
+  fprintf(dist, "usage: %s [-i <index>] <device>\n", progname);
+}
+
+/*
+ * main --- main function
+ *
+ * entry point of sfex_stat command.
+ *
+ * exit code --- 0 - Normal end. Own node is holding lock. 2 - Normal 
+ * end. Own node dose not hold a lock. 3 - Error occurs while processing 
+ * it. The content of the error is displayed into stderr. 4 - The mistake 
+ * is found in the command line parameter.
+ */
+int
+main(int argc, char *argv[]) {
+  sfex_controldata cdata;
+  sfex_lockdata ldata;
+  int ret = 0;
+
+  /* command line parameter */
+  int index = 1;		/* default 1st lock */
+  const char *device;
+
+  /*
+   * startup process
+   */
+
+  /* get a program name */
+  progname = get_progname(argv[0]);
+
+  /* enable the cl_log output from the sfex library */
+  cl_log_set_entity(progname);
+  /* The cl_log is output only to the standard error output */
+  cl_log_enable_stderr(TRUE);
+
+  /* read command line option */
+  opterr = 0;
+  while (1) {
+    int c = getopt(argc, argv, "hi:");
+    if (c == -1)
+      break;
+    switch (c) {
+    case 'h':			/* help */
+      usage(stdout);
+      exit(0);
+    case 'i':			/* -i <index> */
+      {
+	unsigned long l = strtoul(optarg, NULL, 10);
+	if (l < SFEX_MIN_NUMLOCKS || l > SFEX_MAX_NUMLOCKS) {
+	  fprintf(stderr,
+		  "%s: ERROR: index %s is out of range or invalid. it must be integer value between %lu and %lu.\n",
+		  progname, optarg,
+		  (unsigned long)SFEX_MIN_NUMLOCKS,
+		  (unsigned long)SFEX_MAX_NUMLOCKS);
+	  exit(4);
+	}
+	index = l;
+      }
+      break;
+    case '?':			/* error */
+      usage(stderr);
+      exit(4);
+    }
+  }
+
+  /* check parameter except the option */
+  if (optind >= argc) {
+    fprintf(stderr, "%s: ERROR: no device specified.\n", progname);
+    usage(stderr);
+    exit(4);
+  } else if (optind + 1 < argc) {
+    fprintf(stderr, "%s: ERROR: too many arguments.\n", progname);
+    usage(stderr);
+    exit(4);
+  }
+  device = argv[optind];
+
+  /*
+   * main processes start 
+   */
+
+  /* get a node name */
+  nodename = get_nodename();
+
+  prepare_lock(device);
+
+  ret = lock_index_check(&cdata, index);
+  if (ret == -1)
+    exit(EXIT_FAILURE);
+
+  /* read lock data */
+  read_lockdata(&cdata, &ldata, index);
+
+  /* display status */
+  print_controldata(&cdata);
+  print_lockdata(&ldata, index);
+
+  /* check current lock status */
+  if (ldata.status != SFEX_STATUS_LOCK || strcmp(ldata.nodename, nodename)) {
+    fprintf(stdout, "status is UNLOCKED.\n");
+    exit(2);
+  } else {
+    fprintf(stdout, "status is LOCKED.\n");
+    exit(0);
+  }
+}
diff --git a/tools/test-findif.sh b/tools/test-findif.sh
new file mode 100755
index 0000000..1eb9d5d
--- /dev/null
+++ b/tools/test-findif.sh
@@ -0,0 +1,352 @@
+#!/bin/sh
+
+# Easy peasy test for findif, configuration via direct edit...
+# Jan Pokorny <jpokorny at redhat.com>
+
+export LC_ALL=C
+test -n "$BASH_VERSION" && set -o posix
+set -u
+COLOR=0
+if [ -t 1 ] && echo -e foo | grep -Eqv "^-e"; then
+	COLOR=1
+else
+	COLOR=0
+fi
+ok () {
+	[ $COLOR -eq 1 ] \
+	    && echo -en "[\033[32m OK \033[0m]" \
+	    || echo -n "[ OK ]"
+	echo " $*"
+}
+fail () {
+	[ $COLOR -eq 1 ] \
+	    && echo -en "[\033[31mFAIL\033[0m]" \
+	    || echo -n "[FAIL]"
+	echo " $*"
+}
+info () {
+	[ $COLOR -eq 1 ] \
+	    && echo -e "\033[34m$@\033[0m" \
+	    || echo "$*"
+}
+die() { echo "$*"; exit 255; }
+warn() { echo "> $*"; }
+mimic_return () { return $1; }
+verbosely () { echo "$1..."; $1; }
+
+HERE="$(dirname "$0")"
+. "${HERE}/../heartbeat/ocf-returncodes"  # obtain OCF_ERR_CONFIGURED et al.
+
+#
+# soft-config
+#
+
+: ${DEBUG_IN:=0}
+: ${DEBUG_OUT:=0}
+
+: "${PRG:=${HERE}/findif}"
+: "${SCRIPT:=${HERE}/../heartbeat/findif.sh}"
+
+: ${LO_IF:=lo}
+: ${LO_IP4:=127.0.0.1}
+: ${LO_NM4:=8}
+: ${LO_BC4:=127.255.255.255}
+: ${LO_IP6:=::1}
+
+: ${DUMMY_IF:=dummy0}
+# carefully selected to fit TEST-NET-2
+# http://en.wikipedia.org/wiki/Reserved_IP_addresses#Reserved_IPv4_addresses
+: ${DUMMY_IP4:=198.51.100.1}
+: ${DUMMY_NM4:=24}
+: ${DUMMY_BC4:=198.51.100.255}
+
+: ${DUMMY_IP6:=2001:db8::1}
+: ${DUMMY_NM6:=32}
+: ${DUMMY_BC6:=198.51.100.255}
+
+#
+# hard-wired
+#
+
+PRG_CMD="${PRG} -C"
+SCRIPT_CMD="$(head -n1 "${SCRIPT}" | sed 's|#!||') \
+	-c \"export OCF_FUNCTIONS_DIR=$(dirname "${SCRIPT}"); . $(dirname "${SCRIPT}")/ocf-shellfuncs; . ${SCRIPT}; findif\""
+
+DUMMY_USER=test-findif
+
+LO_IP4_13=${LO_IP4%.[0-9]*}
+LO_IP4_4=${LO_IP4##[0-9][0-9]*.}
+LO_IP4_INC=${LO_IP4_13}.$((LO_IP4_4 + 1))
+
+DUMMY_IP4_13=${DUMMY_IP4%.[0-9]*}
+DUMMY_IP4_4=${DUMMY_IP4##[0-9][0-9]*.}
+DUMMY_IP4_INC=${DUMMY_IP4_13}.$((DUMMY_IP4_4 + 1))
+
+DUMMY_IP6_17=${DUMMY_IP6%:[0-9A-Fa-f:][0-9A-Fa-f:]*}
+DUMMY_IP6_8=${DUMMY_IP6##[0-9A-Fa-f][0-9A-Fa-f]*:}
+DUMMY_IP6_INC=${DUMMY_IP6_17}::$((DUMMY_IP6_8 + 1))
+
+#
+# command-line config
+#
+
+CMD="${PRG_CMD}"
+TESTS="4"
+
+#
+# test declarations
+#
+
+TEST_FORMAT=\
+"   OCF_RESKEY_ip	, OCF_RESKEY_cidr_netmask	, expected_ec		, expected_dev	, expected_nm		, expected_bc"
+
+TEST_DATA4=\
+"   # valid: 1-9: loopback, 10-19: dummy if; invalid cases: 20-29: ip, 30-39: netmask bits
+    #  1) LO4_IP
+    ${LO_IP4}		, 				, $OCF_SUCCESS		, ${LO_IF}	, ${LO_NM4}	, ${LO_BC4}
+    #  2) LO4_IP+1
+    ${LO_IP4_INC}	, 				, $OCF_SUCCESS		, ${LO_IF}	, ${LO_NM4}	, ${LO_BC4}
+    #
+    # 10) DUMMY4_IP+1
+    ${DUMMY_IP4_INC}	, 				, $OCF_SUCCESS		, ${DUMMY_IF}	, ${DUMMY_NM4}	, ${DUMMY_BC4}
+    # 11) DUMMY4_IP+1, explicit netmask
+    ${DUMMY_IP4_INC}	, ${DUMMY_NM4}			, $OCF_SUCCESS		, ${DUMMY_IF}	, ${DUMMY_NM4}	, ${DUMMY_BC4}
+    #
+    # 20) *invalid* IPv4 (missing last item in quad)
+    ${DUMMY_IP4_13}.	,				, $OCF_ERR_CONFIGURED	, NA		, NA		, NA
+    # 21) *invalid* IP (random string)
+    foobar		,				, $OCF_ERR_CONFIGURED	, NA		, NA		, NA
+    #
+    # 30) DUMMY4_IP+1, explicit *invalid* netmask (33)
+    ${DUMMY_IP4_INC}	, 33				, $OCF_ERR_CONFIGURED	, NA		, NA		, NA
+    # 31) DUMMY4_IP+1, explicit *invalid* netmask (-1)
+    ${DUMMY_IP4_INC}	, -1				, $OCF_ERR_CONFIGURED	, NA		, NA		, NA
+    # 32) DUMMY4_IP+1, explicit *invalid* netmask (random string)
+    ${DUMMY_IP4_INC}	, foobar			, $OCF_ERR_CONFIGURED	, NA		, NA		, NA
+"
+
+TEST_DATA6=\
+"   # valid: A0-A9: loopback, B0-B9: dummy if; invalid cases: C0-C9: ip, D0-D9: netmask bits
+    # A0) LO6_IP
+    ${LO_IP6}		, 				, $OCF_SUCCESS		, ${LO_IF}	, ${LO_NM4}	,
+    #
+    # B0) DUMMY6_IP+1
+    ${DUMMY_IP6_INC}	, 				, $OCF_SUCCESS		, ${DUMMY_IF}	, ${DUMMY_NM6}	,
+    # B1) DUMMY4_IP+1, explicit netmask
+    ${DUMMY_IP6_INC}	, ${DUMMY_NM6}			, $OCF_SUCCESS		, ${DUMMY_IF}	, ${DUMMY_NM6}	,
+"
+
+#
+# private routines
+#
+
+_get_test_field () {
+	echo "$1" | cut -s -d, -f$2 | sed 's|^ \?\(.*[^ ]\) \?$|\1|g'
+}
+
+#
+# public routines
+#
+
+setup () {
+	if [ "$(uname -o)" != "GNU/Linux" ]; then
+		die "Only tested with Linux, feel free to edit the condition."
+	fi
+
+	if [ "${CMD}" = "${PRG_CMD}" ]; then
+		[ -x "${PRG}" ] || die "Forgot to compile ${PRG} for me to test?"
+	fi
+
+	if [ $(id -u) -ne 0 ]; then
+		die "Due to (unobtrusive) juggling with routing, run as root."
+	fi
+
+	if ! useradd -M ${DUMMY_USER} 2>/dev/null; then
+		if ! getent passwd ${DUMMY_USER} >/dev/null; then
+			die "Cannot add user ${DUMMY_USER} for testing purposes."
+		fi
+		warn "User ${DUMMY_USER} already exists, be careful not" \
+		     " to confirm its removal."
+	fi
+
+	if lsmod | grep -Eq "^dummy[ ]+"; then
+		warn "Looks like you already use dummy network device."
+	else
+		modprobe dummy || die "No dummy kernel module (per name) at hand."
+	fi
+
+	#if ! ifconfig ${DUMMY_IF} ${DUMMY_IP4}/${DUMMY_NM4}; then
+	#if ! ip addr add ${DUMMY_IP4}/${DUMMY_NM4} broadcast + dev ${DUMMY_IF}; then
+	if ! ip addr add ${DUMMY_IP4}/${DUMMY_NM4} dev ${DUMMY_IF}; then
+		die "Cannot add IPv4 address (${DUMMY_IP4}/${DUMMY_NM4}) to ${DUMMY_IF}."
+	fi
+
+	# TODO: IPv6 support check first, disabling 6'ish tests if negative?
+	if ! ip addr add ${DUMMY_IP6}/${DUMMY_NM6} dev ${DUMMY_IF}; then
+		die "Cannot add IPv6 address (${DUMMY_IP6}/${DUMMY_NM6}) to ${DUMMY_IF}."
+	fi
+
+	if ! ip link set ${DUMMY_IF} up; then
+		die "Cannot bring ${DUMMY_IF} up."
+	fi
+}
+
+teardown () {
+	while true; do
+		echo -n "Remove user ${DUMMY_USER}? [y/n] "
+		case $(read l < /dev/tty; echo "${l}") in
+		n)
+			break
+			;;
+		y)
+			[ "${DUMMY_USER}" = "$(whoami)" ] && break
+			userdel ${DUMMY_USER} || warn "Cannot kick user ${DUMMY_USER} out."
+			break
+			;;
+		esac
+	done
+
+	rmmod dummy || warn "Cannot kick dummy kernel module out."
+}
+
+proceed () {
+	err_cnt=0
+	(for test in ${TESTS}; do eval "echo \"\${TEST_DATA${test}}\""; done
+	tty 2>&1 >/dev/null || cat | sed 's|^\(.*\)$|# stdin: \1\n\1|') \
+	  | while read curline; do
+		if echo "${curline}" | grep -Eqv -e '^[ \t]*#' -e '^$'; then
+			err_this=0
+			curline="$(echo "${curline}" | tr '\t' ' ' | tr -s ' ')"
+			info "$(echo "${lastline}" | sed 's|^#|------|')"
+
+			ip="$(     _get_test_field "${curline}" 1)"
+			[ -z "${ip}" ]      &&  die "test spec.: empty ip"
+			mask="$(   _get_test_field "${curline}" 2)"
+			[ -z "${mask}" ]    && warn "test spec.: empty mask"
+			exp_ec="$( _get_test_field "${curline}" 3)"
+			[ -z "${exp_ec}" ]  && warn "test spec.: empty exp_ec"
+			exp_dev="$(_get_test_field "${curline}" 4)"
+			[ -z "${exp_dev}" ] && warn "test spec.: empty exp_dev"
+			exp_nm="$( _get_test_field "${curline}" 5)"
+			[ -z "${exp_nm}" ]  && warn "test spec.: empty exp_nm"
+			exp_bc="$( _get_test_field "${curline}" 6)"
+			[ -z "${exp_bc}" ]  && warn "test spec.: empty exp_bc"
+			[ $DEBUG_IN -ne 0 ] \
+			    && echo "${ip}, ${mask}, ${exp_ec}, ${exp_dev}, ${exp_nm}, ${exp_bc}"
+
+			env="OCF_RESKEY_ip=${ip} OCF_RESKEY_cidr_netmask=${mask}"
+			echo "${env}"
+			res="$(su ${DUMMY_USER} -c "${env} ${CMD} 2>&1")"
+			got_ec=$?
+
+			if [ ${got_ec} -ne ${exp_ec} ]; then
+				warn "FAIL exit code: ${got_ec} vs ${exp_ec}"
+				err_this=$((err_this+1))
+			fi
+
+			res="$(echo "${res}" | tr '\t' ' ' | tr -s ' ')"
+
+			res_check=
+			stop=0
+			echo "${res}" | while read res_line && [ $stop -eq 0 ]; do
+				echo "${res_line}" | grep -Eq "^[0-9A-Za-z_-]+ netmask [0-9]"
+				if [ $? -ne 0 ]; then
+					if [ -z "${res_line}" ] || echo "${res_line}" \
+					  | grep -Fq "Copyright Alan Robertson"; then
+						# findif finishes w/ (C)+usage on failure
+						stop=1
+					else
+						echo "${res_line}"
+					fi
+				elif [ -n "${res_check}" ]; then
+					warn "More than one line with results."
+					stop=1
+				else
+					res_check=${res_line}
+					got_dev="$(echo "${res_check}" | cut -d' ' -f1)"
+					got_nm="$(echo "${res_check}"  | cut -d' ' -f3)"
+					got_bc="$(echo "${res_check}"  | cut -d' ' -f5)"
+					[ ${DEBUG_OUT} -ne 0 ] \
+					    && echo "${got_dev}, ${got_nm}, ${got_bc}"
+
+					if [ "${got_dev}" != "${exp_dev}" ]; then
+						warn "FAIL device: ${got_dev} vs ${exp_dev}"
+						err_this=$((err_this+1))
+					fi
+					if [ "${got_nm}" != "${exp_nm}" ]; then
+						warn "FAIL netmask: ${got_nm} vs ${exp_nm}"
+						err_this=$((err_this+1))
+					fi
+					if [ "${got_bc}" != "${exp_bc}" ]; then
+						warn "FAIL broadcast: ${got_bc} vs ${exp_bc}"
+						err_this=$((err_this+1))
+					fi
+				fi
+
+				mimic_return ${err_this}  # workaround separate process limitation
+			done
+
+			err_this=$?
+			if [ ${err_this} -eq 0 ]; then
+				ok
+			else
+				fail
+				err_cnt=$((err_cnt+1))
+			fi
+		fi
+		lastline="${curline}"
+		mimic_return ${err_cnt}  # workaround separate process limitation
+	done
+	err_cnt=$?
+
+	echo "--- TOTAL ---"
+	[ $err_cnt -eq 0 ] && ok || fail $err_cnt
+	return $err_cnt
+}
+
+if [ $# -ge 1 ]; then
+	while true; do
+		case $1 in
+		-script)
+			CMD="${SCRIPT_CMD}"
+			[ $# -eq 1 ] && break
+			;;
+		--)
+			TESTS=
+			[ $# -eq 1 ] && break
+			;;
+		-4)
+			TESTS="4"
+			[ $# -eq 1 ] && break
+			;;
+		-6)
+			TESTS="6"
+			[ $# -eq 1 ] && break
+			;;
+		-46)
+			TESTS="4 6"
+			[ $# -eq 1 ] && break
+			;;
+		setup|proceed|teardown)
+			verbosely $1
+			ret=$?
+			[ $ret -ne 0 ] && exit $ret
+			;;
+		*)
+			echo "usage: ./$0 [-script] [--|-4|-6|-46] (setup,proceed,teardown)"
+			echo "additional tests may be piped to standard input, format:"
+			echo "${TEST_FORMAT}" | tr '\t' ' ' | tr -s ' '
+			exit 0
+			;;
+		esac
+		[ $# -eq 1 ] && exit 0
+		shift
+	done
+fi
+
+verbosely setup
+verbosely proceed
+ret=$?
+verbosely teardown
+
+exit $ret
diff --git a/tools/tickle_tcp.c b/tools/tickle_tcp.c
new file mode 100644
index 0000000..cf0bdcb
--- /dev/null
+++ b/tools/tickle_tcp.c
@@ -0,0 +1,379 @@
+/* 
+   Tickle TCP connections tool
+
+   Author:	Jiaju Zhang
+   Based on the code in CTDB http://ctdb.samba.org/ written by
+   Andrew Tridgell and Ronnie Sahlberg
+
+   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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#define discard_const(ptr) ((void *)((intptr_t)(ptr)))
+
+typedef union {
+	struct sockaddr     sa;
+	struct sockaddr_in  ip;
+	struct sockaddr_in6 ip6;
+} sock_addr;
+
+uint32_t uint16_checksum(uint16_t *data, size_t n);
+void set_nonblocking(int fd);
+void set_close_on_exec(int fd);
+static int parse_ipv4(const char *s, unsigned port, struct sockaddr_in *sin);
+static int parse_ipv6(const char *s, const char *iface, unsigned port, sock_addr *saddr);
+int parse_ip(const char *addr, const char *iface, unsigned port, sock_addr *saddr);
+int parse_ip_port(const char *addr, sock_addr *saddr);
+int send_tickle_ack(const sock_addr *dst, 
+		    const sock_addr *src, 
+		    uint32_t seq, uint32_t ack, int rst);
+static void usage(void);
+
+uint32_t uint16_checksum(uint16_t *data, size_t n)
+{
+	uint32_t sum=0;
+	while (n >= 2) {
+		sum += (uint32_t)ntohs(*data);
+		data++;        
+		n -= 2;
+	}                      
+	if (n == 1) {
+		sum += (uint32_t)ntohs(*(uint8_t *)data);
+	}
+	return sum;
+}       
+
+static uint16_t tcp_checksum(uint16_t *data, size_t n, struct iphdr *ip)
+{
+	uint32_t sum = uint16_checksum(data, n);
+	uint16_t sum2;
+	sum += uint16_checksum((uint16_t *)(void *)&ip->saddr,
+				sizeof(ip->saddr));
+	sum += uint16_checksum((uint16_t *)(void *)&ip->daddr,
+				sizeof(ip->daddr));
+	sum += ip->protocol + n;
+	sum = (sum & 0xFFFF) + (sum >> 16);
+	sum = (sum & 0xFFFF) + (sum >> 16);
+	sum2 = htons(sum);
+	sum2 = ~sum2;
+	if (sum2 == 0) {
+		return 0xFFFF;
+	}
+	return sum2;
+}
+
+static uint16_t tcp_checksum6(uint16_t *data, size_t n, struct ip6_hdr *ip6)
+{
+	uint32_t phdr[2];
+	uint32_t sum = 0;
+	uint16_t sum2;
+
+	sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_src, 16);
+	sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_dst, 16);
+
+	phdr[0] = htonl(n);
+	phdr[1] = htonl(ip6->ip6_nxt);
+	sum += uint16_checksum((uint16_t *)phdr, 8);
+
+	sum += uint16_checksum(data, n);
+
+	sum = (sum & 0xFFFF) + (sum >> 16);
+	sum = (sum & 0xFFFF) + (sum >> 16);
+	sum2 = htons(sum);
+	sum2 = ~sum2;
+	if (sum2 == 0) {
+		return 0xFFFF;
+	}
+	return sum2;
+}
+
+void set_nonblocking(int fd)
+{
+	unsigned v;
+	v = fcntl(fd, F_GETFL, 0);
+	fcntl(fd, F_SETFL, v | O_NONBLOCK);
+}
+
+void set_close_on_exec(int fd) 
+{               
+	unsigned v;
+	v = fcntl(fd, F_GETFD, 0);
+	fcntl(fd, F_SETFD, v | FD_CLOEXEC);
+}
+
+static int parse_ipv4(const char *s, unsigned port, struct sockaddr_in *sin)
+{
+	sin->sin_family = AF_INET;
+	sin->sin_port   = htons(port);
+
+	if (inet_pton(AF_INET, s, &sin->sin_addr) != 1) {
+		fprintf(stderr, "Failed to translate %s into sin_addr\n", s);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int parse_ipv6(const char *s, const char *iface, unsigned port, sock_addr *saddr)
+{
+	saddr->ip6.sin6_family   = AF_INET6;
+	saddr->ip6.sin6_port     = htons(port);
+	saddr->ip6.sin6_flowinfo = 0;
+	saddr->ip6.sin6_scope_id = 0;
+
+	if (inet_pton(AF_INET6, s, &saddr->ip6.sin6_addr) != 1) {
+		fprintf(stderr, "Failed to translate %s into sin6_addr\n", s);
+		return -1;
+	}
+
+	if (iface && IN6_IS_ADDR_LINKLOCAL(&saddr->ip6.sin6_addr)) {
+		saddr->ip6.sin6_scope_id = if_nametoindex(iface);
+	}
+
+        return 0;
+}
+
+int parse_ip(const char *addr, const char *iface, unsigned port, sock_addr *saddr)
+{
+	char *p;
+	int ret;
+
+	p = index(addr, ':');
+	if (!p)
+		ret = parse_ipv4(addr, port, &saddr->ip);
+	else
+		ret = parse_ipv6(addr, iface, port, saddr);
+
+	return ret;
+}
+
+int parse_ip_port(const char *addr, sock_addr *saddr)
+{
+	char *s, *p;
+	unsigned port;
+	char *endp = NULL;
+	int ret;
+
+	s = strdup(addr);
+	if (!s) {
+		fprintf(stderr, "Failed strdup()\n");
+		return -1;
+	}
+
+	p = rindex(s, ':');
+	if (!p) {
+		fprintf(stderr, "This addr: %s does not contain a port number\n", s);
+		free(s);
+		return -1;
+	}
+	
+	port = strtoul(p+1, &endp, 10);
+	if (!endp || *endp != 0) {
+		fprintf(stderr, "Trailing garbage after the port in %s\n", s);
+		free(s);
+		return -1;
+	}
+	*p = 0;
+
+	ret = parse_ip(s, NULL, port, saddr);
+	free(s);
+	return ret;
+}
+
+int send_tickle_ack(const sock_addr *dst, 
+		    const sock_addr *src, 
+		    uint32_t seq, uint32_t ack, int rst)
+{
+	int s;
+	int ret;
+	uint32_t one = 1;
+	uint16_t tmpport;
+	sock_addr *tmpdest;
+	struct {
+		struct iphdr ip;
+		struct tcphdr tcp;
+	} ip4pkt;
+	struct {
+		struct ip6_hdr ip6;
+		struct tcphdr tcp;
+	} ip6pkt;
+
+	switch (src->ip.sin_family) {
+	case AF_INET:
+		memset(&ip4pkt, 0, sizeof(ip4pkt));
+		ip4pkt.ip.version  = 4;
+		ip4pkt.ip.ihl      = sizeof(ip4pkt.ip)/4;
+		ip4pkt.ip.tot_len  = htons(sizeof(ip4pkt));
+		ip4pkt.ip.ttl      = 255;
+		ip4pkt.ip.protocol = IPPROTO_TCP;
+		ip4pkt.ip.saddr    = src->ip.sin_addr.s_addr;
+		ip4pkt.ip.daddr    = dst->ip.sin_addr.s_addr;
+		ip4pkt.ip.check    = 0;
+
+		ip4pkt.tcp.source  = src->ip.sin_port;
+		ip4pkt.tcp.dest    = dst->ip.sin_port;
+		ip4pkt.tcp.seq     = seq;
+		ip4pkt.tcp.ack_seq = ack;
+		ip4pkt.tcp.ack     = 1;
+		if (rst)
+			ip4pkt.tcp.rst = 1;
+		ip4pkt.tcp.doff    = sizeof(ip4pkt.tcp)/4;
+		ip4pkt.tcp.window   = htons(1234);
+		ip4pkt.tcp.check    = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
+
+		s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+		if (s == -1) {
+			fprintf(stderr, "Failed to open raw socket (%s)\n", strerror(errno));
+			return -1;
+		}
+
+		ret = setsockopt(s, SOL_IP, IP_HDRINCL, &one, sizeof(one));
+		if (ret != 0) {
+			fprintf(stderr, "Failed to setup IP headers (%s)\n", strerror(errno));
+			close(s);
+			return -1;
+		}
+
+		set_nonblocking(s);
+		set_close_on_exec(s);
+
+		ret = sendto(s, &ip4pkt, sizeof(ip4pkt), 0, 
+			     (const struct sockaddr *)&dst->ip, sizeof(dst->ip));
+		close(s);
+		if (ret != sizeof(ip4pkt)) {
+			fprintf(stderr, "Failed sendto (%s)\n", strerror(errno));
+			return -1;
+		}
+		break;
+
+        case AF_INET6:
+		memset(&ip6pkt, 0, sizeof(ip6pkt));
+		ip6pkt.ip6.ip6_vfc  = 0x60;
+		ip6pkt.ip6.ip6_plen = htons(20);
+		ip6pkt.ip6.ip6_nxt  = IPPROTO_TCP;
+		ip6pkt.ip6.ip6_hlim = 64;
+		ip6pkt.ip6.ip6_src  = src->ip6.sin6_addr;
+		ip6pkt.ip6.ip6_dst  = dst->ip6.sin6_addr;
+
+		ip6pkt.tcp.source   = src->ip6.sin6_port;
+		ip6pkt.tcp.dest     = dst->ip6.sin6_port;
+		ip6pkt.tcp.seq      = seq;
+		ip6pkt.tcp.ack_seq  = ack;
+		ip6pkt.tcp.ack      = 1;
+		if (rst)
+			ip6pkt.tcp.rst      = 1;
+		ip6pkt.tcp.doff     = sizeof(ip6pkt.tcp)/4;
+		ip6pkt.tcp.window   = htons(1234);
+		ip6pkt.tcp.check    = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
+
+		s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
+		if (s == -1) {
+			fprintf(stderr, "Failed to open sending socket\n");
+			return -1;
+                }
+
+		tmpdest = discard_const(dst);
+		tmpport = tmpdest->ip6.sin6_port;
+
+		tmpdest->ip6.sin6_port = 0;
+		ret = sendto(s, &ip6pkt, sizeof(ip6pkt), 0, (const struct sockaddr *)&dst->ip6, sizeof(dst->ip6));
+		tmpdest->ip6.sin6_port = tmpport;
+		close(s);
+
+		if (ret != sizeof(ip6pkt)) {
+			fprintf(stderr, "Failed sendto (%s)\n", strerror(errno));
+			return -1;
+		}
+		break;
+
+	default:
+		fprintf(stderr, "Not an ipv4/v6 address\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void usage(void)
+{
+	printf("Usage: /usr/lib/heartbeat/tickle_tcp [ -n num ]\n");
+	printf("Please note that this program need to read the list of\n");
+	printf("{local_ip:port remote_ip:port} from stdin.\n");
+	exit(1);
+}
+
+#define OPTION_STRING "n:h"
+
+int main(int argc, char *argv[])
+{
+	int optchar, i, num = 1, cont = 1;
+	sock_addr src, dst;
+	char addrline[128], addr1[64], addr2[64];
+
+	while(cont) {
+		optchar = getopt(argc, argv, OPTION_STRING);
+		switch(optchar) {
+		case 'n':
+			num = atoi(optarg);
+			break;
+		case 'h':
+			usage();
+			exit(EXIT_SUCCESS);
+			break;
+		case EOF:
+			cont = 0;
+			break;
+		default:
+			fprintf(stderr, "unknown option, please use '-h' for usage.\n");
+			exit(EXIT_FAILURE);
+			break;
+		};
+	}
+
+	while(fgets(addrline, sizeof(addrline), stdin)) {
+		sscanf(addrline, "%s %s", addr1, addr2);
+
+		if (parse_ip_port(addr1, &src)) {
+			fprintf(stderr, "Bad IP:port '%s'\n", addr1);
+			return -1;
+		}
+		if (parse_ip_port(addr2, &dst)) {
+			fprintf(stderr, "Bad IP:port '%s'\n", addr2);
+			return -1;
+		}
+	
+		for (i = 1; i <= num; i++) {
+			if (send_tickle_ack(&dst, &src, 0, 0, 0)) {
+				fprintf(stderr, "Error while sending tickle ack from '%s' to '%s'\n",
+					addr1, addr2);
+				return -1;
+			}
+		}
+
+	}
+	return 0;
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-ha/resource-agents.git



More information about the Debian-HA-Commits mailing list