Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/configure.ac b/configure.ac
index 7a92266639..26b65bf462 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,1740 +1,1740 @@
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_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 unsetenv: is some bsdish function that should also be avoided (No
dnl replacement)
dnl A replacement function is supplied for it.
dnl
dnl strnlen: is a gnu function similar to strlen, but safer.
dnl We wrote a tolearably-fast replacement function for it.
dnl
dnl strndup: is a gnu function similar to strdup, but safer.
dnl We wrote a tolearably-fast replacement function for it.
dnl
dnl daemon: is a GNU function. The daemon() function is for programs wishing to
dnl detach themselves from the controlling terminal and run in the
dnl background as system daemon
dnl A replacement function is supplied for it.
AC_REPLACE_FUNCS(alphasort inet_pton NoSuchFunctionName scandir setenv strerror strchrnul unsetenv strnlen strndup daemon)
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 libuuid
if test "x$ac_cv_lib_uuid_uuid_parse" != x""yes; 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)
USE_GHASH_COMPAT=0
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)
USE_GHASH_COMPAT=1
fi
AC_DEFINE_UNQUOTED(USE_GHASH_COMPAT, $USE_GHASH_COMPAT, Use g_hash_table compatibility functions)
AC_SUBST(USE_GHASH_COMPAT)
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(hb_config.h)
-AC_CHECK_HEADERS(glue_config.h)
+AC_CHECK_HEADERS(heartbeat/hb_config.h)
+AC_CHECK_HEADERS(heartbeat/glue_config.h)
AC_CHECK_HEADERS(agent_config.h)
GLUE_HEADER=none
HAVE_GLUE=0
-if test "$ac_cv_header_glue_config_h" = "yes"; then
+if test "$ac_cv_header_heartbeat_glue_config_h" = "yes"; then
PCMK_FEATURES="$PCMK_FEATURES lha-fencing"
GLUE_HEADER=glue_config.h
HAVE_GLUE=1
-elif test "$ac_cv_header_hb_config_h" = "yes"; then
+elif test "$ac_cv_header_heartbeat_hb_config_h" = "yes"; then
PCMK_FEATURES="$PCMK_FEATURES lha-fencing"
GLUE_HEADER=hb_config.h
HAVE_GLUE=1
else
AC_MSG_WARN(cluster-glue development headers were not found)
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)
LHA_STONITH_LIBS=-lstonith
AC_SUBST(LHA_STONITH_LIBS)
fi
AC_DEFINE_UNQUOTED(SUPPORT_LHA_STONITH, $HAVE_GLUE, Build support for the legacy Linux-HA stonith agents)
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)
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/common/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 \
lrmd/Makefile \
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/include/crm/cluster.h b/include/crm/cluster.h
index 54e8228e41..268c67c986 100644
--- a/include/crm/cluster.h
+++ b/include/crm/cluster.h
@@ -1,128 +1,129 @@
/*
* Copyright (C) 2004 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
*/
#ifndef CRM_COMMON_CLUSTER__H
# define CRM_COMMON_CLUSTER__H
# include <crm/common/xml.h>
# include <crm/common/util.h>
# include <crm/ais.h>
# if SUPPORT_HEARTBEAT
# include <heartbeat/hb_api.h>
# include <ocf/oc_event.h>
# endif
extern gboolean crm_have_quorum;
extern GHashTable *crm_peer_cache;
extern GHashTable *crm_peer_id_cache;
extern unsigned long long crm_peer_seq;
void crm_peer_init(void);
void crm_peer_destroy(void);
char *get_corosync_uuid(uint32_t id, const char *uname);
const char *get_node_uuid(uint32_t id, const char *uname);
int get_corosync_id(int id, const char *uuid);
gboolean crm_cluster_connect(char **our_uname, char **our_uuid, void *dispatch,
void *destroy,
# if SUPPORT_HEARTBEAT
ll_cluster_t ** hb_conn
# else
void **unused
# endif
);
gboolean init_cman_connection(gboolean(*dispatch) (unsigned long long, gboolean),
void (*destroy) (gpointer));
gboolean init_quorum_connection(gboolean(*dispatch) (unsigned long long, gboolean),
void (*destroy) (gpointer));
gboolean send_cluster_message(const char *node, enum crm_ais_msg_types service,
xmlNode * data, gboolean ordered);
void destroy_crm_node(gpointer data);
crm_node_t *crm_get_peer(unsigned int id, const char *uname);
void crm_update_peer_proc(const char *source, crm_node_t *peer, uint32_t flag, const char *status);
crm_node_t *crm_update_peer(const char *source, unsigned int id, uint64_t born, uint64_t seen, int32_t votes,
uint32_t children, const char *uuid, const char *uname,
const char *addr, const char *state);
guint crm_active_peers(void);
gboolean crm_is_peer_active(const crm_node_t * node);
guint reap_crm_member(uint32_t id);
int crm_terminate_member(int nodeid, const char *uname, void* unused);
int crm_terminate_member_no_mainloop(int nodeid, const char *uname, int *connection);
gboolean crm_get_cluster_name(char **cname);
# if SUPPORT_HEARTBEAT
+xmlNode *convert_ha_message(xmlNode * parent, HA_Message *msg, const char *field);
gboolean crm_is_heartbeat_peer_active(const crm_node_t * node);
gboolean ccm_have_quorum(oc_ed_t event);
const char *ccm_event_name(oc_ed_t event);
crm_node_t *crm_update_ccm_node(const oc_ev_membership_t * oc, int offset, const char *state,
uint64_t seq);
# endif
# if SUPPORT_COROSYNC
extern int ais_fd_sync;
gboolean crm_is_corosync_peer_active(const crm_node_t * node);
gboolean send_ais_text(int class, const char *data, gboolean local,
const char *node, enum crm_ais_msg_types dest);
gboolean get_ais_nodeid(uint32_t * id, char **uname);
# endif
void empty_uuid_cache(void);
const char *get_uuid(const char *uname);
const char *get_uname(const char *uuid);
void set_uuid(xmlNode * node, const char *attr, const char *uname);
void unget_uuid(const char *uname);
enum crm_status_type {
crm_status_uname,
crm_status_nstate,
crm_status_processes,
};
enum crm_ais_msg_types text2msg_type(const char *text);
void
crm_set_status_callback(void (*dispatch) (enum crm_status_type, crm_node_t *, const void *));
/* *INDENT-OFF* */
enum cluster_type_e
{
pcmk_cluster_unknown = 0x0001,
pcmk_cluster_invalid = 0x0002,
pcmk_cluster_heartbeat = 0x0004,
pcmk_cluster_classic_ais = 0x0010,
pcmk_cluster_corosync = 0x0020,
pcmk_cluster_cman = 0x0040,
};
/* *INDENT-ON* */
enum cluster_type_e get_cluster_type(void);
const char *name_for_cluster_type(enum cluster_type_e type);
gboolean is_corosync_cluster(void);
gboolean is_cman_cluster(void);
gboolean is_openais_cluster(void);
gboolean is_classic_ais_cluster(void);
gboolean is_heartbeat_cluster(void);
#endif
diff --git a/include/crm/common/xml.h b/include/crm/common/xml.h
index 005b4d6414..9ccc156729 100644
--- a/include/crm/common/xml.h
+++ b/include/crm/common/xml.h
@@ -1,340 +1,334 @@
/*
* Copyright (C) 2004 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
*/
#ifndef CRM_COMMON_XML__H
# define CRM_COMMON_XML__H
# include <stdio.h>
# include <sys/types.h>
# include <unistd.h>
# include <stdlib.h>
# include <errno.h>
# include <fcntl.h>
# include <crm/crm.h>
# include <libxml/tree.h>
# include <libxml/xpath.h>
typedef xmlNode crm_data_t;
/* Encryption costs a LOT, don't do it unless we're hitting message limits
*
* For now, use 256k as the lower size, which means we can have 4 big data fields
* before we hit heartbeat's message limit
*
* The previous limit was 10k, compressing 184 of 1071 messages accounted for 23%
* of the total CPU used by the cib
*/
# define CRM_BZ2_BLOCKS 4
# define CRM_BZ2_WORK 20
# define CRM_BZ2_THRESHOLD 128 * 1024
# define XML_PARANOIA_CHECKS 0
gboolean add_message_xml(xmlNode * msg, const char *field, xmlNode * xml);
xmlNode *get_message_xml(xmlNode * msg, const char *field);
GHashTable *xml2list(xmlNode * parent);
# if CRM_DEPRECATED_SINCE_2_0_3
GHashTable *xml2list_202(xmlNode * parent);
# endif
void hash2nvpair(gpointer key, gpointer value, gpointer user_data);
void hash2field(gpointer key, gpointer value, gpointer user_data);
void hash2metafield(gpointer key, gpointer value, gpointer user_data);
void hash2smartfield(gpointer key, gpointer value, gpointer user_data);
xmlDoc *getDocPtr(xmlNode * node);
/*
* Replacement function for xmlCopyPropList which at the very least,
* doesnt work the way *I* would expect it to.
*
* Copy all the attributes/properties from src into target.
*
* Not recursive, does not return anything.
*
*/
void copy_in_properties(xmlNode * target, xmlNode * src);
void expand_plus_plus(xmlNode * target, const char *name, const char *value);
void fix_plus_plus_recursive(xmlNode * target);
void free_xml_from_parent(xmlNode * parent, xmlNode * a_node);
# define zap_xml_from_parent(parent, xml_obj) free_xml_from_parent(parent, xml_obj); xml_obj = NULL
/*
* Create a node named "name" as a child of "parent"
* If parent is NULL, creates an unconnected node.
*
* Returns the created node
*
*/
xmlNode *create_xml_node(xmlNode * parent, const char *name);
/*
* Make a copy of name and value and use the copied memory to create
* an attribute for node.
*
* If node, name or value are NULL, nothing is done.
*
* If name or value are an empty string, nothing is done.
*
* Returns FALSE on failure and TRUE on success.
*
*/
const char *crm_xml_add(xmlNode * node, const char *name, const char *value);
const char *crm_xml_replace(xmlNode * node, const char *name, const char *value);
const char *crm_xml_add_int(xmlNode * node, const char *name, int value);
/*
* Unlink the node and set its doc pointer to NULL so free_xml()
* will act appropriately
*/
void unlink_xml_node(xmlNode * node);
/*
*
*/
void purge_diff_markers(xmlNode * a_node);
/*
* Returns a deep copy of src_node
*
*/
xmlNode *copy_xml(xmlNode * src_node);
/*
* Add a copy of xml_node to new_parent
*/
xmlNode *add_node_copy(xmlNode * new_parent, xmlNode * xml_node);
int add_node_nocopy(xmlNode * parent, const char *name, xmlNode * child);
/*
* XML I/O Functions
*
* Whitespace between tags is discarded.
*/
xmlNode *filename2xml(const char *filename);
xmlNode *stdin2xml(void);
xmlNode *string2xml(const char *input);
int write_xml_file(xmlNode * xml_node, const char *filename, gboolean compress);
char *dump_xml_formatted(xmlNode * msg);
char *dump_xml_unformatted(xmlNode * msg);
/*
* Diff related Functions
*/
xmlNode *diff_xml_object(xmlNode * left, xmlNode * right, gboolean suppress);
xmlNode *subtract_xml_object(xmlNode * parent, xmlNode * left, xmlNode * right,
gboolean full, const char *marker);
gboolean can_prune_leaf(xmlNode * xml_node);
void print_xml_diff(FILE * where, xmlNode * diff);
void log_xml_diff(unsigned int log_level, xmlNode * diff, const char *function);
gboolean apply_xml_diff(xmlNode * old, xmlNode * diff, xmlNode ** new);
/*
* Searching & Modifying
*/
xmlNode *find_xml_node(xmlNode * cib, const char *node_path, gboolean must_find);
xmlNode *find_entity(xmlNode * parent, const char *node_name, const char *id);
void xml_remove_prop(xmlNode * obj, const char *name);
gboolean replace_xml_child(xmlNode * parent, xmlNode * child, xmlNode * update,
gboolean delete_only);
gboolean update_xml_child(xmlNode * child, xmlNode * to_update);
int find_xml_children(xmlNode ** children, xmlNode * root,
const char *tag, const char *field, const char *value,
gboolean search_matches);
int crm_element_value_int(xmlNode * data, const char *name, int *dest);
char *crm_element_value_copy(xmlNode * data, const char *name);
int crm_element_value_const_int(const xmlNode * data, const char *name, int *dest);
const char *crm_element_value_const(const xmlNode * data, const char *name);
xmlNode *get_xpath_object(const char *xpath, xmlNode * xml_obj, int error_level);
xmlNode *get_xpath_object_relative(const char *xpath, xmlNode * xml_obj, int error_level);
# define crm_element_name(xml) (xml)?(const char *)(xml)->name:NULL
const char *crm_element_value(xmlNode * data, const char *name);
void xml_validate(const xmlNode * root);
gboolean xml_has_children(const xmlNode * root);
/* For ABI compatability with version < 1.1.4 */
char *calculate_xml_digest(xmlNode * local_cib, gboolean sort, gboolean do_filter);
char *calculate_on_disk_digest(xmlNode * local_cib);
char *calculate_operation_digest(xmlNode * local_cib, const char *version);
char *calculate_xml_versioned_digest(xmlNode * input, gboolean sort, gboolean do_filter,
const char *version);
gboolean validate_xml(xmlNode * xml_blob, const char *validation, gboolean to_logs);
gboolean validate_xml_verbose(xmlNode * xml_blob);
int update_validation(xmlNode ** xml_blob, int *best, gboolean transform, gboolean to_logs);
int get_schema_version(const char *name);
const char *get_schema_name(int version);
void crm_xml_cleanup(void);
# if XML_PARANOIA_CHECKS
# define crm_validate_data(obj) xml_validate(obj)
# else
# define crm_validate_data(obj) CRM_LOG_ASSERT(obj != NULL)
# endif
static inline xmlNode *
__xml_first_child(xmlNode * parent)
{
xmlNode *child = NULL;
if (parent) {
child = parent->children;
while (child && child->type != XML_ELEMENT_NODE) {
child = child->next;
}
}
return child;
}
static inline xmlNode *
__xml_next(xmlNode * child)
{
if (child) {
child = child->next;
while (child && child->type != XML_ELEMENT_NODE) {
child = child->next;
}
}
return child;
}
/* These two child iterator macros are no longer to be used
* They exist for compatability reasons and will be removed in a
* future release
*/
# define xml_child_iter(parent, child, code) do { \
if(parent != NULL) { \
xmlNode *child = NULL; \
xmlNode *__crm_xml_iter = parent->children; \
while(__crm_xml_iter != NULL) { \
child = __crm_xml_iter; \
__crm_xml_iter = __crm_xml_iter->next; \
if(child->type == XML_ELEMENT_NODE) { \
code; \
} \
} \
} \
} while(0)
# define xml_child_iter_filter(parent, child, filter, code) do { \
if(parent != NULL) { \
xmlNode *child = NULL; \
xmlNode *__crm_xml_iter = parent->children; \
while(__crm_xml_iter != NULL) { \
child = __crm_xml_iter; \
__crm_xml_iter = __crm_xml_iter->next; \
if(child->type == XML_ELEMENT_NODE) { \
if(filter == NULL \
|| crm_str_eq(filter, (const char *)child->name, TRUE)) { \
code; \
} \
} \
} \
} \
} while(0)
# define xml_prop_iter(parent, prop_name, prop_value, code) do { \
if(parent != NULL) { \
xmlAttrPtr prop_iter = parent->properties; \
const char *prop_name = NULL; \
const char *prop_value = NULL; \
while(prop_iter != NULL) { \
prop_name = (const char *)prop_iter->name; \
prop_value = crm_element_value(parent, prop_name); \
prop_iter = prop_iter->next; \
if(prop_name) { \
code; \
} \
} \
} \
} while(0)
# define xml_prop_name_iter(parent, prop_name, code) do { \
if(parent != NULL) { \
xmlAttrPtr prop_iter = parent->properties; \
const char *prop_name = NULL; \
while(prop_iter != NULL) { \
prop_name = (const char *)prop_iter->name; \
prop_iter = prop_iter->next; \
if(prop_name) { \
code; \
} \
} \
} \
} while(0)
# define free_xml(a_node) do { \
if((a_node) != NULL) { \
xmlNode *a_doc_top = NULL; \
xmlDoc *a_doc = (a_node)->doc; \
if (a_doc != NULL) { \
a_doc_top = xmlDocGetRootElement(a_doc); \
} \
if(a_doc != NULL && a_doc_top == (a_node)) { \
xmlFreeDoc(a_doc); \
\
} else { \
/* make sure the node is unlinked first */ \
xmlUnlinkNode(a_node); \
xmlFreeNode(a_node); \
} \
} \
} while(0)
xmlNode *first_named_child(xmlNode * parent, const char *name);
xmlNode *sorted_xml(xmlNode * input, xmlNode * parent, gboolean recursive);
xmlXPathObjectPtr xpath_search(xmlNode * xml_top, const char *path);
gboolean cli_config_update(xmlNode ** xml, int *best_version, gboolean to_logs);
xmlNode *expand_idref(xmlNode * input, xmlNode * top);
xmlNode *getXpathResult(xmlXPathObjectPtr xpathObj, int index);
-# if SUPPORT_HEARTBEAT
-# include <ha_msg.h>
-xmlNode *convert_ha_message(xmlNode * parent, HA_Message * msg, const char *field);
-HA_Message *convert_xml_message(xmlNode * msg);
-# endif
-
#endif
diff --git a/lib/cluster/cluster.c b/lib/cluster/cluster.c
index 719a625627..2bb7aed5d2 100644
--- a/lib/cluster/cluster.c
+++ b/lib/cluster/cluster.c
@@ -1,520 +1,518 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <crm_internal.h>
#include <dlfcn.h>
#include <sys/param.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <crm/crm.h>
#include <crm/msg_xml.h>
#include <crm/common/ipc.h>
#include <crm/cluster.h>
#include "stack.h"
CRM_TRACE_INIT_DATA(cluster);
#if SUPPORT_HEARTBEAT
void *hb_library = NULL;
#endif
static GHashTable *crm_uuid_cache = NULL;
static GHashTable *crm_uname_cache = NULL;
-xmlNode *create_common_message(xmlNode * original_request, xmlNode * xml_response_data);
-
static char *
get_heartbeat_uuid(uint32_t unused, const char *uname)
{
char *uuid_calc = NULL;
#if SUPPORT_HEARTBEAT
cl_uuid_t uuid_raw;
const char *unknown = "00000000-0000-0000-0000-000000000000";
if (heartbeat_cluster == NULL) {
crm_warn("No connection to heartbeat, using uuid=uname");
return NULL;
}
if (heartbeat_cluster->llc_ops->get_uuid_by_name(heartbeat_cluster, uname, &uuid_raw) ==
HA_FAIL) {
crm_err("get_uuid_by_name() call failed for host %s", uname);
free(uuid_calc);
return NULL;
}
uuid_calc = calloc(1, 50);
cl_uuid_unparse(&uuid_raw, uuid_calc);
if (safe_str_eq(uuid_calc, unknown)) {
crm_warn("Could not calculate UUID for %s", uname);
free(uuid_calc);
return NULL;
}
#endif
return uuid_calc;
}
static gboolean
uname_is_uuid(void)
{
static const char *uuid_pref = NULL;
if (uuid_pref == NULL) {
uuid_pref = getenv("PCMK_uname_is_uuid");
}
if (uuid_pref == NULL) {
/* true is legacy mode */
uuid_pref = "false";
}
return crm_is_true(uuid_pref);
}
int
get_corosync_id(int id, const char *uuid)
{
if (id == 0 && !uname_is_uuid() && is_corosync_cluster()) {
id = crm_atoi(uuid, "0");
}
return id;
}
char *
get_corosync_uuid(uint32_t id, const char *uname)
{
if (!uname_is_uuid() && is_corosync_cluster()) {
if (id <= 0) {
/* Try the membership cache... */
crm_node_t *node = g_hash_table_lookup(crm_peer_cache, uname);
if (node != NULL) {
id = node->id;
}
}
if (id > 0) {
return crm_itoa(id);
} else {
crm_warn("Node %s is not yet known by corosync", uname);
}
} else if (uname != NULL) {
return crm_strdup(uname);
}
return NULL;
}
const char *
get_node_uuid(uint32_t id, const char *uname)
{
char *uuid = NULL;
enum cluster_type_e type = get_cluster_type();
if (crm_uuid_cache == NULL) {
crm_uuid_cache = g_hash_table_new_full(crm_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
}
/* avoid blocking heartbeat calls where possible */
if (uname) {
uuid = g_hash_table_lookup(crm_uuid_cache, uname);
}
if (uuid != NULL) {
return uuid;
}
switch (type) {
case pcmk_cluster_corosync:
uuid = get_corosync_uuid(id, uname);
break;
case pcmk_cluster_cman:
case pcmk_cluster_classic_ais:
if (uname) {
uuid = crm_strdup(uname);
}
break;
case pcmk_cluster_heartbeat:
uuid = get_heartbeat_uuid(id, uname);
break;
case pcmk_cluster_unknown:
case pcmk_cluster_invalid:
crm_err("Unsupported cluster type");
break;
}
if (uuid == NULL) {
return NULL;
}
if (uname) {
g_hash_table_insert(crm_uuid_cache, crm_strdup(uname), uuid);
return g_hash_table_lookup(crm_uuid_cache, uname);
}
/* Memory leak! */
CRM_LOG_ASSERT(uuid != NULL);
return uuid;
}
gboolean
crm_cluster_connect(char **our_uname, char **our_uuid, void *dispatch, void *destroy,
#if SUPPORT_HEARTBEAT
ll_cluster_t ** hb_conn
#else
void **hb_conn
#endif
)
{
enum cluster_type_e type = get_cluster_type();
crm_notice("Connecting to cluster infrastructure: %s", name_for_cluster_type(type));
if (hb_conn != NULL) {
*hb_conn = NULL;
}
#if SUPPORT_COROSYNC
if (is_openais_cluster()) {
crm_peer_init();
return init_ais_connection(dispatch, destroy, our_uuid, our_uname, NULL);
}
#endif
#if SUPPORT_HEARTBEAT
if (is_heartbeat_cluster()) {
int rv;
CRM_ASSERT(hb_conn != NULL);
/* coverity[var_deref_op] False positive */
if (*hb_conn == NULL) {
/* No object passed in, create a new one. */
ll_cluster_t *(*new_cluster) (const char *llctype) =
find_library_function(&hb_library, HEARTBEAT_LIBRARY, "ll_cluster_new");
*hb_conn = (*new_cluster) ("heartbeat");
/* dlclose(handle); */
} else {
/* Object passed in. Disconnect first, then reconnect below. */
ll_cluster_t *conn = *hb_conn;
conn->llc_ops->signoff(conn, FALSE);
}
/* make sure we are disconnected first with the old object, if any. */
if (heartbeat_cluster && heartbeat_cluster != *hb_conn) {
heartbeat_cluster->llc_ops->signoff(heartbeat_cluster, FALSE);
}
CRM_ASSERT(*hb_conn != NULL);
heartbeat_cluster = *hb_conn;
rv = register_heartbeat_conn(heartbeat_cluster, our_uuid, our_uname, dispatch, destroy);
if (rv) {
/* we'll benefit from a bigger queue length on heartbeat side.
* Otherwise, if peers send messages faster than we can consume
* them right now, heartbeat messaging layer will kick us out once
* it's (small) default queue fills up :(
* If we fail to adjust the sendq length, that's not yet fatal, though.
*/
if (HA_OK != (*hb_conn)->llc_ops->set_sendq_len(*hb_conn, 1024)) {
crm_warn("Cannot set sendq length: %s", (*hb_conn)->llc_ops->errmsg(*hb_conn));
}
}
return rv;
}
#endif
crm_info("Unsupported cluster stack: %s", getenv("HA_cluster_type"));
return FALSE;
}
gboolean
send_cluster_message(const char *node, enum crm_ais_msg_types service, xmlNode * data,
gboolean ordered)
{
#if SUPPORT_COROSYNC
if (is_openais_cluster()) {
return send_ais_message(data, FALSE, node, service);
}
#endif
#if SUPPORT_HEARTBEAT
if (is_heartbeat_cluster()) {
return send_ha_message(heartbeat_cluster, data, node, ordered);
}
#endif
return FALSE;
}
void
empty_uuid_cache(void)
{
if (crm_uuid_cache != NULL) {
g_hash_table_destroy(crm_uuid_cache);
crm_uuid_cache = NULL;
}
}
void
unget_uuid(const char *uname)
{
if (crm_uuid_cache == NULL) {
return;
}
g_hash_table_remove(crm_uuid_cache, uname);
}
const char *
get_uuid(const char *uname)
{
return get_node_uuid(0, uname);
}
const char *
get_uname(const char *uuid)
{
const char *uname = NULL;
if (crm_uname_cache == NULL) {
crm_uname_cache = g_hash_table_new_full(crm_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
}
CRM_CHECK(uuid != NULL, return NULL);
/* avoid blocking calls where possible */
uname = g_hash_table_lookup(crm_uname_cache, uuid);
if (uname != NULL) {
crm_trace("%s = %s (cached)", uuid, uname);
return uname;
}
#if SUPPORT_COROSYNC
if (is_openais_cluster()) {
if (!uname_is_uuid() && is_corosync_cluster()) {
uint32_t id = crm_int_helper(uuid, NULL);
crm_node_t *node = g_hash_table_lookup(crm_peer_id_cache, GUINT_TO_POINTER(id));
uname = node ? node->uname : NULL;
} else {
uname = uuid;
}
if (uname) {
crm_trace("Storing %s = %s", uuid, uname);
g_hash_table_insert(crm_uname_cache, crm_strdup(uuid), crm_strdup(uname));
}
}
#endif
#if SUPPORT_HEARTBEAT
if (is_heartbeat_cluster()) {
if (heartbeat_cluster != NULL && uuid != NULL) {
cl_uuid_t uuid_raw;
char *hb_uname = NULL;
char *uuid_copy = crm_strdup(uuid);
cl_uuid_parse(uuid_copy, &uuid_raw);
hb_uname = malloc( MAX_NAME);
if (heartbeat_cluster->llc_ops->get_name_by_uuid(heartbeat_cluster, &uuid_raw, hb_uname,
MAX_NAME) == HA_FAIL) {
crm_err("Could not calculate uname for %s", uuid);
free(uuid_copy);
free(hb_uname);
} else {
crm_trace("Storing %s = %s", uuid, uname);
g_hash_table_insert(crm_uname_cache, uuid_copy, hb_uname);
}
}
}
#endif
return g_hash_table_lookup(crm_uname_cache, uuid);
}
void
set_uuid(xmlNode * node, const char *attr, const char *uname)
{
const char *uuid_calc = get_uuid(uname);
crm_xml_add(node, attr, uuid_calc);
return;
}
const char *
name_for_cluster_type(enum cluster_type_e type)
{
switch (type) {
case pcmk_cluster_classic_ais:
return "classic openais (with plugin)";
case pcmk_cluster_cman:
return "cman";
case pcmk_cluster_corosync:
return "corosync";
case pcmk_cluster_heartbeat:
return "heartbeat";
case pcmk_cluster_unknown:
return "unknown";
case pcmk_cluster_invalid:
return "invalid";
}
crm_err("Invalid cluster type: %d", type);
return "invalid";
}
/* Do not expose these two */
int set_cluster_type(enum cluster_type_e type);
static enum cluster_type_e cluster_type = pcmk_cluster_unknown;
int
set_cluster_type(enum cluster_type_e type)
{
if (cluster_type == pcmk_cluster_unknown) {
crm_info("Cluster type set to: %s", name_for_cluster_type(type));
cluster_type = type;
return 0;
} else if (cluster_type == type) {
return 0;
} else if (pcmk_cluster_unknown == type) {
cluster_type = type;
return 0;
}
crm_err("Cluster type already set to %s, ignoring %s",
name_for_cluster_type(cluster_type), name_for_cluster_type(type));
return -1;
}
enum cluster_type_e
get_cluster_type(void)
{
if (cluster_type == pcmk_cluster_unknown) {
const char *cluster = getenv("HA_cluster_type");
cluster_type = pcmk_cluster_invalid;
if (cluster) {
crm_info("Cluster type is: '%s'", cluster);
} else {
#if SUPPORT_COROSYNC
cluster_type = find_corosync_variant();
if (cluster_type == pcmk_cluster_unknown) {
cluster = "heartbeat";
crm_info("Assuming a 'heartbeat' based cluster");
} else {
cluster = name_for_cluster_type(cluster_type);
crm_info("Detected an active '%s' cluster", cluster);
}
#else
cluster = "heartbeat";
#endif
}
if (safe_str_eq(cluster, "heartbeat")) {
#if SUPPORT_HEARTBEAT
cluster_type = pcmk_cluster_heartbeat;
#else
cluster_type = pcmk_cluster_invalid;
#endif
} else if (safe_str_eq(cluster, "openais")
|| safe_str_eq(cluster, "classic openais (with plugin)")) {
#if SUPPORT_COROSYNC
cluster_type = pcmk_cluster_classic_ais;
#else
cluster_type = pcmk_cluster_invalid;
#endif
} else if (safe_str_eq(cluster, "corosync")) {
#if SUPPORT_COROSYNC
cluster_type = pcmk_cluster_corosync;
#else
cluster_type = pcmk_cluster_invalid;
#endif
} else if (safe_str_eq(cluster, "cman")) {
#if SUPPORT_CMAN
cluster_type = pcmk_cluster_cman;
#else
cluster_type = pcmk_cluster_invalid;
#endif
} else {
cluster_type = pcmk_cluster_invalid;
}
if (cluster_type == pcmk_cluster_invalid) {
crm_notice
("This installation of Pacemaker does not support the '%s' cluster infrastructure. Terminating.",
cluster);
exit(100);
}
}
return cluster_type;
}
gboolean
is_cman_cluster(void)
{
return get_cluster_type() == pcmk_cluster_cman;
}
gboolean
is_corosync_cluster(void)
{
return get_cluster_type() == pcmk_cluster_corosync;
}
gboolean
is_classic_ais_cluster(void)
{
return get_cluster_type() == pcmk_cluster_classic_ais;
}
gboolean
is_openais_cluster(void)
{
enum cluster_type_e type = get_cluster_type();
if (type == pcmk_cluster_classic_ais) {
return TRUE;
} else if (type == pcmk_cluster_corosync) {
return TRUE;
} else if (type == pcmk_cluster_cman) {
return TRUE;
}
return FALSE;
}
gboolean
is_heartbeat_cluster(void)
{
return get_cluster_type() == pcmk_cluster_heartbeat;
}
diff --git a/lib/cluster/heartbeat.c b/lib/cluster/heartbeat.c
index 18e905406c..8cc289aed5 100644
--- a/lib/cluster/heartbeat.c
+++ b/lib/cluster/heartbeat.c
@@ -1,274 +1,558 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <crm_internal.h>
#include <dlfcn.h>
#include <sys/param.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <crm/crm.h>
#include <crm/msg_xml.h>
#include <crm/common/ipc.h>
#include <crm/cluster.h>
#include "stack.h"
-xmlNode *create_common_message(xmlNode * original_request, xmlNode * xml_response_data);
-
+#if HAVE_BZLIB_H
+# include <bzlib.h>
+#endif
#if SUPPORT_HEARTBEAT
ll_cluster_t *heartbeat_cluster = NULL;
+static void
+convert_ha_field(xmlNode *parent, void *msg_v, int lpc)
+{
+ int type = 0;
+ const char *name = NULL;
+ const char *value = NULL;
+ xmlNode *xml = NULL;
+ HA_Message *msg = msg_v;
+
+ int rc = BZ_OK;
+ size_t orig_len = 0;
+ unsigned int used = 0;
+ char *uncompressed = NULL;
+ char *compressed = NULL;
+ int size = orig_len * 10;
+
+ CRM_CHECK(parent != NULL, return);
+ CRM_CHECK(msg != NULL, return);
+
+ name = msg->names[lpc];
+ type = cl_get_type(msg, name);
+
+ switch(type) {
+ case FT_STRUCT:
+ convert_ha_message(parent, msg->values[lpc], name);
+ break;
+ case FT_COMPRESS:
+ case FT_UNCOMPRESS:
+ convert_ha_message(parent, cl_get_struct(msg, name), name);
+ break;
+ case FT_STRING:
+ value = msg->values[lpc];
+ CRM_CHECK(value != NULL, return);
+ crm_trace("Converting %s/%d/%s", name, type, value[0] == '<' ? "xml":"field");
+
+ if( value[0] != '<' ) {
+ crm_xml_add(parent, name, value);
+ break;
+ }
+
+ /* unpack xml string */
+ xml = string2xml(value);
+ if(xml == NULL) {
+ crm_err("Conversion of field '%s' failed", name);
+ return;
+ }
+
+ add_node_nocopy(parent, NULL, xml);
+ break;
+
+ case FT_BINARY:
+ value = cl_get_binary(msg, name, &orig_len);
+ size = orig_len * 10 + 1; /* +1 because an exact 10x compression factor happens occasionally */
+
+ if(orig_len < 3
+ || value[0] != 'B'
+ || value[1] != 'Z'
+ || value[2] != 'h') {
+ if(strstr(name, "uuid") == NULL) {
+ crm_err("Skipping non-bzip binary field: %s", name);
+ }
+ return;
+ }
+
+ compressed = calloc(1, orig_len);
+ memcpy(compressed, value, orig_len);
+
+ crm_trace("Trying to decompress %d bytes", (int)orig_len);
+ retry:
+ crm_realloc(uncompressed, size);
+ memset(uncompressed, 0, size);
+ used = size - 1; /* always leave room for a trailing '\0'
+ * BZ2_bzBuffToBuffDecompress wont say anything if
+ * the uncompressed data is exactly 'size' bytes
+ */
+
+ rc = BZ2_bzBuffToBuffDecompress(
+ uncompressed, &used, compressed, orig_len, 1, 0);
+
+ if(rc == BZ_OUTBUFF_FULL) {
+ size = size * 2;
+ /* dont try to allocate more memory than we have */
+ if(size > 0) {
+ goto retry;
+ }
+ }
+
+ if(rc != BZ_OK) {
+ crm_err("Decompression of %s (%d bytes) into %d failed: %d",
+ name, (int)orig_len, size, rc);
+
+ } else if(used >= size) {
+ CRM_ASSERT(used < size);
+
+ } else {
+ CRM_LOG_ASSERT(uncompressed[used] == 0);
+ uncompressed[used] = 0;
+ xml = string2xml(uncompressed);
+ }
+
+ if(xml != NULL) {
+ add_node_copy(parent, xml);
+ free_xml(xml);
+ }
+
+ free(uncompressed);
+ free(compressed);
+ break;
+ }
+}
+
+xmlNode *
+convert_ha_message(xmlNode *parent, HA_Message *msg, const char *field)
+{
+ int lpc = 0;
+ xmlNode *child = NULL;
+ const char *tag = NULL;
+
+ CRM_CHECK(msg != NULL, crm_err("Empty message for %s", field); return parent);
+
+ tag = cl_get_string(msg, F_XML_TAGNAME);
+ if(tag == NULL) {
+ tag = field;
+
+ } else if(parent && safe_str_neq(field, tag)) {
+ /* For compatability with 0.6.x */
+ crm_debug("Creating intermediate parent %s between %s and %s", field, crm_element_name(parent), tag);
+ parent = create_xml_node(parent, field);
+ }
+
+ if(parent == NULL) {
+ parent = create_xml_node(NULL, tag);
+ child = parent;
+
+ } else {
+ child = create_xml_node(parent, tag);
+ }
+
+ for (lpc = 0; lpc < msg->nfields; lpc++) {
+ convert_ha_field(child, msg, lpc);
+ }
+
+ return parent;
+}
+
+static void add_ha_nocopy(HA_Message *parent, HA_Message *child, const char *field)
+{
+ int next = parent->nfields;
+ if (parent->nfields >= parent->nalloc && ha_msg_expand(parent) != HA_OK ) {
+ crm_err("Parent expansion failed");
+ return;
+ }
+
+ parent->names[next] = crm_strdup(field);
+ parent->nlens[next] = strlen(field);
+ parent->values[next] = child;
+ parent->vlens[next] = sizeof(HA_Message);
+ parent->types[next] = FT_UNCOMPRESS;
+ parent->nfields++;
+}
+
+static HA_Message*
+convert_xml_message_struct(HA_Message *parent, xmlNode *src_node, const char *field)
+{
+ xmlNode *child = NULL;
+ xmlNode *__crm_xml_iter = src_node->children;
+ xmlAttrPtr prop_iter = src_node->properties;
+ const char *name = NULL;
+ const char *value = NULL;
+
+ HA_Message *result = ha_msg_new(3);
+ ha_msg_add(result, F_XML_TAGNAME, (const char *)src_node->name);
+
+ while(prop_iter != NULL) {
+ name = (const char *)prop_iter->name;
+ value = (const char *)xmlGetProp(src_node, prop_iter->name);
+ prop_iter = prop_iter->next;
+ ha_msg_add(result, name, value);
+ }
+
+ while(__crm_xml_iter != NULL) {
+ child = __crm_xml_iter;
+ __crm_xml_iter = __crm_xml_iter->next;
+ convert_xml_message_struct(result, child, NULL);
+ }
+
+ if(parent == NULL) {
+ return result;
+ }
+
+ if(field) {
+ HA_Message *holder = ha_msg_new(3);
+ CRM_ASSERT(holder != NULL);
+
+ ha_msg_add(holder, F_XML_TAGNAME, field);
+ add_ha_nocopy(holder, result, (const char*)src_node->name);
+
+ ha_msg_addstruct_compress(parent, field, holder);
+ ha_msg_del(holder);
+
+ } else {
+ add_ha_nocopy(parent, result, (const char*)src_node->name);
+ }
+ return result;
+}
+
+static void
+convert_xml_child(HA_Message *msg, xmlNode *xml)
+{
+ int orig = 0;
+ int rc = BZ_OK;
+ unsigned int len = 0;
+
+ char *buffer = NULL;
+ char *compressed = NULL;
+ const char *name = NULL;
+
+ name = (const char *)xml->name;
+ buffer = dump_xml_unformatted(xml);
+ orig = strlen(buffer);
+ if(orig < CRM_BZ2_THRESHOLD) {
+ ha_msg_add(msg, name, buffer);
+ goto done;
+ }
+
+ len = (orig * 1.1) + 600; /* recomended size */
+
+ compressed = malloc( len);
+ rc = BZ2_bzBuffToBuffCompress(compressed, &len, buffer, orig, CRM_BZ2_BLOCKS, 0, CRM_BZ2_WORK);
+
+ if(rc != BZ_OK) {
+ crm_err("Compression failed: %d", rc);
+ free(compressed);
+ convert_xml_message_struct(msg, xml, name);
+ goto done;
+ }
+
+ free(buffer);
+ buffer = compressed;
+ crm_trace("Compression details: %d -> %d", orig, len);
+ ha_msg_addbin(msg, name, buffer, len);
+ done:
+ free(buffer);
+
+
+# if 0
+ {
+ unsigned int used = orig;
+ char *uncompressed = NULL;
+
+ crm_debug("Trying to decompress %d bytes", len);
+ uncompressed = calloc(1, orig);
+ rc = BZ2_bzBuffToBuffDecompress(
+ uncompressed, &used, compressed, len, 1, 0);
+ CRM_CHECK(rc == BZ_OK, ;);
+ CRM_CHECK(used == orig, ;);
+ crm_debug("rc=%d, used=%d", rc, used);
+ if(rc != BZ_OK) {
+ exit(100);
+ }
+ crm_debug("Original %s, decompressed %s", buffer, uncompressed);
+ free(uncompressed);
+ }
+# endif
+}
+
+static HA_Message*
+convert_xml_message(xmlNode *xml)
+{
+ xmlNode *child = NULL;
+ HA_Message *result = NULL;
+
+ result = ha_msg_new(3);
+ ha_msg_add(result, F_XML_TAGNAME, (const char *)xml->name);
+
+ xml_prop_iter(xml, name, value, ha_msg_add(result, name, value));
+ for(child = __xml_first_child(xml); child != NULL; child = __xml_next(child)) {
+ convert_xml_child(result, child);
+ }
+
+ return result;
+}
+
gboolean
crm_is_heartbeat_peer_active(const crm_node_t * node)
{
enum crm_proc_flag proc = text2proc(crm_system_name);
if (node == NULL) {
crm_trace("NULL");
return FALSE;
} else if(safe_str_neq(node->state, CRM_NODE_MEMBER)) {
crm_trace("%s: state=%s", node->uname, node->state);
return FALSE;
} else if((node->processes & crm_proc_heartbeat) == 0) {
crm_trace("%s: processes=%.16x", node->uname, node->processes);
return FALSE;
} else if(proc == crm_proc_none) {
return TRUE;
} else if((node->processes & proc) == 0) {
crm_trace("%s: proc %.16x not in %.16x", node->uname, proc, node->processes);
return FALSE;
}
return TRUE;
}
crm_node_t *
crm_update_ccm_node(const oc_ev_membership_t * oc, int offset, const char *state, uint64_t seq)
{
crm_node_t *peer = NULL;
const char *uuid = NULL;
CRM_CHECK(oc->m_array[offset].node_uname != NULL, return NULL);
uuid = get_uuid(oc->m_array[offset].node_uname);
peer = crm_update_peer(__FUNCTION__, oc->m_array[offset].node_id,
oc->m_array[offset].node_born_on, seq, -1, 0,
uuid, oc->m_array[offset].node_uname, NULL, state);
if (safe_str_eq(CRM_NODE_ACTIVE, state)) {
/* Heartbeat doesn't send status notifications for nodes that were already part of the cluster */
crm_update_peer_proc(__FUNCTION__, peer, crm_proc_heartbeat, ONLINESTATUS);
/* Nor does it send status notifications for processes that were already active */
crm_update_peer_proc(__FUNCTION__, peer, crm_proc_crmd, ONLINESTATUS);
}
return peer;
}
gboolean
send_ha_message(ll_cluster_t * hb_conn, xmlNode * xml, const char *node, gboolean force_ordered)
{
gboolean all_is_good = TRUE;
HA_Message *msg = convert_xml_message(xml);
if (msg == NULL) {
crm_err("cant send NULL message");
all_is_good = FALSE;
} else if (hb_conn == NULL) {
crm_err("No heartbeat connection specified");
all_is_good = FALSE;
} else if (hb_conn->llc_ops->chan_is_connected(hb_conn) == FALSE) {
crm_err("Not connected to Heartbeat");
all_is_good = FALSE;
} else if (node != NULL) {
if (hb_conn->llc_ops->send_ordered_nodemsg(hb_conn, msg, node) != HA_OK) {
all_is_good = FALSE;
crm_err("Send failed");
}
} else if (force_ordered) {
if (hb_conn->llc_ops->send_ordered_clustermsg(hb_conn, msg) != HA_OK) {
all_is_good = FALSE;
crm_err("Broadcast Send failed");
}
} else {
if (hb_conn->llc_ops->sendclustermsg(hb_conn, msg) != HA_OK) {
all_is_good = FALSE;
crm_err("Broadcast Send failed");
}
}
if (all_is_good == FALSE && hb_conn != NULL) {
IPC_Channel *ipc = NULL;
IPC_Queue *send_q = NULL;
if (hb_conn->llc_ops->chan_is_connected(hb_conn) != HA_OK) {
ipc = hb_conn->llc_ops->ipcchan(hb_conn);
}
if (ipc != NULL) {
/* ipc->ops->resume_io(ipc); */
send_q = ipc->send_queue;
}
if (send_q != NULL) {
CRM_CHECK(send_q->current_qlen < send_q->max_qlen,;);
}
}
if (all_is_good) {
crm_log_xml_trace(xml, "outbound");
} else {
crm_log_xml_warn(xml, "outbound");
}
if(msg != NULL) {
ha_msg_del(msg);
}
return all_is_good;
}
gboolean
ha_msg_dispatch(ll_cluster_t * cluster_conn, gpointer user_data)
{
IPC_Channel *channel = NULL;
crm_trace("Invoked");
if (cluster_conn != NULL) {
channel = cluster_conn->llc_ops->ipcchan(cluster_conn);
}
CRM_CHECK(cluster_conn != NULL, return FALSE);
CRM_CHECK(channel != NULL, return FALSE);
if (channel != NULL && IPC_ISRCONN(channel)) {
if (cluster_conn->llc_ops->msgready(cluster_conn) == 0) {
crm_trace("no message ready yet");
}
/* invoke the callbacks but dont block */
cluster_conn->llc_ops->rcvmsg(cluster_conn, 0);
}
if (channel == NULL || channel->ch_status != IPC_CONNECT) {
crm_info("Lost connection to heartbeat service.");
return FALSE;
}
return TRUE;
}
gboolean
register_heartbeat_conn(ll_cluster_t * hb_cluster, char **uuid, char **uname,
void (*hb_message) (HA_Message * msg, void *private_data),
void (*hb_destroy) (gpointer user_data))
{
const char *const_uuid = NULL;
const char *const_uname = NULL;
crm_debug("Signing in with Heartbeat");
if (hb_cluster->llc_ops->signon(hb_cluster, crm_system_name) != HA_OK) {
crm_err("Cannot sign on with heartbeat: %s", hb_cluster->llc_ops->errmsg(hb_cluster));
return FALSE;
}
if (HA_OK !=
hb_cluster->llc_ops->set_msg_callback(hb_cluster, crm_system_name, hb_message,
hb_cluster)) {
crm_err("Cannot set msg callback: %s", hb_cluster->llc_ops->errmsg(hb_cluster));
return FALSE;
}
{
void *handle = NULL;
GLLclusterSource *(*g_main_add_cluster) (int priority, ll_cluster_t * api,
gboolean can_recurse,
gboolean(*dispatch) (ll_cluster_t * source_data,
gpointer user_data),
gpointer userdata, GDestroyNotify notify) =
find_library_function(&handle, HEARTBEAT_LIBRARY, "G_main_add_ll_cluster");
(*g_main_add_cluster) (G_PRIORITY_HIGH, hb_cluster,
FALSE, ha_msg_dispatch, hb_cluster, hb_destroy);
dlclose(handle);
}
const_uname = hb_cluster->llc_ops->get_mynodeid(hb_cluster);
CRM_CHECK(const_uname != NULL, return FALSE);
const_uuid = get_uuid(const_uname);
CRM_CHECK(const_uuid != NULL, return FALSE);
crm_info("Hostname: %s", const_uname);
crm_info("UUID: %s", const_uuid);
if (uname) {
*uname = crm_strdup(const_uname);
}
if (uuid) {
*uuid = crm_strdup(const_uuid);
}
return TRUE;
}
gboolean
ccm_have_quorum(oc_ed_t event)
{
if (event == OC_EV_MS_NEW_MEMBERSHIP || event == OC_EV_MS_PRIMARY_RESTORED) {
return TRUE;
}
return FALSE;
}
const char *
ccm_event_name(oc_ed_t event)
{
if (event == OC_EV_MS_NEW_MEMBERSHIP) {
return "NEW MEMBERSHIP";
} else if (event == OC_EV_MS_NOT_PRIMARY) {
return "NOT PRIMARY";
} else if (event == OC_EV_MS_PRIMARY_RESTORED) {
return "PRIMARY RESTORED";
} else if (event == OC_EV_MS_EVICTED) {
return "EVICTED";
} else if (event == OC_EV_MS_INVALID) {
return "INVALID";
}
return "NO QUORUM MEMBERSHIP";
}
#endif
diff --git a/lib/common/Makefile.am b/lib/common/Makefile.am
index 599e08db20..bb5db897a0 100644
--- a/lib/common/Makefile.am
+++ b/lib/common/Makefile.am
@@ -1,50 +1,46 @@
#
# Copyright (C) 2004 Andrew Beekhof
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_builddir)/libltdl -I$(top_srcdir)/libltdl \
-I$(top_builddir)/lib/gnu -I$(top_srcdir)/lib/gnu
## libraries
lib_LTLIBRARIES = libcrmcommon.la
# Can't use -Wcast-qual here because glib insists on pretending things are const
# when they're not and thus we need the crm_element_value_const() hack
# s390 needs -fPIC
# s390-suse-linux/bin/ld: .libs/ipc.o: relocation R_390_PC32DBL against `__stack_chk_fail@@GLIBC_2.4' can not be used when making a shared object; recompile with -fPIC
CFLAGS = $(CFLAGS_COPY:-Wcast-qual=) -fPIC
libcrmcommon_la_SOURCES = ipc.c utils.c xml.c iso8601.c iso8601_fields.c remote.c mainloop.c logging.c
libcrmcommon_la_LDFLAGS = -version-info 3:0:0
libcrmcommon_la_LIBADD = -ldl $(GNUTLSLIBS)
libcrmcommon_la_SOURCES += $(top_builddir)/lib/gnu/md5.c
-if BUILD_HEARTBEAT_SUPPORT
-libcrmcommon_la_SOURCES += heartbeat.c
-endif
-
clean-generic:
rm -f *.log *.debug *.xml *~
install-exec-local:
uninstall-local:
diff --git a/lib/common/heartbeat.c b/lib/common/heartbeat.c
deleted file mode 100644
index d009f36764..0000000000
--- a/lib/common/heartbeat.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <crm_internal.h>
-
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
-#include <crm/crm.h>
-#include <crm/common/xml.h>
-
-#include <ha_msg.h>
-#if HAVE_BZLIB_H
-# include <bzlib.h>
-#endif
-
-static void add_ha_nocopy(HA_Message *parent, HA_Message *child, const char *field)
-{
- int next = parent->nfields;
- if (parent->nfields >= parent->nalloc && ha_msg_expand(parent) != HA_OK ) {
- crm_err("Parent expansion failed");
- return;
- }
-
- parent->names[next] = crm_strdup(field);
- parent->nlens[next] = strlen(field);
- parent->values[next] = child;
- parent->vlens[next] = sizeof(HA_Message);
- parent->types[next] = FT_UNCOMPRESS;
- parent->nfields++;
-}
-
-static HA_Message*
-convert_xml_message_struct(HA_Message *parent, xmlNode *src_node, const char *field)
-{
- xmlNode *child = NULL;
- xmlNode *__crm_xml_iter = src_node->children;
- xmlAttrPtr prop_iter = src_node->properties;
- const char *name = NULL;
- const char *value = NULL;
-
- HA_Message *result = ha_msg_new(3);
- ha_msg_add(result, F_XML_TAGNAME, (const char *)src_node->name);
-
- while(prop_iter != NULL) {
- name = (const char *)prop_iter->name;
- value = (const char *)xmlGetProp(src_node, prop_iter->name);
- prop_iter = prop_iter->next;
- ha_msg_add(result, name, value);
- }
-
- while(__crm_xml_iter != NULL) {
- child = __crm_xml_iter;
- __crm_xml_iter = __crm_xml_iter->next;
- convert_xml_message_struct(result, child, NULL);
- }
-
- if(parent == NULL) {
- return result;
- }
-
- if(field) {
- HA_Message *holder = ha_msg_new(3);
- CRM_ASSERT(holder != NULL);
-
- ha_msg_add(holder, F_XML_TAGNAME, field);
- add_ha_nocopy(holder, result, (const char*)src_node->name);
-
- ha_msg_addstruct_compress(parent, field, holder);
- ha_msg_del(holder);
-
- } else {
- add_ha_nocopy(parent, result, (const char*)src_node->name);
- }
- return result;
-}
-
-static void
-convert_xml_child(HA_Message *msg, xmlNode *xml)
-{
- int orig = 0;
- int rc = BZ_OK;
- unsigned int len = 0;
-
- char *buffer = NULL;
- char *compressed = NULL;
- const char *name = NULL;
-
- name = (const char *)xml->name;
- buffer = dump_xml_unformatted(xml);
- orig = strlen(buffer);
- if(orig < CRM_BZ2_THRESHOLD) {
- ha_msg_add(msg, name, buffer);
- goto done;
- }
-
- len = (orig * 1.1) + 600; /* recomended size */
-
- compressed = malloc( len);
- rc = BZ2_bzBuffToBuffCompress(compressed, &len, buffer, orig, CRM_BZ2_BLOCKS, 0, CRM_BZ2_WORK);
-
- if(rc != BZ_OK) {
- crm_err("Compression failed: %d", rc);
- free(compressed);
- convert_xml_message_struct(msg, xml, name);
- goto done;
- }
-
- free(buffer);
- buffer = compressed;
- crm_trace("Compression details: %d -> %d", orig, len);
- ha_msg_addbin(msg, name, buffer, len);
- done:
- free(buffer);
-
-
-# if 0
- {
- unsigned int used = orig;
- char *uncompressed = NULL;
-
- crm_debug("Trying to decompress %d bytes", len);
- uncompressed = calloc(1, orig);
- rc = BZ2_bzBuffToBuffDecompress(
- uncompressed, &used, compressed, len, 1, 0);
- CRM_CHECK(rc == BZ_OK, ;);
- CRM_CHECK(used == orig, ;);
- crm_debug("rc=%d, used=%d", rc, used);
- if(rc != BZ_OK) {
- exit(100);
- }
- crm_debug("Original %s, decompressed %s", buffer, uncompressed);
- free(uncompressed);
- }
-# endif
-}
-
-HA_Message*
-convert_xml_message(xmlNode *xml)
-{
- xmlNode *child = NULL;
- HA_Message *result = NULL;
-
- result = ha_msg_new(3);
- ha_msg_add(result, F_XML_TAGNAME, (const char *)xml->name);
-
- xml_prop_iter(xml, name, value, ha_msg_add(result, name, value));
- for(child = __xml_first_child(xml); child != NULL; child = __xml_next(child)) {
- convert_xml_child(result, child);
- }
-
- return result;
-}
-
-static void
-convert_ha_field(xmlNode *parent, HA_Message *msg, int lpc)
-{
- int type = 0;
- const char *name = NULL;
- const char *value = NULL;
- xmlNode *xml = NULL;
-
- int rc = BZ_OK;
- size_t orig_len = 0;
- unsigned int used = 0;
- char *uncompressed = NULL;
- char *compressed = NULL;
- int size = orig_len * 10;
-
- CRM_CHECK(parent != NULL, return);
- CRM_CHECK(msg != NULL, return);
-
- name = msg->names[lpc];
- type = cl_get_type(msg, name);
-
- switch(type) {
- case FT_STRUCT:
- convert_ha_message(parent, msg->values[lpc], name);
- break;
- case FT_COMPRESS:
- case FT_UNCOMPRESS:
- convert_ha_message(parent, cl_get_struct(msg, name), name);
- break;
- case FT_STRING:
- value = msg->values[lpc];
- CRM_CHECK(value != NULL, return);
- crm_trace("Converting %s/%d/%s", name, type, value[0] == '<' ? "xml":"field");
-
- if( value[0] != '<' ) {
- crm_xml_add(parent, name, value);
- break;
- }
-
- /* unpack xml string */
- xml = string2xml(value);
- if(xml == NULL) {
- crm_err("Conversion of field '%s' failed", name);
- return;
- }
-
- add_node_nocopy(parent, NULL, xml);
- break;
-
- case FT_BINARY:
- value = cl_get_binary(msg, name, &orig_len);
- size = orig_len * 10 + 1; /* +1 because an exact 10x compression factor happens occasionally */
-
- if(orig_len < 3
- || value[0] != 'B'
- || value[1] != 'Z'
- || value[2] != 'h') {
- if(strstr(name, "uuid") == NULL) {
- crm_err("Skipping non-bzip binary field: %s", name);
- }
- return;
- }
-
- compressed = calloc(1, orig_len);
- memcpy(compressed, value, orig_len);
-
- crm_trace("Trying to decompress %d bytes", (int)orig_len);
- retry:
- crm_realloc(uncompressed, size);
- memset(uncompressed, 0, size);
- used = size - 1; /* always leave room for a trailing '\0'
- * BZ2_bzBuffToBuffDecompress wont say anything if
- * the uncompressed data is exactly 'size' bytes
- */
-
- rc = BZ2_bzBuffToBuffDecompress(
- uncompressed, &used, compressed, orig_len, 1, 0);
-
- if(rc == BZ_OUTBUFF_FULL) {
- size = size * 2;
- /* dont try to allocate more memory than we have */
- if(size > 0) {
- goto retry;
- }
- }
-
- if(rc != BZ_OK) {
- crm_err("Decompression of %s (%d bytes) into %d failed: %d",
- name, (int)orig_len, size, rc);
-
- } else if(used >= size) {
- CRM_ASSERT(used < size);
-
- } else {
- CRM_LOG_ASSERT(uncompressed[used] == 0);
- uncompressed[used] = 0;
- xml = string2xml(uncompressed);
- }
-
- if(xml != NULL) {
- add_node_copy(parent, xml);
- free_xml(xml);
- }
-
- free(uncompressed);
- free(compressed);
- break;
- }
-}
-
-xmlNode *
-convert_ha_message(xmlNode *parent, HA_Message *msg, const char *field)
-{
- int lpc = 0;
- xmlNode *child = NULL;
- const char *tag = NULL;
-
- CRM_CHECK(msg != NULL, crm_err("Empty message for %s", field); return parent);
-
- tag = cl_get_string(msg, F_XML_TAGNAME);
- if(tag == NULL) {
- tag = field;
-
- } else if(parent && safe_str_neq(field, tag)) {
- /* For compatability with 0.6.x */
- crm_debug("Creating intermediate parent %s between %s and %s", field, crm_element_name(parent), tag);
- parent = create_xml_node(parent, field);
- }
-
- if(parent == NULL) {
- parent = create_xml_node(NULL, tag);
- child = parent;
-
- } else {
- child = create_xml_node(parent, tag);
- }
-
- for (lpc = 0; lpc < msg->nfields; lpc++) {
- convert_ha_field(child, msg, lpc);
- }
-
- return parent;
-}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 10, 2:23 AM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2009729
Default Alt Text
(110 KB)

Event Timeline