diff --git a/configure.in b/configure.in index 24bdab1b6..57a1a984b 100644 --- a/configure.in +++ b/configure.in @@ -1,2997 +1,2999 @@ dnl dnl autoconf for heartbeat dnl Started by David Lee December 2000 dnl automake stuff dnl added by Michael Moerz February 2001 dnl dnl License: GNU General Public License (GPL) dnl Initialiase, with sanity check of a unique file in the hierarchy AC_INIT(heartbeat.spec.in) AC_PREREQ(2.53) AC_CONFIG_AUX_DIR(.) AC_REVISION($Revision: 1.552 $) dnl cvs revision 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/hb_config.h dnl - Contains a subset of defines checked here dnl - Manually edit include/hb_config.h.in to have configure include dnl new defines dnl - Should not include HAVE_* defines dnl - Safe to include anywhere AM_CONFIG_HEADER(include/config.h include/hb_config.h) ALL_LINGUAS="en fr" AC_ARG_WITH(hapkgversion, [ --with-hapkgversion=name Override package version (if you're a packager needing to pretend) ], [ HAPKGVERSION="$withval" ], [ HAPKGVERSION="" ], ) if test -z "$HAPKGVERSION" ; then HAPKGVERSION="2.1.1" fi AM_INIT_AUTOMAKE(heartbeat, $HAPKGVERSION) RPMREL=1 AC_SUBST(RPMREL) HB_PKG=heartbeat AC_SUBST(HB_PKG) DISTDIR=$HB_PKG-$VERSION TARFILE=$DISTDIR.tar.gz AC_SUBST(DISTDIR) AC_SUBST(TARFILE) CC_IN_CONFIGURE=yes export CC_IN_CONFIGURE INIT_EXT="" USE_MODULES=0 echo Our Host OS: $host_os/$host 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". pf_argv_set="" case "$host_os" in *bsd*) LIBS="-L/usr/local/lib" CPPFLAGS="$CPPFLAGS -I/usr/local/include" INIT_EXT=".sh" REBOOT_OPTIONS="-f" POWEROFF_OPTIONS="-f" ;; *solaris*) pf_argv_set="PF_ARGV_NONE" REBOOT_OPTIONS="-n" POWEROFF_OPTIONS="-n" ;; *linux*) USE_MODULES=1 REBOOT_OPTIONS="-nf" POWEROFF_OPTIONS="-nf" ;; dnl anything? darwin*) AC_DEFINE_UNQUOTED(ON_DARWIN, 1, Compiling for Darwin platform) LIBS="$LIBS -L${prefix}/lib" CFLAGS="$CFLAGS -I${prefix}/include" REBOOT_OPTIONS="-f" POWEROFF_OPTIONS="-f" ;; esac AC_SUBST(INIT_EXT) AC_SUBST(USE_MODULES) AC_SUBST(REBOOT_OPTIONS) AC_SUBST(POWEROFF_OPTIONS) AC_DEFINE_UNQUOTED(REBOOT_OPTIONS, "$REBOOT_OPTIONS", reboot options) AC_DEFINE_UNQUOTED(POWEROFF_OPTIONS, "$POWEROFF_OPTIONS", poweroff options) dnl Info for building/packaging systems. dnl dnl "pkg" (typically Solaris) generally suggests package names of the form: dnl COMPname dnl where: dnl COMP: (upper case) resembles a four character company "stock ticker"; dnl name: (lower case) is short-form (few character) product name. dnl dnl It is also conventional for the name to be closely related to the dnl installation location, typically "/opt/COMPname". dnl dnl See "linux-ha-dev" discussion, "heartbeat package name", from 12/Oct/2005. dnl "LXHAhb" seems the least evil compromise for a default. dnl Any site or packager may, of course, override this. dnl AC_ARG_WITH(pkgname, [ --with-pkgname=name name for pkg (typically for Solaris) ], [ PKGNAME="$withval" ], [ PKGNAME="LXHAhb" ], ) AC_SUBST(PKGNAME) MISSINGTHINGS="" MISSINGOPTIONALS="" FatalMissingThing() { if test X"$MISSINGTHINGS" = X; then MISSINGTHINGS="$MISSINGTHINGS $1" else MISSINGTHINGS="$MISSINGTHINGS, $1" fi shift AC_MSG_RESULT(configure: ERROR: $1 ====================) shift for j in "$@" do if test "X$j" != X-; then AC_MSG_RESULT(configure: $j ==) fi done } WarnMissingThing() { if test X"$MISSINGOPTIONALS" = X; then MISSINGOPTIONALS="$MISSINGOPTIONALS $1" else MISSINGOPTIONALS="$MISSINGOPTIONALS, $1" fi shift AC_MSG_RESULT(configure: WARNING: $1 ====================) shift for j in "$@" do if test "X$j" != X-; then AC_MSG_RESULT(configure: $j ==) fi done } CheckMissingThings() { if test "X$MISSINGOPTIONALS" != "X" then AC_MSG_WARN(The following recommended components noted earlier are missing: $MISSINGOPTIONALS We will continue but you may have lost some non-critical functionality.) fi if test "X$MISSINGTHINGS" != "X" then AC_MSG_ERROR(The following required components noted earlier are missing: $MISSINGTHINGS Please supply them and try again.) fi } dnl dnl dnl Don't ya just hate working around buggy code? dnl dnl At least code that doesn't do what you want... dnl dnl This is to make substitutions work right in RPM specfiles. dnl dnl Horms says "This is pretty ugly". dnl Alanr says: "It works. s/ ugly//" dnl dnl Patches are being accepted... dnl prefix=`eval echo "$prefix"` case $prefix in NONE) prefix=/usr/local;; esac var() { case $1 in *'${'*) res=`eval echo "$1"`;; *) res="$1";; esac case "$res" in ""|NONE) echo "$2";; *) echo "$res";; esac } dnl Keep copy of original (default) localstatedir localstatedir_orig="$localstatedir" exec_prefix=`var "$exec_prefix" "$prefix"` bindir=`var "$bindir" "$exec_prefix/bin"` sbindir=`var "$sbindir" "$exec_prefix/sbin"` datadir=`var "$datadir" "$prefix/share"` sysconfdir=`var "$sysconfdir" "$prefix/etc"` sharedstatedir=`var "$sharedstatedir" "$prefix/com"` localstatedir=`var "$localstatedir" "$prefix/var"` includedir=`var "$includedir" "$exec_prefix/include"` oldincludedir=`var "$oldincludedir" "$exec_prefix/include"` infodir=`var "$infodir" "$prefix/info"` mandir=`var "$mandir" "$exec_prefix/man"` docdir=${datadir}/doc/${HB_PKG}-${VERSION} libdir=`var "$libdir" "$exec_prefix/lib"` libexecdir=`var "$libexecdir" "$exec_prefix/libexec"` for var in libdir libexecdir do dir=`eval echo '${'${var}'}'` case $dir in *64) if test ! -d "$dir" then newdir=`echo "$dir" | sed 's%64$%%'` if test -d "$newdir" then eval $var="$newdir" AC_MSG_WARN([$var value now set to $newdir since $dir doesn't exist]) fi fi;; esac done for j in exec_prefix bindir sbindir datadir sysconfdir localstatedir \ includedir oldincludedir mandir docdir libdir do dirname=`eval echo '${'${j}'}'` if test ! -d "$dirname" then AC_MSG_WARN([$j directory ($dirname) does not exist!]) fi done dnl The GNU conventions for installation directories don't always dnl sit well with this software. In particular, GNU's stated: dnl dnl '$(localstatedir)' should normally be '/usr/local/var', ... dnl dnl is poor for us: much better would be somewhere under '/var'. dnl dnl Here within "configure" it would be poor practice for us to interfere dnl with such values, irrespective of our opinion: dnl 1. user perspective: we would have gone behind their back; dnl 2. autoconf perspective: autoconf should avoid any OS-specific mindset. dnl dnl So if localstatedir still has its default value, we issue an advisory dnl warning and inform folk of our own "ConfigureMe", which is ideally dnl suited for setting such aspects (by user, and per-OS). dnl dnl [ Another option would be to detect, and to warn of, (post-expansion) dnl non-"/var/[...]" values: something like: dnl if test `expr "$localstatedir" : '^/var/.*'` -ge '5' \ dnl -o `expr "$localstatedir" : '^/var.*'` -eq '4' dnl then else fi dnl ] # If original localstatedir had defaulted then sanity-check the result. if test "x$localstatedir_orig" = 'x${prefix}/var' # Note quote types then SNOOZING=10 AC_MSG_WARN(value/default "--localstatedir=$localstatedir" is poor.) AC_MSG_WARN("/var/something" is strongly recommended.) AC_MSG_WARN(We also recommend using "ConfigureMe".) AC_MSG_WARN(Sleeping for $SNOOZING seconds.) sleep $SNOOZING fi AC_DEFINE_UNQUOTED(HA_SYSCONFDIR, "$sysconfdir", Location of system configuration files) HA_URLBASE="http://linux-ha.org/" AC_SUBST(HA_URLBASE) AC_DEFINE_UNQUOTED(HA_URLBASE, "$HA_URLBASE", Web site base URL) HA_LIBDIR="${libdir}" AC_SUBST(HA_LIBDIR) AC_DEFINE_UNQUOTED(HA_LIBDIR,"$HA_LIBDIR", lib directory) HA_LIBHBDIR="$HA_LIBDIR/${HB_PKG}" AC_SUBST(HA_LIBHBDIR) AC_DEFINE_UNQUOTED(HA_LIBHBDIR,"$HA_LIBHBDIR", lib heartbeat directory) HA_VARRUNDIR="${localstatedir}/run" AC_SUBST(HA_VARRUNDIR) AC_DEFINE_UNQUOTED(HA_VARRUNDIR,"$HA_VARRUNDIR", var run directory) HA_VARRUNHBDIR="$HA_VARRUNDIR/${HB_PKG}" AC_SUBST(HA_VARRUNHBDIR) AC_DEFINE_UNQUOTED(HA_VARRUNHBDIR,"$HA_VARRUNHBDIR", var run heartbeat directory) HA_VARRUNHBRSCDIR="$HA_VARRUNHBDIR/rsctmp" AC_SUBST(HA_VARRUNHBRSCDIR) AC_DEFINE_UNQUOTED(HA_VARRUNHBRSCDIR,"$HA_VARRUNHBRSCDIR", var run heartbeat rsctmp directory) dnl Test the default first (priority) and last (to make sure some value is set) AC_MSG_CHECKING(for the location of the lock directory) for HA_VARLOCKDIR in ${localstatedir}/lock ${localstatedir}/spool/lock ${localstatedir}/spool/locks ${localstatedir}/lock do if test -d "$HA_VARLOCKDIR" then AC_MSG_RESULT($HA_VARLOCKDIR) break fi done AC_SUBST(HA_VARLOCKDIR) AC_DEFINE_UNQUOTED(HA_VARLOCKDIR,"$HA_VARLOCKDIR", System lock directory) HA_VARLIBDIR="${localstatedir}/lib" AC_SUBST(HA_VARLIBDIR) AC_DEFINE_UNQUOTED(HA_VARLIBDIR,"$HA_VARLIBDIR", var lib directory) HA_VARLIBHBDIR="${HA_VARLIBDIR}/${HB_PKG}" AC_SUBST(HA_VARLIBHBDIR) AC_DEFINE_UNQUOTED(HA_VARLIBHBDIR,"$HA_VARLIBHBDIR", var lib heartbeat directory) HA_COREDIR="${HA_VARLIBHBDIR}/cores" AC_SUBST(HA_COREDIR) AC_DEFINE_UNQUOTED(HA_COREDIR,"$HA_COREDIR", top directory of area to drop core files in) HA_LOGDAEMON_IPC="${HA_VARLIBDIR}/log_daemon" AC_SUBST(HA_LOGDAEMON_IPC) AC_DEFINE_UNQUOTED(HA_LOGDAEMON_IPC, "$HA_LOGDAEMON_IPC", Logging Daemon IPC socket name) dnl This IS a default but we should make sure we can override it for any dnl odd OS requirements. HA_VARLOGDIR="/var/log" AC_SUBST(HA_VARLOGDIR) AC_DEFINE_UNQUOTED(HA_VARLOGDIR,"$HA_VARLOGDIR", var log directory) STONITHPKG=stonith AC_SUBST(STONITHPKG) PILSPKG=pils AC_SUBST(PILSPKG) pils_includedir="${includedir}/${PILSPKG}" pils_plugindir="${libdir}/${PILSPKG}/plugins" stonith_includedir="${includedir}/${STONITHPKG}" stonith_plugindir="${libdir}/${STONITHPKG}/plugins" stonith_ext_plugindir="${stonith_plugindir}/external" base_includedir="${includedir}" saf_includedir="${includedir}/saf" AC_SUBST(pils_includedir) AC_SUBST(pils_plugindir) AC_SUBST(stonith_includedir) AC_SUBST(stonith_plugindir) AC_SUBST(stonith_ext_plugindir) AC_DEFINE_UNQUOTED(STONITH_EXT_PLUGINDIR, "$stonith_ext_plugindir", directory for the external stonith plugins) AC_SUBST(base_includedir) AC_SUBST(saf_includedir) AC_SUBST(docdir) # # Other interesting variables: ${host_vendor} and ${host_os} # sample values: suse linux # dnl We use this in the RPM specfile... AC_SUBST(ac_configure_args) dnl ************************************************************************* PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin" export PATH dnl checks for programs dnl dnl Which C compiler? dnl Defaults to GNU C compiler if available. dnl Always tries to set the compiler to ANSI C via options (AM) dnl Can force other with environment variable "CC". AC_PROG_CC AC_PROG_CC_STDC AC_PROG_YACC AC_DECL_YYTEXT AM_PROG_LEX AM_PATH_PYTHON AC_LIBTOOL_DLOPEN dnl Enable dlopen support... AC_LIBLTDL_CONVENIENCE dnl make libltdl a convenience lib AC_PROG_LIBTOOL dnl Replacing AC_PROG_LIBTOOL with AC_CHECK_PROG because LIBTOOL dnl was NOT being expanded all the time thus causing things to fail. AC_CHECK_PROGS(LIBTOOL, glibtool libtool libtool15 libtool13) AC_MSG_CHECKING(for glibtool or libtool*) if test x"${LIBTOOL}" = x""; then FatalMissingThing "libtool" "You need libtool to build heartbeat." \ "You can get the source from ftp://www.gnu.org/pub/gnu/" \ "or you can locate it via http://www.gnu.org/software/libtool" else AC_MSG_RESULT($LIBTOOL has been found.) fi AC_CHECK_PROGS(MAKE, gmake make) AC_MSG_CHECKING(for gmake or make) if test x"${MAKE}" = x""; then FatalMissingThing "gmake" "You need gmake to build heartbeat." \ "You can get the source from ftp://www.gnu.org/pub/gnu/" \ "or you can locate it via http://www.gnu.org/software/make/" else AC_MSG_RESULT($MAKE has been found.) fi AC_SYS_LARGEFILE AC_PATH_PROGS(HTML2TXT, lynx w3m) case $HTML2TXT in */*) ;; *) HTML2TXT="";; esac AC_PATH_PROGS(POD2MAN, pod2man, pod2man) AC_PATH_PROGS(ROUTE, route) AC_PATH_PROGS(RPM, rpmbuild) if test x"${RPM}" = x""; then AC_PATH_PROGS(RPM, rpm) fi AC_DEFINE_UNQUOTED(ROUTE, "$ROUTE", path to route command) AC_PATH_PROGS(NETSTAT, netstat, /sbin/netstat) AC_DEFINE_UNQUOTED(NETSTAT, "$NETSTAT", path to the netstat command) AC_PATH_PROGS(PING, ping, /bin/ping) AC_PATH_PROGS(IFCONFIG, ifconfig, /sbin/ifconfig) AC_PATH_PROGS(SSH, ssh, /usr/bin/ssh) AC_PATH_PROGS(SCP, scp, /usr/bin/scp) AC_PATH_PROGS(PYTHON, python) dnl - Determine which mail program exists. Mailx is Solaris AC_PATH_PROGS(MAILCMD, mail, mailx) AC_SUBST(MAILCMD) AC_DEFINE_UNQUOTED(IFCONFIG, "$IFCONFIG", path to the ifconfig command) AC_PATH_PROGS(BLOCKDEV, blockdev, /sbin/blockdev) AC_PATH_PROGS(BASENAME, basename, basename) AC_PATH_PROGS(FUSER, fuser, fuser) AC_PATH_PROGS(MOUNT, mount, mount) AC_PATH_PROGS(UMOUNT, umount, umount) AC_PATH_PROGS(FSCK, fsck, fsck) AC_PATH_PROGS(MODPROBE, modprobe, modprobe) AC_PATH_PROGS(RAIDSTART, raidstart, raidstart) AC_PATH_PROGS(RAIDSTOP, raidstop, raidstop) AC_PATH_PROGS(MDADM, mdadm, /sbin/mdadm) AC_PATH_PROGS(LIBNETCONFIG, libnet-config) AC_PATH_PROGS(GETENT, getent) AC_PATH_PROGS(IP2UTIL, ip, /sbin/ip) AC_PATH_PROGS(IPTABLES, iptables, /usr/sbin/iptables) AC_PATH_PROGS(XML2CONFIG, xml2-config) AC_PATH_PROGS(REBOOT, reboot, /sbin/reboot) AC_PATH_PROGS(POWEROFF_CMD, poweroff, /sbin/poweroff) AC_SUBST(REBOOT) AC_SUBST(POWEROFF_CMD) AC_DEFINE_UNQUOTED(REBOOT, "$REBOOT", path to the reboot command) AC_DEFINE_UNQUOTED(POWEROFF_CMD, "$POWEROFF_CMD", path to the poweroff command) dnl "whoami", if it exists, may be hidden away on some System-V (e.g. Solaris) AC_PATH_PROGS(WHOAMI, whoami, , ${PATH}:/usr/ucb) AC_PATH_PROGS(STRINGSCMD, strings) AC_DEFINE_UNQUOTED(STRINGSCMD, "$STRINGSCMD", path to strings command) AC_SUBST(STRINGSCMD) AC_PATH_PROGS(PERL, perl) AC_SUBST(PERL) AC_PATH_PROGS(SWIG, swig) AC_SUBST(SWIG) AC_PATH_PROGS(EGREP, egrep) AC_SUBST(EGREP) AC_PATH_PROGS(MSGFMT, msgfmt, [msgfmt not found],) AC_SUBST(MSGFMT) AC_PATH_PROGS(HG, hg, /usr/local/hg) AC_SUBST(HG) AC_PATH_PROGS(GZIP_PROG, gzip) AC_PATH_PROGS(TAR, tar) AC_PATH_PROGS(CP, cp) AC_PATH_PROGS(LS, ls) AC_PATH_PROGS(LN, ln) AC_PATH_PROGS(MD5, md5) AC_SUBST(GZIP_PROG) AC_SUBST(TAR) AC_SUBST(CP) AC_SUBST(LS) AC_SUBST(LN) AC_SUBST(MD5) dnl The "test" program can be different from the "sh" builtin. AC_PATH_PROGS(TEST, test) AC_PATH_PROGS(DRBDADM, drbdadm, /sbin/drbdadm) AC_PATH_PROGS(DRBDSETUP, drbdsetup, /sbin/drbdsetup) AC_PATH_PROGS(PKGCONFIG, pkg-config) dnl ************************************************************************ dnl Check whether non-root user can chown. dnl ************************************************************************ AC_PATH_PROGS(MKTEMP, mktemp) if test -n "$WHOAMI"; then IAM=`$WHOAMI` fi AC_MSG_CHECKING(if chown works for non-root) dnl Prefer "mktemp" command. But some OSes lack it; they can "touch". if test -n "$MKTEMP"; then F=`$MKTEMP "./.chown-testXXXXX"` else F="./.chown-test.$$" touch $F fi if case "$IAM" in root) chown nobody $F; su nobody -c "chown root $F";; *) chown root $F esac >/dev/null 2>&1 then nonroot_chown=yes AC_MSG_RESULT(yes) else nonroot_chown=no AC_MSG_RESULT(no) fi rm -f $F AM_CONDITIONAL(NONROOT_CHOWN, test "$nonroot_chown" = yes ) dnl ************************************************************************ dnl checks for libraries dnl Needed for libnet test. dnl ************************************************************************ AC_CHECK_LIB(nsl, t_open) dnl -lnsl AC_CHECK_LIB(socket, socket) dnl -lsocket AC_CHECK_LIB(posix4, sched_getscheduler) dnl -lposix4 AC_CHECK_LIB(c, dlopen) dnl if dlopen is in libc... AC_CHECK_LIB(dl, dlopen) dnl -ldl (for Linux) AC_CHECK_LIB(rt, sched_getscheduler) dnl -lrt (for Tru64) AC_CHECK_LIB(gnugetopt, getopt_long) dnl -lgnugetopt ( if available ) AC_CHECK_LIB(pam, pam_start) dnl -lpam (if available) # Not sure what OSes need this... Linux and AIX don't... # and AIX barfs on it... if test "$DLPREOPEN" = yes; then DLOPEN_FORCE_FLAGS="-dlpreopen force -dlopen-self" AC_DEFINE(DLPREOPEN, 1, [enable -dlpreopen flag]) else DLOPEN_FORCE_FLAGS="" fi AC_SUBST(DLOPEN_FORCE_FLAGS) dnl ************ uuid ********************** AC_ARG_WITH(uuid, [ --with-uuid=UUID mechanism for uuid {e2fsprogs|ossp|any|no} "e2fsprogs": e2fsprogs, typically Linux "ossp": not yet implemented "any": (default) any of the above, fallback to inbuilt "no": use inbuilt ], [ uuidimpl="$withval" ], [ uuidimpl="any" ], ) case $uuidimpl in e2fsprogs) AC_CHECK_LIB(uuid, uuid_parse,, AC_MSG_ERROR([e2fsprogs uuid library was explicitly requested but not found]) ) ;; ossp) AC_CHECK_LIB(uuid, uuid_create,, AC_MSG_ERROR([ossp uuid library was explicitly requested but not found]) ) ;; no) # Do not define anything; so use inbuilt (replace) implementation. ;; any) # Default: try to discover an implementation that we can use. AC_CHECK_LIB(uuid, uuid_parse) dnl e2fsprogs dnl AC_CHECK_LIB(uuid, uuid_create) dnl ossp ;; *) AC_MSG_ERROR([An invalid uuid library was explicitly requested]) ;; esac case "$host_os" in darwin*) dnl Recent Darwin versions do not need to link against a uuid library dnl Maybe this can be moved up into the previous block but it also might dnl break things (ie. the later check for uuid_parse) AC_CHECK_FUNCS(uuid_parse) esac AC_MSG_CHECKING(uuid implementation:) if test "$ac_cv_lib_uuid_uuid_parse" = yes; then AC_MSG_RESULT(e2fsprogs) elif test "$ac_cv_func_uuid_parse" = yes; then AC_MSG_RESULT(native) elif test "$ac_cv_lib_uuid_uuid_create" = yes; then AC_MSG_RESULT(ossp) AC_MSG_ERROR([heartbeat does not yet support ossp implementation of uuid]) else AC_MSG_RESULT(inbuilt) if test x"$uuidimpl" != x"no"; then WarnMissingThing "uuid library" \ "e2fsprogs uuid library is recommended" \ "On Linux this is the e2fsprogs-devel package" \ "See also http://sourceforge.net/projects/e2fsprogs/" fi fi dnl ************ uuid ********************** EXTRAGLIBMSG="-" if test "X${PKGCONFIG}" = "X"; then AC_MSG_RESULT(not found) FatalMissingThing "pkgconfig" "Package pkgconfig is required" \ "See http://pkgconfig.sourceforge.net/" EXTRALIBMSG="(this message might be bogus because pkgconfig is missing)" fi if test "x${enable_thread_safe}" = "xyes"; then GPKGNAME="gthread-2.0" else GPKGNAME="glib-2.0" fi if test "X${PKGCONFIG}" != "X" && $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 FatalMissingThing "glib2-devel" \ "Package glib2-devel is missing." \ "You can get the source from ftp://ftp.gtk.org/pub/gtk/" \ "or you can locate it via http://www.gtk.org/download/" "$EXTRALIBMSG" fi AC_MSG_RESULT(using $GLIBCONFIG) AC_MSG_CHECKING(which libnet version is installed) if test x"${LIBNETCONFIG}" = x""; then AC_MSG_RESULT(using old version of API) dnl The old version of the API REQUIRES $LIBNETCONFIG dnl so we can only deal with new API unless we have it. AC_CHECK_LIB(net, libnet_get_hwaddr, [], [FatalMissingThing "libnet" "You need libnet to continue." \ "You can get libnet from http://www.packetfactory.net/libnet" \ "Note that some RPMs split libnet up into libnet and libnet-devel." \ "In this case you have to install libnet-devel"]) LIBNETDEFINES="" LIBNETLIBS=" -lnet" 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 else LIBNETDEFINES="`$LIBNETCONFIG --defines` `$LIBNETCONFIG --cflags`"; LIBNETLIBS="`$LIBNETCONFIG --libs`"; AC_MSG_RESULT(using $LIBNETCONFIG) case $LIBNETLIBS in *-l*) libnet=`echo $LIBNETLIBS | sed 's%.*-l%%'`;; *) libnet=$LIBNETLIBS;; esac dnl Add any libnet definitions to the compiler flags. CPPFLAGS="$CPPFLAGS $LIBNETDEFINES" AC_CHECK_HEADERS(libnet.h) if test "$ac_cv_header_libnet_h" = no; then FatalMissingThing "libnet" "You need libnet (headers) to continue." \ "You can get libnet from http://www.packetfactory.net/libnet" \ "Note that some RPMs split libnet up into libnet and libnet-devel." \ "In this case you have to install libnet-devel" fi fi AC_SUBST(LIBNETDEFINES) AC_SUBST(LIBNETLIBS) 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_MSG_CHECKING(where is python installed) if test "x${PYTHON}" = x; then PYTHON="/usr/bin/env python"; fi AC_MSG_RESULT(using $PYTHON); AC_MSG_CHECKING(if netstat supports -f inet flag) $NETSTAT -rn -f inet > /dev/null 2>&1 if test x"$?" = x"0"; then AC_DEFINE(NETSTATPARM, "-rn -f inet ", parameters to netstat to retrieve route information) AC_MSG_RESULT(yes) else AC_DEFINE(NETSTATPARM, "-rn ", parameters to netstat to retrieve route information) AC_MSG_RESULT(no) fi if test X${PING} = X then FatalMissingThing "ping" "ping command is mandantory" fi dnl Determine if we use -w1 or -t1 for ping (in PYTHON Scripts) AC_MSG_CHECKING(ping option for timeout - w or t) for PING_TIMEOUT_OPT in "-w1" "-t1" do $PING -nq -c1 $PING_TIMEOUT_OPT localhost > /dev/null 2>&1 if test "$?" = 0 then AC_DEFINE_UNQUOTED(PING_TIMEOUT_OPT, "$PING_TIMEOUT_OPT", option for ping timeout) AC_MSG_RESULT($PING_TIMEOUT_OPT) break fi done AC_SUBST(PING_TIMEOUT_OPT) dnl Determining a route (particularly for "findif"). dnl There are various mechanisms on different systems. dnl Some mechanisms require root access to evaluate, but configure is often dnl (indeed, some say should be always) running non-root. dnl dnl Therefore much of the determination has to be run-time. dnl So the principle here, at configure time, is to explore what might be dnl available, and offer as much as possible to run-time. dnl AC_DEFINE(ROUTEPARM, "-n get", paramters for route to retrieve route information) AC_DEFINE(PROCROUTE, "/proc/net/route", path were to find route information in proc) 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) AC_SUBST(WHOAMI) AC_SUBST(HTML2TXT) AC_SUBST(POD2MAN) AC_SUBST(ROUTEPARM) AC_SUBST(PROCROUTE) dnl Locales check - is a real ugly workaround for now til I find dnl something more useful dnl dnl "Eric Z. Ayers" wrote: dnl > dnl > Here are some more data points: dnl > dnl > SUN: /usr/lib/locale/ dnl > HP : /usr/lib/nls/loc/ dnl > OSF: /usr/lib/nls/loc/ dnl > LINUX: /usr/share/locale/ dnl > UNIXWARE: /usr/lib/locale/ dnl > FREEBSD: /usr/share/locale dnl > VMS: just kidding dnl FindADir() { type="$1" whatfor="$2" shift; shift; AC_MSG_CHECKING(for $whatfor directory) for dir do if test -d "$dir" then AC_MSG_RESULT($dir) echo $dir return 0 fi done AC_MSG_RESULT(not found) return 1 } locale_locations="/usr/share/locale /usr/lib/locale /usr/lib/nls/loc" LOCALE=`FindADir error "locale" $locale_locations` if test "X$LOCALE" = X then FatalMissingThing "Locale directory" "Locale directory is mandantory." fi RPMDIR=`FindADir warn "RPM" /usr/src/packages /usr/src/redhat` if test x"${HAVE_LIBRT}" = x""; then LIBRT="" else LIBRT=-lrt fi AC_SUBST(LIBRT) # # Where is dlopen? # if test "$ac_cv_lib_c_dlopen" = yes; then LIBADD_DL="" elif test "$ac_cv_lib_dl_dlopen" = yes; then LIBADD_DL=-ldl else LIBADD_DL=${lt_cv_dlopen_libs} fi dnl dnl Check for location of gettext dnl dnl On at least Solaris 2.x, where it is in libc, specifying lintl causes dnl grief. Ensure minimal result, not the sum of all possibilities. dnl And do libc first. dnl Known examples: dnl c: Linux, Solaris 2.6+ dnl intl: BSD, AIX FunIsInLib() { fun=$1 lib=$2 lib_var1="ac_cv_lib_${lib}_$fun" lib_var2="ac_cv_lib_${lib}___$fun" for v in $lib_var1 $lib_var2 do var=`eval echo '${'${v}'}'` case $var in yes) return 0;; no) return 1;; esac done return 0 } for gt_test_lib in c intl do AC_CHECK_LIB($gt_test_lib, gettext) if FunIsInLib gettext $gt_test_lib; then break fi done # # Where is gettext()? # if FunIsInLib gettext c ; then LIBADD_INTL="" elif FunIsInLib gettext intl ; then LIBADD_INTL=-lintl elif test -f /usr/local/lib/libintl.so -a -s /usr/local/lib/libintl.so; then # This was added for FreeBSD LIBADD_INTL="-lintl" elif test -f /sw/lib/libintl.a -a -s /sw/lib/libintl.la -a -s /sw/lib/libintl.dylib; then # This was added for Darwin + Fink LIBADD_INTL="-lintl" else FatalMissingThing "gettext function" "no library providing gettext found" fi dnl dnl Glib allows its headers/libraries to be installed anywhere. dnl And they provide a command to let you know where they are. dnl This is nice, but having them in standard places is nice too ;-) dnl if test "X$GLIBCONFIG" != X; then AC_MSG_CHECKING(for special glib includes: ) GLIBHEAD=`$GLIBCONFIG --cflags` AC_MSG_RESULT($GLIBHEAD) CPPFLAGS="$CPPFLAGS $GLIBHEAD" AC_SUBST(GLIBHEAD) dnl Note: Not bundling "GLIBLIB" with general "LIBS". dnl 1. Only very few programs require GLIBLIB dnl (This isn't true anymore -- AlanR) dnl 2. Danger of creating run-time dependency on build-time LD_LIBRARY_PATH AC_MSG_CHECKING(for glib library flags) GLIBLIB=`$GLIBCONFIG --libs` AC_MSG_RESULT($GLIBLIB) AC_SUBST(GLIBLIB) fi dnl ************************************************************************ dnl checks for header files dnl dnl check for ANSI *.h files first dnl asm/page.h: Linux, for system PAGE_SIZE AC_HEADER_STDC AC_CHECK_HEADERS(db.h) AC_CHECK_HEADERS(asm/page.h) AC_CHECK_HEADERS(time.h) AC_CHECK_HEADERS(stdarg.h) AC_CHECK_HEADERS(tcpd.h) AC_CHECK_HEADERS(uuid.h) AC_CHECK_HEADERS(uuid/uuid.h) AC_CHECK_HEADERS(sys/param.h) AC_CHECK_HEADERS(netinet/in.h) AC_CHECK_HEADERS([stdint.h unistd.h]) AC_CHECK_HEADERS(sys/termios.h) AC_CHECK_HEADERS(termios.h) dnl ************************************************************************ dnl FreeBSD requires sys/param.h and in.h to compile test netinet headers. dnl ************************************************************************ if test "$ac_cv_header_sys_param_h" -a "$ac_cv_header_netinet_in_h" = no; then AC_CHECK_HEADERS(netinet/in_systm.h) AC_CHECK_HEADERS(netinet/ip.h) AC_CHECK_HEADERS(netinet/ip_var.h) AC_CHECK_HEADERS(netinet/ip_compat.h) AC_CHECK_HEADERS(netinet/ip_fw.h) else AC_CHECK_HEADERS(netinet/in_systm.h,[],[],[#include #include ]) if test "$ac_cv_header_in_systm_h" = no; then AC_CHECK_HEADERS(netinet/ip.h,[],[],[#include #include ]) else AC_CHECK_HEADERS(netinet/ip.h,[],[],[#include #include #include ]) fi AC_CHECK_HEADERS(netinet/ip_var.h,[],[],[#include #include ]) AC_CHECK_HEADERS(netinet/ip_compat.h,[],[],[#include #include ]) AC_CHECK_HEADERS(netinet/ip_fw.h,[],[],[#include #include ]) fi AC_CHECK_HEADERS(sys/sockio.h) AC_CHECK_HEADERS(libintl.h) AC_CHECK_HEADERS(sys/types.h) AC_CHECK_HEADERS(sys/socket.h) AC_CHECK_HEADERS(arpa/inet.h) AC_CHECK_HEADERS(net/ethernet.h) AC_CHECK_HEADERS(malloc.h) AC_CHECK_HEADERS(termio.h) AC_CHECK_HEADERS(getopt.h) AC_CHECK_HEADERS(sys/prctl.h) AC_CHECK_HEADERS(linux/watchdog.h,[],[],[#include ]) dnl Sockets are our preferred and supported comms mechanism. But the dnl implementation needs to be able to convey credentials: some don't. dnl So on a few OSes, credentials-carrying streams might be a better choice. dnl dnl Solaris releases up to and including "9" fall into this category dnl (its sockets don't carry credentials; streams do). dnl dnl At Solaris 10, "getpeerucred()" is available, for both sockets and dnl streams, so it should probably use (preferred) socket mechanism. AC_CHECK_HEADERS(stropts.h) dnl streams available (fallback option) AC_CHECK_HEADERS(ucred.h) dnl e.g. Solaris 10 decl. of "getpeerucred()" AC_CHECK_FUNCS(getpeerucred) dnl ************************************************************************ dnl checks for headers needed by clplumbing On BSD AC_CHECK_HEADERS(sys/syslimits.h) if test "$ac_cv_header_sys_param_h" = no; then AC_CHECK_HEADERS(sys/ucred.h) else AC_CHECK_HEADERS(sys/ucred.h,[],[],[#include ]) fi dnl ************************************************************************ dnl checks for headers needed by clplumbing On Solaris AC_CHECK_HEADERS(sys/cred.h xti.h) dnl ************************************************************************ dnl checks for headers needed by clplumbing On FreeBSD/Solaris AC_CHECK_HEADERS(sys/filio.h) dnl dnl These next two are used to help us figure out whether to include dnl some optional STONITH plugins... dnl AC_CHECK_HEADERS(vacmclient_api.h) AC_CHECK_HEADERS(curl/curl.h) AC_CHECK_HEADERS(openhpi/SaHpi.h) AC_MSG_CHECKING(For libOpenIPMI version 2 or greater) AC_TRY_COMPILE([#include ], [ #if (OPENIPMI_VERSION_MAJOR < 2 ) #error "Too Old" #endif ], AC_MSG_RESULT("yes") AM_CONDITIONAL(USE_OPENIPMI, true), AC_MSG_RESULT("no") AM_CONDITIONAL(USE_OPENIPMI, false)) AC_MSG_CHECKING(for special libxml2 includes) if test "x$XML2CONFIG" = "x"; then AC_MSG_RESULT(libxml2 config not found) else XML2HEAD=`$XML2CONFIG --cflags` AC_MSG_RESULT($XML2HEAD) AC_CHECK_LIB(xml2, xmlReadMemory) fi CPPFLAGS="$CPPFLAGS $XML2HEAD" dnl ************************************************************************ dnl * Check for linux/icmpv6.h to make enable the IPv6addr resource agent AC_CHECK_HEADERS(linux/icmpv6.h,[],[],[#include ]) AM_CONDITIONAL(USE_IPV6ADDR, test "$ac_cv_header_linux_icmpv6_h" = yes -a $new_libnet = yes ) AC_CHECK_HEADERS(libxml/xpath.h) dnl dnl Could check for the libraries, but if you have the headers, dnl you're a dolt for not having installed the libs ;-) dnl AM_CONDITIONAL(USE_VACM, test "$ac_cv_header_vacmclient_api_h" = yes) AM_CONDITIONAL(USE_DRAC3, test "$ac_cv_header_curl_curl_h" = yes -a "$ac_cv_header_libxml_xpath_h" = yes) AM_CONDITIONAL(USE_OPENHPI, test "$ac_cv_header_openhpi_SaHpi_h" = yes) dnl dnl SNMP checks dnl SNMPLIB="" SNMPAGENTLIB="" SNMPCONFIG="" ENABLE_SNMP="yes" if test "x${enable_snmp}" = "xno"; then ENABLE_SNMP="no" enable_snmp_subagent="no" fi AC_CHECK_HEADERS(ucd-snmp/snmp.h,[],[],[#include #include ]) AC_CHECK_HEADERS(net-snmp/net-snmp-config.h) if test "x${ENABLE_SNMP}" = "xno"; then # nothing : elif test "x${ac_cv_header_net_snmp_net_snmp_config_h}" = "xyes"; then AC_PATH_PROGS(SNMPCONFIG, net-snmp-config) if test "X${SNMPCONFIG}" = "X"; then AC_MSG_RESULT(You need the net_snmp development package to continue.) ENABLE_SNMP="no" else AC_MSG_CHECKING(for special snmp libraries) SNMPLIB=`net-snmp-config --libs` SNMPAGENTLIB=`net-snmp-config --agent-libs` # KLUDGE!! # Apparently some versions of SUSE Linux don't include -lwrap in $SNMPAGENTLIB case $SNMPAGENTLIB in *wrap*) ;; *) SNMPAGENTLIB="$SNMPAGENTLIB -lwrap";; esac AC_MSG_RESULT($SNMPLIB) fi elif test "x${ac_cv_header_ucd_snmp_snmp_h}" = "xyes"; then # UCD SNMP # ucd-snmp-config does not seem to exist, so just # rely on people having their LDFLAGS set to the path where AC_CHECK_LIB(snmp, init_snmp, SNMPLIB="-lsnmp") if test "X${SNMPLIB}" = "X"; then AC_CHECK_LIB(ucdsnmp, init_snmp, SNMPLIB="-lucdsnmp") fi SNMPAGENTLIB="$SNMPLIB" if test "X${SNMPLIB}" = "X"; then ENABLE_SNMP="no" AC_MSG_RESULT("Could not find ucdsnmp libary." "Please make sure that libsnmp or libucdsnmp" "are in your library path. Or the path to LDFLAGS") fi else ENABLE_SNMP="no" fi if test "$ENABLE_SNMP" = "no" -a "x${enable_snmp_subagent}" = "xyes"; then FatalMissingThing "SNMP Development package" "Missing SNMP development libraries and/or headers" "" "Install net-snmp-devel to enable SNMP features" fi if test "$ENABLE_SNMP" = "no" -o "x${enable_snmp_subagent}" != "xyes"; then enable_snmp_subagent="no" RPM_ENABLE_SNMP_SUBAGENT="0" else RPM_ENABLE_SNMP_SUBAGENT="1" fi check_snmp_libs () { OLDLIBS="$LIBS" LIBS="$LIBS $@" AC_MSG_CHECKING(snmp libraries: $LIBS) AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], , AC_MSG_ERROR(cannot link with requested libraries ($LIBS). Reported errors follow: $(cat conftest.err))) AC_MSG_RESULT(ok) LIBS="$OLDLIBS" } if test "$ENABLE_SNMP" = "yes"; then check_snmp_libs $SNMPLIB fi if test "$enable_snmp_subagent" = "yes"; then check_snmp_libs $SNMPAGENTLIB fi AC_ARG_WITH(mibsdir, [ --with-miBsdir=DIR directory for mib files. ], [ MIBS_DIR="$withval" ]) if test "x${enable_snmp_subagent}" = "xyes" -a "X${MIBS_DIR}" = "X"; then AC_MSG_CHECKING(which MIB directory to use) for mibs_dir in /usr/share/snmp/mibs \ /usr/local/share/snmp/mibs; do if test -d "$mibs_dir"; then MIBS_DIR="$mibs_dir" fi done if test "X${MIBS_DIR}" = "X"; then AC_MSG_ERROR(Could not find mibs directory, please specify with --with-mibsdir); fi AC_MSG_RESULT($MIBS_DIR); fi AC_SUBST(MIBS_DIR) AC_SUBST(SNMPCONFIG) AC_SUBST(SNMPLIB) AC_SUBST(SNMPAGENTLIB) AC_SUBST(RPM_ENABLE_SNMP_SUBAGENT) AM_CONDITIONAL(USE_APC_SNMP, test "$ENABLE_SNMP" = "yes") AM_CONDITIONAL(SNMP_SUBAGENT_BUILD, test "x${enable_snmp_subagent}" = "xyes") if test x"$VERSION" \> x"1.9"; then AC_DEFINE(HAVE_NEW_HB_API, 1, [have new heartbeat api]) fi dnl dnl On many systems libcrypto is needed when linking against libsnmp. dnl Check to see if it exists, and if so use it. dnl AC_CHECK_LIB(crypto, CRYPTO_free, CRYPTOLIB="-lcrypto",) AC_SUBST(CRYPTOLIB) dnl *************************************************************************** dnl TIPC communication module dnl *************************************************************************** AC_ARG_ENABLE([tipc], [ --enable-tipc Enable TIPC Communication module, [default=try]], [], [enable_tipc=try]) AC_ARG_WITH([tipc], [ --with-tipc-source TIPC source code directory], [], []) TIPC_DEV_ROOT=${with_tipc_source} tipc_headers_found=yes if test "x${TIPC_DEV_ROOT}" != "x"; then dnl checking tipc.h in specified directory TIPC_HEADER_DIR=${TIPC_DEV_ROOT}/include AC_CHECK_HEADER([${TIPC_HEADER_DIR}/net/tipc/tipc.h], [], \ [tipc_headers_found=no] ) TIPC_INCLUDE="-I${TIPC_HEADER_DIR}" else dnl checking tipc.h in standard include directory AC_CHECK_HEADERS(net/tipc/tipc.h, [], [tipc_headers_found=no]) fi AC_SUBST(TIPC_INCLUDE) AM_CONDITIONAL(BUILD_TIPC_MODULE, test "x${tipc_headers_found}" = "xyes" && test "x${enable_tipc}" != "xno") dnl *************************************************************************** dnl CIM provider configuration dnl *************************************************************************** AC_ARG_ENABLE([cim-provider], [ --enable-cim-provider Enable CIM providers. [default=no]]) AC_ARG_WITH([cimom], [ --with-cimom Specify CIM server], [], []) AC_ARG_WITH([cmpiheader], [ --with-cmpi-headers Specify CMPI header files], [], []) AC_ARG_WITH([cmpiprovider], [ --with-provider-dir Specify CMPI providers directory], [], []) CMPI_HEADER_PATH=${with_cmpi_headers} CIMOM=${with_cimom} CMPI_PROVIDER_DIR=${with_provider_dir} if test "x${enable_cim_provider}" != "xyes"; then enable_cim_provider="no" fi if test "x${CIMOM}" = "x"; then if test "x${CIMOM}" = "x"; then AC_CHECK_PROG([CIMOM], [cimserver], [pegasus]) fi if test "x${CIMOM}" = "x"; then AC_CHECK_PROG([CIMOM], [sfcbd], [sfcb]) fi if test "x${CIMOM}" = "x"; then AC_CHECK_PROG([CIMOM], [owcimomd], [openwbem]) fi if test "x${CIMOM}" = "x"; then AC_MSG_WARN([Cimom not found, MOF will not be installed!]) fi fi if test "x${enable_cim_provider}" = "xyes"; then if test "x${CMPI_HEADER_PATH}" != "x"; then CPPFLAGS="$CPPFLAGS -I${CMPI_HEADER_PATH}" fi for header in cmpidt.h cmpift.h cmpimacs.h do AC_CHECK_HEADER([${header}], [], [AC_MSG_ERROR([Sorry, can't find CMPI header files, \ specify CMPI header files with --with-cmpi-headers please.])] ) done if test "x${CMPI_PROVIDER_DIR}" = "x"; then case ${CIMOM} in sfcbd) SFCBD_PREFIX=`which sfcbd` SFCBD_PREFIX=`dirname ${SFCBD_PREFIX}` SFCBD_PREFIX=`dirname ${SFCBD_PREFIX}` CMPI_PROVIDER_DIR=${SFCBD_PREFIX}/lib/cmpi;; openwbem) OPENWBEM_PREFIX=`which owcimomd` OPENWBEM_PREFIX=`dirname ${OPENWBEM_PREFIX}` OPENWBEM_PREFIX=`dirname ${OPENWBEM_PREFIX}` OPENWBEM_CONFIG=${OPENWBEM_PREFIX}/etc/openwbem/openwbem.conf OPENWBEM_CMPI_DIR=`grep -e "cmpiprovifc.prov_location.*=" \ ${OPENWBEM_CONFIG} | sed -e 's/.*=\s*\(\.*\)/\1/'` if test "x${OPENWBEM_CMPI_DIR}" != "x"; then CMPI_PROVIDER_DIR=${OPENWBEM_CMPI_DIR} echo cmpi provider dir set, using openwbem config file: \ ${OPENWBEM_CONFIG}. else CMPI_PROVIDER_DIR=${OPENWBEM_PREFIX}/lib/openwbem/cmpiproviders echo openwbem config not found, cmpi provider dir set to \ $(CMPI_PROVIDER_DIR) by default. fi;; pegasus) CMPI_PROVIDER_DIR=/opt/tog-pegasus/providers/lib;; *);; esac if test x"$CMPI_PROVIDER_DIR" = x ; then CMPI_PROVIDER_DIR="$libdir"/cmpi AC_MSG_RESULT(default directory: $CMPI_PROVIDER_DIR) fi fi fi AM_CONDITIONAL(CIM_PROVIDER_BUILD, test "x${enable_cim_provider}" = "xyes") AC_SUBST(CMPI_PROVIDER_DIR) AC_SUBST(CIMOM) AC_SUBST(CMPI_HEADER_PATH) dnl *************************************************************************** dnl Thread safe configuration dnl *************************************************************************** AM_CONDITIONAL(ENABLE_THREAD_SAFE, test "x${enable_thread_safe}" = "xyes") dnl ************************************************************************ dnl Handy function for checking for typedefs or struct defs dnl ************************************************************************ check_for_type() { type="$1" headers="" shift for arg do headers="${headers}${arg} " done program="if ((${type} *) 0) return 0; if (sizeof(${type})) return 0; return 0;" have="HAVE_`echo "$type" | tr ' ' '_' | dd conv=ucase 2>/dev/null`" varhave="heartbeat_cv_$have" AC_CACHE_CHECK([for type $type ],$varhave,[ AC_TRY_COMPILE([$headers], [$program], eval $varhave=yes, eval $varhave=no , eval $varhave=cross) ]) if test x"`eval echo '${'$varhave'}'`" = xyes; then return 0 fi return 1 } check_for_type_member() { type="$1" member="$2" headers="" shift shift for arg do headers="${headers}${arg} " done program="${type} foo; if ((${type} *) 0) return 0; if (sizeof(${type})) return 0; if (sizeof(foo)) return 0; (void*)foo.${member}; return 0;" have="HAVE_`echo "$type" | tr ' ' '_' | dd conv=ucase 2>/dev/null`" varhave="heartbeat_cv_$have" AC_CACHE_CHECK([for type $type ],$varhave,[ AC_TRY_COMPILE([$headers], [$program], eval $varhave=yes, eval $varhave=no , eval $varhave=cross) ]) if test x"`eval echo '${'$varhave'}'`" = xyes; then return 0 fi return 1 } dnl ************************************************************************ dnl checks for typedefs dnl dnl if not known on this system, #define size_t unsigned AC_TYPE_SIZE_T dnl dnl Check poll.h for nfds_t (Linux Only), if not define it as an unsigned long int. dnl if check_for_type "nfds_t" "#include "; then AC_DEFINE(HAVE_NFDS_T,1,[Do we have nfds_t?]) fi dnl ************************************************************************ dnl checks for structures dnl # # Look for all the variants of local/UNIX socket credentials # # Include all of these headers that we can find... # headers="" for hdr in "sys/param.h" "sys/socket.h" "sys/ucred.h" do hdrvar=ac_cv_header_`echo $hdr | sed -e 's%\.%_%' -e 's%/%_%'` if test x"`eval echo '${'$hdrvar'}'`" = xyes; then headers="$headers #include <$hdr>" fi done if check_for_type_member "struct ucred" "cr_ref" "$headers"; then AC_DEFINE(HAVE_STRUCT_UCRED_DARWIN,1,[Do we have the Darwin version of struct ucred?]) fi if check_for_type "struct ucred" "$headers"; then AC_DEFINE(HAVE_STRUCT_UCRED,1,[Do we have struct ucred?]) fi if check_for_type "struct cmsgcred" "$headers" ; then AC_DEFINE(HAVE_STRUCT_CMSGCRED,1,[Do we have struct cmsgcred?]) fi if check_for_type "struct fcred" "$headers"; then AC_DEFINE(HAVE_STRUCT_FCRED,1,[Do we have struct fcred?]) fi if check_for_type "struct cred" "$headers"; then AC_DEFINE(HAVE_STRUCT_CRED,1,[Do we have struct cred?]) fi if check_for_type "struct sockcred" "$headers"; then AC_DEFINE(HAVE_STRUCT_SOCKCRED,1,[Do we have struct sockcred?]) fi dnl Check TERMIOS for components (e.g. c_line not present on Solaris) dnl AC_CACHE_CHECK([for c_line in termios],samba_cv_HAVE_TERMIOS_C_LINE,[ AC_TRY_COMPILE([#include #include ], [struct termios ti; ti.c_line = 'a';], samba_cv_HAVE_TERMIOS_C_LINE=yes,samba_cv_HAVE_TERMIOS_C_LINE=no,samba_cv_HAVE_TERMIOS_C_LINE=cross)]) if test x"$samba_cv_HAVE_TERMIOS_C_LINE" = x"yes"; then AC_DEFINE(HAVE_TERMIOS_C_LINE,1,[ ]) fi dnl Check sockaddr_in for components (e.g. sin_len not present on Solaris) dnl AC_CACHE_CHECK([for sin_len in sockaddr_in],samba_cv_HAVE_SOCKADDR_IN_SIN_LEN,[ AC_TRY_COMPILE([#include #include ], [struct sockaddr_in si; si.sin_len = 1;], samba_cv_HAVE_SOCKADDR_IN_SIN_LEN=yes,samba_cv_HAVE_SOCKADDR_IN_SIN_LEN=no,samba_cv_HAVE_SOCKADDR_IN_SIN_LEN=cross)]) if test x"$samba_cv_HAVE_SOCKADDR_IN_SIN_LEN" = x"yes"; then AC_DEFINE(HAVE_SOCKADDR_IN_SIN_LEN,1,[ ]) fi dnl Check msghdr for components (e.g. msg_control/msg_controlen not present on Solaris) dnl AC_CACHE_CHECK([for msg_control in msghdr],samba_cv_HAVE_MSG_CONTROL_MSGHDR,[ AC_TRY_COMPILE([#include #include ], [struct msghdr mh; mh.msg_control = (void *)0;], samba_cv_HAVE_MSG_CONTROL_MSGHDR=yes,samba_cv_HAVE_MSG_CONTROL_MSGHDR=no,samba_cv_HAVE_MSG_CONTROL_MSGHDR=cross)]) if test x"$samba_cv_HAVE_MSG_CONTROL_MSGHDR" = x"yes"; then MSGHDR_TYPE="msghdr" IPCSOCKET_C="ipcsocket.c" IPCSOCKET_LO="ipcsocket.lo" else MSGHDR_TYPE="nmsghdr" IPCSOCKET_C="" IPCSOCKET_LO="" fi dnl Check syslog.h for 'facilitynames' table dnl AC_CACHE_CHECK([for facilitynames in syslog.h],ac_cv_HAVE_SYSLOG_FACILITYNAMES,[ AC_TRY_COMPILE([ #define SYSLOG_NAMES #include #include ], [ void *fnames; fnames = facilitynames; ], ac_cv_HAVE_SYSLOG_FACILITYNAMES=yes,ac_cv_HAVE_SYSLOG_FACILITYNAMES=no,ac_cv_HAVE_SYSLOG_FACILITYNAMES=cross)]) if test x"$ac_cv_HAVE_SYSLOG_FACILITYNAMES" = x"yes"; then AC_DEFINE(HAVE_SYSLOG_FACILITYNAMES,1,[ ]) fi dnl dnl Check for ALIGN in /sys/param.h dnl AC_MSG_CHECKING("for ALIGN in sys/param.h") AC_EGREP_CPP(FoundAlign, [#include #ifdef ALIGN FoundAlign #endif ], [ ALIGN="ALIGN" AC_MSG_RESULT(Yes) ], AC_MSG_RESULT("No")) AC_MSG_CHECKING("for T_ALIGN in xti.h") AC_EGREP_CPP(FoundAlign, [#include #ifdef T_ALIGN FoundAlign #endif ], [ ALIGN="T_ALIGN" AC_MSG_RESULT(Yes) ], AC_MSG_RESULT(No)) AC_SUBST(IPCSOCKET_C) AC_SUBST(IPCSOCKET_LO) AC_SUBST(ALIGN) AC_SUBST(MSGHDR_TYPE) dnl ************************************************************************ dnl checks for compiler characteristics dnl dnl Warnings for C compilers. Note: generic, portable warnings only. dnl Things likely to be specific to a particular OS or module should be dnl carefully handled afterwards. AC_C_STRINGIZE dnl ********************************************************************** dnl time-related declarations etc. AC_STRUCT_TIMEZONE if check_for_type_member "struct tm" "tm_gmtoff" "#include "; then AC_DEFINE(HAVE_TM_GMTOFF,1,[Do we have structure member tm_gmtoff?]) fi dnl ********************************************************************** dnl Check the size of the integer types dnl So we can have integers of known sizes as needed dnl AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) AC_ARG_ENABLE([all], [ --enable-all Activate ALL features [default=no]]) 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]], [], [enable_fatal_warnings=unknown]) AC_ARG_ENABLE([times-kludge], [ --enable-times-kludge enables a kludge to workaround a bug in glibc's times(2) call [default=yes]], [], [enable_times_kludge=unknown]) AC_ARG_ENABLE([no-long-long], [ --enable-no-long-long removes no long long warning for gcc [default=yes]], [], [enable_no_long_long=yes]) AC_ARG_ENABLE([traditional-warnings], [ --enable-traditional-warnings enable traditional warnings gcc (-Wtraditional) [default=no]]) AC_ARG_ENABLE([pretty], [ --enable-pretty Pretty-print compiler output unless there is an error [default=no]]) AC_ARG_ENABLE([quiet], [ --enable-quiet Supress make output unless there is an error [default=no]]) AC_ARG_ENABLE([ldirectord], [ --enable-ldirectord enable Linix Director Daemon for use with LVS [default=yes]], [], [enable_ldirectord=yes]) AM_CONDITIONAL(LDIRECTORD_BUILD, test "X$enable_ldirectord" = "Xyes") AC_ARG_ENABLE([thread-safe], [ --enable-thread-safe Enable some client libraries to be thread safe. [default=no]]) AC_ARG_ENABLE([snmp], [ --enable-snmp Enable building of SNMP related functionality. [default=yes]]) AC_ARG_ENABLE([snmp-subagent], [ --enable-snmp-subagent Enable building of our SNMP subagent (lots of dependencies). [default=try]]) CC_WARNINGS="" dnl - If requested, enable ALL subsystems. if test "${enable_all}" = "yes" ; then echo "Enabling all optional features." enable_ansi=yes; enable_crm=yes; enable_fatal_warnings=yes; enable_lrm=yes; enable_snmp_subagent=try; enable_mgmt=try; enable_quorumd=try; enable_cim_provider=try; fi AC_ARG_ENABLE([bundled-ltdl], [ --enable-bundled-ltdl Configure, build and install the standalone ltdl library bundled with Heartbeat [default=no]]) LTDL_LIBS="" dnl Check before we enable -Wstrict-prototypes as it causes the test to fail AC_CHECK_LIB(ltdl, lt_dlopen, [LTDL_foo=1]) if test "x${enable_bundled_ltdl}" = "xyes"; then if test $ac_cv_lib_ltdl_lt_dlopen = yes; then AC_MSG_NOTICE([Disabling usage of installed ltdl]) fi ac_cv_lib_ltdl_lt_dlopen=no fi LIBLTDL_DIR="" if test $ac_cv_lib_ltdl_lt_dlopen != yes ; then AC_MSG_NOTICE([Installing local ltdl]) LIBLTDL_DIR=libltdl ( cd $srcdir ; $TAR -xvf libltdl.tar ) if test "$?" -ne 0; then AC_MSG_ERROR([$TAR of libltdl.tar in $srcdir failed]) fi AC_CONFIG_SUBDIRS(libltdl) else LIBS="$LIBS -lltdl" AC_MSG_NOTICE([Using installed ltdl]) INCLTDL="" LIBLTDL="" fi dnl libltdl additions AC_SUBST(INCLTDL) AC_SUBST(LIBLTDL) AC_SUBST(LIBLTDL_DIR) dnl ************ curses ********************** dnl A few OSes (e.g. Linux) deliver a default "ncurses" alongside "curses". dnl Many non-Linux deliver "curses"; sites may add "ncurses". dnl dnl However, the source-code recommendation for both is to #include "curses.h" dnl (i.e. "ncurses" still wants the include to be simple, no-'n', "curses.h"). dnl dnl Andrew Beekhof (author of heartbeat code that uses this functionality) dnl wishes "ncurses" to take precedence. So the following ordering has dnl been devised to implement this. dnl dnl Look first for the headers, then set the libraries accordingly. dnl (Normally autoconf suggests looking for libraries first.) dnl AC_CHECK_HEADERS(curses.h) AC_CHECK_HEADERS(curses/curses.h) AC_CHECK_HEADERS(ncurses.h) AC_CHECK_HEADERS(ncurses/ncurses.h) dnl Although n-library is preferred, only look for it if the n-header was found. CURSESLIBS='' if test "$ac_cv_header_ncurses_h" = "yes"; then AC_CHECK_LIB(ncurses, printw, [CURSESLIBS='-lncurses'; AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)] ) fi if test "$ac_cv_header_ncurses_ncurses_h" = "yes"; then AC_CHECK_LIB(ncurses, printw, [CURSESLIBS='-lncurses'; AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)] ) fi dnl Only look for non-n-library if there was no n-library. if test X"$CURSESLIBS" = X"" -a "$ac_cv_header_curses_h" = "yes"; then AC_CHECK_LIB(curses, printw, [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)] ) fi dnl Only look for non-n-library if there was no n-library. if test X"$CURSESLIBS" = X"" -a "$ac_cv_header_curses_curses_h" = "yes"; then AC_CHECK_LIB(curses, printw, [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)] ) fi AC_SUBST(CURSESLIBS) dnl ************ curses ********************** if test "$GCC" = yes; then dnl dnl We make sure warnings are carefully scrubbed out of the output if dnl you're running on some platforms. You can enable that behavior with dnl the option "fatal-warnings", by specifying --enable-fatal-warnings. dnl Or, you can disable it with --disable-fatal-warnings. dnl dnl Horms 10th August 2001 dnl Don't do this, it seems to cause configure in dnl the libltdl/ directory to die under Debian Woody dnl I'm suspecting it will be a problem on other systems too. dnl For this reason it now defaults to off. dnl AlanR 11 August 2001 dnl Show no mercy to broken OSes and other software. If you have broken dnl software, turn this feature off. dnl NO warnings WHATSOVER will be tolerated without good reason. dnl A distribution being broken isn't a good reason. dnl The cure for that is fix the distribution, not destroy the integrity dnl of the entire project by defaulting it to "off". dnl In my experience, there are ways of making individual warnings go dnl away. dnl The only way I know to keep them out is to make them an absolute dnl pain to deal with. Otherwise they're a pain to fix. dnl This policy is not an accident, nor was it chosen without significant dnl thought and experience. dnl cc_supports_flag() { AC_MSG_CHECKING(whether $CC supports "$@") Cfile=/tmp/foo${$} touch ${Cfile}.c $CC -c "$@" ${Cfile}.c -o ${Cfile}.o >/dev/null 2>&1 rc=$? rm -f ${Cfile}.c ${Cfile}.o case $rc in 0) AC_MSG_RESULT(yes);; *) AC_MSG_RESULT(no);; esac return $rc } dnl ************ printw ********************** if test X"$CURSESLIBS" != X"" && cc_supports_flag -Wcast-qual \ && cc_supports_flag -Werror; then dnl Check for printw() prototype compatibility dnl FIXME: We can check che prototype compatibility only if $CC supports dnl -Wcast-qual and -Werror AC_MSG_CHECKING(whether printw() requires argument of "const char *") ac_save_LIBS=$LIBS LIBS="$CURSESLIBS $LIBS" ac_save_CFLAGS=$CFLAGS CFLAGS="-Wcast-qual -Werror" AC_LINK_IFELSE( [AC_LANG_PROGRAM( [ #if defined(HAVE_CURSES_H) # include #elif defined(HAVE_NCURSES_H) # include #endif ], [printw((const char *)"Test");] )], [ac_cv_compatible_printw=yes], [ac_cv_compatible_printw=no] ) LIBS=$ac_save_LIBS CFLAGS=$ac_save_CFLAGS AC_MSG_RESULT([$ac_cv_compatible_printw]) if test "$ac_cv_compatible_printw" = no; then AC_MSG_WARN([The printw() function of your ncurses or curses library is old, we will disable usage of the library. If you want to use this library anyway, please update to newer version of the library, ncurses 5.4 or later is recommended. You can get the library from http://www.gnu.org/software/ncurses/.]) AC_MSG_NOTICE([Disabling curses]) AC_DEFINE(HAVE_INCOMPATIBLE_PRINTW, 1, [Do we have incompatible printw() in curses library?]) dnl AC_DEFINE(HAVE_CURSES_H, 0) dnl AC_DEFINE(HAVE_NCURSES_H, 0) fi fi dnl ************ printw ********************** EXTRA_WARNINGS="" # We had to eliminate -Wnested-externs because of libtool changes WARNLIST="all missing-prototypes missing-declarations strict-prototypes declaration-after-statement pointer-arith write-strings cast-qual cast-align bad-function-cast inline missing-format-attribute format=2 format-security format-nonliteral no-long-long no-strict-aliasing" for j in $WARNLIST do if cc_supports_flag -W$j then case $j in "no-long-long") if test "${enable_no_long_long}" = "yes"; then EXTRA_WARNINGS="$EXTRA_WARNINGS -W$j" fi;; *) EXTRA_WARNINGS="$EXTRA_WARNINGS -W$j";; esac fi done dnl Add any system specific options here. if test "${enable_ansi}" = "unknown"; then enable_ansi=yes fi case "$host_os" in *linux*|*bsd*) if test "${enable_fatal_warnings}" = "unknown"; then enable_fatal_warnings=yes fi ;; *solaris*) ;; esac case "$host_os" in *linux*) if test "${enable_times_kludge}" = "unknown"; then enable_times_kludge=yes fi ;; esac if test "${enable_ansi}" = yes && cc_supports_flag -std=iso9899:199409 ; then echo "Enabling ANSI Compatibility on this platform" ANSI="-ansi -D_GNU_SOURCE -DANSI_ONLY" fi if test "${enable_fatal_warnings}" = yes && cc_supports_flag -Werror ; then echo "Enabling Fatal Warnings (-Werror) on this platform" FATAL_WARNINGS="-Werror" fi if test "$enable_traditional_warning" = yes && \ cc_supports_flag -Wtraditional; then echo "Enabling traditional warnings" EXTRA_WARNINGS="$EXTRA_WARNINGS -Wtraditional" fi CC_WARNINGS="$EXTRA_WARNINGS $FATAL_WARNINGS $ANSI" NON_FATAL_CC_WARNINGS="$EXTRA_WARNINGS" fi if test "${enable_times_kludge}" = no; then echo "Disabling times(2) kludge" AC_DEFINE(DISABLE_TIMES_KLUDGE, 1, [disable times(2) kludge]) fi AC_SUBST(DISABLE_TIMES_KLUDGE) AC_MSG_CHECKING(which init (rc) directory to use) INITDIR="" 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 AC_MSG_RESULT($INITDIR); break fi done AC_ARG_WITH(initdir, [ --with-initdir=DIR directory for init (rc) scripts [${INITDIR}]], [ if test x"$withval" = xprefix; then INITDIR=${prefix}; else INITDIR="$withval"; fi ]) if test "X$INITDIR" = X then FatalMissingThing "init directory" "Could not locate init directory" fi AC_SUBST(INITDIR) dnl ********************************************************************** dnl checks for group to install fifos as dnl dnl These checks aren't right. We need to locate the lowest dnl unused group id if haclient isn't in the /etc/group file dnl and no one has overridden group-id with a --with-group-id dnl option. dnl AC_ARG_WITH( group-name, [ --with-group-name=GROUP_NAME GROUP_NAME to run our programs as. [default=haclient] ], [ HA_APIGROUP="$withval" ], [ HA_APIGROUP="haclient" ], ) AC_SUBST(HA_APIGROUP) AC_DEFINE_UNQUOTED(HA_APIGROUP, "$HA_APIGROUP", group for our programs) if test -z "${GETENT}" -o ! -x "${GETENT}" then GETENT=getent getent() { grep "^${2}:" /etc/$1 } fi if test -z "${IP2UTIL}" -o ! -x "${IP2UTIL}" then IP2UTIL=/sbin/ip fi AC_ARG_WITH( group-id, [ --with-group-id=GROUP_ID GROUP_ID to run our programs as. [default=60] ], [ HA_APIGID="$withval" ], [ HA_APIGID=65 ], ) if getent group "$HA_APIGROUP" > /dev/null then HA_APIGID=`getent group "$HA_APIGROUP" | cut -d: -f3` fi AC_SUBST(HA_APIGID) AC_DEFINE_UNQUOTED(HA_APIGID, "$HA_APIGID", id for api group) AC_ARG_WITH( ccmuser-name, [ --with-ccmuser-name=HA_CCMUSER_NAME HA_CCMUSER_NAME to run privileged non-root things as. [default=hacluster] ], [ HA_CCMUSER="$withval" ], [ HA_CCMUSER="hacluster" ], ) AC_SUBST(HA_CCMUSER) AC_DEFINE_UNQUOTED(HA_CCMUSER, "$HA_CCMUSER", user to run privileged non-root things as) AC_ARG_WITH( ccmuser-id, [ --with-ccmuser-id=HA_HA_CCMUSER_ID USER_ID to run privileged non-root things as. [default=17] ], [ HA_CCMUID="$withval" ], [ HA_CCMUID=17 ], ) if getent passwd "$HA_CCMUSER" >/dev/null then HA_CCMUID=`getent passwd "$HA_CCMUSER" | cut -d: -f3` fi AC_SUBST(HA_CCMUID) AC_DEFINE_UNQUOTED(HA_CCMUID, "$HA_CCMUID", id for ccm user) # # Priority for starting via init startup scripts # AC_ARG_WITH( start-init-priority, [ --with-start-init-priority=number Init start priority. [default=75] ], [ HB_INITSTARTPRI="$withval" ], [ HB_INITSTARTPRI=75 ], ) AC_SUBST(HB_INITSTARTPRI) AC_DEFINE_UNQUOTED(HB_INITSTARTPRI,"$HB_INITSTARTPRI", init start priority) # # Priority for stopping via init shutdown scripts # AC_ARG_WITH( stop-init-priority, [ --with-stop-init-priority=number Init stop priority. [default=5] ], [ HB_INITSTOPPRI="$withval" ], [ HB_INITSTOPPRI=05 ], ) AC_SUBST(HB_INITSTOPPRI) AC_DEFINE_UNQUOTED(HB_INITSTOPPRI,"$HB_INITSTOPPRI", init stop priority) # # Name of UCD-SNMP development package # AC_ARG_WITH( ucd-snmp-devel, [ --with-snmp-name=name Name of ucd snmp developemnt RPM. [default=ucd-snmp-devel] ], [ UCDSNMPDEVEL=$withval ], [ UCDSNMPDEVEL=ucd-snmp-devel ], ) if test "$ac_cv_header_ucd_snmp_snmp_h" = no; then UCDSNMPDEVEL="" fi AC_SUBST(UCDSNMPDEVEL) AC_DEFINE_UNQUOTED(UCDSNMPDEVEL, $UCDSNMPDEVEL, Name of UCD SNMP development package) dnl ************************************************************************ dnl checks for library functions to replace them dnl dnl alphasort: Only on BSD. dnl System-V systems may have it, but hidden and/or deprecated. dnl A replacement function is supplied for it. dnl dnl NoSuchFunctionName: dnl is a dummy function which no system supplies. It is here to make dnl the system compile semi-correctly on OpenBSD which doesn't know dnl how to create an empty archive dnl dnl scandir: Only on BSD. dnl System-V systems may have it, but hidden and/or deprecated. dnl A replacement function is supplied for it. dnl dnl setenv: is some bsdish function that should also be avoided (use dnl putenv instead) dnl On the other hand, putenv doesn't provide the right API for the dnl code and has memory leaks designed in (sigh...) Fortunately this dnl A replacement function is supplied for it. dnl dnl setproctitle: sets the process title to a given string dnl dnl strerror: returns a string that corresponds to an errno. dnl A replacement function is supplied for it. dnl dnl unsetenv: is some bsdish function that should also be avoided (No dnl replacement) dnl A replacement function is supplied for it. dnl dnl strnlen: is a gnu function similar to strlen, but safer. dnl We wrote a tolearably-fast replacement function for it. dnl dnl strndup: is a gnu function similar to strdup, but safer. dnl We wrote a tolearably-fast replacement function for it. dnl dnl daemon: is a GNU function. The daemon() function is for programs wishing to dnl detach themselves from the controlling terminal and run in the dnl background as system daemon dnl A replacement function is supplied for it. dnl dnl Check Only dnl dnl getopt: If this is valid, define HAVE_DECL_GETOPT to make the getopt.h header compile cleanly. dnl AC_REPLACE_FUNCS(alphasort inet_pton NoSuchFunctionName scandir setenv strerror unsetenv strnlen strndup daemon uuid_parse) dnl AC_CHECK_FUNCS(alphasort inet_pton NoSuchFunctionName scandir setenv strerror unsetenv strnlen strndup daemon uuid_parse) AC_CHECK_FUNCS(getopt, AC_DEFINE(HAVE_DECL_GETOPT, 1, [Have getopt function])) AC_SUBST(HA_HAVE_ALPHASORT) AC_SUBST(HA_HAVE_INET_PTON) AC_SUBST(HA_HAVE_SCANDIR) AC_SUBST(HA_HAVE_SETENV) AC_SUBST(HA_HAVE_STRERROR) AC_SUBST(HA_HAVE_UNSETENV) AC_SUBST(HA_HAVE_STRNLEN) AC_SUBST(HA_HAVE_STRNDUP) AC_SUBST(HA_HAVE_DAEMON) AC_SUBST(HA_HAVE_UUID_PARSE) AC_SUBST(HAVE_DECL_GETOPT) AC_CHECK_FUNCS(fcntl) AC_CHECK_FUNCS(flock) AC_CHECK_FUNCS(inet_aton) AC_CHECK_FUNCS(mallinfo) AC_CHECK_FUNCS(mallopt) AC_CHECK_FUNCS(__default_morecore) AC_CHECK_FUNCS(seteuid) AC_CHECK_FUNCS(setegid) AC_CHECK_FUNCS(getpeereid) dnl ********************************************************************** dnl Check for various argv[] replacing functions on various OSs dnl dnl Borrowed from Proftpd dnl Proftpd is Licenced under the terms of the GNU General Public Licence dnl and is available from http://www.proftpd.org/ dnl AC_CHECK_FUNCS(setproctitle) AC_CHECK_HEADERS(libutil.h) AC_CHECK_LIB(util, setproctitle, [AC_DEFINE(HAVE_SETPROCTITLE,1,[ ]) ac_cv_func_setproctitle="yes" ; LIBS="$LIBS -lutil"]) if test "$ac_cv_func_setproctitle" = "yes"; then pf_argv_set="PF_ARGV_NONE" fi if test "$pf_argv_set" = ""; then AC_CHECK_HEADERS(sys/pstat.h) if test "$ac_cv_header_pstat_h" = "yes"; then AC_CHECK_FUNCS(pstat) if test "$ac_cv_func_pstat" = "yes"; then pf_argv_set="PF_ARGV_PSTAT" else pf_argv_set="PF_ARGV_WRITEABLE" fi fi if test "$pf_argv_set" = ""; then AC_EGREP_HEADER([#define.*PS_STRINGS.*],sys/exec.h, have_psstrings="yes",have_psstrings="no") if test "$have_psstrings" = "yes"; then pf_argv_set="PF_ARGV_PSSTRINGS" fi fi if test "$pf_argv_set" = ""; then AC_CACHE_CHECK(whether __progname and __progname_full are available, pf_cv_var_progname, AC_TRY_LINK([extern char *__progname, *__progname_full;], [__progname = "foo"; __progname_full = "foo bar";], pf_cv_var_progname="yes", pf_cv_var_progname="no")) if test "$pf_cv_var_progname" = "yes"; then AC_DEFINE(HAVE___PROGNAME,1,[ ]) fi AC_CACHE_CHECK(which argv replacement method to use, pf_cv_argv_type, AC_EGREP_CPP(yes,[ #if defined(__GNU_HURD__) yes #endif ],pf_cv_argv_type="new", pf_cv_argv_type="writeable")) if test "$pf_cv_argv_type" = "new"; then pf_argv_set="PF_ARGV_NEW" fi if test "$pf_argv_set" = ""; then pf_argv_set="PF_ARGV_WRITEABLE" fi fi fi AC_DEFINE_UNQUOTED(PF_ARGV_TYPE, $pf_argv_set, mechanism to pretty-print ps output: setproctitle-equivalent) dnl End of tests borrowed from Proftpd dnl check if header file and lib are there for hbaping hbaping_build="yes" AC_CHECK_HEADERS(time.h hbaapi.h, , [hbaping_build="no"],[[#if HAVE_TIME_H #include #endif]]) AC_CHECK_LIB(HBAAPI, HBA_SendScsiInquiry, , [hbaping_build="no"]) AM_CONDITIONAL(HBAAPI_BUILD, test "x${hbaping_build}" = "xyes") dnl check if header file and lib are there for zlib zlib_installed="yes" AC_CHECK_HEADERS(zlib.h, , [zlib_installed="no"],) AC_CHECK_LIB(z, compress , , [zlib_intalled="no"]) AM_CONDITIONAL(BUILD_ZLIB_COMPRESS_MODULE, test "x${zlib_installed}" = "xyes") dnl check if header file and lib are there for zlib bz2_installed="yes" AC_CHECK_HEADERS(bzlib.h, , [bz2_installed="no"],) AC_CHECK_LIB(bz2, BZ2_bzBuffToBuffCompress , , [bz2_intalled="no"]) AM_CONDITIONAL(BUILD_BZ2_COMPRESS_MODULE, test "x${bz2_installed}" = "xyes") dnl check if header file and lib are there for openais module openais_installed="yes" AC_CHECK_HEADERS(evs.h, , [openais_installed="no"],) AC_CHECK_LIB(evs, evs_initialize , , [openais_intalled="no"]) AM_CONDITIONAL(BUILD_OPENAIS_MODULE, test "x${openais_installed}" = "xyes") AC_MSG_CHECKING(if clock_t is long enough) if test $ac_cv_sizeof_long -ge 8; then AC_MSG_RESULT(yes) AC_DEFINE(CLOCK_T_IS_LONG_ENOUGH, 1, [Set if CLOCK_T is adequate by itself for the "indefinite future" (>= 100 years)]) else AC_MSG_RESULT(no) fi dnl check if there are getpid() inconsistency dnl Note: reduce LIBS; in particular, ltdl can cause confusion. dnl Possibly better: move 'LIBS="$LIBS -lltdl"' from above to beyond here. dnl AC_MSG_CHECKING(for getpid() consistency in multi-process/threads program) ac_save_LIBS=$LIBS LIBS="-lpthread" AC_TRY_RUN(`cat $srcdir/config/pidtest.c`, AC_MSG_RESULT(ok), [AC_MSG_RESULT(fail); AC_DEFINE(GETPID_INCONSISTENT, 1 , [pid inconsistent])],) LIBS=$ac_save_LIBS dnl check byte order AC_MSG_CHECKING(for byteorder) AC_TRY_RUN(`cat $srcdir/config/byteorder_test.c`, [AC_MSG_RESULT(little-endian); AC_DEFINE(CONFIG_LITTLE_ENDIAN, 1, [little-endian])], [AC_MSG_RESULT(big-endian); AC_DEFINE(CONFIG_BIG_ENDIAN, 1, [big-endian])],) dnl dnl Lex and yacc can't be trusted to produce code that won't produce dnl warnings dnl NON_FATAL_CFLAGS="$CFLAGS $NON_FATAL_CC_WARNINGS" 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 CFLAGS="$CFLAGS $CC_WARNINGS" dnl NOTE: dnl This check should only be done after CFLAGS is set. Otherwise dnl linux box will complain because of a warning of the undefined dnl function sigignore(). dnl dnl In theory, all function checks should be done after the CFLAGS is dnl set since we are enforcing the -Werror. But this would have a big dnl impact on the whole source tree so I am only moving the dnl sigignore for now. A bit of a hack. dnl dnl sigignore: Only on Solaris. dnl it is a solaris replacement for signal(s,SIG_IGN). dnl AC_CHECK_FUNCS(sigignore) 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. This causes a problem when configure dnl is run in the libltdl directory. Horms 16th July 2002 dnl if export | fgrep " CFLAGS=" > /dev/null; then export -n CFLAGS || true # We don't want to bomb out if this fails fi if test "$GCC" = yes; then CFLAGS="$CFLAGS -ggdb3" if cc_supports_flag -funsigned-char then CFLAGS="$CFLAGS -funsigned-char" fi else CFLAGS="$CFLAGS -g" fi dnl AC_SUBST(CC_WARNINGS) dnl ************************************************************************ dnl pre AC_OUTPUT stuff dnl dnl th aux dir (for holding config & autogenerated stuff) dnl AC_SUBST(ac_aux_dir) AC_SUBST(LIBADD_DL) dnl extra flags for dynamic linking libraries AC_SUBST(LIBADD_INTL) dnl extra flags for GNU gettext stuff... AC_SUBST(LOCALE) HA_HBCONF_DIR=$sysconfdir/ha.d AC_SUBST(HA_HBCONF_DIR) AC_DEFINE_UNQUOTED(HA_HBCONF_DIR,"$HA_HBCONF_DIR", Heartbeat configuration directory) HA_RC_DIR=$HA_HBCONF_DIR/rc.d AC_SUBST(HA_RC_DIR) AC_DEFINE_UNQUOTED(HA_RC_DIR,"$HA_RC_DIR", heartbeat v1 script directory) AC_ARG_ENABLE([crm], [ --enable-crm Compile the Version 2 Cluster Resource Manager. [default=yes]], [], [enable_crm=yes]) CRM_DIR="" if test "x${enable_crm}" = "xyes"; then CRM_ENABLED=1 CRM_DIR=crm AC_DEFINE_UNQUOTED(WITH_CRM, 1, Use the new Cluster Resource Manager) else if test -z "${enable_crm}"; then enable_crm="no" fi dnl None of the following items build without the CRM available enable_mgmt=no enable_dopd=no enable_cim_provider=no fi AC_SUBST(CRM_DIR) AC_MSG_NOTICE([whether to enable the Cluster Resource Manager... ${enable_crm}]) AM_CONDITIONAL(CRM_BUILD, test "x${enable_crm}" = "xyes") AC_SUBST(CRM_ENABLED) dnl lrm configuration AC_ARG_ENABLE([lrm], [ --enable-lrm Compile the new Local Resource Manager. [default=yes]], [], [enable_lrm=yes]) LRM_ENABLED=0 if test "x${enable_crm}" = "xyes"; then if test "x${enable_lrm}" = "xno"; then AC_MSG_WARN([crm enabled, overriding --enable-lrm=no with --enable-lrm=yes]) elif test -z "${enable_lrm}"; then AC_MSG_WARN([crm enabled, defaulting to --enable-lrm=yes]) fi enable_lrm="yes" elif test -z "${enable_lrm}"; then enable_lrm="no" fi if test "x${enable_lrm}" = "xyes"; then LRM_ENABLED=1 fi if test -h /proc/$$/exe then AC_MSG_NOTICE("/proc/{pid}/exe link is supported") AC_DEFINE_UNQUOTED(HAVE_PROC_PID, 1, Define to 1 if /proc/{pid} is supported.) fi AC_SUBST(LRM_ENABLED) AM_CONDITIONAL(LRM_BUILD, test "x${enable_lrm}" = "xyes") AC_MSG_NOTICE([whether to enable the Local Resource Manager... ${enable_lrm}]) dnl ************************************************************************ dnl management and quorum daemons. AC_CHECK_HEADERS(gnutls/gnutls.h) AC_CHECK_HEADERS(security/pam_appl.h pam/pam_appl.h) dnl GNUTLS library: Attempt to determine by 'libgnutls-config' program. dnl If no 'libgnutls-config', try traditional autoconf means. AC_PATH_PROGS(LIBGNUTLS_CONFIG, libgnutls-config) if test -n "$LIBGNUTLS_CONFIG"; then AC_MSG_CHECKING(for gnutls header flags) GNUTLSHEAD="`$LIBGNUTLS_CONFIG --cflags`"; AC_MSG_RESULT($GNUTLSHEAD) AC_MSG_CHECKING(for gnutls library flags) GNUTLSLIBS="`$LIBGNUTLS_CONFIG --libs`"; AC_MSG_RESULT($GNUTLSLIBS) else AC_CHECK_LIB(gnutls, gnutls_init) fi AC_SUBST(GNUTLSHEAD) AC_SUBST(GNUTLSLIBS) dnl management tool configuration AC_ARG_ENABLE([mgmt], [ --enable-mgmt Compile the management tool. [default=try]], [], [enable_mgmt=try]) if test "x${enable_mgmt}" != "xno"; then if test "x${enable_mgmt}" = "xtry"; then MISSING_FN="WarnMissingThing" else MISSING_FN="FatalMissingThing" fi enable_mgmt="yes" MGMT_ENABLED=1 AM_CHECK_PYTHON_HEADERS(,PYTHON_INCLUDES='') AC_SUBST(PYTHON_INCLUDES) if test "x${PYTHON_INCLUDES}" = "x"; then $MISSING_FN "Python.h" \ "The GUI managment module needs Python.h (Linux: python-devel package)" enable_mgmt="no" MGMT_ENABLED=0 fi if test "$ac_cv_header_security_pam_appl_h" = "no" -a "$ac_cv_header_pam_pam_appl_h" = "no"; then $MISSING_FN "security/pam_appl.h" \ "The GUI managment module needs the pam-devel package" enable_mgmt="no" MGMT_ENABLED=0 fi if test "$ac_cv_header_gnutls_gnutls_h" = "no"; then $MISSING_FN "gnutls/gnutls.h" \ "The GUI managment module needs GNU/TLS header files" enable_mgmt="no" MGMT_ENABLED=0 fi if test -z "$SWIG"; then $MISSING_FN "swig" \ "The GUI managment module needs swig" \ "You can get it from http://swig.org/" enable_mgmt="no" MGMT_ENABLED=0 fi fi if test "x${enable_mgmt}" != "xno"; then RPM_ENABLE_MGMT_CONFIG=1 else RPM_ENABLE_MGMT_CONFIG=0 fi AC_SUBST(RPM_ENABLE_MGMT_CONFIG) AM_CONDITIONAL(MGMT_BUILD, test "x${enable_mgmt}" != "xno") if test "x${enable_mgmt}" != "xno"; then AC_DEFINE_UNQUOTED(MGMT_ENABLED, 1, Define to 1 if the mgmt-daemon and friends are enabled.) dnl If this system might be RPM-based, then adjust some RPM-build details if test x"${RPM}" != x""; then dnl FIXME: a flawy solution but no better one now if rpm -q python-gtk > /dev/null; then RPM_MGMT_RUNTIME_REQUIRES="libglade2, python-gtk"; else RPM_MGMT_RUNTIME_REQUIRES="libglade2, pygtk2"; fi else RPM_MGMT_RUNTIME_REQUIRES= fi else RPM_MGMT_RUNTIME_REQUIRES= fi AC_SUBST(RPM_MGMT_RUNTIME_REQUIRES) AC_MSG_NOTICE([whether to enable the management tool... ${enable_mgmt}]) dnl quorum server configuration AC_ARG_ENABLE([quorumd], [ --enable-quorumd Compile the quorum server. [default=try]], [], [enable_quorumd=try]) if test "x${enable_quorumd}" != "xno"; then if test "x${enable_quorumd}" = "xtry"; then MISSING_FN="WarnMissingThing" else MISSING_FN="FatalMissingThing" fi enable_quorumd="yes" QUORUMD_ENABLED=1 if test "$ac_cv_header_gnutls_gnutls_h" = "no"; then $MISSING_FN "gnutls/gnutls.h" \ "The quorum server module needs GNU/TLS header files" enable_quorumd="no" QUORUMD_ENABLED=0 fi fi AC_SUBST(QUORUMD_ENABLED) AM_CONDITIONAL(QUORUMD_BUILD, test "x${enable_quorumd}" != "xno") AC_MSG_NOTICE([whether to enable the quorum server... ${enable_quorumd}]) dnl ********************************************** dnl TSA plugin configuration dnl ********************************************** AC_ARG_ENABLE([tsa-plugin], [ --enable-tsa-plugin Enable TSA plugin. [default=no]], [], [enable_tsa_plugin=no]) AC_ARG_WITH([JAVA_HOME], [ --with-java-home JAVA_HOME dir], [], []) AC_ARG_WITH([TSA_DIR], [ --with-tsa-dir TSA diretory, default = /opt/IBM/tsamp/], [], []) JAVA_HOME=${with_java_home} TSA_DIR=${with_tsa_dir} if test "x${enable_tsa_plugin}" != "xno"; then if test "x${JAVA_HOME}" = "x"; then JAVA_BIN=`which java` JAVA_BIN_DIR=`dirname ${JAVA_BIN}` JAVA_HOME=`dirname ${JAVA_BIN_DIR}` fi if test "x${TSA_DIR}" = "x"; then TSA_DIR="/opt/IBM/tsamp/" fi fi AC_SUBST(JAVA_HOME) AC_SUBST(TSA_DIR) AM_CONDITIONAL(TSA_PLUGIN_BUILD, test "x${enable_tsa_plugin}" != "xno") dnl ********************************************** dnl drbd peer outdate plugin configuration dnl ********************************************** case "$host_os" in *linux*) AC_ARG_ENABLE([dopd], [ --enable-dopd Compile the Drbd Outdate Peer Daemon and tools. [default=yes]], [], [enable_dopd=yes]) ;; *) enable_dopd=no ;; esac AM_CONDITIONAL(BUILD_DRBD_OUTDATE_PEER, test "x${enable_dopd}" != "xno") hb_libdir="${libdir}/${HB_PKG}" AC_SUBST(hb_libdir) HA_PLUGIN_DIR="${hb_libdir}/plugins" AC_SUBST(HA_PLUGIN_DIR) AC_DEFINE_UNQUOTED(HA_PLUGIN_DIR,"$HA_PLUGIN_DIR", PILS plugin dir) LRM_PLUGIN_DIR="${hb_libdir}/plugins/RAExec" AC_SUBST(LRM_PLUGIN_DIR) AC_DEFINE_UNQUOTED(LRM_PLUGIN_DIR,"$LRM_PLUGIN_DIR", LRM plugin dir) HB_RA_DIR="${sysconfdir}/ha.d/resource.d/" AC_SUBST(HB_RA_DIR) AC_DEFINE_UNQUOTED(HB_RA_DIR,"$HB_RA_DIR", Location for v1 Heartbeat v1 RAs) dnl ************ OCF (Open Cluster Framework) ********************** dnl Must be consistent with remainder of platform (analogy with "initdir"). 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 ]) if test "X$OCF_ROOT_DIR" = X; then FatalMissingThing "OCF directory" "Could not locate OCF directory" fi AC_SUBST(OCF_ROOT_DIR) AC_DEFINE_UNQUOTED(OCF_ROOT_DIR,"$OCF_ROOT_DIR", OCF root dir) OCF_RA_DIR="${OCF_ROOT_DIR}/resource.d/" AC_SUBST(OCF_RA_DIR) AC_DEFINE_UNQUOTED(OCF_RA_DIR,"$OCF_RA_DIR", Location for OCF RAs) LSB_RA_DIR="${INITDIR}" AC_SUBST(LSB_RA_DIR) AC_DEFINE_UNQUOTED(LSB_RA_DIR,"$LSB_RA_DIR", Location for LSB RAs) STONITH_RA_DIR="${hb_libdir}/stonith.d/" AC_SUBST(STONITH_RA_DIR) AC_DEFINE_UNQUOTED(STONITH_RA_DIR,"$STONITH_RA_DIR", Location for STONITH RAs) AC_ARG_ENABLE([valgrind], [ --enable-valgrind "Run selected heartbeat components using Valgrind." [default=no]], [], [enable_valgrind=no]) AC_ARG_WITH(valgrind-log, [ --with-valgrind-log=options Logging options to pass to valgrind], [ VALGRIND_LOG="$withval" ], []) AC_ARG_WITH(valgrind-suppress, [ --with-valgrind-suppress=file Name of a suppression file to pass to Valgrind [default=/dev/null]], [ VALGRIND_SUPP="$withval" ], [ VALGRIND_SUPP="/dev/null" ]) if test "x" = "x$VALGRIND_LOG"; then VALGRIND_LOG="--log-socket=127.0.0.1:1234" AC_MSG_NOTICE(Set default Valgrind options to: $VALGRIND_OPTS) AC_MSG_NOTICE(Remember to start a receiver on localhost:1234) fi AC_PATH_PROG(VALGRIND_BIN, valgrind) if test "xyes" = "x$enable_valgrind" -a "x$VALGRIND_BIN" != "x"; then enable_libc_malloc=yes fi AC_DEFINE_UNQUOTED(VALGRIND_BIN, "$VALGRIND_BIN", Valgrind command) AC_DEFINE_UNQUOTED(VALGRIND_LOG, "$VALGRIND_LOG", Valgrind logging options) AC_DEFINE_UNQUOTED(VALGRIND_SUPP, "$VALGRIND_SUPP", Name of a suppression file to pass to Valgrind) AC_ARG_ENABLE([libc-malloc], [ --enable-libc-malloc Use libc malloc instead of Heartbeat's custom one. [default=no]], [], [enable_libc_malloc=no]) if test "xyes" = "x$enable_libc_malloc" -o "x1" = "x$enable_libc_malloc"; then AC_DEFINE_UNQUOTED(CL_USE_LIBC_MALLOC, 1, Use libc malloc instead of Heartbeat's custom one.) fi dnl ********************************************************************** dnl 'AWK' had been determined via 'aclocal.m4' as the simple name, using dnl the current PATH (i.e. in the context of 'configure'). dnl dnl Things within heartbeat will use 'AWK', but from a different context, dnl so we should determine, and substitute, the full path. dnl dnl Note: Even that may have a flaw, e.g. if 'configure' finds (say) 'gawk', dnl which we here convert to '/path/to/gawk', but the run-time machine lacks it. dnl We won't worry about that for now. dnl (David Lee; March 2007) AC_PATH_PROGS([AWK], $AWK) dnl ********************************************************************** dnl Enable optional, experimental directories here... dnl XPERIMENTALDIRS="" AC_SUBST(XPERIMENTALDIRS) CheckMissingThings dnl Options for cleaning up the compiler output PRETTY_CC="" QUIET_LIBTOOL_OPTS="" QUIET_MAKE_OPTS="" if test x"${enable_pretty}" = "xyes"; then enable_quiet="yes" echo "install_sh: ${install_sh}" PRETTY_CC="`pwd`/tools/ccdv" dnl It would be nice if this was rebuilt when needed too... mkdir `pwd`/tools/ 2>/dev/null gcc $CFLAGS -o `pwd`/tools/ccdv ${srcdir}/tools/ccdv.c CC="\$(PRETTY_CC) ${CC}" fi if test "x${enable_quiet}" = "xyes"; then QUIET_LIBTOOL_OPTS="--quiet" QUIET_MAKE_OPTS="--quiet" fi AC_MSG_RESULT(Supressing make details: ${enable_quiet}) AC_MSG_RESULT(Pretty printing of compiler output: ${enable_pretty}) dnl Put the above variables to use LIBTOOL="${LIBTOOL} --tag=CC \$(QUIET_LIBTOOL_OPTS)" MAKE="${MAKE} \$(QUIET_MAKE_OPTS)" AC_SUBST(CC) AC_SUBST(MAKE) AC_SUBST(LIBTOOL) AC_SUBST(PRETTY_CC) AC_SUBST(QUIET_MAKE_OPTS) AC_SUBST(QUIET_LIBTOOL_OPTS) dnl *** "echo" adjustments (begin) *** dnl Some run-time scripts require options to "echo". dnl This configure is already determining and using "ac_n" and "ac_c" dnl for internal use, so make available externally. dnl (Not sure how "future proof" this is, but it at least seems clean.) dnl dnl This must be close to the end of "configure.in" otherwise it interferes dnl with output from the AC_MSG_*() macros. ECHO_N="$ac_n" ECHO_C="$ac_c" case $ac_n in -n) ECHO_E="-e";; *) ECHO_E="";; esac ECHO_CMD="echo" if test -x /usr/linux/bin/echo then # This is for AIX. I'm not sure it's necessary... ECHO_CMD="/usr/linux/bin/echo" ECHO_N="-n" ECHO_E="-e" fi AC_SUBST(ECHO_N) AC_SUBST(ECHO_C) AC_SUBST(ECHO_E) AC_SUBST(ECHO_CMD) dnl *** "echo" adjustments (end) *** dnl The Makefiles and shell scripts we output AC_CONFIG_FILES(heartbeat.spec \ Makefile \ README \ logd/Makefile \ config/Makefile \ cts/Makefile \ cts/CM_fs.py \ cts/CM_hb.py \ cts/CTS.py \ cts/CTSaudits.py \ cts/CTSlab.py \ cts/CTStests.py \ cts/CM_LinuxHAv2.py \ cts/CTSproxy.py \ cts/extracttests.py \ cts/getpeinputs.sh \ cts/OCFIPraTest.py \ cts/CIB.py \ cts/LSBDummy \ crm/Makefile \ crm/cib/Makefile \ crm/crmd/Makefile \ crm/pengine/Makefile \ crm/tengine/Makefile \ crm/admin/Makefile \ crm/admin/crm_primitive.py \ crm/admin/crm_sh \ crm/admin/crm_utils.py \ crm/admin/crm_commands.py \ debian/Makefile \ doc/Makefile \ doc/startstop \ doc/cibadmin.8 \ doc/crm_resource.8 \ contrib/Makefile \ contrib/ipfail/Makefile \ contrib/mlock/Makefile \ contrib/drbd-outdate-peer/Makefile \ include/Makefile \ include/clplumbing/Makefile \ include/crm/Makefile \ include/crm/common/Makefile \ include/crm/pengine/Makefile \ include/lrm/Makefile \ include/mgmt/Makefile \ include/ocf/Makefile \ include/pils/Makefile \ include/pils/plugin.h \ include/saf/Makefile \ include/stonith/Makefile \ include/fencing/Makefile \ replace/Makefile \ lib/Makefile \ lib/apphb/Makefile \ lib/clplumbing/Makefile \ lib/hbclient/Makefile \ lib/crm/Makefile \ lib/crm/common/Makefile \ lib/crm/cib/Makefile \ lib/crm/pengine/Makefile \ lib/crm/transition/Makefile \ lib/lrm/Makefile \ lib/mgmt/Makefile \ lib/pils/Makefile \ lib/plugins/Makefile \ lib/plugins/InterfaceMgr/Makefile \ lib/plugins/HBauth/Makefile \ lib/plugins/HBcomm/Makefile \ lib/plugins/lrm/Makefile \ lib/plugins/stonith/Makefile \ lib/plugins/stonith/ribcl.py \ lib/plugins/stonith/external/Makefile \ lib/plugins/stonith/external/ibmrsa \ lib/plugins/stonith/external/riloe \ lib/plugins/stonith/external/ssh \ lib/plugins/AppHBNotification/Makefile \ lib/plugins/HBcompress/Makefile \ lib/plugins/quorum/Makefile \ lib/plugins/quorumd/Makefile \ lib/plugins/tiebreaker/Makefile \ lib/recoverymgr/Makefile \ lib/stonith/Makefile \ lib/fencing/Makefile \ lrm/Makefile \ lrm/lrmd/Makefile \ lrm/admin/Makefile \ lrm/test/LRMBasicSanityCheck \ lrm/test/Makefile \ lrm/test/simple_ops \ mgmt/Makefile \ mgmt/daemon/Makefile \ mgmt/client/Makefile \ mgmt/client/haclient.py \ mgmt/client/mgmtcmd.py \ heartbeat/Makefile \ heartbeat/rc.d/Makefile \ heartbeat/rc.d/ask_resources \ heartbeat/rc.d/hb_takeover \ heartbeat/init.d/Makefile \ heartbeat/init.d/heartbeat \ heartbeat/lib/Makefile \ heartbeat/lib/BasicSanityCheck \ heartbeat/lib/ha_config \ heartbeat/lib/ha_propagate \ heartbeat/lib/hb_standby \ heartbeat/lib/mach_down \ heartbeat/lib/req_resource \ heartbeat/lib/ResourceManager \ heartbeat/lib/TestHeartbeatComm \ heartbeat/lib/hb_takeover \ heartbeat/lib/hb_addnode \ heartbeat/lib/hb_delnode \ heartbeat/lib/hb_setweight \ heartbeat/lib/hb_setsite \ heartbeat/shellfuncs \ heartbeat/libnet_util/Makefile \ heartbeat/logrotate.d/Makefile \ 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 \ membership/Makefile \ membership/ccm/Makefile \ membership/quorumd/Makefile \ pkg/Makefile \ pkg/InfoFiles/pkginfo \ pkg/InfoFiles/preinstall \ pkg/InfoFiles/postinstall \ port/Makefile \ port/portMakefile \ port/heartbeat/pkg-deinstall \ port/heartbeat/pkg-descr \ port/heartbeat/pkg-install \ port/heartbeat/pkg-plist \ snmp_subagent/Makefile \ snmp_subagent/SNMPAgentSanityCheck \ cim/Makefile \ cim/mof/Makefile \ cim/mof/register_providers.sh \ cim/mof/unregister_providers.sh \ tsa_plugin/Makefile \ tsa_plugin/testrun.sh \ tsa_plugin/linuxha-adapter \ telecom/Makefile \ telecom/apphbd/Makefile \ telecom/recoverymgrd/Makefile \ fencing/Makefile \ fencing/stonithd/Makefile \ fencing/test/Makefile \ fencing/test/STONITHDBasicSanityCheck \ tools/Makefile \ tools/haresources2cib.py \ resources/Makefile \ resources/OCF/Makefile \ + resources/OCF/.ocf-binaries \ + resources/OCF/.ocf-directories \ resources/OCF/ocf-shellfuncs \ resources/OCF/ClusterMon \ resources/OCF/Dummy \ resources/OCF/pingd \ resources/OCF/apache \ resources/OCF/AudibleAlarm \ resources/OCF/Delay \ resources/OCF/db2 \ resources/OCF/drbd \ resources/OCF/eDir88 \ resources/OCF/EvmsSCC \ resources/OCF/Evmsd \ resources/OCF/Filesystem \ resources/OCF/ICP \ resources/OCF/IPaddr \ resources/OCF/IPaddr2 \ resources/OCF/IPsrcaddr \ resources/OCF/LinuxSCSI \ resources/OCF/LVM \ resources/OCF/MailTo \ resources/OCF/ManageRAID \ resources/OCF/ManageVE \ resources/OCF/mysql \ resources/OCF/o2cb \ resources/OCF/oracle \ resources/OCF/oralsnr \ resources/OCF/portblock \ resources/OCF/Raid1 \ resources/OCF/rsyncd \ resources/OCF/pgsql \ resources/OCF/Pure-FTPd \ resources/OCF/SAPDatabase \ resources/OCF/SAPInstance \ resources/OCF/SendArp \ resources/OCF/ServeRAID \ resources/OCF/Stateful \ resources/OCF/SysInfo \ resources/OCF/VIPArip \ resources/OCF/WAS \ resources/OCF/WAS6 \ resources/OCF/WinPopup \ resources/OCF/Xen \ resources/OCF/Xinetd \ resources/heartbeat/Makefile \ resources/heartbeat/apache \ resources/heartbeat/AudibleAlarm \ resources/heartbeat/Delay \ resources/heartbeat/db2 \ resources/heartbeat/Filesystem \ resources/heartbeat/hto-mapfuncs \ resources/heartbeat/ICP \ resources/heartbeat/IPaddr \ resources/heartbeat/IPaddr2 \ resources/heartbeat/IPsrcaddr \ resources/heartbeat/IPv6addr \ resources/heartbeat/LinuxSCSI \ resources/heartbeat/LVM \ resources/heartbeat/LVSSyncDaemonSwap \ resources/heartbeat/MailTo \ resources/heartbeat/OCF \ resources/heartbeat/portblock \ resources/heartbeat/Raid1 \ resources/heartbeat/ServeRAID \ resources/heartbeat/SendArp \ resources/heartbeat/WAS \ resources/heartbeat/WinPopup \ resources/heartbeat/Xinetd \ ) dnl Now process the entire list of files added by previous dnl calls to AC_CONFIG_FILES() AC_OUTPUT() dnl subpackages configuration - perhaps configure it properly some other time dnl when it has been discussed at linux-ha-dev dnl AC_CONFIG_SUBDIRS(stonith heartbeat) dnl ***************** dnl Configure summary dnl ***************** eval my_datadir="`eval echo ${datadir}`" eval my_includedir="`eval echo ${includedir}`" eval my_initdir="${INITDIR}" eval my_libdir="`eval echo ${libdir}`" eval my_localstatedir="`eval echo ${localstatedir}`" eval my_mandir="`eval echo ${mandir}`" eval my_sbindir="`eval echo ${sbindir}`" eval my_sysconfdir="`eval echo ${sysconfdir}`" AC_MSG_RESULT([]) AC_MSG_RESULT([$PACKAGE configuration:]) AC_MSG_RESULT([ Version = "$VERSION"]) AC_MSG_RESULT([ Executables = "$my_sbindir"]) AC_MSG_RESULT([ Man pages = "$my_mandir"]) AC_MSG_RESULT([ Libraries = "$my_libdir"]) AC_MSG_RESULT([ Header files = "$my_includedir"]) AC_MSG_RESULT([ Data files = "$my_datadir"]) AC_MSG_RESULT([ State information = "$my_localstatedir"]) AC_MSG_RESULT([ System configuration = "$my_sysconfdir"]) AC_MSG_RESULT([ Init (rc) scripts = "$my_initdir"]) AC_MSG_RESULT([ Use system LTDL = "${ac_cv_lib_ltdl_lt_dlopen}"]) AC_MSG_RESULT([ HA group name = "${HA_APIGROUP}"]) AC_MSG_RESULT([ HA group id = "${HA_APIGID}"]) AC_MSG_RESULT([ HA user name = "${HA_CCMUSER}"]) AC_MSG_RESULT([ HA user user id = "${HA_CCMUID}"]) AC_MSG_RESULT([ Build snmp subagent = "${enable_snmp_subagent}"]) if test "x${enable_snmp_subagent}" = "xyes"; then AC_MSG_RESULT([ SNMP MIB directory = "${MIBS_DIR}"]) AC_MSG_RESULT([ SNMP agent libraries = "${SNMPAGENTLIB}"]) fi AC_MSG_RESULT([ SNMP libraries = "${SNMPLIB}"]) AC_MSG_RESULT([ ucd_snmp_devel name = "${UCDSNMPDEVEL}"]) AC_MSG_RESULT([ Build New CRM = "${enable_crm}"]) AC_MSG_RESULT([ Build New LRM = "${enable_lrm}"]) AC_MSG_RESULT([ Build Ldirectord = "${enable_ldirectord}"]) AC_MSG_RESULT([ Build CIM providers = "${enable_cim_provider}"]) if test "x${enable_cim_provider}" = "xyes"; then AC_MSG_RESULT([ CIM server = "${CIMOM}"]) AC_MSG_RESULT([ CIM providers dir = "${CMPI_PROVIDER_DIR}"]) AC_MSG_RESULT([ CMPI header files = "${CMPI_HEADER_PATH}"]) fi AC_MSG_RESULT([ Build TSA plugin = "${enable_tsa_plugin}"]) if test "x${enable_tsa_plugin}" != "xno"; then AC_MSG_RESULT([ JAVA_HOME = "${JAVA_HOME}"]) AC_MSG_RESULT([ TSA_DIR = "${TSA_DIR}"]) fi AC_MSG_RESULT([ Build dopd plugin = "${enable_dopd}"]) AC_MSG_RESULT([ Enable times kludge = "${enable_times_kludge}"]) AC_SUBST(DISABLE_TIMES_KLUDGE) AC_MSG_RESULT([ CC_WARNINGS = "${CC_WARNINGS}"]) AC_MSG_RESULT([ Mangled CFLAGS = "${CFLAGS}"]) AC_MSG_RESULT([ Libraries = "${LIBS}"]) AC_MSG_RESULT([ ]) AC_MSG_RESULT([Note: If you use the 'make install' method for installation you]) AC_MSG_RESULT([also need to adjust '/etc/passwd' and '/etc/group' manually.]) AC_MSG_RESULT([ ]) diff --git a/heartbeat/.ocf-binaries.in b/heartbeat/.ocf-binaries.in new file mode 100644 index 000000000..b113353ce --- /dev/null +++ b/heartbeat/.ocf-binaries.in @@ -0,0 +1,56 @@ +# Make sure PATH contains all the usual suspects +export PATH="$PATH:/sbin:/usr/sbin:/usr/bin" + +# Include /usr/ucb for finding whoami on Solaris +export PATH="$PATH:/usr/ucb" + +# Binaries and binary options for use in Resource Agents +: ${AWK:=@AWK@} +: ${GREP:="@EGREP@"} +: ${IFCONFIG_A_OPT:="@IFCONFIG_A_OPT@"} +: ${MAILCMD:=@MAILCMD@} +: ${PING:=@PING@} +: ${SH:=@SHELL@} +: ${RPM:=@RPM@} + +# Entries that should probably be removed +: ${BASENAME:=basename} +: ${BLOCKDEV:=blockdev} +: ${FSCK:=fsck} +: ${FUSER:=fuser} +: ${GETENT:=getent} +: ${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} +: ${WHOAMI:=whoami} +: ${STRINGSCMD:=strings)} +: ${SCP:=scp} +: ${SSH:=ssh} +: ${SWIG:=swig} + +check_binary () { + if [ ! -x "`which $1`" ] ; then + ocf_log err "Setup problem: Couldn't find utility $1" + exit $OCF_ERR_INSTALLED + fi +} + +have_binary () { + if [ ! -x "`which $1`" ] ; then + return 0 + fi + return 1 +} diff --git a/heartbeat/.ocf-directories.in b/heartbeat/.ocf-directories.in new file mode 100644 index 000000000..d58f6c15e --- /dev/null +++ b/heartbeat/.ocf-directories.in @@ -0,0 +1,20 @@ +# Binaries and binary options for use in Resource Agents + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +: ${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_VARRUNDIR@/heartbeat/rsctmp} +: ${HA_FIFO:=@localstatedir@/lib/heartbeat/fifo} +: ${HA_BIN:=@libdir@/heartbeat} +: ${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_LOGTAG:=$__SCRIPT_NAME[$$]} +: ${HA_VARRUN:=@localstatedir@/run/} +: ${HA_VARLOCK:=@localstatedir@/lock/subsys/} diff --git a/heartbeat/Filesystem.in b/heartbeat/Filesystem.in index ba9195c79..a64cc2528 100644 --- a/heartbeat/Filesystem.in +++ b/heartbeat/Filesystem.in @@ -1,814 +1,802 @@ #!/bin/sh # # Support: linux-ha@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@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_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 # # # An example usage in /etc/ha.d/haresources: # node1 10.0.0.170 Filesystem::/dev/sda1::/data1::ext2 # or # node1 10.0.0.170 Filesystem::-Ldata1::/data1::ext2 # or # node1 10.0.0.170 Filesystem::server:/data1::/data1::nfs::ro # # This assumes you want to manage a filesystem on a shared (scsi) bus. # Do not put this filesystem in /etc/fstab. This script manages all of # that for you. # # If you are interested in High Availability, you will probably also want # some sort of external hardware RAID controller in front of the actual # disks. I don't mean a RAID controller embedded in the host controller - # it has to be an external controller. # # It can also be an internal RAID controller if the controller supports # failover. IBM's ServeRAID controller does this, and it automatically # prohibits concurrent access too, so it's pretty cool in this application. # # There is a script for software RAID-1 included in this directory. Right # now, I wouldn't recommend using software RAID (see notes in the Raid1 script) # # NOTE: There is no locking (such as a SCSI reservation) being done here. # I would if the SCSI driver could properly maintain the reservation, # which it cannot, even with the 'scsi reservation' patch submitted # earlier this year by James Bottomley. The patch minimizes the # bus resets caused by a RESERVATION_CONFLICT return, and helps the # reservation stay when 2 nodes contend for a reservation, # but it does not attempt to recover the reservation in the # case of a bus reset. # # What all this means is that if 2 nodes mount the same file system # read-write, 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. # # Note: the ServeRAID controller does prohibit concurrent acess # In this case, you don't actually need STONITH, but redundant comm is # still an excellent idea. # ####################################################################### # Initialization: . ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs ####################################################################### -# Utilities used by this script -MODPROBE=@MODPROBE@ -FSCK=@FSCK@ -FUSER=@FUSER@ -MOUNT=@MOUNT@ -UMOUNT=@UMOUNT@ -BLOCKDEV=@BLOCKDEV@ - -check_util () { - if [ ! -x `which $1` ] ; then - ocf_log err "Setup problem: Couldn't find utility $1" - exit $OCF_ERR_GENERIC - fi -} - usage() { cat <<-EOT usage: $0 {start|stop|status|monitor|validate-all|meta-data} EOT } meta_data() { cat < 1.0 Resource script for Filesystem. It manages a Filesystem on a shared storage medium. Filesystem resource agent The name of block device for the filesystem, or -U, -L options for mount, or NFS mount specification. block device The mount point for the filesystem. mount point The optional type of filesystem to be mounted. filesystem type Any extra options to be given as -o options to mount. options The name (UUID) of the OCFS2 cluster this filesystem is part of, iff this is an OCFS2 resource and there's more than one cluster. You should not need to specify this. OCFS2 cluster name/UUID Mountpoint of the cluster hierarchy below configfs. You should not need to specify this. OCFS2 configfs root 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 [ -z "$BLOCKDEV" -a "$BLOCKDEV" != "/dev/null" -a -x "$BLOCKDEV" -a "$blockdevice" = "yes" ]; then + if + have_binary $BLOCKDEV + if [ "$blockdevice" = "yes" ]; then $BLOCKDEV --flushbufs $1 return $? fi - return 0 + fi + return 0 } # Take advantage of /proc/mounts if present, use portabel mount command # otherwise. Normalize format to "dev mountpoint fstype". list_mounts() { if [ -f "/proc/mounts" -a -r "/proc/mounts" ]; then cut -d' ' -f1,2,3 /dev/null fi } ocfs2_cleanup() { # We'll never see the post-stop notification. We're gone now, # have unmounted, and thus should remove the membership. # # (Do so regardless of whether we were unmounted already, # because the admin might have manually unmounted but not # cleared up the membership directory. Bad admin, no cookie.) # if [ ! -d "$OCFS2_FS_ROOT" ]; then ocf_log info "$OCFS2_FS_ROOT: Filesystem membership already gone." else ocf_log info "$OCFS2_FS_ROOT: Removing membership directory." rm -rf $OCFS2_FS_ROOT/ fi ocfs2_del_cache } ocfs2_fetch_uuid() { mounted.ocfs2 -d $DEVICE|tail -1|awk '{print $3}'|tr -d -- -|tr '[a-z]' '[A-Z]' } ocfs2_set_uuid() { _OCFS2_uuid_cache="@HA_VARRUNHBRSCDIR@/Filesystem.ocfs2_uuid.$(echo $DEVICE|tr / .)" if [ "$OP" != "start" -a -e "$_OCFS2_uuid_cache" ]; then # Trust the cache. OCFS2_UUID=$(cat $_OCFS2_uuid_cache 2>/dev/null) return 0 fi OCFS2_UUID=$(ocfs2_fetch_uuid) if [ -n "$OCFS2_UUID" -a "$OCFS2_UUID" != "UUID" ]; then # UUID valid: echo $OCFS2_UUID > $_OCFS2_uuid_cache return 0 fi # Ok, no UUID still, but that's alright for stop, because it # very likely means we never got started - if [ "$OP" = "stop" ]; then ocf_log warn "$DEVICE: No UUID; assuming never started!" OCFS2_UUID="UUID_NOT_SET" return 0 fi # Everything else - wrong: ocf_log err "$DEVICE: Could not determine ocfs2 UUID for device." exit $OCF_ERR_GENERIC } ocfs2_init() { # Check & initialize the OCFS2 specific variables. if [ $OP != "stop" ]; then if [ -z "$OCF_RESKEY_CRM_meta_clone" ]; then ocf_log err "ocfs2 must be run as a clone." exit $OCF_ERR_GENERIC fi fi if [ $blockdevice = "no" ]; then ocf_log err "$DEVICE: ocfs2 needs a block device instead." exit $OCF_ERR_GENERIC fi for f in "$OCF_RESKEY_ocfs2_configfs" /sys/kernel/config/cluster /configfs/cluster ; do if [ -n "$f" -a -d "$f" ]; then OCFS2_CONFIGFS="$f" break fi done if [ ! -d "$OCFS2_CONFIGFS" ]; then ocf_log err "ocfs2 needs configfs mounted." exit $OCF_ERR_GENERIC fi ocfs2_set_uuid if [ -n "$OCF_RESKEY_ocfs2_cluster" ]; then OCFS2_CLUSTER=$(echo $OCF_RESKEY_ocfs2_cluster | tr '[a-z]' '[A-Z]') else OCFS2_CLUSTER=$(find "$OCFS2_CONFIGFS" -maxdepth 1 -mindepth 1 -type d -printf %f 2>/dev/null) set -- $OCFS2_CLUSTER local n="$#" if [ $n -gt 1 ]; then ocf_log err "$OCFS2_CLUSTER: several clusters found." exit $OCF_ERR_GENERIC fi if [ $n -eq 0 ]; then ocf_log err "$OCFS2_CONFIGFS: no clusters found." exit $OCF_ERR_GENERIC fi fi OCFS2_CLUSTER_ROOT="$OCFS2_CONFIGFS/$OCFS2_CLUSTER" if [ ! -d "$OCFS2_CLUSTER_ROOT" ]; then ocf_log err "$OCFS2_CLUSTER: Cluster doesn't exist. Maybe o2cb hasn't been run?" exit $OCF_ERR_GENERIC fi OCFS2_FS_ROOT=$OCFS2_CLUSTER_ROOT/heartbeat/$OCFS2_UUID } # # START: Start up the filesystem # Filesystem_start() { if [ "$FSTYPE" = "ocfs2" ]; then # "start" now has the notification data available; that # we're being started means we didn't get the # pre-notification, because we weren't running, so # process the information now first. ocf_log info "$OCFS2_UUID: Faking pre-notification on start." OCF_RESKEY_CRM_meta_notify_type="pre" OCF_RESKEY_CRM_meta_notify_operation="start" Filesystem_notify fi # 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 # Insert SCSI module # TODO: This probably should go away. Why should the filesystem # RA magically load a kernel module? $MODPROBE scsi_hostadapter >/dev/null 2>&1 if [ -z "$FSTYPE" ]; then : No FSTYPE specified, rely on the system has the right file-system support already else # Insert Filesystem module $MODPROBE $FSTYPE >/dev/null 2>&1 grep -e "$FSTYPE"'$' /proc/filesystems >/dev/null if [ $? -ne 0 ] ; then ocf_log err "Couldn't find filesystem $FSTYPE in /proc/filesystems" return $OCF_ERR_ARGS 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_ARGS fi if case $FSTYPE in ext3|reiserfs|reiser4|nss|xfs|jfs|vfat|fat|nfs|cifs|smbfs|ocfs2) false;; *) true;; esac then ocf_log info "Starting filesystem check on $DEVICE" if [ -z "$FSTYPE" ]; then $FSCK -a $DEVICE else $FSCK -t $FSTYPE -a $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 if [ ! -d "$MOUNTPOINT" ] ; then ocf_log err "Couldn't find directory [$MOUNTPOINT] to use as a mount point" exit $OCF_ERR_ARGS fi flushbufs $DEVICE # Mount the filesystem. if [ -z "$FSTYPE" ]; then $MOUNT $options $DEVICE $MOUNTPOINT else $MOUNT -t $FSTYPE $options $DEVICE $MOUNTPOINT fi if [ $? -ne 0 ]; then ocf_log err "Couldn't mount filesystem $DEVICE on $MOUNTPOINT" if [ "$FSTYPE" = "ocfs2" ]; then ocfs2_cleanup fi return $OCF_ERR_GENERIC fi return 0 } # end of Filesystem_start Filesystem_notify() { # Process notifications; this is the essential glue level for # giving user-space membership events to a cluster-aware # filesystem. Right now, only OCFS2 is supported. # # When we get a pre-start notification, we set up all the nodes # which will be active in our membership for the filesystem. # (For the resource to be started, this happens at the time of # the actual 'start' operation.) # # At a post-start, actually there's nothing to do for us really, # but no harm done in re-syncing either. # # pre-stop is meaningless; we can't remove any node yet, it # first needs to unmount. # # post-stop: the node is removed from the membership of the # other nodes. # # Note that this expects that the base cluster is already # active; ie o2cb has been started and populated # $OCFS2_CLUSTER_ROOT/node/ already. This can be achieved by # simply having o2cb run on all nodes by the CRM too. This # probably ought to be mentioned somewhere in the to be written # documentation. ;-) # if [ "$FSTYPE" != "ocfs2" ]; then # One of the cases which shouldn't occur; it should have # been caught much earlier. Still, you know ... ocf_log warn "$DEVICE: Notification received for non-ocfs2 mount." return $OCF_ERR_UNIMPLEMENTED fi 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 info "$OCFS2_UUID: notify: $n_type for $n_op" ocf_log info "$OCFS2_UUID: notify active: $n_active" ocf_log info "$OCFS2_UUID: notify stop: $n_stop" ocf_log info "$OCFS2_UUID: notify start: $n_start" case "$n_type" in pre) case "$n_op" in stop) ocf_log info "$OCFS2_UUID: ignoring pre-notify for stop." return $OCF_SUCCESS ;; start) # These are about to become active; prepare to # communicate with them. # Duplicate removal - start can contain nodes # already on the active list, confusing the # script later on: for UNAME in "$n_active"; do n_start="${n_start//$UNAME/}" done # Merge pruned lists again: n_active="$n_active $n_start" ;; esac ;; post) case "$n_op" in stop) # remove unames from notify_stop_uname; these have been # stopped and can no longer be considered active. for UNAME in "$n_stop"; do n_active="${n_active//$UNAME/}" done ;; start) if [ "$n_op" = "start" ]; then ocf_log info "$OCFS2_UUID: ignoring post-notify for start." return $OCF_SUCCESS fi ;; esac ;; esac ocf_log info "$OCFS2_UUID: post-processed active: $n_active" local n_myself=${HA_CURHOST:-$(uname -n | tr '[A-Z]' '[a-z]')} ocf_log info "$OCFS2_UUID: I am node $n_myself." case " $n_active " in *" $n_myself "*) ;; *) ocf_log err "$OCFS2_UUID: $n_myself (local) not on active list!" return $OCF_ERR_GENERIC ;; esac if [ -d "$OCFS2_FS_ROOT" ]; then entry_prefix=$OCFS2_FS_ROOT/ for entry in $OCFS2_FS_ROOT/* ; do n_fs="${entry##$entry_prefix}" # ocf_log info "$OCFS2_UUID: Found current node $n_fs" case " $n_active " in *" $n_fs "*) # Construct a list of nodes which are present # already in the membership. n_exists="$n_exists $n_fs" ocf_log info "$OCFS2_UUID: Keeping node: $n_fs" ;; *) # Node is in the membership currently, but not on our # active list. Must be removed. if [ "$n_op" = "start" ]; then ocf_log warn "$OCFS2_UUID: Removing nodes on start" fi ocf_log info "$OCFS2_UUID: Removing dead node: $n_fs" if ! rm -f $entry ; then ocf_log err "$OCFS2_UUID: Removal of $n_fs failed!" fi ;; esac done else ocf_log info "$OCFS2_UUID: heartbeat directory doesn't exist yet, creating." mkdir -p $OCFS2_FS_ROOT fi ocf_log info "$OCFS2_UUID: Existing node list: $n_exists" # (2) for entry in $n_active ; do # ocf_log info "$OCFS2_UUID: Expected active node: $entry" case " $n_exists " in *" $entry "*) ocf_log info "$OCFS2_UUID: Already active: $entry" ;; *) if [ "$n_op" = "stop" ]; then ocf_log warn "$OCFS2_UUID: Adding nodes on stop" fi ocf_log info "$OCFS2_UUID: Activating node: $entry" if ! ln -s $OCFS2_CLUSTER_ROOT/node/$entry $OCFS2_FS_ROOT/$entry ; then ocf_log err "$OCFS2_CLUSTER_ROOT/node/$entry: failed to link" fi ;; esac done } # # 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 # 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 nfs|cifs|smbfs) umount_force="-f" ;; esac # Umount all sub-filesystems mounted under $MOUNTPOINT/ too. for SUB in `list_submounts $MOUNTPOINT` $MOUNTPOINT; do ocf_log info "Trying to unmount $MOUNTPOINT" for sig in SIGTERM SIGTERM SIGTERM SIGKILL SIGKILL SIGKILL; do if $UMOUNT $umount_force $SUB ; then rc=$OCF_SUCCESS ocf_log info "unmounted $SUB successfully" break else rc=$OCF_ERR_GENERIC ocf_log err "Couldn't unmount $SUB; trying cleanup with $sig" # fuser returns a non-zero return code if none of the # specified files is accessed or in case of a fatal # error. if $FUSER -$sig -m -k $SUB ; then ocf_log info "Some processes on $SUB were signalled" else ocf_log info "No processes on $SUB were signalled" fi sleep 1 fi done if [ $rc -ne $OCF_SUCCESS ]; then ocf_log err "Couldn't unmount $SUB, giving up!" fi done fi flushbufs $DEVICE if [ "$FSTYPE" = "ocfs2" ]; then ocfs2_init ocfs2_cleanup fi 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 # TODO: For ocfs2, or other cluster filesystems, should we be # checking connectivity to other nodes here, or the IO path to # the storage? # 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 # # 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" ]; 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 #TODO: How to check the $options ? return $OCF_SUCCESS } # 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 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 blockdevice=no case $DEVICE in "") ocf_log err "Please set OCF_RESKEY_device to the device to be managed" exit $OCF_ERR_ARGS ;; -*) # Oh... An option to mount instead... Typically -U or -L ;; [^/]*:/*) # An NFS filesystem specification... ;; //[^/]*/*) # An SMB filesystem specification... ;; /dev/null) # Special case for BSC blockdevice=yes ;; *) if [ ! -b "$DEVICE" -a "X$OP" != Xstart ] ; then ocf_log warn "Couldn't find device [$DEVICE]. Expected /dev/??? to exist" fi blockdevice=yes ;; esac # 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_ARGS 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 -check_util $MODPROBE -check_util $FSCK -check_util $FUSER -check_util $MOUNT -check_util $UMOUNT +check_binary $MODPROBE +check_binary $FSCK +check_binary $FUSER +check_binary $MOUNT +check_binary $UMOUNT if [ "$OP" != "monitor" ]; then ocf_log info "Running $OP for $DEVICE on $MOUNTPOINT" fi # These operations do not require the clone checking + OCFS2 # initialization. case $OP in status|monitor) Filesystem_status exit $? ;; validate-all) Filesystem_validate_all exit $? ;; stop) Filesystem_stop exit $? ;; esac case $FSTYPE in ocfs2) ocfs2_init ;; nfs) : # this is kind of safe too ;; *) if [ -n "$OCF_RESKEY_CRM_meta_clone" ]; then 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_GENERIC fi ;; esac case $OP in start) Filesystem_start ;; notify) Filesystem_notify ;; *) usage exit $OCF_ERR_UNIMPLEMENTED ;; esac exit $? diff --git a/heartbeat/ICP.in b/heartbeat/ICP.in index 05bda8e2f..41383f1ae 100644 --- a/heartbeat/ICP.in +++ b/heartbeat/ICP.in @@ -1,294 +1,295 @@ #!/bin/sh # # # ICP # # Description: Manages an ICP Vortex clustered host drive as an HA resource # # # Author: Lars Marowsky-Bree # Support: linux-ha@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_ROOT}/resource.d/heartbeat/.ocf-shellfuncs ####################################################################### # ICPCLUCON=/usr/sbin/icpclucon # -BLOCKDEV=@BLOCKDEV@ -# 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 < 1.0 Resource script for ICP. It Manages an ICP Vortex clustered host drive as an HA resource. ICP resource agent The ICP cluster drive ID. ICP cluster drive ID The device name. device 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_start $driveid + 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.in b/heartbeat/IPaddr.in index e081ab342..e7db6740f 100644 --- a/heartbeat/IPaddr.in +++ b/heartbeat/IPaddr.in @@ -1,833 +1,834 @@ #!/bin/sh # # License: GNU General Public License (GPL) # Support: linux-ha@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_ROOT}/resource.d/heartbeat/.ocf-shellfuncs -AWK=@AWK@ -HA_VARRUNHBRSCDIR=${HA_RSCTMP} HA_HBCONF_DIR=${HA_DIR} -IFCONFIG=@IFCONFIG@ -IFCONFIG_A_OPT=@IFCONFIG_A_OPT@ SENDARP=$HA_BIN/send_arp FINDIF=$HA_BIN/findif -VLDIR=$HA_VARRUNHBRSCDIR/IPaddr -SENDARPPIDDIR=$HA_VARRUNHBRSCDIR/send_arp +VLDIR=$HA_RSCTMP/IPaddr +SENDARPPIDDIR=$HA_RSCTMP/send_arp SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$OCF_RESKEY_ip" -ROUTE=@ROUTE@ USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}"; ####################################################################### # Prevent ifconfig localization issues unset LC_ALL; export LC_ALL unset LANGUAGE; export LANGUAGE LC_ALL=C; export LC_ALL LC_MESSAGES=C; export LC_MESSAGES . $HA_HBCONF_DIR/shellfuncs 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 < 1.0 This script manages IP alias IP addresses It can add an IP alias, or remove one. Manages virtual IPv4 addresses The IPv4 address to be configured in dotted quad notation, for example "192.168.1.1". IPv4 address 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. Network interface 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. Netmask Broadcast address associated with the IP. If left empty, the script will determine this from the netmask. Broadcast address You can specify an additional label for your IP address here. Interface label 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. Enable support for LVS DR Script called when the IP is released Script called when the IP is released Script called when the IP is added Script called when the IP is added milliseconds between ARPs milliseconds between gratuitous ARPs How many gratuitous ARPs to send out when bringing up a new address repeat count run in background (no longer any reason to do this) run in background netmask for ARP - in nonstandard hexadecimal format. netmask for ARP END exit $OCF_SUCCESS } # 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 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` then netmask_text=`echo "$NICINFO" | cut -f2` broadcast=`echo "$NICINFO" | cut -f3` 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 | grep "inet.*[: ]$OCF_RESKEY_ip " $IFCONFIG | grep "$ipaddr" -B20 | grep "UP," | tail -n 1 | cut -d ":" -f 1 } # # 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 *:*) ;; *) 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/$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/$NIC" if [ $rc != 0 ]; then ocf_log warn "IP Address $OCF_RESKEY_ip NOT released" fi return $rc } # # 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 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" 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="" fi if [ x$SENDARP != x ]; 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 - if @PING@ $PINGARGS >/dev/null 2>&1 ; then + if $PING $PINGARGS >/dev/null 2>&1 ; then return $OCF_SUCCESS fi done 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 [ -d "$VLDIR/" ] || mkdir -p "$VLDIR/" then : Directory $VLDIR now exists else ocf_log err "Could not create \"$VLDIR/\"." return $OCF_ERR_GENERIC fi 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 [ -z "$OCF_RESKEY_cidr_netmask" ] then ocf_log debug "Using calculated netmask for ${OCF_RESKEY_ip}: $tmp" OCF_RESKEY_cidr_netmask=$tmp; export OCF_RESKEY_cidr_netmask elif [ "x$OCF_RESKEY_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 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" ]; 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.in b/heartbeat/IPaddr2.in index 23c8b8b92..e291a0016 100644 --- a/heartbeat/IPaddr2.in +++ b/heartbeat/IPaddr2.in @@ -1,806 +1,806 @@ #!/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_ROOT}/resource.d/heartbeat/.ocf-shellfuncs -HA_VARRUNHBRSCDIR=${HA_RSCTMP} -IP2UTIL="@IP2UTIL@" -IPTABLES="@IPTABLES@" -MODPROBE="@MODPROBE@" SENDARP=$HA_BIN/send_arp FINDIF=$HA_BIN/findif -VLDIR=$HA_VARRUNHBRSCDIR/IPaddr -SENDARPPIDDIR=$HA_VARRUNHBRSCDIR/send_arp -CIP_lockfile=$HA_VARRUNHBRSCDIR/IPaddr2-CIP-${OCF_RESKEY_ip} +VLDIR=$HA_RSCTMP/IPaddr +SENDARPPIDDIR=$HA_RSCTMP/send_arp +CIP_lockfile=$HA_RSCTMP/IPaddr2-CIP-${OCF_RESKEY_ip} ####################################################################### meta_data() { cat < 1.0 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. Manages virtual IPv4 addresses The IPv4 address to be configured in dotted quad notation, for example "192.168.1.1". IPv4 address 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. Network interface 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. CIDR netmask Broadcast address associated with the IP. If left empty, the script will determine this from the netmask. Broadcast address You can specify an additional label for your IP address here. This label is appended to your interface name. If a label is specified in nic name, this parameter has no effect. Interface label 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. Enable support for LVS DR Set the interface MAC address explicitly. Currently only used in case of the Cluster IP Alias. Leave empty to chose automatically. Cluster IP MAC address Specify the hashing algorithm used for the Cluster IP functionality. Cluster IP hashing function Specify the interval between unsolicited ARP packets in milliseconds. ARP packet interval in ms Number of unsolicited ARP packets to send. ARP packet count Whether or not to send the arp packets in the background. ARP from background MAC address to send the ARP packets too. You really shouldn't be touching this. ARP MAC END exit $OCF_SUCCESS } ip_init() { if [ X`uname -s` != "XLinux" ]; then ocf_log err "IPaddr2 only supported Linux." exit $OCF_ERR_INSTALLED 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 if [ ! -x "$IP2UTIL" ]; then ocf_log err "$IP2UTIL not found." exit $OCF_ERR_INSTALLED 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" LVS_SUPPORT=0 if [ x"${OCF_RESKEY_lvs_support}" = x"true" \ -o x"${OCF_RESKEY_lvs_support}" = x"on" \ -o x"${OCF_RESKEY_lvs_support}" = x"1" ]; then LVS_SUPPORT=1 fi IP_INC_GLOBAL=${OCF_RESKEY_CRM_meta_clone_max:-1} IP_INC_NO=$((OCF_RESKEY_CRM_meta_clone+1)) IP_CIP_HASH="${OCF_RESKEY_clusterip_hash}" if [ $LVS_SUPPORT -gt 0 ] && [ $IP_INC_GLOBAL -gt 1 ]; then ocf_log err "LVS and load sharing do not go together well" exit OCF_ERR_ARGS fi ARP_INTERVAL_MS=${OCF_RESKEY_arp_interval:-200} ARP_REPEAT=${OCF_RESKEY_arp_count:-5} ARP_BACKGROUND=${OCF_RESKEY_arp_bg:-yes} ARP_NETMASK=${OCF_RESKEY_arp_mac:-ffffffffffff} 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_ARGS fi # Validation is performed in ip_validate()... # # $FINDIF now takes its parameters from the environment # if NICINFO=`$FINDIF -C` 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 ocf_log err "[$FINDIF -C] failed" exit $OCF_ERR_ARGS fi SENDARPPIDFILE="$SENDARPPIDDIR/send_arp-$BASEIP" case $NIC in *:*) IFLABEL=$NIC NIC=`echo $NIC | sed 's/:.*//'` ;; *) if [ -n "$IFLABEL" ]; then IFLABEL=${NIC}:${IFLABEL} fi ;; esac IP_CIP= if [ "$IP_INC_GLOBAL" -gt 1 ]; then if [ ! -x "$IPTABLES" ]; then ocf_log err "Cluster Alias IP mode selected, but iptables not configured" exit $OCF_ERR_INSTALLED fi IP_CIP="yes" 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 $BASEIP $NETMASK $BRDCAST | \ md5sum | \ sed -e 's#\(............\).*#\1#' \ -e 's#..#&:#g; s#:$##' \ -e 's#^\(.\)[02468aAcCeE]#\11#'` fi IP_CIP_FILE="/proc/net/ipt_CLUSTERIP/$BASEIP" fi } # # Find out which interface serves the given IP address # The argument is an IP address, and its output # is an interface name (e.g., "eth0"). # find_interface() { # # List interfaces but exclude FreeS/WAN ipsecN virtual interfaces # local iface=`$IP2UTIL -o -f inet addr show | grep "\ $BASEIP/" \ | 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 inet addr delete $ipaddr/$netmask dev $iface" ocf_log info "$CMD" $CMD if [ $? -ne 0 ]; then return $OCF_ERR_GENERIC fi CMD="$IP2UTIL -o -f inet addr show $iface" ocf_log info "$CMD" ADDR=`$CMD` if [ $? -ne 0 -o ! -z "$ADDR" ]; then return $? fi CMD="$IP2UTIL link set $iface down" ocf_log info "$CMD" $CMD return $? } # # Add an interface # add_interface () { ipaddr="$1" netmask="$2" broadcast="$3" iface="$4" label="$5" CMD="$IP2UTIL -f inet addr add $ipaddr/$netmask brd $broadcast dev $iface" if [ ! -z "$label" ]; then CMD="$CMD label $label" fi ocf_log info "$CMD" $CMD if [ $? -ne 0 ]; then return $OCF_ERR_GENERIC fi CMD="$IP2UTIL link set $iface up" ocf_log info "$CMD" $CMD return $? } # # 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 [ -d "$VLDIR/" ] || mkdir -p "$VLDIR/"; then : Directory $VLDIR now exists else ocf_log err "Could not create \"$VLDIR/\" conflicting" \ " loopback $ifname cannot be restored." fi 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 } # # Run send_arp to note peers about new mac address # run_send_arp() { - ARGS="-i $ARP_INTERVAL_MS -r $ARP_REPEAT -p $SENDARPPIDFILE $NIC $BASEIP auto $BASEIP $ARP_NETMASK" + ARGS="-i $ARP_INTERVAL_MS -r $ARP_REPEAT -p $SENDARPPIDFILE $NIC $BASEIP auto not_used not_used" if [ $IP_CIP="yes" ] ; then - MY_MAC=${IF_MAC//:/} - ARGS="-i $ARP_INTERVAL_MS -r $ARP_REPEAT -p $SENDARPPIDFILE $NIC $BASEIP $MY_MAC $BASEIP $ARP_NETMASK" + MY_MAC=`echo ${IF_MAC} | sed -e 's/://'` + ARGS="-i $ARP_INTERVAL_MS -r $ARP_REPEAT -p $SENDARPPIDFILE $NIC $BASEIP $MY_MAC not_used not_used" fi ocf_log info "$SENDARP $ARGS" case $ARP_BACKGROUND in yes) ($SENDARP $ARGS || ocf_log err "Could not send gratuitous arps" &) >&2 ;; *) $SENDARP $ARGS || ocf_log err "Could not send gratuitous arps" ;; esac } # Do we already serve this IP address? # # returns: # ok = served (for CIP: + hash bucket) # partial = served and no hash bucket (CIP only) # no = nothing # ip_served() { cur_nic="`find_interface $BASEIP`" if [ -z "$cur_nic" ]; then echo "no" return 0 fi if [ -z "$IP_CIP" ]; then case $cur_nic in lo*) if [ "$LVS_SUPPORT" = "1" ]; then echo "no" return 0 fi ;; esac echo "ok" return 0 fi # Special handling for the CIP: if grep -q "^${IP_INC_NO},\|,${IP_INC_NO},\|,${IP_INC_NO}$\|^${IP_INC_NO}$" $IP_CIP_FILE ; then echo "ok" return 0 else echo "partial" return 0 fi exit $OCF_ERR_GENERIC } ####################################################################### ip_usage() { cat <$IP_CIP_FILE fi if [ "$ip_status" = "no" ]; then if [ "$LVS_SUPPORT" = "1" ]; then case `find_interface $BASEIP` in lo*) remove_conflicting_loopback $BASEIP 32 255.255.255.255 lo ;; esac fi add_interface $BASEIP $NETMASK $BRDCAST $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 ;; *) run_send_arp ;; esac exit $OCF_SUCCESS } ip_stop() { ip_init 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 $BASEIP" else ocf_log info "killed previously running send_arp for $BASEIP" rm -f "$SENDARPPIDFILE" fi fi local ip_status=`ip_served` if [ $ip_status = "no" ]; then : Requested interface not in use exit $OCF_SUCCESS fi if [ -n "$IP_CIP" ]; 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 $BASEIP, $IP_CIP_HASH for ((i=1; i<=$IP_INC_GLOBAL; i++)) ; do ocf_log info $i $IPTABLES -D INPUT -d $BASEIP -i $NIC -j CLUSTERIP \ --new \ --clustermac $IF_MAC \ --total-nodes $IP_INC_GLOBAL \ --local-node $i \ --hashmode $IP_CIP_HASH done else ip_del_if="no" fi fi if [ "$ip_del_if" = "yes" ]; then delete_interface $BASEIP $NIC $NETMASK if [ $? -ne 0 ]; then exit $OCF_ERR_GENERIC fi if [ "$LVS_SUPPORT" = 1 ]; then restore_loopback "$BASEIP" fi fi exit $OCF_SUCCESS } ip_monitor() { ip_init # 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) exit $OCF_NOT_RUNNING ;; *) # Errors on this interface? return $OCF_ERR_GENERIC ;; esac } ip_validate() { + check_binary $IP2UTIL + check_binary $IPTABLES + check_binary $MODPROBE + ip_init # $BASEIP, $NETMASK, $NIC , $IP_INC_GLOBAL, and $BRDCAST have been checked within ip_init, # do not bother here. if ocf_is_decimal "$ARP_INTERVAL_MS" && [ $ARP_INTERVAL_MS -gt 0 ]; then : else ocf_log err "Invalid OCF_RESKEY_arp_interval [$ARP_INTERVAL_MS]" exit $OCF_ERR_ARGS fi if ocf_is_decimal "$ARP_REPEAT" && [ $ARP_REPEAT -gt 0 ]; then : else ocf_log err "Invalid OCF_RESKEY_arp_count [$ARP_REPEAT]" exit $OCF_ERR_ARGS 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_ARGS ;; esac if [ "$LVS_SUPPORT" = 1 ]; then ecf_log err "LVS and load sharing not advised to try" exit $OCF_ERR_ARGS fi case $IF_MAC in [0-9a-zA-Z][1379bBdDfF][^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_ARGS fi fi exit $OCF_SUCCESS } case $__OCF_ACTION in meta-data) meta_data ;; start) ip_start ;; stop) ip_stop ;; status) ip_init 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_validate ;; usage|help) ip_usage exit $OCF_SUCCESS ;; *) ip_usage exit $OCF_ERR_UNIMPLEMENTED ;; esac diff --git a/heartbeat/IPsrcaddr.in b/heartbeat/IPsrcaddr.in index 185050bde..8dd8869ca 100644 --- a/heartbeat/IPsrcaddr.in +++ b/heartbeat/IPsrcaddr.in @@ -1,466 +1,466 @@ #!/bin/sh # # Description: IPsrcaddr - Preferred source address modification # # Author: John Sutton # Support: linux-ha@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_ROOT}/resource.d/heartbeat/.ocf-shellfuncs ####################################################################### -AWK=@AWK@ -IPROUTE=@IP2UTIL@ -IFCONFIG=@IFCONFIG@ -IFCONFIG_A_OPT=@IFCONFIG_A_OPT@ USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}"; - CMDSHOW="$IPROUTE route show to exact 0/0" -CMDCHANGE="$IPROUTE route change to " + CMDSHOW="$IP2UTIL route show to exact 0/0" +CMDCHANGE="$IP2UTIL route change to " SYSTYPE="`uname -s`" usage() { echo $USAGE >&2 } meta_data() { cat < 1.0 Resource script for IPsrcaddr. It manages the preferred source address modification. IPsrcaddr resource agent The IP address. IP address 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.*\|$\)" 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 $CMDCHANGE $ROUTE_WO_SRC src $1 || \ errorexit "command '$CMDCHANGE $ROUTE_WO_SRC src $1' failed" return $? } # # 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" $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_ARGS fi else true fi # return $OCF_SUCCESS ;; *) #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() { $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 "$SYSTYPE" in *BSD) $IFCONFIG | grep "$BASEIP" -B`$IFCONFIG | grep -c inet` | grep "UP," | cut -d ":" -f 1 return 0;; *) : "comparing $BASEIP to $addr (from ifconfig)" case $addr in addr:$BASEIP) echo $ifname; return $OCF_SUCCESS;; $BASEIP) echo $ifname; return $OCF_SUCCESS;; esac continue;; 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() { 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"` # echo $IF 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_ARGS ;; *)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 $IPROUTE + 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_ARGS 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_ARGS 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_ARGS fi ipaddress="$OCF_RESKEY_ipaddress" 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 # 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 # Changed status output to "OK" to satisfy ResourceManager's # we_own_resource() function. # # Version 0.1 2002/11/01 17:00:00 John Sutton # First effort but does the job? # diff --git a/heartbeat/LVM.in b/heartbeat/LVM.in index 66ff2f119..6f215d77b 100644 --- a/heartbeat/LVM.in +++ b/heartbeat/LVM.in @@ -1,341 +1,342 @@ #!/bin/sh # # # LVM # # Description: Manages an LVM volume as an HA resource # # # Author: Alan Robertson # Support: linux-ha@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_ROOT}/resource.d/heartbeat/.ocf-shellfuncs ####################################################################### -AWK=@AWK@ usage() { methods=`LVM_methods` methods=`echo $methods | tr ' ' '|'` cat <<-! 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 'methods' operation reports on the methods $0 supports ! exit $OCF_ERR_GENERIC } meta_data() { cat < 1.0 Resource script for LVM. It manages an Linux Volume Manager volume (LVM) as an HA resource. LVM resource agent The name of volume group. Volume group name END } # # methods: What methods/operations do we support? # LVM_methods() { cat <<-! start stop status monitor methods validate-all usage ! } # # Return LVM status (silently) # LVM_status() { if [ "$LVM_MAJOR" -eq "1" ] then vgdisplay $1 | grep -i 'Status.*available' >/dev/null return $? else vgdisplay -v $1 | grep -i 'Status[ \t]*available' >/dev/null return $? fi } # # Report on LVM volume status to stdout... # LVM_report_status() { if [ "$LVM_MAJOR" -eq "1" ] then VGOUT=`vgdisplay $1 2>&1` echo "$VGOUT" | grep -i 'Status.*available' >/dev/null rc=$? else VGOUT=`vgdisplay -v $1 2>&1` echo "$VGOUT" | grep -i 'Status[ \t]*available' >/dev/null rc=$? fi if [ $rc -eq 0 ] then : Volume $1 is available else ocf_log debug "LVM Volume $1 is not available (stopped)" return $OCF_NOT_RUNNING fi if echo "$VGOUT" | grep -i 'Access.*read/write' >/dev/null then ocf_log debug "Volume $1 is available read/write (running)" else ocf_log debug "Volume $1 is available read-only (running)" fi return $OCF_SUCCESS } # # Monitor the volume - does it really seem to be working? # # LVM_monitor() { if LVM_status $1 then : OK else ocf_log info "LVM Volume $1 is offline" return $OCF_NOT_RUNNING fi ocf_run vgck $1 return $? } # # Enable LVM volume # LVM_start() { # TODO: This MUST run vgimport as well ocf_log info "Activating volume group $1" if [ "$LVM_MAJOR" -eq "1" ] then ocf_run vgscan $1 else ocf_run vgscan fi # TODO: For v2, this MUST use --refresh ocf_run vgchange -a y $1 || return $OCF_ERR_GENERIC if LVM_status $1 then : OK Volume $1 activated just fine! return $OCF_SUCCESS else ocf_log err "LVM: $1 did not activate correctly" return $OCF_ERR_GENERIC fi } # # Disable the LVM volume # LVM_stop() { ocf_log info "Deactivating volume group $1" ocf_run vgchange -a n $1 || return 1 if LVM_status $1 then ocf_log err "LVM: $1 did not stop correctly" return $OCF_ERR_GENERIC fi # TODO: This MUST run vgexport as well return $OCF_SUCCESS } # # Check whether the OCF instance parameters are valid # LVM_validate_all() { + check_binary $AWK + # Off-the-shelf tests... vgck "$VOLUME" >/dev/nulll 2>&1 if [ $? -ne 0 ]; then ocf_log err "Volume group [$VOLUME] does not exist or contains error!" exit $OCF_ERR_GENERIC fi # Double-check if [ "$LVM_MAJOR" -eq "1" ] then vgdisplay "$VOLUME" >/dev/null 2>&1 else vgdisplay -v "$VOLUME" >/dev/null 2>&1 fi if [ $? -ne 0 ]; then ocf_log err "Volume group [$VOLUME] does not exist or contains error!" exit $OCF_ERR_GENERIC fi 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 # echo "You must identify the volume group name!" ocf_log err "You must identify the volume group name!" # usage exit $OCF_ERR_ARGS 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_GENERIC fi LVM_MAJOR="${LVM_VERSION%%.*}" VOLUME=$OCF_RESKEY_volgrpname # What kind of method was invoked? case "$1" in start) LVM_start $VOLUME exit $?;; stop) LVM_stop $VOLUME exit $?;; status) LVM_report_status $VOLUME exit $?;; monitor) LVM_monitor $VOLUME exit $?;; validate-all) LVM_validate_all ;; *) usage exit $OCF_ERR_AEGS;; esac diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am index 47b9639de..6f57535e6 100644 --- a/heartbeat/Makefile.am +++ b/heartbeat/Makefile.am @@ -1,92 +1,94 @@ # 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-returncodes INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/linux-ha ocfdir = @OCF_RA_DIR@/heartbeat gliblib = @GLIBLIB@ if USE_IPV6ADDR ocf_PROGRAMS = IPv6addr else ocf_PROGRAMS = endif IPv6addr_SOURCES = IPv6addr.c IPv6addr_LDADD = $(top_builddir)/lib/clplumbing/libplumb.la \ $(gliblib) @LIBNETLIBS@ \ $(top_builddir)/lib/pils/libpils.la ocf_SCRIPTS = ClusterMon \ Dummy \ IPaddr \ IPaddr2 \ drbd \ apache \ AudibleAlarm \ db2 \ Delay \ drbd \ eDir88 \ EvmsSCC \ Evmsd \ Filesystem \ ICP \ IPsrcaddr \ LinuxSCSI \ LVM \ MailTo \ ManageRAID \ ManageVE \ mysql \ o2cb \ oracle \ oralsnr \ pingd \ portblock \ pgsql \ Pure-FTPd \ Raid1 \ rsyncd \ SAPDatabase \ SAPInstance \ SendArp \ ServeRAID \ Stateful \ SysInfo \ VIPArip \ WAS \ WAS6 \ WinPopup \ Xen \ Xinetd \ - .ocf-shellfuncs + .ocf-shellfuncs \ + .ocf-binaries \ + .ocf-directories commondir = @hb_libdir@ common_SCRIPTS = ocf-shellfuncs ocf-returncodes .ocf-shellfuncs: ocf-shellfuncs cp $(top_srcdir)/resources/OCF/ocf-shellfuncs .ocf-shellfuncs diff --git a/heartbeat/Raid1.in b/heartbeat/Raid1.in index bc4b23910..24f10c403 100644 --- a/heartbeat/Raid1.in +++ b/heartbeat/Raid1.in @@ -1,407 +1,399 @@ #!/bin/sh # # # License: GNU General Public License (GPL) # Support: linux-ha@lists.linux-ha.org # # Raid1 # Description: Manages a software Raid1 device on a shared storage medium. # Original Author: Eric Z. Ayers (eric.ayers@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@vger.kernel.org # # usage: $0 {start|stop|status|monitor|validate-all|usage|meta-data} # # OCF parameters are as below: # OCF_RESKEY_raidconf # (name of MD configuration file. e.g. /etc/raidtab or /etc/mdadm.conf) # OCF_RESKEY_raiddev # (of the form /dev/md* the block device to use) # # in /etc/ha.d/haresources, use a line such as: # nodea 10.0.0.170 Raid1::/etc/raidtab.md0::/dev/md0 Filesystem::/dev/md0::/data1::ext2 # (for systems with raidtools) # or # nodea 10.0.0.170 Raid1::/etc/mdadm.conf::/dev/md0 Filesystem::/dev/md0::/data1::ext2 # (for systems with mdadm) # # The "start" arg starts up the raid device # The "stop" arg stops it. NOTE: all filesystems must be unmounted # and no processes should be accessing the device. # The "status" arg just prints out whether the device is running or not # # # DISCLAIMER: Use at your own risk! # # Besides all of the usual legalese that accompanies free software, # I will warn you that I do not yet use this kind of setup (software RAID # over shared storage) in production, and I have reservations about doing so. # # The linux md driver/scsi drivers under Raid 0.90 and kernel version 2.2 # do not behave well when a drive is in the process of going bad. # The kernel slows down, but doesn't completely crash. This is about the # worst possible thing that could happen in an un-attended HA type # environment. (Once the system is rebooted, the sofware raid stuff works # like a champ.) # My other reservation has to do with the interation of RAID recovery with # journaling filesystems and other parts of the kernel. Subscribe to # linux-raid@vger.kernel.org for other opinions and possible solutions. # # -EZA 25 Oct 2000 # # SETUP: # # You might need to pass the command line parameter: raid=noautodetect # in an HA environment so that the kernel doesn't automatically start # up your raid partitions when you boot the node. This means that it isn't # going to work to use RAID for the system disks and the shared disks. # # 0) partition the disks to use for RAID. Use normal Linux partition # types, not the RAID autodetect type for your partitions. # 1) Create /etc/raidtab.md? on both systems (see example file below) # or for systems with mdadm tools create /etc/mdadm.conf (see example below) # 2) Initialize your raid partition with # /sbin/mkraid --configfile /etc/raidtab.md? /dev/md? # or create mirror raid with the following command # mdadm --create /dev/md? -l 1 -n 2 /dev/sdb? /dev/sdb? # 3) Format your filesystem # mke2fs /dev/md0 # for ext2fs... a journaling filesystem would be nice # 3) Create the mount point on both systems. # DO NOT add your raid filesystem to /etc/fstab # 4) copy this script (to /etc/rc.d/init.d if you wish) and edit it to # reflect your desired settings. # 5) Modify the heartbeat 'haresources' (for non-crm heartbeat) or 'cib.xml' (for crm heartbeat) setup file # 6) unmount the filesystem and stop the raid device with 'raidstop' or 'mdadm -S' # 7) fire up heartbeat! # # # 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/sdb2 # ARRAY /dev/md0 level=raid1 UUID=4a865b55:ba27ef8d:29cd5701:6fb42799 ####################################################################### # Initialization: . ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs ####################################################################### -# Utilities used by this script -MODPROBE=@MODPROBE@ -FSCK=@FSCK@ -FUSER=@FUSER@ -RAIDSTART=@RAIDSTART@ -MOUNT=@MOUNT@ -UMOUNT=@UMOUNT@ -RAIDSTOP=@RAIDSTOP@ -MDADM=@MDADM@ - check_util () { if [ ! -x "$1" ] ; then ocf_log err "setup problem: Couldn't find utility $1" exit $OCF_ERR_GENERIC fi } usage() { cat <<-EOT usage: $0 {start|stop|status|monitor|validate-all|usage|meta-data} EOT } meta_data() { cat < 1.0 Resource script for RAID1. It manages a software Raid1 device on a shared storage medium. RAID1 resource agent The RAID configuration file. e.g. /etc/raidtab or /etc/mdadm.conf. RAID config file The block device to use. block device END } # # START: Start up the RAID device # raid1_start() { # See if the md device is already mounted. $MOUNT | grep -e "^$MDDEV\>" >/dev/null if [ $? -ne 1 ] ; then ocf_log err "Device $MDDEV is already mounted!" return $OCF_ERR_GENERIC fi if [ "running" = `raid1_status` ]; then # We are already online, do not bother return $OCF_SUCCESS fi # Insert SCSI module $MODPROBE scsi_hostadapter if [ $? -ne 0 ] ; then ocf_log warn "Couldn't insert SCSI module." fi # Insert raid personality module $MODPROBE raid1 if [ $? -ne 0 ] ; then # It is not fatal, chance is that we have raid1 builtin... ocf_log warn "Couldn't insert RAID1 module" fi grep -q "^Personalities.*\[raid1\]" /proc/mdstat 2>/dev/null if [ $? -ne 0 ] ; then ocf_log err "We don't have RAID1 support! Exiting" return $OCF_ERR_GENERIC fi if [ $HAVE_RAIDTOOLS = "true" ]; then # Run raidstart to start up the RAID array $RAIDSTART --configfile $RAIDCONF $MDDEV else # Run mdadm $MDADM --assemble $MDDEV --config=$RAIDCONF fi if [ "running" = `raid1_status` ]; then return $OCF_SUCCESS else ocf_log err "Couldn't start RAID for $MDDEV" return $OCF_ERR_GENERIC fi } # # STOP: stop the RAID device # raid1_stop() { # See if the MD device is online if [ "stopped" = `raid1_status` ]; then return $OCF_SUCCESS fi # See if the MD device is mounted $MOUNT | grep -e "^$MDDEV\>" >/dev/null if [ $? -ne 1 ] ; then # Kill all processes open on filesystem $FUSER -m -k $MDDEV # the return from fuser doesn't tell us much #if [ $? -ne 0 ] ; then # ocf_log "err" "Couldn't kill processes on $MOUNTPOINT" # return 1; #fi # Unmount the filesystem $UMOUNT $MDDEV $MOUNT | grep -e "^$MDDEV\>" >/dev/null if [ $? -ne 1 ] ; then ocf_log err "filesystem for $MDDEV still mounted" return $OCF_ERR_GENERIC fi fi # Turn off raid if [ $HAVE_RAIDTOOLS = "true" ]; then $RAIDSTOP --configfile $RAIDCONF $MDDEV else $MDADM --stop $MDDEV --config=$RAIDCONF fi if [ $? -ne 0 ] ; then ocf_log err "Couldn't stop RAID for $MDDEV" return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } # # STATUS: is the raid device online or offline? # raid1_status() { # See if the MD device is online grep -e "^$MD[ \t:]" /proc/mdstat >/dev/null if [ $? -ne 0 ] ; then echo "stopped" return $OCF_NOT_RUNNING else echo "running" return $OCF_SUCCESS fi } raid1_validate_all() { + # Utilities used by this script + check_binary $MODPROBE + check_binary $FSCK + check_binary $FUSER + check_binary $MOUNT + check_binary $UMOUNT + if [ $HAVE_RAIDTOOLS = "true" ]; then # $MDDEV should be an md device lsraid -a $MDDEV 2>&1 | grep -q -i "is not an md device" if [ $? -eq 0 ]; then ocf_log err "$MDDEV is not an md device!" exit $OCF_ERR_ARGS fi COMMENT="\(#.*\)" grep -q "^[[:space:]]*raiddev[[:space:]]\+$MDDEV[[:space:]]*$COMMENT\?$" $RAIDCONF 2>/dev/null if [ $? -ne 0 ]; then ocf_log err "Raid device $MDDEV does not appear in $RAIDCONF" exit $OCF_ERR_GENERIC fi else error=`$MDADM --query $MDDEV 2>&1` if [ $? -ne 0 ]; then ocf_log err "$error" exit $OCF_ERR_GENERIC fi echo $error | grep -q -i "^$MDDEV[ \t:].*is not an md array" if [ $? -eq 0 ]; then ocf_log err "$MDDEV is not an md array!" exit $OCF_ERR_ARGS fi 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 # # Check the necessary enviroment virable's setting # RAIDCONF=$OCF_RESKEY_raidconf MDDEV=$OCF_RESKEY_raiddev if [ -z "$RAIDCONF" ] ; then ocf_log err "Please set OCF_RESKEY_raidconf!" exit $OCF_ERR_ARGS fi if [ ! -r "$RAIDCONF" ] ; then ocf_log err "Configuration file [$RAIDCONF] does not exist, or can not be opend!" exit $OCF_ERR_ARGS fi if [ -z "$MDDEV" ] ; then ocf_log err "Please set OCF_RESKEY_raiddev to the Raid device you want to control!" exit $OCF_ERR_ARGS fi if [ ! -b "$MDDEV" ] ; then ocf_log err "$MDDEV is not a block device!" exit $OCF_ERR_ARGS fi # strip off the /dev/ prefix to get the name of the MD device MD=`echo $MDDEV | sed -e 's/\/dev\///'` -# Check to make sure the utilites are found -check_util $MODPROBE -check_util $FUSER -check_util $MOUNT -check_util $UMOUNT HAVE_RAIDTOOLS=false - -if [ -z "$RAIDSTART" -o ! -x "$RAIDSTART" ]; then - ocf_log info "$RAIDSTART not found, trying mdadm..." - check_util $MDADM -else - check_util $RAIDSTOP +if + have_binary $RAIDSTART +then + check_binary $RAIDSTOP HAVE_RAIDTOOLS=true +else + check_binary $MDADM 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|monitor) raid1_status ;; validate-all) raid1_validate_all ;; *) usage exit $OCF_ERR_UNIMPLEMENTED ;; esac exit $? diff --git a/heartbeat/SysInfo.in b/heartbeat/SysInfo.in index 28e6302c4..bb449d1bc 100644 --- a/heartbeat/SysInfo.in +++ b/heartbeat/SysInfo.in @@ -1,364 +1,362 @@ #!/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_ROOT}/resource.d/heartbeat/.ocf-shellfuncs ####################################################################### -HA_VARRUNHBRSCDIR=${HA_RSCTMP} - meta_data() { cat < 1.0 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 SysInfo resource agent PID file PID file Interval to allow values to stabilize Dampening Delay 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/*average/} | awk '{print $4}'` load15=${load15/.*/} 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 ' to the equivalent 'tail -'. 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 : elif [ $mem_round -lt "50" ]; then mem=$[mem+50] mem=$[mem-$mem_round] else mem=$[mem+100] mem=$[mem-$mem_round] 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 < $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_VARRUNHBRSCDIR/SysInfo-${OCF_RESOURCE_INSTANCE}"} +: ${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.in b/heartbeat/VIPArip.in index d14069dd3..febe71467 100644 --- a/heartbeat/VIPArip.in +++ b/heartbeat/VIPArip.in @@ -1,287 +1,285 @@ #!/bin/sh # # License: GNU General Public License (GPL) # Support: linux-ha@lists.linux-ha.org # Author: Huang Zhen # 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_ROOT}/resource.d/heartbeat/.ocf-shellfuncs -HA_VARRUNHBRSCDIR=${HA_RSCTMP} HA_HBCONF_DIR=${HA_DIR} -GREP=@EGREP@ -VLDIR=$HA_VARRUNHBRSCDIR/VIPArip +VLDIR=$HA_RSCTMP/VIPArip RIPDCONF=$VLDIR/ripd.conf -IP=@IP2UTIL@ USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}"; ####################################################################### LC_ALL=C export LC_ALL . $HA_HBCONF_DIR/shellfuncs meta_data() { cat < 1.0 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. Virtual IP Address by RIP2 protocol The IPv4 address in different subnet, for example "192.168.1.1". The IP address in different subnet The nic for broadcast the route information. The ripd uses this nic to broadcast the route informaton to others The nic for broadcast the route information END exit $OCF_SUCCESS } usage() { echo $USAGE >&2 } new_config_file() { echo new_config_file $1 $2 $3 cat >$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 /usr/sbin/zebra -d /usr/sbin/zebra -d echo /usr/sbin/ripd -d -f $RIPDCONF /usr/sbin/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 [ -d "$VLDIR/" ] || mkdir -p "$VLDIR/" then : Directory $VLDIR now exists else ocf_log err "Could not create \"$VLDIR/\"." exit $OCF_ERR_GENERIC fi if [ x"$OCF_RESKEY_nic" = x ] then echo OCF_RESKEY_nic is null, set to eth0 OCF_RESKEY_nic="eth0" fi - if $IP addr | $GREP $OCF_RESKEY_ip >/dev/null + if $IP2UTIL addr | $GREP $OCF_RESKEY_ip >/dev/null then ocf_log err "Invalid OCF_RESKEY_ip [$OCF_RESKEY_ip]" exit $OCF_ERR_ARGS fi - $IP addr add $OCF_RESKEY_ip/32 dev lo + $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 ocf_log err "Invalid OCF_RESKEY_ip [$OCF_RESKEY_ip]" exit $OCF_ERR_ARGS fi - $IP addr del $OCF_RESKEY_ip dev lo + $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 $IP addr | $GREP $OCF_RESKEY_ip >/dev/null + 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 fi return $OCF_NOT_RUNNING } if [ $# -ne 1 ] then usage exit $OCF_ERR_ARGS fi case $1 in start) start_rip_ip;; stop) stop_rip_ip;; status) status_rip_ip;; monitor) status_rip_ip;; - validate-all) exit $OCF_SUCCESS;; + validate-all) check_binary $IP2UTIL + exit $OCF_SUCCESS;; meta-data) meta_data;; usage) usage; exit $OCF_SUCCESS;; *) usage exit $OCF_ERR_ARGS ;; esac diff --git a/heartbeat/Xinetd.in b/heartbeat/Xinetd.in index bae30c104..6cd73000a 100644 --- a/heartbeat/Xinetd.in +++ b/heartbeat/Xinetd.in @@ -1,460 +1,461 @@ #!/bin/sh # # Startup/shutdown script for services managed by xinetd. # # Copyright (C) 2003 Charlie Brooks # # WARNING: Tested ONLY on Red Hat 7.3 and Fedora Core 2/4 at this time. # # Author: Charlie Brooks # 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@lists.linux-ha.org # License: GNU General Public License (GPL) # # OCF parameters are as below: # OCF_RESKEY_service HA_VARRUNDIR=${HA_VARRUN} XPIDFILE=$HA_VARRUNDIR/xinetd.pid ####################################################################### # Initialization: . ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs ####################################################################### -AWK=@AWK@ meta_data() { cat < 1.0 Resource script for Xinetd. It startup/shutdown the services mananged by xinetd. Xinetd resource agent The service name managed by xinetd. service name END } # It's important to note that the absence of a xinetd PID file causes # this script to assume that xinetd is not yet running, and therefore # that we are in the initial boot process. If you port this script to # a distro that keeps the pid files in some other place, be sure to # make an appropriate revision. hup_inetd () { if [ -s $XPIDFILE ]; then if kill -HUP `cat $XPIDFILE`; then : else ocf_log err "Could not SigHUP xinetd superdaemon!" ocf_log err "perhaps we are booting after a system crash" exit $OCF_ERR_GENERIC fi else ocf_log info "xinetd superdaemon PID file $XPIDFILE not found!" ocf_log info "perhaps we are currently booting the system." fi } xup_start () { if [ "running" = "`xup_status`" ]; then ocf_log info "Service $service already started" exit $OCF_SUCCESS fi ocf_log "info" "$0: enabling in $RCFILE" if $AWK '!/disable/' $RCFILE > $RCFILE.xup then if mv $RCFILE.xup $RCFILE then ocf_log "info" "$0: Starting" hup_inetd touch $PIDFILE else ocf_log "err" "Could not replace $RCFILE" fi else ocf_log "err" "Could not rewrite $RCFILE!" fi } xup_stop () { if [ "stopped" = "`xup_status`" ]; then ocf_log info "Service $service already stopped" exit $OCF_SUCCESS fi ocf_log "info" "$0: disabling in $RCFILE" if $AWK '!/disable/;/{/{printf "\tdisable\t\t\t= yes\n"}' $RCFILE >$RCFILE.xup then if mv $RCFILE.xup $RCFILE then ocf_log "info" "$0: Shutting down" hup_inetd rm -f $PIDFILE else ocf_log "err" "Could not replace $RCFILE" fi else ocf_log "err" "Could not rewrite $RCFILE!" fi } xup_usage () { echo "Usage: $0 {start|stop|restart|status|monitor|validate-all|meta-data}" return 0 } xup_status () { if [ -f $PIDFILE ]; then echo running return $OCF_SUCCESS else echo stopped return $OCF_NOT_RUNNING fi } # # Check if the arg is a valid integer # CheckInteger() { # Examples of valid integer: "1080", "1", "0080", "0", "0000" # Examples of invalid integer: "1080bad", "" case "$1" in "") #empty string false;; *[^0-9]*) #got invalid char false;; *) #no invalid char, and has at least one digit, so is a good integer true;; esac } # # Check if the arg is a valid umask # CheckUmask() { # Examples of valid umask: "100", "1", "000", "0" # Examples of invalid umask: "108", "bad", "1111" "" case "$1" in [0-7]) true;; [0-7][0-7]) true;; [0-7][0-7][0-7]) true;; *) false;; esac } # Check (part of) the attributes based on xinetd.conf(5) and xinetd source code # confparse.c # parsers.c # attr.h check_attributes () { # Empty these attributes before validating them unset socket_type wait server user protocol port group instances \ type flags disable nice umask export $* if [ $? -ne 0 ]; then return $OCF_ERR_GENERIC fi case $disable in "") disable=no # Default to no. ;; yes|no) ;; *) ocf_log err "Invalid value for disable [$disable] in $RCFILE, yes|no please" exit $OCF_ERR_CONFIGURED ;; esac case $socket_type in "") socket_type=dgram # Default value for socket_type is dgram. ;; stream|dgram|raw|seqpacket) ;; *) ocf_log err "Invalid socket type $socket_type in $RCFILE" exit $OCF_ERR_CONFIGURED ;; esac case $wait in # Wait has no default value. yes|no) ;; *) ocf_log err "Invalid waid [$wait] in $RCFILE, yes|no please" exit $OCF_ERR_CONFIGURED ;; esac case $type in # Default value for type is RPC or INTERNAL, determined at compile time. # It may be a list in $RCFILE, however we only capture the first one. ""|RPC|INTERNAL|UNLISTED|SPECIAL|TCPMUX|TCPMUXPLUS) ;; *) ocf_log err "Invalid service type [$type] in $RCFILE" exit $OCF_ERR_CONFIGURED ;; esac if [ ! -z $type -a "INTERNAL" != "$type" ]; then # Type is explicitly set to EXTERNAL, hence server and user are necessary. case $server in "") ocf_log err "Please specify server in $RCFILE" exit $OCF_ERR_CONFIGURED ;; /*) if [ -x $server ]; then : OK else ocf_log err "Server $server is not executable" exit $OCF_ERR_CONFIGURED fi ;; *) ocf_log err "Server $server is not of obsolute path" exit $OCF_ERR_CONFIGURED ;; esac case $user in "") ocf_log err "Please specify user in $RCFILE" exit $OCF_ERR_CONFIGURED ;; *) getent passwd $user >/dev/null 2>&1 if [ $? -ne 0 ]; then ocf_log err "User $user does not exist!" exit $OCF_ERR_CONFIGURED fi ;; esac # Protocol is necessary when type is MUX if [ $type = "TCPMUX" -o $type ="TCPMUXPLUS" ]; then case $protocol in "") ocf_log err "Please specify protocol in $RCFILE" exit $OCF_ERR_CONFIGURED ;; *) get protocols $protocol >/dev/null 2>&1 if [ $? -ne 0 ]; then ocf_log err "Invalid protocol [$protocol] in $RCFILE" exit $OCF_ERR_CONFIGURED fi ;; esac fi fi case $group in "") ;; # OK to be empty, the group for $user is used *) getent group $group >/dev/null 2>&1 if [ $? -ne 0 ]; then ocf_log err "Group $group does not exist!" exit $OCF_ERR_CONFIGURED fi ;; esac case $flags in # Default value for flags is REUSE. # It may be a list in $RCFILE, however we only capture the first one. "") flags=RESUME ;; REUSE|INTERCEPT|NORETRY|IDONLY|NAMEINARGS|NODELAY|KEEPALIVE|NOLIBWRAP|SENSOR|IPv4|IPv6) ;; *) ocf_log err "Invalid flags [$flags] in $RCFILE" exit $OCF_ERR_CONFIGURED ;; esac case $instances in ""|[Uu][Nn][Ll][Ii][Mm][Ii][Ti][Ee][Dd]) ;; *) if CheckInteger $instances; then : OK else ocf_log err "Invalid instances [$instances] in $RCFILE, non-negative integer expected" exit $OCF_ERR_CONFIGURED fi ;; esac case $nice in "") ;; *) local foo=`echo $nice | sed s/^-//` if CheckInteger $foo; then : OK else ocf_log err "Invalid nice [$nice] in $RCFILE, integer expected" exit $OCF_ERR_CONFIGURED fi ;; esac if [ ! -z $umask ]; then if CheckUmask $umask; then : OK else ocf_log err "Invalid umask [$umask] in $RCFILE" exit $OCF_ERR_CONFIGURED fi fi } xup_validate_all () { + check_binary $AWK + # Parse the $RCFILE for necessary attributes, assume $RCFILE does not # contain "include" or "includedir" directives. space="[ \t]*" leading_space="^$space" trailing_space="$space$" comment="$space\#" # Strip comments, delete blank lines. stripped=`sed -e "/^$comment/d" -e "/=$trailing_space/d" -e "/$leading_space$/d" $RCFILE` stripped=`echo $stripped` # At this stage, stripped="service { attribute-list }". case $stripped in *#*) ocf_log err "Descriptor file $RCFILE contains extra \"#\", which is forbidden" exit $OCF_ERR_CONFIGURED ;; service*) case $stripped in *[^\ \ +-]=*) ocf_log err "Attribute needs a space before operator =" exit $OCF_ERR_CONFIGURED ;; *[^\ \ ][+-]=*) ocf_log err "Attribute needs a space before operator [+-]=" exit $OCF_ERR_CONFIGURED ;; *) ;; esac # Strip leading "service" keyword, remove spaces surrounding "=". stripped=`echo $stripped | sed -e "s/^service//" -e "s/-=/ /g" \ -e "s/+=/=/g" -e "s/$space=$space/=/g"` # At this stage, stripped=" { attribute-list }", # note that the leading space before is significant. case $stripped in " "*) stripped=`echo $stripped | sed -e "s/$leading_space[^ \t]\+$space//"` # At this stage, stripped="{ attribute-list }" case $stripped in {*}) stripped=`echo $stripped | sed -e "s/^{//" -e "s/}$//"` # At this stage, stripped= # echo $stripped check_attributes "$stripped" ;; *) ocf_log err "Attrbute list should be contained in {}" exit $OCF_ERR_CONFIGURED ;; esac ;; *) ocf_log err "Service name should follow the service key word" exit $OCF_ERR_CONFIGURED ;; esac ;; *) ocf_log err "Service key word is necessary in $RCFILE" exit $OCF_ERR_CONFIGURED ;; esac } 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 set OCF_RESKEY_service to the service managed by Xinetd" exit $OCF_ERR_ARGS fi service=$OCF_RESKEY_service RCFILE=${HA_SYSCONF_DIR}/xinetd.d/$service PIDFILE=$HA_VARRUNDIR/xup$service # Make sure the OCF_RESKEY_service is a valid xinetd service name if [ ! -f $RCFILE ]; then ocf_log err "Service descriptor $RCFILE not found!" exit $OCF_ERR_ARGS fi # See how we were called. case "$1" in start) xup_start ;; stop) xup_stop ;; restart) $0 stop $0 start ;; status|monitor) xup_status ;; validate-all) xup_validate_all ;; *) xup_usage exit $OCF_ERR_UNIMPLEMENTED esac exit $? diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in index 857defef8..601936533 100644 --- a/heartbeat/ocf-shellfuncs.in +++ b/heartbeat/ocf-shellfuncs.in @@ -1,250 +1,253 @@ # # # 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 # # 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` . @HA_HBCONF_DIR@/shellfuncs -. @hb_libdir@/ocf-returncodes +if [ -z "$OCF_ROOT" ]; then + : ${OCF_ROOT=@OCF_ROOT_DIR@} +fi + +. ${OCF_ROOT}/resource.d/heartbeat/.ocf-binaries +. ${OCF_ROOT}/resource.d/heartbeat/.ocf-returncodes +. ${OCF_ROOT}/resource.d/heartbeat/.ocf-directories ocf_is_root() { case `id` in *'uid=0(root)'*) true;; *) false;; esac } # 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_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 [ -z "$OCF_ROOT" ]; then - : ${OCF_ROOT=@OCF_ROOT_DIR@} - 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 # 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 ha_log "ERROR: 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 ha_log "ERROR: 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 ha_log "ERROR: 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 __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_run: Run a script, and log its output. # Usage: ocf_run # ocf_run() { output=`"$@" 2>&1` rc=$? output=`echo $output` if [ $rc -eq 0 ]; then if [ ! -z "$output" ]; then ocf_log info "$output" fi return $OCF_SUCCESS else if [ ! -z "$output" ]; then ocf_log err "$output" else ocf_log err "command failed: $*" fi return $OCF_ERR_GENERIC fi } ocf_pidfile_status() { 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() { lockfile=$1 if [ ! -n $RANDOM ]; then # Something sane-ish in case a shell doesn't support $RANDOM RANDOM=$$ fi sleep 0.$RANDOM while ocf_pidfile_status $lockfile do ocf_log info "Sleeping until $lockfile is released..." sleep 0.$RANDOM done echo $$ > $lockfile } ocf_release_lock_on_exit() { lockfile=$1 trap "rm -f $lockfile" EXIT } __ocf_set_defaults "$@" diff --git a/heartbeat/pgsql.in b/heartbeat/pgsql.in index 2d45f3c00..3642b5857 100644 --- a/heartbeat/pgsql.in +++ b/heartbeat/pgsql.in @@ -1,423 +1,422 @@ #!/bin/bash # # Description: Manages a PostrgreSQL Server as an OCF High-Availability # resource under Heartbeat/LinuxHA control # # # Author: Serge Dubrouski (sergeyfd@gmail.com) # Copyright 2006 Serge Dubrouski # License: GNU General Public License (GPL) # # OCF parameters: # OCF_RESKEY_pgctl - Path to pg_ctl. Default /usr/bin/pg_ctl # OCF_RESKEY_start_opt - Startup options, options passed to postgress with -o # OCF_RESKEY_ctl_opt - Additional options for pg_ctl (-w, -W etc...) # OCF_RESKEY_psql - Path to psql. Default is /usr/bin/psql # OCF_RESKEY_pgdata - PGDATA directory. Default is /var/lib/pgsql/data # OCF_RESKEY_pgdba - userID that manages DB. Default is postgres # OCF_RESKEY_pghost - Host/IP Address where PostgreSQL is listening # OCF_RESKEY_pgport - Port where PostgreSQL is listening # OCF_RESKEY_pgdb - database to monitor. Default is template1 # OCF_RESKEY_logfile - Path to PostgreSQL log file. Default is /dev/null # OCF_RESKEY_stop_escalate - Stop waiting time. Default is 30 ############################################################################### # Initialization: . ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs unset LC_ALL; export LC_ALL unset LANGUAGE; export LANGUAGE -SH=@SHELL@ - usage() { cat <<-! >&1 usage: $0 start|stop|status|monitor|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 'validate-all' operation reports whether the parameters are valid. The 'methods' operation reports on the methods $0 supports. ! return $OCF_ERR_ARGS } meta_data() { cat < 1.0 Resource script for PostgreSQL. It manages a PostgreSQL as an HA resource. pgsql resource agent Path to pg_ctl command. pgctl Start options (-o start_opt in pgi_ctl). "-i -p 5432" for example. start_opt Additional pg_ctl options (-w, -W etc..). Default is "" ctl_opt Path to psql command. psql Path PostgreSQL data directory. pgdata User that owns PostgreSQL. pgdba Hostname/IP Addreess where PosrgeSQL is listening pghost Port where PosrgeSQL is listening pgport Database that will be used for monitoring. pgdb Path to PostgreSQL server log output file. logfile Number of retries (using -m fast) before resorting to -m immediate stop escalation END } # # Run the given command in the Resource owner environment... # runasowner() { su $OCF_RESKEY_pgdba -c ". ~${OCF_RESKEY_pgdba}/.bash_profile; $*" } # # methods: What methods/operations do we support? # pgsql_methods() { cat <<-! start stop status monitor methods meta-data validate-all ! } #pgsql_start: Starts PostgreSQL pgsql_start() { if pgsql_status then ocf_log info "PostgreSQL is already running. PID=`cat $PIDFILE`" return $OCF_SUCCESS fi if [ -x $OCF_RESKEY_pgctl ] then # Remove postmastre.pid if it exists rm -f $PIDFILE # 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_GENERIC fi if runasowner "$OCF_RESKEY_pgctl $OCF_RESKEY_ctl_opt -D $OCF_RESKEY_pgdata -l $OCF_RESKEY_logfile -o "\'$OCF_RESKEY_start_opt\'" start > /dev/null 2>&1" then # Probably started..... ocf_log info "PostgreSQL start command sent." else ocf_log err "Can't start PostgreSQL."; return $OCF_ERR_GENERIC fi else ocf_log err "$OCF_RESKEY_pgctl not found!" return $OCF_ERR_GENERIC fi rc=$OCF_ERR_GENERIC while [ $rc -ne 0 ]; do pgsql_monitor rc=$? sleep 1 ocf_log debug "PostgreSQL still hasn't started yet. Waiting..." done return $OCF_SUCCESS } #pgsql_stop: Stop PostgreSQL pgsql_stop() { if ! pgsql_status then #Already stopped return $OCF_SUCCESS fi # Stop PostgreSQL do not wait for clients to disconnect runasowner "$OCF_RESKEY_pgctl -D $OCF_RESKEY_pgdata stop -m fast > /dev/null 2>&1" # stop waiting count=0 while [ $count -lt $OCF_RESKEY_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 > /dev/null 2>&1" fi rc=$OCF_ERR_GENERIC while [ $rc != $OCF_NOT_RUNNING ]; do pgsql_monitor rc=$? sleep 1 ocf_log debug "PostgreSQL still hasn't stopped yet. Waiting..." done # Remove postmastre.pid if it exists rm -f $PIDFILE return $OCF_SUCCESS } # # pgsql_status: is PostgreSQL up? # pgsql_status() { if [ -f $PIDFILE ] then PID=`head -n 1 $PIDFILE` process_running $PID else : No pid file false fi } # # return TRUE if a process with given PID is running # process_running() { kill -0 "$1" >/dev/null 2>&1 } # # pgsql_monitor # pgsql_monitor() { if ! pgsql_status then ocf_log info "PostgreSQL is down" return $OCF_NOT_RUNNING fi if [ "x" = "x$OCF_RESKEY_pghost" ] then $OCF_RESKEY_psql -p $OCF_RESKEY_pgport -U $OCF_RESKEY_pgdba $OCF_RESKEY_pgdb -c 'select now();' >/dev/null 2>&1 else $OCF_RESKEY_psql -h $OCF_RESKEY_pghost -p $OCF_RESKEY_pgport -U $OCF_RESKEY_pgdba $OCF_RESKEY_pgdb -c 'select now();' >/dev/null 2>&1 fi if [ $? -ne 0 ] then ocf_log err "PostgreSQL $OCF_RESKEY_pgdb isn't running" return $OCF_ERR_GENERIC fi return $OCF_SUCCESS } # Validate most critical parameters pgsql_validate_all() { + check_binary $SH if [ ! -x $OCF_RESKEY_pgctl ] then ocf_log err "Can't run $OCF_RESKEY_pgctl" return $OCF_ERR_CONFIGURED fi if [ ! -x $OCF_RESKEY_psql ] then ocf_log err "Can't run $OCF_RESKEY_psql" return $OCF_ERR_CONFIGURED 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:$(cat /etc/passwd | grep $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 } # # 'main' starts here... # if [ $# -ne 1 ] then usage exit 1 fi US=`id -u -n` if [ $US != root ] then ocf_log err "$0 must be run as root" exit 1 fi : ${OCF_RESKEY_pgctl=/usr/bin/pg_ctl} : ${OCF_RESKEY_psql=/usr/bin/psql} : ${OCF_RESKEY_pgdata=/var/lib/pgsql/data} : ${OCF_RESKEY_pgdba=postgres} : ${OCF_RESKEY_pgport=5432} : ${OCF_RESKEY_pgdb=template1} : ${OCF_RESKEY_logfile=/dev/null} : ${OCF_RESKEY_stop_escalate=30} PIDFILE=${OCF_RESKEY_pgdata}/postmaster.pid case "$1" in methods) pgsql_methods exit $?;; meta-data) meta_data exit $OCF_SUCCESS;; validate-all) pgsql_validate_all exit $?;; esac if ! pgsql_validate_all then exit $OCF_ERR_CONFIGURED fi # What kind of method was invoked? case "$1" in start) pgsql_start exit $?;; stop) pgsql_stop exit $?;; 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 exit $?;; monitor) pgsql_monitor exit $?;; esac usage diff --git a/heartbeat/pingd.in b/heartbeat/pingd.in index d6f20023f..ac7da4a54 100644 --- a/heartbeat/pingd.in +++ b/heartbeat/pingd.in @@ -1,262 +1,260 @@ #!/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_ROOT}/resource.d/heartbeat/.ocf-shellfuncs ####################################################################### -HA_VARRUNHBRSCDIR=${HA_RSCTMP} - meta_data() { cat < 1.0 This is a pingd Resource Agent. It records (in the CIB) the current number of ping nodes a node can connect to. pingd resource agent PID file PID file - + The user we want to run pingd as The user we want to run pingd as The time to wait (dampening) further changes occur Dampening interval The name of the instance_attributes set to place the value in. Rarely needs to be specified. Set name The name of the attributes to set. This is the name to be used in the constraints. Attribute name The section place the value in. Rarely needs to be specified. Section name The number by which to multiply the number of connected ping nodes by Value multiplier The list of ping nodes to count. Defaults to all configured ping nodes. Rarely needs to be specified. Host list END } ####################################################################### pingd_usage() { cat </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_VARRUNHBRSCDIR/pingd-${OCF_RESOURCE_INSTANCE}"} +: ${OCF_RESKEY_pidfile:="$HA_RSCTMP/pingd-${OCF_RESOURCE_INSTANCE}"} : ${OCF_RESKEY_name:="pingd"} : ${OCF_RESKEY_dampen:="1s"} case $__OCF_ACTION in meta-data) meta_data exit $OCF_SUCCESS ;; 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.in b/heartbeat/portblock.in index 1c35b8ae6..20c1d223a 100644 --- a/heartbeat/portblock.in +++ b/heartbeat/portblock.in @@ -1,361 +1,360 @@ #!/bin/sh # # portblock: iptables temporary portblocking control # # Author: Sun Jiang Dong # # 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 ####################################################################### # Initialization: . ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs . ${HA_DIR}/shellfuncs ####################################################################### CMD=`basename $0` -iptables=@IPTABLES@ - usage() { cat <<-!USAGE >&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... !USAGE } meta_data() { cat < 1.0 Resource script for portblock. It is used to temporarily block ports using iptables. portblock resource agent The protocol used to be blocked/unblocked. protocol The port number used to be blocked/unblocked. portno The action (block/unblock) to be done on the protocol::portno. action 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... # # So, we track the state here using the pseudo_resource() function. # # The psuedo_resource function should be moved into the functions # available to resources so other resource scripts could use it... # # # pseudo_resource filename operation pseudo_resource() { ha_pseudo_resource $* } #iptables_spec {udp|tcp} portno,portno iptables_spec() { echo -D INPUT -p $1 -m multiport --dports $2 -j DROP } #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}${any}${w}multiport${w}dports${w}${2} " } #chain_isactive {udp|tcp} portno,portno chain_isactive() { PAT=`active_grep_pat "$1" "$2"` - $iptables -n -L INPUT | grep "$PAT" >/dev/null + $IPTABLES -n -L INPUT | grep "$PAT" >/dev/null } SayActive() { echo "$CMD DROP rule for INPUT chain [$*] is running (OK)" return 0 } SayConsideredActive() { echo "$CMD DROP rule for INPUT chain [$*] considered to be running (OK)" return 0 } SayInactive() { echo "$CMD DROP rule for INPUT chain [$*] is inactive" return 1 } #IptablesStatus {udp|tcp} portno,portno {block|unblock} IptablesStatus() { activewords="$CMD $1 $2 is running (OK)" if chain_isactive "$1" "$2" then case $3 in block) SayActive $*;; *) SayInactive $*;; esac else case $3 in block) if pseudo_resource "$RSCNAME" status then SayConsideredActive $* else SayInactive $* fi;; *) SayActive $*;; esac fi return $? } #IptablesBLOCK {udp|tcp} portno,portno IptablesBLOCK() { if chain_isactive "$1" "$2" then : OK -- chain already active else - $iptables -I INPUT -p "$1" -m multiport --dports "$2" -j DROP + $IPTABLES -I INPUT -p "$1" -m multiport --dports "$2" -j DROP fi return $? } #IptablesUNBLOCK {udp|tcp} portno,portno IptablesUNBLOCK() { if chain_isactive "$1" "$2" then - $iptables -D INPUT -p "$1" -m multiport --dports "$2" -j DROP + $IPTABLES -D INPUT -p "$1" -m multiport --dports "$2" -j DROP else : Chain Not active fi return $? } #IptablesStart {udp|tcp} portno,portno {block|unblock} IptablesStart() { pseudo_resource "$RSCNAME" start case $3 in block) IptablesBLOCK "$@";; unblock) IptablesUNBLOCK "$@";; *) usage; return 1; esac return $? } #IptablesStop {udp|tcp} portno,portno {block|unblock} IptablesStop() { pseudo_resource "$RSCNAME" stop case $3 in block) IptablesUNBLOCK "$@";; unblock) 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", "" case "$1" in *[^0-9]*) #got invalid char false;; *[1-9]*) #no invalid char, and has non-zero digit, so is a good port true;; *) #empty string, or string of 0's false;; esac } IptablesValidateAll() { + check_binary $IPTABLES case $protocol in tcp|udp) ;; *) ocf_log err "Invalid protocol $protocol!" exit $OCF_ERR_ARGS ;; esac if CheckPort "$portno"; then : else ocf_log err "Invalid port number $portno!" exit $OCF_ERR_ARGS fi case $action in block|unblock) ;; *) ocf_log err "Invalid action $action!" exit $OCF_ERR_ARGS ;; 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_ARGS fi if [ -z "$OCF_RESKEY_portno" ]; then ocf_log err "Please set OCF_RESKEY_portno" exit $OCF_ERR_ARGS fi if [ -z "$OCF_RESKEY_action" ]; then ocf_log err "Please set OCF_RESKEY_action" exit $OCF_ERR_ARGS fi protocol=$OCF_RESKEY_protocol portno=$OCF_RESKEY_portno action=$OCF_RESKEY_action RSCNAME=${CMD}_${protocol}_${portno}_${action} case $1 in start) IptablesStart $protocol $portno $action ;; stop) IptablesStop $protocol $portno $action ;; status|monitor) IptablesStatus $protocol $portno $action ;; validate-all) IptablesValidateAll ;; *) usage exit $OCF_ERR_UNIMPLEMENTED ;; esac exit $?