Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/configure.ac b/configure.ac
index 782b9e51f0..7ec36d3e2d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,2153 +1,2156 @@
dnl
dnl autoconf for Pacemaker
dnl
dnl Copyright 2009-2025 the Pacemaker project contributors
dnl
dnl The version control history for this file may have further details.
dnl
dnl This source code is licensed under the GNU General Public License version 2
dnl or later (GPLv2+) WITHOUT ANY WARRANTY.
dnl ==============================================
dnl Bootstrap autotools
dnl ==============================================
# Require a minimum version of autoconf itself
AC_PREREQ(2.64)
dnl AC_CONFIG_MACRO_DIR is deprecated as of autoconf 2.70 (2020-12-08).
dnl Once we can require that version, we can simplify this, and no longer
dnl need ACLOCAL_AMFLAGS in Makefile.am.
m4_ifdef([AC_CONFIG_MACRO_DIRS],
[AC_CONFIG_MACRO_DIRS([m4])],
[AC_CONFIG_MACRO_DIR([m4])])
m4_include([m4/version.m4])
AC_INIT([pacemaker], VERSION_NUMBER, [users@clusterlabs.org], [pacemaker],
PCMK_URL)
LT_CONFIG_LTDL_DIR([libltdl])
AC_CONFIG_AUX_DIR([libltdl/config])
dnl Where #defines that autoconf makes (e.g. HAVE_whatever) go
dnl
dnl include/config.h
dnl - Internal API
dnl - Contains all defines
dnl - include/config.h.in is generated automatically by autoheader
dnl - Not to be included in any header files except crm_internal.h
dnl (which is also not to be included in any other header files)
dnl
dnl include/crm_config.h
dnl - External API
dnl - Contains a subset of defines
dnl - include/crm_config.h.in is manually edited to select the subset
dnl - Should not include HAVE_* defines
dnl - Safe to include anywhere
AC_CONFIG_HEADERS([include/config.h include/crm_config.h])
dnl 1.13: minimum automake version required
dnl foreign: don't require GNU-standard top-level files
dnl tar-ustar: use (older) POSIX variant of generated tar rather than v7
dnl subdir-objects: keep .o's with their .c's (no-op in 2.0+)
AM_INIT_AUTOMAKE([1.13 foreign tar-ustar subdir-objects])
dnl Require minimum version of pkg-config
PKG_PROG_PKG_CONFIG(0.28)
AS_IF([test x"${PKG_CONFIG}" != x""], [],
[AC_MSG_FAILURE([Could not find required build tool pkg-config (0.28 or later)])])
PKG_INSTALLDIR
PKG_NOARCH_INSTALLDIR
dnl ==============================================
dnl Compiler checks and helpers
dnl ==============================================
dnl A particular compiler can be forced by setting the CC environment variable
AC_PROG_CC
dnl C++ is needed only to run maintainer utilities, not to build
AC_PROG_CXX
dnl Use at least C99 if possible (automatic for autoconf >= 2.70)
m4_version_prereq([2.70], [:], [AC_PROG_CC_STDC])
# cc_supports_flag <compiler-flag>
# Return success if the C compiler supports the given flag
cc_supports_flag() {
local CFLAGS="-Werror $@"
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
}
# cc_temp_flags <compiler-flags>
# Use the given flags for subsequent C compilation. These can be reverted to
# what was used previously with cc_restore_flags. This allows certain tests to
# use specific flags without affecting anything else.
cc_temp_flags() {
ac_save_CFLAGS="$CFLAGS"
CFLAGS="$*"
}
# cc_restore_flags
# Restore C compiler flags to what they were before the last cc_temp_flags
# call.
cc_restore_flags() {
CFLAGS=$ac_save_CFLAGS
}
# Check for fatal warning support
AS_IF([test $enable_fatal_warnings -ne $DISABLED dnl
&& test x"$GCC" = x"yes" && cc_supports_flag -Werror],
[WERROR="-Werror"],
[
WERROR=""
AS_CASE([$enable_fatal_warnings],
[$REQUIRED], [AC_MSG_ERROR([Compiler does not support fatal warnings])],
[$OPTIONAL], [enable_fatal_warnings=$DISABLED])
])
dnl ==============================================
dnl Linker checks
dnl ==============================================
# Check whether linker supports --enable-new-dtags to use RUNPATH instead of
# RPATH. It is necessary to do this before libtool does linker detection.
# See also: https://github.com/kronosnet/kronosnet/issues/107
AX_CHECK_LINK_FLAG([-Wl,--enable-new-dtags],
[AM_LDFLAGS=-Wl,--enable-new-dtags],
[AC_MSG_ERROR(["Linker support for --enable-new-dtags is required"])])
AC_SUBST([AM_LDFLAGS])
saved_LDFLAGS="$LDFLAGS"
LDFLAGS="$AM_LDFLAGS $LDFLAGS"
LT_INIT([dlopen])
LDFLAGS="$saved_LDFLAGS"
LTDL_INIT([convenience])
dnl ==============================================
dnl Define configure options
dnl ==============================================
# yes_no_try <user-response> <default>
# Map a yes/no/try user selection to $REQUIRED for yes, $DISABLED for no, and
# $OPTIONAL for try.
DISABLED=0
REQUIRED=1
OPTIONAL=2
yes_no_try() {
local value
AS_IF([test x"$1" = x""], [value="$2"], [value="$1"])
AS_CASE(["`echo "$value" | tr '[A-Z]' '[a-z]'`"],
[0|no|false|disable], [return $DISABLED],
[1|yes|true|enable], [return $REQUIRED],
[try|check], [return $OPTIONAL]
)
AC_MSG_ERROR([Invalid option value "$value"])
}
#
# Fix the defaults of certain built-in variables so they can be used in the
# defaults for our custom arguments
#
AC_MSG_NOTICE([Sanitizing prefix: ${prefix}])
AS_IF([test x"$prefix" = x"NONE"],
[
prefix=/usr
dnl Fix default variables - "prefix" variable if not specified
AS_IF([test x"$localstatedir" = x"\${prefix}/var"],
[localstatedir="/var"])
AS_IF([test x"$sysconfdir" = x"\${prefix}/etc"],
[sysconfdir="/etc"])
])
AC_MSG_NOTICE([Sanitizing exec_prefix: ${exec_prefix}])
AS_CASE([$exec_prefix],
[prefix|NONE], [exec_prefix=$prefix])
AC_MSG_NOTICE([Sanitizing libdir: ${libdir}])
AS_CASE([$libdir],
[prefix|NONE], [
AC_MSG_CHECKING([which lib directory to use])
for aDir in lib64 lib
do
trydir="${exec_prefix}/${aDir}"
AS_IF([test -d ${trydir}],
[
libdir=${trydir}
break
])
done
AC_MSG_RESULT([$libdir])
])
# Start a list of optional features this build supports
PCMK_FEATURES=""
dnl This section should include only the definition of configure script
dnl options and determining their values. Processing should be done later when
dnl possible, other than what's needed to determine values and defaults.
dnl Per the autoconf docs, --enable-*/--disable-* options should control
dnl features inherent to Pacemaker, while --with-*/--without-* options should
dnl control the use of external software. However, --enable-*/--disable-* may
dnl implicitly require additional external dependencies, and
dnl --with-*/--without-* may implicitly enable or disable features, so the
dnl line is blurry.
dnl
dnl We also use --with-* options for custom file, directory, and path
dnl locations, since autoconf does not provide an option type for those.
dnl --enable-* options: build process
AC_ARG_ENABLE([quiet],
[AS_HELP_STRING([--enable-quiet],
[suppress make output unless there is an error @<:@no@:>@])]
)
yes_no_try "$enable_quiet" "no"
enable_quiet=$?
AC_ARG_ENABLE([fatal-warnings],
[AS_HELP_STRING([--enable-fatal-warnings],
[enable pedantic and fatal warnings for gcc @<:@try@:>@])],
)
yes_no_try "$enable_fatal_warnings" "try"
enable_fatal_warnings=$?
AC_ARG_ENABLE([hardening],
[AS_HELP_STRING([--enable-hardening],
[harden the resulting executables/libraries @<:@try@:>@])]
)
yes_no_try "$enable_hardening" "try"
enable_hardening=$?
dnl --enable-* options: features within Pacemaker
dnl @COMPAT This should be --with-systemd
AC_ARG_ENABLE([systemd],
[AS_HELP_STRING([--enable-systemd],
[enable support for managing resources via systemd @<:@try@:>@])]
)
yes_no_try "$enable_systemd" "try"
enable_systemd=$?
AC_ARG_ENABLE([deprecated-libs],
[AS_HELP_STRING([--enable-deprecated-libs],
[Build and install deprecated C libraries @<:@yes@:>@])]
)
yes_no_try "$enable_deprecated_libs" "yes"
enable_deprecated_libs=$?
AM_CONDITIONAL([BUILD_DEPRECATED_LIBS],
[test $enable_deprecated_libs -ne $DISABLED])
# AM_GNU_GETTEXT calls AM_NLS which defines the nls option, but it defaults
# to enabled. We override the definition of AM_NLS to flip the default and mark
# it as experimental in the help text.
AC_DEFUN([AM_NLS],
[AC_MSG_CHECKING([whether NLS is requested])
AC_ARG_ENABLE([nls],
[AS_HELP_STRING([--enable-nls],
[use Native Language Support (experimental)])],
USE_NLS=$enableval, USE_NLS=no)
AC_MSG_RESULT([$USE_NLS])
AC_SUBST([USE_NLS])]
)
AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION([0.18])
dnl --with-* options: external software support, and custom values
dnl This argument is defined via an M4 macro so default can be a variable
AC_DEFUN([VERSION_ARG],
[AC_ARG_WITH([version],
[AS_HELP_STRING([--with-version=VERSION],
[override package version @<:@$1@:>@])],
[ PACEMAKER_VERSION="$withval" ],
[ PACEMAKER_VERSION="$PACKAGE_VERSION" ])]
)
VERSION_ARG(VERSION_NUMBER)
CRM_DAEMON_USER=""
AC_ARG_WITH([daemon-user],
[AS_HELP_STRING([--with-daemon-user=USER],
[user to run unprivileged Pacemaker daemons as (advanced option: changing this may break other cluster components unless similarly configured) @<:@hacluster@:>@])],
[ CRM_DAEMON_USER="$withval" ]
)
AS_IF([test x"${CRM_DAEMON_USER}" = x""],
[CRM_DAEMON_USER="hacluster"])
CRM_DAEMON_GROUP=""
AC_ARG_WITH([daemon-group],
[AS_HELP_STRING([--with-daemon-group=GROUP],
[group to run unprivileged Pacemaker daemons as (advanced option: changing this may break other cluster components unless similarly configured) @<:@haclient@:>@])],
[ CRM_DAEMON_GROUP="$withval" ]
)
AS_IF([test x"${CRM_DAEMON_GROUP}" = x""],
[CRM_DAEMON_GROUP="haclient"])
BUG_URL=""
AC_ARG_WITH([bug-url],
[AS_HELP_STRING([--with-bug-url=DIR], m4_normalize([
address where users should submit bug reports
@<:@https://bugs.clusterlabs.org/enter_bug.cgi?product=Pacemaker@:>@]))],
[ BUG_URL="$withval" ]
)
AS_IF([test x"${BUG_URL}" = x""],
[BUG_URL="https://bugs.clusterlabs.org/enter_bug.cgi?product=Pacemaker"])
dnl @COMPAT This should be --enable-cibsecrets option
AC_ARG_WITH([cibsecrets],
[AS_HELP_STRING([--with-cibsecrets],
[support separate file for CIB secrets @<:@no@:>@])]
)
yes_no_try "$with_cibsecrets" "no"
with_cibsecrets=$?
PCMK__GNUTLS_PRIORITIES="NORMAL"
AC_ARG_WITH([gnutls-priorities],
[AS_HELP_STRING([--with-gnutls-priorities],
[default GnuTLS cipher priorities @<:@NORMAL@:>@])],
[ test x"$withval" = x"no" || PCMK__GNUTLS_PRIORITIES="$withval" ]
)
AC_ARG_WITH([concurrent-fencing-default],
[AS_HELP_STRING([--with-concurrent-fencing-default], m4_normalize([
default value for concurrent-fencing cluster option (deprecated)
@<:@true@:>@]))],
)
AS_CASE([$with_concurrent_fencing_default],
[""], [with_concurrent_fencing_default="true"],
[true], [],
[false], [PCMK_FEATURES="$PCMK_FEATURES concurrent-fencing-default-false"],
[AC_MSG_ERROR([Invalid value "$with_concurrent_fencing_default" for --with-concurrent-fencing-default])]
)
AC_ARG_WITH([sbd-sync-default],
[AS_HELP_STRING([--with-sbd-sync-default], m4_normalize([
default value used by sbd if SBD_SYNC_RESOURCE_STARTUP
environment variable is not set @<:@false@:>@]))],
)
AS_CASE([$with_sbd_sync_default],
[""], [with_sbd_sync_default=false],
[false], [],
[true], [PCMK_FEATURES="$PCMK_FEATURES default-sbd-sync"],
[AC_MSG_ERROR([Invalid value "$with_sbd_sync_default" for --with-sbd-sync-default])]
)
AC_ARG_WITH([resource-stickiness-default],
[AS_HELP_STRING([--with-resource-stickiness-default],
[If positive, value to add to new CIBs as explicit resource default for resource-stickiness @<:@0@:>@])],
)
errmsg="Invalid value \"$with_resource_stickiness_default\" for --with-resource-stickiness-default"
AS_CASE([$with_resource_stickiness_default],
[0|""], [with_resource_stickiness_default="0"],
[*[[!0-9]]*], [AC_MSG_ERROR([$errmsg])],
[PCMK_FEATURES="$PCMK_FEATURES default-resource-stickiness"]
)
AC_ARG_WITH([corosync],
[AS_HELP_STRING([--with-corosync],
[support the Corosync messaging and membership layer @<:@try@:>@])]
)
yes_no_try "$with_corosync" "try"
with_corosync=$?
dnl Get default from Corosync if possible
PKG_CHECK_VAR([PCMK__COROSYNC_CONF], [corosync], [corosysconfdir],
[PCMK__COROSYNC_CONF="$PCMK__COROSYNC_CONF/corosync.conf"],
[PCMK__COROSYNC_CONF="${sysconfdir}/corosync/corosync.conf"])
AC_ARG_WITH([corosync-conf],
[AS_HELP_STRING([--with-corosync-conf], m4_normalize([
location of Corosync configuration file
@<:@value from Corosync package if available otherwise
SYSCONFDIR/corosync/corosync.conf@:>@]))],
[ PCMK__COROSYNC_CONF="$withval" ]
)
dnl --with-* options: directory locations
INITDIR=""
AC_ARG_WITH([initdir],
[AS_HELP_STRING([--with-initdir=DIR], m4_normalize([
directory for lsb resources (init scripts), or "try" to check for
common locations, or "no" to disable] @<:@try@:>@))],
[ INITDIR="$withval" ]
)
AS_IF([test x"$INITDIR" = x""], [INITDIR="try"])
systemdsystemunitdir="${systemdsystemunitdir-}"
AC_ARG_WITH([systemdsystemunitdir],
[AS_HELP_STRING([--with-systemdsystemunitdir=DIR],
[directory for systemd unit files (advanced option: must match what systemd uses)])],
[ systemdsystemunitdir="$withval" ]
)
CONFIGDIR=""
AC_ARG_WITH([configdir],
[AS_HELP_STRING([--with-configdir=DIR],
[directory for Pacemaker configuration file @<:@SYSCONFDIR/sysconfig@:>@])],
[ CONFIGDIR="$withval" ]
)
dnl --runstatedir is available as of autoconf 2.70 (2020-12-08). When users
dnl have an older version, they can use our --with-runstatedir.
pcmk_runstatedir=""
AC_ARG_WITH([runstatedir],
[AS_HELP_STRING([--with-runstatedir=DIR],
[modifiable per-process data @<:@LOCALSTATEDIR/run@:>@ (ignored if --runstatedir is available)])],
[ pcmk_runstatedir="$withval" ]
)
CRM_LOG_DIR=""
AC_ARG_WITH([logdir],
[AS_HELP_STRING([--with-logdir=DIR],
[directory for Pacemaker log file @<:@LOCALSTATEDIR/log/pacemaker@:>@])],
[ CRM_LOG_DIR="$withval" ]
)
CRM_BUNDLE_DIR=""
AC_ARG_WITH([bundledir],
[AS_HELP_STRING([--with-bundledir=DIR],
[directory for Pacemaker bundle logs @<:@LOCALSTATEDIR/log/pacemaker/bundles@:>@])],
[ CRM_BUNDLE_DIR="$withval" ]
)
dnl Get default from resource-agents if possible. Otherwise, the default uses
dnl /usr/lib rather than libdir because it's determined by the OCF project and
dnl not Pacemaker. Even if a user wants to install Pacemaker to /usr/local or
dnl such, the OCF agents will be expected in their usual location. However, we
dnl do give the user the option to override it.
PKG_CHECK_VAR([PCMK_OCF_ROOT], [resource-agents], [ocfrootdir], [],
[PCMK_OCF_ROOT="/usr/lib/ocf"])
AC_ARG_WITH([ocfdir],
[AS_HELP_STRING([--with-ocfdir=DIR], m4_normalize([
OCF resource agent root directory (advanced option: changing this
may break other cluster components unless similarly configured)
@<:@value from resource-agents package if available otherwise
/usr/lib/ocf@:>@]))],
[ PCMK_OCF_ROOT="$withval" ]
)
dnl Get default from resource-agents if possible
PKG_CHECK_VAR([PCMK__OCF_RA_PATH], [resource-agents], [ocfrapath], [],
[PCMK__OCF_RA_PATH="$PCMK_OCF_ROOT/resource.d"])
AC_ARG_WITH([ocfrapath],
[AS_HELP_STRING([--with-ocfrapath=DIR], m4_normalize([
OCF resource agent directories (colon-separated) to search
@<:@value from resource-agents package if available otherwise
OCFDIR/resource.d@:>@]))],
[ PCMK__OCF_RA_PATH="$withval" ]
)
OCF_RA_INSTALL_DIR="$PCMK_OCF_ROOT/resource.d"
AC_ARG_WITH([ocfrainstalldir],
[AS_HELP_STRING([--with-ocfrainstalldir=DIR], m4_normalize([
OCF installation directory for Pacemakers resource agents
@<:@OCFDIR/resource.d@:>@]))],
[ OCF_RA_INSTALL_DIR="$withval" ]
)
dnl Get default from fence-agents if available
PKG_CHECK_VAR([FA_PREFIX], [fence-agents], [prefix],
[PCMK__FENCE_BINDIR="${FA_PREFIX}/sbin"],
[PCMK__FENCE_BINDIR="$sbindir"])
AC_ARG_WITH([fence-bindir],
[AS_HELP_STRING([--with-fence-bindir=DIR], m4_normalize([
directory for executable fence agents @<:@value from fence-agents
package if available otherwise SBINDIR@:>@]))],
[ PCMK__FENCE_BINDIR="$withval" ]
)
dnl --with-* options: non-production testing
AC_ARG_WITH([profiling],
[AS_HELP_STRING([--with-profiling],
[disable optimizations, for effective profiling @<:@no@:>@])]
)
yes_no_try "$with_profiling" "no"
with_profiling=$?
AC_ARG_WITH([coverage],
[AS_HELP_STRING([--with-coverage],
[disable optimizations, for effective profiling and coverage testing @<:@no@:>@])]
)
yes_no_try "$with_coverage" "no"
with_coverage=$?
AC_DEFINE_UNQUOTED([PCMK__WITH_COVERAGE], [$with_coverage], [Build with code coverage])
AM_CONDITIONAL([BUILD_COVERAGE], [test $with_coverage -ne $DISABLED])
AC_ARG_WITH([sanitizers],
[AS_HELP_STRING([--with-sanitizers=...,...],
[enable SANitizer build, do *NOT* use for production. Only ASAN/UBSAN/TSAN are currently supported])],
[ SANITIZERS="$withval" ],
[ SANITIZERS="" ])
dnl Environment variable options
AC_ARG_VAR([CFLAGS_HARDENED_LIB], [extra C compiler flags for hardened libraries])
AC_ARG_VAR([LDFLAGS_HARDENED_LIB], [extra linker flags for hardened libraries])
AC_ARG_VAR([CFLAGS_HARDENED_EXE], [extra C compiler flags for hardened executables])
AC_ARG_VAR([LDFLAGS_HARDENED_EXE], [extra linker flags for hardened executables])
dnl ==============================================
dnl Locate essential tools
dnl ==============================================
PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin"
export PATH
dnl Pacemaker's executable python scripts will invoke the python specified by
dnl configure's PYTHON variable. If not specified, AM_PATH_PYTHON will check a
dnl built-in list with (unversioned) "python" having precedence. To configure
dnl Pacemaker to use a specific python interpreter version, define PYTHON
dnl when calling configure, for example: ./configure PYTHON=/usr/bin/python3.6
dnl If PYTHON was specified, ensure it is an absolute path
AS_IF([test x"${PYTHON}" != x""], [AC_PATH_PROG([PYTHON], [$PYTHON])])
dnl Require a minimum Python version
AM_PATH_PYTHON([3.6])
+PKG_CHECK_MODULES([PYTHON], [python])
+AC_SUBST([PYTHON_LIBS])
+AC_SUBST([PYTHON_CFLAGS])
AC_PROG_LN_S
AC_PROG_MKDIR_P
AC_PATH_PROG([GIT], [git], [false])
dnl Bash is needed for building man pages and running regression tests.
dnl We set "BASH_PATH" because "BASH" is already an environment variable.
REQUIRE_PROG([BASH_PATH], [bash])
AC_PATH_PROGS(PCMK__VALGRIND_EXEC, valgrind, /usr/bin/valgrind)
AC_DEFINE_UNQUOTED(PCMK__VALGRIND_EXEC, "$PCMK__VALGRIND_EXEC", Valgrind command)
dnl ==============================================
dnl Package and schema versioning
dnl ==============================================
# Redefine PACKAGE_VERSION and VERSION according to PACEMAKER_VERSION in case
# the user used --with-version. Unfortunately, this can only affect the
# substitution variables and later uses in this file, not the config.h
# constants, so we have to be careful to use only PACEMAKER_VERSION in C code.
PACKAGE_VERSION=$PACEMAKER_VERSION
VERSION=$PACEMAKER_VERSION
AC_DEFINE_UNQUOTED(PACEMAKER_VERSION, "$VERSION",
[Version number of this Pacemaker build])
AC_MSG_CHECKING([build version])
AS_IF([test "$GIT" != "false" && test -d .git],
[
BUILD_VERSION=`"$GIT" log --pretty="format:%h" -n 1`
AC_MSG_RESULT([$BUILD_VERSION (git hash)])
],
[
# 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([$BUILD_VERSION (directory name)])
])
AC_DEFINE_UNQUOTED(BUILD_VERSION, "$BUILD_VERSION", Build version)
AC_SUBST(BUILD_VERSION)
# schema_files <schema-dir>
# List all manually edited RNG schemas (as opposed to auto-generated via make)
# in the given directory. Use git if available to list managed RNGs, in case
# there are leftover schema files from an earlier build of a different
# version. Otherwise, check all RNGs.
schema_files() {
local files="$("$GIT" ls-files "$1"/*.rng 2>/dev/null)"
AS_IF([test x"$files" = x""],
[
files="$(ls -1 "$1"/*.rng | grep -E -v \
'/(pacemaker|api-result|crm_mon|versions)[^/]*\.rng')"
])
echo "$files"
}
# latest_schema_version <schema-dir>
# Determine highest RNG version in the given schema directory.
latest_schema_version() {
schema_files "$1" | sed -n -e 's/^.*-\([[0-9]][[0-9.]]*\).rng$/\1/p' dnl
| sort -V | tail -1
}
# schemas_for_make <schema-dir>
# Like schema_files, but suitable for use in make variables.
schemas_for_make() {
local file
for file in $(schema_files "$1"); do
AS_ECHO_N(["\$(top_srcdir)/$file "])
done
}
# Detect highest API schema version
API_VERSION=$(latest_schema_version "xml/api")
AC_DEFINE_UNQUOTED([PCMK__API_VERSION], ["$API_VERSION"],
[Highest API schema version])
# Detect highest CIB schema version
CIB_VERSION=$(latest_schema_version "xml")
AC_SUBST(CIB_VERSION)
# Re-run configure at next make if schema files change, to re-detect versions
cib_schemas="$(schemas_for_make "xml")"
api_schemas="$(schemas_for_make "xml/api")"
CONFIG_STATUS_DEPENDENCIES="$cib_schemas $api_schemas"
AC_SUBST(CONFIG_STATUS_DEPENDENCIES)
dnl ==============================================
dnl Process simple options
dnl ==============================================
AS_IF([test x"$enable_nls" = x"yes"], [PCMK_FEATURES="$PCMK_FEATURES nls"])
AS_IF([test x"$with_concurrent_fencing_default" = x"true"],
[PCMK__CONCURRENT_FENCING_DEFAULT_TRUE="1"],
[PCMK__CONCURRENT_FENCING_DEFAULT_TRUE="0"])
AC_DEFINE_UNQUOTED([PCMK__CONCURRENT_FENCING_DEFAULT_TRUE],
[$PCMK__CONCURRENT_FENCING_DEFAULT_TRUE],
[Whether concurrent-fencing cluster option default is true])
AC_DEFINE_UNQUOTED([PCMK__SBD_SYNC_DEFAULT],
[$with_sbd_sync_default],
[Default value for SBD_SYNC_RESOURCE_STARTUP environment variable])
AC_DEFINE_UNQUOTED([PCMK__RESOURCE_STICKINESS_DEFAULT],
[$with_resource_stickiness_default],
[Default value for resource-stickiness resource meta-attribute])
AS_IF([test x"${PCMK__GNUTLS_PRIORITIES}" != x""], [],
[AC_MSG_ERROR([--with-gnutls-priorities value must not be empty])])
AC_DEFINE_UNQUOTED([PCMK__GNUTLS_PRIORITIES], ["$PCMK__GNUTLS_PRIORITIES"],
[GnuTLS cipher priorities])
AC_SUBST(PCMK__GNUTLS_PRIORITIES)
AC_SUBST(BUG_URL)
AC_DEFINE_UNQUOTED([PCMK__BUG_URL], ["$BUG_URL"],
[Where bugs should be reported])
AC_DEFINE_UNQUOTED([CRM_DAEMON_USER], ["$CRM_DAEMON_USER"],
[User to run Pacemaker daemons as])
AC_SUBST(CRM_DAEMON_USER)
AC_DEFINE_UNQUOTED([CRM_DAEMON_GROUP], ["$CRM_DAEMON_GROUP"],
[Group to run Pacemaker daemons as])
AC_SUBST(CRM_DAEMON_GROUP)
dnl ==============================================
dnl Process file paths
dnl ==============================================
# expand_path_option <path-variable-name> [<default>]
# Given the name of a file path variable, expand any variable references
# inside it, use the specified default if it is not specified, and ensure it
# is a full path.
expand_path_option() {
# The first argument is the variable *name* (not value)
ac_path_varname="$1"
# Get the original value of the variable
ac_path_value=$(eval echo "\${${ac_path_varname}}")
# Expand any literal variable expressions in the value so that we don't
# end up with something like '${prefix}' in #defines etc.
#
# Autoconf deliberately leaves values unexpanded to allow overriding
# the configure script choices in make commands (for example,
# "make exec_prefix=/foo install"). No longer being able to do this seems
# like no great loss.
eval ac_path_value=$(eval echo "${ac_path_value}")
# Use (expanded) default if necessary
AS_IF([test x"${ac_path_value}" = x""],
[eval ac_path_value=$(eval echo "$2")])
# Require a full path
AS_CASE(["$ac_path_value"],
[/*], [eval ${ac_path_varname}="$ac_path_value"],
[*], [AC_MSG_ERROR([$ac_path_varname value "$ac_path_value" is not a full path])]
)
}
dnl Expand values of autoconf-provided directory options
expand_path_option prefix
expand_path_option exec_prefix
expand_path_option bindir
expand_path_option sbindir
expand_path_option libexecdir
expand_path_option datarootdir
expand_path_option datadir
expand_path_option sysconfdir
expand_path_option sharedstatedir
expand_path_option localstatedir
expand_path_option libdir
expand_path_option includedir
expand_path_option oldincludedir
expand_path_option infodir
expand_path_option mandir
AC_DEFUN([AC_DATAROOTDIR_CHECKED])
dnl Expand values of custom directory options
AS_IF([test x"$INITDIR" = x"try"],
[
AC_MSG_CHECKING([for an init directory])
INITDIR=no
for initdir in /etc/init.d /etc/rc.d/init.d /sbin/init.d \
/usr/local/etc/rc.d /etc/rc.d ${sysconfdir}/init.d
do
AS_IF([test -d $initdir],
[
INITDIR=$initdir
break
])
done
AC_MSG_RESULT([$INITDIR])
])
support_lsb=$DISABLED
AM_CONDITIONAL([BUILD_LSB], [test x"${INITDIR}" != x"no"])
AM_COND_IF([BUILD_LSB],
[
support_lsb=$REQUIRED
expand_path_option INITDIR
PCMK_FEATURES="$PCMK_FEATURES lsb"
],
[ INITDIR="" ])
AC_SUBST(INITDIR)
AC_DEFINE_UNQUOTED([PCMK__ENABLE_LSB], [$support_lsb],
[Whether to support LSB resource agents])
AC_DEFINE_UNQUOTED([PCMK__LSB_INIT_DIR], ["$INITDIR"],
[Location for LSB init scripts])
expand_path_option localedir "${datadir}/locale"
AC_DEFINE_UNQUOTED([PCMK__LOCALE_DIR],["$localedir"],
[Base directory for message catalogs])
AS_IF([test x"${runstatedir}" = x""], [runstatedir="${pcmk_runstatedir}"])
expand_path_option runstatedir "${localstatedir}/run"
AC_DEFINE_UNQUOTED([PCMK__RUN_DIR], ["$runstatedir"],
[Location for modifiable per-process data])
AC_SUBST(runstatedir)
expand_path_option docdir "${datadir}/doc/${PACKAGE}-${VERSION}"
AC_SUBST(docdir)
expand_path_option CONFIGDIR "${sysconfdir}/sysconfig"
AC_SUBST(CONFIGDIR)
expand_path_option PCMK__COROSYNC_CONF "${sysconfdir}/corosync/corosync.conf"
AC_SUBST(PCMK__COROSYNC_CONF)
expand_path_option CRM_LOG_DIR "${localstatedir}/log/pacemaker"
AC_DEFINE_UNQUOTED([CRM_LOG_DIR], ["$CRM_LOG_DIR"],
[Location for Pacemaker log file])
AC_SUBST(CRM_LOG_DIR)
expand_path_option CRM_BUNDLE_DIR "${localstatedir}/log/pacemaker/bundles"
AC_DEFINE_UNQUOTED([CRM_BUNDLE_DIR], ["$CRM_BUNDLE_DIR"],
[Location for Pacemaker bundle logs])
AC_SUBST(CRM_BUNDLE_DIR)
expand_path_option PCMK__FENCE_BINDIR
AC_SUBST(PCMK__FENCE_BINDIR)
AC_DEFINE_UNQUOTED([PCMK__FENCE_BINDIR], ["$PCMK__FENCE_BINDIR"],
[Location for executable fence agents])
expand_path_option PCMK_OCF_ROOT
AC_SUBST(PCMK_OCF_ROOT)
AC_DEFINE_UNQUOTED([PCMK_OCF_ROOT], ["$PCMK_OCF_ROOT"],
[OCF root directory for resource agents and libraries])
expand_path_option PCMK__OCF_RA_PATH
AC_SUBST(PCMK__OCF_RA_PATH)
AC_DEFINE_UNQUOTED([PCMK__OCF_RA_PATH], ["$PCMK__OCF_RA_PATH"],
[OCF directories to search for resource agents ])
expand_path_option OCF_RA_INSTALL_DIR
AC_SUBST(OCF_RA_INSTALL_DIR)
# Derived paths
PCMK_SCHEMA_DIR="${datadir}/pacemaker"
AC_DEFINE_UNQUOTED([PCMK_SCHEMA_DIR], ["$PCMK_SCHEMA_DIR"],
[Location for the Pacemaker Relax-NG Schema])
AC_SUBST(PCMK_SCHEMA_DIR)
PCMK__REMOTE_SCHEMA_DIR="${localstatedir}/lib/pacemaker/schemas"
AC_DEFINE_UNQUOTED([PCMK__REMOTE_SCHEMA_DIR], ["$PCMK__REMOTE_SCHEMA_DIR"],
[Location to store Relax-NG Schema files on remote nodes])
AC_SUBST(PCMK__REMOTE_SCHEMA_DIR)
CRM_CORE_DIR="${localstatedir}/lib/pacemaker/cores"
AC_DEFINE_UNQUOTED([CRM_CORE_DIR], ["$CRM_CORE_DIR"],
[Directory Pacemaker daemons should change to (without systemd, core files will go here)])
AC_SUBST(CRM_CORE_DIR)
PCMK__PERSISTENT_DATA_DIR="${localstatedir}/lib/pacemaker"
AC_DEFINE_UNQUOTED([PCMK__PERSISTENT_DATA_DIR], ["$PCMK__PERSISTENT_DATA_DIR"],
[Location to store directory produced by Pacemaker daemons])
AC_SUBST(PCMK__PERSISTENT_DATA_DIR)
CRM_BLACKBOX_DIR="${localstatedir}/lib/pacemaker/blackbox"
AC_DEFINE_UNQUOTED([CRM_BLACKBOX_DIR], ["$CRM_BLACKBOX_DIR"],
[Where to keep blackbox dumps])
AC_SUBST(CRM_BLACKBOX_DIR)
PCMK_SCHEDULER_INPUT_DIR="${localstatedir}/lib/pacemaker/pengine"
AC_DEFINE_UNQUOTED([PCMK_SCHEDULER_INPUT_DIR], ["$PCMK_SCHEDULER_INPUT_DIR"],
[Where to keep scheduler outputs])
AC_SUBST(PCMK_SCHEDULER_INPUT_DIR)
CRM_CONFIG_DIR="${localstatedir}/lib/pacemaker/cib"
AC_DEFINE_UNQUOTED([CRM_CONFIG_DIR], ["$CRM_CONFIG_DIR"],
[Where to keep 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)
CRM_STATE_DIR="${runstatedir}/crm"
AC_DEFINE_UNQUOTED([CRM_STATE_DIR], ["$CRM_STATE_DIR"],
[Where to keep state files and sockets])
AC_SUBST(CRM_STATE_DIR)
PCMK__OCF_TMP_DIR="${runstatedir}/resource-agents"
AC_DEFINE_UNQUOTED([PCMK__OCF_TMP_DIR], ["$PCMK__OCF_TMP_DIR"],
[Where resource agents should keep state files])
AC_SUBST(PCMK__OCF_TMP_DIR)
PACEMAKER_CONFIG_DIR="${sysconfdir}/pacemaker"
AC_DEFINE_UNQUOTED([PACEMAKER_CONFIG_DIR], ["$PACEMAKER_CONFIG_DIR"],
[Where to keep configuration files like authkey])
AC_SUBST(PACEMAKER_CONFIG_DIR)
# Fedora >=42 makes /usr/sbin a symlink to /usr/bin. It updates the RPM macros
# to set _sbindir to "${_exec_prefix}/bin", the same value as _bindir.
# Previously it was set to "${_exec_prefix}/sbin". (Note that because of the
# symlink, paths beginning with /usr/sbin remain valid.)
#
# This causes problems with bundle resources. Pacemaker automatically generates
# a configuration for the bundle's container resource. If the bundle contains a
# primitive and the container's run-command attribute is unset, the generated
# container resource has its run_cmd attribute set to
# SBIN_DIR "/" PCMK__SERVER_REMOTED, which is intended as a reasonable default.
# If SBIN_DIR becomes "/usr/bin" instead of "/usr/sbin", at least two problems
# can occur:
# 1. The container resource's digest changes compared to the digest in the
# resource history entry. Pacemaker interprets this as a configuration
# change and restarts the container resource.
# 2. If the container is running a different OS distro or an older version of
# Fedora, then the new /usr/bin/pacemaker-remoted path may be invalid; the
# executable was installed at /usr/sbin/pacemaker-remoted, which is NOT a
# symlink to /usr/bin path. In this case, the container fails to start.
#
# We override the value only for the SBIN_DIR constant, which is used only for
# the sbd path and the default pacemaker-remoted path. There is no need to
# override sbindir, which would affect installation directories.
#
# There is no more specific way than the below, to detect whether the build
# system has this /usr/sbin vs. /usr/bin change in effect. Thus corner cases are
# possible when sbindir/bindir are manually specified or in distros with
# atypical defaults.
#
# At time of writing, autoconf is unchanged. However, we perform the override
# here instead of in the spec file, in case autoconf changes in the future.
#
# Note that other distros (for example, RHEL) are likely to incorporate these
# changes in the future.
#
# References:
# * https://fedoraproject.org/wiki/Changes/Unify_bin_and_sbin
# * https://bodhi.fedoraproject.org/updates/FEDORA-2025-da0a082e66
# * https://discussion.fedoraproject.org/t/144562
AS_IF([test x"$sbindir" = x"$bindir" \
&& test x"$sbindir" = x"${exec_prefix}/bin"],
[SBIN_DIR="${exec_prefix}/sbin"],
[SBIN_DIR="$sbindir"])
AC_DEFINE_UNQUOTED([SBIN_DIR], ["$SBIN_DIR"], [Location for system binaries])
# Warn about any directories that don't exist (which may be OK)
for j in prefix exec_prefix bindir sbindir libexecdir datadir sysconfdir \
sharedstatedir localstatedir libdir includedir oldincludedir infodir \
mandir INITDIR docdir CONFIGDIR localedir SBIN_DIR
do
dirname=`eval echo '${'${j}'}'`
AS_IF([test -n "$dirname" && test ! -d "$dirname"],
[AC_MSG_WARN([$j directory ($dirname) does not exist (yet)])])
done
dnl ===============================================
dnl General Processing
dnl ===============================================
us_auth=
AC_CHECK_HEADER([sys/socket.h], [
AC_CHECK_DECL([SO_PEERCRED], [
# Linux
AC_CHECK_TYPE([struct ucred], [
us_auth=peercred_ucred;
AC_DEFINE([HAVE_UCRED], [1],
[Define if Unix socket auth method is
getsockopt(s, SO_PEERCRED, &ucred, ...)])
], [
# OpenBSD
AC_CHECK_TYPE([struct sockpeercred], [
us_auth=localpeercred_sockepeercred;
AC_DEFINE([HAVE_SOCKPEERCRED], [1],
[Define if Unix socket auth method is
getsockopt(s, SO_PEERCRED, &sockpeercred, ...)])
], [], [[#include <sys/socket.h>]])
], [[#define _GNU_SOURCE
#include <sys/socket.h>]])
], [], [[#include <sys/socket.h>]])
])
AS_IF([test -z "${us_auth}"], [
# FreeBSD
AC_CHECK_DECL([getpeereid], [
us_auth=getpeereid;
AC_DEFINE([HAVE_GETPEEREID], [1],
[Define if Unix socket auth method is
getpeereid(s, &uid, &gid)])
], [
# Solaris/OpenIndiana
AC_CHECK_DECL([getpeerucred], [
us_auth=getpeerucred;
AC_DEFINE([HAVE_GETPEERUCRED], [1],
[Define if Unix socket auth method is
getpeercred(s, &ucred)])
], [
AC_MSG_FAILURE([No way to authenticate a Unix socket peer])
], [[#include <ucred.h>]])
])
])
dnl OS-based decision-making is poor autotools practice; feature-based
dnl mechanisms are strongly preferred. Keep this section to a bare minimum;
dnl regard as a "necessary evil".
dnl Set host_os and host_cpu
AC_CANONICAL_HOST
INIT_EXT=""
PROCFS=0
dnl Solaris and some *BSD versions support procfs but not files we need
AS_CASE(["$host_os"],
[*bsd*], [INIT_EXT=".sh"],
[*linux*], [PROCFS=1],
[darwin*], [
LIBS="$LIBS -L${prefix}/lib"
CFLAGS="$CFLAGS -I${prefix}/include"
])
AC_SUBST(INIT_EXT)
AM_CONDITIONAL([SUPPORT_PROCFS], [test $PROCFS -eq 1])
AC_DEFINE_UNQUOTED([HAVE_LINUX_PROCFS], [$PROCFS],
[Define to 1 if procfs is supported])
AS_CASE(["$host_cpu"],
[ppc64|powerpc64], [
AS_CASE([$CFLAGS],
[*powerpc64*], [],
[*], [AS_IF([test x"$GCC" = x"yes"], [CFLAGS="$CFLAGS -m64"])
])
])
dnl ==============================================
dnl Documentation build dependencies and checks
dnl ==============================================
AC_PATH_PROG([HELP2MAN], [help2man])
AC_PATH_PROG([SPHINX], [sphinx-build])
AC_PATH_PROG([XSLTPROC], [xsltproc])
AC_PATH_PROG([XMLCATALOG], [xmlcatalog])
AM_CONDITIONAL(BUILD_HELP, test x"${HELP2MAN}" != x"")
AS_IF([test x"${HELP2MAN}" != x""],
[PCMK_FEATURES="$PCMK_FEATURES generated-manpages"])
MANPAGE_XSLT=""
AS_IF([test x"${XSLTPROC}" != x""],
[
AC_MSG_CHECKING([for DocBook-to-manpage transform])
# first try to figure out correct template using xmlcatalog query,
# resort to extensive (semi-deterministic) file search if that fails
DOCBOOK_XSL_URI='http://docbook.sourceforge.net/release/xsl/current'
DOCBOOK_XSL_PATH='manpages/docbook.xsl'
MANPAGE_XSLT=$(${XMLCATALOG} "" ${DOCBOOK_XSL_URI}/${DOCBOOK_XSL_PATH} \
| sed -n 's|^file://||p;q')
AS_IF([test x"${MANPAGE_XSLT}" = x""],
[
DIRS=$(find "${datadir}" -name $(basename $(dirname ${DOCBOOK_XSL_PATH})) \
-type d 2>/dev/null | LC_ALL=C sort)
XSLT=$(basename ${DOCBOOK_XSL_PATH})
for d in ${DIRS}
do
AS_IF([test -f "${d}/${XSLT}"],
[
MANPAGE_XSLT="${d}/${XSLT}"
break
])
done
])
])
AC_MSG_RESULT([$MANPAGE_XSLT])
AC_SUBST(MANPAGE_XSLT)
AM_CONDITIONAL(BUILD_XML_HELP, test x"${MANPAGE_XSLT}" != x"")
AS_IF([test x"${MANPAGE_XSLT}" != x""],
[PCMK_FEATURES="$PCMK_FEATURES agent-manpages"])
AM_CONDITIONAL([BUILD_SPHINX_DOCS], [test x"${SPHINX}" != x""])
AM_COND_IF([BUILD_SPHINX_DOCS], [PCMK_FEATURES="$PCMK_FEATURES books"])
dnl Pacemaker's shell scripts (and thus man page builders) rely on GNU getopt
AC_MSG_CHECKING([for GNU-compatible getopt])
IFS_orig=$IFS
IFS=:
for PATH_DIR in $PATH
do
IFS=$IFS_orig
GETOPT_PATH="${PATH_DIR}/getopt"
AS_IF([test -f "$GETOPT_PATH" && test -x "$GETOPT_PATH"],
[
$GETOPT_PATH -T >/dev/null 2>/dev/null
AS_IF([test $? -eq 4], [break])
])
GETOPT_PATH=""
done
IFS=$IFS_orig
AS_IF([test -n "$GETOPT_PATH"], [AC_MSG_RESULT([$GETOPT_PATH])],
[
AC_MSG_RESULT([no])
AC_MSG_ERROR([Could not find required build tool GNU-compatible getopt])
])
AC_SUBST([GETOPT_PATH])
dnl ===============================================
dnl Libraries
dnl ===============================================
AC_SEARCH_LIBS([socket], [socket])
save_LIBS="$LIBS"
DL_LIBS=""
LIBS=""
AC_SEARCH_LIBS([dlopen], [dl],
[test "$ac_cv_search_dlopen" = "none required" || DL_LIBS="$LIBS"])
AC_SUBST(DL_LIBS)
LIBS="$save_LIBS"
save_LIBS="$LIBS"
PAM_LIBS=""
LIBS=""
AC_SEARCH_LIBS([pam_start], [pam],
[test "$ac_cv_search_pam_start" = "none required" || PAM_LIBS="$LIBS"])
AC_SUBST(PAM_LIBS)
LIBS="$save_LIBS"
PKG_CHECK_MODULES([UUID], [uuid],
[CPPFLAGS="${CPPFLAGS} ${UUID_CFLAGS}"
LIBS="${LIBS} ${UUID_LIBS}"])
# Require minimum glib version
PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.42.0],
[CPPFLAGS="${CPPFLAGS} ${GLIB_CFLAGS}"
LIBS="${LIBS} ${GLIB_LIBS}"])
# Check whether high-resolution sleep function is available
AC_CHECK_FUNCS([nanosleep usleep])
PKG_CHECK_MODULES(LIBXML2, [libxml-2.0 >= 2.9.2],
[CPPFLAGS="${CPPFLAGS} ${LIBXML2_CFLAGS}"
LIBS="${LIBS} ${LIBXML2_LIBS}"])
AC_PATH_PROGS(XMLLINT_PATH, xmllint, /usr/bin/xmllint)
AC_DEFINE_UNQUOTED(XMLLINT_PATH, "$XMLLINT_PATH", xmllint command)
REQUIRE_LIB([xslt], [xsltApplyStylesheet])
AC_MSG_CHECKING([whether __progname and __progname_full are available])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[extern char *__progname, *__progname_full;]],
[[__progname = "foo";
__progname_full = "foo bar";]])],
[
have_progname="yes"
AC_DEFINE(HAVE_PROGNAME, 1,
[Define to 1 if processes can change their name])
],
[have_progname="no"])
AC_MSG_RESULT([$have_progname])
dnl ========================================================================
dnl Headers
dnl ========================================================================
# Some distributions insert #warnings into deprecated headers. If we will
# enable fatal warnings for the build, then enable them for the header checks
# as well, otherwise the build could fail even though the header check
# succeeds. (We should probably be doing this in more places.)
cc_temp_flags "$CFLAGS $WERROR"
# Optional headers (inclusion of these should be conditional in C code)
AC_CHECK_HEADERS([linux/swab.h])
AC_CHECK_HEADERS([sys/signalfd.h])
AC_CHECK_HEADERS([uuid/uuid.h])
AC_CHECK_HEADERS([security/pam_appl.h pam/pam_appl.h])
AS_IF([test x"$ac_cv_lib_pam_pam_start" = x"yes"],
AS_IF([test x"$ac_cv_header_security_pam_appl_h" = x"yes" dnl
|| test x"$ac_cv_header_pam_pam_appl_h" = x"yes"],
[PCMK_FEATURES="$PCMK_FEATURES pam"]))
# Required headers
REQUIRE_HEADER([arpa/inet.h])
REQUIRE_HEADER([ctype.h])
REQUIRE_HEADER([dirent.h])
REQUIRE_HEADER([dlfcn.h])
REQUIRE_HEADER([errno.h])
REQUIRE_HEADER([fcntl.h])
REQUIRE_HEADER([float.h])
REQUIRE_HEADER([glib.h])
REQUIRE_HEADER([grp.h])
REQUIRE_HEADER([inttypes.h])
REQUIRE_HEADER([libgen.h])
REQUIRE_HEADER([limits.h])
REQUIRE_HEADER([locale.h])
REQUIRE_HEADER([netdb.h])
REQUIRE_HEADER([netinet/in.h])
REQUIRE_HEADER([netinet/ip.h], [
#include <sys/types.h>
#include <netinet/in.h>
])
REQUIRE_HEADER([netinet/tcp.h])
REQUIRE_HEADER([pwd.h])
REQUIRE_HEADER([regex.h])
REQUIRE_HEADER([sched.h])
REQUIRE_HEADER([signal.h])
REQUIRE_HEADER([stdarg.h])
REQUIRE_HEADER([stdbool.h])
REQUIRE_HEADER([stdint.h])
REQUIRE_HEADER([stdio.h])
REQUIRE_HEADER([stdlib.h])
REQUIRE_HEADER([string.h])
REQUIRE_HEADER([strings.h])
REQUIRE_HEADER([sys/ioctl.h])
REQUIRE_HEADER([sys/param.h])
REQUIRE_HEADER([sys/reboot.h])
REQUIRE_HEADER([sys/resource.h])
REQUIRE_HEADER([sys/socket.h])
REQUIRE_HEADER([sys/stat.h])
REQUIRE_HEADER([sys/time.h])
REQUIRE_HEADER([sys/types.h])
REQUIRE_HEADER([sys/uio.h])
REQUIRE_HEADER([sys/utsname.h])
REQUIRE_HEADER([sys/wait.h])
REQUIRE_HEADER([termios.h])
REQUIRE_HEADER([time.h])
REQUIRE_HEADER([unistd.h])
REQUIRE_HEADER([libxml/xpath.h])
REQUIRE_HEADER([libxslt/xslt.h])
cc_restore_flags
dnl ========================================================================
dnl Generic declarations
dnl ========================================================================
AC_CHECK_DECLS([CLOCK_MONOTONIC], [PCMK_FEATURES="$PCMK_FEATURES monotonic"], [], [[
#include <time.h>
]])
dnl ========================================================================
dnl Unit test declarations
dnl ========================================================================
AC_CHECK_DECLS([assert_float_equal], [], [], [[
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
]])
dnl ========================================================================
dnl Byte size
dnl ========================================================================
# Compile-time assert hack
# https://jonjagger.blogspot.com/2017/07/compile-time-assertions-in-c.html
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <limits.h>]],
[[
switch (0) {
case 0:
case (CHAR_BIT == 8):
break;
}
]])],
[],
[AC_MSG_FAILURE(m4_normalize([Pacemaker is not supported on
platforms where char is not 8
bits]))])
dnl ========================================================================
dnl Structures
dnl ========================================================================
AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[[#include <time.h>]])
dnl ========================================================================
dnl Functions
dnl ========================================================================
REQUIRE_FUNC([alphasort])
REQUIRE_FUNC([getopt])
REQUIRE_FUNC([scandir])
REQUIRE_FUNC([sched_getscheduler])
REQUIRE_FUNC([setenv])
REQUIRE_FUNC([strndup])
REQUIRE_FUNC([strnlen])
REQUIRE_FUNC([unsetenv])
REQUIRE_FUNC([uuid_unparse])
REQUIRE_FUNC([vasprintf])
AC_CHECK_FUNCS([strchrnul])
AC_CHECK_FUNCS([fopen64])
AM_CONDITIONAL([WRAPPABLE_FOPEN64], [test x"$ac_cv_func_fopen64" = x"yes"])
AC_MSG_CHECKING([whether strerror always returns non-NULL])
AC_RUN_IFELSE([AC_LANG_PROGRAM([[
#include <stdio.h>
#include <string.h>
]], [[
return strerror(-1) == NULL;
]])],
[AC_MSG_RESULT([yes])],
[AC_MSG_ERROR([strerror() is not C99-compliant])],
[AC_MSG_ERROR([strerror() is not C99-compliant])])
AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [[
const char *s = "some-command-line-arg";
char *name = NULL;
int n = sscanf(s, "%ms", &name);
return n != 1;
]])],
[have_sscanf_m="yes"],
[have_sscanf_m="no"],
[have_sscanf_m="no"])
AS_IF([test x"$have_sscanf_m" = x"yes"],
[AC_DEFINE([HAVE_SSCANF_M], [1],
[Define to 1 if sscanf %m modifier is available])])
dnl ========================================================================
dnl bzip2
dnl ========================================================================
REQUIRE_HEADER([bzlib.h])
REQUIRE_LIB([bz2], [BZ2_bzBuffToBuffCompress])
dnl ========================================================================
dnl sighandler_t is missing from Illumos, Solaris11 systems
dnl ========================================================================
AC_MSG_CHECKING([for sighandler_t])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <signal.h>]], [[sighandler_t *f;]])],
[
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_SIGHANDLER_T], [1],
[Define to 1 if sighandler_t is available])
],
[AC_MSG_RESULT([no])])
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 ncurses takes precedence.
dnl
AC_CHECK_HEADERS([curses.h curses/curses.h ncurses.h ncurses/ncurses.h])
save_LIBS="$LIBS"
found_curses=0
CURSES_LIBS=""
LIBS=""
AC_SEARCH_LIBS([printw], [ncurses curses],
[test "$ac_cv_search_printw" = "none required" || CURSES_LIBS="$LIBS"
found_curses=1],
[found_curses=0])
LIBS="$save_LIBS"
dnl Check for printw() prototype compatibility
AS_IF([test $found_curses -eq 1 && cc_supports_flag -Wcast-qual], [
ac_save_LIBS="$LIBS"
LIBS="$CURSES_LIBS"
# avoid broken test because of hardened build environment in Fedora 23+
# - https://fedoraproject.org/wiki/Changes/Harden_All_Packages
# - https://bugzilla.redhat.com/1297985
AS_IF([cc_supports_flag -fPIC],
[cc_temp_flags "-Wcast-qual $WERROR -fPIC"],
[cc_temp_flags "-Wcast-qual $WERROR"])
AC_MSG_CHECKING([whether curses library is compatible])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([
#if defined(HAVE_NCURSES_H)
# include <ncurses.h>
#elif defined(HAVE_NCURSES_NCURSES_H)
# include <ncurses/ncurses.h>
#elif defined(HAVE_CURSES_H)
# include <curses.h>
#elif defined(HAVE_CURSES_CURSES_H)
# include <curses/curses.h>
#endif
],
[printw((const char *)"Test");]
)],
[AC_MSG_RESULT([yes])
PCMK_FEATURES="$PCMK_FEATURES ncurses"
],
[
found_curses=0
CURSES_LIBS=""
AC_MSG_RESULT([no])
AC_MSG_WARN(m4_normalize([Disabling curses because the printw()
function of your (n)curses library is old.
If you wish to enable curses, update to a
newer version (ncurses 5.4 or later is
recommended, available from
https://invisible-island.net/ncurses/)
]))
]
)
LIBS="$ac_save_LIBS"
cc_restore_flags
])
AC_DEFINE_UNQUOTED([PCMK__ENABLE_CURSES], [$found_curses], [have ncurses library])
AC_SUBST(CURSES_LIBS)
dnl ========================================================================
dnl Profiling and GProf
dnl ========================================================================
CFLAGS_ORIG="$CFLAGS"
AS_IF([test $with_coverage -ne $DISABLED],
[
with_profiling=$REQUIRED
PCMK_FEATURES="$PCMK_FEATURES coverage"
CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage"
dnl During linking, make sure to specify -lgcov or -coverage
]
)
AS_IF([test $with_profiling -ne $DISABLED],
[
with_profiling=$REQUIRED
PCMK_FEATURES="$PCMK_FEATURES profile"
dnl Disable various compiler optimizations
CFLAGS="$CFLAGS -fno-omit-frame-pointer -fno-inline -fno-builtin"
dnl CFLAGS="$CFLAGS -fno-inline-functions"
dnl CFLAGS="$CFLAGS -fno-default-inline"
dnl CFLAGS="$CFLAGS -fno-inline-functions-called-once"
dnl CFLAGS="$CFLAGS -fno-optimize-sibling-calls"
dnl Turn off optimization so tools can get accurate line numbers
CFLAGS=`echo $CFLAGS | sed \
-e 's/-O.\ //g' \
-e 's/-Wp,-D_FORTIFY_SOURCE=.\ //g' \
-e 's/-D_FORTIFY_SOURCE=.\ //g'`
CFLAGS="$CFLAGS -O0 -g3 -gdwarf-2"
AC_MSG_NOTICE([CFLAGS before adding profiling options: $CFLAGS_ORIG])
AC_MSG_NOTICE([CFLAGS after: $CFLAGS])
]
)
AM_CONDITIONAL([BUILD_PROFILING], [test "$with_profiling" = "$REQUIRED"])
dnl ========================================================================
dnl Cluster infrastructure - LibQB
dnl ========================================================================
PKG_CHECK_MODULES([libqb], [libqb >= 1.0.1])
CPPFLAGS="$libqb_CFLAGS $CPPFLAGS"
LIBS="$libqb_LIBS $LIBS"
dnl libqb 2.0.5+ (2022-03)
AC_CHECK_FUNCS([qb_ipcc_connect_async])
dnl libqb 2.0.2+ (2020-10)
AC_CHECK_FUNCS([qb_ipcc_auth_get])
dnl libqb 2.0.0+ (2020-05)
dnl also defines QB_FEATURE_LOG_HIRES_TIMESTAMPS
CHECK_ENUM_VALUE([qb/qblog.h],[qb_log_conf],[QB_LOG_CONF_MAX_LINE_LEN])
CHECK_ENUM_VALUE([qb/qblog.h],[qb_log_conf],[QB_LOG_CONF_ELLIPSIS])
dnl Support Linux-HA fence agents if available
AS_IF([test x"$cross_compiling" != x"yes"],
[CPPFLAGS="$CPPFLAGS -I${prefix}/include/heartbeat"])
AC_CHECK_HEADERS([stonith/stonith.h],
[
save_LIBS="$LIBS"
STONITH_LIBS=""
LIBS=""
AC_SEARCH_LIBS([PILLoadPlugin], [pils],
[test "$ac_cv_search_PILLoadPlugin" = "none required" || STONITH_LIBS="$LIBS"])
LIBS=""
AC_SEARCH_LIBS([G_main_add_IPC_Channel], [plumb],
[test "$ac_cv_search_G_main_add_IPC_Channel" = "none required" || STONITH_LIBS="$STONITH_LIBS $LIBS"])
AC_SUBST(STONITH_LIBS)
LIBS="$save_LIBS"
PCMK_FEATURES="$PCMK_FEATURES lha"
])
AM_CONDITIONAL([BUILD_LHA_SUPPORT], [test x"$ac_cv_header_stonith_stonith_h" = x"yes"])
dnl ===============================
dnl Detect DBus and systemd support
dnl ===============================
HAVE_dbus=0
PC_NAME_DBUS=""
PKG_CHECK_MODULES([DBUS],[dbus-1 >= 1.5.12],
[
HAVE_dbus=1
PC_NAME_DBUS="dbus-1"
CPPFLAGS="${CPPFLAGS} ${DBUS_CFLAGS}"
],[])
AC_DEFINE_UNQUOTED(HAVE_DBUS, $HAVE_dbus, Support dbus)
AC_SUBST(PC_NAME_DBUS)
check_systemdsystemunitdir() {
AC_MSG_CHECKING([which system unit file directory to use])
PKG_CHECK_VAR([systemdsystemunitdir], [systemd], [systemdsystemunitdir])
AC_MSG_RESULT([${systemdsystemunitdir}])
test x"$systemdsystemunitdir" != x""
return $?
}
AS_CASE([$enable_systemd],
[$REQUIRED], [
AS_IF([test $HAVE_dbus = 0],
[AC_MSG_FAILURE([Cannot support systemd resources without DBus])])
AS_IF([test "$ac_cv_have_decl_CLOCK_MONOTONIC" = "no"],
[AC_MSG_FAILURE([Cannot support systemd resources without monotonic clock])])
AS_IF([check_systemdsystemunitdir], [],
[AC_MSG_FAILURE([Cannot support systemd resources without systemdsystemunitdir])])
],
[$OPTIONAL], [
AS_IF([test $HAVE_dbus = 0 \
|| test x"$ac_cv_have_decl_CLOCK_MONOTONIC" = x"no"],
[enable_systemd=$DISABLED],
[
AC_MSG_CHECKING([for systemd version (using dbus-send)])
ret=$({ dbus-send --system --print-reply \
--dest=org.freedesktop.systemd1 \
/org/freedesktop/systemd1 \
org.freedesktop.DBus.Properties.Get \
string:org.freedesktop.systemd1.Manager \
string:Version 2>/dev/null \
|| echo "version unavailable"; } | tail -n1)
# sanitize output a bit (interested just in value, not type),
# ret is intentionally unenquoted so as to normalize whitespace
ret=$(echo ${ret} | cut -d' ' -f2-)
AC_MSG_RESULT([${ret}])
AS_IF([test x"$ret" != x"unavailable" \
|| systemctl --version 2>/dev/null | grep -q systemd],
[
AS_IF([check_systemdsystemunitdir],
[enable_systemd=$REQUIRED],
[enable_systemd=$DISABLED])
],
[enable_systemd=$DISABLED]
)
])
],
)
AC_MSG_CHECKING([whether to enable support for managing resources via systemd])
AS_IF([test $enable_systemd -eq $DISABLED], [AC_MSG_RESULT([no])],
[
AC_MSG_RESULT([yes])
PCMK_FEATURES="$PCMK_FEATURES systemd"
]
)
AC_SUBST([systemdsystemunitdir])
AC_DEFINE_UNQUOTED([SUPPORT_SYSTEMD], [$enable_systemd],
[Support systemd resources])
AM_CONDITIONAL([BUILD_SYSTEMD], [test $enable_systemd = $REQUIRED])
AC_SUBST(SUPPORT_SYSTEMD)
STACKS=""
CLUSTERLIBS=""
PC_NAME_CLUSTER=""
dnl ========================================================================
dnl Detect support for "service" alias
dnl ========================================================================
PCMK__ENABLE_SERVICE=$DISABLED
AM_COND_IF([BUILD_LSB], [PCMK__ENABLE_SERVICE=$REQUIRED])
AM_COND_IF([BUILD_SYSTEMD], [PCMK__ENABLE_SERVICE=$REQUIRED])
AS_IF([test $PCMK__ENABLE_SERVICE -ne $DISABLED],
[PCMK_FEATURES="$PCMK_FEATURES service"])
AC_SUBST(PCMK__ENABLE_SERVICE)
AC_DEFINE_UNQUOTED([PCMK__ENABLE_SERVICE], [$PCMK__ENABLE_SERVICE],
[Whether "service" is supported as an agent standard])
dnl ========================================================================
dnl Cluster stack - Corosync
dnl ========================================================================
COROSYNC_LIBS=""
AS_CASE([$with_corosync],
[$REQUIRED], [
# These will be fatal if unavailable
PKG_CHECK_MODULES([cpg], [libcpg])
PKG_CHECK_MODULES([cfg], [libcfg])
PKG_CHECK_MODULES([cmap], [libcmap])
PKG_CHECK_MODULES([quorum], [libquorum])
PKG_CHECK_MODULES([libcorosync_common], [libcorosync_common])
]
[$OPTIONAL], [
PKG_CHECK_MODULES([cpg], [libcpg], [], [with_corosync=$DISABLED])
PKG_CHECK_MODULES([cfg], [libcfg], [], [with_corosync=$DISABLED])
PKG_CHECK_MODULES([cmap], [libcmap], [], [with_corosync=$DISABLED])
PKG_CHECK_MODULES([quorum], [libquorum], [], [with_corosync=$DISABLED])
PKG_CHECK_MODULES([libcorosync_common], [libcorosync_common], [], [with_corosync=$DISABLED])
AS_IF([test $with_corosync -ne $DISABLED], [with_corosync=$REQUIRED])
]
)
AS_IF([test $with_corosync -ne $DISABLED],
[
AC_MSG_CHECKING([for Corosync 2 or later])
AC_MSG_RESULT([yes])
CFLAGS="$CFLAGS $libqb_CFLAGS $cpg_CFLAGS $cfg_CFLAGS $cmap_CFLAGS $quorum_CFLAGS $libcorosync_common_CFLAGS"
CPPFLAGS="$CPPFLAGS `$PKG_CONFIG --cflags-only-I corosync`"
COROSYNC_LIBS="$COROSYNC_LIBS $cpg_LIBS $cfg_LIBS $cmap_LIBS $quorum_LIBS $libcorosync_common_LIBS"
CLUSTERLIBS="$CLUSTERLIBS $COROSYNC_LIBS"
PC_NAME_CLUSTER="$PC_CLUSTER_NAME libcfg libcmap libcorosync_common libcpg libquorum"
STACKS="$STACKS corosync-ge-2"
dnl Shutdown tracking added (back) to corosync Jan 2021
saved_LIBS="$LIBS"
LIBS="$LIBS $COROSYNC_LIBS"
AC_CHECK_FUNCS([corosync_cfg_trackstart])
LIBS="$saved_LIBS"
]
)
AC_DEFINE_UNQUOTED([SUPPORT_COROSYNC], [$with_corosync],
[Support the Corosync messaging and membership layer])
AM_CONDITIONAL([BUILD_CS_SUPPORT], [test $with_corosync -eq $REQUIRED])
AC_SUBST([SUPPORT_COROSYNC])
dnl
dnl Cluster stack - Sanity
dnl
AS_IF([test x"$STACKS" != x""], [AC_MSG_NOTICE([Supported stacks:${STACKS}])],
[AC_MSG_FAILURE([At least one cluster stack must be supported])])
PCMK_FEATURES="${PCMK_FEATURES}${STACKS}"
AC_SUBST(CLUSTERLIBS)
AC_SUBST(PC_NAME_CLUSTER)
dnl ========================================================================
dnl CIB secrets
dnl ========================================================================
AS_IF([test $with_cibsecrets -ne $DISABLED],
[
with_cibsecrets=$REQUIRED
PCMK_FEATURES="$PCMK_FEATURES cibsecrets"
PCMK__CIB_SECRETS_DIR="${localstatedir}/lib/pacemaker/lrm/secrets"
AC_DEFINE_UNQUOTED([PCMK__CIB_SECRETS_DIR], ["$PCMK__CIB_SECRETS_DIR"],
[Location for CIB secrets])
AC_SUBST([PCMK__CIB_SECRETS_DIR])
]
)
AC_DEFINE_UNQUOTED([PCMK__ENABLE_CIBSECRETS], [$with_cibsecrets], [Support CIB secrets])
AM_CONDITIONAL([BUILD_CIBSECRETS], [test $with_cibsecrets -eq $REQUIRED])
dnl ========================================================================
dnl GnuTLS
dnl ========================================================================
PKG_CHECK_MODULES(GNUTLS, [gnutls >= 3.4.6],
[CPPFLAGS="${CPPFLAGS} ${GNUTLS_CFLAGS}"
LIBS="${LIBS} ${GNUTLS_LIBS}"])
# --- ASAN/UBSAN/TSAN (see man gcc) ---
# when using SANitizers, we need to pass the -fsanitize..
# to both CFLAGS and LDFLAGS. The CFLAGS/LDFLAGS must be
# specified as first in the list or there will be runtime
# issues (for example user has to LD_PRELOAD asan for it to work
# properly).
AS_IF([test -n "${SANITIZERS}"], [
SANITIZERS=$(echo $SANITIZERS | sed -e 's/,/ /g')
for SANITIZER in $SANITIZERS
do
AS_CASE([$SANITIZER],
[asan|ASAN], [
SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=address"
SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=address -lasan"
PCMK_FEATURES="$PCMK_FEATURES asan"
REQUIRE_LIB([asan],[main])
],
[ubsan|UBSAN], [
SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=undefined"
SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=undefined -lubsan"
PCMK_FEATURES="$PCMK_FEATURES ubsan"
REQUIRE_LIB([ubsan],[main])
],
[tsan|TSAN], [
SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=thread"
SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=thread -ltsan"
PCMK_FEATURES="$PCMK_FEATURES tsan"
REQUIRE_LIB([tsan],[main])
])
done
])
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.
AS_IF([export | fgrep " CFLAGS=" > /dev/null],
[
SAVED_CFLAGS="$CFLAGS"
unset CFLAGS
CFLAGS="$SAVED_CFLAGS"
unset SAVED_CFLAGS
])
CC_EXTRAS=""
AS_IF([test x"$GCC" != x"yes"], [CFLAGS="$CFLAGS -g"], [
CFLAGS="$CFLAGS -ggdb"
dnl When we don't have diagnostic push / pull, we can't explicitly disable
dnl checking for nonliteral formats in the places where they occur on purpose
dnl thus we disable nonliteral format checking globally as we are aborting
dnl on warnings.
dnl what makes the things really ugly is that nonliteral format checking is
dnl obviously available as an extra switch in very modern gcc but for older
dnl gcc this is part of -Wformat=2
dnl so if we have push/pull we can enable -Wformat=2 -Wformat-nonliteral
dnl if we don't have push/pull but -Wformat-nonliteral we can enable -Wformat=2
dnl otherwise none of both
gcc_diagnostic_push_pull=no
cc_temp_flags "$CFLAGS $WERROR"
AC_MSG_CHECKING([for gcc diagnostic push / pull])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#pragma GCC diagnostic push
#pragma GCC diagnostic pop
]])],
[
AC_MSG_RESULT([yes])
gcc_diagnostic_push_pull=yes
], AC_MSG_RESULT([no]))
cc_restore_flags
AS_IF([cc_supports_flag "-Wformat-nonliteral"],
[gcc_format_nonliteral=yes],
[gcc_format_nonliteral=no])
# We had to eliminate -Wnested-externs because of libtool changes
# Make sure to order options so that the former stand for prerequisites
# of the latter (e.g., -Wformat-nonliteral requires -Wformat).
EXTRA_FLAGS="-fgnu89-inline"
EXTRA_FLAGS="$EXTRA_FLAGS -Wall"
EXTRA_FLAGS="$EXTRA_FLAGS -Waggregate-return"
EXTRA_FLAGS="$EXTRA_FLAGS -Wbad-function-cast"
EXTRA_FLAGS="$EXTRA_FLAGS -Wcast-align"
EXTRA_FLAGS="$EXTRA_FLAGS -Wdeclaration-after-statement"
EXTRA_FLAGS="$EXTRA_FLAGS -Wendif-labels"
EXTRA_FLAGS="$EXTRA_FLAGS -Wfloat-equal"
EXTRA_FLAGS="$EXTRA_FLAGS -Wformat-security"
EXTRA_FLAGS="$EXTRA_FLAGS -Wimplicit-fallthrough"
EXTRA_FLAGS="$EXTRA_FLAGS -Wmissing-prototypes"
EXTRA_FLAGS="$EXTRA_FLAGS -Wmissing-declarations"
EXTRA_FLAGS="$EXTRA_FLAGS -Wnested-externs"
EXTRA_FLAGS="$EXTRA_FLAGS -Wno-long-long"
EXTRA_FLAGS="$EXTRA_FLAGS -Wno-strict-aliasing"
EXTRA_FLAGS="$EXTRA_FLAGS -Wpointer-arith"
EXTRA_FLAGS="$EXTRA_FLAGS -Wstrict-prototypes"
EXTRA_FLAGS="$EXTRA_FLAGS -Wwrite-strings"
EXTRA_FLAGS="$EXTRA_FLAGS -Wunused-but-set-variable"
EXTRA_FLAGS="$EXTRA_FLAGS -Wunsigned-char"
AS_IF([test x"$gcc_diagnostic_push_pull" = x"yes"],
[
AC_DEFINE([HAVE_FORMAT_NONLITERAL], [],
[gcc can complain about nonliterals in format])
EXTRA_FLAGS="$EXTRA_FLAGS -Wformat=2 -Wformat-nonliteral"
],
[test x"$gcc_format_nonliteral" = x"yes"],
[EXTRA_FLAGS="$EXTRA_FLAGS -Wformat=2"])
# Additional warnings it might be nice to enable one day
# -Wshadow
# -Wunreachable-code
for j in $EXTRA_FLAGS
do
AS_IF([cc_supports_flag $CC_EXTRAS $j], [CC_EXTRAS="$CC_EXTRAS $j"])
done
AC_MSG_NOTICE([Using additional gcc flags: ${CC_EXTRAS}])
])
dnl
dnl Hardening flags
dnl
dnl The prime control of whether to apply (targeted) hardening build flags and
dnl which ones is --{enable,disable}-hardening option passed to ./configure:
dnl
dnl --enable-hardening=try (default):
dnl depending on whether any of CFLAGS_HARDENED_EXE, LDFLAGS_HARDENED_EXE,
dnl CFLAGS_HARDENED_LIB or LDFLAGS_HARDENED_LIB environment variables
dnl (see below) is set and non-null, all these custom flags (even if not
dnl set) are used as are, otherwise the best effort is made to offer
dnl reasonably strong hardening in several categories (RELRO, PIE,
dnl "bind now", stack protector) according to what the selected toolchain
dnl can offer
dnl
dnl --enable-hardening:
dnl same effect as --enable-hardening=try when the environment variables
dnl in question are suppressed
dnl
dnl --disable-hardening:
dnl do not apply any targeted hardening measures at all
dnl
dnl The user-injected environment variables that regulate the hardening in
dnl default case are as follows:
dnl
dnl * CFLAGS_HARDENED_EXE, LDFLAGS_HARDENED_EXE
dnl compiler and linker flags (respectively) for daemon programs
dnl (pacemakerd, pacemaker-attrd, pacemaker-controld, pacemaker-execd,
dnl pacemaker-based, pacemaker-fenced, pacemaker-remoted,
dnl pacemaker-schedulerd)
dnl
dnl * CFLAGS_HARDENED_LIB, LDFLAGS_HARDENED_LIB
dnl compiler and linker flags (respectively) for libraries linked
dnl with the daemon programs
dnl
dnl Note that these are purposedly targeted variables (addressing particular
dnl targets all over the scattered Makefiles) and have no effect outside of
dnl the predestined scope (e.g., CLI utilities). For a global reach,
dnl use CFLAGS, LDFLAGS, etc. as usual.
dnl
dnl For guidance on the suitable flags consult, for instance:
dnl https://fedoraproject.org/wiki/Changes/Harden_All_Packages#Detailed_Harden_Flags_Description
dnl https://owasp.org/index.php/C-Based_Toolchain_Hardening#GCC.2FBinutils
dnl
AS_IF([test $enable_hardening -eq $OPTIONAL],
[
AS_IF([test "$(env | grep -Ec '^(C|LD)FLAGS_HARDENED_(EXE|LIB)=.')" = 0],
[enable_hardening=$REQUIRED],
[AC_MSG_NOTICE([Hardening: using custom flags from environment])]
)
],
[
unset CFLAGS_HARDENED_EXE
unset CFLAGS_HARDENED_LIB
unset LDFLAGS_HARDENED_EXE
unset LDFLAGS_HARDENED_LIB
]
)
AS_CASE([$enable_hardening],
[$DISABLED], [AC_MSG_NOTICE([Hardening: explicitly disabled])],
[$REQUIRED], [
CFLAGS_HARDENED_EXE=
CFLAGS_HARDENED_LIB=
LDFLAGS_HARDENED_EXE=
LDFLAGS_HARDENED_LIB=
relro=0
pie=0
bindnow=0
stackprot="none"
# daemons incl. libs: partial RELRO
flag="-Wl,-z,relro"
CC_CHECK_LDFLAGS(["${flag}"],
[
LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}"
LDFLAGS_HARDENED_LIB="${LDFLAGS_HARDENED_LIB} ${flag}"
relro=1
])
# daemons: PIE for both CFLAGS and LDFLAGS
AS_IF([cc_supports_flag -fPIE],
[
flag="-pie"
CC_CHECK_LDFLAGS(["${flag}"],
[
CFLAGS_HARDENED_EXE="${CFLAGS_HARDENED_EXE} -fPIE"
LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}"
pie=1
])
]
)
# daemons incl. libs: full RELRO if sensible + as-needed linking
# so as to possibly mitigate startup performance
# hit caused by excessive linking with unneeded
# libraries
AS_IF([test "${relro}" = 1 && test "${pie}" = 1],
[
flag="-Wl,-z,now"
CC_CHECK_LDFLAGS(["${flag}"],
[
LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}"
LDFLAGS_HARDENED_LIB="${LDFLAGS_HARDENED_LIB} ${flag}"
bindnow=1
])
]
)
AS_IF([test "${bindnow}" = 1],
[
flag="-Wl,--as-needed"
CC_CHECK_LDFLAGS(["${flag}"],
[
LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}"
LDFLAGS_HARDENED_LIB="${LDFLAGS_HARDENED_LIB} ${flag}"
])
])
# universal: prefer strong > all > default stack protector if possible
flag=
AS_IF([cc_supports_flag -fstack-protector-strong],
[
flag="-fstack-protector-strong"
stackprot="strong"
],
[cc_supports_flag -fstack-protector-all],
[
flag="-fstack-protector-all"
stackprot="all"
],
[cc_supports_flag -fstack-protector],
[
flag="-fstack-protector"
stackprot="default"
]
)
AS_IF([test -n "${flag}"], [CC_EXTRAS="${CC_EXTRAS} ${flag}"])
# universal: enable stack clash protection if possible
AS_IF([cc_supports_flag -fstack-clash-protection],
[
CC_EXTRAS="${CC_EXTRAS} -fstack-clash-protection"
AS_IF([test "${stackprot}" = "none"],
[stackprot="clash-only"],
[stackprot="${stackprot}+clash"]
)
]
)
# Log a summary
AS_IF([test "${relro}" = 1 || test "${pie}" = 1 || test x"${stackprot}" != x"none"],
[AC_MSG_NOTICE(m4_normalize([Hardening:
relro=${relro}
pie=${pie}
bindnow=${bindnow}
stackprot=${stackprot}]))
],
[AC_MSG_WARN([Hardening: no suitable features in the toolchain detected])]
)
],
)
CFLAGS="$SANITIZERS_CFLAGS $CFLAGS $CC_EXTRAS"
LDFLAGS="$SANITIZERS_LDFLAGS $LDFLAGS"
CFLAGS_HARDENED_EXE="$SANITIZERS_CFLAGS $CFLAGS_HARDENED_EXE"
LDFLAGS_HARDENED_EXE="$SANITIZERS_LDFLAGS $LDFLAGS_HARDENED_EXE"
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
AS_IF([test $enable_fatal_warnings -ne $DISABLED], [
AC_MSG_NOTICE([Enabling fatal compiler warnings])
CFLAGS="$CFLAGS $WERROR"
])
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(LOCALE)
dnl Options for cleaning up the compiler output
AS_IF([test $enable_quiet -ne $DISABLED],
[
AC_MSG_NOTICE([Suppressing make details])
QUIET_LIBTOOL_OPTS="--silent"
QUIET_MAKE_OPTS="-s" # POSIX compliant
],
[
QUIET_LIBTOOL_OPTS=""
QUIET_MAKE_OPTS=""
]
)
dnl Put the above variables to use
LIBTOOL="${LIBTOOL} --tag=CC \$(QUIET_LIBTOOL_OPTS)"
MAKEFLAGS="${MAKEFLAGS} ${QUIET_MAKE_OPTS}"
# Make features list available (sorted alphabetically, without leading space)
PCMK_FEATURES=`echo "$PCMK_FEATURES" | sed -e 's/^ //' -e 's/ /\n/g' | sort | xargs`
AC_DEFINE_UNQUOTED(CRM_FEATURES, "$PCMK_FEATURES", Set of enabled features)
AC_SUBST(PCMK_FEATURES)
AC_SUBST(CC)
AC_SUBST(MAKEFLAGS)
AC_SUBST(LIBTOOL)
AC_SUBST(QUIET_LIBTOOL_OPTS)
dnl Files we output that need to be executable
CONFIG_FILES_EXEC([agents/ocf/ClusterMon],
[agents/ocf/Dummy],
[agents/ocf/HealthCPU],
[agents/ocf/HealthIOWait],
[agents/ocf/HealthSMART],
[agents/ocf/Stateful],
[agents/ocf/SysInfo],
[agents/ocf/attribute],
[agents/ocf/controld],
[agents/ocf/ifspeed],
[agents/ocf/ping],
[agents/ocf/remote],
[agents/stonith/fence_legacy],
[agents/stonith/fence_watchdog],
[cts/cluster_test],
[cts/cts],
[cts/cts-attrd],
[cts/cts-cli],
[cts/cts-exec],
[cts/cts-fencing],
[cts/cts-lab],
[cts/cts-regression],
[cts/cts-scheduler],
[cts/cts-schemas],
[cts/benchmark/clubench],
[cts/support/LSBDummy],
[cts/support/cts-support],
[cts/support/fence_dummy],
[cts/support/pacemaker-cts-dummyd],
[doc/abi-check],
[maint/bumplibs],
[tools/cluster-clean],
[tools/cluster-helper],
[tools/crm_failcount],
[tools/crm_master],
[tools/crm_report],
[tools/crm_standby],
[tools/cibsecret],
[tools/pcmk_simtimes],
[xml/rng-helper])
dnl Other files we output
AC_CONFIG_FILES(Makefile \
agents/Makefile \
agents/alerts/Makefile \
agents/ocf/Makefile \
agents/stonith/Makefile \
cts/Makefile \
cts/benchmark/Makefile \
cts/scheduler/Makefile \
cts/scheduler/dot/Makefile \
cts/scheduler/exp/Makefile \
cts/scheduler/scores/Makefile \
cts/scheduler/stderr/Makefile \
cts/scheduler/summary/Makefile \
cts/scheduler/xml/Makefile \
cts/support/Makefile \
cts/support/pacemaker-cts-dummyd@.service \
daemons/Makefile \
daemons/attrd/Makefile \
daemons/based/Makefile \
daemons/controld/Makefile \
daemons/execd/Makefile \
daemons/execd/pacemaker_remote \
daemons/execd/pacemaker_remote.service \
daemons/fenced/Makefile \
daemons/pacemakerd/Makefile \
daemons/pacemakerd/pacemaker.service \
daemons/schedulerd/Makefile \
devel/Makefile \
doc/Doxyfile \
doc/Makefile \
doc/sphinx/Makefile \
etc/Makefile \
etc/init.d/pacemaker \
etc/logrotate.d/pacemaker \
etc/sysconfig/pacemaker \
include/Makefile \
include/crm/Makefile \
include/crm/cib/Makefile \
include/crm/common/Makefile \
include/crm/cluster/Makefile \
include/crm/fencing/Makefile \
include/crm/pengine/Makefile \
include/pcmki/Makefile \
lib/Makefile \
lib/cib/Makefile \
lib/cluster/Makefile \
lib/cluster/tests/Makefile \
lib/cluster/tests/cluster/Makefile \
lib/cluster/tests/cpg/Makefile \
lib/common/Makefile \
lib/common/tests/Makefile \
lib/common/tests/acl/Makefile \
lib/common/tests/actions/Makefile \
lib/common/tests/agents/Makefile \
lib/common/tests/cmdline/Makefile \
lib/common/tests/digest/Makefile \
lib/common/tests/flags/Makefile \
lib/common/tests/health/Makefile \
lib/common/tests/io/Makefile \
lib/common/tests/iso8601/Makefile \
lib/common/tests/lists/Makefile \
lib/common/tests/messages/Makefile \
lib/common/tests/nodes/Makefile \
lib/common/tests/nvpair/Makefile \
lib/common/tests/options/Makefile \
lib/common/tests/output/Makefile \
lib/common/tests/patchset/Makefile \
lib/common/tests/probes/Makefile \
lib/common/tests/procfs/Makefile \
lib/common/tests/resources/Makefile \
lib/common/tests/results/Makefile \
lib/common/tests/rules/Makefile \
lib/common/tests/scheduler/Makefile \
lib/common/tests/schemas/Makefile \
lib/common/tests/scores/Makefile \
lib/common/tests/strings/Makefile \
lib/common/tests/utils/Makefile \
lib/common/tests/xml/Makefile \
lib/common/tests/xml_comment/Makefile \
lib/common/tests/xml_element/Makefile \
lib/common/tests/xml_idref/Makefile \
lib/common/tests/xpath/Makefile \
lib/fencing/Makefile \
lib/libpacemaker.pc \
lib/lrmd/Makefile \
lib/pacemaker/Makefile \
lib/pacemaker/tests/Makefile \
lib/pacemaker/tests/pcmk_resource/Makefile \
lib/pacemaker/tests/pcmk_ticket/Makefile \
lib/pacemaker.pc \
lib/pacemaker-cib.pc \
lib/pacemaker-cluster.pc \
lib/pacemaker-fencing.pc \
lib/pacemaker-lrmd.pc \
lib/pacemaker-service.pc \
lib/pacemaker-pe_rules.pc \
lib/pacemaker-pe_status.pc \
lib/pengine/Makefile \
lib/pengine/tests/Makefile \
lib/pengine/tests/native/Makefile \
lib/pengine/tests/status/Makefile \
lib/pengine/tests/unpack/Makefile \
lib/pengine/tests/utils/Makefile \
lib/services/Makefile \
maint/Makefile \
po/Makefile.in \
python/Makefile \
python/setup.py \
python/pacemaker/Makefile \
python/pacemaker/_cts/Makefile \
python/pacemaker/_cts/tests/Makefile \
python/pacemaker/buildoptions.py \
python/tests/Makefile \
rpm/Makefile \
tests/Makefile \
tools/Makefile \
tools/crm_mon.service \
tools/report.collector \
tools/report.common \
xml/Makefile \
xml/pacemaker-schemas.pc \
)
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_NOTICE([])
AC_MSG_NOTICE([$PACKAGE configuration:])
AC_MSG_NOTICE([ Version = ${VERSION} (Build: $BUILD_VERSION)])
AC_MSG_NOTICE([ Features = ${PCMK_FEATURES}])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([ Prefix = ${prefix}])
AC_MSG_NOTICE([ Executables = ${sbindir}])
AC_MSG_NOTICE([ Man pages = ${mandir}])
AC_MSG_NOTICE([ Libraries = ${libdir}])
AC_MSG_NOTICE([ Header files = ${includedir}])
AC_MSG_NOTICE([ Arch-independent files = ${datadir}])
AC_MSG_NOTICE([ State information = ${localstatedir}])
AC_MSG_NOTICE([ System configuration = ${sysconfdir}])
AC_MSG_NOTICE([ OCF agents = ${PCMK_OCF_ROOT}])
AM_COND_IF([BUILD_LSB],
[AC_MSG_NOTICE([ LSB agents = ${INITDIR}])])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([ HA group name = ${CRM_DAEMON_GROUP}])
AC_MSG_NOTICE([ HA user name = ${CRM_DAEMON_USER}])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([ CFLAGS = ${CFLAGS}])
AC_MSG_NOTICE([ CFLAGS_HARDENED_EXE = ${CFLAGS_HARDENED_EXE}])
AC_MSG_NOTICE([ CFLAGS_HARDENED_LIB = ${CFLAGS_HARDENED_LIB}])
AC_MSG_NOTICE([ LDFLAGS_HARDENED_EXE = ${LDFLAGS_HARDENED_EXE}])
AC_MSG_NOTICE([ LDFLAGS_HARDENED_LIB = ${LDFLAGS_HARDENED_LIB}])
AC_MSG_NOTICE([ Libraries = ${LIBS}])
AC_MSG_NOTICE([ Stack Libraries = ${CLUSTERLIBS}])
AC_MSG_NOTICE([ Unix socket auth method = ${us_auth}])
diff --git a/mk/python.mk b/mk/python.mk
index 9e7dd173fc..6f543aeaf7 100644
--- a/mk/python.mk
+++ b/mk/python.mk
@@ -1,31 +1,31 @@
#
# Copyright 2024 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
.PHONY: pylint
pylint: $(PYCHECKFILES)
- PYTHONPATH=$(abs_top_builddir)/python \
+ PYTHONPATH=$(abs_top_builddir)/python:$(abs_top_builddir)/python/pacemaker/.libs \
pylint --rcfile $(top_srcdir)/python/pylintrc $(PYCHECKFILES)
# Disabled warnings:
# W503 - Line break occurred before a binary operator
# (newer versions of pyflake and PEP8 want line breaks after binary
# operators, but older versions still suggest before)
# E402 - Module level import not at top of file
# (pylint already warns about this, and we shouldn't need to add
# ignore pragmas for two tools)
# E501 - Line too long
# F401 - Imported but not used
# (pylint already warns about this, and we shouldn't need to add
# ignore pragmas for two tools)
#
# Disable docstrings warnings on unit tests.
.PHONY: pyflake
pyflake: $(PYCHECKFILES)
- PYTHONPATH=$(abs_top_builddir)/python \
+ PYTHONPATH=$(abs_top_builddir)/python:$(abs_top_builddir)/python/pacemaker/.libs \
flake8 --ignore=W503,E402,E501,F401 --per-file-ignores="tests/*:D100,D101,D102,D104" $(PYCHECKFILES)
diff --git a/python/Makefile.am b/python/Makefile.am
index 7d2508434f..aa6976a73f 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -1,25 +1,26 @@
#
-# Copyright 2023-2024 the Pacemaker project contributors
+# Copyright 2023-2025 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
include $(top_srcdir)/mk/common.mk
include $(top_srcdir)/mk/python.mk
EXTRA_DIST = pylintrc
SUBDIRS = pacemaker \
tests
PYCHECKFILES ?= $(SUBDIRS)
.PHONY: check-local
check-local:
if [ "x$(top_srcdir)" != "x$(top_builddir)" ]; then \
cp -r $(top_srcdir)/python/* $(abs_top_builddir)/python/; \
fi
- PYTHONPATH=$(top_builddir)/python $(PYTHON) -m unittest discover -v -s $(top_builddir)/python/tests
+ PYTHONPATH=$(top_builddir)/python:$(top_builddir)/python/pacemaker/.libs \
+ $(PYTHON) -m unittest discover -v -s $(top_builddir)/python/tests
diff --git a/python/pacemaker/Makefile.am b/python/pacemaker/Makefile.am
index 27e6d6888f..8e9e82347d 100644
--- a/python/pacemaker/Makefile.am
+++ b/python/pacemaker/Makefile.am
@@ -1,18 +1,27 @@
#
-# Copyright 2023-2024 the Pacemaker project contributors
+# Copyright 2023-2025 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
include $(top_srcdir)/mk/common.mk
+pyexec_LTLIBRARIES = _pcmksupport.la
+
+_pcmksupport_la_SOURCES = pcmksupport.c
+_pcmksupport_la_CPPFLAGS = $(PYTHON_CFLAGS)
+_pcmksupport_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version -export-symbols-regex PyInit__pcmksupport
+_pcmksupport_la_LIBADD = $(top_builddir)/lib/pacemaker/libpacemaker.la
+
pkgpython_PYTHON = __init__.py \
_library.py \
- exitstatus.py
+ exceptions.py \
+ exitstatus.py \
+ resource.py
nodist_pkgpython_PYTHON = buildoptions.py
SUBDIRS = _cts
diff --git a/python/pacemaker/__init__.py b/python/pacemaker/__init__.py
index e6b1b2a685..a4afbc90a8 100644
--- a/python/pacemaker/__init__.py
+++ b/python/pacemaker/__init__.py
@@ -1,7 +1,9 @@
"""API reference documentation for the `pacemaker` package."""
__copyright__ = "Copyright 2023-2024 the Pacemaker project contributors"
__license__ = "GNU Lesser General Public License version 2.1 or later (LGPLv2.1+)"
-from pacemaker.buildoptions import BuildOptions
-from pacemaker.exitstatus import ExitStatus
+from .buildoptions import BuildOptions
+from .exitstatus import ExitStatus
+from . import exceptions
+from . import resource
diff --git a/python/pacemaker/exceptions.py b/python/pacemaker/exceptions.py
new file mode 100644
index 0000000000..93e71918dd
--- /dev/null
+++ b/python/pacemaker/exceptions.py
@@ -0,0 +1,9 @@
+"""A module providing exceptions that can be raised by the Pacemaker module."""
+
+__all__ = ["PacemakerError"]
+__copyright__ = "Copyright 2025 the Pacemaker project contributors"
+__license__ = "GNU Lesser General Public License version 2.1 or later (LGPLv2.1+)"
+
+
+class PacemakerError(Exception):
+ """Base exception class for all Pacemaker errors."""
diff --git a/python/pacemaker/pcmksupport.c b/python/pacemaker/pcmksupport.c
new file mode 100644
index 0000000000..09c6ab2c4f
--- /dev/null
+++ b/python/pacemaker/pcmksupport.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2025 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU Lesser General Public License
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
+ */
+
+#include <Python.h>
+#include <libxml/tree.h>
+
+#include <pacemaker.h>
+
+/* This file defines a c-based low level module that wraps libpacemaker
+ * functions and returns python objects. This is necessary because most
+ * libpacemaker functions return an xmlNode **, which needs to be coerced
+ * through the PyCapsule type into something that libxml2's python
+ * bindings can work with.
+ */
+
+/* Base exception class for any errors in the _pcmksupport module */
+static PyObject *PacemakerError;
+
+PyMODINIT_FUNC PyInit__pcmksupport(void);
+
+static PyObject *
+py_list_standards(PyObject *self, PyObject *args)
+{
+ int rc;
+ xmlNodePtr xml = NULL;
+
+ if (!PyArg_ParseTuple(args, "")) {
+ return NULL;
+ }
+
+ rc = pcmk_list_standards(&xml);
+ if (rc != pcmk_rc_ok) {
+ PyErr_SetString(PacemakerError, pcmk_rc_str(rc));
+ return NULL;
+ }
+
+ return PyCapsule_New(xml, "xmlNodePtr", NULL);
+}
+
+static PyMethodDef pcmksupportMethods[] = {
+ { "list_standards", py_list_standards, METH_VARARGS, NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "_pcmksupport",
+ NULL,
+ -1,
+ pcmksupportMethods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PyMODINIT_FUNC
+PyInit__pcmksupport(void)
+{
+ PyObject *module = PyModule_Create(&moduledef);
+
+ if (module == NULL) {
+ return NULL;
+ }
+
+ /* Add the base exception to the module */
+ PacemakerError = PyErr_NewException("_pcmksupport.PacemakerError", NULL, NULL);
+
+ /* FIXME: When we can support Python >= 3.10, we can use PyModule_AddObjectRef */
+ if (PyModule_AddObject(module, "PacemakerError", PacemakerError) < 0) {
+ Py_XDECREF(PacemakerError);
+ return NULL;
+ }
+
+ return module;
+}
diff --git a/python/pacemaker/resource.py b/python/pacemaker/resource.py
new file mode 100644
index 0000000000..1abf1c2531
--- /dev/null
+++ b/python/pacemaker/resource.py
@@ -0,0 +1,22 @@
+"""A module for managing cluster resources."""
+
+__all__ = ["list_standards"]
+__copyright__ = "Copyright 2025 the Pacemaker project contributors"
+__license__ = "GNU Lesser General Public License version 2.1 or later (LGPLv2.1+)"
+
+import libxml2
+
+import _pcmksupport
+from pacemaker.exceptions import PacemakerError
+
+
+def list_standards():
+ """Return a list of supported resource standards."""
+ try:
+ xml = _pcmksupport.list_standards()
+ except _pcmksupport.PacemakerError as e:
+ raise PacemakerError(*e.args) from None
+
+ doc = libxml2.xmlDoc(xml)
+
+ return [item.getContent() for item in doc.xpathEval("/pacemaker-result/standards/item")]
diff --git a/python/pylintrc b/python/pylintrc
index 81f63fea95..644dd63120 100644
--- a/python/pylintrc
+++ b/python/pylintrc
@@ -1,558 +1,558 @@
# NOTE: Any line with CHANGED: describes something that we changed from the
# default pylintrc configuration.
[MAIN]
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Files or directories to be skipped. They should be base names, not
# paths.
ignore=CVS
# Add files or directories matching the regex patterns to the ignore-list. The
# regex matches against paths and can be in Posix or Windows format.
ignore-paths=
# Files or directories matching the regex patterns are skipped. The regex
# matches against base names, not paths.
ignore-patterns=^\.#
# Pickle collected data for later comparisons.
persistent=yes
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use.
jobs=1
# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
-extension-pkg-allow-list=
+extension-pkg-allow-list=_pcmksupport
# Minimum supported python version
# CHANGED
py-version = 3.6
# Control the amount of potential inferred values when inferring a single
# object. This can help the performance when dealing with large functions or
# complex, nested conditions.
limit-inference-results=100
# Specify a score threshold under which the program will exit with error.
fail-under=10.0
# Return non-zero exit code if any of these messages/categories are detected,
# even if score is above --fail-under value. Syntax same as enable. Messages
# specified are enabled, while categories only check already-enabled messages.
fail-on=
# Clear in-memory caches upon conclusion of linting. Useful if running pylint in
# a server-like mode.
clear-cache-post-run=no
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
# confidence=
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=
use-symbolic-message-instead,
useless-suppression,
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then re-enable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
# CHANGED
disable=R0801,
line-too-long,
too-few-public-methods,
too-many-arguments,
too-many-branches,
too-many-instance-attributes,
too-many-statements,
unrecognized-option,
useless-option-value
[REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html. You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text
# Tells whether to display a full report or only the messages
reports=no
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables 'fatal', 'error', 'warning', 'refactor', 'convention'
# and 'info', which contain the number of messages in each category, as
# well as 'statement', which is the total number of statements analyzed. This
# score is used by the global evaluation report (RP0004).
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=
# Activate the evaluation score.
score=yes
[LOGGING]
# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging
# The type of string formatting that logging methods do. `old` means using %
# formatting, `new` is for `{}` formatting.
logging-format-style=old
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
# CHANGED: Don't do anything about FIXME, XXX, or TODO
notes=
# Regular expression of note tags to take in consideration.
#notes-rgx=
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=6
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=yes
# Signatures are removed from the similarity computation
ignore-signatures=yes
[VARIABLES]
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
additional-builtins=
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,_cb
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of names allowed to shadow builtins
allowed-redefined-builtins=
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=100
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Maximum number of lines in a module
max-module-lines=2000
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
[BASIC]
# Good variable names which should always be accepted, separated by a comma
# CHANGED: Single variable names are handled by variable-rgx below, leaving
# _ here as the name for any variable that should be ignored.
good-names=_
# Good variable names regexes, separated by a comma. If names match any regex,
# they will always be accepted
good-names-rgxs=
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
# Bad variable names regexes, separated by a comma. If names match any regex,
# they will always be refused
bad-names-rgxs=
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
# Naming style matching correct function names.
function-naming-style=snake_case
# Regular expression matching correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming style matching correct variable names.
variable-naming-style=snake_case
# Regular expression matching correct variable names
# CHANGED: One letter variables are fine
variable-rgx=[a-z_][a-z0-9_]{,30}$
# Naming style matching correct constant names.
const-naming-style=UPPER_CASE
# Regular expression matching correct constant names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Naming style matching correct attribute names.
attr-naming-style=snake_case
# Regular expression matching correct attribute names
attr-rgx=[a-z_][a-z0-9_]{2,}$
# Naming style matching correct argument names.
argument-naming-style=snake_case
# Regular expression matching correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming style matching correct class attribute names.
class-attribute-naming-style=any
# Regular expression matching correct class attribute names
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Naming style matching correct class constant names.
class-const-naming-style=UPPER_CASE
# Regular expression matching correct class constant names. Overrides class-
# const-naming-style.
#class-const-rgx=
# Naming style matching correct inline iteration names.
inlinevar-naming-style=any
# Regular expression matching correct inline iteration names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Naming style matching correct class names.
class-naming-style=PascalCase
# Regular expression matching correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Naming style matching correct module names.
module-naming-style=snake_case
# Regular expression matching correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Naming style matching correct method names.
method-naming-style=snake_case
# Regular expression matching correct method names
method-rgx=[a-z_][a-z0-9_]{2,}$
# Regular expression matching correct type variable names
#typevar-rgx=
# Regular expression which should only match function or class names that do
# not require a docstring. Use ^(?!__init__$)_ to also check __init__.
no-docstring-rgx=__.*__
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
# List of decorators that define properties, such as abc.abstractproperty.
property-classes=abc.abstractproperty
[TYPECHECK]
# Regex pattern to define which classes are considered mixins if ignore-mixin-
# members is set to 'yes'
mixin-class-rgx=.*MixIn
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis). It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=SQLObject, optparse.Values, thread._local, _thread._local
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=REQUEST,acl_users,aq_parent,argparse.Namespace
# List of decorators that create context managers from functions, such as
# contextlib.contextmanager.
contextmanager-decorators=contextlib.contextmanager
# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
[SPELLING]
# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# List of comma separated words that should be considered directives if they
# appear and the beginning of a comment and should not be checked.
spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:,pragma:,# noinspection
# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=.pyenchant_pylint_custom_dict.txt
# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions=2
[DESIGN]
# Maximum number of arguments for function / method
max-args=10
# Maximum number of locals for function / method body
max-locals=25
# Maximum number of return / yield for function / method body
max-returns=11
# Maximum number of branch for function / method body
max-branches=27
# Maximum number of statements in function / method body
max-statements=100
# Maximum number of parents for a class (see R0901).
max-parents=7
# List of qualified class names to ignore when counting class parents (see R0901).
ignored-parents=
# Maximum number of attributes for a class (see R0902).
max-attributes=11
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=25
# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr=5
# Maximum number of statements in a try-block
max-try-statements = 14
# List of regular expressions of class ancestor names to
# ignore when counting public methods (see R0903).
exclude-too-few-public-methods=
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
# CHANGED: Remove setUp and __post_init__, add reset
defining-attr-methods=__init__,__new__,reset
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make
# Warn about protected attribute access inside special methods
check-protected-access-in-special-methods=no
[IMPORTS]
# List of modules that can be imported at any level, not just the top level
# one.
allow-any-import-level=
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,TERMIOS,Bastion,rexec
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
# Couples of modules and preferred modules, separated by a comma.
preferred-modules=
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=builtins.Exception
[TYPING]
# Set to ``no`` if the app / library does **NOT** need to support runtime
# introspection of type annotations. If you use type annotations
# **exclusively** for type checking of an application, you're probably fine.
# For libraries, evaluate if some users what to access the type hints at
# runtime first, e.g., through ``typing.get_type_hints``. Applies to Python
# versions 3.7 - 3.9
runtime-typing = no
[DEPRECATED_BUILTINS]
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,input
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=sys.exit,argparse.parse_error
[STRING]
# This flag controls whether inconsistent-quotes generates a warning when the
# character used as a quote delimiter is used inconsistently within a module.
check-quote-consistency=no
# This flag controls whether the implicit-str-concat should generate a warning
# on implicit string concatenation in sequences defined over several lines.
check-str-concat-over-line-jumps=no
[CODE_STYLE]
# Max line length for which to sill emit suggestions. Used to prevent optional
# suggestions which would get split by a code formatter (e.g., black). Will
# default to the setting for ``max-line-length``.
#max-line-length-suggestions=
diff --git a/rpm/pacemaker.spec.in b/rpm/pacemaker.spec.in
index 9072783aa8..9fcf19af86 100644
--- a/rpm/pacemaker.spec.in
+++ b/rpm/pacemaker.spec.in
@@ -1,813 +1,815 @@
#
# Copyright 2008-2025 the Pacemaker project contributors
#
# The version control history for this file may have further details.
#
# This source code is licensed under the GNU General Public License version 2
# or later (GPLv2+) WITHOUT ANY WARRANTY.
#
# User-configurable globals and defines to control package behavior
# (these should not test {with X} values, which are declared later)
## User and group to use for nonprivileged services
%global uname hacluster
%global gname haclient
## Where to install Pacemaker documentation
%if 0%{?suse_version}
%global pcmk_docdir %{_docdir}/%{name}-%{version}
%else
%if 0%{?rhel}
%global pcmk_docdir %{_docdir}/%{name}-doc
%else
%global pcmk_docdir %{_docdir}/%{name}
%endif
%endif
## GitHub entity that distributes source (for ease of using a fork)
%global github_owner ClusterLabs
## Where bug reports should be submitted
## Leave bug_url undefined to use ClusterLabs default, others define it here
## What to use as the OCF resource agent root directory
%global ocf_root %{_prefix}/lib/ocf
## Upstream pacemaker version, and its package version (specversion
## can be incremented to build packages reliably considered "newer"
## than previously built packages with the same pcmkversion)
%global pcmkversion X.Y.Z
%global specversion 1
## Upstream commit (full commit ID, abbreviated commit ID, or tag) to build
%global commit HEAD
## Since git v2.11, the extent of abbreviation is autoscaled by default
## (used to be constant of 7), so we need to convey it for non-tags, too.
%if 0%{?fedora} || (0%{?rhel} >= 9)
%global commit_abbrev 9
%else
%global commit_abbrev 7
%endif
# Define conditionals so that "rpmbuild --with <feature>" and
# "rpmbuild --without <feature>" can enable and disable specific features
## Add option for Linux-HA (stonith/external) fencing agent support
%if 0%{?suse_version}
%bcond_without linuxha
%else
%bcond_with linuxha
%endif
## Add option for whether to support storing sensitive information outside CIB
%if (0%{?fedora} && 0%{?fedora} <= 33) || (0%{?rhel} && 0%{?rhel} <= 8)
%bcond_with cibsecrets
%else
%bcond_without cibsecrets
%endif
## Add option to enable Native Language Support (experimental)
%bcond_with nls
## Add option to create binaries suitable for use with profiling tools
%bcond_with profiling
## Allow deprecated option to skip (or enable, on RHEL) documentation
%if 0%{?rhel}
%bcond_with doc
%else
%bcond_without doc
%endif
## Add option to default to start-up synchronization with SBD.
##
## If enabled, SBD *MUST* be built to default similarly, otherwise data
## corruption could occur. Building both Pacemaker and SBD to default
## to synchronization improves safety, without requiring higher-level tools
## to be aware of the setting or requiring users to modify configurations
## after upgrading to versions that support synchronization.
%if 0%{?rhel} && 0%{?rhel} > 8
%bcond_without sbd_sync
%else
%bcond_with sbd_sync
%endif
## Add option to prefix package version with "0."
## (so later "official" packages will be considered updates)
%bcond_with pre_release
## Add option to turn off hardening of libraries and daemon executables
%bcond_without hardening
# Define globals for convenient use later
## Workaround to use parentheses in other globals
%global lparen (
%global rparen )
## Whether this is a tagged release (final or release candidate)
%define tag_release %(c=%{commit}; case ${c} in Pacemaker-*%{rparen} echo 1 ;;
*%{rparen} echo 0 ;; esac)
## Portion of export/dist tarball name after "pacemaker-", and release version
%if 0%{tag_release}
%define archive_version %(c=%{commit}; echo ${c:10})
%define archive_github_url %{commit}#/%{name}-%{archive_version}.tar.gz
%define pcmk_release %(c=%{commit}; case $c in *-rc[[:digit:]]*%{rparen}
echo 0.%{specversion}.${c: -3} ;;
*%{rparen} echo %{specversion} ;; esac)
%else
%if "%{commit}" == "DIST"
%define archive_version %{pcmkversion}
%define archive_github_url %{archive_version}#/%{name}-%{pcmkversion}.tar.gz
%if %{with pre_release}
%define pcmk_release 0.%{specversion}
%else
%define pcmk_release %{specversion}
%endif
%else
%define archive_version %(c=%{commit}; echo ${c:0:%{commit_abbrev}})
%define archive_github_url %{archive_version}#/%{name}-%{archive_version}.tar.gz
%if %{with pre_release}
%define pcmk_release 0.%{specversion}.%{archive_version}.git
%else
%define pcmk_release %{specversion}.%{archive_version}.git
%endif
%endif
%endif
%if 0%{?fedora} || 0%{?rhel}
## Base GnuTLS cipher priorities (presumably only the initial, required keyword)
## overridable with "rpmbuild --define 'pcmk_gnutls_priorities PRIORITY-SPEC'"
%define gnutls_priorities %{?pcmk_gnutls_priorities}%{!?pcmk_gnutls_priorities:@SYSTEM}
%endif
## Different distros name certain packages differently
## (note: corosync libraries also differ, but all provide corosync-devel)
%if 0%{?suse_version}
%global pkgname_bzip2_devel libbz2-devel
%global pkgname_docbook_xsl docbook-xsl-stylesheets
%global pkgname_gettext gettext-tools
%global pkgname_shadow_utils shadow
%global pkgname_procps procps
%global pkgname_glue_libs libglue
%global pkgname_pcmk_libs lib%{name}3
%global hacluster_id 90
%else
%global pkgname_libtool_devel libtool-ltdl-devel
%global pkgname_libtool_devel_arch libtool-ltdl-devel%{?_isa}
%global pkgname_bzip2_devel bzip2-devel
%global pkgname_docbook_xsl docbook-style-xsl
%global pkgname_gettext gettext-devel
%global pkgname_shadow_utils shadow-utils
%global pkgname_procps procps-ng
%global pkgname_glue_libs cluster-glue-libs
%global pkgname_pcmk_libs %{name}-libs
%global hacluster_id 189
%endif
## Distro-specific configuration choices
### Default resource-stickiness to 1 when distro prefers that
%if 0%{?fedora} >= 35 || 0%{?rhel} >= 9
%global resource_stickiness --with-resource-stickiness-default=1
%endif
# Python-related definitions
## Turn off auto-compilation of Python files outside Python specific paths,
## so there's no risk that unexpected "__python" macro gets picked to do the
## RPM-native byte-compiling there (only "{_datadir}/pacemaker/tests" affected)
## -- distro-dependent tricks or automake's fallback to be applied there
%if %{defined _python_bytecompile_extra}
%global _python_bytecompile_extra 0
%else
### the statement effectively means no RPM-native byte-compiling will occur at
### all, so distro-dependent tricks for Python-specific packages to be applied
%global __os_install_post %(echo '%{__os_install_post}' | {
sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompile[[:space:]].*$!!g'; })
%endif
## Prefer Python 3 definitions explicitly, in case 2 is also available
%if %{defined __python3}
%global python_name python3
%global python_path %{__python3}
%define python_site %{?python3_sitelib}%{!?python3_sitelib:%(
%{python_path} -c 'from distutils.sysconfig import get_python_lib as gpl; print(gpl(1))' 2>/dev/null)}
%else
%if %{defined python_version}
%global python_name python%(echo %{python_version} | cut -d'.' -f1)
%define python_path %{?__python}%{!?__python:/usr/bin/%{python_name}}
%else
%global python_name python
%global python_path %{?__python}%{!?__python:/usr/bin/python%{?python_pkgversion}}
%endif
%define python_site %{?python_sitelib}%{!?python_sitelib:%(
%{python_name} -c 'from distutils.sysconfig import get_python_lib as gpl; print(gpl(1))' 2>/dev/null)}
%endif
# Keep sane profiling data if requested
%if %{with profiling}
## Disable -debuginfo package and stripping binaries/libraries
%define debug_package %{nil}
%endif
Name: pacemaker
Summary: Scalable High-Availability cluster resource manager
Version: %{pcmkversion}
Release: %{pcmk_release}%{?dist}
License: GPL-2.0-or-later AND LGPL-2.1-or-later
Url: https://www.clusterlabs.org/
# Example: https://codeload.github.com/ClusterLabs/pacemaker/tar.gz/e91769e
# will download pacemaker-e91769e.tar.gz
#
# The ending part starting with '#' is ignored by github but necessary for
# rpmbuild to know what the tar archive name is. (The downloaded file will be
# named correctly only for commit IDs, not tagged releases.)
#
# You can use "spectool -s 0 pacemaker.spec" (rpmdevtools) to show final URL.
Source0: https://codeload.github.com/%{github_owner}/%{name}/tar.gz/%{archive_github_url}
Requires: resource-agents
Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release}
Requires: %{name}-cluster-libs%{?_isa} = %{version}-%{release}
Requires: %{name}-cli = %{version}-%{release}
%if %{with linuxha}
Requires: %{python_name}-%{name} = %{version}-%{release}
%endif
%{?systemd_requires}
Requires: %{python_path}
BuildRequires: %{python_name}-devel
BuildRequires: %{python_name}-setuptools
+BuildRequires: %{python_name}-libxml2
# Pacemaker requires a minimum libqb functionality
Requires: libqb >= 1.0.1
BuildRequires: pkgconfig(libqb) >= 1.0.1
# Required basic build tools
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: coreutils
BuildRequires: findutils
BuildRequires: gcc
BuildRequires: grep
BuildRequires: libtool
%if %{defined pkgname_libtool_devel}
BuildRequires: %{?pkgname_libtool_devel}
%endif
BuildRequires: make
BuildRequires: pkgconfig >= 0.28
BuildRequires: sed
# Required for core functionality
BuildRequires: pkgconfig(glib-2.0) >= 2.42
BuildRequires: pkgconfig(gnutls) >= 3.4.6
BuildRequires: pkgconfig(libxml-2.0) >= 2.9.2
BuildRequires: pkgconfig(systemd)
BuildRequires: libxslt-devel
BuildRequires: pkgconfig(uuid)
BuildRequires: %{pkgname_bzip2_devel}
# Enables optional functionality
BuildRequires: pkgconfig(dbus-1) >= 1.5.12
BuildRequires: %{pkgname_docbook_xsl}
BuildRequires: help2man
BuildRequires: ncurses-devel
BuildRequires: pam-devel
BuildRequires: %{pkgname_gettext} >= 0.18
# Required for "make check"
BuildRequires: libcmocka-devel >= 1.1.0
BuildRequires: %{python_name}-psutil
Requires: corosync >= 2.0.0
BuildRequires: corosync-devel >= 2.0.0
%if %{with linuxha}
BuildRequires: %{pkgname_glue_libs}-devel
%endif
%if %{with doc}
BuildRequires: %{python_name}-sphinx
%endif
# Booth requires this
Provides: pacemaker-ticket-support = 2.0
Provides: pcmk-cluster-manager = %{version}-%{release}
Provides: pcmk-cluster-manager%{?_isa} = %{version}-%{release}
%description
Pacemaker is an advanced, scalable High-Availability cluster resource
manager.
It supports more than 16 node clusters with significant capabilities
for managing resources and dependencies.
It will run scripts at initialization, when machines go up or down,
when related resources fail and can be configured to periodically check
resource health.
Available rpmbuild rebuild options:
--with(out) : cibsecrets hardening linuxha nls pre_release profiling
%package cli
License: GPL-2.0-or-later AND LGPL-2.1-or-later
Summary: Command line tools for controlling Pacemaker clusters
Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release}
Recommends: pcmk-cluster-manager = %{version}-%{release}
# For crm_report
Recommends: tar
Recommends: bzip2
Requires: perl-TimeDate
Requires: %{pkgname_procps}
Requires: psmisc
Requires(post):coreutils
%description cli
Pacemaker is an advanced, scalable High-Availability cluster resource
manager.
The %{name}-cli package contains command line tools that can be used
to query and control the cluster from machines that may, or may not,
be part of the cluster.
%package -n %{pkgname_pcmk_libs}
License: GPL-2.0-or-later AND LGPL-2.1-or-later
Summary: Core Pacemaker libraries
Requires(pre): %{pkgname_shadow_utils}
Requires: %{name}-schemas = %{version}-%{release}
# sbd 1.4.0+ supports the libpe_status API for pe_working_set_t
Conflicts: sbd < 1.4.0
%description -n %{pkgname_pcmk_libs}
Pacemaker is an advanced, scalable High-Availability cluster resource
manager.
The %{pkgname_pcmk_libs} package contains shared libraries needed for cluster
nodes and those just running the CLI tools.
%package cluster-libs
License: GPL-2.0-or-later AND LGPL-2.1-or-later
Summary: Cluster Libraries used by Pacemaker
Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release}
%description cluster-libs
Pacemaker is an advanced, scalable High-Availability cluster resource
manager.
The %{name}-cluster-libs package contains cluster-aware shared
libraries needed for nodes that will form part of the cluster nodes.
%package -n %{python_name}-%{name}
License: LGPL-2.1-or-later
Summary: Python libraries for Pacemaker
Requires: %{python_path}
Requires: %{pkgname_pcmk_libs} = %{version}-%{release}
-BuildArch: noarch
%description -n %{python_name}-%{name}
Pacemaker is an advanced, scalable High-Availability cluster resource
manager.
The %{python_name}-%{name} package contains a Python library that can be used
to interface with Pacemaker.
%package remote
License: GPL-2.0-or-later AND LGPL-2.1-or-later
Summary: Pacemaker remote executor daemon for non-cluster nodes
Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release}
Requires: %{name}-cli = %{version}-%{release}
Requires: resource-agents
Requires: %{pkgname_procps}
%{?systemd_requires}
Provides: pcmk-cluster-manager = %{version}-%{release}
Provides: pcmk-cluster-manager%{?_isa} = %{version}-%{release}
%description remote
Pacemaker is an advanced, scalable High-Availability cluster resource
manager.
The %{name}-remote package contains the Pacemaker Remote daemon
which is capable of extending pacemaker functionality to remote
nodes not running the full corosync/cluster stack.
%package -n %{pkgname_pcmk_libs}-devel
License: GPL-2.0-or-later AND LGPL-2.1-or-later
Summary: Pacemaker development package
Requires: %{pkgname_pcmk_libs}%{?_isa} = %{version}-%{release}
Requires: %{name}-cluster-libs%{?_isa} = %{version}-%{release}
Requires: %{pkgname_bzip2_devel}%{?_isa}
Requires: corosync-devel >= 2.0.0
Requires: glib2-devel%{?_isa}
Requires: libqb-devel%{?_isa} >= 1.0.1
%if %{defined pkgname_libtool_devel_arch}
Requires: %{?pkgname_libtool_devel_arch}
%endif
Requires: libuuid-devel%{?_isa}
Requires: libxml2-devel%{?_isa} >= 2.9.2
Requires: libxslt-devel%{?_isa}
%description -n %{pkgname_pcmk_libs}-devel
Pacemaker is an advanced, scalable High-Availability cluster resource
manager.
The %{pkgname_pcmk_libs}-devel package contains headers and shared libraries
for developing tools for Pacemaker.
%package cts
License: GPL-2.0-or-later AND LGPL-2.1-or-later
Summary: Test framework for cluster-related technologies like Pacemaker
Requires: %{python_path}
Requires: %{pkgname_pcmk_libs} = %{version}-%{release}
Requires: %{name}-cli = %{version}-%{release}
Requires: %{python_name}-%{name} = %{version}-%{release}
Requires: %{pkgname_procps}
Requires: psmisc
Requires: %{python_name}-psutil
BuildArch: noarch
%if 0%{?fedora} || 0%{?rhel}
Requires: %{python_name}-systemd
%endif
%description cts
Test framework for cluster-related technologies like Pacemaker
%package doc
License: CC-BY-SA-4.0
Summary: Documentation for Pacemaker
BuildArch: noarch
%description doc
Documentation for Pacemaker.
Pacemaker is an advanced, scalable High-Availability cluster resource
manager.
%package schemas
License: GPL-2.0-or-later
Summary: Schemas and upgrade stylesheets for Pacemaker
BuildArch: noarch
%description schemas
Schemas and upgrade stylesheets for Pacemaker
Pacemaker is an advanced, scalable High-Availability cluster resource
manager.
%prep
%setup -q -n %{name}-%{archive_version}
%build
export systemdsystemunitdir=%{_unitdir}
%if %{with hardening}
# prefer distro-provided hardening flags in case they are defined
# through _hardening_{c,ld}flags macros, configure script will
# use its own defaults otherwise; if such hardenings are completely
# undesired, rpmbuild using "--without hardening"
# (or "--define '_without_hardening 1'")
export CFLAGS_HARDENED_EXE="%{?_hardening_cflags}"
export CFLAGS_HARDENED_LIB="%{?_hardening_cflags}"
export LDFLAGS_HARDENED_EXE="%{?_hardening_ldflags}"
export LDFLAGS_HARDENED_LIB="%{?_hardening_ldflags}"
%endif
./autogen.sh
%{configure} \
PYTHON=%{python_path} \
%{!?with_hardening: --disable-hardening} \
%{?with_profiling: --with-profiling} \
%{?with_cibsecrets: --with-cibsecrets} \
%{?with_nls: --enable-nls} \
%{?with_sbd_sync: --with-sbd-sync-default="true"} \
%{?gnutls_priorities: --with-gnutls-priorities="%{gnutls_priorities}"} \
%{?bug_url: --with-bug-url=%{bug_url}} \
%{?ocf_root: --with-ocfdir=%{ocf_root}} \
%{?resource_stickiness} \
--disable-static \
--with-initdir=%{_initrddir} \
--with-runstatedir=%{_rundir} \
--localstatedir=%{_var} \
--with-version=%{version}-%{release}
%if 0%{?suse_version}
sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool
sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
%endif
make %{_smp_mflags} V=1
pushd python
%py3_build
popd
%check
make %{_smp_mflags} check
-{ cts/cts-scheduler --run load-stopped-loop \
- && cts/cts-cli -V \
+{ PYTHONPATH=python/pacemaker/.libs \
+ cts/cts-scheduler --run load-stopped-loop \
+ && PYTHONPATH=python/pacemaker/.libs cts/cts-cli -V \
&& touch .CHECKED
} 2>&1 | sed 's/[fF]ail/faiil/g' # prevent false positives in rpmlint
[ -f .CHECKED ] && rm -f -- .CHECKED
%install
# skip automake-native Python byte-compilation, since RPM-native one (possibly
# distro-confined to Python-specific directories, which is currently the only
# relevant place, anyway) assures proper intrinsic alignment with wider system
# (such as with py_byte_compile macro, which is concurrent Fedora/EL specific)
make install \
DESTDIR=%{buildroot} V=1 docdir=%{pcmk_docdir} \
%{?_python_bytecompile_extra:%{?py_byte_compile:am__py_compile=true}}
pushd python
%py3_install
popd
mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/lib/rpm-state/%{name}
%if %{with nls}
%find_lang %{name}
%endif
# Don't package libtool archives
find %{buildroot} -name '*.la' -type f -print0 | xargs -0 rm -f
%post
%systemd_post pacemaker.service
%preun
%systemd_preun pacemaker.service
%postun
%systemd_postun_with_restart pacemaker.service
%pre remote
# Stop the service before anything is touched, and remember to restart
# it as one of the last actions (compared to using systemd_postun_with_restart,
# this avoids suicide when sbd is in use)
systemctl --quiet is-active pacemaker_remote
if [ $? -eq 0 ] ; then
mkdir -p %{_localstatedir}/lib/rpm-state/%{name}
touch %{_localstatedir}/lib/rpm-state/%{name}/restart_pacemaker_remote
systemctl stop pacemaker_remote >/dev/null 2>&1
else
rm -f %{_localstatedir}/lib/rpm-state/%{name}/restart_pacemaker_remote
fi
%post remote
%systemd_post pacemaker_remote.service
%preun remote
%systemd_preun pacemaker_remote.service
%postun remote
# This next line is a no-op, because we stopped the service earlier, but
# we leave it here because it allows us to revert to the standard behavior
# in the future if desired
%systemd_postun_with_restart pacemaker_remote.service
# Explicitly take care of removing the flag-file(s) upon final removal
if [ "$1" -eq 0 ] ; then
rm -f %{_localstatedir}/lib/rpm-state/%{name}/restart_pacemaker_remote
fi
%posttrans remote
if [ -e %{_localstatedir}/lib/rpm-state/%{name}/restart_pacemaker_remote ] ; then
systemctl start pacemaker_remote >/dev/null 2>&1
rm -f %{_localstatedir}/lib/rpm-state/%{name}/restart_pacemaker_remote
fi
%post cli
%systemd_post crm_mon.service
if [ "$1" -eq 2 ]; then
# Package upgrade, not initial install:
# Move any pre-2.0 logs to new location to ensure they get rotated
{ mv -fbS.rpmsave %{_var}/log/pacemaker.log* %{_var}/log/pacemaker \
|| mv -f %{_var}/log/pacemaker.log* %{_var}/log/pacemaker
} >/dev/null 2>/dev/null || :
fi
%preun cli
%systemd_preun crm_mon.service
%postun cli
%systemd_postun_with_restart crm_mon.service
%pre -n %{pkgname_pcmk_libs}
getent group %{gname} >/dev/null || groupadd -r %{gname} -g %{hacluster_id}
getent passwd %{uname} >/dev/null || useradd -r -g %{gname} -u %{hacluster_id} -s /sbin/nologin -c "cluster user" %{uname}
exit 0
%if %{defined ldconfig_scriptlets}
%ldconfig_scriptlets -n %{pkgname_pcmk_libs}
%ldconfig_scriptlets cluster-libs
%else
%post -n %{pkgname_pcmk_libs} -p /sbin/ldconfig
%postun -n %{pkgname_pcmk_libs} -p /sbin/ldconfig
%post cluster-libs -p /sbin/ldconfig
%postun cluster-libs -p /sbin/ldconfig
%endif
%files
###########################################################
%config(noreplace) %{_sysconfdir}/sysconfig/pacemaker
%config(noreplace) %{_sysconfdir}/logrotate.d/pacemaker
%{_sbindir}/pacemakerd
%{_unitdir}/pacemaker.service
%exclude %{_libexecdir}/pacemaker/cts-support
%exclude %{_sbindir}/pacemaker-remoted
%{_libexecdir}/pacemaker/*
%if %{with linuxha}
%{_sbindir}/fence_legacy
%endif
%{_sbindir}/fence_watchdog
%doc %{_mandir}/man7/pacemaker-based.*
%doc %{_mandir}/man7/pacemaker-controld.*
%doc %{_mandir}/man7/pacemaker-schedulerd.*
%doc %{_mandir}/man7/pacemaker-fenced.*
%doc %{_mandir}/man7/ocf_pacemaker_controld.*
%doc %{_mandir}/man7/ocf_pacemaker_remote.*
%if %{with linuxha}
%doc %{_mandir}/man8/fence_legacy.*
%endif
%doc %{_mandir}/man8/fence_watchdog.*
%doc %{_mandir}/man8/pacemakerd.*
%doc %{_datadir}/pacemaker/alerts
%license licenses/GPLv2
%doc COPYING
%doc ChangeLog.md
%dir %attr (750, %{uname}, %{gname}) %{_var}/lib/pacemaker/cib
%dir %attr (750, %{uname}, %{gname}) %{_var}/lib/pacemaker/pengine
%{ocf_root}/resource.d/pacemaker/controld
%{ocf_root}/resource.d/pacemaker/remote
%files cli
%dir %attr (750, root, %{gname}) %{_sysconfdir}/pacemaker
%config(noreplace) %{_sysconfdir}/sysconfig/crm_mon
%{_unitdir}/crm_mon.service
%{_sbindir}/attrd_updater
%{_sbindir}/cibadmin
%if %{with cibsecrets}
%{_sbindir}/cibsecret
%endif
%{_sbindir}/crm_attribute
%{_sbindir}/crm_diff
%{_sbindir}/crm_error
%{_sbindir}/crm_failcount
%{_sbindir}/crm_master
%{_sbindir}/crm_mon
%{_sbindir}/crm_node
%{_sbindir}/crm_resource
%{_sbindir}/crm_rule
%{_sbindir}/crm_standby
%{_sbindir}/crm_verify
%{_sbindir}/crmadmin
%{_sbindir}/iso8601
%{_sbindir}/crm_shadow
%{_sbindir}/crm_simulate
%{_sbindir}/crm_report
%{_sbindir}/crm_ticket
%{_sbindir}/stonith_admin
# "dirname" is owned by -schemas, which is a prerequisite
%{_datadir}/pacemaker/report.collector
%{_datadir}/pacemaker/report.common
# XXX "dirname" is not owned by any prerequisite
%{_datadir}/snmp/mibs/PCMK-MIB.txt
%exclude %{ocf_root}/resource.d/pacemaker/controld
%exclude %{ocf_root}/resource.d/pacemaker/remote
%dir %{ocf_root}
%dir %{ocf_root}/resource.d
%{ocf_root}/resource.d/pacemaker
%doc %{_mandir}/man7/*pacemaker*
%exclude %{_mandir}/man7/pacemaker-based.*
%exclude %{_mandir}/man7/pacemaker-controld.*
%exclude %{_mandir}/man7/pacemaker-schedulerd.*
%exclude %{_mandir}/man7/pacemaker-fenced.*
%exclude %{_mandir}/man7/ocf_pacemaker_controld.*
%exclude %{_mandir}/man7/ocf_pacemaker_remote.*
%doc %{_mandir}/man8/crm*.8.gz
%doc %{_mandir}/man8/attrd_updater.*
%doc %{_mandir}/man8/cibadmin.*
%if %{with cibsecrets}
%doc %{_mandir}/man8/cibsecret.*
%endif
%doc %{_mandir}/man8/iso8601.*
%doc %{_mandir}/man8/stonith_admin.*
%license licenses/GPLv2
%doc COPYING
%doc ChangeLog.md
%dir %attr (750, %{uname}, %{gname}) %{_var}/lib/pacemaker
%dir %attr (750, %{uname}, %{gname}) %{_var}/lib/pacemaker/blackbox
%dir %attr (750, %{uname}, %{gname}) %{_var}/lib/pacemaker/cores
%dir %attr (770, %{uname}, %{gname}) %{_var}/log/pacemaker
%dir %attr (770, %{uname}, %{gname}) %{_var}/log/pacemaker/bundles
%files -n %{pkgname_pcmk_libs} %{?with_nls:-f %{name}.lang}
%{_libdir}/libcib.so.*
%{_libdir}/liblrmd.so.*
%{_libdir}/libcrmservice.so.*
%{_libdir}/libcrmcommon.so.*
%{_libdir}/libpe_status.so.*
%{_libdir}/libpe_rules.so.*
%{_libdir}/libpacemaker.so.*
%{_libdir}/libstonithd.so.*
%license licenses/LGPLv2.1
%doc COPYING
%doc ChangeLog.md
%files cluster-libs
%{_libdir}/libcrmcluster.so.*
%license licenses/LGPLv2.1
%doc COPYING
%doc ChangeLog.md
%files -n %{python_name}-%{name}
+%{python3_sitearch}/_pcmksupport.so
%{python3_sitelib}/pacemaker/
%{python3_sitelib}/pacemaker-*.egg-info
%exclude %{python3_sitelib}/pacemaker/_cts/
%license licenses/LGPLv2.1
%doc COPYING
%doc ChangeLog.md
%files remote
%config(noreplace) %{_sysconfdir}/sysconfig/pacemaker
# state directory is shared between the subpackets
# let rpm take care of removing it once it isn't
# referenced anymore and empty
%ghost %dir %{_localstatedir}/lib/rpm-state/%{name}
%{_unitdir}/pacemaker_remote.service
%{_sbindir}/pacemaker-remoted
%{_mandir}/man8/pacemaker-remoted.*
%license licenses/GPLv2
%doc COPYING
%doc ChangeLog.md
%files doc
%doc %{pcmk_docdir}
%license licenses/CC-BY-SA-4.0
%files cts
%{python3_sitelib}/pacemaker/_cts/
%{_datadir}/pacemaker/tests
%{_libexecdir}/pacemaker/cts-support
%license licenses/GPLv2
%doc COPYING
%doc ChangeLog.md
%files -n %{pkgname_pcmk_libs}-devel
%{_includedir}/pacemaker
%{_libdir}/libcib.so
%{_libdir}/liblrmd.so
%{_libdir}/libcrmservice.so
%{_libdir}/libcrmcommon.so
%{_libdir}/libpe_status.so
%{_libdir}/libpe_rules.so
%{_libdir}/libpacemaker.so
%{_libdir}/libstonithd.so
%{_libdir}/libcrmcluster.so
%{_libdir}/pkgconfig/*pacemaker*.pc
%license licenses/LGPLv2.1
%doc COPYING
%doc ChangeLog.md
%files schemas
%license licenses/GPLv2
%dir %{_datadir}/pacemaker
%{_datadir}/pacemaker/*.rng
%{_datadir}/pacemaker/*.xsl
%{_datadir}/pacemaker/api
%{_datadir}/pacemaker/base
%{_datadir}/pkgconfig/pacemaker-schemas.pc
%changelog
* PACKAGE_DATE ClusterLabs <admin@clusterlabs.org> PACKAGE_VERSION
- See included ChangeLog.md file for details

File Metadata

Mime Type
text/x-diff
Expires
Mon, Apr 21, 6:11 PM (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1657344
Default Alt Text
(139 KB)

Event Timeline