Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/.gitignore b/.gitignore
index 23bd6c9326..d87273f551 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,155 +1,156 @@
# Common
GPATH
GRTAGS
GTAGS
TAGS
Makefile
Makefile.in
.deps
.libs
*.pc
*.pyc
*.bz2
*.rpm
*.la
*.lo
*.o
*~
# Autobuild
aclocal.m4
autoconf
autoheader
autom4te.cache/
automake
build.counter
compile
config.guess
config.log
config.status
config.sub
configure
depcomp
install-sh
include/stamp-*
libltdl.tar
libtool
libtool.m4
ltdl.m4
ltmain.sh
missing
py-compile
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
# Configure targets
cts/CTSvars.py
cts/LSBDummy
cts/benchmark/clubench
include/config.h
include/config.h.in
include/crm_config.h
mcp/pacemaker
mcp/pacemaker.service
pengine/regression.core.sh
publican.cfg
shell/modules/help.py
shell/modules/ra.py
shell/modules/ui.py
shell/modules/vars.py
tools/coverage.sh
tools/crm_report
lrmd/regression.py
+fencing/regression.py
# Build targets
*.7
*.7.xml
*.7.html
*.8
*.8.xml
*.8.html
doc/*/en-US/images/*.png
doc/*/tmp/**
doc/*/publish
cib/cib
cib/cibmon
cib/cibpipe
crmd/atest
crmd/crmd
doc/Clusters_from_Scratch.txt
doc/Pacemaker_Explained.txt
doc/acls.html
doc/crm_fencing.html
fencing/stonith-test
fencing/stonith_admin
fencing/stonithd
fencing/stonithd.xml
lrmd/lrmd
lrmd/lrmd_test
mcp/pacemakerd
pengine/pengine
pengine/pengine.xml
pengine/ptest
shell/regression/testcases/confbasic-xml.filter
scratch
tools/attrd
tools/attrd_updater
tools/cibadmin
tools/crm_attribute
tools/crm_diff
tools/crm_mon
tools/crm_node
tools/crm_resource
tools/crm_shadow
tools/crm_simulate
tools/crm_uuid
tools/crm_verify
tools/crmadmin
tools/iso8601
tools/crm_ticket
tools/report.collector.1
xml/crm.dtd
xml/pacemaker.rng
extra/rgmanager/ccs2cib
extra/rgmanager/ccs_flatten
extra/rgmanager/disable_rgmanager
doc/Clusters_from_Scratch/en-US/Ap-Configuration.xml
doc/Clusters_from_Scratch/en-US/Ap-Corosync-Conf.xml
doc/Clusters_from_Scratch/en-US/Ap-Reading.xml
doc/Clusters_from_Scratch/en-US/Ch-Active-Active.xml
doc/Clusters_from_Scratch/en-US/Ch-Active-Passive.xml
doc/Clusters_from_Scratch/en-US/Ch-Apache.xml
doc/Clusters_from_Scratch/en-US/Ch-Installation.xml
doc/Clusters_from_Scratch/en-US/Ch-Intro.xml
doc/Clusters_from_Scratch/en-US/Ch-Shared-Storage.xml
doc/Clusters_from_Scratch/en-US/Ch-Stonith.xml
doc/Clusters_from_Scratch/en-US/Ch-Tools.xml
doc/Clusters_from_Scratch/en-US/Ch-Verification.xml
doc/Pacemaker_Explained/en-US/Ch-Basics.xml
doc/Pacemaker_Explained/en-US/Ch-Options.xml
lib/gnu/libgnu.a
lib/gnu/stdalign.h
#Other
mock
HTML
pacemaker.spec
pengine/.regression.failed.diff
ClusterLabs-pacemaker-*.tar.gz
coverity-*
compat_reports
.ABI-build
abi_dumps
logs
*.patch
*.diff
*.sed
*.orig
*.rej
*.swp
pengine/test10/shadow.*
diff --git a/TODO.markdown b/TODO.markdown
index 6c234c9185..7c5bd46c82 100644
--- a/TODO.markdown
+++ b/TODO.markdown
@@ -1,59 +1,57 @@
# Semi-random collection of tasks we'd like to get done
## Targeted for 1.2
-- Get fencing/test.c working again (with and without stonithd -s)
- Avoid the use of xmlNode in fencing register_callback() call types
- Replace (delegated)_variant_op in CIB API with a private function
- Need a way to indicate when unfencing operations need to be initiated from the host to be unfenced
- Test startup fencing with node lists
- Figure out how to distinguish between "down" and "down
but we've never seen them before so they need to be shot"
- Attempt to obtain a node list from corosync if one exists
## Targeted for 1.2.x
- Check for uppercase letters in node names, warn if found
- Imply startup-failure-is-fatal from on-fail="restart"
- Show an english version of the config with crm_resource --rules
- Convert cts/CIB.py into a supported Python API for the CIB
- Use crm_log_tag() in the PE to allow per-resource trace logging
- Reduce the amount of stonith-ng logging
- Reduce the amount of attrd logging
- Use dlopen for snmp in crm_mon
## Targeted for 1.4
- Support A colocated with (B || C || D)
- Implement a truely atomic version of attrd
- Support rolling average values in attrd
- Support heartbeat with the mcp
- Freeze/Thaw
- Create Pacemaker plugin for snmpd - http://www.net-snmp.org/
- Investigate using a DB as the back-end for the CIB
- Decide whether to fully support or drop failover domains
# Testing
-- Write a regression test for Stonith-NG
- Convert BandwidthTest CTS test into a Scenario wrapper
- find_operations() is not covered by PE regression tests
- Some node states in determine_online_status_fencing() are untested by PE regression tests
- no_quorum_policy==suicide is not covered by PE regression tests
- parse_xml_duration() is not covered by PE regression tests
- phase_of_the_moon() is not covered by PE regression tests
- test_role_expression() is not covered by PE regression tests
- native_parameter() is not covered by PE regression tests
- clone_resource_state() is not covered by PE regression tests
- clone_active() is not covered by PE regression tests
- convert_non_atomic_task() in native.c is not covered by PE regression tests
- clone_rsc_colocation_lh() is not covered by PE regression tests
- group_rsc_colocation_lh() is not covered by PE regression tests
- Test on-fail=standby
# Documentation
- Clusters from Scratch: Mail
- Clusters from Scratch: MySQL
- Document reload in Pacemaker Explained
- Document advanced fencing logic in Pacemaker Explained
- Use ann:defaultValue="..." instead of <optional> in the schema more often
- Allow Clusters from Scratch to be built in two flavors - pcs and crm shell
diff --git a/configure.ac b/configure.ac
index 4c0e57eabc..03132082d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,1773 +1,1774 @@
dnl
dnl autoconf for Pacemaker
dnl
dnl License: GNU General Public License (GPL)
dnl ===============================================
dnl Bootstrap
dnl ===============================================
AC_PREREQ(2.59)
dnl Suggested structure:
dnl information on the package
dnl checks for programs
dnl checks for libraries
dnl checks for header files
dnl checks for types
dnl checks for structures
dnl checks for compiler characteristics
dnl checks for library functions
dnl checks for system services
AC_INIT(pacemaker, 1.1.7, pacemaker@oss.clusterlabs.org)
CRM_DTD_VERSION="1.2"
PCMK_FEATURES=""
HB_PKG=heartbeat
AC_CONFIG_AUX_DIR(.)
AC_CANONICAL_HOST
dnl Where #defines go (e.g. `AC_CHECK_HEADERS' below)
dnl
dnl Internal header: include/config.h
dnl - Contains ALL defines
dnl - include/config.h.in is generated automatically by autoheader
dnl - NOT to be included in any header files except lha_internal.h
dnl (which is also not to be included in any other header files)
dnl
dnl External header: include/crm_config.h
dnl - Contains a subset of defines checked here
dnl - Manually edit include/crm_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/crm_config.h)
ALL_LINGUAS="en fr"
AC_ARG_WITH(version,
[ --with-version=version Override package version (if you're a packager needing to pretend) ],
[ PACKAGE_VERSION="$withval" ])
AC_ARG_WITH(pkg-name,
[ --with-pkg-name=name Override package name (if you're a packager needing to pretend) ],
[ PACKAGE_NAME="$withval" ])
AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION)
AC_DEFINE_UNQUOTED(PACEMAKER_VERSION, "$PACKAGE_VERSION", Current pacemaker version)
PACKAGE_SERIES=`echo $PACKAGE_VERSION | awk -F. '{ print $1"."$2 }'`
AC_SUBST(PACKAGE_SERIES)
AC_SUBST(PACKAGE_VERSION)
dnl automake >= 1.11 offers --enable-silent-rules for suppressing the output from
dnl normal compilation. When a failure occurs, it will then display the full
dnl command line
dnl Wrap in m4_ifdef to avoid breaking on older platforms
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
dnl Example 2.4. Silent Custom Rule to Generate a File
dnl %-bar.pc: %.pc
dnl $(AM_V_GEN)$(LN_S) $(notdir $^) $@
CC_IN_CONFIGURE=yes
export CC_IN_CONFIGURE
LDD=ldd
dnl ========================================================================
dnl Compiler characteristics
dnl ========================================================================
AC_PROG_CC dnl Can force other with environment variable "CC".
AM_PROG_CC_C_O
AC_PROG_CC_STDC
gl_EARLY
gl_INIT
AC_LIBTOOL_DLOPEN dnl Enable dlopen support...
AC_LIBLTDL_CONVENIENCE dnl make libltdl a convenience lib
AC_PROG_LIBTOOL
AC_PROG_YACC
AM_PROG_LEX
AC_C_STRINGIZE
AC_TYPE_SIZE_T
AC_CHECK_SIZEOF(char)
AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(long long)
AC_STRUCT_TIMEZONE
dnl ===============================================
dnl Helpers
dnl ===============================================
cc_supports_flag() {
local CFLAGS="$@"
AC_MSG_CHECKING(whether $CC supports "$@")
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[ ]])], [RC=0; AC_MSG_RESULT(yes)],[RC=1; AC_MSG_RESULT(no)])
return $RC
}
try_extract_header_define() {
AC_MSG_CHECKING(if $2 in $1 exists. If not defaulting to $3)
Cfile=$srcdir/extract_define.$2.${$}
printf "#include <stdio.h>\n" > ${Cfile}.c
printf "#include <%s>\n" $1 >> ${Cfile}.c
printf "int main(int argc, char **argv) {\n" >> ${Cfile}.c
printf "#ifdef %s\n" $2 >> ${Cfile}.c
printf "printf(\"%%s\", %s);\n" $2 >> ${Cfile}.c
printf "#endif \n return 0; }\n" >> ${Cfile}.c
$CC $CFLAGS ${Cfile}.c -o ${Cfile}
value=`${Cfile}`
if test x"${value}" == x""; then
value=$3
fi
AC_MSG_RESULT($value)
printf $value
rm -rf ${Cfile}.c ${Cfile} ${Cfile}.dSYM ${Cfile}.gcno
}
extract_header_define() {
AC_MSG_CHECKING(for $2 in $1)
Cfile=$srcdir/extract_define.$2.${$}
printf "#include <stdio.h>\n" > ${Cfile}.c
printf "#include <%s>\n" $1 >> ${Cfile}.c
printf "int main(int argc, char **argv) { printf(\"%%s\", %s); return 0; }\n" $2 >> ${Cfile}.c
$CC $CFLAGS ${Cfile}.c -o ${Cfile}
value=`${Cfile}`
AC_MSG_RESULT($value)
printf $value
rm -rf ${Cfile}.c ${Cfile} ${Cfile}.dSYM ${Cfile}.gcno
}
dnl ===============================================
dnl Configure Options
dnl ===============================================
dnl Some systems, like Solaris require a custom package name
AC_ARG_WITH(pkgname,
[ --with-pkgname=name name for pkg (typically for Solaris) ],
[ PKGNAME="$withval" ],
[ PKGNAME="LXHAhb" ],
)
AC_SUBST(PKGNAME)
AC_ARG_ENABLE([ansi],
[ --enable-ansi force GCC to compile to ANSI/ANSI standard for older compilers.
[default=no]])
AC_ARG_ENABLE([fatal-warnings],
[ --enable-fatal-warnings very pedantic and fatal warnings for gcc
[default=yes]])
AC_ARG_ENABLE([quiet],
[ --enable-quiet
Supress make output unless there is an error
[default=no]])
AC_ARG_ENABLE([thread-safe],
[ --enable-thread-safe Enable some client libraries to be thread safe.
[default=no]])
AC_ARG_ENABLE([bundled-ltdl],
[ --enable-bundled-ltdl Configure, build and install the standalone ltdl library bundled with ${PACKAGE} [default=no]])
LTDL_LIBS=""
AC_ARG_ENABLE([no-stack],
[ --enable-no-stack
Only build the Policy Engine and pieces needed to support it [default=no]])
AC_ARG_ENABLE([upstart],
[ --enable-upstart
Do not build support for the Upstart init system [default=yes]])
AC_ARG_ENABLE([systemd],
[ --enable-systemd
Do not build support for the Systemd init system [default=yes]])
AC_ARG_WITH(ais,
[ --with-ais
Support the Corosync messaging and membership layer ],
[ SUPPORT_CS=$withval ],
[ SUPPORT_CS=try ],
)
AC_ARG_WITH(corosync,
[ --with-corosync
Support the Corosync messaging and membership layer ],
[ SUPPORT_CS=$withval ]
dnl initialized in AC_ARG_WITH(ais...) already,
dnl don't reset to try if it was given as --without-ais
)
AC_ARG_WITH(heartbeat,
[ --with-heartbeat
Support the Heartbeat messaging and membership layer ],
[ SUPPORT_HEARTBEAT=$withval ],
[ SUPPORT_HEARTBEAT=try ],
)
AC_ARG_WITH(cman,
[ --with-cman
Support the consumption of membership and quorum from cman ],
[ SUPPORT_CMAN=$withval ],
[ SUPPORT_CMAN=try ],
)
AC_ARG_WITH(cpg,
[ --with-cs-quorum
Support the consumption of membership and quorum from corosync ],
[ SUPPORT_CS_QUORUM=$withval ],
[ SUPPORT_CS_QUORUM=try ],
)
AC_ARG_WITH(snmp,
[ --with-snmp
Support the SNMP protocol ],
[ SUPPORT_SNMP=$withval ],
[ SUPPORT_SNMP=try ],
)
AC_ARG_WITH(esmtp,
[ --with-esmtp
Support the sending mail notifications with the esmtp library ],
[ SUPPORT_ESMTP=$withval ],
[ SUPPORT_ESMTP=try ],
)
AC_ARG_WITH(acl,
[ --with-acl
Support CIB ACL ],
[ SUPPORT_ACL=$withval ],
[ SUPPORT_ACL=no ],
)
CSPREFIX=""
AC_ARG_WITH(ais-prefix,
[ --with-ais-prefix=DIR Prefix used when Corosync was installed [$prefix]],
[ CSPREFIX=$withval ],
[ CSPREFIX=$prefix ])
LCRSODIR=""
AC_ARG_WITH(lcrso-dir,
[ --with-lcrso-dir=DIR Corosync lcrso files. ],
[ LCRSODIR="$withval" ])
INITDIR=""
AC_ARG_WITH(initdir,
[ --with-initdir=DIR directory for init (rc) scripts [${INITDIR}]],
[ INITDIR="$withval" ])
SUPPORT_PROFILING=0
AC_ARG_WITH(profiling,
[ --with-profiling
Support gprof profiling ],
[ SUPPORT_PROFILING=$withval ])
SUPPORT_GCOV=0
AC_ARG_WITH(gcov,
[ --with-gcov
Support gcov coverage testing ],
[ SUPPORT_GCOV=$withval ])
PUBLICAN_BRAND="common"
AC_ARG_WITH(brand,
[ --with-brand=brand Brand to use for generated documentation [$PUBLICAN_BRAND]],
[ PUBLICAN_BRAND="$withval" ])
AC_SUBST(PUBLICAN_BRAND)
dnl ===============================================
dnl General Processing
dnl ===============================================
AC_SUBST(HB_PKG)
INIT_EXT=""
echo Our Host OS: $host_os/$host
AC_MSG_NOTICE(Sanitizing prefix: ${prefix})
case $prefix in
NONE)
prefix=/usr
dnl Fix default variables - "prefix" variable if not specified
if test "$localstatedir" = "\${prefix}/var"; then
localstatedir="/var"
fi
if test "$sysconfdir" = "\${prefix}/etc"; then
sysconfdir="/etc"
fi
;;
esac
AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix})
case $exec_prefix in
dnl For consistency with Heartbeat, map NONE->$prefix
NONE) exec_prefix=$prefix;;
prefix) exec_prefix=$prefix;;
esac
AC_MSG_NOTICE(Sanitizing ais_prefix: ${CSPREFIX})
case $CSPREFIX in
dnl For consistency with Heartbeat, map NONE->$prefix
NONE) CSPREFIX=$prefix;;
prefix) CSPREFIX=$prefix;;
esac
AC_MSG_NOTICE(Sanitizing INITDIR: ${INITDIR})
case $INITDIR in
prefix) INITDIR=$prefix;;
"")
AC_MSG_CHECKING(which init (rc) directory to use)
for initdir in /etc/init.d /etc/rc.d/init.d /sbin/init.d \
/usr/local/etc/rc.d /etc/rc.d
do
if
test -d $initdir
then
INITDIR=$initdir
break
fi
done
AC_MSG_RESULT($INITDIR);;
esac
AC_SUBST(INITDIR)
AC_MSG_NOTICE(Sanitizing libdir: ${libdir})
case $libdir in
dnl For consistency with Heartbeat, map NONE->$prefix
*prefix*|NONE)
AC_MSG_CHECKING(which lib directory to use)
for aDir in lib64 lib
do
trydir="${exec_prefix}/${aDir}"
if
test -d ${trydir}
then
libdir=${trydir}
break
fi
done
AC_MSG_RESULT($libdir);
;;
esac
dnl Expand autoconf variables so that we dont end up with '${prefix}'
dnl in #defines and python scripts
dnl NOTE: Autoconf deliberately leaves them unexpanded to allow
dnl make exec_prefix=/foo install
dnl No longer being able to do this seems like no great loss to me...
eval prefix="`eval echo ${prefix}`"
eval exec_prefix="`eval echo ${exec_prefix}`"
eval bindir="`eval echo ${bindir}`"
eval sbindir="`eval echo ${sbindir}`"
eval libexecdir="`eval echo ${libexecdir}`"
eval datadir="`eval echo ${datadir}`"
eval sysconfdir="`eval echo ${sysconfdir}`"
eval sharedstatedir="`eval echo ${sharedstatedir}`"
eval localstatedir="`eval echo ${localstatedir}`"
eval libdir="`eval echo ${libdir}`"
eval includedir="`eval echo ${includedir}`"
eval oldincludedir="`eval echo ${oldincludedir}`"
eval infodir="`eval echo ${infodir}`"
eval mandir="`eval echo ${mandir}`"
dnl Home-grown variables
eval INITDIR="${INITDIR}"
eval docdir="`eval echo ${docdir}`"
if test x"${docdir}" = x""; then
docdir=${datadir}/doc/${PACKAGE}-${VERSION}
#docdir=${datadir}/doc/packages/${PACKAGE}
fi
AC_SUBST(docdir)
for j in prefix exec_prefix bindir sbindir libexecdir datadir sysconfdir \
sharedstatedir localstatedir libdir includedir oldincludedir infodir \
mandir INITDIR docdir
do
dirname=`eval echo '${'${j}'}'`
if
test ! -d "$dirname"
then
AC_MSG_WARN([$j directory ($dirname) does not exist!])
fi
done
dnl This OS-based decision-making is poor autotools practice;
dnl feature-based mechanisms are strongly preferred.
dnl
dnl So keep this section to a bare minimum; regard as a "necessary evil".
case "$host_os" in
*bsd*) LIBS="-L/usr/local/lib"
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
INIT_EXT=".sh"
;;
*solaris*)
;;
*linux*)
AC_DEFINE_UNQUOTED(ON_LINUX, 1, Compiling for Linux platform)
CFLAGS="$CFLAGS -I${prefix}/include"
;;
darwin*)
AC_DEFINE_UNQUOTED(ON_DARWIN, 1, Compiling for Darwin platform)
LIBS="$LIBS -L${prefix}/lib"
CFLAGS="$CFLAGS -I${prefix}/include"
;;
esac
dnl Eventually remove this
CFLAGS="$CFLAGS -I${prefix}/include/heartbeat"
AC_SUBST(INIT_EXT)
AC_MSG_NOTICE(Host CPU: $host_cpu)
case "$host_cpu" in
ppc64|powerpc64)
case $CFLAGS in
*powerpc64*) ;;
*) if test "$GCC" = yes; then
CFLAGS="$CFLAGS -m64"
fi ;;
esac
esac
AC_MSG_CHECKING(which format is needed to print uint64_t)
ac_save_CFLAGS=$CFLAGS
CFLAGS="-Wall -Werror"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
],
[
int max = 512;
uint64_t bignum = 42;
char *buffer = malloc(max);
const char *random = "random";
snprintf(buffer, max-1, "<quorum id=%lu quorate=%s/>", bignum, random);
fprintf(stderr, "Result: %s\n", buffer);
]
)],
[U64T="%lu"],
[U64T="%llu"]
)
CFLAGS=$ac_save_CFLAGS
AC_MSG_RESULT($U64T)
AC_DEFINE_UNQUOTED(U64T, "$U64T", Correct printf format for logging uint64_t)
dnl ===============================================
dnl Program Paths
dnl ===============================================
PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin"
export PATH
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)
AM_PATH_PYTHON
AC_CHECK_PROGS(MAKE, gmake make)
AC_PATH_PROGS(HTML2TXT, lynx w3m)
AC_PATH_PROGS(HELP2MAN, help2man)
AC_PATH_PROGS(POD2MAN, pod2man, pod2man)
AC_PATH_PROGS(ASCIIDOC, asciidoc)
AC_PATH_PROGS(PUBLICAN, publican)
AC_PATH_PROGS(INKSCAPE, inkscape)
AC_PATH_PROGS(XSLTPROC, xsltproc)
AC_PATH_PROGS(FOP, fop)
AC_PATH_PROGS(SSH, ssh, /usr/bin/ssh)
AC_PATH_PROGS(SCP, scp, /usr/bin/scp)
AC_PATH_PROGS(TAR, tar)
AC_PATH_PROGS(MD5, md5)
AC_PATH_PROGS(TEST, test)
AC_PATH_PROGS(PKGCONFIG, pkg-config)
AC_PATH_PROGS(XML2CONFIG, xml2-config)
AC_PATH_PROGS(VALGRIND_BIN, valgrind, /usr/bin/valgrind)
AC_DEFINE_UNQUOTED(VALGRIND_BIN, "$VALGRIND_BIN", Valgrind command)
dnl Disable these until we decide if the stonith config file should be supported
dnl AC_PATH_PROGS(BISON, bison)
dnl AC_PATH_PROGS(FLEX, flex)
dnl AC_PATH_PROGS(HAVE_YACC, $YACC)
if test x"${LIBTOOL}" = x""; then
AC_MSG_ERROR(You need (g)libtool installed in order to build ${PACKAGE})
fi
if test x"${MAKE}" = x""; then
AC_MSG_ERROR(You need (g)make installed in order to build ${PACKAGE})
fi
AM_CONDITIONAL(BUILD_HELP, test x"${HELP2MAN}" != x"")
if test x"${HELP2MAN}" != x""; then
PCMK_FEATURES="$PCMK_FEATURES generated-manpages"
fi
MANPAGE_XSLT=""
if test x"${XSLTPROC}" != x""; then
AC_MSG_CHECKING(docbook to manpage transform)
XSLT=`find ${datadir} -name docbook.xsl`
for xsl in $XSLT; do
dname=`dirname $xsl`
bname=`basename $dname`
if test "$bname" = "manpages"; then
MANPAGE_XSLT="$xsl"
break
fi
done
fi
AC_MSG_RESULT($MANPAGE_XSLT)
AC_SUBST(MANPAGE_XSLT)
AM_CONDITIONAL(BUILD_XML_HELP, test x"${MANPAGE_XSLT}" != x"")
if test x"${MANPAGE_XSLT}" != x""; then
PCMK_FEATURES="$PCMK_FEATURES agent-manpages"
fi
AM_CONDITIONAL(BUILD_ASCIIDOC, test x"${ASCIIDOC}" != x"")
if test x"${ASCIIDOC}" != x""; then
PCMK_FEATURES="$PCMK_FEATURES ascii-docs"
fi
SUPPORT_STONITH_CONFIG=0
if test x"${HAVE_YACC}" != x"" -a x"${FLEX}" != x"" -a x"${BISON}" != x""; then
SUPPORT_STONITH_CONFIG=1
PCMK_FEATURES="$PCMK_FEATURES st-conf"
fi
AM_CONDITIONAL(BUILD_STONITH_CONFIG, test $SUPPORT_STONITH_CONFIG = 1)
AC_DEFINE_UNQUOTED(SUPPORT_STONITH_CONFIG, $SUPPORT_STONITH_CONFIG, Support a stand-alone stonith config file in addition to the CIB)
AM_CONDITIONAL(BUILD_DOCBOOK, test x"${PUBLICAN}" != x"" -a x"${INKSCAPE}" != x"")
if test x"${PUBLICAN}" != x"" -a x"${INKSCAPE}" != x""; then
AC_MSG_NOTICE(Enabling publican)
PCMK_FEATURES="$PCMK_FEATURES publican-docs"
fi
dnl ========================================================================
dnl checks for library functions to replace them
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 strerror: returns a string that corresponds to an errno.
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.
AC_REPLACE_FUNCS(alphasort NoSuchFunctionName scandir setenv strerror strchrnul unsetenv strnlen strndup)
dnl ===============================================
dnl Libraries
dnl ===============================================
AC_CHECK_LIB(socket, socket) dnl -lsocket
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)
AC_CHECK_LIB(uuid, uuid_parse) dnl load the library if necessary
AC_CHECK_FUNCS(uuid_unparse) dnl OSX ships uuid_* as standard functions
AC_CHECK_HEADERS(uuid/uuid.h)
if test "x$ac_cv_func_uuid_unparse" != xyes; then
AC_MSG_ERROR(You do not have the libuuid development package installed)
fi
if test x"${PKGCONFIG}" = x""; then
AC_MSG_ERROR(You need pkgconfig installed in order to build ${PACKAGE})
fi
if test "x${enable_thread_safe}" = "xyes"; then
GPKGNAME="gthread-2.0"
else
GPKGNAME="glib-2.0"
fi
if
$PKGCONFIG --exists $GPKGNAME
then
GLIBCONFIG="$PKGCONFIG $GPKGNAME"
else
set -x
echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH
$PKGCONFIG --exists $GPKGNAME; echo $?
$PKGCONFIG --cflags $GPKGNAME; echo $?
$PKGCONFIG $GPKGNAME; echo $?
set +x
AC_MSG_ERROR(You need glib2-devel installed in order to build ${PACKAGE})
fi
AC_MSG_RESULT(using $GLIBCONFIG)
AC_CHECK_LIB(glib-2.0, g_hash_table_get_values)
if test "x$ac_cv_lib_glib_2_0_g_hash_table_get_values" != x""yes; then
AC_MSG_WARN(Your version of Glib is too old, you should have at least 2.14)
fi
AC_CHECK_LIB(glib-2.0, g_list_free_full)
if test "x$ac_cv_lib_glib_2_0_g_list_free_full" != x""yes; then
AC_DEFINE_UNQUOTED(NEED_G_LIST_FREE_FULL, 1, glib-2.0 has no g_list_free_full)
fi
if
$PKGCONFIG --exists systemd
then
systemdunitdir=`$PKGCONFIG --variable=systemdsystemunitdir systemd`
AC_SUBST(systemdunitdir)
fi
AM_CONDITIONAL(HAVE_SYSTEMD, test -n "$systemdunitdir" -a "x$systemdunitdir" != xno)
#
# 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
AC_CHECK_LIB(c, gettext)
if test x$ac_cv_lib_c_gettext != xyes; then
AC_CHECK_LIB(intl, gettext)
fi
if test x$ac_cv_lib_c_gettext != xyes -a x$ac_cv_lib_intl_gettext != xyes; then
AC_MSG_ERROR(You need gettext installed in order to build ${PACKAGE})
fi
if test "X$GLIBCONFIG" != X; then
AC_MSG_CHECKING(for special glib includes: )
GLIBHEAD=`$GLIBCONFIG --cflags`
AC_MSG_RESULT($GLIBHEAD)
CPPFLAGS="$CPPFLAGS $GLIBHEAD"
AC_MSG_CHECKING(for glib library flags)
GLIBLIB=`$GLIBCONFIG --libs`
AC_MSG_RESULT($GLIBLIB)
LIBS="$LIBS $GLIBLIB"
fi
dnl ========================================================================
dnl Headers
dnl ========================================================================
AC_HEADER_STDC
AC_CHECK_HEADERS(arpa/inet.h)
AC_CHECK_HEADERS(asm/types.h)
AC_CHECK_HEADERS(assert.h)
AC_CHECK_HEADERS(auth-client.h)
AC_CHECK_HEADERS(ctype.h)
AC_CHECK_HEADERS(dirent.h)
AC_CHECK_HEADERS(errno.h)
AC_CHECK_HEADERS(fcntl.h)
AC_CHECK_HEADERS(getopt.h)
AC_CHECK_HEADERS(glib.h)
AC_CHECK_HEADERS(grp.h)
AC_CHECK_HEADERS(limits.h)
AC_CHECK_HEADERS(linux/errqueue.h)
AC_CHECK_HEADERS(malloc.h)
AC_CHECK_HEADERS(netdb.h)
AC_CHECK_HEADERS(netinet/in.h)
AC_CHECK_HEADERS(netinet/ip.h)
AC_CHECK_HEADERS(pam/pam_appl.h)
AC_CHECK_HEADERS(pthread.h)
AC_CHECK_HEADERS(pwd.h)
AC_CHECK_HEADERS(security/pam_appl.h)
AC_CHECK_HEADERS(sgtty.h)
AC_CHECK_HEADERS(signal.h)
AC_CHECK_HEADERS(stdarg.h)
AC_CHECK_HEADERS(stddef.h)
AC_CHECK_HEADERS(stdio.h)
AC_CHECK_HEADERS(stdlib.h)
AC_CHECK_HEADERS(string.h)
AC_CHECK_HEADERS(strings.h)
AC_CHECK_HEADERS(sys/dir.h)
AC_CHECK_HEADERS(sys/ioctl.h)
AC_CHECK_HEADERS(sys/param.h)
AC_CHECK_HEADERS(sys/poll.h)
AC_CHECK_HEADERS(sys/resource.h)
AC_CHECK_HEADERS(sys/select.h)
AC_CHECK_HEADERS(sys/socket.h)
AC_CHECK_HEADERS(sys/sockio.h)
AC_CHECK_HEADERS(sys/stat.h)
AC_CHECK_HEADERS(sys/time.h)
AC_CHECK_HEADERS(sys/timeb.h)
AC_CHECK_HEADERS(sys/types.h)
AC_CHECK_HEADERS(sys/uio.h)
AC_CHECK_HEADERS(sys/un.h)
AC_CHECK_HEADERS(sys/utsname.h)
AC_CHECK_HEADERS(sys/wait.h)
AC_CHECK_HEADERS(time.h)
AC_CHECK_HEADERS(unistd.h)
AC_CHECK_HEADERS(winsock.h)
dnl These headers need prerequisits before the tests will pass
dnl AC_CHECK_HEADERS(net/if.h)
dnl AC_CHECK_HEADERS(netinet/icmp6.h)
dnl AC_CHECK_HEADERS(netinet/ip6.h)
dnl AC_CHECK_HEADERS(netinet/ip_icmp.h)
AC_MSG_CHECKING(for special libxml2 includes)
if test "x$XML2CONFIG" = "x"; then
AC_MSG_ERROR(libxml2 config not found)
else
XML2HEAD="`$XML2CONFIG --cflags`"
AC_MSG_RESULT($XML2HEAD)
AC_CHECK_LIB(xml2, xmlReadMemory)
AC_CHECK_LIB(xslt, xsltApplyStylesheet)
fi
CPPFLAGS="$CPPFLAGS $XML2HEAD"
AC_CHECK_HEADERS(libxml/xpath.h)
AC_CHECK_HEADERS(libxslt/xslt.h)
if test "$ac_cv_header_libxml_xpath_h" != "yes"; then
AC_MSG_ERROR(The libxml developement headers were not found)
fi
if test "$ac_cv_header_libxslt_xslt_h" != "yes"; then
AC_MSG_ERROR(The libxslt developement headers were not found)
fi
dnl ========================================================================
dnl Structures
dnl ========================================================================
AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[[#include <time.h>]])
AC_CHECK_MEMBERS([lrm_op_t.rsc_deleted],,,[[#include <lrm/lrm_api.h>]])
dnl ========================================================================
dnl Functions
dnl ========================================================================
AC_CHECK_FUNCS(g_log_set_default_handler)
AC_CHECK_FUNCS(getopt, AC_DEFINE(HAVE_DECL_GETOPT, 1, [Have getopt function]))
AC_CHECK_FUNCS(nanosleep, AC_DEFINE(HAVE_DECL_NANOSLEEP, 1, [Have nanosleep function]))
dnl ========================================================================
dnl ltdl
dnl ========================================================================
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
AC_SUBST(INCLTDL)
AC_SUBST(LIBLTDL)
AC_SUBST(LIBLTDL_DIR)
dnl ========================================================================
dnl bzip2
dnl ========================================================================
AC_CHECK_HEADERS(bzlib.h)
AC_CHECK_LIB(bz2, BZ2_bzBuffToBuffCompress)
if test x$ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress != xyes ; then
AC_MSG_ERROR(BZ2 libraries not found)
fi
if test x$ac_cv_header_bzlib_h != xyes; then
AC_MSG_ERROR(BZ2 Development headers not found)
fi
dnl ========================================================================
dnl ncurses
dnl ========================================================================
dnl
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 ncurse takes precedence.
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
if test "x$CURSESLIBS" != "x"; then
PCMK_FEATURES="$PCMK_FEATURES ncurses"
fi
dnl Check for printw() prototype compatibility
if test X"$CURSESLIBS" != X"" && cc_supports_flag -Wcast-qual && cc_supports_flag -Werror; then
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 <curses.h>
#elif defined(HAVE_NCURSES_H)
# include <ncurses.h>
#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?])
fi
fi
AC_SUBST(CURSESLIBS)
dnl ========================================================================
dnl Profiling and GProf
dnl ========================================================================
case $SUPPORT_PROFILING in
1|yes|true)
SUPPORT_PROFILING=1
dnl Enable gprof
#LIBS="$LIBS -pg"
#CFLAGS="$CFLAGS -pg"
dnl Disable various compiler optimizations
CFLAGS="$CFLAGS -fno-omit-frame-pointer"
#CFLAGS="$CFLAGS -fno-inline-functions -fno-inline-functions-called-once -fno-optimize-sibling-calls"
dnl CFLAGS="$CFLAGS -fno-default-inline -fno-inline"
dnl Update features
PCMK_FEATURES="$PCMK_FEATURES gprof"
;;
*) SUPPORT_PROFILING=0;;
esac
AC_DEFINE_UNQUOTED(SUPPORT_PROFILING, $SUPPORT_PROFILING, Support for gprof profiling)
case $SUPPORT_GCOV in
1|yes|true)
SUPPORT_GCOV=1
dnl Enable gprof
#LIBS="$LIBS -pg"
#CFLAGS="$CFLAGS -pg"
dnl Disable various compiler optimizations
CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage -fno-inline"
dnl Turn off optimization so code coverage tool
dnl can get accurate line numbers
AC_MSG_NOTICE(Old CFLAGS: $CFLAGS)
CFLAGS=`echo $CFLAGS | sed -e 's/-O.\ //g' -e 's/-Wp,-D_FORTIFY_SOURCE=.\ //g'`
CFLAGS="$CFLAGS -O0"
AC_MSG_NOTICE(New CFLAGS: $CFLAGS)
dnl Update features
PCMK_FEATURES="$PCMK_FEATURES gcov"
;;
*) SUPPORT_PROFILING=0;;
esac
AC_DEFINE_UNQUOTED(SUPPORT_GCOV, $SUPPORT_GCOV, Support for gcov coverage testing)
dnl ========================================================================
dnl Cluster infrastructure - Heartbeat / LibQB
dnl ========================================================================
dnl Compatability checks
AC_CHECK_MEMBERS([struct lrm_ops.fail_rsc],,,[[#include <lrm/lrm_api.h>]])
if test x${enable_no_stack} = xyes; then
SUPPORT_HEARTBEAT=no
SUPPORT_CS=no
fi
PKG_CHECK_MODULES(libqb, libqb, HAVE_libqb=1, HAVE_libqb=0)
AC_CHECK_HEADERS(qb/qbipc_common.h)
AC_CHECK_LIB(qb, qb_ipcc_is_connected)
AC_CHECK_FUNCS(qb_ipcc_is_connected)
LIBQB_LOG=1
PCMK_FEATURES="$PCMK_FEATURES libqb-logging libqb-ipc"
if test $ac_cv_lib_qb_qb_ipcc_is_connected != yes; then
AC_MSG_FAILURE(Version of IPC in libqb is not new enough)
fi
AC_DEFINE_UNQUOTED(LIBQB_LOGGING, $LIBQB_LOG, Use libqb for logging)
AC_DEFINE_UNQUOTED(LIBQB_IPC, 0, Use libqb for IPC)
LIBS="$LIBS $libqb_LIBS"
AC_CHECK_HEADERS(heartbeat/hb_config.h)
AC_CHECK_HEADERS(heartbeat/glue_config.h)
AC_CHECK_HEADERS(stonith/stonith.h)
AC_CHECK_HEADERS(agent_config.h)
GLUE_HEADER=none
HAVE_GLUE=0
if test "$ac_cv_header_heartbeat_glue_config_h" = "yes"; then
GLUE_HEADER=glue_config.h
HAVE_GLUE=1
elif test "$ac_cv_header_heartbeat_hb_config_h" = "yes"; then
GLUE_HEADER=hb_config.h
HAVE_GLUE=1
else
AC_MSG_WARN(cluster-glue development headers were not found)
fi
if test "$ac_cv_header_stonith_stonith_h" = "yes"; then
PCMK_FEATURES="$PCMK_FEATURES lha-fencing"
fi
if test $HAVE_GLUE = 1; then
dnl On Debian, AC_CHECK_LIBS fail if a library has any unresolved symbols
dnl So check for all the depenancies (so they're added to LIBS) before checking for -lplumb
AC_CHECK_LIB(pils, PILLoadPlugin)
AC_CHECK_LIB(plumb, G_main_add_IPC_Channel)
fi
dnl ===============================================
dnl Variables needed for substitution
dnl ===============================================
CRM_DTD_DIRECTORY="${datadir}/pacemaker"
AC_DEFINE_UNQUOTED(CRM_DTD_DIRECTORY,"$CRM_DTD_DIRECTORY", Location for the Pacemaker Relax-NG Schema)
AC_SUBST(CRM_DTD_DIRECTORY)
AC_DEFINE_UNQUOTED(CRM_DTD_VERSION,"$CRM_DTD_VERSION", Current version of the Pacemaker Relax-NG Schema)
AC_SUBST(CRM_DTD_VERSION)
CRM_CORE_DIR=`try_extract_header_define $GLUE_HEADER HA_COREDIR ${localstatedir}/lib/heartbeat/cores`
AC_DEFINE_UNQUOTED(CRM_CORE_DIR,"$CRM_CORE_DIR", Location to store core files produced by Pacemaker daemons)
AC_SUBST(CRM_CORE_DIR)
CRM_DAEMON_USER=`try_extract_header_define $GLUE_HEADER HA_CCMUSER hacluster`
AC_DEFINE_UNQUOTED(CRM_DAEMON_USER,"$CRM_DAEMON_USER", User to run Pacemaker daemons as)
AC_SUBST(CRM_DAEMON_USER)
CRM_DAEMON_GROUP=`try_extract_header_define $GLUE_HEADER HA_APIGROUP haclient`
AC_DEFINE_UNQUOTED(CRM_DAEMON_GROUP,"$CRM_DAEMON_GROUP", Group to run Pacemaker daemons as)
AC_SUBST(CRM_DAEMON_GROUP)
CRM_STATE_DIR=${localstatedir}/run/crm
AC_DEFINE_UNQUOTED(CRM_STATE_DIR,"$CRM_STATE_DIR", Where to keep state files and sockets)
AC_SUBST(CRM_STATE_DIR)
CRM_BLACKBOX_DIR=${localstatedir}/lib/pacemaker
AC_DEFINE_UNQUOTED(CRM_BLACKBOX_DIR,"$CRM_BLACKBOX_DIR", Where to keep blackbox dumps)
AC_SUBST(CRM_BLACKBOX_DIR)
PE_STATE_DIR="${localstatedir}/lib/pengine"
AC_DEFINE_UNQUOTED(PE_STATE_DIR,"$PE_STATE_DIR", Where to keep PEngine outputs)
AC_SUBST(PE_STATE_DIR)
dnl Eventually move out of the heartbeat dir tree and create compatability code
CRM_CONFIG_DIR="${localstatedir}/lib/heartbeat/crm"
AC_DEFINE_UNQUOTED(CRM_CONFIG_DIR,"$CRM_CONFIG_DIR", Where to keep CIB configuration files)
AC_SUBST(CRM_CONFIG_DIR)
CRM_DAEMON_DIR="${libexecdir}/pacemaker"
AC_DEFINE_UNQUOTED(CRM_DAEMON_DIR,"$CRM_DAEMON_DIR", Location for Pacemaker daemons)
AC_SUBST(CRM_DAEMON_DIR)
HB_DAEMON_DIR=`try_extract_header_define $GLUE_HEADER HA_LIBHBDIR $libdir/heartbeat`
AC_DEFINE_UNQUOTED(HB_DAEMON_DIR,"$HB_DAEMON_DIR", Location for Heartbeat expects Pacemaker daemons to be in)
AC_SUBST(HB_DAEMON_DIR)
dnl Needed so that the Corosync plugin can clear out the directory as Heartbeat does
HA_STATE_DIR=`try_extract_header_define $GLUE_HEADER HA_VARRUNDIR ${localstatedir}/run`
AC_DEFINE_UNQUOTED(HA_STATE_DIR,"$HA_STATE_DIR", Where Heartbeat keeps state files and sockets)
AC_SUBST(HA_STATE_DIR)
CRM_RSCTMP_DIR=`try_extract_header_define agent_config.h HA_RSCTMPDIR $HA_STATE_DIR/heartbeat/rsctmp`
AC_MSG_CHECKING(Scratch dir for resource agents)
AC_MSG_RESULT($CRM_RSCTMP_DIR)
AC_DEFINE_UNQUOTED(CRM_RSCTMP_DIR,"$CRM_RSCTMP_DIR", Where resource agents should keep state files)
AC_SUBST(CRM_RSCTMP_DIR)
dnl Needed for the location of hostcache in CTS.py
HA_VARLIBHBDIR=`try_extract_header_define $GLUE_HEADER HA_VARLIBHBDIR ${localstatedir}/lib/heartbeat`
AC_SUBST(HA_VARLIBHBDIR)
AC_DEFINE_UNQUOTED(UUID_FILE,"$localstatedir/lib/heartbeat/hb_uuid", Location of Heartbeat's UUID file)
OCF_ROOT_DIR=`try_extract_header_define $GLUE_HEADER OCF_ROOT_DIR /usr/lib/ocf`
if test "X$OCF_ROOT_DIR" = X; then
AC_MSG_ERROR(Could not locate OCF directory)
fi
AC_SUBST(OCF_ROOT_DIR)
OCF_RA_DIR=`try_extract_header_define $GLUE_HEADER OCF_RA_DIR $OCF_ROOT_DIR/resource.d`
AC_DEFINE_UNQUOTED(OCF_RA_DIR,"$OCF_RA_DIR", Location for OCF RAs)
AC_SUBST(OCF_RA_DIR)
RH_STONITH_DIR="$sbindir"
AC_DEFINE_UNQUOTED(RH_STONITH_DIR,"$RH_STONITH_DIR", Location for Red Hat Stonith agents)
RH_STONITH_PREFIX="fence_"
AC_DEFINE_UNQUOTED(RH_STONITH_PREFIX,"$RH_STONITH_PREFIX", Prefix for Red Hat Stonith agents)
AC_PATH_PROGS(GIT, git false)
AC_MSG_CHECKING(build version)
BUILD_VERSION=$Format:%h$
if test $BUILD_VERSION != ":%h$"; then
AC_MSG_RESULT(archive hash: $BUILD_VERSION)
elif test -x $GIT -a -d .git; then
BUILD_VERSION=`$GIT log --pretty="format:%h" -n 1`
AC_MSG_RESULT(git hash: $BUILD_VERSION)
else
# The current directory name make a reasonable default
# Most generated archives will include the hash or tag
BASE=`basename $PWD`
BUILD_VERSION=`echo $BASE | sed s:.*[[Pp]]acemaker-::`
AC_MSG_RESULT(directory based hash: $BUILD_VERSION)
fi
AC_DEFINE_UNQUOTED(BUILD_VERSION, "$BUILD_VERSION", Build version)
AC_SUBST(BUILD_VERSION)
HAVE_gio=1
HAVE_upstart=0
HAVE_systemd=0
PKG_CHECK_MODULES(GIO, gio-2.0, ,HAVE_gio=0)
AC_CHECK_TYPE([GDBusProxy],,,[[#include <gio/gio.h>]])
if test x$ac_cv_type_GDBusProxy != xyes; then
HAVE_gio=0
AC_MSG_WARN(Unable to support systemd/upstart. You need to use glib >= 2.26)
fi
if test $HAVE_gio = 1 -a "x${enable_upstart}" != xno; then
HAVE_upstart=1
PCMK_FEATURES="$PCMK_FEATURES upstart"
fi
AC_DEFINE_UNQUOTED(SUPPORT_UPSTART, $HAVE_upstart, Support upstart based system services)
AM_CONDITIONAL(BUILD_UPSTART, test $HAVE_upstart = 1)
if test $HAVE_gio = 1 -a "x${enable_systemd}" != xno; then
HAVE_systemd=1
PCMK_FEATURES="$PCMK_FEATURES systemd"
fi
AC_DEFINE_UNQUOTED(SUPPORT_SYSTEMD, $HAVE_systemd, Support systemd based system services)
AM_CONDITIONAL(BUILD_SYSTEMD, test $HAVE_systemd = 1)
STACKS=""
CLUSTERLIBS=""
dnl ========================================================================
dnl Cluster stack - Heartbeat
dnl ========================================================================
case $SUPPORT_HEARTBEAT in
1|yes|true|try)
AC_MSG_CHECKING(for heartbeat support)
AC_CHECK_LIB(hbclient, ll_cluster_new, [SUPPORT_HEARTBEAT=1],
[if $SUPPORT_HEARTBEAT != try; then
AC_MSG_FAILURE(Unable to support Heartbeat: client libraries not found)
fi])
if test $SUPPORT_HEARTBEAT = 1 ; then
STACKS="$STACKS heartbeat"
AC_DEFINE_UNQUOTED(CCM_LIBRARY, "libccmclient.so.1", Library to load for ccm support)
AC_DEFINE_UNQUOTED(HEARTBEAT_LIBRARY, "libhbclient.so.1", Library to load for heartbeat support)
else
SUPPORT_HEARTBEAT=0
fi
;;
*) SUPPORT_HEARTBEAT=0;;
esac
AM_CONDITIONAL(BUILD_HEARTBEAT_SUPPORT, test $SUPPORT_HEARTBEAT = 1)
AC_DEFINE_UNQUOTED(SUPPORT_HEARTBEAT, $SUPPORT_HEARTBEAT, Support the Heartbeat messaging and membership layer)
AC_SUBST(SUPPORT_HEARTBEAT)
dnl ========================================================================
dnl Cluster stack - Corosync
dnl ========================================================================
dnl Normalize the values
case $SUPPORT_CS in
1|yes|true)
SUPPORT_CS=yes
missingisfatal=1;;
try) missingisfatal=0;;
*) SUPPORT_CS=no;;
esac
AC_MSG_CHECKING(for native corosync)
COROSYNC_LIBS=""
CS_USES_LIBQB=0
PCMK_SERVICE_ID=9
LCRSODIR="$libdir"
if test $SUPPORT_CS = no; then
AC_MSG_RESULT(no (disabled))
SUPPORT_CS=0
else
AC_MSG_RESULT($SUPPORT_CS, with '$CSPREFIX')
PKG_CHECK_MODULES(cpg, libcpg) dnl Fatal
PKG_CHECK_MODULES(cfg, libcfg) dnl Fatal
PKG_CHECK_MODULES(cmap, libcmap, HAVE_cmap=1, HAVE_cmap=0)
PKG_CHECK_MODULES(cman, libcman, HAVE_cman=1, HAVE_cman=0)
PKG_CHECK_MODULES(confdb, libconfdb, HAVE_confdb=1, HAVE_confdb=0)
PKG_CHECK_MODULES(fenced, libfenced, HAVE_fenced=1, HAVE_fenced=0)
PKG_CHECK_MODULES(quorum, libquorum, HAVE_quorum=1, HAVE_quorum=0)
PKG_CHECK_MODULES(oldipc, libcoroipcc, HAVE_oldipc=1, HAVE_oldipc=0)
if test $HAVE_oldipc = 1; then
SUPPORT_CS=1
CFLAGS="$CFLAGS $oldipc_FLAGS $cpg_FLAGS $cfg_FLAGS"
COROSYNC_LIBS="$COROSYNC_LIBS $oldipc_LIBS $cpg_LIBS $cfg_LIBS"
elif test $HAVE_libqb = 1; then
SUPPORT_CS=1
CS_USES_LIBQB=1
CFLAGS="$CFLAGS $libqb_FLAGS $cpg_FLAGS $cfg_FLAGS"
COROSYNC_LIBS="$COROSYNC_LIBS $libqb_LIBS $cpg_LIBS $cfg_LIBS"
AC_CHECK_LIB(corosync_common, cs_strerror)
else
aisreason="corosync/libqb IPC libraries not found by pkg_config"
fi
AC_DEFINE_UNQUOTED(HAVE_CONFDB, $HAVE_confdb, Have the old herarchial Corosync config API)
AC_DEFINE_UNQUOTED(HAVE_CMAP, $HAVE_cmap, Have the new non-herarchial Corosync config API)
fi
if test $SUPPORT_CS = 1 -a x$HAVE_oldipc = x0 ; then
dnl Support for plugins was removed about the time the IPC was
dnl moved to libqb.
dnl The only option now is the built-in quorum API
CFLAGS="$CFLAGS $cmap_CFLAGS $quorum_CFLAGS"
COROSYNC_LIBS="$COROSYNC_LIBS $cmap_LIBS $quorum_LIBS"
STACKS="$STACKS corosync-native"
AC_DEFINE_UNQUOTED(SUPPORT_CS_QUORUM, 1, Support the consumption of membership and quorum from corosync)
fi
if test $SUPPORT_CS = 1 -a x$HAVE_confdb = x1; then
dnl Need confdb to support cman and the plugins
LCRSODIR=`$PKGCONFIG corosync --variable=lcrsodir`
STACKS="$STACKS corosync-plugin"
COROSYNC_LIBS="$COROSYNC_LIBS $confdb_LIBS"
if test $SUPPORT_CMAN != no; then
if test $HAVE_cman = 1 -a $HAVE_fenced = 1; then
SUPPORT_CMAN=1
STACKS="$STACKS cman"
CFLAGS="$CFLAGS $cman_FLAGS $fenced_FLAGS"
COROSYNC_LIBS="$COROSYNC_LIBS $cman_LIBS $fenced_LIBS"
fi
fi
fi
dnl Normalize SUPPORT_CS and SUPPORT_CMAN for use with #if directives
if test $SUPPORT_CMAN != 1; then
SUPPORT_CMAN=0
fi
if test $SUPPORT_CS = 1; then
CLUSTERLIBS="$CLUSTERLIBS $COROSYNC_LIBS"
elif test $SUPPORT_CS != 0; then
SUPPORT_CS=0
if test $missingisfatal = 0; then
AC_MSG_WARN(Unable to support Corosync: $aisreason)
else
AC_MSG_FAILURE(Unable to support Corosync: $aisreason)
fi
fi
AC_DEFINE_UNQUOTED(SUPPORT_COROSYNC, $SUPPORT_CS, Support the Corosync messaging and membership layer)
AC_DEFINE_UNQUOTED(SUPPORT_CMAN, $SUPPORT_CMAN, Support the consumption of membership and quorum from cman)
AC_DEFINE_UNQUOTED(CS_USES_LIBQB, $CS_USES_LIBQB, Does corosync use libqb for its ipc)
AC_DEFINE_UNQUOTED(PCMK_SERVICE_ID, $PCMK_SERVICE_ID, Corosync service number)
AM_CONDITIONAL(BUILD_CS_SUPPORT, test $SUPPORT_CS = 1)
AM_CONDITIONAL(BUILD_CS_PLUGIN, test $HAVE_confdb = 1) dnl confdb went away at about the same time as plugins
AC_SUBST(SUPPORT_CMAN)
AC_SUBST(SUPPORT_CS)
dnl
dnl Cluster stack - Sanity
dnl
if test x${enable_no_stack} = xyes; then
AC_MSG_NOTICE(No cluster stack supported. Just building the Policy Engine)
PCMK_FEATURES="$PCMK_FEATURES no-cluster-stack"
else
AC_MSG_CHECKING(for supported stacks)
if test x"$STACKS" = x; then
AC_MSG_FAILURE(You must support at least one cluster stack (heartbeat or corosync) )
fi
AC_MSG_RESULT($STACKS)
PCMK_FEATURES="$PCMK_FEATURES $STACKS"
fi
AC_SUBST(CLUSTERLIBS)
AC_SUBST(LCRSODIR)
dnl ========================================================================
dnl SNMP
dnl ========================================================================
case $SUPPORT_SNMP in
1|yes|true) missingisfatal=1;;
try) missingisfatal=0;;
*) SUPPORT_SNMP=no;;
esac
SNMPLIBS=""
AC_MSG_CHECKING(for snmp support)
if test $SUPPORT_SNMP = no; then
AC_MSG_RESULT(no (disabled))
SUPPORT_SNMP=0
else
SNMPCONFIG=""
AC_MSG_RESULT($SUPPORT_SNMP)
AC_CHECK_HEADERS(net-snmp/net-snmp-config.h)
if test "x${ac_cv_header_net_snmp_net_snmp_config_h}" != "xyes"; then
SUPPORT_SNMP="no"
fi
if test $SUPPORT_SNMP != no; 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.)
SUPPORT_SNMP=no
fi
fi
if test $SUPPORT_SNMP != no; then
AC_MSG_CHECKING(for special snmp libraries)
SNMPLIBS=`$SNMPCONFIG --agent-libs`
AC_MSG_RESULT($SNMPLIBS)
fi
if test $SUPPORT_SNMP != no; then
savedLibs=$LIBS
LIBS="$LIBS $SNMPLIBS"
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",)
dnl AC_SUBST(CRYPTOLIB)
AC_CHECK_FUNCS(netsnmp_transport_open_client)
if test $ac_cv_func_netsnmp_transport_open_client != yes; then
AC_CHECK_FUNCS(netsnmp_tdomain_transport)
if test $ac_cv_func_netsnmp_tdomain_transport != yes; then
SUPPORT_SNMP=no
else
AC_DEFINE_UNQUOTED(NETSNMPV53, 1, [Use the older 5.3 version of the net-snmp API])
fi
fi
LIBS=$savedLibs
fi
if test $SUPPORT_SNMP = no; then
SNMPLIBS=""
SUPPORT_SNMP=0
if test $missingisfatal = 0; then
AC_MSG_WARN(Unable to support SNMP)
else
AC_MSG_FAILURE(Unable to support SNMP)
fi
else
SUPPORT_SNMP=1
fi
fi
if test $SUPPORT_SNMP = 1; then
PCMK_FEATURES="$PCMK_FEATURES snmp"
fi
AC_SUBST(SNMPLIBS)
AM_CONDITIONAL(ENABLE_SNMP, test "$SUPPORT_SNMP" = "1")
AC_DEFINE_UNQUOTED(ENABLE_SNMP, $SUPPORT_SNMP, Build in support for sending SNMP traps)
dnl ========================================================================
dnl ESMTP
dnl ========================================================================
case $SUPPORT_ESMTP in
1|yes|true) missingisfatal=1;;
try) missingisfatal=0;;
*) SUPPORT_ESMTP=no;;
esac
ESMTPLIB=""
AC_MSG_CHECKING(for esmtp support)
if test $SUPPORT_ESMTP = no; then
AC_MSG_RESULT(no (disabled))
SUPPORT_ESMTP=0
else
ESMTPCONFIG=""
AC_MSG_RESULT($SUPPORT_ESMTP)
AC_CHECK_HEADERS(libesmtp.h)
if test "x${ac_cv_header_libesmtp_h}" != "xyes"; then
ENABLE_ESMTP="no"
fi
if test $SUPPORT_ESMTP != no; then
AC_PATH_PROGS(ESMTPCONFIG, libesmtp-config)
if test "X${ESMTPCONFIG}" = "X"; then
AC_MSG_RESULT(You need the libesmtp development package to continue.)
SUPPORT_ESMTP=no
fi
fi
if test $SUPPORT_ESMTP != no; then
AC_MSG_CHECKING(for special esmtp libraries)
ESMTPLIBS=`$ESMTPCONFIG --libs | tr '\n' ' '`
AC_MSG_RESULT($ESMTPLIBS)
fi
if test $SUPPORT_ESMTP = no; then
SUPPORT_ESMTP=0
if test $missingisfatal = 0; then
AC_MSG_WARN(Unable to support ESMTP)
else
AC_MSG_FAILURE(Unable to support ESMTP)
fi
else
SUPPORT_ESMTP=1
PCMK_FEATURES="$PCMK_FEATURES libesmtp"
fi
fi
AC_SUBST(ESMTPLIBS)
AM_CONDITIONAL(ENABLE_ESMTP, test "$SUPPORT_ESMTP" = "1")
AC_DEFINE_UNQUOTED(ENABLE_ESMTP, $SUPPORT_ESMTP, Build in support for sending mail notifications with ESMTP)
dnl ========================================================================
dnl ACL
dnl ========================================================================
case $SUPPORT_ACL in
1|yes|true) missingisfatal=1;;
try) missingisfatal=0;;
*) SUPPORT_ACL=no;;
esac
AC_MSG_CHECKING(for acl support)
if test $SUPPORT_ACL = no; then
AC_MSG_RESULT(no (disabled))
SUPPORT_ACL=0
else
AC_MSG_RESULT($SUPPORT_ACL)
AC_CHECK_LIB(qb, qb_ipcs_connection_auth_set)
if test $ac_cv_lib_qb_qb_ipcs_connection_auth_set != yes; then
SUPPORT_ACL=0
else
SUPPORT_ACL=1
fi
if test $SUPPORT_ACL = 0; then
if test $missingisfatal = 0; then
AC_MSG_WARN(Unable to support ACL. You need to use libqb > 0.13.0)
else
AC_MSG_FAILURE(Unable to support ACL. You need to use libqb > 0.13.0)
fi
fi
fi
if test $SUPPORT_ACL = 1; then
PCMK_FEATURES="$PCMK_FEATURES acls"
fi
AM_CONDITIONAL(ENABLE_ACL, test "$SUPPORT_ACL" = "1")
AC_DEFINE_UNQUOTED(ENABLE_ACL, $SUPPORT_ACL, Build in support for CIB ACL)
dnl ========================================================================
dnl GnuTLS
dnl ========================================================================
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)
fi
AC_CHECK_LIB(gnutls, gnutls_init)
AC_CHECK_FUNCS(gnutls_priority_set_direct)
AC_SUBST(GNUTLSHEAD)
AC_SUBST(GNUTLSLIBS)
dnl ========================================================================
dnl System Health
dnl ========================================================================
dnl Check if servicelog development package is installed
SERVICELOG=servicelog-1
SERVICELOG_EXISTS="no"
AC_MSG_CHECKING(for $SERVICELOG packages)
if
$PKGCONFIG --exists $SERVICELOG
then
PKG_CHECK_MODULES([SERVICELOG], [servicelog-1])
SERVICELOG_EXISTS="yes"
fi
AC_MSG_RESULT($SERVICELOG_EXISTS)
AM_CONDITIONAL(BUILD_SERVICELOG, test "$SERVICELOG_EXISTS" = "yes")
dnl Check if OpenIMPI packages and servicelog are installed
OPENIPMI="OpenIPMI OpenIPMIposix"
OPENIPMI_SERVICELOG_EXISTS="no"
AC_MSG_CHECKING(for $SERVICELOG $OPENIPMI packages)
if
$PKGCONFIG --exists $OPENIPMI $SERVICELOG
then
PKG_CHECK_MODULES([OPENIPMI_SERVICELOG],[OpenIPMI OpenIPMIposix])
OPENIPMI_SERVICELOG_EXISTS="yes"
fi
AC_MSG_RESULT($OPENIPMI_SERVICELOG_EXISTS)
AM_CONDITIONAL(BUILD_OPENIPMI_SERVICELOG, test "$OPENIPMI_SERVICELOG_EXISTS" = "yes")
dnl ========================================================================
dnl Compiler flags
dnl ========================================================================
dnl Make sure that CFLAGS is not exported. If the user did
dnl not have CFLAGS in their environment then this should have
dnl no effect. However if CFLAGS was exported from the user's
dnl environment, then the new CFLAGS will also be exported
dnl to sub processes.
CC_ERRORS=""
CC_EXTRAS=""
if export | fgrep " CFLAGS=" > /dev/null; then
SAVED_CFLAGS="$CFLAGS"
unset CFLAGS
CFLAGS="$SAVED_CFLAGS"
unset SAVED_CFLAGS
fi
if test "$GCC" != yes; then
CFLAGS="$CFLAGS -g"
enable_fatal_warnings=no
else
CFLAGS="$CFLAGS -ggdb"
# We had to eliminate -Wnested-externs because of libtool changes
EXTRA_FLAGS="-fgnu89-inline
-fstack-protector-all
-Wall
-Waggregate-return
-Wbad-function-cast
-Wcast-align
-Wdeclaration-after-statement
-Wendif-labels
-Wfloat-equal
-Wformat=2
-Wformat-security
-Wformat-nonliteral
-Wmissing-prototypes
-Wmissing-declarations
-Wnested-externs
-Wno-long-long
-Wno-strict-aliasing
-Wno-unused-but-set-variable
-Wpointer-arith
-Wstrict-prototypes
-Wunsigned-char
-Wwrite-strings"
# Additional warnings it might be nice to enable one day
# -Wshadow
# -Wunreachable-code
for j in $EXTRA_FLAGS
do
if
cc_supports_flag $j
then
CC_EXTRAS="$CC_EXTRAS $j"
fi
done
dnl In lib/ais/Makefile.am there's a gcc option available as of v4.x
GCC_MAJOR=`gcc -v 2>&1 | awk 'END{print $3}' | sed 's/[.].*//'`
AM_CONDITIONAL(GCC_4, test "${GCC_MAJOR}" = 4)
dnl System specific options
case "$host_os" in
*linux*|*bsd*)
if test "${enable_fatal_warnings}" = "unknown"; then
enable_fatal_warnings=yes
fi
;;
esac
if test "x${enable_fatal_warnings}" != xno && cc_supports_flag -Werror ; then
enable_fatal_warnings=yes
else
enable_fatal_warnings=no
fi
if test "x${enable_ansi}" = xyes && cc_supports_flag -std=iso9899:199409 ; then
AC_MSG_NOTICE(Enabling ANSI Compatibility)
CC_EXTRAS="$CC_EXTRAS -ansi -D_GNU_SOURCE -DANSI_ONLY"
fi
AC_MSG_NOTICE(Activated additional gcc flags: ${CC_EXTRAS})
fi
CFLAGS="$CFLAGS $CC_EXTRAS"
NON_FATAL_CFLAGS="$CFLAGS"
AC_SUBST(NON_FATAL_CFLAGS)
dnl
dnl We reset CFLAGS to include our warnings *after* all function
dnl checking goes on, so that our warning flags don't keep the
dnl AC_*FUNCS() calls above from working. In particular, -Werror will
dnl *always* cause us troubles if we set it before here.
dnl
dnl
if test "x${enable_fatal_warnings}" = xyes ; then
AC_MSG_NOTICE(Enabling Fatal Warnings)
CFLAGS="$CFLAGS -Werror"
fi
AC_SUBST(CFLAGS)
dnl This is useful for use in Makefiles that need to remove one specific flag
CFLAGS_COPY="$CFLAGS"
AC_SUBST(CFLAGS_COPY)
AC_SUBST(LIBADD_DL) dnl extra flags for dynamic linking libraries
AC_SUBST(LIBADD_INTL) dnl extra flags for GNU gettext stuff...
AC_SUBST(LOCALE)
dnl Options for cleaning up the compiler output
QUIET_LIBTOOL_OPTS=""
QUIET_MAKE_OPTS=""
if test "x${enable_quiet}" = "xyes"; then
QUIET_LIBTOOL_OPTS="--quiet"
QUIET_MAKE_OPTS="--quiet"
fi
AC_MSG_RESULT(Supress make details: ${enable_quiet})
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(QUIET_MAKE_OPTS)
AC_SUBST(QUIET_LIBTOOL_OPTS)
AC_DEFINE_UNQUOTED(CRM_FEATURES, "$PCMK_FEATURES", Set of enabled features)
AC_SUBST(PCMK_FEATURES)
dnl The Makefiles and shell scripts we output
AC_CONFIG_FILES(Makefile \
cts/Makefile \
cts/CTSvars.py \
cts/LSBDummy \
cts/benchmark/Makefile \
cts/benchmark/clubench \
cib/Makefile \
crmd/Makefile \
pengine/Makefile \
pengine/regression.core.sh \
doc/Makefile \
doc/Pacemaker_Explained/publican.cfg \
doc/Clusters_from_Scratch/publican.cfg \
include/Makefile \
include/crm/Makefile \
include/crm/cib/Makefile \
include/crm/common/Makefile \
include/crm/cluster/Makefile \
include/crm/fencing/Makefile \
include/crm/pengine/Makefile \
replace/Makefile \
lib/Makefile \
lib/pcmk.pc \
lib/pcmk-pe.pc \
lib/pcmk-cib.pc \
lib/ais/Makefile \
lib/common/Makefile \
lib/cluster/Makefile \
lib/cib/Makefile \
lib/pengine/Makefile \
lib/transition/Makefile \
lib/fencing/Makefile \
lib/lrmd/Makefile \
lib/services/Makefile \
mcp/Makefile \
mcp/pacemaker \
mcp/pacemaker.service \
fencing/Makefile \
+ fencing/regression.py \
lrmd/Makefile \
lrmd/regression.py \
extra/Makefile \
extra/resources/Makefile \
extra/rgmanager/Makefile \
tools/Makefile \
tools/crm_report \
tools/coverage.sh \
xml/Makefile \
lib/gnu/Makefile \
)
dnl Now process the entire list of files added by previous
dnl calls to AC_CONFIG_FILES()
AC_OUTPUT()
dnl *****************
dnl Configure summary
dnl *****************
AC_MSG_RESULT([])
AC_MSG_RESULT([$PACKAGE configuration:])
AC_MSG_RESULT([ Version = ${VERSION} (Build: $BUILD_VERSION)])
AC_MSG_RESULT([ Features =${PCMK_FEATURES}])
AC_MSG_RESULT([])
AC_MSG_RESULT([ Prefix = ${prefix}])
AC_MSG_RESULT([ Executables = ${sbindir}])
AC_MSG_RESULT([ Man pages = ${mandir}])
AC_MSG_RESULT([ Libraries = ${libdir}])
AC_MSG_RESULT([ Header files = ${includedir}])
AC_MSG_RESULT([ Arch-independent files = ${datadir}])
AC_MSG_RESULT([ State information = ${localstatedir}])
AC_MSG_RESULT([ System configuration = ${sysconfdir}])
AC_MSG_RESULT([ Corosync Plugins = ${LCRSODIR}])
AC_MSG_RESULT([])
AC_MSG_RESULT([ Use system LTDL = ${ac_cv_lib_ltdl_lt_dlopen}])
AC_MSG_RESULT([])
AC_MSG_RESULT([ HA group name = ${CRM_DAEMON_GROUP}])
AC_MSG_RESULT([ HA user name = ${CRM_DAEMON_USER}])
AC_MSG_RESULT([])
AC_MSG_RESULT([ CFLAGS = ${CFLAGS}])
AC_MSG_RESULT([ Libraries = ${LIBS}])
AC_MSG_RESULT([ Stack Libraries = ${CLUSTERLIBS}])
diff --git a/fencing/Makefile.am b/fencing/Makefile.am
index 05e92d37a8..eed59048ac 100644
--- a/fencing/Makefile.am
+++ b/fencing/Makefile.am
@@ -1,82 +1,85 @@
# Author: Sun Jiang Dong <sunjd@cn.ibm.com>
# Copyright (c) 2004 International Business Machines
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
MAINTAINERCLEANFILES = Makefile.in
SUBDIRS =
## binary progs
+testdir = $(datadir)/$(PACKAGE)/tests/fencing
+test_SCRIPTS = regression.py
+
halibdir = $(CRM_DAEMON_DIR)
halib_PROGRAMS = stonithd stonith-test
sbin_PROGRAMS = stonith_admin
sbin_SCRIPTS = fence_legacy fence_pcmk
man7_MANS =
man8_MANS =
if BUILD_XML_HELP
man7_MANS += stonithd.7
stonithd.xml: stonithd
$(top_builddir)/fencing/$< metadata | $(XSLTPROC) --nonet --novalid --stringparam man.name $< $(top_srcdir)/xml/ocf-meta2man.xsl - > $(top_builddir)/fencing/$@
stonithd.7: stonithd.xml
$(XSLTPROC) $(MANPAGE_XSLT) $(top_builddir)/fencing/$<
endif
if BUILD_HELP
man8_MANS += $(sbin_PROGRAMS:%=%.8) $(sbin_SCRIPTS:%=%.8)
%.8: %
echo Creating $@
chmod a+x $<
$(HELP2MAN) --output $@ --no-info --section 8 --name "Part of the Pacemaker cluster resource manager" $(top_builddir)/fencing/$<
endif
stonith_test_SOURCES = test.c
stonith_test_LDADD = $(top_builddir)/lib/common/libcrmcommon.la \
$(top_builddir)/lib/cluster/libcrmcluster.la \
$(top_builddir)/lib/fencing/libstonithd.la \
$(CRYPTOLIB) $(CLUSTERLIBS)
stonith_admin_SOURCES = admin.c
stonith_admin_LDADD = $(top_builddir)/lib/common/libcrmcommon.la \
$(top_builddir)/lib/cib/libcib.la \
$(top_builddir)/lib/pengine/libpe_status.la \
$(top_builddir)/lib/cluster/libcrmcluster.la \
$(top_builddir)/lib/fencing/libstonithd.la \
$(CRYPTOLIB) $(CLUSTERLIBS)
stonithd_SOURCES = main.c commands.c remote.c
if BUILD_STONITH_CONFIG
BUILT_SOURCES = standalone_config.h
stonithd_SOURCES += standalone_config.c config.y config.l
stonithd_AM_LFLAGS = -o$(LEX_OUTPUT_ROOT).c
# lex/yacc issues:
endif
stonithd_YFLAGS = -d
stonithd_LDADD = $(top_builddir)/lib/common/libcrmcommon.la \
$(top_builddir)/lib/cluster/libcrmcluster.la \
$(top_builddir)/lib/fencing/libstonithd.la \
$(CRYPTOLIB) $(CLUSTERLIBS)
CFLAGS = $(CFLAGS_COPY:-Werror=)
diff --git a/fencing/fence_false b/fencing/fence_false
index af9409e893..ae7c2d15e2 100644
--- a/fencing/fence_false
+++ b/fencing/fence_false
@@ -1,75 +1,76 @@
#!/usr/bin/python
# The Following Agent Has Been Tested On:
#
# Virsh 0.3.3 on RHEL 5.2 with xen-3.0.3-51
#
import sys, time
sys.path.append("/usr/share/fence")
from fencing import *
#BEGIN_VERSION_GENERATION
RELEASE_VERSION="3.1.6"
BUILD_DATE="(built Mon Oct 24 12:14:08 UTC 2011)"
REDHAT_COPYRIGHT="Copyright (C) Red Hat, Inc. 2004-2010 All rights reserved."
#END_VERSION_GENERATION
plug_status="on"
def get_outlets_status(conn, options):
result={}
# This fake agent has no port data to list, so we have to make
# something up for the list action.
if options.has_key("-o") and options["-o"] == "list":
result["fake_port_1"]=[plug_status, "fake"]
result["fake_port_2"]=[plug_status, "fake"]
elif (options.has_key("-n") == 0):
fail_usage("Failed: You have to enter existing machine!")
else:
port=options["-n"]
result[port]=[plug_status, "fake"]
return result
def get_power_status(conn, options):
outlets=get_outlets_status(conn,options)
if len(outlets) == 0 or options.has_key("-n") == 0:
fail_usage("Failed: You have to enter existing machine!")
else:
return outlets[options["-n"]][0]
def set_power_status(conn, options):
global plug_status
plug_status = "unknown"
+ exit(1)
def main():
device_opt = [ "help", "version", "agent", "quiet", "verbose", "debug", "action", "port",
"no_password", "power_wait", "power_timeout", ]
atexit.register(atexit_handler)
pinput = process_input(device_opt)
# Fake options to keep the library happy
#pinput["-p"] = "none"
pinput["-a"] = "localhost"
pinput["-C"] = ","
options = check_input(device_opt, pinput)
if options.has_key("-o") and (options["-o"] == "monitor"):
sys.exit(0)
## Defaults for fence agent
docs = { }
docs["shortdesc"] = "Fake fence agent"
docs["longdesc"] = "fence_true is a fake Fencing agent which always reports success without doing anything."
show_docs(options, docs)
## Operate the fencing device
result = fence_action(None, options, set_power_status, get_power_status, get_outlets_status)
sys.exit(result)
if __name__ == "__main__":
main()
diff --git a/fencing/main.c b/fencing/main.c
index 502bfe1a57..bf6bfb89cd 100644
--- a/fencing/main.c
+++ b/fencing/main.c
@@ -1,864 +1,872 @@
/*
* Copyright (C) 2009 Andrew Beekhof <andrew@beekhof.net>
*
* 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 software 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <crm_internal.h>
#include <sys/param.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <crm/crm.h>
#include <crm/msg_xml.h>
#include <crm/common/ipc.h>
#include <crm/cluster/internal.h>
#include <crm/stonith-ng.h>
#include <crm/fencing/internal.h>
#include <crm/common/xml.h>
#include <crm/common/mainloop.h>
#include <crm/cib/internal.h>
#include <internal.h>
#include <standalone_config.h>
char *stonith_our_uname = NULL;
GMainLoop *mainloop = NULL;
GHashTable *client_list = NULL;
gboolean stand_alone = FALSE;
+gboolean no_cib_connect = FALSE;
gboolean stonith_shutdown_flag = FALSE;
qb_ipcs_service_t *ipcs = NULL;
#if SUPPORT_HEARTBEAT
ll_cluster_t *hb_conn = NULL;
#endif
static void stonith_shutdown(int nsig);
static void stonith_cleanup(void);
static int32_t
st_ipc_accept(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
{
crm_trace("Connecting %p for uid=%d gid=%d", c, uid, gid);
if(stonith_shutdown_flag) {
crm_info("Ignoring new client [%d] during shutdown", crm_ipcs_client_pid(c));
return -EPERM;
}
return 0;
}
static void
st_ipc_created(qb_ipcs_connection_t *c)
{
stonith_client_t *new_client = NULL;
#if 0
struct qb_ipcs_stats srv_stats;
qb_ipcs_stats_get(s1, &srv_stats, QB_FALSE);
qb_log(LOG_INFO, "Connection created (active:%d, closed:%d)",
srv_stats.active_connections,
srv_stats.closed_connections);
#endif
new_client = calloc(1, sizeof(stonith_client_t));
new_client->channel = c;
new_client->channel_name = strdup("ipc");
CRM_CHECK(new_client->id == NULL, free(new_client->id));
new_client->id = crm_generate_uuid();
crm_trace("Created channel %p for client %s", c, new_client->id);
/* make sure we can find ourselves later for sync calls
* redirected to the master instance
*/
g_hash_table_insert(client_list, new_client->id, new_client);
qb_ipcs_context_set(c, new_client);
CRM_ASSERT(qb_ipcs_context_get(c) != NULL);
}
/* Exit code means? */
static int32_t
st_ipc_dispatch(qb_ipcs_connection_t *c, void *data, size_t size)
{
xmlNode *request = NULL;
stonith_client_t *client = (stonith_client_t*)qb_ipcs_context_get(c);
request = crm_ipcs_recv(c, data, size);
if (request == NULL) {
return 0;
}
CRM_CHECK(client != NULL, goto cleanup);
if(client->name == NULL) {
const char *value = crm_element_value(request, F_STONITH_CLIENTNAME);
if(value == NULL) {
client->name = crm_itoa(crm_ipcs_client_pid(c));
} else {
client->name = strdup(value);
}
}
CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p/%s", client, client->name); goto cleanup);
crm_xml_add(request, F_STONITH_CLIENTID, client->id);
crm_xml_add(request, F_STONITH_CLIENTNAME, client->name);
crm_log_xml_trace(request, "Client[inbound]");
stonith_command(client, request, NULL);
cleanup:
if(client == NULL || client->id == NULL) {
crm_log_xml_notice(request, "Invalid client");
}
free_xml(request);
return 0;
}
/* Error code means? */
static int32_t
st_ipc_closed(qb_ipcs_connection_t *c)
{
stonith_client_t *client = (stonith_client_t*)qb_ipcs_context_get(c);
#if 0
qb_ipcs_stats_get(s1, &srv_stats, QB_FALSE);
qb_ipcs_connection_stats_get(c, &stats, QB_FALSE);
qb_log(LOG_INFO, "Connection to pid:%d destroyed (active:%d, closed:%d)",
stats.client_pid,
srv_stats.active_connections,
srv_stats.closed_connections);
qb_log(LOG_DEBUG, " Requests %"PRIu64"", stats.requests);
qb_log(LOG_DEBUG, " Responses %"PRIu64"", stats.responses);
qb_log(LOG_DEBUG, " Events %"PRIu64"", stats.events);
qb_log(LOG_DEBUG, " Send retries %"PRIu64"", stats.send_retries);
qb_log(LOG_DEBUG, " Recv retries %"PRIu64"", stats.recv_retries);
qb_log(LOG_DEBUG, " FC state %d", stats.flow_control_state);
qb_log(LOG_DEBUG, " FC count %"PRIu64"", stats.flow_control_count);
#endif
if (client == NULL) {
crm_err("No client");
return 0;
}
crm_trace("Cleaning up after client disconnect: %p/%s/%s", client, crm_str(client->name), client->id);
if(client->id != NULL) {
g_hash_table_remove(client_list, client->id);
}
/* 0 means: yes, go ahead and destroy the connection */
return 0;
}
static void
st_ipc_destroy(qb_ipcs_connection_t *c)
{
stonith_client_t *client = (stonith_client_t*)qb_ipcs_context_get(c);
/* Make sure the connection is fully cleaned up */
st_ipc_closed(c);
if(client == NULL) {
crm_trace("Nothing to destroy");
return;
}
crm_trace("Destroying %s (%p)", client->name, client);
free(client->name);
free(client->id);
free(client);
crm_trace("Done");
return;
}
static void
stonith_peer_callback(xmlNode * msg, void* private_data)
{
const char *remote = crm_element_value(msg, F_ORIG);
crm_log_xml_trace(msg, "Peer[inbound]");
stonith_command(NULL, msg, remote);
}
#if SUPPORT_HEARTBEAT
static void
stonith_peer_hb_callback(HA_Message * msg, void* private_data)
{
xmlNode *xml = convert_ha_message(NULL, msg, __FUNCTION__);
stonith_peer_callback(xml, private_data);
free_xml(xml);
}
static void
stonith_peer_hb_destroy(gpointer user_data)
{
if(stonith_shutdown_flag) {
crm_info("Heartbeat disconnection complete... exiting");
} else {
crm_err("Heartbeat connection lost! Exiting.");
}
stonith_shutdown(0);
}
#endif
#if SUPPORT_COROSYNC
static gboolean stonith_peer_ais_callback(
AIS_Message *wrapper, char *data, int sender)
{
xmlNode *xml = NULL;
if(wrapper->header.id == crm_class_cluster) {
xml = string2xml(data);
if(xml == NULL) {
goto bail;
}
crm_xml_add(xml, F_ORIG, wrapper->sender.uname);
crm_xml_add_int(xml, F_SEQ, wrapper->id);
stonith_peer_callback(xml, NULL);
}
free_xml(xml);
return TRUE;
bail:
crm_err("Invalid XML: '%.120s'", data);
return TRUE;
}
static void
stonith_peer_ais_destroy(gpointer user_data)
{
crm_err("AIS connection terminated");
stonith_shutdown(0);
}
#endif
void do_local_reply(xmlNode *notify_src, const char *client_id,
gboolean sync_reply, gboolean from_peer)
{
/* send callback to originating child */
stonith_client_t *client_obj = NULL;
int local_rc = pcmk_ok;
crm_trace("Sending response");
if(client_id != NULL) {
client_obj = g_hash_table_lookup(client_list, client_id);
} else {
crm_trace("No client to sent the response to."
" F_STONITH_CLIENTID not set.");
}
crm_trace("Sending callback to request originator");
if(client_obj == NULL) {
local_rc = -1;
} else {
crm_trace("Sending %ssync response to %s %s",
sync_reply?"":"an a-",
client_obj->name,
from_peer?"(originator of delegated request)":"");
local_rc = crm_ipcs_send(client_obj->channel, notify_src, !sync_reply);
}
if(local_rc < pcmk_ok && client_obj != NULL) {
crm_warn("%sSync reply to %s failed: %s",
sync_reply?"":"A-",
client_obj?client_obj->name:"<unknown>", pcmk_strerror(local_rc));
}
}
long long get_stonith_flag(const char *name)
{
if(safe_str_eq(name, T_STONITH_NOTIFY_FENCE)) {
return 0x01;
} else if(safe_str_eq(name, STONITH_OP_DEVICE_ADD)) {
return 0x04;
} else if(safe_str_eq(name, STONITH_OP_DEVICE_DEL)) {
return 0x10;
}
return 0;
}
static void
stonith_notify_client(gpointer key, gpointer value, gpointer user_data)
{
xmlNode *update_msg = user_data;
stonith_client_t *client = value;
const char *type = NULL;
CRM_CHECK(client != NULL, return);
CRM_CHECK(update_msg != NULL, return);
type = crm_element_value(update_msg, F_SUBTYPE);
CRM_CHECK(type != NULL, crm_log_xml_err(update_msg, "notify"); return);
if(client->channel == NULL) {
crm_trace("Skipping client with NULL channel");
return;
} else if(client->name == NULL) {
crm_trace("Skipping unnammed client / comamnd channel");
return;
}
if(client->flags & get_stonith_flag(type)) {
crm_trace("Sending %s-notification to client %s/%s", type, client->name, client->id);
if(crm_ipcs_send(client->channel, update_msg, ipcs_send_event|ipcs_send_error) <= 0) {
crm_warn("%s-Notification of client %s/%s failed",
type, client->name, client->id);
}
}
}
void
do_stonith_notify(
int options, const char *type, int result, xmlNode *data,
const char *remote)
{
/* TODO: Standardize the contents of data */
xmlNode *update_msg = create_xml_node(NULL, "notify");
CRM_CHECK(type != NULL, ;);
crm_xml_add(update_msg, F_TYPE, T_STONITH_NOTIFY);
crm_xml_add(update_msg, F_SUBTYPE, type);
crm_xml_add(update_msg, F_STONITH_OPERATION, type);
crm_xml_add_int(update_msg, F_STONITH_RC, result);
if(data != NULL) {
add_message_xml(update_msg, F_STONITH_CALLDATA, data);
}
crm_trace("Notifying clients");
g_hash_table_foreach(client_list, stonith_notify_client, update_msg);
free_xml(update_msg);
crm_trace("Notify complete");
}
static stonith_key_value_t *parse_device_list(const char *devices)
{
int lpc = 0;
int max = 0;
int last = 0;
stonith_key_value_t *output = NULL;
if(devices == NULL) {
return output;
}
max = strlen(devices);
for(lpc = 0; lpc <= max; lpc++) {
if(devices[lpc] == ',' || devices[lpc] == 0) {
char *line = NULL;
line = calloc(1, 2 + lpc - last);
snprintf(line, 1 + lpc - last, "%s", devices+last);
output = stonith_key_value_add(output, NULL, line);
free(line);
last = lpc + 1;
}
}
return output;
}
static void topology_remove_helper(const char *node, int level)
{
int rc;
char *desc = NULL;
xmlNode *data = create_xml_node(NULL, F_STONITH_LEVEL);
xmlNode *notify_data = create_xml_node(NULL, STONITH_OP_LEVEL_DEL);
crm_xml_add(data, "origin", __FUNCTION__);
crm_xml_add_int(data, XML_ATTR_ID, level);
crm_xml_add(data, F_STONITH_TARGET, node);
rc = stonith_level_remove(data, &desc);
crm_xml_add(notify_data, F_STONITH_DEVICE, desc);
crm_xml_add_int(notify_data, F_STONITH_ACTIVE, g_hash_table_size(topology));
do_stonith_notify(0, STONITH_OP_LEVEL_DEL, rc, notify_data, NULL);
free_xml(notify_data);
free_xml(data);
free(desc);
}
static void topology_register_helper(const char *node, int level, stonith_key_value_t *device_list)
{
int rc;
char *desc = NULL;
xmlNode *notify_data = create_xml_node(NULL, STONITH_OP_LEVEL_ADD);
xmlNode *data = create_level_registration_xml(node, level, device_list);
rc = stonith_level_register(data, &desc);
crm_xml_add(notify_data, F_STONITH_DEVICE, desc);
crm_xml_add_int(notify_data, F_STONITH_ACTIVE, g_hash_table_size(topology));
do_stonith_notify(0, STONITH_OP_LEVEL_ADD, rc, notify_data, NULL);
free_xml(notify_data);
free_xml(data);
free(desc);
}
static void remove_fencing_topology(xmlXPathObjectPtr xpathObj)
{
int max = 0, lpc = 0;
if(xpathObj && xpathObj->nodesetval) {
max = xpathObj->nodesetval->nodeNr;
}
for(lpc = 0; lpc < max; lpc++) {
xmlNode *match = getXpathResult(xpathObj, lpc);
CRM_CHECK(match != NULL, continue);
if(crm_element_value(match, XML_DIFF_MARKER)) {
/* Deletion */
int index = 0;
const char *target = crm_element_value(match, XML_ATTR_STONITH_TARGET);
crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index);
if(target == NULL) {
crm_err("Invalid fencing target in element %s", ID(match));
} else if(index <= 0) {
crm_err("Invalid level for %s in element %s", target, ID(match));
} else {
topology_remove_helper(target, index);
}
/* } else { Deal with modifications during the 'addition' stage */
}
}
}
static void register_fencing_topology(xmlXPathObjectPtr xpathObj, gboolean force)
{
int max = 0, lpc = 0;
if(xpathObj && xpathObj->nodesetval) {
max = xpathObj->nodesetval->nodeNr;
}
for(lpc = 0; lpc < max; lpc++) {
int index = 0;
const char *target;
const char *dev_list;
stonith_key_value_t *devices = NULL;
xmlNode *match = getXpathResult(xpathObj, lpc);
CRM_CHECK(match != NULL, continue);
crm_element_value_int(match, XML_ATTR_STONITH_INDEX, &index);
target = crm_element_value(match, XML_ATTR_STONITH_TARGET);
dev_list = crm_element_value(match, XML_ATTR_STONITH_DEVICES);
devices = parse_device_list(dev_list);
crm_trace("Updating %s[%d] (%s) to %s", target, index, ID(match), dev_list);
if(target == NULL) {
crm_err("Invalid fencing target in element %s", ID(match));
} else if(index <= 0) {
crm_err("Invalid level for %s in element %s", target, ID(match));
} else if(force == FALSE && crm_element_value(match, XML_DIFF_MARKER)) {
/* Addition */
topology_register_helper(target, index, devices);
} else { /* Modification */
/* Remove then re-add */
topology_remove_helper(target, index);
topology_register_helper(target, index, devices);
}
stonith_key_value_freeall(devices, 1, 1);
}
}
/* Fencing
<diff crm_feature_set="3.0.6">
<diff-removed>
<fencing-topology>
<fencing-level id="f-p1.1" target="pcmk-1" index="1" devices="poison-pill" __crm_diff_marker__="removed:top"/>
<fencing-level id="f-p1.2" target="pcmk-1" index="2" devices="power" __crm_diff_marker__="removed:top"/>
<fencing-level devices="disk,network" id="f-p2.1"/>
</fencing-topology>
</diff-removed>
<diff-added>
<fencing-topology>
<fencing-level id="f-p.1" target="pcmk-1" index="1" devices="poison-pill" __crm_diff_marker__="added:top"/>
<fencing-level id="f-p2.1" target="pcmk-2" index="1" devices="disk,something"/>
<fencing-level id="f-p3.1" target="pcmk-2" index="2" devices="power" __crm_diff_marker__="added:top"/>
</fencing-topology>
</diff-added>
</diff>
*/
static void
fencing_topology_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
xmlXPathObjectPtr xpathObj = NULL;
const char *xpath = "//" XML_TAG_FENCING_LEVEL;
crm_trace("Pushing in stonith topology");
/* Grab everything */
xpathObj = xpath_search(msg, xpath);
register_fencing_topology(xpathObj, TRUE);
if(xpathObj) {
xmlXPathFreeObject(xpathObj);
}
}
static void
update_fencing_topology(const char *event, xmlNode * msg)
{
const char *xpath;
xmlXPathObjectPtr xpathObj = NULL;
/* Process deletions (only) */
xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_REMOVED "//" XML_TAG_FENCING_LEVEL;
xpathObj = xpath_search(msg, xpath);
remove_fencing_topology(xpathObj);
if(xpathObj) {
xmlXPathFreeObject(xpathObj);
}
/* Process additions and changes */
xpath = "//" F_CIB_UPDATE_RESULT "//" XML_TAG_DIFF_ADDED "//" XML_TAG_FENCING_LEVEL;
xpathObj = xpath_search(msg, xpath);
register_fencing_topology(xpathObj, FALSE);
if(xpathObj) {
xmlXPathFreeObject(xpathObj);
}
}
static void
stonith_shutdown(int nsig)
{
stonith_shutdown_flag = TRUE;
crm_info("Terminating with %d clients", g_hash_table_size(client_list));
if(mainloop != NULL && g_main_is_running(mainloop)) {
g_main_quit(mainloop);
} else {
stonith_cleanup();
exit(EX_OK);
}
}
cib_t *cib = NULL;
static void
stonith_cleanup(void)
{
if(cib) {
cib->cmds->signoff(cib);
}
qb_ipcs_destroy(ipcs);
crm_peer_destroy();
g_hash_table_destroy(client_list);
free(stonith_our_uname);
#if HAVE_LIBXML2
crm_xml_cleanup();
#endif
}
/* *INDENT-OFF* */
static struct crm_option long_options[] = {
- {"stand-alone", 0, 0, 's'},
+ {"stand-alone", 0, 0, 's'},
+ {"stand-alone-w-cpg", 0, 0, 'c'},
{"verbose", 0, 0, 'V'},
{"version", 0, 0, '$'},
{"help", 0, 0, '?'},
{0, 0, 0, 0}
};
/* *INDENT-ON* */
static void
setup_cib(void)
{
static void *cib_library = NULL;
static cib_t *(*cib_new_fn)(void) = NULL;
static const char *(*cib_err_fn)(int) = NULL;
int rc, retries = 0;
if(cib_library == NULL) {
cib_library = dlopen(CIB_LIBRARY, RTLD_LAZY);
}
if(cib_library && cib_new_fn == NULL) {
cib_new_fn = dlsym(cib_library, "cib_new");
}
if(cib_library && cib_err_fn == NULL) {
cib_err_fn = dlsym(cib_library, "pcmk_strerror");
}
if(cib_new_fn != NULL) {
cib = (*cib_new_fn)();
}
if(cib == NULL) {
crm_err("No connection to the CIB");
return;
}
do {
sleep(retries);
rc = cib->cmds->signon(cib, CRM_SYSTEM_CRMD, cib_command);
} while(rc == -ENOTCONN && ++retries < 5);
if (rc != pcmk_ok) {
crm_err("Could not connect to the CIB service: %s", (*cib_err_fn)(rc));
} else if (pcmk_ok != cib->cmds->add_notify_callback(
cib, T_CIB_DIFF_NOTIFY, update_fencing_topology)) {
crm_err("Could not set CIB notification callback");
} else {
rc = cib->cmds->query(cib, NULL, NULL, cib_scope_local);
add_cib_op_callback(cib, rc, FALSE, NULL, fencing_topology_callback);
crm_notice("Watching for stonith topology changes");
}
}
struct qb_ipcs_service_handlers ipc_callbacks =
{
.connection_accept = st_ipc_accept,
.connection_created = st_ipc_created,
.msg_process = st_ipc_dispatch,
.connection_closed = st_ipc_closed,
.connection_destroyed = st_ipc_destroy
};
int
main(int argc, char ** argv)
{
int flag;
int rc = 0;
int lpc = 0;
int argerr = 0;
int option_index = 0;
const char *actions[] = { "reboot", "poweroff", "list", "monitor", "status" };
crm_log_init("stonith-ng", LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
crm_set_options(NULL, "mode [options]", long_options,
"Provides a summary of cluster's current state."
"\n\nOutputs varying levels of detail in a number of different formats.\n");
while (1) {
flag = crm_get_option(argc, argv, &option_index);
if (flag == -1) {
break;
}
switch(flag) {
case 'V':
crm_bump_log_level();
break;
case 's':
stand_alone = TRUE;
break;
+ case 'c':
+ stand_alone = FALSE;
+ no_cib_connect = TRUE;
+ break;
case '$':
case '?':
crm_help(flag, EX_OK);
break;
default:
++argerr;
break;
}
}
if(argc - optind == 1 && safe_str_eq("metadata", argv[optind])) {
printf("<?xml version=\"1.0\"?><!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n");
printf("<resource-agent name=\"stonithd\">\n");
printf(" <version>1.0</version>\n");
printf(" <longdesc lang=\"en\">This is a fake resource that details the instance attributes handled by stonithd.</longdesc>\n");
printf(" <shortdesc lang=\"en\">Options available for all stonith resources</shortdesc>\n");
printf(" <parameters>\n");
printf(" <parameter name=\"stonith-timeout\" unique=\"0\">\n");
printf(" <shortdesc lang=\"en\">How long to wait for the STONITH action to complete.</shortdesc>\n");
printf(" <longdesc lang=\"en\">Overrides the stonith-timeout cluster property</longdesc>\n");
printf(" <content type=\"time\" default=\"60s\"/>\n");
printf(" </parameter>\n");
printf(" <parameter name=\"priority\" unique=\"0\">\n");
printf(" <shortdesc lang=\"en\">The priority of the stonith resource. The lower the number, the higher the priority.</shortdesc>\n");
printf(" <content type=\"integer\" default=\"0\"/>\n");
printf(" </parameter>\n");
printf(" <parameter name=\"%s\" unique=\"0\">\n", STONITH_ATTR_HOSTARG);
printf(" <shortdesc lang=\"en\">Advanced use only: An alternate parameter to supply instead of 'port'</shortdesc>\n");
printf(" <longdesc lang=\"en\">Some devices do not support the standard 'port' parameter or may provide additional ones.\n"
"Use this to specify an alternate, device-specific, parameter that should indicate the machine to be fenced.\n"
"A value of 'none' can be used to tell the cluster not to supply any additional parameters.\n"
" </longdesc>\n");
printf(" <content type=\"string\" default=\"port\"/>\n");
printf(" </parameter>\n");
printf(" <parameter name=\"%s\" unique=\"0\">\n", STONITH_ATTR_HOSTMAP);
printf(" <shortdesc lang=\"en\">A mapping of host names to ports numbers for devices that do not support host names.</shortdesc>\n");
printf(" <longdesc lang=\"en\">Eg. node1:1;node2:2,3 would tell the cluster to use port 1 for node1 and ports 2 and 3 for node2</longdesc>\n");
printf(" <content type=\"string\" default=\"\"/>\n");
printf(" </parameter>\n");
printf(" <parameter name=\"%s\" unique=\"0\">\n", STONITH_ATTR_HOSTLIST);
printf(" <shortdesc lang=\"en\">A list of machines controlled by this device (Optional unless %s=static-list).</shortdesc>\n", STONITH_ATTR_HOSTCHECK);
printf(" <content type=\"string\" default=\"\"/>\n");
printf(" </parameter>\n");
printf(" <parameter name=\"%s\" unique=\"0\">\n", STONITH_ATTR_HOSTCHECK);
printf(" <shortdesc lang=\"en\">How to determin which machines are controlled by the device.</shortdesc>\n");
printf(" <longdesc lang=\"en\">Allowed values: dynamic-list (query the device), static-list (check the %s attribute), none (assume every device can fence every machine)</longdesc>\n", STONITH_ATTR_HOSTLIST);
printf(" <content type=\"string\" default=\"dynamic-list\"/>\n");
printf(" </parameter>\n");
for(lpc = 0; lpc < DIMOF(actions); lpc++) {
printf(" <parameter name=\"pcmk_%s_action\" unique=\"0\">\n", actions[lpc]);
printf(" <shortdesc lang=\"en\">Advanced use only: An alternate command to run instead of '%s'</shortdesc>\n", actions[lpc]);
printf(" <longdesc lang=\"en\">Some devices do not support the standard commands or may provide additional ones.\n"
"Use this to specify an alternate, device-specific, command that implements the '%s' action.</longdesc>\n", actions[lpc]);
printf(" <content type=\"string\" default=\"%s\"/>\n", actions[lpc]);
printf(" </parameter>\n");
}
printf(" </parameters>\n");
printf("</resource-agent>\n");
return 0;
}
if (optind != argc) {
++argerr;
}
if (argerr) {
crm_help('?', EX_USAGE);
}
mainloop_add_signal(SIGTERM, stonith_shutdown);
crm_peer_init();
client_list = g_hash_table_new(crm_str_hash, g_str_equal);
if(stand_alone == FALSE) {
void *dispatch = NULL;
void *destroy = NULL;
#if SUPPORT_HEARTBEAT
dispatch = stonith_peer_hb_callback;
destroy = stonith_peer_hb_destroy;
#endif
if(is_openais_cluster()) {
#if SUPPORT_COROSYNC
destroy = stonith_peer_ais_destroy;
dispatch = stonith_peer_ais_callback;
#endif
}
if(crm_cluster_connect(&stonith_our_uname, NULL, dispatch, destroy,
#if SUPPORT_HEARTBEAT
&hb_conn
#else
NULL
#endif
) == FALSE) {
crm_crit("Cannot sign in to the cluster... terminating");
exit(100);
}
- setup_cib();
+ if (no_cib_connect == FALSE) {
+ setup_cib();
+ }
} else {
stonith_our_uname = strdup("localhost");
}
device_list = g_hash_table_new_full(
crm_str_hash, g_str_equal, NULL, free_device);
topology = g_hash_table_new_full(
crm_str_hash, g_str_equal, NULL, free_topology_entry);
ipcs = mainloop_add_ipc_server("stonith-ng", QB_IPC_NATIVE, &ipc_callbacks);
#if SUPPORT_STONITH_CONFIG
if (((stand_alone == TRUE)) && !(standalone_cfg_read_file(STONITH_NG_CONF_FILE))) {
standalone_cfg_commit();
}
#endif
if(ipcs != NULL) {
/* Create the mainloop and run it... */
mainloop = g_main_new(FALSE);
crm_info("Starting %s mainloop", crm_system_name);
g_main_run(mainloop);
} else {
crm_err("Couldnt start all communication channels, exiting.");
}
stonith_cleanup();
#if SUPPORT_HEARTBEAT
if(hb_conn) {
hb_conn->llc_ops->delete(hb_conn);
}
#endif
crm_info("Done");
qb_log_fini();
return rc;
}
diff --git a/fencing/regression.py.in b/fencing/regression.py.in
new file mode 100644
index 0000000000..ea508b7c96
--- /dev/null
+++ b/fencing/regression.py.in
@@ -0,0 +1,496 @@
+#!/usr/bin/python
+
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+import os
+import sys
+import subprocess
+import shlex
+import time
+
+def output_from_command(command):
+ test = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ test.wait()
+
+ return test.communicate()[0].split("\n")
+
+class Test:
+ def __init__(self, name, description, verbose = 0, with_cpg = 0):
+ self.name = name
+ self.description = description
+ self.cmds = []
+ self.verbose = verbose
+
+ self.result_txt = ""
+ self.cmd_tool_output = ""
+ self.result_exitcode = 0;
+
+ self.stonith_options = "-s"
+ self.enable_corosync = 0
+ if with_cpg:
+ self.stonith_options = "-c"
+ self.enable_corosync = 1
+
+ self.stonith_process = None
+ self.stonith_output = ""
+ self.stonith_patterns = []
+
+ self.executed = 0
+
+ rsc_classes = output_from_command("crm_resource --list-standards")
+
+ self.has_systemd = 0
+ if "systemd" in rsc_classes:
+ self.has_systemd = 1
+
+ def __new_cmd(self, cmd, args, exitcode, stdout_match = "", no_wait = 0, stdout_negative_match = "", kill=None):
+ self.cmds.append(
+ {
+ "cmd" : cmd,
+ "kill" : kill,
+ "args" : args,
+ "expected_exitcode" : exitcode,
+ "stdout_match" : stdout_match,
+ "stdout_negative_match" : stdout_negative_match,
+ "no_wait" : no_wait,
+ }
+ )
+
+ def start_corosync(self):
+ if self.enable_corosync == 0:
+ return
+
+ if self.has_systemd:
+ cmd = shlex.split("systemctl start corosync.service")
+ else:
+ cmd = shlex.split("service corosync start")
+
+ test = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ test.wait()
+
+ def stop_corosync(self):
+ if self.enable_corosync == 0:
+ return
+
+ if self.has_systemd:
+ cmd = shlex.split("systemctl stop corosync.service")
+ else:
+ cmd = shlex.split("service corosync stop")
+ test = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ test.wait()
+
+ def stop_pacemaker(self):
+ if self.has_systemd:
+ cmd = shlex.split("systemctl stop pacemaker.service")
+ else:
+ cmd = shlex.split("service pacemaker stop")
+ test = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ test.wait()
+
+ def start_environment(self):
+ ### make sure we are in full control here ###
+ self.stop_pacemaker()
+ self.stop_corosync()
+
+ cmd = shlex.split("killall -q -9 stonithd")
+ test = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ test.wait()
+
+ self.start_corosync()
+
+ self.stonith_process = subprocess.Popen(
+ shlex.split("@CRM_DAEMON_DIR@/stonithd %s -V" % self.stonith_options),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ time.sleep(1)
+
+ def clean_environment(self):
+ if self.stonith_process:
+ self.stonith_process.kill()
+
+ self.stonith_output = self.stonith_process.communicate()[1]
+ self.stonith_process = None
+
+ self.stop_corosync()
+
+ def add_stonith_log_pattern(self, pattern):
+ self.stonith_patterns.append(pattern)
+
+ def add_cmd(self, cmd, args):
+ self.__new_cmd(cmd, args, 0, "")
+
+ def add_cmd_no_wait(self, cmd, args):
+ self.__new_cmd(cmd, args, 0, "", 1)
+
+ def add_cmd_check_stdout(self, cmd, args, match, no_match = ""):
+ self.__new_cmd(cmd, args, 0, match, 0, no_match)
+
+ def add_expected_fail_cmd(self, cmd, args, exitcode = 255):
+ self.__new_cmd(cmd, args, exitcode, "")
+
+ def get_exitcode(self):
+ return self.result_exitcode
+
+ def print_result(self, filler):
+ print "%s%s" % (filler, self.result_txt)
+
+ def run_cmd(self, args):
+ cmd = shlex.split(args['args'])
+ cmd.insert(0, args['cmd'])
+
+ if self.verbose:
+ print "\n\nRunning: "+" ".join(cmd)
+ test = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ if args['kill']:
+ if self.verbose:
+ print "Also running: "+args['kill']
+ subprocess.Popen(shlex.split(args['kill']))
+
+ if args['no_wait'] == 0:
+ test.wait()
+ else:
+ return 0
+
+ output = test.communicate()[0]
+
+ if args['stdout_match'] != "" and output.count(args['stdout_match']) == 0:
+ test.returncode = -2
+ print "STDOUT string '%s' was not found in cmd output: %s" % (args['stdout_match'], output)
+
+ if args['stdout_negative_match'] != "" and output.count(args['stdout_negative_match']) != 0:
+ test.returncode = -2
+ print "STDOUT string '%s' was found in cmd output: %s" % (args['stdout_negative_match'], output)
+
+ return test.returncode;
+
+ def match_stonith_patterns(self):
+ cur = 0
+ total_patterns = len(self.stonith_patterns)
+
+ if len(self.stonith_patterns) == 0:
+ return
+
+ for line in self.stonith_output.split("\n"):
+ if line.count(self.stonith_patterns[cur]):
+ cur = cur + 1
+ if cur == total_patterns:
+ break
+
+ if cur != len(self.stonith_patterns):
+ for item in range(total_patterns):
+ if self.verbose and item > (cur -1):
+ print "Pattern Not Matched = '%s'" % self.stonith_patterns[item]
+
+ self.result_txt = "FAILURE - '%s' failed. %d patterns out of %d not matched" % (self.name, total_patterns - cur, total_patterns)
+ self.result_exitcode = -1
+
+ def run(self):
+ res = 0
+ i = 1
+ self.start_environment()
+
+ if self.verbose:
+ print "\n--- START TEST - %s" % self.name
+
+ self.result_txt = "SUCCESS - '%s'" % (self.name)
+ self.result_exitcode = 0
+ for cmd in self.cmds:
+ res = self.run_cmd(cmd)
+ if res != cmd['expected_exitcode']:
+ print "Step %d FAILED - command returned %d, expected %d" % (i, res, cmd['expected_exitcode'])
+ self.result_txt = "FAILURE - '%s' failed at step %d. Command: lrmd_test %s" % (self.name, i, cmd['args'])
+ self.result_exitcode = -1
+ break
+ else:
+ if self.verbose:
+ print "Step %d SUCCESS" % (i)
+ i = i + 1
+ self.clean_environment()
+
+ if self.result_exitcode == 0:
+ self.match_stonith_patterns()
+
+ print self.result_txt
+ if self.verbose:
+ print "--- END TEST - %s\n" % self.name
+
+ self.executed = 1
+ return res
+
+class Tests:
+ def __init__(self, verbose = 0):
+ self.tests = []
+ self.verbose = verbose
+
+ def new_test(self, name, description, with_cpg = 0):
+ test = Test(name, description, self.verbose, with_cpg)
+ self.tests.append(test)
+ return test
+
+ def print_list(self):
+ print "\n==== %d TESTS FOUND ====" % (len(self.tests))
+ print "%35s - %s" % ("TEST NAME", "TEST DESCRIPTION")
+ print "%35s - %s" % ("--------------------", "--------------------")
+ for test in self.tests:
+ print "%35s - %s" % (test.name, test.description)
+ print "==== END OF LIST ====\n"
+
+ def run_single(self, name):
+ for test in self.tests:
+ if test.name == name:
+ test.run()
+ break;
+
+ def run_tests_matching(self, pattern):
+ for test in self.tests:
+ if test.name.count(pattern) != 0:
+ test.run()
+
+ def run_tests(self):
+ for test in self.tests:
+ test.run()
+
+ def print_results(self):
+ failures = 0;
+ success = 0;
+ print "\n\n======= FINAL RESULTS =========="
+ print "\n--- FAILURE RESULTS:"
+ for test in self.tests:
+ if test.executed == 0:
+ continue
+
+ if test.get_exitcode() != 0:
+ failures = failures + 1
+ test.print_result(" ")
+ else:
+ success = success + 1
+
+ if failures == 0:
+ print " None"
+
+ print "\n--- TOTALS\n Pass:%d\n Fail:%d\n" % (success, failures)
+ def build_api_sanity_tests(self):
+ verbose_arg = ""
+ if self.verbose:
+ verbose_arg = "-V"
+
+ test = self.new_test("api_sanity_test", "Sanity test client api.")
+ test.add_cmd("@CRM_DAEMON_DIR@/stonith-test", "-t %s" % (verbose_arg))
+
+ def build_standalone_tests(self):
+ test_types = [
+ {
+ "prefix" : "standalone" ,
+ "use_cpg" : 0,
+ },
+ {
+ "prefix" : "cpg" ,
+ "use_cpg" : 1,
+ },
+ ]
+
+ # test what happens when multiple devices can fence a node, but the first device fails.
+ for test_type in test_types:
+ test = self.new_test("%s_fence_device_failure" % test_type["prefix"],
+ "Verify that when one fence device fails for a node, the others are tried.", test_type["use_cpg"])
+ test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
+ test.add_cmd("stonith_admin", "-R true1 -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
+ test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
+ test.add_cmd("stonith_admin", "-F node3 -t 5")
+
+ # simple topology test for one device
+ for test_type in test_types:
+ if test_type["use_cpg"] == 0:
+ continue
+
+ test = self.new_test("%s_topology_simple" % test_type["prefix"],
+ "Verify all fencing devices at a level are used.", test_type["use_cpg"])
+ test.add_cmd("stonith_admin", "-R true -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
+
+ test.add_cmd("stonith_admin", "-r node3 -i 1 -v true")
+ test.add_cmd("stonith_admin", "-F node3 -t 5")
+
+ test.add_stonith_log_pattern("for host 'node3' with device 'true' returned: 0")
+
+ # test what happens when the first fencing level has multiple devices.
+ for test_type in test_types:
+ if test_type["use_cpg"] == 0:
+ continue
+
+ test = self.new_test("%s_topology_device_fails" % test_type["prefix"],
+ "Verify if one device in a level fails, the other is tried.", test_type["use_cpg"])
+ test.add_cmd("stonith_admin", "-R false -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
+ test.add_cmd("stonith_admin", "-R true -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
+
+ test.add_cmd("stonith_admin", "-r node3 -i 1 -v false")
+ test.add_cmd("stonith_admin", "-r node3 -i 2 -v true")
+ test.add_cmd("stonith_admin", "-F node3 -t 5")
+
+ test.add_stonith_log_pattern("for host 'node3' with device 'false' returned: -1001")
+ test.add_stonith_log_pattern("for host 'node3' with device 'true' returned: 0")
+
+ # test what happens when the first fencing level fails.
+ for test_type in test_types:
+ if test_type["use_cpg"] == 0:
+ continue
+
+ test = self.new_test("%s_topology_multi_level_fails" % test_type["prefix"],
+ "Verify if one level fails, the next leve is tried.", test_type["use_cpg"])
+ test.add_cmd("stonith_admin", "-R true1 -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
+ test.add_cmd("stonith_admin", "-R true2 -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
+ test.add_cmd("stonith_admin", "-R true3 -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
+ test.add_cmd("stonith_admin", "-R true4 -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
+ test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
+ test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
+
+ test.add_cmd("stonith_admin", "-r node3 -i 1 -v false1")
+ test.add_cmd("stonith_admin", "-r node3 -i 1 -v true1")
+ test.add_cmd("stonith_admin", "-r node3 -i 2 -v true2")
+ test.add_cmd("stonith_admin", "-r node3 -i 2 -v false2")
+ test.add_cmd("stonith_admin", "-r node3 -i 3 -v true3")
+ test.add_cmd("stonith_admin", "-r node3 -i 3 -v true4")
+
+ test.add_cmd("stonith_admin", "-F node3 -t 5")
+
+
+ test.add_stonith_log_pattern("for host 'node3' with device 'false1' returned: -1001")
+ test.add_stonith_log_pattern("for host 'node3' with device 'false2' returned: -1001")
+ test.add_stonith_log_pattern("for host 'node3' with device 'true3' returned: 0")
+ test.add_stonith_log_pattern("for host 'node3' with device 'true4' returned: 0")
+
+ # test the stonith builds the correct list of devices that can fence a node.
+ for test_type in test_types:
+ test = self.new_test("%s_list_devices" % test_type["prefix"],
+ "Verify list of devices that can fence a node is correct", test_type["use_cpg"])
+ test.add_cmd("stonith_admin", "-R true1 -a fence_true -o \"pcmk_host_list=node3\"")
+ test.add_cmd("stonith_admin", "-R true2 -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
+ test.add_cmd("stonith_admin", "-R true3 -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
+
+ test.add_cmd_check_stdout("stonith_admin", "-l node1 -V", "true2", "true1")
+ test.add_cmd_check_stdout("stonith_admin", "-l node1 -V", "true3", "true1")
+
+ # simple test of device monitor
+ for test_type in test_types:
+ test = self.new_test("%s_monitor" % test_type["prefix"],
+ "Verify device is reachable", test_type["use_cpg"])
+ test.add_cmd("stonith_admin", "-R true1 -a fence_true -o \"pcmk_host_list=node3\"")
+ test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node3\"")
+
+ test.add_cmd("stonith_admin", "-Q true1")
+ test.add_cmd("stonith_admin", "-Q false1")
+ test.add_expected_fail_cmd("stonith_admin", "-Q true2", 237)
+
+ # simple register test
+ for test_type in test_types:
+ test = self.new_test("%s_register" % test_type["prefix"],
+ "Verify devices can be registered and un-registered", test_type["use_cpg"])
+ test.add_cmd("stonith_admin", "-R true1 -a fence_true -o \"pcmk_host_list=node3\"")
+
+ test.add_cmd("stonith_admin", "-Q true1")
+
+ test.add_cmd("stonith_admin", "-D true1")
+
+ test.add_expected_fail_cmd("stonith_admin", "-Q true1", 237)
+
+ # test fencing history.
+ for test_type in test_types:
+ if test_type["use_cpg"] == 0:
+ continue
+ test = self.new_test("%s_fence_history" % test_type["prefix"],
+ "Verify last fencing operation is returned.", test_type["use_cpg"])
+ test.add_cmd("stonith_admin", "-R true1 -a fence_true -o \"pcmk_host_list=node3\"")
+
+ test.add_cmd("stonith_admin", "-F node3 -t 5 -V")
+
+ test.add_cmd_check_stdout("stonith_admin", "-H node3", "was able to turn off node node3", "")
+
+class TestOptions:
+ def __init__(self):
+ self.options = {}
+ self.options['list-tests'] = 0
+ self.options['run-all'] = 1
+ self.options['run-only'] = ""
+ self.options['run-only-pattern'] = ""
+ self.options['verbose'] = 0
+ self.options['invalid-arg'] = ""
+ self.options['show-usage'] = 0
+
+ def build_options(self, argv):
+ args = argv[1:]
+ skip = 0
+ for i in range(0, len(args)):
+ if skip:
+ skip = 0
+ continue
+ elif args[i] == "-h" or args[i] == "--help":
+ self.options['show-usage'] = 1
+ elif args[i] == "-l" or args[i] == "--list-tests":
+ self.options['list-tests'] = 1
+ elif args[i] == "-V" or args[i] == "--verbose":
+ self.options['verbose'] = 1
+ elif args[i] == "-r" or args[i] == "--run-only":
+ self.options['run-only'] = args[i+1]
+ skip = 1
+ elif args[i] == "-p" or args[i] == "--run-only-pattern":
+ self.options['run-only-pattern'] = args[i+1]
+ skip = 1
+
+ def show_usage(self):
+ print "usage: " + sys.argv[0] + " [options]"
+ print "If no options are provided, all tests will run"
+ print "Options:"
+ print "\t [--help | -h] Show usage"
+ print "\t [--list-tests | -l] Print out all registered tests."
+ print "\t [--run-only | -r 'testname'] Run a specific test"
+ print "\t [--verbose | -V] Verbose output"
+ print "\t [--run-only-pattern | -p 'string'] Run only tests containing the string value"
+ print "\n\tExample: Run only the test 'start_top'"
+ print "\t\t python ./regression.py --run-only start_stop"
+ print "\n\tExample: Run only the tests with the string 'systemd' present in them"
+ print "\t\t python ./regression.py --run-only-pattern systemd"
+
+def main(argv):
+ o = TestOptions()
+ o.build_options(argv)
+
+ tests = Tests(o.options['verbose'])
+ tests.build_standalone_tests()
+ tests.build_api_sanity_tests()
+
+ os.system("cp /usr/share/pacemaker/tests/cts/fence_false /usr/sbin/fence_false")
+ os.system("cp /usr/share/pacemaker/tests/cts/fence_true /usr/sbin/fence_true")
+
+ print "Starting ..."
+
+ if o.options['list-tests']:
+ tests.print_list()
+ elif o.options['show-usage']:
+ o.show_usage()
+ elif o.options['run-only-pattern'] != "":
+ tests.run_tests_matching(o.options['run-only-pattern'])
+ tests.print_results()
+ elif o.options['run-only'] != "":
+ tests.run_single(o.options['run-only'])
+ tests.print_results()
+ else:
+ tests.run_tests()
+ tests.print_results()
+
+if __name__=="__main__":
+ main(sys.argv)
diff --git a/fencing/test.c b/fencing/test.c
index cb26bd56da..be9b5df1e8 100644
--- a/fencing/test.c
+++ b/fencing/test.c
@@ -1,209 +1,378 @@
/*
* Copyright (C) 2009 Andrew Beekhof <andrew@beekhof.net>
*
* 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 software 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <crm_internal.h>
#include <sys/param.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <crm/crm.h>
#include <crm/msg_xml.h>
#include <crm/common/ipc.h>
#include <crm/cluster/internal.h>
#include <crm/stonith-ng.h>
#include <crm/fencing/internal.h>
#include <crm/common/xml.h>
-
/* *INDENT-OFF* */
+enum test_modes {
+ /* class dev test using a very specific environment */
+ test_standard = 0,
+ /* watch notifications only */
+ test_passive,
+ /* sanity test stonith client api using fence_true and fence_false */
+ test_api_sanity,
+};
+
static struct crm_option long_options[] = {
{"verbose", 0, 0, 'V'},
{"version", 0, 0, '$'},
{"help", 0, 0, '?'},
{"passive", 0, 0, 'p'},
+ {"api_test", 0, 0, 't'},
{0, 0, 0, 0}
};
/* *INDENT-ON* */
+stonith_t *st = NULL;
+struct pollfd pollfd;
int st_opts = st_opt_sync_call;
+int expected_notifications = 0;
+int verbose = 0;
+
+static void dispatch_helper(int timeout)
+{
+ int rc;
+ crm_debug("Looking for notification");
+ pollfd.events = POLLIN;
+ while(true) {
+ rc = poll( &pollfd, 1, timeout); /* wait 10 minutes, -1 forever */
+ if (rc > 0 ) {
+ stonith_dispatch( st );
+ } else {
+ break;
+ }
+ }
+}
static void st_callback(stonith_t *st, stonith_event_t *e)
{
if(st->state == stonith_disconnected) {
exit(1);
}
crm_notice("Operation %s requested by %s %s for peer %s. %s reported: %s (ref=%s)",
e->operation, e->origin, e->result == pcmk_ok?"completed":"failed",
e->target, e->executioner ? e->executioner : "<none>",
pcmk_strerror(e->result), e->id);
+
+ if (expected_notifications) {
+ expected_notifications--;
+ }
}
static void
st_global_callback(stonith_t * stonith, const xmlNode * msg, int call_id, int rc,
xmlNode * output, void *userdata)
{
crm_log_xml_notice((xmlNode*)msg, "Event");
}
+static void
+passive_test(void)
+{
+ st->cmds->register_notification(st, T_STONITH_NOTIFY_DISCONNECT, st_callback);
+ st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, st_callback);
+ st->cmds->register_notification(st, STONITH_OP_DEVICE_ADD, st_callback);
+ st->cmds->register_notification(st, STONITH_OP_DEVICE_DEL, st_callback);
+ st->cmds->register_callback(st, 0, 120, FALSE, NULL, "st_global_callback", st_global_callback);
+
+ dispatch_helper(600 * 1000);
+}
+
+#define single_test(cmd, str, num_notifications, expected_rc) \
+{ \
+ int rc = 0; \
+ rc = cmd; \
+ expected_notifications = 0; \
+ if (num_notifications) { \
+ expected_notifications = num_notifications; \
+ dispatch_helper(500); \
+ } \
+ if (rc != expected_rc) { \
+ crm_info("FAILURE - expected rc %d != %d(%s) for cmd - %s\n", expected_rc, rc, pcmk_strerror(rc), str); \
+ exit(-1); \
+ } else if (expected_notifications) { \
+ crm_info("FAILURE - expected %d notifications, got only %d for cmd - %s\n", \
+ num_notifications, num_notifications - expected_notifications, str); \
+ exit(-1); \
+ } else { \
+ if (verbose) { \
+ crm_info("SUCCESS - %s: %d", str, rc); \
+ } else { \
+ crm_debug("SUCCESS - %s: %d", str, rc); \
+ } \
+ } \
+}\
+
+static void
+run_fence_failure_test(void)
+{
+ stonith_key_value_t *params = NULL;
+
+ params = stonith_key_value_add(params, "pcmk_host_map", "pcmk-1=1,2 pcmk-2=3,4");
+
+ single_test(st->cmds->register_device(st, st_opts, "test-id1", "stonith-ng", "fence_false", params),
+ "Register device1 for failure test", 1, 0);
+
+ single_test(st->cmds->fence(st, st_opts, "pcmk-2", "off", 3),
+ "Fence failure results off", 1, -1001);
+
+ single_test(st->cmds->fence(st, st_opts, "pcmk-2", "reboot", 3),
+ "Fence failure results reboot", 1, -1001);
+
+ single_test(st->cmds->remove_device(st, st_opts, "test-id1"),
+ "Remove device1 for failure test", 1, 0);
+
+ stonith_key_value_freeall(params, 1, 1);
+}
+
+static void
+run_fence_failure_rollover_test(void)
+{
+ stonith_key_value_t *params = NULL;
+
+ params = stonith_key_value_add(params, "pcmk_host_map", "pcmk-1=1,2 pcmk-2=3,4");
+
+ single_test(st->cmds->register_device(st, st_opts, "test-id1", "stonith-ng", "fence_false", params),
+ "Register device1 for rollover test", 1, 0);
+
+ single_test(st->cmds->register_device(st, st_opts, "test-id2", "stonith-ng", "fence_true", params),
+ "Register device2 for rollover test", 1, 0);
+
+ single_test(st->cmds->fence(st, st_opts, "pcmk-2", "off", 3),
+ "Fence rollover results off", 1, 0);
+
+ single_test(st->cmds->fence(st, st_opts, "pcmk-2", "on", 3),
+ "Fence rollover results on", 1, 0);
+
+ single_test(st->cmds->remove_device(st, st_opts, "test-id1"),
+ "Remove device1 for rollover tests", 1, 0);
+
+ single_test(st->cmds->remove_device(st, st_opts, "test-id2"),
+ "Remove device2 for rollover tests", 1, 0);
+
+ stonith_key_value_freeall(params, 1, 1);
+}
+
+static void
+run_standard_test(void)
+{
+ stonith_key_value_t *params = NULL;
+
+ params = stonith_key_value_add(params, "pcmk_host_map", "pcmk-1=1,2 pcmk-2=3,4");
+
+ single_test(st->cmds->register_device(st, st_opts, "test-id", "stonith-ng", "fence_true", params),
+ "Register", 1, 0);
+
+ single_test(st->cmds->list(st, st_opts, "test-id", NULL, 1),
+ "list", 1, 0);
+
+ single_test(st->cmds->monitor(st, st_opts, "test-id", 1),
+ "Monitor", 1, 0);
+
+ single_test(st->cmds->status(st, st_opts, "test-id", "pcmk-2", 1),
+ "Status pcmk-2", 1, 0);
+
+ single_test(st->cmds->status(st, st_opts, "test-id", "pcmk-1", 1),
+ "Status pcmk-1", 1, 0);
+
+ single_test(st->cmds->fence(st, st_opts, "unknown-host", "off", 1),
+ "Fence unknown-host (expected failure)", 0, -113);
+
+ single_test(st->cmds->fence(st, st_opts, "pcmk-1", "off", 1),
+ "Fence pcmk-1", 1, 0);
+
+ single_test(st->cmds->fence(st, st_opts, "pcmk-1", "on", 1),
+ "Unfence pcmk-1", 1, 0);
+
+ single_test(st->cmds->remove_device(st, st_opts, "test-id"),
+ "Remove test-id", 1, 0);
+
+ stonith_key_value_freeall(params, 1, 1);
+}
+
+static void
+sanity_tests(void)
+{
+ st->cmds->register_notification(st, T_STONITH_NOTIFY_DISCONNECT, st_callback);
+ st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, st_callback);
+ st->cmds->register_notification(st, STONITH_OP_DEVICE_ADD, st_callback);
+ st->cmds->register_notification(st, STONITH_OP_DEVICE_DEL, st_callback);
+ st->cmds->register_callback(st, 0, 120, FALSE, NULL, "st_global_callback", st_global_callback);
+
+ crm_info("Starting API Sanity Tests");
+ run_standard_test();
+ run_fence_failure_test();
+ run_fence_failure_rollover_test();
+ crm_info("Sanity Tests Passed");
+}
+
+static void
+standard_dev_test(void)
+{
+ int rc = 0;
+ char *tmp = NULL;
+ stonith_key_value_t *params = NULL;
+
+ params = stonith_key_value_add(params, "pcmk_host_map", "some-host=pcmk-7 pcmk-3=3,4");
+
+ rc = st->cmds->register_device(st, st_opts, "test-id", "stonith-ng", "fence_xvm", params);
+ crm_debug("Register: %d", rc);
+
+ rc = st->cmds->list(st, st_opts, "test-id", &tmp, 10);
+ crm_debug("List: %d output: %s\n", rc, tmp ? tmp : "<none>");
+
+ rc = st->cmds->monitor(st, st_opts, "test-id", 10);
+ crm_debug("Monitor: %d", rc);
+
+ rc = st->cmds->status(st, st_opts, "test-id", "pcmk-2", 10);
+ crm_debug("Status pcmk-2: %d", rc);
+
+ rc = st->cmds->status(st, st_opts, "test-id", "pcmk-1", 10);
+ crm_debug("Status pcmk-1: %d", rc);
+
+ rc = st->cmds->fence(st, st_opts, "unknown-host", "off", 60);
+ crm_debug("Fence unknown-host: %d", rc);
+
+ rc = st->cmds->status(st, st_opts, "test-id", "pcmk-1", 10);
+ crm_debug("Status pcmk-1: %d", rc);
+
+ rc = st->cmds->fence(st, st_opts, "pcmk-1", "off", 60);
+ crm_debug("Fence pcmk-1: %d", rc);
+
+ rc = st->cmds->status(st, st_opts, "test-id", "pcmk-1", 10);
+ crm_debug("Status pcmk-1: %d", rc);
+
+ rc = st->cmds->fence(st, st_opts, "pcmk-1", "on", 10);
+ crm_debug("Unfence pcmk-1: %d", rc);
+
+ rc = st->cmds->status(st, st_opts, "test-id", "pcmk-1", 10);
+ crm_debug("Status pcmk-1: %d", rc);
+
+ rc = st->cmds->fence(st, st_opts, "some-host", "off", 10);
+ crm_debug("Fence alias: %d", rc);
+
+ rc = st->cmds->status(st, st_opts, "test-id", "some-host", 10);
+ crm_debug("Status alias: %d", rc);
+
+ rc = st->cmds->fence(st, st_opts, "pcmk-1", "on", 10);
+ crm_debug("Unfence pcmk-1: %d", rc);
+
+ rc = st->cmds->remove_device(st, st_opts, "test-id");
+ crm_debug("Remove test-id: %d", rc);
+
+ stonith_key_value_freeall(params, 1, 1);
+}
int
main(int argc, char ** argv)
{
int argerr = 0;
int flag;
int option_index = 0;
int rc = 0;
- char *tmp = NULL;
- struct pollfd pollfd;
- stonith_t *st = NULL;
+ enum test_modes mode = test_standard;
- stonith_key_value_t *params = NULL;
- gboolean passive_mode = FALSE;
-
- crm_log_cli_init("stonith-test");
crm_set_options(NULL, "mode [options]", long_options,
"Provides a summary of cluster's current state."
"\n\nOutputs varying levels of detail in a number of different formats.\n");
- params = stonith_key_value_add(params, "pcmk_host_map", "some-host=pcmk-7 pcmk-3=3,4");
-
while (1) {
flag = crm_get_option(argc, argv, &option_index);
if (flag == -1) {
break;
}
switch(flag) {
case 'V':
- crm_bump_log_level();
+ verbose = 1;
break;
case '$':
case '?':
crm_help(flag, EX_OK);
break;
case 'p':
- passive_mode = TRUE;
+ mode = test_passive;
break;
- default:
+ case 't':
+ mode = test_api_sanity;
+ break;
+ default:
++argerr;
break;
}
}
+ crm_log_init("stonith-test", LOG_INFO, TRUE, verbose ? TRUE : FALSE, argc, argv, FALSE);
+
if (optind > argc) {
++argerr;
}
if (argerr) {
crm_help('?', EX_USAGE);
}
crm_debug("Create");
st = stonith_api_new();
rc = st->cmds->connect(st, crm_system_name, &pollfd.fd);
crm_debug("Connect: %d", rc);
- rc = st->cmds->register_notification(st, T_STONITH_NOTIFY_DISCONNECT, st_callback);
-
- if(passive_mode) {
- rc = st->cmds->register_notification(st, T_STONITH_NOTIFY_FENCE, st_callback);
- rc = st->cmds->register_notification(st, STONITH_OP_DEVICE_ADD, st_callback);
- rc = st->cmds->register_notification(st, STONITH_OP_DEVICE_DEL, st_callback);
-
- st->cmds->register_callback(st, 0, 120, FALSE, NULL, "st_global_callback", st_global_callback);
-
- crm_info("Looking for notification");
- pollfd.events = POLLIN;
- while(true) {
- rc = poll( &pollfd, 1, 600 * 1000 ); /* wait 10 minutes, -1 forever */
- if (rc > 0 )
- stonith_dispatch( st );
- else
- break;
- }
-
- } else {
- rc = st->cmds->register_device(st, st_opts, "test-id", "stonith-ng", "fence_xvm", params);
- crm_debug("Register: %d", rc);
-
- rc = st->cmds->list(st, st_opts, "test-id", &tmp, 10);
- crm_debug("List: %d output: %s\n", rc, tmp ? tmp : "<none>");
-
- rc = st->cmds->monitor(st, st_opts, "test-id", 10);
- crm_debug("Monitor: %d", rc);
-
- rc = st->cmds->status(st, st_opts, "test-id", "pcmk-2", 10);
- crm_debug("Status pcmk-2: %d", rc);
-
- rc = st->cmds->status(st, st_opts, "test-id", "pcmk-1", 10);
- crm_debug("Status pcmk-1: %d", rc);
-
- rc = st->cmds->fence(st, st_opts, "unknown-host", "off", 60);
- crm_debug("Fence unknown-host: %d", rc);
-
- rc = st->cmds->status(st, st_opts, "test-id", "pcmk-1", 10);
- crm_debug("Status pcmk-1: %d", rc);
-
- rc = st->cmds->fence(st, st_opts, "pcmk-1", "off", 60);
- crm_debug("Fence pcmk-1: %d", rc);
-
- rc = st->cmds->status(st, st_opts, "test-id", "pcmk-1", 10);
- crm_debug("Status pcmk-1: %d", rc);
-
- rc = st->cmds->fence(st, st_opts, "pcmk-1", "on", 10);
- crm_debug("Unfence pcmk-1: %d", rc);
-
- rc = st->cmds->status(st, st_opts, "test-id", "pcmk-1", 10);
- crm_debug("Status pcmk-1: %d", rc);
-
- rc = st->cmds->fence(st, st_opts, "some-host", "off", 10);
- crm_debug("Fence alias: %d", rc);
-
- rc = st->cmds->status(st, st_opts, "test-id", "some-host", 10);
- crm_debug("Status alias: %d", rc);
-
- rc = st->cmds->fence(st, st_opts, "pcmk-1", "on", 10);
- crm_debug("Unfence pcmk-1: %d", rc);
-
- rc = st->cmds->remove_device(st, st_opts, "test-id");
- crm_debug("Remove test-id: %d", rc);
+ switch (mode) {
+ case test_standard:
+ standard_dev_test();
+ break;
+ case test_passive:
+ passive_test();
+ break;
+ case test_api_sanity:
+ sanity_tests();
+ break;
}
- stonith_key_value_freeall(params, 1, 1);
-
rc = st->cmds->disconnect(st);
crm_debug("Disconnect: %d", rc);
crm_debug("Destroy");
stonith_api_delete(st);
return rc;
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 23, 7:24 AM (16 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1018400
Default Alt Text
(123 KB)

Event Timeline