diff --git a/.gitignore b/.gitignore index 8b46f4bcdc..cd80ba4d06 100644 --- a/.gitignore +++ b/.gitignore @@ -1,174 +1,176 @@ # Common \#* .\#* GPATH GRTAGS GTAGS TAGS Makefile Makefile.in .deps .libs *.pc *.pyc *.bz2 *.tar.gz *.rpm *.la *.lo *.o *~ *.gcda *.gcno # Autobuild aclocal.m4 autoconf autoheader autom4te.cache/ automake build.counter compile config.guess config.log config.status config.sub configure depcomp install-sh include/stamp-* libltdl.tar libtool libtool.m4 ltdl.m4 ltmain.sh missing py-compile m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 m4/lt~obsolete.m4 test-driver ylwrap # Configure targets Doxyfile coverage.sh cts/CTSvars.py cts/HBDummy cts/LSBDummy cts/benchmark/clubench cts/lxc_autogen.sh extra/logrotate/pacemaker include/config.h include/config.h.in include/crm_config.h lrmd/pacemaker_remote lrmd/pacemaker_remoted lrmd/pacemaker_remote.service mcp/pacemaker mcp/pacemaker.combined.upstart mcp/pacemaker.service mcp/pacemaker.upstart pengine/regression.core.sh publican.cfg shell/modules/help.py shell/modules/ra.py shell/modules/ui.py shell/modules/vars.py tools/cibsecret tools/coverage.sh tools/crm_error tools/crm_mon.service tools/crm_mon.upstart tools/crm_report tools/report.common lrmd/regression.py fencing/regression.py # Build targets *.7 *.7.xml *.7.html *.8 *.8.xml *.8.html attrd/attrd doc/*/en-US/images/*.png doc/*/tmp/** doc/*/publish cib/cib cib/cibmon cib/cibpipe crmd/atest crmd/crmd doc/api/* doc/Clusters_from_Scratch.txt doc/Pacemaker_Explained.txt doc/acls.html doc/crm_fencing.html doc/publican-catalog* fencing/stonith-test fencing/stonith_admin fencing/stonithd fencing/stonithd.xml lrmd/lrmd lrmd/lrmd_internal_ctl lrmd/lrmd_test mcp/pacemakerd pengine/pengine pengine/pengine.xml pengine/ptest shell/regression/testcases/confbasic-xml.filter scratch tools/attrd_updater tools/cibadmin tools/crm_attribute tools/crm_diff tools/crm_mon tools/crm_node tools/crm_resource tools/crm_shadow tools/crm_simulate tools/crm_uuid tools/crm_verify tools/crmadmin tools/iso8601 tools/crm_ticket tools/report.collector.1 xml/crm.dtd xml/pacemaker*.rng xml/versions.rng doc/shared/en-US/*.xml doc/Clusters_from_Scratch.build doc/Clusters_from_Scratch/en-US/Ap-*.xml doc/Clusters_from_Scratch/en-US/Ch-*.xml +doc/Pacemaker_Development.build +doc/Pacemaker_Development/en-US/Ch-*.xml doc/Pacemaker_Explained.build doc/Pacemaker_Explained/en-US/Ch-*.xml doc/Pacemaker_Explained/en-US/Ap-*.xml doc/Pacemaker_Remote.build doc/Pacemaker_Remote/en-US/Ch-*.xml lib/gnu/libgnu.a lib/gnu/stdalign.h *.coverity #Other mock HTML pacemaker*.spec pengine/.regression.failed.diff coverity-* compat_reports .ABI-build abi_dumps logs *.patch *.diff *.sed *.orig *.rej *.swp pengine/test10/shadow.* diff --git a/configure.ac b/configure.ac index 4beb8775c5..bf52507917 100644 --- a/configure.ac +++ b/configure.ac @@ -1,2115 +1,2116 @@ dnl dnl autoconf for Pacemaker dnl dnl License: GNU General Public License (GPL) dnl =============================================== dnl Bootstrap dnl =============================================== AC_PREREQ(2.59) dnl Suggested structure: dnl information on the package dnl checks for programs dnl checks for libraries dnl checks for header files dnl checks for types dnl checks for structures dnl checks for compiler characteristics dnl checks for library functions dnl checks for system services m4_include([version.m4]) AC_INIT([pacemaker], VERSION_NUMBER, [pacemaker@oss.clusterlabs.org], [pacemaker], PCMK_URL) dnl Workaround autoconf < 2.64 if test x"${PACKAGE_URL}" = x""; then AC_SUBST([PACKAGE_URL], PCMK_URL) fi PCMK_FEATURES="" HB_PKG=heartbeat AC_CONFIG_AUX_DIR(.) AC_CANONICAL_HOST dnl Where #defines go (e.g. `AC_CHECK_HEADERS' below) dnl dnl Internal header: include/config.h dnl - Contains ALL defines dnl - include/config.h.in is generated automatically by autoheader dnl - NOT to be included in any header files except lha_internal.h dnl (which is also not to be included in any other header files) dnl dnl External header: include/crm_config.h dnl - Contains a subset of defines checked here dnl - Manually edit include/crm_config.h.in to have configure include dnl new defines dnl - Should not include HAVE_* defines dnl - Safe to include anywhere AM_CONFIG_HEADER(include/config.h include/crm_config.h) ALL_LINGUAS="en fr" AC_ARG_WITH(version, [ --with-version=version Override package version (if you're a packager needing to pretend) ], [ PACKAGE_VERSION="$withval" ]) AC_ARG_WITH(pkg-name, [ --with-pkg-name=name Override package name (if you're a packager needing to pretend) ], [ PACKAGE_NAME="$withval" ]) dnl Older distros may need: AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION) AM_INIT_AUTOMAKE([foreign]) AC_DEFINE_UNQUOTED(PACEMAKER_VERSION, "$PACKAGE_VERSION", Current pacemaker version) PACKAGE_SERIES=`echo $PACKAGE_VERSION | awk -F. '{ print $1"."$2 }'` AC_SUBST(PACKAGE_SERIES) AC_SUBST(PACKAGE_VERSION) dnl automake >= 1.11 offers --enable-silent-rules for suppressing the output from dnl normal compilation. When a failure occurs, it will then display the full dnl command line dnl Wrap in m4_ifdef to avoid breaking on older platforms m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) dnl Example 2.4. Silent Custom Rule to Generate a File dnl %-bar.pc: %.pc dnl $(AM_V_GEN)$(LN_S) $(notdir $^) $@ CC_IN_CONFIGURE=yes export CC_IN_CONFIGURE LDD=ldd BUILD_ATOMIC_ATTRD=1 dnl ======================================================================== dnl Compiler characteristics dnl ======================================================================== AC_PROG_CC dnl Can force other with environment variable "CC". AM_PROG_CC_C_O AC_PROG_CC_STDC gl_EARLY gl_INIT AC_LIBTOOL_DLOPEN dnl Enable dlopen support... AC_LIBLTDL_CONVENIENCE dnl make libltdl a convenience lib AC_PROG_LIBTOOL AC_PROG_YACC AM_PROG_LEX AC_C_STRINGIZE AC_TYPE_SIZE_T AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) AC_STRUCT_TIMEZONE dnl =============================================== dnl Helpers dnl =============================================== cc_supports_flag() { local CFLAGS="-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 } try_extract_header_define() { AC_MSG_CHECKING(if $2 in $1 exists) Cfile=$srcdir/extract_define.$2.${$} printf "#include \n" > ${Cfile}.c printf "#include <%s>\n" $1 >> ${Cfile}.c printf "int main(int argc, char **argv) {\n" >> ${Cfile}.c printf "#ifdef %s\n" $2 >> ${Cfile}.c printf "printf(\"%%s\", %s);\n" $2 >> ${Cfile}.c printf "#endif \n return 0; }\n" >> ${Cfile}.c $CC $CFLAGS ${Cfile}.c -o ${Cfile} 2>/dev/null value= if test -x ${Cfile}; then value=`${Cfile} 2>/dev/null` fi if test x"${value}" == x""; then value=$3 AC_MSG_RESULT(default: $value) else AC_MSG_RESULT($value) fi printf $value rm -rf ${Cfile}.c ${Cfile} ${Cfile}.dSYM ${Cfile}.gcno } extract_header_define() { AC_MSG_CHECKING(for $2 in $1) Cfile=$srcdir/extract_define.$2.${$} printf "#include \n" > ${Cfile}.c printf "#include <%s>\n" $1 >> ${Cfile}.c printf "int main(int argc, char **argv) { printf(\"%%s\", %s); return 0; }\n" $2 >> ${Cfile}.c $CC $CFLAGS ${Cfile}.c -o ${Cfile} value=`${Cfile}` AC_MSG_RESULT($value) printf $value rm -rf ${Cfile}.c ${Cfile} ${Cfile}.dSYM ${Cfile}.gcno } dnl =============================================== dnl Configure Options dnl =============================================== dnl Some systems, like Solaris require a custom package name AC_ARG_WITH(pkgname, [ --with-pkgname=name name for pkg (typically for Solaris) ], [ PKGNAME="$withval" ], [ PKGNAME="LXHAhb" ], ) AC_SUBST(PKGNAME) AC_ARG_ENABLE([ansi], [ --enable-ansi force GCC to compile to ANSI/ANSI standard for older compilers. [default=no]]) AC_ARG_ENABLE([fatal-warnings], [ --enable-fatal-warnings very pedantic and fatal warnings for gcc [default=yes]]) AC_ARG_ENABLE([quiet], [ --enable-quiet Supress make output unless there is an error [default=no]]) AC_ARG_ENABLE([bundled-ltdl], [ --enable-bundled-ltdl Configure, build and install the standalone ltdl library bundled with ${PACKAGE} [default=no]]) LTDL_LIBS="" AC_ARG_ENABLE([no-stack], [ --enable-no-stack Only build the Policy Engine and pieces needed to support it [default=no]]) AC_ARG_ENABLE([upstart], [ --enable-upstart Do not build support for the Upstart init system [default=yes]]) AC_ARG_ENABLE([systemd], [ --enable-systemd Do not build support for the Systemd init system [default=yes]]) AC_ARG_ENABLE(hardening, [ --with-hardening Harden the resulting executables/libraries (best effort by default)], [ HARDENING="${enableval}" ], [ HARDENING=try ], ) AC_ARG_WITH(ais, [ --with-ais Support the Corosync messaging and membership layer ], [ SUPPORT_CS=$withval ], [ SUPPORT_CS=try ], ) AC_ARG_WITH(corosync, [ --with-corosync Support the Corosync messaging and membership layer ], [ SUPPORT_CS=$withval ] dnl initialized in AC_ARG_WITH(ais...) already, dnl don't reset to try if it was given as --without-ais ) AC_ARG_WITH(heartbeat, [ --with-heartbeat Support the Heartbeat messaging and membership layer ], [ SUPPORT_HEARTBEAT=$withval ], [ SUPPORT_HEARTBEAT=try ], ) AC_ARG_WITH(cman, [ --with-cman Support the consumption of membership and quorum from cman ], [ SUPPORT_CMAN=$withval ], [ SUPPORT_CMAN=try ], ) AC_ARG_WITH(cpg, [ --with-cs-quorum Support the consumption of membership and quorum from corosync ], [ SUPPORT_CS_QUORUM=$withval ], [ SUPPORT_CS_QUORUM=try ], ) AC_ARG_WITH(nagios, [ --with-nagios Support nagios remote monitoring ], [ SUPPORT_NAGIOS=$withval ], [ SUPPORT_NAGIOS=try ], ) AC_ARG_WITH(nagios-plugin-dir, [ --with-nagios-plugin-dir=DIR Directory for nagios plugins [${NAGIOS_PLUGIN_DIR}]], [ NAGIOS_PLUGIN_DIR="$withval" ] ) AC_ARG_WITH(nagios-metadata-dir, [ --with-nagios-metadata-dir=DIR Directory for nagios plugins metadata [${NAGIOS_METADATA_DIR}]], [ NAGIOS_METADATA_DIR="$withval" ] ) AC_ARG_WITH(snmp, [ --with-snmp Support the SNMP protocol ], [ SUPPORT_SNMP=$withval ], [ SUPPORT_SNMP=try ], ) AC_ARG_WITH(esmtp, [ --with-esmtp Support the sending mail notifications with the esmtp library ], [ SUPPORT_ESMTP=$withval ], [ SUPPORT_ESMTP=try ], ) AC_ARG_WITH(acl, [ --with-acl Support CIB ACL ], [ SUPPORT_ACL=$withval ], [ SUPPORT_ACL=yes ], ) AC_ARG_WITH(cibsecrets, [ --with-cibsecrets Support CIB secrets ], [ SUPPORT_CIBSECRETS=$withval ], [ SUPPORT_CIBSECRETS=no ], ) CSPREFIX="" AC_ARG_WITH(ais-prefix, [ --with-ais-prefix=DIR Prefix used when Corosync was installed [$prefix]], [ CSPREFIX=$withval ], [ CSPREFIX=$prefix ]) LCRSODIR="" AC_ARG_WITH(lcrso-dir, [ --with-lcrso-dir=DIR Corosync lcrso files. ], [ LCRSODIR="$withval" ]) INITDIR="" AC_ARG_WITH(initdir, [ --with-initdir=DIR directory for init (rc) scripts [${INITDIR}]], [ INITDIR="$withval" ]) SUPPORT_PROFILING=0 AC_ARG_WITH(profiling, [ --with-profiling Disable optimizations for effective profiling ], [ SUPPORT_PROFILING=$withval ]) AC_ARG_WITH(coverage, [ --with-coverage Disable optimizations for effective profiling ], [ SUPPORT_COVERAGE=$withval ]) PUBLICAN_BRAND="common" AC_ARG_WITH(brand, [ --with-brand=brand Brand to use for generated documentation (set empty for no docs) [$PUBLICAN_BRAND]], [ test x"$withval" = x"no" || PUBLICAN_BRAND="$withval" ]) AC_SUBST(PUBLICAN_BRAND) ASCIIDOC_CLI_TYPE="pcs" AC_ARG_WITH(doc-cli, [ --with-doc-cli=cli_type CLI type to use for generated documentation. [$ASCIIDOC_CLI_TYPE]], [ ASCIIDOC_CLI_TYPE="$withval" ]) AC_SUBST(ASCIIDOC_CLI_TYPE) CONFIGDIR="" AC_ARG_WITH(configdir, [ --with-configdir=DIR Directory for Pacemaker configuration file [${CONFIGDIR}]], [ CONFIGDIR="$withval" ] ) dnl =============================================== dnl General Processing dnl =============================================== AC_SUBST(HB_PKG) INIT_EXT="" echo Our Host OS: $host_os/$host AC_MSG_NOTICE(Sanitizing prefix: ${prefix}) case $prefix in NONE) prefix=/usr dnl Fix default variables - "prefix" variable if not specified if test "$localstatedir" = "\${prefix}/var"; then localstatedir="/var" fi if test "$sysconfdir" = "\${prefix}/etc"; then sysconfdir="/etc" fi ;; esac AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix}) case $exec_prefix in dnl For consistency with Heartbeat, map NONE->$prefix NONE) exec_prefix=$prefix;; prefix) exec_prefix=$prefix;; esac AC_MSG_NOTICE(Sanitizing ais_prefix: ${CSPREFIX}) case $CSPREFIX in dnl For consistency with Heartbeat, map NONE->$prefix NONE) CSPREFIX=$prefix;; prefix) CSPREFIX=$prefix;; esac AC_MSG_NOTICE(Sanitizing INITDIR: ${INITDIR}) case $INITDIR in prefix) INITDIR=$prefix;; "") AC_MSG_CHECKING(which init (rc) directory to use) for initdir in /etc/init.d /etc/rc.d/init.d /sbin/init.d \ /usr/local/etc/rc.d /etc/rc.d do if test -d $initdir then INITDIR=$initdir break fi done AC_MSG_RESULT($INITDIR);; esac AC_SUBST(INITDIR) AC_MSG_NOTICE(Sanitizing libdir: ${libdir}) case $libdir in dnl For consistency with Heartbeat, map NONE->$prefix prefix|NONE) AC_MSG_CHECKING(which lib directory to use) for aDir in lib64 lib do trydir="${exec_prefix}/${aDir}" if test -d ${trydir} then libdir=${trydir} break fi done AC_MSG_RESULT($libdir); ;; esac dnl Expand autoconf variables so that we don't end up with '${prefix}' dnl in #defines and python scripts dnl NOTE: Autoconf deliberately leaves them unexpanded to allow dnl make exec_prefix=/foo install dnl No longer being able to do this seems like no great loss to me... eval prefix="`eval echo ${prefix}`" eval exec_prefix="`eval echo ${exec_prefix}`" eval bindir="`eval echo ${bindir}`" eval sbindir="`eval echo ${sbindir}`" eval libexecdir="`eval echo ${libexecdir}`" eval datadir="`eval echo ${datadir}`" eval sysconfdir="`eval echo ${sysconfdir}`" eval sharedstatedir="`eval echo ${sharedstatedir}`" eval localstatedir="`eval echo ${localstatedir}`" eval libdir="`eval echo ${libdir}`" eval includedir="`eval echo ${includedir}`" eval oldincludedir="`eval echo ${oldincludedir}`" eval infodir="`eval echo ${infodir}`" eval mandir="`eval echo ${mandir}`" dnl Home-grown variables eval INITDIR="${INITDIR}" eval docdir="`eval echo ${docdir}`" if test x"${docdir}" = x""; then docdir=${datadir}/doc/${PACKAGE}-${VERSION} #docdir=${datadir}/doc/packages/${PACKAGE} fi AC_SUBST(docdir) if test x"${CONFIGDIR}" = x""; then CONFIGDIR="${sysconfdir}/sysconfig" fi AC_SUBST(CONFIGDIR) for j in prefix exec_prefix bindir sbindir libexecdir datadir sysconfdir \ sharedstatedir localstatedir libdir includedir oldincludedir infodir \ mandir INITDIR docdir CONFIGDIR do dirname=`eval echo '${'${j}'}'` if test ! -d "$dirname" then AC_MSG_WARN([$j directory ($dirname) does not exist!]) fi done dnl This OS-based decision-making is poor autotools practice; dnl feature-based mechanisms are strongly preferred. dnl dnl So keep this section to a bare minimum; regard as a "necessary evil". case "$host_os" in *bsd*) AC_DEFINE_UNQUOTED(ON_BSD, 1, Compiling for BSD platform) LIBS="-L/usr/local/lib" CPPFLAGS="$CPPFLAGS -I/usr/local/include" INIT_EXT=".sh" ;; *solaris*) AC_DEFINE_UNQUOTED(ON_SOLARIS, 1, Compiling for Solaris platform) ;; *linux*) AC_DEFINE_UNQUOTED(ON_LINUX, 1, Compiling for Linux platform) ;; darwin*) AC_DEFINE_UNQUOTED(ON_DARWIN, 1, Compiling for Darwin platform) LIBS="$LIBS -L${prefix}/lib" CFLAGS="$CFLAGS -I${prefix}/include" ;; esac dnl Eventually remove this if test "$cross_compiling" != "yes"; then CPPFLAGS="$CPPFLAGS -I${prefix}/include/heartbeat" fi AC_SUBST(INIT_EXT) AC_MSG_NOTICE(Host CPU: $host_cpu) case "$host_cpu" in ppc64|powerpc64) case $CFLAGS in *powerpc64*) ;; *) if test "$GCC" = yes; then CFLAGS="$CFLAGS -m64" fi ;; esac esac AC_MSG_CHECKING(which format is needed to print uint64_t) ac_save_CFLAGS=$CFLAGS CFLAGS="-Wall -Werror" AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [ #include #include #include ], [ int max = 512; uint64_t bignum = 42; char *buffer = malloc(max); const char *random = "random"; snprintf(buffer, max-1, "", bignum, random); fprintf(stderr, "Result: %s\n", buffer); ] )], [U64T="%lu"], [U64T="%llu"] ) CFLAGS=$ac_save_CFLAGS AC_MSG_RESULT($U64T) AC_DEFINE_UNQUOTED(U64T, "$U64T", Correct printf format for logging uint64_t) dnl =============================================== dnl Program Paths dnl =============================================== PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin" export PATH dnl Replacing AC_PROG_LIBTOOL with AC_CHECK_PROG because LIBTOOL dnl was NOT being expanded all the time thus causing things to fail. AC_CHECK_PROGS(LIBTOOL, glibtool libtool libtool15 libtool13) AM_PATH_PYTHON AC_CHECK_PROGS(MAKE, gmake make) AC_PATH_PROGS(HTML2TXT, lynx w3m) AC_PATH_PROGS(HELP2MAN, help2man) AC_PATH_PROGS(POD2MAN, pod2man, pod2man) AC_PATH_PROGS(ASCIIDOC, asciidoc) AC_PATH_PROGS(PUBLICAN, publican) AC_PATH_PROGS(INKSCAPE, inkscape) AC_PATH_PROGS(XSLTPROC, xsltproc) AC_PATH_PROGS(XMLCATALOG, xmlcatalog) AC_PATH_PROGS(FOP, fop) AC_PATH_PROGS(SSH, ssh, /usr/bin/ssh) AC_PATH_PROGS(SCP, scp, /usr/bin/scp) AC_PATH_PROGS(TAR, tar) AC_PATH_PROGS(MD5, md5) AC_PATH_PROGS(TEST, test) AC_PATH_PROGS(PKGCONFIG, pkg-config) AC_PATH_PROGS(XML2CONFIG, xml2-config) AC_PATH_PROGS(VALGRIND_BIN, valgrind, /usr/bin/valgrind) AC_DEFINE_UNQUOTED(VALGRIND_BIN, "$VALGRIND_BIN", Valgrind command) dnl Disable these until we decide if the stonith config file should be supported dnl AC_PATH_PROGS(BISON, bison) dnl AC_PATH_PROGS(FLEX, flex) dnl AC_PATH_PROGS(HAVE_YACC, $YACC) if test x"${LIBTOOL}" = x""; then AC_MSG_ERROR(You need (g)libtool installed in order to build ${PACKAGE}) fi if test x"${MAKE}" = x""; then AC_MSG_ERROR(You need (g)make installed in order to build ${PACKAGE}) fi AM_CONDITIONAL(BUILD_HELP, test x"${HELP2MAN}" != x"") if test x"${HELP2MAN}" != x""; then PCMK_FEATURES="$PCMK_FEATURES generated-manpages" fi MANPAGE_XSLT="" if test x"${XSLTPROC}" != x""; then AC_MSG_CHECKING(docbook to manpage transform) # 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') if test x"${MANPAGE_XSLT}" = x""; then DIRS=$(find "${datadir}" -name $(basename $(dirname ${DOCBOOK_XSL_PATH})) \ -type d | LC_ALL=C sort) XSLT=$(basename ${DOCBOOK_XSL_PATH}) for d in ${DIRS}; do if test -f "${d}/${XSLT}"; then MANPAGE_XSLT="${d}/${XSLT}" break fi done fi fi AC_MSG_RESULT($MANPAGE_XSLT) AC_SUBST(MANPAGE_XSLT) AM_CONDITIONAL(BUILD_XML_HELP, test x"${MANPAGE_XSLT}" != x"") if test x"${MANPAGE_XSLT}" != x""; then PCMK_FEATURES="$PCMK_FEATURES agent-manpages" fi AM_CONDITIONAL(BUILD_ASCIIDOC, test x"${ASCIIDOC}" != x"") if test x"${ASCIIDOC}" != x""; then PCMK_FEATURES="$PCMK_FEATURES ascii-docs" fi SUPPORT_STONITH_CONFIG=0 if test x"${HAVE_YACC}" != x"" -a x"${FLEX}" != x"" -a x"${BISON}" != x""; then SUPPORT_STONITH_CONFIG=1 PCMK_FEATURES="$PCMK_FEATURES st-conf" fi AM_CONDITIONAL(BUILD_STONITH_CONFIG, test $SUPPORT_STONITH_CONFIG = 1) AC_DEFINE_UNQUOTED(SUPPORT_STONITH_CONFIG, $SUPPORT_STONITH_CONFIG, Support a stand-alone stonith config file in addition to the CIB) publican_intree_brand=no if test x"${PUBLICAN_BRAND}" != x"" \ && test x"${PUBLICAN}" != x"" \ && test x"${INKSCAPE}" != x""; then dnl special handling for clusterlabs brand (possibly in-tree version used) test "${PUBLICAN_BRAND}" != "clusterlabs" \ || test -d /usr/share/publican/Common_Content/clusterlabs if test $? -ne 0; then dnl Unknown option: brand_dir vs. Option brand_dir requires an argument if ${PUBLICAN} build --brand_dir 2>&1 | grep -Eq 'brand_dir$'; then AC_MSG_WARN([Cannot use in-tree clusterlabs brand, resorting to common]) PUBLICAN_BRAND=common else publican_intree_brand=yes fi fi AC_MSG_NOTICE([Enabling Publican-generated documentation using ${PUBLICAN_BRAND} brand]) PCMK_FEATURES="$PCMK_FEATURES publican-docs" fi AM_CONDITIONAL([BUILD_DOCBOOK], [test x"${PUBLICAN_BRAND}" != x"" \ && test x"${PUBLICAN}" != x"" \ && test x"${INKSCAPE}" != x""]) AM_CONDITIONAL([PUBLICAN_INTREE_BRAND], [test x"${publican_intree_brand}" = x"yes"]) dnl ======================================================================== dnl checks for library functions to replace them dnl dnl NoSuchFunctionName: dnl is a dummy function which no system supplies. It is here to make dnl the system compile semi-correctly on OpenBSD which doesn't know dnl how to create an empty archive dnl dnl scandir: Only on BSD. dnl System-V systems may have it, but hidden and/or deprecated. dnl A replacement function is supplied for it. dnl dnl setenv: is some bsdish function that should also be avoided (use dnl putenv instead) dnl On the other hand, putenv doesn't provide the right API for the dnl code and has memory leaks designed in (sigh...) Fortunately this dnl A replacement function is supplied for it. dnl dnl strerror: returns a string that corresponds to an errno. dnl A replacement function is supplied for it. dnl dnl strnlen: is a gnu function similar to strlen, but safer. dnl We wrote a tolearably-fast replacement function for it. dnl dnl strndup: is a gnu function similar to strdup, but safer. dnl We wrote a tolearably-fast replacement function for it. AC_REPLACE_FUNCS(alphasort NoSuchFunctionName scandir setenv strerror strchrnul unsetenv strnlen strndup) dnl =============================================== dnl Libraries dnl =============================================== AC_CHECK_LIB(socket, socket) dnl -lsocket AC_CHECK_LIB(c, dlopen) dnl if dlopen is in libc... AC_CHECK_LIB(dl, dlopen) dnl -ldl (for Linux) AC_CHECK_LIB(rt, sched_getscheduler) dnl -lrt (for Tru64) AC_CHECK_LIB(gnugetopt, getopt_long) dnl -lgnugetopt ( if available ) AC_CHECK_LIB(pam, pam_start) dnl -lpam (if available) AC_CHECK_FUNCS([sched_setscheduler]) AC_CHECK_LIB(uuid, uuid_parse) dnl load the library if necessary AC_CHECK_FUNCS(uuid_unparse) dnl OSX ships uuid_* as standard functions AC_CHECK_HEADERS(uuid/uuid.h) if test "x$ac_cv_func_uuid_unparse" != xyes; then AC_MSG_ERROR(You do not have the libuuid development package installed) fi if test x"${PKGCONFIG}" = x""; then AC_MSG_ERROR(You need pkgconfig installed in order to build ${PACKAGE}) fi if $PKGCONFIG --exists glib-2.0 then GLIBCONFIG="$PKGCONFIG glib-2.0" else set -x echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH $PKGCONFIG --exists glib-2.0; echo $? $PKGCONFIG --cflags glib-2.0; echo $? $PKGCONFIG glib-2.0; echo $? set +x AC_MSG_ERROR(You need glib2-devel installed in order to build ${PACKAGE}) fi AC_MSG_RESULT(using $GLIBCONFIG) # # Where is dlopen? # if test "$ac_cv_lib_c_dlopen" = yes; then LIBADD_DL="" elif test "$ac_cv_lib_dl_dlopen" = yes; then LIBADD_DL=-ldl else LIBADD_DL=${lt_cv_dlopen_libs} fi if test "X$GLIBCONFIG" != X; then AC_MSG_CHECKING(for special glib includes: ) GLIBHEAD=`$GLIBCONFIG --cflags` AC_MSG_RESULT($GLIBHEAD) CPPFLAGS="$CPPFLAGS $GLIBHEAD" AC_MSG_CHECKING(for glib library flags) GLIBLIB=`$GLIBCONFIG --libs` AC_MSG_RESULT($GLIBLIB) LIBS="$LIBS $GLIBLIB" fi dnl FreeBSD needs -lcompat for ftime() used by lrmd.c AC_CHECK_LIB([compat], [ftime], [COMPAT_LIBS='-lcompat']) AC_SUBST(COMPAT_LIBS) dnl ======================================================================== dnl Headers dnl ======================================================================== AC_HEADER_STDC AC_CHECK_HEADERS(arpa/inet.h) AC_CHECK_HEADERS(asm/types.h) AC_CHECK_HEADERS(assert.h) AC_CHECK_HEADERS(auth-client.h) AC_CHECK_HEADERS(ctype.h) AC_CHECK_HEADERS(dirent.h) AC_CHECK_HEADERS(errno.h) AC_CHECK_HEADERS(fcntl.h) AC_CHECK_HEADERS(getopt.h) AC_CHECK_HEADERS(glib.h) AC_CHECK_HEADERS(grp.h) AC_CHECK_HEADERS(limits.h) AC_CHECK_HEADERS(linux/errqueue.h) AC_CHECK_HEADERS(linux/swab.h) AC_CHECK_HEADERS(malloc.h) AC_CHECK_HEADERS(netdb.h) AC_CHECK_HEADERS(netinet/in.h) AC_CHECK_HEADERS(netinet/ip.h) AC_CHECK_HEADERS(pam/pam_appl.h) AC_CHECK_HEADERS(pthread.h) AC_CHECK_HEADERS(pwd.h) AC_CHECK_HEADERS(security/pam_appl.h) AC_CHECK_HEADERS(sgtty.h) AC_CHECK_HEADERS(signal.h) AC_CHECK_HEADERS(stdarg.h) AC_CHECK_HEADERS(stddef.h) AC_CHECK_HEADERS(stdio.h) AC_CHECK_HEADERS(stdlib.h) AC_CHECK_HEADERS(string.h) AC_CHECK_HEADERS(strings.h) AC_CHECK_HEADERS(sys/dir.h) AC_CHECK_HEADERS(sys/ioctl.h) AC_CHECK_HEADERS(sys/param.h) AC_CHECK_HEADERS(sys/poll.h) AC_CHECK_HEADERS(sys/reboot.h) AC_CHECK_HEADERS(sys/resource.h) AC_CHECK_HEADERS(sys/select.h) AC_CHECK_HEADERS(sys/socket.h) AC_CHECK_HEADERS(sys/signalfd.h) AC_CHECK_HEADERS(sys/sockio.h) AC_CHECK_HEADERS(sys/stat.h) AC_CHECK_HEADERS(sys/time.h) AC_CHECK_HEADERS(sys/timeb.h) AC_CHECK_HEADERS(sys/types.h) AC_CHECK_HEADERS(sys/uio.h) AC_CHECK_HEADERS(sys/un.h) AC_CHECK_HEADERS(sys/utsname.h) AC_CHECK_HEADERS(sys/wait.h) AC_CHECK_HEADERS(time.h) AC_CHECK_HEADERS(unistd.h) AC_CHECK_HEADERS(winsock.h) dnl These headers need prerequisits before the tests will pass dnl AC_CHECK_HEADERS(net/if.h) dnl AC_CHECK_HEADERS(netinet/icmp6.h) dnl AC_CHECK_HEADERS(netinet/ip6.h) dnl AC_CHECK_HEADERS(netinet/ip_icmp.h) AC_MSG_CHECKING(for special libxml2 includes) if test "x$XML2CONFIG" = "x"; then AC_MSG_ERROR(libxml2 config not found) else XML2HEAD="`$XML2CONFIG --cflags`" AC_MSG_RESULT($XML2HEAD) AC_CHECK_LIB(xml2, xmlReadMemory) AC_CHECK_LIB(xslt, xsltApplyStylesheet) fi CPPFLAGS="$CPPFLAGS $XML2HEAD" AC_CHECK_HEADERS(libxml/xpath.h) AC_CHECK_HEADERS(libxslt/xslt.h) if test "$ac_cv_header_libxml_xpath_h" != "yes"; then AC_MSG_ERROR(The libxml developement headers were not found) fi if test "$ac_cv_header_libxslt_xslt_h" != "yes"; then AC_MSG_ERROR(The libxslt developement headers were not found) fi dnl ======================================================================== dnl Structures dnl ======================================================================== AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[[#include ]]) AC_CHECK_MEMBERS([lrm_op_t.rsc_deleted],,,[[#include ]]) AC_CHECK_MEMBER([struct dirent.d_type], AC_DEFINE(HAVE_STRUCT_DIRENT_D_TYPE,1,[Define this if struct dirent has d_type]),, [#include ]) dnl ======================================================================== dnl Functions dnl ======================================================================== AC_CHECK_FUNCS(g_log_set_default_handler) AC_CHECK_FUNCS(getopt, AC_DEFINE(HAVE_DECL_GETOPT, 1, [Have getopt function])) AC_CHECK_FUNCS(nanosleep, AC_DEFINE(HAVE_DECL_NANOSLEEP, 1, [Have nanosleep function])) dnl ======================================================================== dnl ltdl dnl ======================================================================== AC_CHECK_LIB(ltdl, lt_dlopen, [LTDL_foo=1]) if test "x${enable_bundled_ltdl}" = "xyes"; then if test $ac_cv_lib_ltdl_lt_dlopen = yes; then AC_MSG_NOTICE([Disabling usage of installed ltdl]) fi ac_cv_lib_ltdl_lt_dlopen=no fi LIBLTDL_DIR="" if test $ac_cv_lib_ltdl_lt_dlopen != yes ; then AC_MSG_NOTICE([Installing local ltdl]) LIBLTDL_DIR=libltdl ( cd $srcdir ; $TAR -xvf libltdl.tar ) if test "$?" -ne 0; then AC_MSG_ERROR([$TAR of libltdl.tar in $srcdir failed]) fi AC_CONFIG_SUBDIRS(libltdl) else LIBS="$LIBS -lltdl" AC_MSG_NOTICE([Using installed ltdl]) INCLTDL="" LIBLTDL="" fi AC_SUBST(INCLTDL) AC_SUBST(LIBLTDL) AC_SUBST(LIBLTDL_DIR) dnl ======================================================================== dnl bzip2 dnl ======================================================================== AC_CHECK_HEADERS(bzlib.h) AC_CHECK_LIB(bz2, BZ2_bzBuffToBuffCompress) if test x$ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress != xyes ; then AC_MSG_ERROR(BZ2 libraries not found) fi if test x$ac_cv_header_bzlib_h != xyes; then AC_MSG_ERROR(BZ2 Development headers not found) fi dnl ======================================================================== dnl sighandler_t is missing from Illumos, Solaris11 systems dnl ======================================================================== AC_MSG_CHECKING([for sighandler_t]) AC_TRY_COMPILE([#include ],[sighandler_t *f;], has_sighandler_t=yes,has_sighandler_t=no) AC_MSG_RESULT($has_sighandler_t) if test "$has_sighandler_t" = "yes" ; then AC_DEFINE( HAVE_SIGHANDLER_T, 1, [Define if sighandler_t available] ) fi dnl ======================================================================== dnl ncurses dnl ======================================================================== dnl dnl A few OSes (e.g. Linux) deliver a default "ncurses" alongside "curses". dnl Many non-Linux deliver "curses"; sites may add "ncurses". dnl dnl However, the source-code recommendation for both is to #include "curses.h" dnl (i.e. "ncurses" still wants the include to be simple, no-'n', "curses.h"). dnl dnl ncurse takes precedence. dnl AC_CHECK_HEADERS(curses.h) AC_CHECK_HEADERS(curses/curses.h) AC_CHECK_HEADERS(ncurses.h) AC_CHECK_HEADERS(ncurses/ncurses.h) dnl Although n-library is preferred, only look for it if the n-header was found. CURSESLIBS='' if test "$ac_cv_header_ncurses_h" = "yes"; then AC_CHECK_LIB(ncurses, printw, [AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)] ) CURSESLIBS=`$PKGCONFIG --libs ncurses` || CURSESLIBS='-lncurses' fi if test "$ac_cv_header_ncurses_ncurses_h" = "yes"; then AC_CHECK_LIB(ncurses, printw, [AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)] ) CURSESLIBS=`$PKGCONFIG --libs ncurses` || CURSESLIBS='-lncurses' fi dnl Only look for non-n-library if there was no n-library. if test X"$CURSESLIBS" = X"" -a "$ac_cv_header_curses_h" = "yes"; then AC_CHECK_LIB(curses, printw, [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)] ) fi dnl Only look for non-n-library if there was no n-library. if test X"$CURSESLIBS" = X"" -a "$ac_cv_header_curses_curses_h" = "yes"; then AC_CHECK_LIB(curses, printw, [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)] ) fi if test "x$CURSESLIBS" != "x"; then PCMK_FEATURES="$PCMK_FEATURES ncurses" fi dnl Check for printw() prototype compatibility if test X"$CURSESLIBS" != X"" && cc_supports_flag -Wcast-qual && cc_supports_flag -Werror; then ac_save_LIBS=$LIBS LIBS="$CURSESLIBS" ac_save_CFLAGS=$CFLAGS CFLAGS="-Wcast-qual -Werror" # avoid broken test because of hardened build environment in Fedora 23+ # - https://fedoraproject.org/wiki/Changes/Harden_All_Packages # - https://bugzilla.redhat.com/1297985 if cc_supports_flag -fPIC; then CFLAGS="$CFLAGS -fPIC" fi AC_MSG_CHECKING(whether printw() requires argument of "const char *") AC_LINK_IFELSE( [AC_LANG_PROGRAM( [ #if defined(HAVE_NCURSES_H) # include #elif defined(HAVE_NCURSES_NCURSES_H) # include #elif defined(HAVE_CURSES_H) # include #endif ], [printw((const char *)"Test");] )], [ac_cv_compatible_printw=yes], [ac_cv_compatible_printw=no] ) LIBS=$ac_save_LIBS CFLAGS=$ac_save_CFLAGS AC_MSG_RESULT([$ac_cv_compatible_printw]) if test "$ac_cv_compatible_printw" = no; then AC_MSG_WARN([The printw() function of your ncurses or curses library is old, we will disable usage of the library. If you want to use this library anyway, please update to newer version of the library, ncurses 5.4 or later is recommended. You can get the library from http://www.gnu.org/software/ncurses/.]) AC_MSG_NOTICE([Disabling curses]) AC_DEFINE(HAVE_INCOMPATIBLE_PRINTW, 1, [Do we have incompatible printw() in curses library?]) fi fi AC_SUBST(CURSESLIBS) dnl ======================================================================== dnl Profiling and GProf dnl ======================================================================== AC_MSG_NOTICE(Old CFLAGS: $CFLAGS) case $SUPPORT_COVERAGE in 1|yes|true) SUPPORT_PROFILING=1 PCMK_FEATURES="$PCMK_FEATURES coverage" CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage" dnl During linking, make sure to specify -lgcov or -coverage dnl Enable gprof #LIBS="$LIBS -pg" #CFLAGS="$CFLAGS -pg" ;; esac case $SUPPORT_PROFILING in 1|yes|true) SUPPORT_PROFILING=1 dnl Disable various compiler optimizations CFLAGS="$CFLAGS -fno-omit-frame-pointer -fno-inline -fno-builtin " dnl CFLAGS="$CFLAGS -fno-inline-functions -fno-default-inline -fno-inline-functions-called-once -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" dnl Update features PCMK_FEATURES="$PCMK_FEATURES profile" ;; *) SUPPORT_PROFILING=0;; esac AC_MSG_NOTICE(New CFLAGS: $CFLAGS) AC_DEFINE_UNQUOTED(SUPPORT_PROFILING, $SUPPORT_PROFILING, Support for profiling) dnl ======================================================================== dnl Cluster infrastructure - Heartbeat / LibQB dnl ======================================================================== dnl Compatibility checks AC_CHECK_MEMBERS([struct lrm_ops.fail_rsc],,,[[#include ]]) if test x${enable_no_stack} = xyes; then SUPPORT_HEARTBEAT=no SUPPORT_CS=no fi PKG_CHECK_MODULES(libqb, libqb >= 0.13, HAVE_libqb=1) CPPFLAGS="$libqb_CFLAGS $CPPFLAGS" LIBS="$libqb_LIBS $LIBS" AC_CHECK_HEADERS(qb/qbipc_common.h) AC_CHECK_LIB(qb, qb_ipcs_connection_auth_set) PCMK_FEATURES="$PCMK_FEATURES libqb-logging libqb-ipc" AC_CHECK_FUNCS(qb_ipcs_connection_get_buffer_size, AC_DEFINE(HAVE_IPCS_GET_BUFFER_SIZE, 1, [Have qb_ipcc_get_buffer_size function])) AC_CHECK_HEADERS(heartbeat/hb_config.h) AC_CHECK_HEADERS(heartbeat/glue_config.h) AC_CHECK_HEADERS(stonith/stonith.h) AC_CHECK_HEADERS(agent_config.h) GLUE_HEADER=none HAVE_GLUE=0 if test "$ac_cv_header_heartbeat_glue_config_h" = "yes"; then GLUE_HEADER=glue_config.h HAVE_GLUE=1 elif test "$ac_cv_header_heartbeat_hb_config_h" = "yes"; then GLUE_HEADER=hb_config.h HAVE_GLUE=1 else AC_MSG_WARN(cluster-glue development headers were not found) fi if test "$ac_cv_header_stonith_stonith_h" = "yes"; then PCMK_FEATURES="$PCMK_FEATURES lha-fencing" fi if test $HAVE_GLUE = 1; then dnl On Debian, AC_CHECK_LIBS fail if a library has any unresolved symbols dnl So check for all the dependencies (so they're added to LIBS) before checking for -lplumb AC_CHECK_LIB(pils, PILLoadPlugin) AC_CHECK_LIB(plumb, G_main_add_IPC_Channel) fi dnl =============================================== dnl Variables needed for substitution dnl =============================================== CRM_DTD_DIRECTORY="${datadir}/pacemaker" AC_DEFINE_UNQUOTED(CRM_DTD_DIRECTORY,"$CRM_DTD_DIRECTORY", Location for the Pacemaker Relax-NG Schema) AC_SUBST(CRM_DTD_DIRECTORY) CRM_CORE_DIR=`try_extract_header_define $GLUE_HEADER HA_COREDIR ${localstatedir}/lib/pacemaker/cores` AC_DEFINE_UNQUOTED(CRM_CORE_DIR,"$CRM_CORE_DIR", Location to store core files produced by Pacemaker daemons) AC_SUBST(CRM_CORE_DIR) CRM_DAEMON_USER=`try_extract_header_define $GLUE_HEADER HA_CCMUSER hacluster` AC_DEFINE_UNQUOTED(CRM_DAEMON_USER,"$CRM_DAEMON_USER", User to run Pacemaker daemons as) AC_SUBST(CRM_DAEMON_USER) CRM_DAEMON_GROUP=`try_extract_header_define $GLUE_HEADER HA_APIGROUP haclient` AC_DEFINE_UNQUOTED(CRM_DAEMON_GROUP,"$CRM_DAEMON_GROUP", Group to run Pacemaker daemons as) AC_SUBST(CRM_DAEMON_GROUP) CRM_STATE_DIR=${localstatedir}/run/crm AC_DEFINE_UNQUOTED(CRM_STATE_DIR,"$CRM_STATE_DIR", Where to keep state files and sockets) AC_SUBST(CRM_STATE_DIR) CRM_BLACKBOX_DIR=${localstatedir}/lib/pacemaker/blackbox AC_DEFINE_UNQUOTED(CRM_BLACKBOX_DIR,"$CRM_BLACKBOX_DIR", Where to keep blackbox dumps) AC_SUBST(CRM_BLACKBOX_DIR) PE_STATE_DIR="${localstatedir}/lib/pacemaker/pengine" AC_DEFINE_UNQUOTED(PE_STATE_DIR,"$PE_STATE_DIR", Where to keep PEngine outputs) AC_SUBST(PE_STATE_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_CONFIG_CTS="${localstatedir}/lib/pacemaker/cts" AC_DEFINE_UNQUOTED(CRM_CONFIG_CTS,"$CRM_CONFIG_CTS", Where to keep cts stateful data) AC_SUBST(CRM_CONFIG_CTS) CRM_LEGACY_CONFIG_DIR="${localstatedir}/lib/heartbeat/crm" AC_DEFINE_UNQUOTED(CRM_LEGACY_CONFIG_DIR,"$CRM_LEGACY_CONFIG_DIR", Where Pacemaker used to keep configuration files) AC_SUBST(CRM_LEGACY_CONFIG_DIR) CRM_DAEMON_DIR="${libexecdir}/pacemaker" AC_DEFINE_UNQUOTED(CRM_DAEMON_DIR,"$CRM_DAEMON_DIR", Location for Pacemaker daemons) AC_SUBST(CRM_DAEMON_DIR) HB_DAEMON_DIR=`try_extract_header_define $GLUE_HEADER HA_LIBHBDIR $libdir/heartbeat` AC_DEFINE_UNQUOTED(HB_DAEMON_DIR,"$HB_DAEMON_DIR", Location Heartbeat expects Pacemaker daemons to be in) AC_SUBST(HB_DAEMON_DIR) dnl Needed so that the Corosync plugin can clear out the directory as Heartbeat does HA_STATE_DIR=`try_extract_header_define $GLUE_HEADER HA_VARRUNDIR ${localstatedir}/run` AC_DEFINE_UNQUOTED(HA_STATE_DIR,"$HA_STATE_DIR", Where Heartbeat keeps state files and sockets) AC_SUBST(HA_STATE_DIR) CRM_RSCTMP_DIR=`try_extract_header_define agent_config.h HA_RSCTMPDIR $HA_STATE_DIR/resource-agents` AC_MSG_CHECKING(Scratch dir for resource agents) AC_MSG_RESULT($CRM_RSCTMP_DIR) AC_DEFINE_UNQUOTED(CRM_RSCTMP_DIR,"$CRM_RSCTMP_DIR", Where resource agents should keep state files) AC_SUBST(CRM_RSCTMP_DIR) dnl Needed for the location of hostcache in CTS.py HA_VARLIBHBDIR=`try_extract_header_define $GLUE_HEADER HA_VARLIBHBDIR ${localstatedir}/lib/heartbeat` AC_SUBST(HA_VARLIBHBDIR) AC_DEFINE_UNQUOTED(UUID_FILE,"$localstatedir/lib/heartbeat/hb_uuid", Location of Heartbeat's UUID file) OCF_ROOT_DIR=`try_extract_header_define $GLUE_HEADER OCF_ROOT_DIR /usr/lib/ocf` if test "X$OCF_ROOT_DIR" = X; then AC_MSG_ERROR(Could not locate OCF directory) fi AC_SUBST(OCF_ROOT_DIR) OCF_RA_DIR=`try_extract_header_define $GLUE_HEADER OCF_RA_DIR $OCF_ROOT_DIR/resource.d` AC_DEFINE_UNQUOTED(OCF_RA_DIR,"$OCF_RA_DIR", Location for OCF RAs) AC_SUBST(OCF_RA_DIR) RH_STONITH_DIR="$sbindir" AC_DEFINE_UNQUOTED(RH_STONITH_DIR,"$RH_STONITH_DIR", Location for Red Hat Stonith agents) RH_STONITH_PREFIX="fence_" AC_DEFINE_UNQUOTED(RH_STONITH_PREFIX,"$RH_STONITH_PREFIX", Prefix for Red Hat Stonith agents) AC_PATH_PROGS(GIT, git false) AC_MSG_CHECKING(build version) BUILD_VERSION=$Format:%h$ if test $BUILD_VERSION != ":%h$"; then AC_MSG_RESULT(archive hash: $BUILD_VERSION) elif test -x $GIT -a -d .git; then BUILD_VERSION=`$GIT log --pretty="format:%h" -n 1` AC_MSG_RESULT(git hash: $BUILD_VERSION) else # The current directory name make a reasonable default # Most generated archives will include the hash or tag BASE=`basename $PWD` BUILD_VERSION=`echo $BASE | sed s:.*[[Pp]]acemaker-::` AC_MSG_RESULT(directory based hash: $BUILD_VERSION) fi AC_DEFINE_UNQUOTED(BUILD_VERSION, "$BUILD_VERSION", Build version) AC_SUBST(BUILD_VERSION) HAVE_dbus=1 HAVE_upstart=0 HAVE_systemd=0 PKG_CHECK_MODULES(DBUS, dbus-1, ,HAVE_dbus=0) AC_DEFINE_UNQUOTED(SUPPORT_DBUS, $HAVE_dbus, Support dbus) AM_CONDITIONAL(BUILD_DBUS, test $HAVE_dbus = 1) if test $HAVE_dbus = 1; then CFLAGS="$CFLAGS `$PKGCONFIG --cflags dbus-1`" fi DBUS_LIBS="$CFLAGS `$PKGCONFIG --libs dbus-1`" AC_SUBST(DBUS_LIBS) AC_CHECK_TYPES([DBusBasicValue],,,[[#include ]]) if test $HAVE_dbus = 1 -a "x${enable_upstart}" != xno; then HAVE_upstart=1 PCMK_FEATURES="$PCMK_FEATURES upstart" fi AC_DEFINE_UNQUOTED(SUPPORT_UPSTART, $HAVE_upstart, Support upstart based system services) AM_CONDITIONAL(BUILD_UPSTART, test $HAVE_upstart = 1) AC_SUBST(SUPPORT_UPSTART) if $PKGCONFIG --exists systemd then systemdunitdir=`$PKGCONFIG --variable=systemdsystemunitdir systemd` AC_SUBST(systemdunitdir) else enable_systemd=no fi if test $HAVE_dbus = 1 -a "x${enable_systemd}" != xno; then if test -n "$systemdunitdir" -a "x$systemdunitdir" != xno; then HAVE_systemd=1 PCMK_FEATURES="$PCMK_FEATURES systemd" fi fi AC_DEFINE_UNQUOTED(SUPPORT_SYSTEMD, $HAVE_systemd, Support systemd based system services) AM_CONDITIONAL(BUILD_SYSTEMD, test $HAVE_systemd = 1) AC_SUBST(SUPPORT_SYSTEMD) case $SUPPORT_NAGIOS in 1|yes|true|try) SUPPORT_NAGIOS=1;; *) SUPPORT_NAGIOS=0;; esac if test $SUPPORT_NAGIOS = 1; then PCMK_FEATURES="$PCMK_FEATURES nagios" fi AC_DEFINE_UNQUOTED(SUPPORT_NAGIOS, $SUPPORT_NAGIOS, Support nagios plugins) AM_CONDITIONAL(BUILD_NAGIOS, test $SUPPORT_NAGIOS = 1) if test x"$NAGIOS_PLUGIN_DIR" = x""; then NAGIOS_PLUGIN_DIR="${libexecdir}/nagios/plugins" fi AC_DEFINE_UNQUOTED(NAGIOS_PLUGIN_DIR, "$NAGIOS_PLUGIN_DIR", Directory for nagios plugins) AC_SUBST(NAGIOS_PLUGIN_DIR) if test x"$NAGIOS_METADATA_DIR" = x""; then NAGIOS_METADATA_DIR="${datadir}/nagios/plugins-metadata" fi AC_DEFINE_UNQUOTED(NAGIOS_METADATA_DIR, "$NAGIOS_METADATA_DIR", Directory for nagios plugins metadata) AC_SUBST(NAGIOS_METADATA_DIR) STACKS="" CLUSTERLIBS="" dnl ======================================================================== dnl Cluster stack - Heartbeat dnl ======================================================================== case $SUPPORT_HEARTBEAT in 1|yes|true|try) AC_MSG_CHECKING(for heartbeat support) AC_CHECK_LIB(hbclient, ll_cluster_new, [SUPPORT_HEARTBEAT=1], [if test $SUPPORT_HEARTBEAT != try; then AC_MSG_FAILURE(Unable to support Heartbeat: client libraries not found) fi]) if test $SUPPORT_HEARTBEAT = 1 ; then STACKS="$STACKS heartbeat" dnl objdump -x ${libdir}/libccmclient.so | grep SONAME | awk '{print $2}' AC_DEFINE_UNQUOTED(CCM_LIBRARY, "libccmclient.so.1", Library to load for ccm support) AC_DEFINE_UNQUOTED(HEARTBEAT_LIBRARY, "libhbclient.so.1", Library to load for heartbeat support) BUILD_ATOMIC_ATTRD=0 else SUPPORT_HEARTBEAT=0 fi ;; *) SUPPORT_HEARTBEAT=0;; esac AM_CONDITIONAL(BUILD_HEARTBEAT_SUPPORT, test $SUPPORT_HEARTBEAT = 1) AC_DEFINE_UNQUOTED(SUPPORT_HEARTBEAT, $SUPPORT_HEARTBEAT, Support the Heartbeat messaging and membership layer) AC_SUBST(SUPPORT_HEARTBEAT) dnl ======================================================================== dnl Cluster stack - Corosync dnl ======================================================================== dnl Normalize the values case $SUPPORT_CS in 1|yes|true) SUPPORT_CS=yes missingisfatal=1;; try) missingisfatal=0;; *) SUPPORT_CS=no;; esac AC_MSG_CHECKING(for native corosync) COROSYNC_LIBS="" CS_USES_LIBQB=0 PCMK_SERVICE_ID=9 LCRSODIR="$libdir" if test $SUPPORT_CS = no; then AC_MSG_RESULT(no (disabled)) SUPPORT_CS=0 else AC_MSG_RESULT($SUPPORT_CS, with '$CSPREFIX') PKG_CHECK_MODULES(cpg, libcpg) dnl Fatal PKG_CHECK_MODULES(cfg, libcfg) dnl Fatal PKG_CHECK_MODULES(cmap, libcmap, HAVE_cmap=1, HAVE_cmap=0) PKG_CHECK_MODULES(cman, libcman, HAVE_cman=1, HAVE_cman=0) PKG_CHECK_MODULES(confdb, libconfdb, HAVE_confdb=1, HAVE_confdb=0) PKG_CHECK_MODULES(fenced, libfenced, HAVE_fenced=1, HAVE_fenced=0) PKG_CHECK_MODULES(quorum, libquorum, HAVE_quorum=1, HAVE_quorum=0) PKG_CHECK_MODULES(oldipc, libcoroipcc, HAVE_oldipc=1, HAVE_oldipc=0) if test $HAVE_oldipc = 1; then SUPPORT_CS=1 CFLAGS="$CFLAGS $oldipc_FLAGS $cpg_FLAGS $cfg_FLAGS" COROSYNC_LIBS="$COROSYNC_LIBS $oldipc_LIBS $cpg_LIBS $cfg_LIBS" elif test $HAVE_libqb = 1; then SUPPORT_CS=1 CS_USES_LIBQB=1 CFLAGS="$CFLAGS $libqb_FLAGS $cpg_FLAGS $cfg_FLAGS" COROSYNC_LIBS="$COROSYNC_LIBS $libqb_LIBS $cpg_LIBS $cfg_LIBS" AC_CHECK_LIB(corosync_common, cs_strerror) else aisreason="corosync/libqb IPC libraries not found by pkg_config" fi AC_DEFINE_UNQUOTED(HAVE_CONFDB, $HAVE_confdb, Have the old herarchial Corosync config API) AC_DEFINE_UNQUOTED(HAVE_CMAP, $HAVE_cmap, Have the new non-herarchial Corosync config API) fi if test $SUPPORT_CS = 1 -a x$HAVE_oldipc = x0 ; then dnl Support for plugins was removed about the time the IPC was dnl moved to libqb. dnl The only option now is the built-in quorum API CFLAGS="$CFLAGS $cmap_CFLAGS $quorum_CFLAGS" COROSYNC_LIBS="$COROSYNC_LIBS $cmap_LIBS $quorum_LIBS" STACKS="$STACKS corosync-native" AC_DEFINE_UNQUOTED(SUPPORT_CS_QUORUM, 1, Support the consumption of membership and quorum from corosync) fi SUPPORT_PLUGIN=0 if test $SUPPORT_CS = 1 -a x$HAVE_confdb = x1; then dnl Need confdb to support cman and the plugins SUPPORT_PLUGIN=1 BUILD_ATOMIC_ATTRD=0 LCRSODIR=`$PKGCONFIG corosync --variable=lcrsodir` STACKS="$STACKS corosync-plugin" COROSYNC_LIBS="$COROSYNC_LIBS $confdb_LIBS" if test $SUPPORT_CMAN != no; then if test $HAVE_cman = 1 -a $HAVE_fenced = 1; then SUPPORT_CMAN=1 STACKS="$STACKS cman" CFLAGS="$CFLAGS $cman_FLAGS $fenced_FLAGS" COROSYNC_LIBS="$COROSYNC_LIBS $cman_LIBS $fenced_LIBS" fi fi fi dnl Normalize SUPPORT_CS and SUPPORT_CMAN for use with #if directives if test $SUPPORT_CMAN != 1; then SUPPORT_CMAN=0 fi if test $SUPPORT_CS = 1; then CLUSTERLIBS="$CLUSTERLIBS $COROSYNC_LIBS" elif test $SUPPORT_CS != 0; then SUPPORT_CS=0 if test $missingisfatal = 0; then AC_MSG_WARN(Unable to support Corosync: $aisreason) else AC_MSG_FAILURE(Unable to support Corosync: $aisreason) fi fi AC_DEFINE_UNQUOTED(SUPPORT_COROSYNC, $SUPPORT_CS, Support the Corosync messaging and membership layer) AC_DEFINE_UNQUOTED(SUPPORT_CMAN, $SUPPORT_CMAN, Support the consumption of membership and quorum from cman) AC_DEFINE_UNQUOTED(CS_USES_LIBQB, $CS_USES_LIBQB, Does corosync use libqb for its ipc) AC_DEFINE_UNQUOTED(PCMK_SERVICE_ID, $PCMK_SERVICE_ID, Corosync service number) AC_DEFINE_UNQUOTED(SUPPORT_PLUGIN, $SUPPORT_PLUGIN, Support the Pacemaker plugin for Corosync) AM_CONDITIONAL(BUILD_CS_SUPPORT, test $SUPPORT_CS = 1) AM_CONDITIONAL(BUILD_CS_PLUGIN, test $SUPPORT_PLUGIN = 1) AM_CONDITIONAL(BUILD_CMAN, test $SUPPORT_CMAN = 1) AM_CONDITIONAL(BUILD_ATOMIC_ATTRD, test $BUILD_ATOMIC_ATTRD = 1) AC_DEFINE_UNQUOTED(HAVE_ATOMIC_ATTRD, $BUILD_ATOMIC_ATTRD, Support the new atomic attrd) AC_SUBST(SUPPORT_CMAN) AC_SUBST(SUPPORT_CS) AC_SUBST(SUPPORT_PLUGIN) dnl dnl Cluster stack - Sanity dnl if test x${enable_no_stack} = xyes; then AC_MSG_NOTICE(No cluster stack supported. Just building the Policy Engine) PCMK_FEATURES="$PCMK_FEATURES no-cluster-stack" else AC_MSG_CHECKING(for supported stacks) if test x"$STACKS" = x; then AC_MSG_FAILURE(You must support at least one cluster stack (heartbeat or corosync) ) fi AC_MSG_RESULT($STACKS) PCMK_FEATURES="$PCMK_FEATURES $STACKS" fi if test ${BUILD_ATOMIC_ATTRD} = 1; then PCMK_FEATURES="$PCMK_FEATURES atomic-attrd" fi AC_SUBST(CLUSTERLIBS) AC_SUBST(LCRSODIR) dnl ======================================================================== dnl SNMP dnl ======================================================================== case $SUPPORT_SNMP in 1|yes|true) missingisfatal=1;; try) missingisfatal=0;; *) SUPPORT_SNMP=no;; esac SNMPLIBS="" AC_MSG_CHECKING(for snmp support) if test $SUPPORT_SNMP = no; then AC_MSG_RESULT(no (disabled)) SUPPORT_SNMP=0 else SNMPCONFIG="" AC_MSG_RESULT($SUPPORT_SNMP) AC_CHECK_HEADERS(net-snmp/net-snmp-config.h) if test "x${ac_cv_header_net_snmp_net_snmp_config_h}" != "xyes"; then SUPPORT_SNMP="no" fi if test $SUPPORT_SNMP != no; then AC_PATH_PROGS(SNMPCONFIG, net-snmp-config) if test "X${SNMPCONFIG}" = "X"; then AC_MSG_RESULT(You need the net_snmp development package to continue.) SUPPORT_SNMP=no fi fi if test $SUPPORT_SNMP != no; then AC_MSG_CHECKING(for special snmp libraries) SNMPLIBS=`$SNMPCONFIG --agent-libs` AC_MSG_RESULT($SNMPLIBS) fi if test $SUPPORT_SNMP != no; then savedLibs=$LIBS LIBS="$LIBS $SNMPLIBS" dnl On many systems libcrypto is needed when linking against libsnmp. dnl Check to see if it exists, and if so use it. dnl AC_CHECK_LIB(crypto, CRYPTO_free, CRYPTOLIB="-lcrypto",) dnl AC_SUBST(CRYPTOLIB) AC_CHECK_FUNCS(netsnmp_transport_open_client) if test $ac_cv_func_netsnmp_transport_open_client != yes; then AC_CHECK_FUNCS(netsnmp_tdomain_transport) if test $ac_cv_func_netsnmp_tdomain_transport != yes; then SUPPORT_SNMP=no else AC_DEFINE_UNQUOTED(NETSNMPV53, 1, [Use the older 5.3 version of the net-snmp API]) fi fi LIBS=$savedLibs fi if test $SUPPORT_SNMP = no; then SNMPLIBS="" SUPPORT_SNMP=0 if test $missingisfatal = 0; then AC_MSG_WARN(Unable to support SNMP) else AC_MSG_FAILURE(Unable to support SNMP) fi else SUPPORT_SNMP=1 fi fi if test $SUPPORT_SNMP = 1; then PCMK_FEATURES="$PCMK_FEATURES snmp" fi AC_SUBST(SNMPLIBS) AM_CONDITIONAL(ENABLE_SNMP, test "$SUPPORT_SNMP" = "1") AC_DEFINE_UNQUOTED(ENABLE_SNMP, $SUPPORT_SNMP, Build in support for sending SNMP traps) dnl ======================================================================== dnl ESMTP dnl ======================================================================== case $SUPPORT_ESMTP in 1|yes|true) missingisfatal=1;; try) missingisfatal=0;; *) SUPPORT_ESMTP=no;; esac ESMTPLIB="" AC_MSG_CHECKING(for esmtp support) if test $SUPPORT_ESMTP = no; then AC_MSG_RESULT(no (disabled)) SUPPORT_ESMTP=0 else ESMTPCONFIG="" AC_MSG_RESULT($SUPPORT_ESMTP) AC_CHECK_HEADERS(libesmtp.h) if test "x${ac_cv_header_libesmtp_h}" != "xyes"; then ENABLE_ESMTP="no" fi if test $SUPPORT_ESMTP != no; then AC_PATH_PROGS(ESMTPCONFIG, libesmtp-config) if test "X${ESMTPCONFIG}" = "X"; then AC_MSG_RESULT(You need the libesmtp development package to continue.) SUPPORT_ESMTP=no fi fi if test $SUPPORT_ESMTP != no; then AC_MSG_CHECKING(for special esmtp libraries) ESMTPLIBS=`$ESMTPCONFIG --libs | tr '\n' ' '` AC_MSG_RESULT($ESMTPLIBS) fi if test $SUPPORT_ESMTP = no; then SUPPORT_ESMTP=0 if test $missingisfatal = 0; then AC_MSG_WARN(Unable to support ESMTP) else AC_MSG_FAILURE(Unable to support ESMTP) fi else SUPPORT_ESMTP=1 PCMK_FEATURES="$PCMK_FEATURES libesmtp" fi fi AC_SUBST(ESMTPLIBS) AM_CONDITIONAL(ENABLE_ESMTP, test "$SUPPORT_ESMTP" = "1") AC_DEFINE_UNQUOTED(ENABLE_ESMTP, $SUPPORT_ESMTP, Build in support for sending mail notifications with ESMTP) dnl ======================================================================== dnl ACL dnl ======================================================================== case $SUPPORT_ACL in 1|yes|true) missingisfatal=1;; try) missingisfatal=0;; *) SUPPORT_ACL=no;; esac AC_MSG_CHECKING(for acl support) if test $SUPPORT_ACL = no; then AC_MSG_RESULT(no (disabled)) SUPPORT_ACL=0 else AC_MSG_RESULT($SUPPORT_ACL) SUPPORT_ACL=1 AC_CHECK_LIB(qb, qb_ipcs_connection_auth_set) if test $ac_cv_lib_qb_qb_ipcs_connection_auth_set != yes; then SUPPORT_ACL=0 fi if test $SUPPORT_ACL = 0; then if test $missingisfatal = 0; then AC_MSG_WARN(Unable to support ACL. You need to use libqb > 0.13.0) else AC_MSG_FAILURE(Unable to support ACL. You need to use libqb > 0.13.0) fi fi fi if test $SUPPORT_ACL = 1; then PCMK_FEATURES="$PCMK_FEATURES acls" fi AM_CONDITIONAL(ENABLE_ACL, test "$SUPPORT_ACL" = "1") AC_DEFINE_UNQUOTED(ENABLE_ACL, $SUPPORT_ACL, Build in support for CIB ACL) dnl ======================================================================== dnl CIB secrets dnl ======================================================================== case $SUPPORT_CIBSECRETS in 1|yes|true|try) SUPPORT_CIBSECRETS=1;; *) SUPPORT_CIBSECRETS=0;; esac AC_DEFINE_UNQUOTED(SUPPORT_CIBSECRETS, $SUPPORT_CIBSECRETS, Support CIB secrets) AM_CONDITIONAL(BUILD_CIBSECRETS, test $SUPPORT_CIBSECRETS = 1) if test $SUPPORT_CIBSECRETS = 1; then PCMK_FEATURES="$PCMK_FEATURES cibsecrets" LRM_CIBSECRETS_DIR="${localstatedir}/lib/pacemaker/lrm/secrets" AC_DEFINE_UNQUOTED(LRM_CIBSECRETS_DIR,"$LRM_CIBSECRETS_DIR", Location for CIB secrets) AC_SUBST(LRM_CIBSECRETS_DIR) LRM_LEGACY_CIBSECRETS_DIR="${localstatedir}/lib/heartbeat/lrm/secrets" AC_DEFINE_UNQUOTED(LRM_LEGACY_CIBSECRETS_DIR,"$LRM_LEGACY_CIBSECRETS_DIR", Legacy location for CIB secrets) AC_SUBST(LRM_LEGACY_CIBSECRETS_DIR) fi dnl ======================================================================== dnl GnuTLS dnl ======================================================================== AC_CHECK_HEADERS(gnutls/gnutls.h) AC_CHECK_HEADERS(security/pam_appl.h pam/pam_appl.h) dnl GNUTLS library: Attempt to determine by 'libgnutls-config' program. dnl If no 'libgnutls-config', try traditional autoconf means. AC_PATH_PROGS(LIBGNUTLS_CONFIG, libgnutls-config) if test -n "$LIBGNUTLS_CONFIG"; then AC_MSG_CHECKING(for gnutls header flags) GNUTLSHEAD="`$LIBGNUTLS_CONFIG --cflags`"; AC_MSG_RESULT($GNUTLSHEAD) AC_MSG_CHECKING(for gnutls library flags) GNUTLSLIBS="`$LIBGNUTLS_CONFIG --libs`"; AC_MSG_RESULT($GNUTLSLIBS) fi AC_CHECK_LIB(gnutls, gnutls_init) AC_CHECK_FUNCS(gnutls_priority_set_direct) AC_SUBST(GNUTLSHEAD) AC_SUBST(GNUTLSLIBS) dnl ======================================================================== dnl System Health dnl ======================================================================== dnl Check if servicelog development package is installed SERVICELOG=servicelog-1 SERVICELOG_EXISTS="no" AC_MSG_CHECKING(for $SERVICELOG packages) if $PKGCONFIG --exists $SERVICELOG then PKG_CHECK_MODULES([SERVICELOG], [servicelog-1]) SERVICELOG_EXISTS="yes" fi AC_MSG_RESULT($SERVICELOG_EXISTS) AM_CONDITIONAL(BUILD_SERVICELOG, test "$SERVICELOG_EXISTS" = "yes") dnl Check if OpenIMPI packages and servicelog are installed OPENIPMI="OpenIPMI OpenIPMIposix" OPENIPMI_SERVICELOG_EXISTS="no" AC_MSG_CHECKING(for $SERVICELOG $OPENIPMI packages) if $PKGCONFIG --exists $OPENIPMI $SERVICELOG then PKG_CHECK_MODULES([OPENIPMI_SERVICELOG],[OpenIPMI OpenIPMIposix]) OPENIPMI_SERVICELOG_EXISTS="yes" fi AC_MSG_RESULT($OPENIPMI_SERVICELOG_EXISTS) AM_CONDITIONAL(BUILD_OPENIPMI_SERVICELOG, test "$OPENIPMI_SERVICELOG_EXISTS" = "yes") dnl ======================================================================== dnl Compiler flags dnl ======================================================================== dnl Make sure that CFLAGS is not exported. If the user did dnl not have CFLAGS in their environment then this should have dnl no effect. However if CFLAGS was exported from the user's dnl environment, then the new CFLAGS will also be exported dnl to sub processes. if export | fgrep " CFLAGS=" > /dev/null; then SAVED_CFLAGS="$CFLAGS" unset CFLAGS CFLAGS="$SAVED_CFLAGS" unset SAVED_CFLAGS fi 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]) CC_EXTRAS="" if test "$GCC" != yes; then CFLAGS="$CFLAGS -g" enable_fatal_warnings=no else CFLAGS="$CFLAGS -ggdb" dnl when we don't have diagnostic push / pull we can't explicitely 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 SAVED_CFLAGS="$CFLAGS" CFLAGS="$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])) CFLAGS="$SAVED_CFLAGS" if cc_supports_flag "-Wformat-nonliteral"; then gcc_format_nonliteral=yes else gcc_format_nonliteral=no fi # We had to eliminate -Wnested-externs because of libtool changes EXTRA_FLAGS="-fgnu89-inline -Wall -Waggregate-return -Wbad-function-cast -Wcast-align -Wdeclaration-after-statement -Wendif-labels -Wfloat-equal -Wformat-security -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Wno-long-long -Wno-strict-aliasing -Wpointer-arith -Wstrict-prototypes -Wwrite-strings -Wunused-but-set-variable -Wunsigned-char" if test "x$gcc_diagnostic_push_pull" = "xyes"; then AC_DEFINE([GCC_FORMAT_NONLITERAL_CHECKING_ENABLED], [], [gcc can complain about nonliterals in format]) EXTRA_FLAGS="$EXTRA_FLAGS -Wformat=2 -Wformat-nonliteral" else if test "x$gcc_format_nonliteral" = "xyes"; then EXTRA_FLAGS="$EXTRA_FLAGS -Wformat=2" fi fi # Additional warnings it might be nice to enable one day # -Wshadow # -Wunreachable-code for j in $EXTRA_FLAGS do if cc_supports_flag $j then CC_EXTRAS="$CC_EXTRAS $j" fi done dnl In lib/ais/Makefile.am there's a gcc option available as of v4.x GCC_MAJOR=`gcc -v 2>&1 | awk 'END{print $3}' | sed 's/[.].*//'` AM_CONDITIONAL(GCC_4, test "${GCC_MAJOR}" = 4) dnl System specific options case "$host_os" in *linux*|*bsd*) if test "${enable_fatal_warnings}" = "unknown"; then enable_fatal_warnings=yes fi ;; esac if test "x${enable_fatal_warnings}" != xno && cc_supports_flag -Werror ; then enable_fatal_warnings=yes else enable_fatal_warnings=no fi if test "x${enable_ansi}" = xyes && cc_supports_flag -std=iso9899:199409 ; then AC_MSG_NOTICE(Enabling ANSI Compatibility) CC_EXTRAS="$CC_EXTRAS -ansi -D_GNU_SOURCE -DANSI_ONLY" fi AC_MSG_NOTICE(Activated additional gcc flags: ${CC_EXTRAS}) fi 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 (attrd, cib, crmd, lrmd, stonithd, pacemakerd, pacemaker_remoted, dnl pengine) 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 if test "x${HARDENING}" != "xtry"; then unset CFLAGS_HARDENED_EXE unset CFLAGS_HARDENED_LIB unset LDFLAGS_HARDENED_EXE unset LDFLAGS_HARDENED_LIB fi if test "x${HARDENING}" = "xno"; then AC_MSG_NOTICE([Hardening: explicitly disabled]) elif test "x${HARDENING}" = "xyes" \ || test "$(env | grep -Ec '^(C|LD)FLAGS_HARDENED_(EXE|LIB)=.')" = 0; then dnl We'll figure out on our own... CFLAGS_HARDENED_EXE= CFLAGS_HARDENED_LIB= LDFLAGS_HARDENED_EXE= LDFLAGS_HARDENED_LIB= relro=0 pie=0 bindnow=0 # 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 if cc_supports_flag -fPIE; then flag="-pie" CC_CHECK_LDFLAGS(["${flag}"], [CFLAGS_HARDENED_EXE="${CFLAGS_HARDENED_EXE} -fPIE"; LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}"; pie=1] ) fi # 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 if test "${relro}" = 1 && test "${pie}" = 1; then flag="-Wl,-z,now" CC_CHECK_LDFLAGS(["${flag}"], [LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}"; LDFLAGS_HARDENED_LIB="${LDFLAGS_HARDENED_LIB} ${flag}"; bindnow=1] ) fi if test "${bindnow}" = 1; then flag="-Wl,--as-needed" CC_CHECK_LDFLAGS(["${flag}"], [LDFLAGS_HARDENED_EXE="${LDFLAGS_HARDENED_EXE} ${flag}"; LDFLAGS_HARDENED_LIB="${LDFLAGS_HARDENED_LIB} ${flag}"] ) fi # universal: prefer strong > all > default stack protector if possible flag= if cc_supports_flag -fstack-protector-strong; then flag="-fstack-protector-strong" elif cc_supports_flag -fstack-protector-all; then flag="-fstack-protector-all" elif cc_supports_flag -fstack-protector; then flag="-fstack-protector" fi if test -n "${flag}"; then CC_EXTRAS="${CC_EXTRAS} ${flag}" stackprot=1 fi if test "${relro}" = 1 \ || test "${pie}" = 1 \ || test "${stackprot}" = 1; then AC_MSG_NOTICE( [Hardening: relro=${relro} pie=${pie} bindnow=${bindnow} stackprot=${flag}]) else AC_MSG_WARN([Hardening: no suitable features in the toolchain detected]) fi else AC_MSG_NOTICE([Hardening: using custom flags]) fi CFLAGS="$CFLAGS $CC_EXTRAS" NON_FATAL_CFLAGS="$CFLAGS" AC_SUBST(NON_FATAL_CFLAGS) dnl dnl We reset CFLAGS to include our warnings *after* all function dnl checking goes on, so that our warning flags don't keep the dnl AC_*FUNCS() calls above from working. In particular, -Werror will dnl *always* cause us troubles if we set it before here. dnl dnl if test "x${enable_fatal_warnings}" = xyes ; then AC_MSG_NOTICE(Enabling Fatal Warnings) CFLAGS="$CFLAGS -Werror" fi AC_SUBST(CFLAGS) dnl This is useful for use in Makefiles that need to remove one specific flag CFLAGS_COPY="$CFLAGS" AC_SUBST(CFLAGS_COPY) AC_SUBST(LIBADD_DL) dnl extra flags for dynamic linking libraries AC_SUBST(LIBADD_INTL) dnl extra flags for GNU gettext stuff... AC_SUBST(LOCALE) dnl Options for cleaning up the compiler output QUIET_LIBTOOL_OPTS="" QUIET_MAKE_OPTS="" if test "x${enable_quiet}" = "xyes"; then QUIET_LIBTOOL_OPTS="--quiet" QUIET_MAKE_OPTS="--quiet" fi AC_MSG_RESULT(Supress make details: ${enable_quiet}) dnl Put the above variables to use LIBTOOL="${LIBTOOL} --tag=CC \$(QUIET_LIBTOOL_OPTS)" MAKE="${MAKE} \$(QUIET_MAKE_OPTS)" AC_SUBST(CC) AC_SUBST(MAKE) AC_SUBST(LIBTOOL) AC_SUBST(QUIET_MAKE_OPTS) AC_SUBST(QUIET_LIBTOOL_OPTS) AC_DEFINE_UNQUOTED(CRM_FEATURES, "$PCMK_FEATURES", Set of enabled features) AC_SUBST(PCMK_FEATURES) dnl The Makefiles and shell scripts we output AC_CONFIG_FILES(Makefile \ Doxyfile \ coverage.sh \ cts/Makefile \ cts/CTSvars.py \ cts/LSBDummy \ cts/HBDummy \ cts/benchmark/Makefile \ cts/benchmark/clubench \ cts/lxc_autogen.sh \ cib/Makefile \ attrd/Makefile \ crmd/Makefile \ pengine/Makefile \ pengine/regression.core.sh \ doc/Makefile \ - doc/Pacemaker_Explained/publican.cfg \ doc/Clusters_from_Scratch/publican.cfg \ + doc/Pacemaker_Development/publican.cfg \ + doc/Pacemaker_Explained/publican.cfg \ doc/Pacemaker_Remote/publican.cfg \ include/Makefile \ include/crm/Makefile \ include/crm/cib/Makefile \ include/crm/common/Makefile \ include/crm/cluster/Makefile \ include/crm/fencing/Makefile \ include/crm/pengine/Makefile \ replace/Makefile \ lib/Makefile \ lib/pacemaker.pc \ lib/pacemaker-cib.pc \ lib/pacemaker-lrmd.pc \ lib/pacemaker-service.pc \ lib/pacemaker-pengine.pc \ lib/pacemaker-fencing.pc \ lib/pacemaker-cluster.pc \ lib/ais/Makefile \ lib/common/Makefile \ lib/cluster/Makefile \ lib/cib/Makefile \ lib/pengine/Makefile \ lib/transition/Makefile \ lib/fencing/Makefile \ lib/lrmd/Makefile \ lib/services/Makefile \ mcp/Makefile \ mcp/pacemaker \ mcp/pacemaker.service \ mcp/pacemaker.upstart \ mcp/pacemaker.combined.upstart \ fencing/Makefile \ fencing/regression.py \ lrmd/Makefile \ lrmd/regression.py \ lrmd/pacemaker_remote.service \ lrmd/pacemaker_remote \ extra/Makefile \ extra/alerts/Makefile \ extra/resources/Makefile \ extra/logrotate/Makefile \ extra/logrotate/pacemaker \ tools/Makefile \ tools/crm_report \ tools/report.common \ tools/cibsecret \ tools/crm_mon.service \ tools/crm_mon.upstart \ xml/Makefile \ lib/gnu/Makefile \ ) dnl Now process the entire list of files added by previous dnl calls to AC_CONFIG_FILES() AC_OUTPUT() dnl ***************** dnl Configure summary dnl ***************** AC_MSG_RESULT([]) AC_MSG_RESULT([$PACKAGE configuration:]) AC_MSG_RESULT([ Version = ${VERSION} (Build: $BUILD_VERSION)]) AC_MSG_RESULT([ Features =${PCMK_FEATURES}]) AC_MSG_RESULT([]) AC_MSG_RESULT([ Prefix = ${prefix}]) AC_MSG_RESULT([ Executables = ${sbindir}]) AC_MSG_RESULT([ Man pages = ${mandir}]) AC_MSG_RESULT([ Libraries = ${libdir}]) AC_MSG_RESULT([ Header files = ${includedir}]) AC_MSG_RESULT([ Arch-independent files = ${datadir}]) AC_MSG_RESULT([ State information = ${localstatedir}]) AC_MSG_RESULT([ System configuration = ${sysconfdir}]) AC_MSG_RESULT([ Corosync Plugins = ${LCRSODIR}]) AC_MSG_RESULT([]) AC_MSG_RESULT([ Use system LTDL = ${ac_cv_lib_ltdl_lt_dlopen}]) AC_MSG_RESULT([]) AC_MSG_RESULT([ HA group name = ${CRM_DAEMON_GROUP}]) AC_MSG_RESULT([ HA user name = ${CRM_DAEMON_USER}]) AC_MSG_RESULT([]) AC_MSG_RESULT([ CFLAGS = ${CFLAGS}]) AC_MSG_RESULT([ CFLAGS_HARDENED_EXE = ${CFLAGS_HARDENED_EXE}]) AC_MSG_RESULT([ CFLAGS_HARDENED_LIB = ${CFLAGS_HARDENED_LIB}]) AC_MSG_RESULT([ LDFLAGS_HARDENED_EXE = ${LDFLAGS_HARDENED_EXE}]) AC_MSG_RESULT([ LDFLAGS_HARDENED_LIB = ${LDFLAGS_HARDENED_LIB}]) AC_MSG_RESULT([ Libraries = ${LIBS}]) AC_MSG_RESULT([ Stack Libraries = ${CLUSTERLIBS}]) diff --git a/doc/Makefile.am b/doc/Makefile.am index 9771293048..a97c2f187c 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,260 +1,286 @@ # # doc: Pacemaker code # # Copyright (C) 2008 Andrew Beekhof # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # include $(top_srcdir)/Makefile.common helpdir = $(datadir)/$(PACKAGE) ascii = crm_fencing.txt acls.txt -docbook = Pacemaker_Explained Clusters_from_Scratch Pacemaker_Remote +docbook = Clusters_from_Scratch \ + Pacemaker_Development \ + Pacemaker_Explained \ + Pacemaker_Remote doc_DATA = $(ascii) $(generated_docs) # rsync destination for www targets RSYNC_DEST = root@www.clusterlabs.org:/var/www/html/doc/ publican_docs = generated_docs = generated_mans = ASCIIDOC_CLI_TYPE := pcs DOCBOOK_FORMATS := html-desktop DOCBOOK_LANGS := en-US DOTs = $(wildcard */en-US/images/*.dot) SVG = $(wildcard */en-US/images/pcmk-*.svg) $(DOTs:%.dot=%.svg) generated_PNGS = $(SVG:%.svg=%-small.png) $(SVG:%.svg=%.png) $(SVG:%.svg=%-large.png) \ Pacemaker_Explained/en-US/images/Policy-Engine-big.png \ Pacemaker_Explained/en-US/images/Policy-Engine-small.png PNGS = $(generated_PNGS) \ Pacemaker_Remote/en-US/images/pcmk-ha-cluster-stack.png \ Pacemaker_Remote/en-US/images/pcmk-ha-remote-stack.png BRAND_PNGS = publican-clusterlabs/en-US/images/title_logo.png \ publican-clusterlabs/en-US/images/image_left.png \ publican-clusterlabs/en-US/images/image_right.png \ publican-clusterlabs/en-US/images/h1-bg.png graphics: $(PNGS) %.png: %.svg $(AM_V_IMG)$(INKSCAPE) --file=$< --export-dpi=90 -C --export-png=$@ %-small.png: %.svg $(AM_V_IMG)$(INKSCAPE) --file=$< --export-dpi=45 -C --export-png=$@ %-large.png: %.svg $(AM_V_IMG)$(INKSCAPE) --file=$< --export-dpi=180 -C --export-png=$@ if BUILD_ASCIIDOC generated_docs += $(ascii:%.txt=%.html) if BUILD_DOCBOOK publican_docs += $(docbook) endif endif EXTRA_DIST = $(docbook:%=%.xml) %.html: %.txt $(AM_V_ASCII)$(ASCIIDOC) --unsafe --backend=xhtml11 $< # publican-clusterlabs/xsl/{html,html-single,pdf}.xsl refer to URIs # requiring Internet access, hence we shadow that with a XML catalog-based # redirect to local files brought with Publican installation; # this is what newer Publican normally does with the system-wide catalog # upon its installation, but let's provide a compatibility for older # or badly installed instances (via adding the created file into # XML_CATALOG_FILES for libxml2 backing Publican as a fallback); # note that nextCatalog arrangement needed so as to overcome # https://rt.cpan.org/Public/Bug/Display.html?id=113781 publican-catalog-fallback: @exec >$@-t \ && echo '' \ && echo '' \ && echo '' $(AM_V_GEN)mv $@-t $@ publican-catalog: publican-catalog-fallback @exec >$@-t \ && echo '' \ && echo '' \ && echo '' \ && echo '' $(AM_V_GEN)mv $@-t $@ SHARED_TXT=$(wildcard shared/en-US/*.txt) SHARED_XML=$(SHARED_TXT:%.txt=%.xml) CFS_SHARED_TXT=$(addprefix shared/en-US/,pacemaker-intro.txt) CFS_SHARED_XML=$(CFS_SHARED_TXT:%.txt=%.xml) CFS_TXT=$(wildcard Clusters_from_Scratch/en-US/*.txt) CFS_XML=$(CFS_TXT:%.txt=%.xml) $(CFS_XML): $(CFS_SHARED_XML) PUBLICAN_INTREE_DEPS = if PUBLICAN_INTREE_BRAND PUBLICAN_INTREE_DEPS += publican-catalog endif # We have to hardcode the book name # With '%' the test for 'newness' fails Clusters_from_Scratch.build: $(PNGS) $(wildcard Clusters_from_Scratch/en-US/*.xml) $(CFS_XML) $(CFS_SHARED_XML) $(PUBLICAN_INTREE_DEPS) $(PCMK_V) @echo Building $(@:%.build=%) because of $? rm -rf $(@:%.build=%)/publish/* if PUBLICAN_INTREE_BRAND $(AM_V_PUB)cd $(@:%.build=%) \ && RPM_BUILD_DIR="" XML_CATALOG_FILES="$(CURDIR)/publican-catalog" \ $(PUBLICAN) build --publish --langs=$(DOCBOOK_LANGS) --formats=$(DOCBOOK_FORMATS) --brand_dir=../publican-clusterlabs \ $(PCMK_quiet) else $(AM_V_PUB)cd $(@:%.build=%) \ && RPM_BUILD_DIR="" \ $(PUBLICAN) build --publish --langs=$(DOCBOOK_LANGS) --formats=$(DOCBOOK_FORMATS) \ $(PCMK_quiet) endif rm -rf $(@:%.build=%)/tmp touch $@ +PD_TXT=$(wildcard Pacemaker_Development/en-US/*.txt) +PD_XML=$(PD_TXT:%.txt=%.xml) + +# We have to hardcode the book name +# With '%' the test for 'newness' fails +Pacemaker_Development.build: $(wildcard Pacemaker_Development/en-US/*.xml) $(PD_XML) $(PUBLICAN_INTREE_DEPS) + $(PCMK_V) @echo Building $(@:%.build=%) because of $? + rm -rf $(@:%.build=%)/publish/* +if PUBLICAN_INTREE_BRAND + $(AM_V_PUB)cd $(@:%.build=%) \ + && RPM_BUILD_DIR="" XML_CATALOG_FILES="$(CURDIR)/publican-catalog" \ + $(PUBLICAN) build --publish --langs=$(DOCBOOK_LANGS) --formats=$(DOCBOOK_FORMATS) --brand_dir=../publican-clusterlabs \ + $(PCMK_quiet) +else + $(AM_V_PUB)cd $(@:%.build=%) \ + && RPM_BUILD_DIR="" \ + $(PUBLICAN) build --publish --langs=$(DOCBOOK_LANGS) --formats=$(DOCBOOK_FORMATS) \ + $(PCMK_quiet) +endif + rm -rf $(@:%.build=%)/tmp + touch $@ + + PE_SHARED_TXT=$(addprefix shared/en-US/,pacemaker-intro.txt) PE_SHARED_XML=$(PE_SHARED_TXT:%.txt=%.xml) PE_TXT=$(wildcard Pacemaker_Explained/en-US/*.txt) PE_XML=$(PE_TXT:%.txt=%.xml) $(PE_XML): $(PE_SHARED_XML) # We have to hardcode the book name # With '%' the test for 'newness' fails Pacemaker_Explained.build: $(PNGS) $(wildcard Pacemaker_Explained/en-US/*.xml) $(PE_XML) $(PE_SHARED_XML) $(PUBLICAN_INTREE_DEPS) $(PCMK_V) @echo Building $(@:%.build=%) because of $? rm -rf $(@:%.build=%)/publish/* if PUBLICAN_INTREE_BRAND $(AM_V_PUB)cd $(@:%.build=%) \ && RPM_BUILD_DIR="" XML_CATALOG_FILES="$(CURDIR)/publican-catalog" \ $(PUBLICAN) build --publish --langs=$(DOCBOOK_LANGS) --formats=$(DOCBOOK_FORMATS) --brand_dir=../publican-clusterlabs \ $(PCMK_quiet) else $(AM_V_PUB)cd $(@:%.build=%) \ && RPM_BUILD_DIR="" \ $(PUBLICAN) build --publish --langs=$(DOCBOOK_LANGS) --formats=$(DOCBOOK_FORMATS) \ $(PCMK_quiet) endif rm -rf $(@:%.build=%)/tmp touch $@ PR_TXT=$(wildcard Pacemaker_Remote/en-US/*.txt) PR_XML=$(PR_TXT:%.txt=%.xml) # We have to hardcode the book name # With '%' the test for 'newness' fails Pacemaker_Remote.build: $(PNGS) $(wildcard Pacemaker_Remote/en-US/*.xml) $(PR_XML) $(PUBLICAN_INTREE_DEPS) $(PCMK_V) @echo Building $(@:%.build=%) because of $? rm -rf $(@:%.build=%)/publish/* if PUBLICAN_INTREE_BRAND $(AM_V_PUB)cd $(@:%.build=%) \ && RPM_BUILD_DIR="" XML_CATALOG_FILES="$(CURDIR)/publican-catalog" \ $(PUBLICAN) build --publish --langs=$(DOCBOOK_LANGS) --formats=$(DOCBOOK_FORMATS) --brand_dir=../publican-clusterlabs \ $(PCMK_quiet) else $(AM_V_PUB)cd $(@:%.build=%) \ && RPM_BUILD_DIR="" \ $(PUBLICAN) build --publish --langs=$(DOCBOOK_LANGS) --formats=$(DOCBOOK_FORMATS) \ $(PCMK_quiet) endif rm -rf $(@:%.build=%)/tmp touch $@ # Update the translation template pot: for book in $(docbook); do \ echo "Updating translation templates in: $$book"; \ ( cd $$book && RPM_BUILD_DIR="" $(PUBLICAN) update_pot ); \ done # Update the actual translations po: pot for book in $(docbook); do \ echo "Updating translations in: $$book"; \ ( cd $$book && RPM_BUILD_DIR="" $(PUBLICAN) update_po --langs=all );\ done if BUILD_DOCBOOK docbook_build = $(docbook:%=%.build) all-local: $(docbook_build) */publican.cfg install-data-local: all-local for book in $(docbook); do \ filelist=`find $$book/publish/* -print`; \ for f in $$filelist; do \ p=`echo $$f | sed s:publish/:: | sed s:Pacemaker/::`; \ if [ -d $$f ]; then \ $(INSTALL) -d -m 775 $(DESTDIR)$(docdir)/$$p; \ else \ $(INSTALL) -m 644 $$f $(DESTDIR)$(docdir)/$$p; \ fi \ done; \ done endif brand: $(BRAND_PNGS) $(wildcard publican-clusterlabs/en-US/*.xml) cd publican-clusterlabs && publican build --formats=xml --langs=all --publish echo "Installing..." cd publican-clusterlabs && sudo publican install_brand --path=$(datadir)/publican/Common_Content # find publican-clusterlabs -name "*.noarch.rpm" -exec rm -f \{\} \; # cd publican-clusterlabs && $(PUBLICAN) package --binary # find publican-clusterlabs -name "*.noarch.rpm" -exec sudo rpm -Uvh --force \{\} \; pdf: make DOCBOOK_FORMATS="pdf" ASCIIDOC_CLI_TYPE=$(ASCIIDOC_CLI_TYPE) all-local www: clean-local $(generated_docs) $(ascii) make www-cli rsync -rtz --progress $(generated_docs) $(ascii) $(asciiman) $(RSYNC_DEST) www-pcs: www-cli www-cli: for book in $(docbook); do \ sed -i.sed 's@brand:.*@brand: clusterlabs@' $$book/publican.cfg; \ sed -i.sed 's@version:.*@version: $(PACKAGE_SERIES)-$(ASCIIDOC_CLI_TYPE)@' $$book/publican.cfg; \ done make DOCBOOK_FORMATS="pdf,html,html-single,epub" DOCBOOK_LANGS="all" ASCIIDOC_CLI_TYPE=$(ASCIIDOC_CLI_TYPE) all-local echo Uploading current $(PACKAGE_SERIES)-$(ASCIIDOC_CLI_TYPE) documentation set to clusterlabs.org if BUILD_DOCBOOK for book in $(docbook); do \ echo Uploading $$book...; \ echo "Generated on `date` from version: $(shell git log --pretty="format:%h %d" -n 1)" >> $$book/publish/build-$(PACKAGE_SERIES)-$(ASCIIDOC_CLI_TYPE).txt; \ for lang in `ls -1 $$book/publish | grep [a-z][a-z]-[A-Z][A-Z]`; do \ mv $$book/publish/$$lang/Pacemaker/$(PACKAGE_SERIES)-$(ASCIIDOC_CLI_TYPE)/epub/$$book/Pacemaker-1.1{-$(ASCIIDOC_CLI_TYPE),}-$$book-$$lang.epub; \ mv $$book/publish/$$lang/Pacemaker/$(PACKAGE_SERIES)-$(ASCIIDOC_CLI_TYPE)/pdf/$$book/Pacemaker-1.1{-$(ASCIIDOC_CLI_TYPE),}-$$book-$$lang.pdf; \ done; \ rsync -rtz --progress $$book/publish/* $(RSYNC_DEST); \ sed -i.sed 's@version:.*@version: $(PACKAGE_SERIES)@' $$book/publican.cfg; \ done endif clean-local: -rm -rf $(generated_docs) $(generated_mans) $(docbook_build) $(generated_PNGS) -rm -rf $(SHARED_XML) $(CFS_XML) $(PE_XML) $(PR_XML) -rm -rf publican-catalog-fallback publican-catalog for book in $(docbook); do rm -rf $$book/tmp $$book/publish; done diff --git a/doc/Pacemaker_Development/en-US/Author_Group.xml b/doc/Pacemaker_Development/en-US/Author_Group.xml new file mode 100644 index 0000000000..a40b3adcc6 --- /dev/null +++ b/doc/Pacemaker_Development/en-US/Author_Group.xml @@ -0,0 +1,17 @@ + + + + + AndrewBeekhof + Red Hat + Co-author + andrew@beekhof.net + + + KenGaillot + Red Hat + Co-author + kgaillot@redhat.com + + diff --git a/doc/Pacemaker_Development/en-US/Book_Info.xml b/doc/Pacemaker_Development/en-US/Book_Info.xml new file mode 100644 index 0000000000..13334d724f --- /dev/null +++ b/doc/Pacemaker_Development/en-US/Book_Info.xml @@ -0,0 +1,36 @@ + + +%BOOK_ENTITIES; +]> + + Pacemaker Development + Working with the Pacemaker Code Base + + 1 + 0 + + + This document has guidelines and tips for developers + interested in editing Pacemaker source code and + submitting changes for inclusion in the project. + + + + + + + + + + + + + diff --git a/doc/Pacemaker_Development/en-US/Ch-Coding.txt b/doc/Pacemaker_Development/en-US/Ch-Coding.txt new file mode 100644 index 0000000000..a47f504d45 --- /dev/null +++ b/doc/Pacemaker_Development/en-US/Ch-Coding.txt @@ -0,0 +1,158 @@ += C Coding Guidelines = + +== Formatting == + +=== Whitespace === + +indexterm:[C,whitespace] + +- Indentation must be 4 spaces, no tabs. +- Do not leave trailing whitespace. + +=== Line Length === + +- Lines should be no longer than 80 characters unless limiting line length + significantly impacts readability. + +=== Pointers === + +indexterm:[C,pointers] + +- The +*+ goes by the variable name, not the type: + +==== +[source,C] +---- +char *foo; +---- +==== + +- Use a space before the +*+ and after the closing parenthesis in a cast: + +==== +[source,C] +---- +char *foo = (char *) bar; +---- +==== + +=== Functions === + +indexterm:[C,functions] + +- In the function definition, put the return type on its own line, and place + the opening brace by itself on a line: + +==== +[source,C] +---- +static int +foo(void) +{ +---- +==== + +- For functions with enough arguments that they must break to the next line, + align arguments with the first argument: + +==== +[source,C] +---- +static int +function_name(int bar, const char *a, const char *b, + const char *c, const char *d) +{ +---- +==== + +- If a function name gets really long, start the arguments on their own line + with 8 spaces of indentation: + +==== +[source,C] +---- +static int +really_really_long_function_name_this_is_getting_silly_now( + int bar, const char *a, const char *b, + const char *c, const char *d) +{ +---- +==== + +=== Control Statements (if, else, while, for, switch) === + +- The keyword is followed by one space, then left parenthesis without space, + condition, right parenthesis, space, opening bracket on the same line. + +else+ and +else if+ are on the same line with the ending brace and opening + brace, separated by a space: + +==== +[source,C] +---- +if (condition1) { + statement1; +} else if (condition2) { + statement2; +} else { + statement3; +} +---- +==== + +- In a +switch+ statement, +case+ is indented one level, and the body of each + +case+ is indented by another level. The opening brace is on the same line as + +switch+. + +==== +[source,C] +---- +switch (expression) { + case 0: + command1; + break; + case 1: + command2; + break; + default: + command3; +} +---- +==== + +=== Operators === + +indexterm:[C,operators] + +- Operators have spaces from both sides. Do not rely on operator precedence; + use parentheses when mixing operators with different priority. +- No space is used after opening parenthesis and before closing parenthesis. + +==== +[source,C] +---- +x = a + b - (c * d); +---- +==== + +== Naming Conventions == + +indexterm:[C,naming] + +- Any exposed symbols in libraries (non-+static+ function names, type names, + etc.) must begin with a prefix appropriate to the library, for example, + +crm_+, +pe_+, +st_+, +lrm_+. + +== vim Settings == + +indexterm:[vim] + +Developers who use +vim+ to edit source code can add the following settings to +their +~/.vimrc+ file to follow Pacemaker C coding guidelines: + +---- +" follow Pacemaker coding guidelines when editing C source code files +filetype plugin indent on +au FileType c setlocal expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80 +autocmd BufNewFile,BufRead *.h set filetype=c +let c_space_errors = 1 +---- diff --git a/doc/Pacemaker_Development/en-US/Pacemaker_Development.ent b/doc/Pacemaker_Development/en-US/Pacemaker_Development.ent new file mode 100644 index 0000000000..8679f6ffb1 --- /dev/null +++ b/doc/Pacemaker_Development/en-US/Pacemaker_Development.ent @@ -0,0 +1,4 @@ + + + + diff --git a/doc/Pacemaker_Development/en-US/Pacemaker_Development.xml b/doc/Pacemaker_Development/en-US/Pacemaker_Development.xml new file mode 100644 index 0000000000..179a6ff12b --- /dev/null +++ b/doc/Pacemaker_Development/en-US/Pacemaker_Development.xml @@ -0,0 +1,11 @@ + + +%BOOK_ENTITIES; +]> + + + + + + diff --git a/doc/Pacemaker_Development/en-US/Revision_History.xml b/doc/Pacemaker_Development/en-US/Revision_History.xml new file mode 100644 index 0000000000..dea79047c9 --- /dev/null +++ b/doc/Pacemaker_Development/en-US/Revision_History.xml @@ -0,0 +1,26 @@ + + +%BOOK_ENTITIES; +]> + + + Revision History + + + + + 1-0 + Tue Jul 26 2016 + + KenGaillot + kgaillot@redhat.com + + + Convert coding guidelines to Publican document + + + + + + diff --git a/doc/Pacemaker_Development/en-US/images/.keep b/doc/Pacemaker_Development/en-US/images/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/doc/Pacemaker_Development/publican.cfg.in b/doc/Pacemaker_Development/publican.cfg.in new file mode 100644 index 0000000000..7b5e54e512 --- /dev/null +++ b/doc/Pacemaker_Development/publican.cfg.in @@ -0,0 +1,11 @@ +docname: Pacemaker_Development +xml_lang: en-US +#edition: 1 +type: Book +version: @PACKAGE_SERIES@ +brand: @PUBLICAN_BRAND@ +product: Pacemaker + +chunk_first: 0 +chunk_section_depth: 3 +generate_section_toc_level: 4 diff --git a/doc/Pacemaker_Explained/en-US/Ch-Rules.txt b/doc/Pacemaker_Explained/en-US/Ch-Rules.txt index 6e158f7b94..986a6aac8b 100644 --- a/doc/Pacemaker_Explained/en-US/Ch-Rules.txt +++ b/doc/Pacemaker_Explained/en-US/Ch-Rules.txt @@ -1,573 +1,600 @@ = Rules = //// We prefer [[ch-rules]], but older versions of asciidoc don't deal well with that construct for chapter headings //// anchor:ch-rules[Chapter 8, Rules] indexterm:[Resource,Constraint,Rule] Rules can be used to make your configuration more dynamic. One common example is to set one value for +resource-stickiness+ during working hours, to prevent resources from being moved back to their most preferred location, and another on weekends when no-one is around to notice an outage. Another use of rules might be to assign machines to different processing groups (using a node attribute) based on time and to then use that attribute when creating location constraints. Each rule can contain a number of expressions, date-expressions and even other rules. The results of the expressions are combined based on the rule's +boolean-op+ field to determine if the rule ultimately evaluates to +true+ or +false+. What happens next depends on the context in which the rule is being used. == Rule Properties == .Properties of a Rule [width="95%",cols="2m,1,5<",options="header",align="center"] |========================================================= |Field |Default |Description |role |+Started+ |Limits the rule to apply only when the resource is in the specified role. Allowed values are +Started+, +Slave+, and +Master+. A rule with +role="Master"+ cannot determine the initial location of a clone instance and will only affect which of the active instances will be promoted. indexterm:[role,Constraint Rule] indexterm:[Constraint,Rule,role] |score | |The score to apply if the rule evaluates to +true+. Limited to use in rules that are part of location constraints. indexterm:[score,Constraint Rule] indexterm:[Constraint,Rule,score] |score-attribute | |The node attribute to look up and use as a score if the rule evaluates to +true+. Limited to use in rules that are part of location constraints. indexterm:[score-attribute,Constraint Rule] indexterm:[Constraint,Rule,score-attribute] |boolean-op |+and+ |How to combine the result of multiple expression objects. Allowed values are +and+ and +or+. indexterm:[boolean-op,Constraint Rule] indexterm:[Constraint,Rule,boolean-op] |========================================================= == Node Attribute Expressions == indexterm:[Resource,Constraint,Attribute Expression] Expression objects are used to control a resource based on the -attributes defined by a node or nodes. In addition to any attributes -added by the administrator, each node has a built-in node attribute -called +#uname+ that can also be used. +attributes defined by a node or nodes. .Properties of an Expression [width="95%",cols="1m,1,5 ---- ==== .Equivalent expression ==== [source,XML] ---- ---- ==== .9am-5pm Monday-Friday ==== [source,XML] ------- ------- ==== Please note that the +16+ matches up to +16:59:59+, as the numeric value (hour) still matches! .9am-6pm Monday through Friday or anytime Saturday ==== [source,XML] ------- ------- ==== .9am-5pm or 9pm-12am Monday through Friday ==== [source,XML] ------- ------- ==== .Mondays in March 2005 ==== [source,XML] ------- ------- ==== [NOTE] ====== Because no time is specified with the above dates, 00:00:00 is implied. This means that the range includes all of 2005-03-01 but none of 2005-04-01. You may wish to write +end="2005-03-31T23:59:59"+ to avoid confusion. ====== .A full moon on Friday the 13th ===== [source,XML] ------- ------- ===== == Using Rules to Determine Resource Location == indexterm:[Rule,Determine Resource Location] indexterm:[Resource,Location,Determine by Rules] A location constraint may contain rules. When the constraint's outermost rule evaluates to +false+, the cluster treats the constraint as if it were not there. When the rule evaluates to +true+, the node's preference for running the resource is updated with the score associated with the rule. If this sounds familiar, it is because you have been using a simplified syntax for location constraint rules already. Consider the following location constraint: .Prevent myApacheRsc from running on c001n03 ===== [source,XML] ------- ------- ===== This constraint can be more verbosely written as: .Prevent myApacheRsc from running on c001n03 - expanded version ===== [source,XML] ------- ------- ===== The advantage of using the expanded form is that one can then add extra clauses to the rule, such as limiting the rule such that it only applies during certain times of the day or days of the week. === Location Rules Based on Other Node Properties === The expanded form allows us to match on node properties other than its name. If we rated each machine's CPU power such that the cluster had the following nodes section: .A sample nodes section for use with score-attribute ===== [source,XML] ------- ------- ===== then we could prevent resources from running on underpowered machines with this rule: [source,XML] ------- ------- === Using +score-attribute+ Instead of +score+ === When using +score-attribute+ instead of +score+, each node matched by the rule has its score adjusted differently, according to its value for the named node attribute. Thus, in the previous example, if a rule used +score-attribute="cpu_mips"+, +c001n01+ would have its preference to run the resource increased by +1234+ whereas +c001n02+ would have its preference increased by +5678+. == Using Rules to Control Resource Options == Often some cluster nodes will be different from their peers. Sometimes, these differences -- e.g. the location of a binary or the names of network interfaces -- require resources to be configured differently depending on the machine they're hosted on. By defining multiple +instance_attributes+ objects for the resource and adding a rule to each, we can easily handle these special cases. In the example below, +mySpecialRsc+ will use eth1 and port 9999 when run on +node1+, eth2 and port 8888 on +node2+ and default to eth0 and port 9999 for all other nodes. .Defining different resource options based on the node name ===== [source,XML] ------- ------- ===== The order in which +instance_attributes+ objects are evaluated is determined by their score (highest to lowest). If not supplied, score defaults to zero, and objects with an equal score are processed in listed order. If the +instance_attributes+ object has no rule or a +rule+ that evaluates to +true+, then for any parameter the resource does not yet have a value for, the resource will use the parameter values defined by the +instance_attributes+. For example, given the configuration above, if the resource is placed on node1: . +special-node1+ has the highest score (3) and so is evaluated first; its rule evaluates to +true+, so +interface+ is set to +eth1+. . +special-node2+ is evaluated next with score 2, but its rule evaluates to +false+, so it is ignored. . +defaults+ is evaluated last with score 1, and has no rule, so its values are examined; +interface+ is already defined, so the value here is not used, but +port+ is not yet defined, so +port+ is set to +9999+. == Using Rules to Control Cluster Options == indexterm:[Rule,Controlling Cluster Options] indexterm:[Cluster,Setting Options with Rules] Controlling cluster options is achieved in much the same manner as specifying different resource options on different nodes. The difference is that because they are cluster options, one cannot (or should not, because they won't work) use attribute-based expressions. The following example illustrates how to set a different +resource-stickiness+ value during and outside work hours. This allows resources to automatically move back to their most preferred hosts, but at a time that (in theory) does not interfere with business activities. .Change +resource-stickiness+ during working hours ===== [source,XML] ------- ------- ===== [[s-rules-recheck]] == Ensuring Time-Based Rules Take Effect == A Pacemaker cluster is an event-driven system. As such, it won't recalculate the best place for resources to run unless something (like a resource failure or configuration change) happens. This can mean that a location constraint that only allows resource X to run between 9am and 5pm is not enforced. If you rely on time-based rules, the +cluster-recheck-interval+ cluster option (which defaults to 15 minutes) is essential. This tells the cluster to periodically recalculate the ideal state of the cluster. For example, if you set +cluster-recheck-interval="5m"+, then sometime between 09:00 and 09:05 the cluster would notice that it needs to start resource X, and between 17:00 and 17:05 it would realize that X needed to be stopped. The timing of the actual start and stop actions depends on what other actions the cluster may need to perform first. diff --git a/doc/Pacemaker_Remote/en-US/Ch-Intro.txt b/doc/Pacemaker_Remote/en-US/Ch-Intro.txt index 416c19d880..df5e1eae23 100644 --- a/doc/Pacemaker_Remote/en-US/Ch-Intro.txt +++ b/doc/Pacemaker_Remote/en-US/Ch-Intro.txt @@ -1,204 +1,205 @@ = Scaling a Pacemaker Cluster = == Overview == In a basic Pacemaker high-availability cluster,footnote:[See the http://www.clusterlabs.org/doc/[Pacemaker documentation], especially 'Clusters From Scratch' and 'Pacemaker Explained', for basic information about high-availability using Pacemaker] each node runs the full cluster stack of corosync and all Pacemaker components. This allows great flexibility but limits scalability to around 16 nodes. To allow for scalability to dozens or even hundreds of nodes, Pacemaker allows nodes not running the full cluster stack to integrate into the cluster and have the cluster manage their resources as if they were a cluster node. == Terms == cluster node:: A node running the full high-availability stack of corosync and all Pacemaker components. Cluster nodes may run cluster resources, run all Pacemaker command-line tools (`crm_mon`, `crm_resource` and so on), execute fencing actions, count toward cluster quorum, and serve as the cluster's Designated Controller (DC). (((cluster node))) (((node,cluster node))) pacemaker_remote:: A small service daemon that allows a host to be used as a Pacemaker node without running the full cluster stack. Nodes running pacemaker_remote may run cluster resources and most command-line tools, but cannot perform other functions of full cluster nodes such as fencing execution, quorum voting or DC eligibility. The pacemaker_remote daemon is an enhanced version of Pacemaker's local resource management daemon (LRMD). (((pacemaker_remote))) remote node:: A physical host running pacemaker_remote. Remote nodes have a special resource that manages communication with the cluster. This is sometimes referred to as the 'baremetal' case. (((remote node))) (((node,remote node))) guest node:: A virtual host running pacemaker_remote. Guest nodes differ from remote nodes mainly in that the guest node is itself a resource that the cluster manages. (((guest node))) (((node,guest node))) [NOTE] ====== 'Remote' in this document refers to the node not being a part of the underlying corosync cluster. It has nothing to do with physical proximity. Remote nodes and guest nodes are subject to the same latency requirements as cluster nodes, which means they are typically in the same data center. ====== [NOTE] ====== It is important to distinguish the various roles a virtual machine can serve in Pacemaker clusters: * A virtual machine can run the full cluster stack, in which case it is a cluster node and is not itself managed by the cluster. * A virtual machine can be managed by the cluster as a resource, without the cluster having any awareness of the services running inside the virtual machine. The virtual machine is 'opaque' to the cluster. * A virtual machine can be a cluster resource, and run pacemaker_remote to make it a guest node, allowing the cluster to manage services inside it. The virtual machine is 'transparent' to the cluster. ====== == Support in Pacemaker Versions == It is recommended to run Pacemaker 1.1.12 or later when using pacemaker_remote due to important bug fixes. An overview of changes in pacemaker_remote capability by version: .1.1.15 * If pacemaker_remote is stopped on an active node, it will wait for the cluster to migrate all resources off before exiting, rather than exit immediately and get fenced. * Bug fixes .1.1.14 * Resources that create guest nodes can be included in groups * reconnect_interval option for remote nodes * Bug fixes, including a memory leak .1.1.13 * Support for maintenance mode * Remote nodes can recover without being fenced when the cluster node hosting their connection fails * Running pacemaker_remote within LXC environments is deprecated due to newly added Pacemaker support for isolated resources +* +#kind+ built-in node attribute for use with rules * Bug fixes .1.1.12 * Support for permanent node attributes * Support for migration * Bug fixes .1.1.11 * Support for IPv6 * Support for remote nodes * Support for transient node attributes * Support for clusters with mixed endian architectures * Bug fixes .1.1.10 * Bug fixes .1.1.9 * Initial version to include pacemaker_remote * Limited to guest nodes in KVM/LXC environments using only IPv4; all nodes' architectures must have same endianness == Guest Nodes == (((guest node))) (((node,guest node))) *"I want a Pacemaker cluster to manage virtual machine resources, but I also want Pacemaker to be able to manage the resources that live within those virtual machines."* Without pacemaker_remote, the possibilities for implementing the above use case have significant limitations: * The cluster stack could be run on the physical hosts only, which loses the ability to monitor resources within the guests. * A separate cluster could be on the virtual guests, which quickly hits scalability issues. * The cluster stack could be run on the guests using the same cluster as the physical hosts, which also hits scalability issues and complicates fencing. With pacemaker_remote: * The physical hosts are cluster nodes (running the full cluster stack). * The virtual machines are guest nodes (running the pacemaker_remote service). Nearly zero configuration is required on the virtual machine. * The cluster stack on the cluster nodes launches the virtual machines and immediately connects to the pacemaker_remote service on them, allowing the virtual machines to integrate into the cluster. The key difference here between the guest nodes and the cluster nodes is that the guest nodes do not run the cluster stack. This means they will never become the DC, initiate fencing actions or participate in quorum voting. On the other hand, this also means that they are not bound to the scalability limits associated with the cluster stack (no 16-node corosync member limits to deal with). That isn't to say that guest nodes can scale indefinitely, but it is known that guest nodes scale horizontally much further than cluster nodes. Other than the quorum limitation, these guest nodes behave just like cluster nodes with respect to resource management. The cluster is fully capable of managing and monitoring resources on each guest node. You can build constraints against guest nodes, put them in standby, or do whatever else you'd expect to be able to do with cluster nodes. They even show up in `crm_mon` output as nodes. To solidify the concept, below is an example that is very similar to an actual deployment we test in our developer environment to verify guest node scalability: * 16 cluster nodes running the full corosync + pacemaker stack * 64 Pacemaker-managed virtual machine resources running pacemaker_remote configured as guest nodes * 64 Pacemaker-managed webserver and database resources configured to run on the 64 guest nodes With this deployment, you would have 64 webservers and databases running on 64 virtual machines on 16 hardware nodes, all of which are managed and monitored by the same Pacemaker deployment. It is known that pacemaker_remote can scale to these lengths and possibly much further depending on the specific scenario. == Remote Nodes == (((remote node))) (((node,remote node))) *"I want my traditional high-availability cluster to scale beyond the limits imposed by the corosync messaging layer."* Ultimately, the primary advantage of remote nodes over cluster nodes is scalability. There are likely some other use cases related to geographically distributed HA clusters that remote nodes may serve a purpose in, but those use cases are not well understood at this point. Like guest nodes, remote nodes will never become the DC, initiate fencing actions or participate in quorum voting. That is not to say, however, that fencing of a remote node works any differently than that of a cluster node. The Pacemaker policy engine understands how to fence remote nodes. As long as a fencing device exists, the cluster is capable of ensuring remote nodes are fenced in the exact same way as cluster nodes. == Expanding the Cluster Stack == With pacemaker_remote, the traditional view of the high-availability stack can be expanded to include a new layer: .Traditional HA Stack image::images/pcmk-ha-cluster-stack.png["Traditional Pacemaker+Corosync Stack",width="17cm",height="9cm",align="center"] .HA Stack With Guest Nodes image::images/pcmk-ha-remote-stack.png["Pacemaker+Corosync Stack With pacemaker_remote",width="20cm",height="10cm",align="center"] diff --git a/doc/coding_guidelines.txt b/doc/coding_guidelines.txt deleted file mode 100644 index a95134e9dc..0000000000 --- a/doc/coding_guidelines.txt +++ /dev/null @@ -1,129 +0,0 @@ -= Pacemaker Coding Guidelines = - -== Table of Contents == - -1. Introduction -2. Formatting Guidelines -3. Naming Conventions -4. vim Settings - -== Introduction == - -The purpose of this document is to discuss guidelines about how to write -code that will be a part of the Pacemaker project. - -== Formatting Guidelines == - -=== Whitespace === - -- Indentation must be 4 spaces, no tabs. -- Do not leave trailing whitespace. - -=== Line Length === - -- Lines should be no longer than 80 characters unless limiting line length significantly impacts readability. - -=== Pointers === - -- The '*' goes by the variable name, not the type: - -``` - char *foo; -``` - -- Use a space before the '*' and after the closing parenthesis in a cast: - -``` - char *foo = (char *) bar; -``` - -=== Functions === - -- Put the return type on its own line: -- Place the opening brace for a function on the next line: - -``` - static int - foo(void) - { -``` - -- For functions with enough arguments that they must break to the next line, align arguments with the first argument: - -``` - static int - function_name(int bar, const char *a, const char *b, - const char *c, const char *d) - { -``` - -- If a function name gets really long, start the arguments on their own line with 8 spaces of indentation: - -``` - static int - really_really_long_function_name_this_is_getting_silly_now( - int bar, const char *a, const char *b, - const char *c, const char *d) - { -``` - -=== Control statements (if, else, while, for, switch) === - -- Keyword is followed by one space, then left parenthesis witout space, - condition, right parenthesis, space, opening bracket on the same line. - -- "else" and "else if" are on the same line with ending brace and opening - brace, separated by space - -``` - if (condition1) { - statement1; - } else if (condition2) { - statement2; - } else { - statement3; - } -``` - -- Cases in switch statement have same indentation as switch. Body of cases - is indented by one level. Opening brace is on the same line as switch. - -``` - switch (expression) { - case 0: - command0; - break; - case 1: - command1; - break; - default: - command; - } -``` - -=== Operators === - -- Operators have spaces from both sides. Do not rely on operator precedence, - use brackets when mixing operators with different priority. -- No space after opening bracked and before closing bracket. - -``` - x = a + b - (c * d); -``` - -== Naming Conventions == - -- Public C API calls and type names must begin with an API specific prefix, eg. "crm_", "pe_", "st_", "lrm_". - -== vim Settings == - -```vim - " This section contains settings that can be placed in the vimrc file that are - " compatible with the Pacemaker coding guidelines. - - " Whitespace - set ts=4 - set sw=4 - set expandtab - let c_space_error=1 -``` diff --git a/include/doxygen.h b/include/doxygen.h index 58785d33e3..d7f90a672c 100644 --- a/include/doxygen.h +++ b/include/doxygen.h @@ -1,67 +1,62 @@ /* doxygen.h */ /* * Copyright (C) 2006 - 2012 * Andrew Beekhof * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef DOXYGEN__H # define DOXYGEN__H /** * \file * \brief Fake header file that contains doxygen documentation. * \author Andrew Beekhof * * The purpose of this file is to provide a file that can be used to create * doxygen pages. It should contain _only_ comment blocks. * * * \defgroup core Core API * \defgroup date ISO-8601 Date/Time API * \defgroup cib Configuration API * \defgroup lrmd Local Resource Manager API * \defgroup pengine Policy Engine API * \defgroup fencing Fencing API */ /** * \mainpage * Welcome to the developer documentation for The Pacemaker Project! For more * information about Pacemaker, please visit the - * project web site. + * project web site. * * Here are some pointers on where to go from here. * * Using Pacemaker APIs: * - \ref core * - \ref date * - \ref cib * - \ref lrmd * - \ref pengine * - \ref fencing * * Contributing to the Pacemaker Project: - * - \ref coding_guidelines - */ - -/** - * \page coding_guidelines Coding Guidelines - * \verbinclude doc/coding_guidelines.txt + * - Pacemaker Development */ #endif /* DOXYGEN__H */ diff --git a/lrmd/regression.py.in b/lrmd/regression.py.in index a3397d07a8..82f2730628 100755 --- a/lrmd/regression.py.in +++ b/lrmd/regression.py.in @@ -1,1121 +1,1168 @@ #!/usr/bin/python # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. import os import sys import subprocess import shlex import time # Where to find test binaries # Prefer the source tree if available build_dir="@abs_top_builddir@" test_dir=sys.path[0] new_path=os.environ['PATH'] if os.path.exists("%s/regression.py.in" % test_dir): print "Running tests from the source tree: %s (%s)" % (build_dir, test_dir) new_path = "%s/lrmd:%s" % (build_dir, new_path) # For lrmd, lrmd_test and pacemaker_remoted new_path = "%s/tools:%s" % (build_dir, new_path) # For crm_resource new_path = "%s/fencing:%s" % (build_dir, new_path) # For stonithd else: print "Running tests from the install tree: @CRM_DAEMON_DIR@ (not %s)" % test_dir new_path = "@CRM_DAEMON_DIR@:%s" % (new_path) # For stonithd, lrmd, lrmd_test and pacemaker_remoted print new_path os.environ['PATH']=new_path def output_from_command(command, no_wait=0): - test = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE) + test = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE) - if no_wait == 0: - test.wait() - else: - return 0 + if no_wait == 0: + test.wait() + else: + return 0 - return test.communicate()[0].split("\n") + return test.communicate()[0].split("\n") class Test: - def __init__(self, name, description, verbose = 0, tls = 0): - self.name = name - self.description = description - self.cmds = [] + def __init__(self, name, description, verbose = 0, tls = 0): + self.name = name + self.description = description + self.cmds = [] - if tls: - self.daemon_location = "pacemaker_remoted" - else: - self.daemon_location = "lrmd" + if tls: + self.daemon_location = "pacemaker_remoted" + else: + self.daemon_location = "lrmd" - self.test_tool_location = "lrmd_test" - self.verbose = verbose - self.tls = tls + self.test_tool_location = "lrmd_test" + self.verbose = verbose + self.tls = tls - self.result_txt = "" - self.cmd_tool_output = "" - self.result_exitcode = 0; - - self.lrmd_process = None - self.stonith_process = None - - self.executed = 0 - - def __new_cmd(self, cmd, args, exitcode, stdout_match = "", no_wait = 0, stdout_negative_match = "", kill=None): - if self.verbose and cmd == self.test_tool_location: - args = args + " -V " - - if (cmd == self.test_tool_location) and self.tls: - args = args + " -S " - - self.cmds.append( - { - "cmd" : cmd, - "kill" : kill, - "args" : args, - "expected_exitcode" : exitcode, - "stdout_match" : stdout_match, - "stdout_negative_match" : stdout_negative_match, - "no_wait" : no_wait, - "cmd_output" : "", - } - ) + self.result_txt = "" + self.cmd_tool_output = "" + self.result_exitcode = 0; - def start_environment(self): - ### make sure we are in full control here ### - cmd = shlex.split("killall -q -9 stonithd lt-stonithd lrmd lt-lrmd lrmd_test lt-lrmd_test pacemaker_remoted") - test = subprocess.Popen(cmd, stdout=subprocess.PIPE) - test.wait() + self.lrmd_process = None + self.stonith_process = None + + self.executed = 0 + + def __new_cmd(self, cmd, args, exitcode, stdout_match = "", no_wait = 0, stdout_negative_match = "", kill=None): + if self.verbose and cmd == self.test_tool_location: + args = args + " -V " + + if (cmd == self.test_tool_location) and self.tls: + args = args + " -S " + + self.cmds.append( + { + "cmd" : cmd, + "kill" : kill, + "args" : args, + "expected_exitcode" : exitcode, + "stdout_match" : stdout_match, + "stdout_negative_match" : stdout_negative_match, + "no_wait" : no_wait, + "cmd_output" : "", + } + ) - additional_args = "" + def start_environment(self): + ### make sure we are in full control here ### + cmd = shlex.split("killall -q -9 stonithd lt-stonithd lrmd lt-lrmd lrmd_test lt-lrmd_test pacemaker_remoted") + test = subprocess.Popen(cmd, stdout=subprocess.PIPE) + test.wait() - if self.tls == 0: - self.stonith_process = subprocess.Popen(shlex.split("stonithd -s")) + additional_args = "" - if self.verbose: - additional_args = additional_args + " -V" + if self.tls == 0: + self.stonith_process = subprocess.Popen(shlex.split("stonithd -s")) - self.lrmd_process = subprocess.Popen(shlex.split("%s %s -l /tmp/lrmd-regression.log" % (self.daemon_location, additional_args))) + if self.verbose: + additional_args = additional_args + " -V" - time.sleep(1) - - def clean_environment(self): - if self.lrmd_process: - self.lrmd_process.terminate() - self.lrmd_process.wait() - - if self.verbose: - print "Daemon output" - f = open('/tmp/lrmd-regression.log', 'r') - for line in f.readlines(): - print line.strip() - os.remove('/tmp/lrmd-regression.log') - - if self.stonith_process: - self.stonith_process.terminate() - self.stonith_process.wait() - - self.lrmd_process = None - self.stonith_process = None - - def add_sys_cmd(self, cmd, args): - self.__new_cmd(cmd, args, 0, "") - - def add_sys_cmd_no_wait(self, cmd, args): - self.__new_cmd(cmd, args, 0, "", 1) - - def add_cmd_check_stdout(self, args, match, no_match = ""): - self.__new_cmd(self.test_tool_location, args, 0, match, 0, no_match) - - def add_cmd(self, args): - self.__new_cmd(self.test_tool_location, args, 0, "") - - def add_cmd_and_kill(self, killProc, args): - self.__new_cmd(self.test_tool_location, args, 0, "", kill=killProc) - - def add_expected_fail_cmd(self, args): - self.__new_cmd(self.test_tool_location, args, 1, "") - - def get_exitcode(self): - return self.result_exitcode - - def print_result(self, filler): - print "%s%s" % (filler, self.result_txt) - - def run_cmd(self, args): - cmd = shlex.split(args['args']) - cmd.insert(0, args['cmd']) - if self.verbose: - print "\n\nRunning: "+" ".join(cmd) - test = subprocess.Popen(cmd, stdout=subprocess.PIPE) - - if args['kill']: - if self.verbose: - print "Also running: "+args['kill'] - ### Typically the kill argument is used to detect some sort of - ### failure. Without yeilding for a few seconds here the process - ### launched earlier that is listening for the failure may not have time - ### to connect to the lrmd. - time.sleep(2) - subprocess.Popen(shlex.split(args['kill'])) - - if args['no_wait'] == 0: - test.wait() - else: - return 0 - - output = test.communicate()[0] - - if args['stdout_match'] != "" and output.count(args['stdout_match']) == 0: - test.returncode = -2 - print "STDOUT string '%s' was not found in cmd output" % (args['stdout_match']) - - if args['stdout_negative_match'] != "" and output.count(args['stdout_negative_match']) != 0: - test.returncode = -2 - print "STDOUT string '%s' was found in cmd output" % (args['stdout_negative_match']) - - args['cmd_output'] = output - - return test.returncode; + self.lrmd_process = subprocess.Popen(shlex.split("%s %s -l /tmp/lrmd-regression.log" % (self.daemon_location, additional_args))) - def run(self): - res = 0 - i = 1 + time.sleep(1) - if self.tls and self.name.count("stonith") != 0: - self.result_txt = "SKIPPED - '%s' - disabled when testing pacemaker_remote" % (self.name) - print self.result_txt - return res + def clean_environment(self): + if self.lrmd_process: + self.lrmd_process.terminate() + self.lrmd_process.wait() + + if self.verbose: + print "Daemon output" + f = open('/tmp/lrmd-regression.log', 'r') + for line in f.readlines(): + print line.strip() + os.remove('/tmp/lrmd-regression.log') + + if self.stonith_process: + self.stonith_process.terminate() + self.stonith_process.wait() + + self.lrmd_process = None + self.stonith_process = None + + def add_sys_cmd(self, cmd, args): + self.__new_cmd(cmd, args, 0, "") + + def add_sys_cmd_no_wait(self, cmd, args): + self.__new_cmd(cmd, args, 0, "", 1) + + def add_expected_fail_sys_cmd(self, cmd, args, exitcode): + self.__new_cmd(cmd, args, exitcode) + + def add_cmd_check_stdout(self, args, match, no_match = ""): + self.__new_cmd(self.test_tool_location, args, 0, match, 0, no_match) + + def add_cmd(self, args): + self.__new_cmd(self.test_tool_location, args, 0, "") + + def add_cmd_and_kill(self, killProc, args): + self.__new_cmd(self.test_tool_location, args, 0, "", kill=killProc) + + def add_expected_fail_cmd(self, args): + self.__new_cmd(self.test_tool_location, args, 1, "") + + def get_exitcode(self): + return self.result_exitcode + + def print_result(self, filler): + print "%s%s" % (filler, self.result_txt) + + def run_cmd(self, args): + cmd = shlex.split(args['args']) + cmd.insert(0, args['cmd']) + if self.verbose: + print "\n\nRunning: "+" ".join(cmd) + test = subprocess.Popen(cmd, stdout=subprocess.PIPE) + + if args['kill']: + if self.verbose: + print "Also running: "+args['kill'] + ### Typically the kill argument is used to detect some sort of + ### failure. Without yeilding for a few seconds here the process + ### launched earlier that is listening for the failure may not have time + ### to connect to the lrmd. + time.sleep(2) + subprocess.Popen(shlex.split(args['kill'])) + + if args['no_wait'] == 0: + test.wait() + else: + return 0 + + output = test.communicate()[0] + + if args['stdout_match'] != "" and output.count(args['stdout_match']) == 0: + test.returncode = -2 + print "STDOUT string '%s' was not found in cmd output" % (args['stdout_match']) + + if args['stdout_negative_match'] != "" and output.count(args['stdout_negative_match']) != 0: + test.returncode = -2 + print "STDOUT string '%s' was found in cmd output" % (args['stdout_negative_match']) - self.start_environment() + args['cmd_output'] = output - if self.verbose: - print "\n--- START TEST - %s" % self.name + return test.returncode; - self.result_txt = "SUCCESS - '%s'" % (self.name) - self.result_exitcode = 0 - for cmd in self.cmds: - res = self.run_cmd(cmd) - if res != cmd['expected_exitcode']: - print cmd['cmd_output'] - print "Step %d FAILED - command returned %d, expected %d" % (i, res, cmd['expected_exitcode']) - self.result_txt = "FAILURE - '%s' failed at step %d. Command: lrmd_test %s" % (self.name, i, cmd['args']) - self.result_exitcode = -1 - break - else: - if self.verbose: - print cmd['cmd_output'].strip() - print "Step %d SUCCESS" % (i) - i = i + 1 - self.clean_environment() - - print self.result_txt - if self.verbose: - print "--- END TEST - %s\n" % self.name - - self.executed = 1 - return res + def run(self): + res = 0 + i = 1 + + if self.tls and self.name.count("stonith") != 0: + self.result_txt = "SKIPPED - '%s' - disabled when testing pacemaker_remote" % (self.name) + print self.result_txt + return res + + self.start_environment() + + if self.verbose: + print "\n--- START TEST - %s" % self.name + + self.result_txt = "SUCCESS - '%s'" % (self.name) + self.result_exitcode = 0 + for cmd in self.cmds: + res = self.run_cmd(cmd) + if res != cmd['expected_exitcode']: + print cmd['cmd_output'] + print "Step %d FAILED - command returned %d, expected %d" % (i, res, cmd['expected_exitcode']) + self.result_txt = "FAILURE - '%s' failed at step %d. Command: lrmd_test %s" % (self.name, i, cmd['args']) + self.result_exitcode = -1 + break + else: + if self.verbose: + print cmd['cmd_output'].strip() + print "Step %d SUCCESS" % (i) + i = i + 1 + self.clean_environment() + + print self.result_txt + if self.verbose: + print "--- END TEST - %s\n" % self.name + + self.executed = 1 + return res class Tests: - def __init__(self, verbose = 0, tls = 0): - self.tests = [] - self.verbose = verbose - self.tls = tls; - self.rsc_classes = output_from_command("crm_resource --list-standards") - self.rsc_classes = self.rsc_classes[:-1] # Strip trailing empty line - self.need_authkey = 0 - self.action_timeout = " -t 5000 " - if self.tls: - self.rsc_classes.remove("stonith") - if "systemd" in self.rsc_classes: - # the lrmd_dummy_daemon requires this, we are importing it - # here just to guarantee it is installed before allowing this - # script to run. Otherwise, running without this import being - # available will make all the systemd tests look like they fail, - # which is really scary looking. I'd rather see the import fail. - import systemd.daemon - - print "Testing "+repr(self.rsc_classes) - - self.common_cmds = { - "ocf_reg_line" : "-c register_rsc -r ocf_test_rsc "+self.action_timeout+" -C ocf -P pacemaker -T Dummy", - "ocf_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:ocf_test_rsc action:none rc:ok op_status:complete\"", - "ocf_unreg_line" : "-c unregister_rsc -r \"ocf_test_rsc\" "+self.action_timeout, - "ocf_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:ocf_test_rsc action:none rc:ok op_status:complete\"", - "ocf_start_line" : "-c exec -r \"ocf_test_rsc\" -a \"start\" "+self.action_timeout, - "ocf_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:start rc:ok op_status:complete\" ", - "ocf_stop_line" : "-c exec -r \"ocf_test_rsc\" -a \"stop\" "+self.action_timeout, - "ocf_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:stop rc:ok op_status:complete\" ", - "ocf_monitor_line" : "-c exec -r \"ocf_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, - "ocf_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, - "ocf_cancel_line" : "-c cancel -r \"ocf_test_rsc\" -a \"monitor\" -i \"2000\" -t \"6000\" ", - "ocf_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:monitor rc:ok op_status:Cancelled\" ", - - "systemd_reg_line" : "-c register_rsc -r systemd_test_rsc "+self.action_timeout+" -C systemd -T lrmd_dummy_daemon", - "systemd_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:systemd_test_rsc action:none rc:ok op_status:complete\"", - "systemd_unreg_line" : "-c unregister_rsc -r \"systemd_test_rsc\" "+self.action_timeout, - "systemd_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:systemd_test_rsc action:none rc:ok op_status:complete\"", - "systemd_start_line" : "-c exec -r \"systemd_test_rsc\" -a \"start\" "+self.action_timeout, - "systemd_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:start rc:ok op_status:complete\" ", - "systemd_stop_line" : "-c exec -r \"systemd_test_rsc\" -a \"stop\" "+self.action_timeout, - "systemd_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:stop rc:ok op_status:complete\" ", - "systemd_monitor_line" : "-c exec -r \"systemd_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, - "systemd_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, - "systemd_cancel_line" : "-c cancel -r \"systemd_test_rsc\" -a \"monitor\" -i \"2000\" -t \"6000\" ", - "systemd_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:monitor rc:ok op_status:Cancelled\" ", - - "upstart_reg_line" : "-c register_rsc -r upstart_test_rsc "+self.action_timeout+" -C upstart -T lrmd_dummy_daemon", - "upstart_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:upstart_test_rsc action:none rc:ok op_status:complete\"", - "upstart_unreg_line" : "-c unregister_rsc -r \"upstart_test_rsc\" "+self.action_timeout, - "upstart_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:upstart_test_rsc action:none rc:ok op_status:complete\"", - "upstart_start_line" : "-c exec -r \"upstart_test_rsc\" -a \"start\" "+self.action_timeout, - "upstart_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:start rc:ok op_status:complete\" ", - "upstart_stop_line" : "-c exec -r \"upstart_test_rsc\" -a \"stop\" "+self.action_timeout, - "upstart_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:stop rc:ok op_status:complete\" ", - "upstart_monitor_line" : "-c exec -r \"upstart_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, - "upstart_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, - "upstart_cancel_line" : "-c cancel -r \"upstart_test_rsc\" -a \"monitor\" -i \"2000\" -t \"6000\" ", - "upstart_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:monitor rc:ok op_status:Cancelled\" ", - - "service_reg_line" : "-c register_rsc -r service_test_rsc "+self.action_timeout+" -C service -T LSBDummy", - "service_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:service_test_rsc action:none rc:ok op_status:complete\"", - "service_unreg_line" : "-c unregister_rsc -r \"service_test_rsc\" "+self.action_timeout, - "service_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:service_test_rsc action:none rc:ok op_status:complete\"", - "service_start_line" : "-c exec -r \"service_test_rsc\" -a \"start\" "+self.action_timeout, - "service_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:start rc:ok op_status:complete\" ", - "service_stop_line" : "-c exec -r \"service_test_rsc\" -a \"stop\" "+self.action_timeout, - "service_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:stop rc:ok op_status:complete\" ", - "service_monitor_line" : "-c exec -r \"service_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, - "service_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, - "service_cancel_line" : "-c cancel -r \"service_test_rsc\" -a \"monitor\" -i \"2000\" -t \"6000\" ", - "service_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:monitor rc:ok op_status:Cancelled\" ", - - "lsb_reg_line" : "-c register_rsc -r lsb_test_rsc "+self.action_timeout+" -C lsb -T LSBDummy", - "lsb_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:lsb_test_rsc action:none rc:ok op_status:complete\" ", - "lsb_unreg_line" : "-c unregister_rsc -r \"lsb_test_rsc\" "+self.action_timeout, - "lsb_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:lsb_test_rsc action:none rc:ok op_status:complete\"", - "lsb_start_line" : "-c exec -r \"lsb_test_rsc\" -a \"start\" "+self.action_timeout, - "lsb_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:start rc:ok op_status:complete\" ", - "lsb_stop_line" : "-c exec -r \"lsb_test_rsc\" -a \"stop\" "+self.action_timeout, - "lsb_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:stop rc:ok op_status:complete\" ", - "lsb_monitor_line" : "-c exec -r \"lsb_test_rsc\" -a status -i \"2000\" "+self.action_timeout, - "lsb_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:status rc:ok op_status:complete\" "+self.action_timeout, - "lsb_cancel_line" : "-c cancel -r \"lsb_test_rsc\" -a \"status\" -i \"2000\" -t \"6000\" ", - "lsb_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:status rc:ok op_status:Cancelled\" ", - - "heartbeat_reg_line" : "-c register_rsc -r hb_test_rsc "+self.action_timeout+" -C heartbeat -T HBDummy", - "heartbeat_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:hb_test_rsc action:none rc:ok op_status:complete\" ", - "heartbeat_unreg_line" : "-c unregister_rsc -r \"hb_test_rsc\" "+self.action_timeout, - "heartbeat_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:hb_test_rsc action:none rc:ok op_status:complete\"", - "heartbeat_start_line" : "-c exec -r \"hb_test_rsc\" -a \"start\" -k 1 -v a -k 2 -v b "+self.action_timeout, - "heartbeat_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:start rc:ok op_status:complete\" ", - "heartbeat_stop_line" : "-c exec -r \"hb_test_rsc\" -a \"stop\" -k 1 -v a -k 2 -v b "+self.action_timeout, - "heartbeat_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:stop rc:ok op_status:complete\" ", - "heartbeat_monitor_line" : "-c exec -r \"hb_test_rsc\" -a status -k 1 -v a -k 2 -v b -i \"2000\" "+self.action_timeout, - "heartbeat_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:status rc:ok op_status:complete\" "+self.action_timeout, - "heartbeat_cancel_line" : "-c cancel -r \"hb_test_rsc\" -a \"status\" -k 1 -v a -k 2 -v b -i \"2000\" -t \"6000\" ", - "heartbeat_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:status rc:ok op_status:Cancelled\" ", - - "stonith_reg_line" : "-c register_rsc -r stonith_test_rsc "+self.action_timeout+" -C stonith -P pacemaker -T fence_dummy_monitor", - "stonith_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:stonith_test_rsc action:none rc:ok op_status:complete\" ", - "stonith_unreg_line" : "-c unregister_rsc -r \"stonith_test_rsc\" "+self.action_timeout, - "stonith_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:stonith_test_rsc action:none rc:ok op_status:complete\"", - "stonith_start_line" : "-c exec -r \"stonith_test_rsc\" -a \"start\" -t 8000 ", - "stonith_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:start rc:ok op_status:complete\" ", - "stonith_stop_line" : "-c exec -r \"stonith_test_rsc\" -a \"stop\" "+self.action_timeout, - "stonith_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:stop rc:ok op_status:complete\" ", - "stonith_monitor_line" : "-c exec -r \"stonith_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, - "stonith_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, - "stonith_cancel_line" : "-c cancel -r \"stonith_test_rsc\" -a \"monitor\" -i \"2000\" -t \"6000\" ", - "stonith_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:ok op_status:Cancelled\" ", - } - - def new_test(self, name, description): - test = Test(name, description, self.verbose, self.tls) - self.tests.append(test) - return test - - def setup_test_environment(self): - os.system("service pacemaker_remote stop") - self.cleanup_test_environment() - - if self.tls and not os.path.isfile("/etc/pacemaker/authkey"): - self.need_authkey = 1 - os.system("mkdir -p /etc/pacemaker") - os.system("dd if=/dev/urandom of=/etc/pacemaker/authkey bs=4096 count=1") - - ### Make fake systemd daemon and unit file ### - dummy_daemon = """#!/bin/python + def __init__(self, verbose = 0, tls = 0): + self.tests = [] + self.verbose = verbose + self.tls = tls; + self.rsc_classes = output_from_command("crm_resource --list-standards") + self.rsc_classes = self.rsc_classes[:-1] # Strip trailing empty line + self.need_authkey = 0 + self.action_timeout = " -t 5000 " + if self.tls: + self.rsc_classes.remove("stonith") + if "systemd" in self.rsc_classes: + # the lrmd_dummy_daemon requires this, we are importing it + # here just to guarantee it is installed before allowing this + # script to run. Otherwise, running without this import being + # available will make all the systemd tests look like they fail, + # which is really scary looking. I'd rather see the import fail. + import systemd.daemon + + print "Testing "+repr(self.rsc_classes) + + self.common_cmds = { + "ocf_reg_line" : "-c register_rsc -r ocf_test_rsc "+self.action_timeout+" -C ocf -P pacemaker -T Dummy", + "ocf_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:ocf_test_rsc action:none rc:ok op_status:complete\"", + "ocf_unreg_line" : "-c unregister_rsc -r \"ocf_test_rsc\" "+self.action_timeout, + "ocf_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:ocf_test_rsc action:none rc:ok op_status:complete\"", + "ocf_start_line" : "-c exec -r \"ocf_test_rsc\" -a \"start\" "+self.action_timeout, + "ocf_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:start rc:ok op_status:complete\" ", + "ocf_stop_line" : "-c exec -r \"ocf_test_rsc\" -a \"stop\" "+self.action_timeout, + "ocf_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:stop rc:ok op_status:complete\" ", + "ocf_monitor_line" : "-c exec -r \"ocf_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, + "ocf_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, + "ocf_cancel_line" : "-c cancel -r \"ocf_test_rsc\" -a \"monitor\" -i \"2000\" -t \"6000\" ", + "ocf_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:ocf_test_rsc action:monitor rc:ok op_status:Cancelled\" ", + + "systemd_reg_line" : "-c register_rsc -r systemd_test_rsc "+self.action_timeout+" -C systemd -T lrmd_dummy_daemon", + "systemd_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:systemd_test_rsc action:none rc:ok op_status:complete\"", + "systemd_unreg_line" : "-c unregister_rsc -r \"systemd_test_rsc\" "+self.action_timeout, + "systemd_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:systemd_test_rsc action:none rc:ok op_status:complete\"", + "systemd_start_line" : "-c exec -r \"systemd_test_rsc\" -a \"start\" "+self.action_timeout, + "systemd_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:start rc:ok op_status:complete\" ", + "systemd_stop_line" : "-c exec -r \"systemd_test_rsc\" -a \"stop\" "+self.action_timeout, + "systemd_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:stop rc:ok op_status:complete\" ", + "systemd_monitor_line" : "-c exec -r \"systemd_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, + "systemd_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, + "systemd_cancel_line" : "-c cancel -r \"systemd_test_rsc\" -a \"monitor\" -i \"2000\" -t \"6000\" ", + "systemd_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:systemd_test_rsc action:monitor rc:ok op_status:Cancelled\" ", + + "upstart_reg_line" : "-c register_rsc -r upstart_test_rsc "+self.action_timeout+" -C upstart -T lrmd_dummy_daemon", + "upstart_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:upstart_test_rsc action:none rc:ok op_status:complete\"", + "upstart_unreg_line" : "-c unregister_rsc -r \"upstart_test_rsc\" "+self.action_timeout, + "upstart_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:upstart_test_rsc action:none rc:ok op_status:complete\"", + "upstart_start_line" : "-c exec -r \"upstart_test_rsc\" -a \"start\" "+self.action_timeout, + "upstart_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:start rc:ok op_status:complete\" ", + "upstart_stop_line" : "-c exec -r \"upstart_test_rsc\" -a \"stop\" "+self.action_timeout, + "upstart_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:stop rc:ok op_status:complete\" ", + "upstart_monitor_line" : "-c exec -r \"upstart_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, + "upstart_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, + "upstart_cancel_line" : "-c cancel -r \"upstart_test_rsc\" -a \"monitor\" -i \"2000\" -t \"6000\" ", + "upstart_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:upstart_test_rsc action:monitor rc:ok op_status:Cancelled\" ", + + "service_reg_line" : "-c register_rsc -r service_test_rsc "+self.action_timeout+" -C service -T LSBDummy", + "service_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:service_test_rsc action:none rc:ok op_status:complete\"", + "service_unreg_line" : "-c unregister_rsc -r \"service_test_rsc\" "+self.action_timeout, + "service_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:service_test_rsc action:none rc:ok op_status:complete\"", + "service_start_line" : "-c exec -r \"service_test_rsc\" -a \"start\" "+self.action_timeout, + "service_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:start rc:ok op_status:complete\" ", + "service_stop_line" : "-c exec -r \"service_test_rsc\" -a \"stop\" "+self.action_timeout, + "service_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:stop rc:ok op_status:complete\" ", + "service_monitor_line" : "-c exec -r \"service_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, + "service_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, + "service_cancel_line" : "-c cancel -r \"service_test_rsc\" -a \"monitor\" -i \"2000\" -t \"6000\" ", + "service_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:service_test_rsc action:monitor rc:ok op_status:Cancelled\" ", + + "lsb_reg_line" : "-c register_rsc -r lsb_test_rsc "+self.action_timeout+" -C lsb -T LSBDummy", + "lsb_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:lsb_test_rsc action:none rc:ok op_status:complete\" ", + "lsb_unreg_line" : "-c unregister_rsc -r \"lsb_test_rsc\" "+self.action_timeout, + "lsb_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:lsb_test_rsc action:none rc:ok op_status:complete\"", + "lsb_start_line" : "-c exec -r \"lsb_test_rsc\" -a \"start\" "+self.action_timeout, + "lsb_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:start rc:ok op_status:complete\" ", + "lsb_stop_line" : "-c exec -r \"lsb_test_rsc\" -a \"stop\" "+self.action_timeout, + "lsb_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:stop rc:ok op_status:complete\" ", + "lsb_monitor_line" : "-c exec -r \"lsb_test_rsc\" -a status -i \"2000\" "+self.action_timeout, + "lsb_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:status rc:ok op_status:complete\" "+self.action_timeout, + "lsb_cancel_line" : "-c cancel -r \"lsb_test_rsc\" -a \"status\" -i \"2000\" -t \"6000\" ", + "lsb_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:lsb_test_rsc action:status rc:ok op_status:Cancelled\" ", + + "heartbeat_reg_line" : "-c register_rsc -r hb_test_rsc "+self.action_timeout+" -C heartbeat -T HBDummy", + "heartbeat_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:hb_test_rsc action:none rc:ok op_status:complete\" ", + "heartbeat_unreg_line" : "-c unregister_rsc -r \"hb_test_rsc\" "+self.action_timeout, + "heartbeat_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:hb_test_rsc action:none rc:ok op_status:complete\"", + "heartbeat_start_line" : "-c exec -r \"hb_test_rsc\" -a \"start\" -k 1 -v a -k 2 -v b "+self.action_timeout, + "heartbeat_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:start rc:ok op_status:complete\" ", + "heartbeat_stop_line" : "-c exec -r \"hb_test_rsc\" -a \"stop\" -k 1 -v a -k 2 -v b "+self.action_timeout, + "heartbeat_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:stop rc:ok op_status:complete\" ", + "heartbeat_monitor_line" : "-c exec -r \"hb_test_rsc\" -a status -k 1 -v a -k 2 -v b -i \"2000\" "+self.action_timeout, + "heartbeat_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:status rc:ok op_status:complete\" "+self.action_timeout, + "heartbeat_cancel_line" : "-c cancel -r \"hb_test_rsc\" -a \"status\" -k 1 -v a -k 2 -v b -i \"2000\" -t \"6000\" ", + "heartbeat_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:hb_test_rsc action:status rc:ok op_status:Cancelled\" ", + + "stonith_reg_line" : "-c register_rsc -r stonith_test_rsc "+self.action_timeout+" -C stonith -P pacemaker -T fence_dummy_monitor", + "stonith_reg_event" : "-l \"NEW_EVENT event_type:register rsc_id:stonith_test_rsc action:none rc:ok op_status:complete\" ", + "stonith_unreg_line" : "-c unregister_rsc -r \"stonith_test_rsc\" "+self.action_timeout, + "stonith_unreg_event" : "-l \"NEW_EVENT event_type:unregister rsc_id:stonith_test_rsc action:none rc:ok op_status:complete\"", + "stonith_start_line" : "-c exec -r \"stonith_test_rsc\" -a \"start\" -t 8000 ", + "stonith_start_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:start rc:ok op_status:complete\" ", + "stonith_stop_line" : "-c exec -r \"stonith_test_rsc\" -a \"stop\" "+self.action_timeout, + "stonith_stop_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:stop rc:ok op_status:complete\" ", + "stonith_monitor_line" : "-c exec -r \"stonith_test_rsc\" -a \"monitor\" -i \"2000\" "+self.action_timeout, + "stonith_monitor_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout, + "stonith_cancel_line" : "-c cancel -r \"stonith_test_rsc\" -a \"monitor\" -i \"2000\" -t \"6000\" ", + "stonith_cancel_event" : "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:ok op_status:Cancelled\" ", + } + + def new_test(self, name, description): + test = Test(name, description, self.verbose, self.tls) + self.tests.append(test) + return test + + def setup_test_environment(self): + os.system("service pacemaker_remote stop") + self.cleanup_test_environment() + + if self.tls and not os.path.isfile("/etc/pacemaker/authkey"): + self.need_authkey = 1 + os.system("mkdir -p /etc/pacemaker") + os.system("dd if=/dev/urandom of=/etc/pacemaker/authkey bs=4096 count=1") + + ### Make fake systemd daemon and unit file ### + dummy_daemon = """#!/bin/python import time, systemd.daemon time.sleep(3) systemd.daemon.notify("READY=1") while True: time.sleep(5) """ - dummy_service_file = """ + dummy_service_file = """ [Unit] Description=Dummy resource that takes a while to start [Service] Type=notify ExecStart=/usr/sbin/lrmd_dummy_daemon """ - dummy_upstart_job = (""" + dummy_upstart_job = (""" description "Dummy service for regression tests" exec dd if=/dev/random of=/dev/null """) - dummy_fence_sleep_agent = ("""#!/usr/bin/python + dummy_fence_sleep_agent = ("""#!/usr/bin/python import sys import time def main(): for line in sys.stdin.readlines(): if line.count("monitor") > 0: time.sleep(30000) sys.exit(0) sys.exit(-1) if __name__ == "__main__": main() """) - dummy_fence_agent = ("""#!/usr/bin/python + dummy_fence_agent = ("""#!/usr/bin/python import sys def main(): for line in sys.stdin.readlines(): if line.count("monitor") > 0: sys.exit(0) if line.count("metadata") > 0: print '' print ' dummy description.' print ' http://www.example.com' print ' ' print ' ' print ' ' print ' ' print ' Fencing Action' print ' ' print ' ' print ' ' print ' ' print ' Physical plug number or name of virtual machine' print ' ' print ' ' print ' ' print ' ' print ' ' print ' ' print ' ' print ' ' print '' sys.exit(0) sys.exit(-1) if __name__ == "__main__": main() """) - os.system("cat <<-END >>/etc/init/lrmd_dummy_daemon.conf\n%s\nEND" % (dummy_upstart_job)) - os.system("cat <<-END >>/usr/sbin/lrmd_dummy_daemon\n%s\nEND" % (dummy_daemon)) - os.system("cat <<-END >>/lib/systemd/system/lrmd_dummy_daemon.service\n%s\nEND" % (dummy_service_file)) - os.system("chmod a+x /usr/sbin/lrmd_dummy_daemon") - - os.system("cat <<-END >>/usr/sbin/fence_dummy_sleep\n%s\nEND" % (dummy_fence_sleep_agent)) - os.system("chmod 711 /usr/sbin/fence_dummy_sleep") - - os.system("cat <<-END >>/usr/sbin/fence_dummy_monitor\n%s\nEND" % (dummy_fence_agent)) - os.system("chmod 711 /usr/sbin/fence_dummy_monitor") - - if os.path.exists("%s/cts/LSBDummy" % build_dir): - print "Using %s/cts/LSBDummy" % build_dir - os.system("cp %s/cts/LSBDummy /etc/init.d/LSBDummy" % build_dir) - - if not os.path.exists("@OCF_RA_DIR@/pacemaker"): - os.system("mkdir -p @OCF_RA_DIR@/pacemaker/") - - # Install helper OCF agents - for ra in [ "Dummy", "Stateful", "ping" ]: - os.system("cp %s/extra/resources/%s @OCF_RA_DIR@/pacemaker/%s" % (build_dir, ra, ra)) - os.system("chmod a+x @OCF_RA_DIR@/pacemaker/%s" % (ra)) - - else: - # Assume it's installed - print "Using @datadir@/@PACKAGE@/tests/cts/LSBDummy" - os.system("cp @datadir@/@PACKAGE@/tests/cts/LSBDummy /etc/init.d/LSBDummy") - - os.system("chmod a+x /etc/init.d/LSBDummy") - os.system("ls -al /etc/init.d/LSBDummy") - os.system("mkdir -p @CRM_CORE_DIR@/root") - - os.system("mkdir -p /etc/ha.d/resource.d") - if os.path.exists("%s/cts/HBDummy" % build_dir): - print "Using %s/cts/HBDummy" % build_dir - os.system("cp %s/cts/HBDummy /etc/ha.d/resource.d/HBDummy" % build_dir) - else: - # Assume it's installed - print "Using @datadir@/@PACKAGE@/tests/cts/HBDummy" - os.system("cp @datadir@/@PACKAGE@/tests/cts/HBDummy /etc/ha.d/resource.d/HBDummy") - - os.system("chmod a+x /etc/ha.d/resource.d/HBDummy") - os.system("ls -al /etc/ha.d/resource.d/HBDummy") - - if os.path.exists("/bin/systemctl"): - os.system("systemctl daemon-reload") - - def cleanup_test_environment(self): - if self.need_authkey: - os.system("rm -f /etc/pacemaker/authkey") - - os.system("rm -f /etc/init.d/LSBDummy") - os.system("rm -f /etc/ha.d/resource.d/HBDummy") - os.system("rm -f /lib/systemd/system/lrmd_dummy_daemon.service") - os.system("rm -f /usr/sbin/lrmd_dummy_daemon") - os.system("rm -f /usr/sbin/fence_dummy_monitor") - os.system("rm -f /usr/sbin/fence_dummy_sleep") - if os.path.exists("/bin/systemctl"): + os.system("cat <<-END >>/etc/init/lrmd_dummy_daemon.conf\n%s\nEND" % (dummy_upstart_job)) + os.system("cat <<-END >>/usr/sbin/lrmd_dummy_daemon\n%s\nEND" % (dummy_daemon)) + os.system("cat <<-END >>/lib/systemd/system/lrmd_dummy_daemon.service\n%s\nEND" % (dummy_service_file)) + os.system("chmod a+x /usr/sbin/lrmd_dummy_daemon") + + os.system("cat <<-END >>/usr/sbin/fence_dummy_sleep\n%s\nEND" % (dummy_fence_sleep_agent)) + os.system("chmod 711 /usr/sbin/fence_dummy_sleep") + + os.system("cat <<-END >>/usr/sbin/fence_dummy_monitor\n%s\nEND" % (dummy_fence_agent)) + os.system("chmod 711 /usr/sbin/fence_dummy_monitor") + + if os.path.exists("%s/cts/LSBDummy" % build_dir): + print "Using %s/cts/LSBDummy" % build_dir + os.system("cp %s/cts/LSBDummy /etc/init.d/LSBDummy" % build_dir) + + if not os.path.exists("@OCF_RA_DIR@/pacemaker"): + os.system("mkdir -p @OCF_RA_DIR@/pacemaker/") + + # Install helper OCF agents + for ra in [ "Dummy", "Stateful", "ping" ]: + os.system("cp %s/extra/resources/%s @OCF_RA_DIR@/pacemaker/%s" % (build_dir, ra, ra)) + os.system("chmod a+x @OCF_RA_DIR@/pacemaker/%s" % (ra)) + + else: + # Assume it's installed + print "Using @datadir@/@PACKAGE@/tests/cts/LSBDummy" + os.system("cp @datadir@/@PACKAGE@/tests/cts/LSBDummy /etc/init.d/LSBDummy") + + os.system("chmod a+x /etc/init.d/LSBDummy") + os.system("ls -al /etc/init.d/LSBDummy") + os.system("mkdir -p @CRM_CORE_DIR@/root") + + os.system("mkdir -p /etc/ha.d/resource.d") + if os.path.exists("%s/cts/HBDummy" % build_dir): + print "Using %s/cts/HBDummy" % build_dir + os.system("cp %s/cts/HBDummy /etc/ha.d/resource.d/HBDummy" % build_dir) + else: + # Assume it's installed + print "Using @datadir@/@PACKAGE@/tests/cts/HBDummy" + os.system("cp @datadir@/@PACKAGE@/tests/cts/HBDummy /etc/ha.d/resource.d/HBDummy") + + os.system("chmod a+x /etc/ha.d/resource.d/HBDummy") + os.system("ls -al /etc/ha.d/resource.d/HBDummy") + + if os.path.exists("/bin/systemctl"): + os.system("systemctl daemon-reload") + + def cleanup_test_environment(self): + if self.need_authkey: + os.system("rm -f /etc/pacemaker/authkey") + + os.system("rm -f /etc/init.d/LSBDummy") + os.system("rm -f /etc/ha.d/resource.d/HBDummy") + os.system("rm -f /lib/systemd/system/lrmd_dummy_daemon.service") + os.system("rm -f /usr/sbin/lrmd_dummy_daemon") + os.system("rm -f /usr/sbin/fence_dummy_monitor") + os.system("rm -f /usr/sbin/fence_dummy_sleep") + if os.path.exists("/bin/systemctl"): os.system("systemctl daemon-reload") - ### These are tests that should apply to all resource classes ### - def build_generic_tests(self): - common_cmds = self.common_cmds - - ### register/unregister tests ### - for rsc in self.rsc_classes: - test = self.new_test("generic_registration_%s" % (rsc), "Simple resource registration test for %s standard" % (rsc)) - test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) - test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) - - ### start/stop tests ### - for rsc in self.rsc_classes: - test = self.new_test("generic_start_stop_%s" % (rsc), "Simple start and stop test for %s standard" % (rsc)) - test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) - test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) - test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) - test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) - - ### monitor cancel test ### - for rsc in self.rsc_classes: - test = self.new_test("generic_monitor_cancel_%s" % (rsc), "Simple monitor cancel test for %s standard" % (rsc)) - test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) - test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) - test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) - test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### - test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### - test.add_cmd(common_cmds["%s_cancel_line" % (rsc)] + " " + common_cmds["%s_cancel_event" % (rsc)]) - test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### - test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### - test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) - test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) - - ### monitor duplicate test ### - for rsc in self.rsc_classes: - test = self.new_test("generic_monitor_duplicate_%s" % (rsc), "Test creation and canceling of duplicate monitors for %s standard" % (rsc)) - test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) - test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) - test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) - test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### - test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### - - # Add the duplicate monitors. - test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) - test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) - test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) - test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) - # verify we still get update events - test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### - - # cancel the monitor, if the duplicate merged with the original, we should no longer see monitor updates - test.add_cmd(common_cmds["%s_cancel_line" % (rsc)] + " " + common_cmds["%s_cancel_event" % (rsc)]) - test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### - test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### - test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) - test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) - - ### stop implies cancel test ### - for rsc in self.rsc_classes: - test = self.new_test("generic_stop_implies_cancel_%s" % (rsc), "Verify stopping a resource implies cancel of recurring ops for %s standard" % (rsc)) - test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) - test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) - test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) - test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### - test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### - test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) - test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### - test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### - test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) - - - ### These are complex tests that involve managing multiple resouces of different types ### - def build_multi_rsc_tests(self): - common_cmds = self.common_cmds - # do not use service and systemd at the same time, it is the same resource. - - ### register start monitor stop unregister resources of each type at the same time. ### - test = self.new_test("multi_rsc_start_stop_all", "Start, monitor, and stop resources of multiple types and classes") - for rsc in self.rsc_classes: - test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) - for rsc in self.rsc_classes: - test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) - for rsc in self.rsc_classes: - test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) - for rsc in self.rsc_classes: - test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor is not being rescheduled #### - for rsc in self.rsc_classes: - test.add_cmd(common_cmds["%s_cancel_line" % (rsc)] + " " + common_cmds["%s_cancel_event" % (rsc)]) - for rsc in self.rsc_classes: - test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) - for rsc in self.rsc_classes: - test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) - - ### These are tests related to how the lrmd handles failures. ### - def build_negative_tests(self): - - ### ocf start timeout test ### - test = self.new_test("ocf_start_timeout", "Force start timeout to occur, verify start failure.") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" -k \"op_sleep\" -v \"5\" -t 1000 -w") # -t must be less than self.action_timeout - test.add_cmd("-l " - "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:unknown error op_status:Timed Out\" "+self.action_timeout) - test.add_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") - test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - - ### stonith start timeout test ### - test = self.new_test("stonith_start_timeout", "Force start timeout to occur, verify start failure.") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"stonith\" -P \"pacemaker\" -T \"fence_dummy_sleep\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" -t 1000 -w") # -t must be less than self.action_timeout - test.add_cmd("-l " - "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:unknown error op_status:Timed Out\" "+self.action_timeout) - test.add_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") - test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### stonith component fail ### - common_cmds = self.common_cmds - test = self.new_test("stonith_component_fail", "Kill stonith component after lrmd connects") - test.add_cmd(common_cmds["stonith_reg_line"] + " " + common_cmds["stonith_reg_event"]) - test.add_cmd(common_cmds["stonith_start_line"] + " " + common_cmds["stonith_start_event"]) - - test.add_cmd("-c exec -r \"stonith_test_rsc\" -a \"monitor\" -i \"600000\" " - "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - - test.add_cmd_and_kill("killall -9 -q stonithd lt-stonithd" ,"-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:unknown error op_status:error\" -t 15000") - test.add_cmd(common_cmds["stonith_unreg_line"] + " " + common_cmds["stonith_unreg_event"]) - - - ### monitor fail for ocf resources ### - test = self.new_test("monitor_fail_ocf", "Force ocf monitor to fail, verify failure is reported.") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") - test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd_and_kill("rm -f @localstatedir@/run/Dummy-test_rsc.state", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 6000") - test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"6000\" " - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") - test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) - test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### verify notify changes only for monitor operation. ### - test = self.new_test("monitor_changes_only", "Verify when flag is set, only monitor changes are notified.") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+" -o " - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+" -o " - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") - test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd_and_kill("rm -f @localstatedir@/run/Dummy-test_rsc.state", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 6000") - test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"6000\" " - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") - test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) - test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### monitor fail for systemd resource ### - if "systemd" in self.rsc_classes: - test = self.new_test("monitor_fail_systemd", "Force systemd monitor to fail, verify failure is reported..") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C systemd -T lrmd_dummy_daemon "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") - test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd_and_kill("killall -9 -q lrmd_dummy_daemon", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 8000") - test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"6000\" " - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") - test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) - test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### monitor fail for upstart resource ### - if "upstart" in self.rsc_classes: - test = self.new_test("monitor_fail_upstart", "Force upstart monitor to fail, verify failure is reported..") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C upstart -T lrmd_dummy_daemon "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") - test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd_and_kill("killall -9 -q dd", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 8000") - test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"6000\" " - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") - test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) - test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### Cancel non-existent operation on a resource ### - test = self.new_test("cancel_non_existent_op", "Attempt to cancel the wrong monitor operation, verify expected failure") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") - test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_expected_fail_cmd("-c cancel -r test_rsc -a \"monitor\" -i 1234 -t \"6000\" " ### interval is wrong, should fail - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") - test.add_expected_fail_cmd("-c cancel -r test_rsc -a stop -i 100 -t \"6000\" " ### action name is wrong, should fail - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### Attempt to invoke non-existent rsc id ### - test = self.new_test("invoke_non_existent_rsc", "Attempt to perform operations on a non-existent rsc id.") - test.add_expected_fail_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:unknown error op_status:complete\" ") - test.add_expected_fail_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") - test.add_expected_fail_cmd("-c exec -r test_rsc -a monitor -i 6000 "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") - test.add_expected_fail_cmd("-c cancel -r test_rsc -a start "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:Cancelled\" ") - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### Register and start a resource that doesn't exist, systemd ### - if "systemd" in self.rsc_classes: - test = self.new_test("start_uninstalled_systemd", "Register uninstalled systemd agent, try to start, verify expected failure") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C systemd -T this_is_fake1234 "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - if "upstart" in self.rsc_classes: - test = self.new_test("start_uninstalled_upstart", "Register uninstalled upstart agent, try to start, verify expected failure") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C upstart -T this_is_fake1234 "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### Register and start a resource that doesn't exist, ocf ### - test = self.new_test("start_uninstalled_ocf", "Register uninstalled ocf agent, try to start, verify expected failure.") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C ocf -P pacemaker -T this_is_fake1234 "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### Register ocf with non-existent provider ### - test = self.new_test("start_ocf_bad_provider", "Register ocf agent with a non-existent provider, verify expected failure.") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C ocf -P pancakes -T Dummy "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### Register ocf with empty provider field ### - test = self.new_test("start_ocf_no_provider", "Register ocf agent with a no provider, verify expected failure.") - test.add_expected_fail_cmd("-c register_rsc -r \"test_rsc\" -C ocf -T Dummy "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_expected_fail_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:Error\" ") - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### stress tests ### - def build_stress_tests(self): - timeout = "-t 20000" - - iterations = 25 - test = self.new_test("ocf_stress", "Verify OCF agent handling works under load") - for i in range(iterations): - test.add_cmd("-c register_rsc -r rsc_%s %s -C ocf -P heartbeat -T Dummy -l \"NEW_EVENT event_type:register rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) - test.add_cmd("-c exec -r rsc_%s -a start %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:start rc:ok op_status:complete\"" % (i, timeout, i)) - test.add_cmd("-c exec -r rsc_%s -a monitor %s -i 1000 -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:monitor rc:ok op_status:complete\"" % (i, timeout, i)) - for i in range(iterations): - test.add_cmd("-c exec -r rsc_%s -a stop %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:stop rc:ok op_status:complete\"" % (i, timeout, i)) - test.add_cmd("-c unregister_rsc -r rsc_%s %s -l \"NEW_EVENT event_type:unregister rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) - - - if "systemd" in self.rsc_classes: - test = self.new_test("systemd_stress", "Verify systemd dbus connection works under load") - for i in range(iterations): - test.add_cmd("-c register_rsc -r rsc_%s %s -C systemd -T lrmd_dummy_daemon -l \"NEW_EVENT event_type:register rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) - test.add_cmd("-c exec -r rsc_%s -a start %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:start rc:ok op_status:complete\"" % (i, timeout, i)) - test.add_cmd("-c exec -r rsc_%s -a monitor %s -i 1000 -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:monitor rc:ok op_status:complete\"" % (i, timeout, i)) - - for i in range(iterations): - test.add_cmd("-c exec -r rsc_%s -a stop %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:stop rc:ok op_status:complete\"" % (i, timeout, i)) - test.add_cmd("-c unregister_rsc -r rsc_%s %s -l \"NEW_EVENT event_type:unregister rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) - - iterations = 9 - timeout = "-t 30000" - ### Verify recurring op in-flight collision is handled in series properly - test = self.new_test("rsc_inflight_collision", "Verify recurring ops do not collide with other operations for the same rsc.") - test.add_cmd("-c register_rsc -r test_rsc -P pacemaker -C ocf -T Dummy " - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-c exec -r test_rsc -a start %s -k op_sleep -v 1 -l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\"" % (timeout)) - for i in range(iterations): - test.add_cmd("-c exec -r test_rsc -a monitor %s -i 100%d -k op_sleep -v 2 -l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\"" % (timeout, i)) -# test.add_sys_cmd("sleep", "-al @CRM_RSCTMP_DIR@") - - test.add_cmd("-c exec -r test_rsc -a stop %s -l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\"" % (timeout)) - test.add_cmd("-c unregister_rsc -r test_rsc %s -l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\"" % (timeout)) - - ### These are tests that target specific cases ### - def build_custom_tests(self): - - - ### verify resource temporary folder is created and used by heartbeat agents. ### - test = self.new_test("rsc_tmp_dir", "Verify creation and use of rsc temporary state directory") - test.add_sys_cmd("ls", "-al @CRM_RSCTMP_DIR@") - test.add_cmd("-c register_rsc -r test_rsc -P heartbeat -C ocf -T Dummy " - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-c exec -r test_rsc -a start -t 4000") - test.add_sys_cmd("ls", "-al @CRM_RSCTMP_DIR@") - test.add_sys_cmd("ls", "@CRM_RSCTMP_DIR@/Dummy-test_rsc.state") - test.add_cmd("-c exec -r test_rsc -a stop -t 4000") - test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### start delay then stop test ### - test = self.new_test("start_delay", "Verify start delay works as expected.") - test.add_cmd("-c register_rsc -r test_rsc -P pacemaker -C ocf -T Dummy " - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-c exec -r test_rsc -s 6000 -a start -w -t 6000") - test.add_expected_fail_cmd("-l " - "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" -t 2000") - test.add_cmd("-l " - "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" -t 6000") - test.add_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") - test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### start delay, but cancel before it gets a chance to start. ### - test = self.new_test("start_delay_cancel", "Using start_delay, start a rsc, but cancel the start op before execution.") - test.add_cmd("-c register_rsc -r test_rsc -P pacemaker -C ocf -T Dummy " - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-c exec -r test_rsc -s 5000 -a start -w -t 4000") - test.add_cmd("-c cancel -r test_rsc -a start "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:Cancelled\" ") - test.add_expected_fail_cmd("-l " - "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" -t 5000") - test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### Register a bunch of resources, verify we can get info on them ### - test = self.new_test("verify_get_rsc_info", "Register multiple resources, verify retrieval of rsc info.") - if "systemd" in self.rsc_classes: - test.add_cmd("-c register_rsc -r rsc1 -C systemd -T lrmd_dummy_daemon "+self.action_timeout) - test.add_cmd("-c get_rsc_info -r rsc1 ") - test.add_cmd("-c unregister_rsc -r rsc1 "+self.action_timeout) - test.add_expected_fail_cmd("-c get_rsc_info -r rsc1 ") - - if "upstart" in self.rsc_classes: - test.add_cmd("-c register_rsc -r rsc1 -C upstart -T lrmd_dummy_daemon "+self.action_timeout) - test.add_cmd("-c get_rsc_info -r rsc1 ") - test.add_cmd("-c unregister_rsc -r rsc1 "+self.action_timeout) - test.add_expected_fail_cmd("-c get_rsc_info -r rsc1 ") - - test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Dummy -P pacemaker "+self.action_timeout) - test.add_cmd("-c get_rsc_info -r rsc2 ") - test.add_cmd("-c unregister_rsc -r rsc2 "+self.action_timeout) - test.add_expected_fail_cmd("-c get_rsc_info -r rsc2 ") - - ### Register duplicate, verify only one entry exists and can still be removed. - test = self.new_test("duplicate_registration", "Register resource multiple times, verify only one entry exists and can be removed.") - test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Dummy -P pacemaker "+self.action_timeout) - test.add_cmd_check_stdout("-c get_rsc_info -r rsc2 ", "id:rsc2 class:ocf provider:pacemaker type:Dummy") - test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Dummy -P pacemaker "+self.action_timeout) - test.add_cmd_check_stdout("-c get_rsc_info -r rsc2 ", "id:rsc2 class:ocf provider:pacemaker type:Dummy") - test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Stateful -P pacemaker "+self.action_timeout) - test.add_cmd_check_stdout("-c get_rsc_info -r rsc2 ", "id:rsc2 class:ocf provider:pacemaker type:Stateful") - test.add_cmd("-c unregister_rsc -r rsc2 "+self.action_timeout) - test.add_expected_fail_cmd("-c get_rsc_info -r rsc2 ") - - ### verify the option to only send notification to the original client. ### - test = self.new_test("notify_orig_client_only", "Verify option to only send notifications to the client originating the action.") - test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") - test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+" -n " - "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") - # this will fail because the monitor notifications should only go to the original caller, which no longer exists. - test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) - test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"6000\" ") - test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ - "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") - - ### get metadata ### - test = self.new_test("get_ocf_metadata", "Retrieve metadata for a resource") - test.add_cmd_check_stdout("-c metadata -C \"ocf\" -P \"pacemaker\" -T \"Dummy\"" - ,"resource-agent name=\"Dummy\"") - test.add_cmd("-c metadata -C \"ocf\" -P \"pacemaker\" -T \"Stateful\"") - test.add_expected_fail_cmd("-c metadata -P \"pacemaker\" -T \"Stateful\"") - test.add_expected_fail_cmd("-c metadata -C \"ocf\" -P \"pacemaker\" -T \"fake_agent\"") - - ### get metadata ### - test = self.new_test("get_lsb_metadata", "Retrieve metadata for a resource") - test.add_cmd_check_stdout("-c metadata -C \"lsb\" -T \"LSBDummy\"" - ,"resource-agent name='LSBDummy'") - - ### get stonith metadata ### - test = self.new_test("get_stonith_metadata", "Retrieve stonith metadata for a resource") - test.add_cmd_check_stdout("-c metadata -C \"stonith\" -P \"pacemaker\" -T \"fence_dummy_monitor\"", - "resource-agent name=\"fence_dummy_monitor\"") - - ### get metadata ### - if "systemd" in self.rsc_classes: - test = self.new_test("get_systemd_metadata", "Retrieve metadata for a resource") - test.add_cmd_check_stdout("-c metadata -C \"systemd\" -T \"lrmd_dummy_daemon\"" - ,"resource-agent name=\"lrmd_dummy_daemon\"") - - ### get metadata ### - if "upstart" in self.rsc_classes: - test = self.new_test("get_upstart_metadata", "Retrieve metadata for a resource") - test.add_cmd_check_stdout("-c metadata -C \"upstart\" -T \"lrmd_dummy_daemon\"" - ,"resource-agent name=\"lrmd_dummy_daemon\"") - - if "heartbeat" in self.rsc_classes: - test = self.new_test("get_heartbeat_metadata", "Retrieve metadata for a resource") - test.add_cmd_check_stdout("-c metadata -C \"heartbeat\" -T \"HBDummy\"" - ,"resource-agent name='HBDummy'") - - ### get ocf providers ### - test = self.new_test("list_ocf_providers", "Retrieve list of available resource providers, verifies pacemaker is a provider.") - test.add_cmd_check_stdout("-c list_ocf_providers ", "pacemaker") - test.add_cmd_check_stdout("-c list_ocf_providers -T ping", "pacemaker") - - ### Verify agents only exist in their lists ### - test = self.new_test("verify_agent_lists", "Verify the agent lists contain the right data.") - test.add_cmd_check_stdout("-c list_agents ", "Stateful") ### ocf ### - test.add_cmd_check_stdout("-c list_agents -C ocf", "Stateful") - test.add_cmd_check_stdout("-c list_agents -C lsb", "", "Stateful") ### should not exist - test.add_cmd_check_stdout("-c list_agents -C service", "", "Stateful") ### should not exist - test.add_cmd_check_stdout("-c list_agents ", "LSBDummy") ### init.d ### - test.add_cmd_check_stdout("-c list_agents -C lsb", "LSBDummy") - test.add_cmd_check_stdout("-c list_agents -C service", "LSBDummy") - test.add_cmd_check_stdout("-c list_agents -C ocf", "", "lrmd_dummy_daemon") ### should not exist - - test.add_cmd_check_stdout("-c list_agents -C ocf", "", "lrmd_dummy_daemon") ### should not exist - test.add_cmd_check_stdout("-c list_agents -C lsb", "", "fence_dummy_monitor") ### should not exist - test.add_cmd_check_stdout("-c list_agents -C service", "", "fence_dummy_monitor") ### should not exist - test.add_cmd_check_stdout("-c list_agents -C ocf", "", "fence_dummy_monitor") ### should not exist - - if "systemd" in self.rsc_classes: - test.add_cmd_check_stdout("-c list_agents ", "lrmd_dummy_daemon") ### systemd ### - test.add_cmd_check_stdout("-c list_agents -C service", "LSBDummy") - test.add_cmd_check_stdout("-c list_agents -C systemd", "", "Stateful") ### should not exist - test.add_cmd_check_stdout("-c list_agents -C systemd", "lrmd_dummy_daemon") - test.add_cmd_check_stdout("-c list_agents -C systemd", "", "fence_dummy_monitor") ### should not exist - - if "upstart" in self.rsc_classes: - test.add_cmd_check_stdout("-c list_agents ", "lrmd_dummy_daemon") ### upstart ### - test.add_cmd_check_stdout("-c list_agents -C service", "LSBDummy") - test.add_cmd_check_stdout("-c list_agents -C upstart", "", "Stateful") ### should not exist - test.add_cmd_check_stdout("-c list_agents -C upstart", "lrmd_dummy_daemon") - test.add_cmd_check_stdout("-c list_agents -C upstart", "", "fence_dummy_monitor") ### should not exist - - if "stonith" in self.rsc_classes: - test.add_cmd_check_stdout("-c list_agents -C stonith", "fence_dummy_monitor") ### stonith ### - test.add_cmd_check_stdout("-c list_agents -C stonith", "", "lrmd_dummy_daemon") ### should not exist - test.add_cmd_check_stdout("-c list_agents -C stonith", "", "Stateful") ### should not exist - test.add_cmd_check_stdout("-c list_agents ", "fence_dummy_monitor") - - if "heartbeat" in self.rsc_classes: - test.add_cmd_check_stdout("-c list_agents -C heartbeat", "HBDummy") - test.add_cmd_check_stdout("-c list_agents -C heartbeat", "", "LSBDummy") ### should not exist - test.add_cmd_check_stdout("-c list_agents -C service", "", "HBDummy") ### should not exist - - def print_list(self): - print "\n==== %d TESTS FOUND ====" % (len(self.tests)) - print "%35s - %s" % ("TEST NAME", "TEST DESCRIPTION") - print "%35s - %s" % ("--------------------", "--------------------") - for test in self.tests: - print "%35s - %s" % (test.name, test.description) - print "==== END OF LIST ====\n" - - def run_single(self, name): - for test in self.tests: - if test.name == name: - test.run() - break; - - def run_tests_matching(self, pattern): - for test in self.tests: - if test.name.count(pattern) != 0: - test.run() - - def run_tests(self): - for test in self.tests: - test.run() - - def exit(self): - for test in self.tests: - if test.executed == 0: - continue - - if test.get_exitcode() != 0: - sys.exit(-1) - - sys.exit(0); - - def print_results(self): - failures = 0; - success = 0; - print "\n\n======= FINAL RESULTS ==========" - print "\n--- FAILURE RESULTS:" - for test in self.tests: - if test.executed == 0: - continue - - if test.get_exitcode() != 0: - failures = failures + 1 - test.print_result(" ") - else: - success = success + 1 - - if failures == 0: - print " None" - - print "\n--- TOTALS\n Pass:%d\n Fail:%d\n" % (success, failures) + ### These are tests that should apply to all resource classes ### + def build_generic_tests(self): + common_cmds = self.common_cmds + + ### register/unregister tests ### + for rsc in self.rsc_classes: + test = self.new_test("generic_registration_%s" % (rsc), "Simple resource registration test for %s standard" % (rsc)) + test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) + test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) + + ### start/stop tests ### + for rsc in self.rsc_classes: + test = self.new_test("generic_start_stop_%s" % (rsc), "Simple start and stop test for %s standard" % (rsc)) + test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) + test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) + test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) + test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) + + ### monitor cancel test ### + for rsc in self.rsc_classes: + test = self.new_test("generic_monitor_cancel_%s" % (rsc), "Simple monitor cancel test for %s standard" % (rsc)) + test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) + test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) + test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) + test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### + test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### + test.add_cmd(common_cmds["%s_cancel_line" % (rsc)] + " " + common_cmds["%s_cancel_event" % (rsc)]) + test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### + test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### + test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) + test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) + + ### monitor duplicate test ### + for rsc in self.rsc_classes: + test = self.new_test("generic_monitor_duplicate_%s" % (rsc), "Test creation and canceling of duplicate monitors for %s standard" % (rsc)) + test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) + test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) + test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) + test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### + test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### + + # Add the duplicate monitors. + test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) + test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) + test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) + test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) + # verify we still get update events + test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### + + # cancel the monitor, if the duplicate merged with the original, we should no longer see monitor updates + test.add_cmd(common_cmds["%s_cancel_line" % (rsc)] + " " + common_cmds["%s_cancel_event" % (rsc)]) + test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### + test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### + test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) + test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) + + ### stop implies cancel test ### + for rsc in self.rsc_classes: + test = self.new_test("generic_stop_implies_cancel_%s" % (rsc), "Verify stopping a resource implies cancel of recurring ops for %s standard" % (rsc)) + test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) + test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) + test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) + test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### + test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor may not be getting rescheduled #### + test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) + test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### + test.add_expected_fail_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this happens the monitor did not actually cancel correctly. ### + test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) + + + ### These are complex tests that involve managing multiple resouces of different types ### + def build_multi_rsc_tests(self): + common_cmds = self.common_cmds + # do not use service and systemd at the same time, it is the same resource. + + ### register start monitor stop unregister resources of each type at the same time. ### + test = self.new_test("multi_rsc_start_stop_all", "Start, monitor, and stop resources of multiple types and classes") + for rsc in self.rsc_classes: + test.add_cmd(common_cmds["%s_reg_line" % (rsc)] + " " + common_cmds["%s_reg_event" % (rsc)]) + for rsc in self.rsc_classes: + test.add_cmd(common_cmds["%s_start_line" % (rsc)] + " " + common_cmds["%s_start_event" % (rsc)]) + for rsc in self.rsc_classes: + test.add_cmd(common_cmds["%s_monitor_line" % (rsc)] + " " + common_cmds["%s_monitor_event" % (rsc)]) + for rsc in self.rsc_classes: + test.add_cmd(common_cmds["%s_monitor_event" % (rsc)]) ### If this fails, that means the monitor is not being rescheduled #### + for rsc in self.rsc_classes: + test.add_cmd(common_cmds["%s_cancel_line" % (rsc)] + " " + common_cmds["%s_cancel_event" % (rsc)]) + for rsc in self.rsc_classes: + test.add_cmd(common_cmds["%s_stop_line" % (rsc)] + " " + common_cmds["%s_stop_event" % (rsc)]) + for rsc in self.rsc_classes: + test.add_cmd(common_cmds["%s_unreg_line" % (rsc)] + " " + common_cmds["%s_unreg_event" % (rsc)]) + + ### These are tests related to how the lrmd handles failures. ### + def build_negative_tests(self): + + ### ocf start timeout test ### + test = self.new_test("ocf_start_timeout", "Force start timeout to occur, verify start failure.") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" -k \"op_sleep\" -v \"5\" -t 1000 -w") # -t must be less than self.action_timeout + test.add_cmd("-l " + "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:unknown error op_status:Timed Out\" "+self.action_timeout) + test.add_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") + test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + + ### stonith start timeout test ### + test = self.new_test("stonith_start_timeout", "Force start timeout to occur, verify start failure.") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"stonith\" -P \"pacemaker\" -T \"fence_dummy_sleep\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" -t 1000 -w") # -t must be less than self.action_timeout + test.add_cmd("-l " + "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:unknown error op_status:Timed Out\" "+self.action_timeout) + test.add_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") + test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### stonith component fail ### + common_cmds = self.common_cmds + test = self.new_test("stonith_component_fail", "Kill stonith component after lrmd connects") + test.add_cmd(common_cmds["stonith_reg_line"] + " " + common_cmds["stonith_reg_event"]) + test.add_cmd(common_cmds["stonith_start_line"] + " " + common_cmds["stonith_start_event"]) + + test.add_cmd("-c exec -r \"stonith_test_rsc\" -a \"monitor\" -i \"600000\" " + "-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + + test.add_cmd_and_kill("killall -9 -q stonithd lt-stonithd" ,"-l \"NEW_EVENT event_type:exec_complete rsc_id:stonith_test_rsc action:monitor rc:unknown error op_status:error\" -t 15000") + test.add_cmd(common_cmds["stonith_unreg_line"] + " " + common_cmds["stonith_unreg_event"]) + + + ### monitor fail for ocf resources ### + test = self.new_test("monitor_fail_ocf", "Force ocf monitor to fail, verify failure is reported.") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") + test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd_and_kill("rm -f @localstatedir@/run/Dummy-test_rsc.state", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 6000") + test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"6000\" " + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") + test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) + test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### verify notify changes only for monitor operation. ### + test = self.new_test("monitor_changes_only", "Verify when flag is set, only monitor changes are notified.") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+" -o " + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+" -o " + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") + test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd_and_kill("rm -f @localstatedir@/run/Dummy-test_rsc.state", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 6000") + test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"6000\" " + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") + test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) + test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### monitor fail for systemd resource ### + if "systemd" in self.rsc_classes: + test = self.new_test("monitor_fail_systemd", "Force systemd monitor to fail, verify failure is reported..") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C systemd -T lrmd_dummy_daemon "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") + test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd_and_kill("killall -9 -q lrmd_dummy_daemon", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 8000") + test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"6000\" " + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") + test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) + test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### monitor fail for upstart resource ### + if "upstart" in self.rsc_classes: + test = self.new_test("monitor_fail_upstart", "Force upstart monitor to fail, verify failure is reported..") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C upstart -T lrmd_dummy_daemon "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") + test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd_and_kill("killall -9 -q dd", "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" -t 8000") + test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"6000\" " + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") + test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:complete\" "+self.action_timeout) + test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### Cancel non-existent operation on a resource ### + test = self.new_test("cancel_non_existent_op", "Attempt to cancel the wrong monitor operation, verify expected failure") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") + test.add_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_expected_fail_cmd("-c cancel -r test_rsc -a \"monitor\" -i 1234 -t \"6000\" " ### interval is wrong, should fail + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") + test.add_expected_fail_cmd("-c cancel -r test_rsc -a stop -i 100 -t \"6000\" " ### action name is wrong, should fail + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:not running op_status:Cancelled\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### Attempt to invoke non-existent rsc id ### + test = self.new_test("invoke_non_existent_rsc", "Attempt to perform operations on a non-existent rsc id.") + test.add_expected_fail_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:unknown error op_status:complete\" ") + test.add_expected_fail_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") + test.add_expected_fail_cmd("-c exec -r test_rsc -a monitor -i 6000 "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") + test.add_expected_fail_cmd("-c cancel -r test_rsc -a start "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:Cancelled\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### Register and start a resource that doesn't exist, systemd ### + if "systemd" in self.rsc_classes: + test = self.new_test("start_uninstalled_systemd", "Register uninstalled systemd agent, try to start, verify expected failure") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C systemd -T this_is_fake1234 "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + if "upstart" in self.rsc_classes: + test = self.new_test("start_uninstalled_upstart", "Register uninstalled upstart agent, try to start, verify expected failure") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C upstart -T this_is_fake1234 "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### Register and start a resource that doesn't exist, ocf ### + test = self.new_test("start_uninstalled_ocf", "Register uninstalled ocf agent, try to start, verify expected failure.") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C ocf -P pacemaker -T this_is_fake1234 "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### Register ocf with non-existent provider ### + test = self.new_test("start_ocf_bad_provider", "Register ocf agent with a non-existent provider, verify expected failure.") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C ocf -P pancakes -T Dummy "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:not installed op_status:Not installed\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### Register ocf with empty provider field ### + test = self.new_test("start_ocf_no_provider", "Register ocf agent with a no provider, verify expected failure.") + test.add_expected_fail_cmd("-c register_rsc -r \"test_rsc\" -C ocf -T Dummy "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_expected_fail_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:Error\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### stress tests ### + def build_stress_tests(self): + timeout = "-t 20000" + + iterations = 25 + test = self.new_test("ocf_stress", "Verify OCF agent handling works under load") + for i in range(iterations): + test.add_cmd("-c register_rsc -r rsc_%s %s -C ocf -P heartbeat -T Dummy -l \"NEW_EVENT event_type:register rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) + test.add_cmd("-c exec -r rsc_%s -a start %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:start rc:ok op_status:complete\"" % (i, timeout, i)) + test.add_cmd("-c exec -r rsc_%s -a monitor %s -i 1000 -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:monitor rc:ok op_status:complete\"" % (i, timeout, i)) + for i in range(iterations): + test.add_cmd("-c exec -r rsc_%s -a stop %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:stop rc:ok op_status:complete\"" % (i, timeout, i)) + test.add_cmd("-c unregister_rsc -r rsc_%s %s -l \"NEW_EVENT event_type:unregister rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) + + + if "systemd" in self.rsc_classes: + test = self.new_test("systemd_stress", "Verify systemd dbus connection works under load") + for i in range(iterations): + test.add_cmd("-c register_rsc -r rsc_%s %s -C systemd -T lrmd_dummy_daemon -l \"NEW_EVENT event_type:register rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) + test.add_cmd("-c exec -r rsc_%s -a start %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:start rc:ok op_status:complete\"" % (i, timeout, i)) + test.add_cmd("-c exec -r rsc_%s -a monitor %s -i 1000 -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:monitor rc:ok op_status:complete\"" % (i, timeout, i)) + + for i in range(iterations): + test.add_cmd("-c exec -r rsc_%s -a stop %s -l \"NEW_EVENT event_type:exec_complete rsc_id:rsc_%s action:stop rc:ok op_status:complete\"" % (i, timeout, i)) + test.add_cmd("-c unregister_rsc -r rsc_%s %s -l \"NEW_EVENT event_type:unregister rsc_id:rsc_%s action:none rc:ok op_status:complete\"" % (i, timeout, i)) + + iterations = 9 + timeout = "-t 30000" + ### Verify recurring op in-flight collision is handled in series properly + test = self.new_test("rsc_inflight_collision", "Verify recurring ops do not collide with other operations for the same rsc.") + test.add_cmd("-c register_rsc -r test_rsc -P pacemaker -C ocf -T Dummy " + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-c exec -r test_rsc -a start %s -k op_sleep -v 1 -l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\"" % (timeout)) + for i in range(iterations): + test.add_cmd("-c exec -r test_rsc -a monitor %s -i 100%d -k op_sleep -v 2 -l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\"" % (timeout, i)) +# test.add_sys_cmd("sleep", "-al @CRM_RSCTMP_DIR@") + + test.add_cmd("-c exec -r test_rsc -a stop %s -l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\"" % (timeout)) + test.add_cmd("-c unregister_rsc -r test_rsc %s -l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\"" % (timeout)) + + ### These are tests that target specific cases ### + def build_custom_tests(self): + + + ### verify resource temporary folder is created and used by heartbeat agents. ### + test = self.new_test("rsc_tmp_dir", "Verify creation and use of rsc temporary state directory") + test.add_sys_cmd("ls", "-al @CRM_RSCTMP_DIR@") + test.add_cmd("-c register_rsc -r test_rsc -P heartbeat -C ocf -T Dummy " + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-c exec -r test_rsc -a start -t 4000") + test.add_sys_cmd("ls", "-al @CRM_RSCTMP_DIR@") + test.add_sys_cmd("ls", "@CRM_RSCTMP_DIR@/Dummy-test_rsc.state") + test.add_cmd("-c exec -r test_rsc -a stop -t 4000") + test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### start delay then stop test ### + test = self.new_test("start_delay", "Verify start delay works as expected.") + test.add_cmd("-c register_rsc -r test_rsc -P pacemaker -C ocf -T Dummy " + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-c exec -r test_rsc -s 6000 -a start -w -t 6000") + test.add_expected_fail_cmd("-l " + "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" -t 2000") + test.add_cmd("-l " + "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" -t 6000") + test.add_cmd("-c exec -r test_rsc -a stop "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:stop rc:ok op_status:complete\" ") + test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### start delay, but cancel before it gets a chance to start. ### + test = self.new_test("start_delay_cancel", "Using start_delay, start a rsc, but cancel the start op before execution.") + test.add_cmd("-c register_rsc -r test_rsc -P pacemaker -C ocf -T Dummy " + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-c exec -r test_rsc -s 5000 -a start -w -t 4000") + test.add_cmd("-c cancel -r test_rsc -a start "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:Cancelled\" ") + test.add_expected_fail_cmd("-l " + "\"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" -t 5000") + test.add_cmd("-c unregister_rsc -r test_rsc "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### Register a bunch of resources, verify we can get info on them ### + test = self.new_test("verify_get_rsc_info", "Register multiple resources, verify retrieval of rsc info.") + if "systemd" in self.rsc_classes: + test.add_cmd("-c register_rsc -r rsc1 -C systemd -T lrmd_dummy_daemon "+self.action_timeout) + test.add_cmd("-c get_rsc_info -r rsc1 ") + test.add_cmd("-c unregister_rsc -r rsc1 "+self.action_timeout) + test.add_expected_fail_cmd("-c get_rsc_info -r rsc1 ") + + if "upstart" in self.rsc_classes: + test.add_cmd("-c register_rsc -r rsc1 -C upstart -T lrmd_dummy_daemon "+self.action_timeout) + test.add_cmd("-c get_rsc_info -r rsc1 ") + test.add_cmd("-c unregister_rsc -r rsc1 "+self.action_timeout) + test.add_expected_fail_cmd("-c get_rsc_info -r rsc1 ") + + test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Dummy -P pacemaker "+self.action_timeout) + test.add_cmd("-c get_rsc_info -r rsc2 ") + test.add_cmd("-c unregister_rsc -r rsc2 "+self.action_timeout) + test.add_expected_fail_cmd("-c get_rsc_info -r rsc2 ") + + ### Register duplicate, verify only one entry exists and can still be removed. + test = self.new_test("duplicate_registration", "Register resource multiple times, verify only one entry exists and can be removed.") + test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Dummy -P pacemaker "+self.action_timeout) + test.add_cmd_check_stdout("-c get_rsc_info -r rsc2 ", "id:rsc2 class:ocf provider:pacemaker type:Dummy") + test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Dummy -P pacemaker "+self.action_timeout) + test.add_cmd_check_stdout("-c get_rsc_info -r rsc2 ", "id:rsc2 class:ocf provider:pacemaker type:Dummy") + test.add_cmd("-c register_rsc -r rsc2 -C ocf -T Stateful -P pacemaker "+self.action_timeout) + test.add_cmd_check_stdout("-c get_rsc_info -r rsc2 ", "id:rsc2 class:ocf provider:pacemaker type:Stateful") + test.add_cmd("-c unregister_rsc -r rsc2 "+self.action_timeout) + test.add_expected_fail_cmd("-c get_rsc_info -r rsc2 ") + + ### verify the option to only send notification to the original client. ### + test = self.new_test("notify_orig_client_only", "Verify option to only send notifications to the client originating the action.") + test.add_cmd("-c register_rsc -r \"test_rsc\" -C \"ocf\" -P \"pacemaker\" -T \"Dummy\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"start\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:start rc:ok op_status:complete\" ") + test.add_cmd("-c exec -r \"test_rsc\" -a \"monitor\" -i \"100\" "+self.action_timeout+" -n " + "-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" ") + # this will fail because the monitor notifications should only go to the original caller, which no longer exists. + test.add_expected_fail_cmd("-l \"NEW_EVENT event_type:exec_complete rsc_id:test_rsc action:monitor rc:ok op_status:complete\" "+self.action_timeout) + test.add_cmd("-c cancel -r \"test_rsc\" -a \"monitor\" -i \"100\" -t \"6000\" ") + test.add_cmd("-c unregister_rsc -r \"test_rsc\" "+self.action_timeout+ + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + ### Verify that versioned resource parameters are chosen properly + + # We'll default to one state file, then check the version to use a different one + state_file_default = "@CRM_RSCTMP_DIR@/versioned_params_default.state" + state_file_expected = "@CRM_RSCTMP_DIR@/versioned_params_expected.state" + + # Versioned attributes are passed as a single key-value pair. + # Here, we define the value to choose the state file; + # ocf:heartbeat:Dummy should always be at least version 0.9. + versioned_key = "#versioned_attributes" + versioned_attrs = """ + + + + + + + + + + """ % (state_file_expected, state_file_default) + cmd_params = "-k '%s' -v '%s' " % (versioned_key, versioned_attrs) + + test = self.new_test("versioned_params", "Verify use of versioned resource parameters") + + # First, remove the possible state files, so we can reliably tell what gets created. + test.add_sys_cmd("rm", "-f %s %s" % (state_file_expected, state_file_default)) + + # Register and start the resource. + test.add_cmd("-c register_rsc -r test_rsc -P heartbeat -C ocf -T Dummy " + "-l 'NEW_EVENT event_type:register rsc_id:test_rsc action:none rc:ok op_status:complete' " + "%s" % (self.action_timeout)) + test.add_cmd("-c exec -r test_rsc -a start -t 6000 %s" % cmd_params) + + # Check the created state file. + test.add_expected_fail_sys_cmd("ls", state_file_default, 2) + test.add_sys_cmd("ls", state_file_expected) + + # Stop and unregister the resource. + test.add_cmd("-c exec -r test_rsc -a stop -t 4000 %s" % cmd_params) + test.add_cmd("-c unregister_rsc -r test_rsc " + self.action_timeout + + "-l \"NEW_EVENT event_type:unregister rsc_id:test_rsc action:none rc:ok op_status:complete\" ") + + + ### get metadata ### + test = self.new_test("get_ocf_metadata", "Retrieve metadata for a resource") + test.add_cmd_check_stdout("-c metadata -C \"ocf\" -P \"pacemaker\" -T \"Dummy\"" + ,"resource-agent name=\"Dummy\"") + test.add_cmd("-c metadata -C \"ocf\" -P \"pacemaker\" -T \"Stateful\"") + test.add_expected_fail_cmd("-c metadata -P \"pacemaker\" -T \"Stateful\"") + test.add_expected_fail_cmd("-c metadata -C \"ocf\" -P \"pacemaker\" -T \"fake_agent\"") + + ### get metadata ### + test = self.new_test("get_lsb_metadata", "Retrieve metadata for a resource") + test.add_cmd_check_stdout("-c metadata -C \"lsb\" -T \"LSBDummy\"" + ,"resource-agent name='LSBDummy'") + + ### get stonith metadata ### + test = self.new_test("get_stonith_metadata", "Retrieve stonith metadata for a resource") + test.add_cmd_check_stdout("-c metadata -C \"stonith\" -P \"pacemaker\" -T \"fence_dummy_monitor\"", + "resource-agent name=\"fence_dummy_monitor\"") + + ### get metadata ### + if "systemd" in self.rsc_classes: + test = self.new_test("get_systemd_metadata", "Retrieve metadata for a resource") + test.add_cmd_check_stdout("-c metadata -C \"systemd\" -T \"lrmd_dummy_daemon\"" + ,"resource-agent name=\"lrmd_dummy_daemon\"") + + ### get metadata ### + if "upstart" in self.rsc_classes: + test = self.new_test("get_upstart_metadata", "Retrieve metadata for a resource") + test.add_cmd_check_stdout("-c metadata -C \"upstart\" -T \"lrmd_dummy_daemon\"" + ,"resource-agent name=\"lrmd_dummy_daemon\"") + + if "heartbeat" in self.rsc_classes: + test = self.new_test("get_heartbeat_metadata", "Retrieve metadata for a resource") + test.add_cmd_check_stdout("-c metadata -C \"heartbeat\" -T \"HBDummy\"" + ,"resource-agent name='HBDummy'") + + ### get ocf providers ### + test = self.new_test("list_ocf_providers", "Retrieve list of available resource providers, verifies pacemaker is a provider.") + test.add_cmd_check_stdout("-c list_ocf_providers ", "pacemaker") + test.add_cmd_check_stdout("-c list_ocf_providers -T ping", "pacemaker") + + ### Verify agents only exist in their lists ### + test = self.new_test("verify_agent_lists", "Verify the agent lists contain the right data.") + test.add_cmd_check_stdout("-c list_agents ", "Stateful") ### ocf ### + test.add_cmd_check_stdout("-c list_agents -C ocf", "Stateful") + test.add_cmd_check_stdout("-c list_agents -C lsb", "", "Stateful") ### should not exist + test.add_cmd_check_stdout("-c list_agents -C service", "", "Stateful") ### should not exist + test.add_cmd_check_stdout("-c list_agents ", "LSBDummy") ### init.d ### + test.add_cmd_check_stdout("-c list_agents -C lsb", "LSBDummy") + test.add_cmd_check_stdout("-c list_agents -C service", "LSBDummy") + test.add_cmd_check_stdout("-c list_agents -C ocf", "", "lrmd_dummy_daemon") ### should not exist + + test.add_cmd_check_stdout("-c list_agents -C ocf", "", "lrmd_dummy_daemon") ### should not exist + test.add_cmd_check_stdout("-c list_agents -C lsb", "", "fence_dummy_monitor") ### should not exist + test.add_cmd_check_stdout("-c list_agents -C service", "", "fence_dummy_monitor") ### should not exist + test.add_cmd_check_stdout("-c list_agents -C ocf", "", "fence_dummy_monitor") ### should not exist + + if "systemd" in self.rsc_classes: + test.add_cmd_check_stdout("-c list_agents ", "lrmd_dummy_daemon") ### systemd ### + test.add_cmd_check_stdout("-c list_agents -C service", "LSBDummy") + test.add_cmd_check_stdout("-c list_agents -C systemd", "", "Stateful") ### should not exist + test.add_cmd_check_stdout("-c list_agents -C systemd", "lrmd_dummy_daemon") + test.add_cmd_check_stdout("-c list_agents -C systemd", "", "fence_dummy_monitor") ### should not exist + + if "upstart" in self.rsc_classes: + test.add_cmd_check_stdout("-c list_agents ", "lrmd_dummy_daemon") ### upstart ### + test.add_cmd_check_stdout("-c list_agents -C service", "LSBDummy") + test.add_cmd_check_stdout("-c list_agents -C upstart", "", "Stateful") ### should not exist + test.add_cmd_check_stdout("-c list_agents -C upstart", "lrmd_dummy_daemon") + test.add_cmd_check_stdout("-c list_agents -C upstart", "", "fence_dummy_monitor") ### should not exist + + if "stonith" in self.rsc_classes: + test.add_cmd_check_stdout("-c list_agents -C stonith", "fence_dummy_monitor") ### stonith ### + test.add_cmd_check_stdout("-c list_agents -C stonith", "", "lrmd_dummy_daemon") ### should not exist + test.add_cmd_check_stdout("-c list_agents -C stonith", "", "Stateful") ### should not exist + test.add_cmd_check_stdout("-c list_agents ", "fence_dummy_monitor") + + if "heartbeat" in self.rsc_classes: + test.add_cmd_check_stdout("-c list_agents -C heartbeat", "HBDummy") + test.add_cmd_check_stdout("-c list_agents -C heartbeat", "", "LSBDummy") ### should not exist + test.add_cmd_check_stdout("-c list_agents -C service", "", "HBDummy") ### should not exist + + def print_list(self): + print "\n==== %d TESTS FOUND ====" % (len(self.tests)) + print "%35s - %s" % ("TEST NAME", "TEST DESCRIPTION") + print "%35s - %s" % ("--------------------", "--------------------") + for test in self.tests: + print "%35s - %s" % (test.name, test.description) + print "==== END OF LIST ====\n" + + def run_single(self, name): + for test in self.tests: + if test.name == name: + test.run() + break; + + def run_tests_matching(self, pattern): + for test in self.tests: + if test.name.count(pattern) != 0: + test.run() + + def run_tests(self): + for test in self.tests: + test.run() + + def exit(self): + for test in self.tests: + if test.executed == 0: + continue + + if test.get_exitcode() != 0: + sys.exit(-1) + + sys.exit(0); + + def print_results(self): + failures = 0; + success = 0; + print "\n\n======= FINAL RESULTS ==========" + print "\n--- FAILURE RESULTS:" + for test in self.tests: + if test.executed == 0: + continue + + if test.get_exitcode() != 0: + failures = failures + 1 + test.print_result(" ") + else: + success = success + 1 + + if failures == 0: + print " None" + + print "\n--- TOTALS\n Pass:%d\n Fail:%d\n" % (success, failures) class TestOptions: - def __init__(self): - self.options = {} - self.options['list-tests'] = 0 - self.options['run-all'] = 1 - self.options['run-only'] = "" - self.options['run-only-pattern'] = "" - self.options['verbose'] = 0 - self.options['invalid-arg'] = "" - self.options['show-usage'] = 0 - self.options['pacemaker-remote'] = 0 - - def build_options(self, argv): - args = argv[1:] - skip = 0 - for i in range(0, len(args)): - if skip: - skip = 0 - continue - elif args[i] == "-h" or args[i] == "--help": - self.options['show-usage'] = 1 - elif args[i] == "-l" or args[i] == "--list-tests": - self.options['list-tests'] = 1 - elif args[i] == "-V" or args[i] == "--verbose": - self.options['verbose'] = 1 - elif args[i] == "-R" or args[i] == "--pacemaker-remote": - self.options['pacemaker-remote'] = 1 - elif args[i] == "-r" or args[i] == "--run-only": - self.options['run-only'] = args[i+1] - skip = 1 - elif args[i] == "-p" or args[i] == "--run-only-pattern": - self.options['run-only-pattern'] = args[i+1] - skip = 1 - - def show_usage(self): - print "usage: " + sys.argv[0] + " [options]" - print "If no options are provided, all tests will run" - print "Options:" - print "\t [--help | -h] Show usage" - print "\t [--list-tests | -l] Print out all registered tests." - print "\t [--run-only | -r 'testname'] Run a specific test" - print "\t [--verbose | -V] Verbose output" - print "\t [--pacemaker-remote | -R Test pacemaker-remote binary instead of lrmd." - print "\t [--run-only-pattern | -p 'string'] Run only tests containing the string value" - print "\n\tExample: Run only the test 'start_top'" - print "\t\t python ./regression.py --run-only start_stop" - print "\n\tExample: Run only the tests with the string 'systemd' present in them" - print "\t\t python ./regression.py --run-only-pattern systemd" + def __init__(self): + self.options = {} + self.options['list-tests'] = 0 + self.options['run-all'] = 1 + self.options['run-only'] = "" + self.options['run-only-pattern'] = "" + self.options['verbose'] = 0 + self.options['invalid-arg'] = "" + self.options['show-usage'] = 0 + self.options['pacemaker-remote'] = 0 + + def build_options(self, argv): + args = argv[1:] + skip = 0 + for i in range(0, len(args)): + if skip: + skip = 0 + continue + elif args[i] == "-h" or args[i] == "--help": + self.options['show-usage'] = 1 + elif args[i] == "-l" or args[i] == "--list-tests": + self.options['list-tests'] = 1 + elif args[i] == "-V" or args[i] == "--verbose": + self.options['verbose'] = 1 + elif args[i] == "-R" or args[i] == "--pacemaker-remote": + self.options['pacemaker-remote'] = 1 + elif args[i] == "-r" or args[i] == "--run-only": + self.options['run-only'] = args[i+1] + skip = 1 + elif args[i] == "-p" or args[i] == "--run-only-pattern": + self.options['run-only-pattern'] = args[i+1] + skip = 1 + + def show_usage(self): + print "usage: " + sys.argv[0] + " [options]" + print "If no options are provided, all tests will run" + print "Options:" + print "\t [--help | -h] Show usage" + print "\t [--list-tests | -l] Print out all registered tests." + print "\t [--run-only | -r 'testname'] Run a specific test" + print "\t [--verbose | -V] Verbose output" + print "\t [--pacemaker-remote | -R Test pacemaker-remote binary instead of lrmd." + print "\t [--run-only-pattern | -p 'string'] Run only tests containing the string value" + print "\n\tExample: Run only the test 'start_top'" + print "\t\t python ./regression.py --run-only start_stop" + print "\n\tExample: Run only the tests with the string 'systemd' present in them" + print "\t\t python ./regression.py --run-only-pattern systemd" def main(argv): - o = TestOptions() - o.build_options(argv) - - tests = Tests(o.options['verbose'], o.options['pacemaker-remote']) - - tests.build_generic_tests() - tests.build_multi_rsc_tests() - tests.build_negative_tests() - tests.build_custom_tests() - tests.build_stress_tests() - - tests.setup_test_environment() - - print "Starting ..." - - if o.options['list-tests']: - tests.print_list() - elif o.options['show-usage']: - o.show_usage() - elif o.options['run-only-pattern'] != "": - tests.run_tests_matching(o.options['run-only-pattern']) - tests.print_results() - elif o.options['run-only'] != "": - tests.run_single(o.options['run-only']) - tests.print_results() - else: - tests.run_tests() - tests.print_results() - - tests.cleanup_test_environment() - tests.exit() + o = TestOptions() + o.build_options(argv) + + tests = Tests(o.options['verbose'], o.options['pacemaker-remote']) + + tests.build_generic_tests() + tests.build_multi_rsc_tests() + tests.build_negative_tests() + tests.build_custom_tests() + tests.build_stress_tests() + + tests.setup_test_environment() + + print "Starting ..." + + if o.options['list-tests']: + tests.print_list() + elif o.options['show-usage']: + o.show_usage() + elif o.options['run-only-pattern'] != "": + tests.run_tests_matching(o.options['run-only-pattern']) + tests.print_results() + elif o.options['run-only'] != "": + tests.run_single(o.options['run-only']) + tests.print_results() + else: + tests.run_tests() + tests.print_results() + + tests.cleanup_test_environment() + tests.exit() if __name__=="__main__": - main(sys.argv) + main(sys.argv) diff --git a/pengine/regression.sh b/pengine/regression.sh index 22ad3bfc30..56c3a07ac0 100755 --- a/pengine/regression.sh +++ b/pengine/regression.sh @@ -1,846 +1,849 @@ #!/bin/bash # Copyright (C) 2004 Andrew Beekhof # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This software is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # core=`dirname $0` . $core/regression.core.sh || exit 1 create_mode="true" info Generating test outputs for these tests... # do_test file description info Done. echo "" info Performing the following tests from $io_dir create_mode="false" echo "" do_test simple1 "Offline " do_test simple2 "Start " do_test simple3 "Start 2 " do_test simple4 "Start Failed" do_test simple6 "Stop Start " do_test simple7 "Shutdown " #do_test simple8 "Stonith " #do_test simple9 "Lower version" #do_test simple10 "Higher version" do_test simple11 "Priority (ne)" do_test simple12 "Priority (eq)" do_test simple8 "Stickiness" echo "" do_test group1 "Group " do_test group2 "Group + Native " do_test group3 "Group + Group " do_test group4 "Group + Native (nothing)" do_test group5 "Group + Native (move) " do_test group6 "Group + Group (move) " do_test group7 "Group colocation" do_test group13 "Group colocation (cant run)" do_test group8 "Group anti-colocation" do_test group9 "Group recovery" do_test group10 "Group partial recovery" do_test group11 "Group target_role" do_test group14 "Group stop (graph terminated)" do_test group15 "-ve group colocation" do_test bug-1573 "Partial stop of a group with two children" do_test bug-1718 "Mandatory group ordering - Stop group_FUN" do_test bug-lf-2613 "Move group on failure" do_test bug-lf-2619 "Move group on clone failure" do_test group-fail "Ensure stop order is preserved for partially active groups" do_test group-unmanaged "No need to restart r115 because r114 is unmanaged" do_test group-unmanaged-stopped "Make sure r115 is stopped when r114 fails" do_test group-dependents "Account for the location preferences of things colocated with a group" echo "" do_test rsc_dep1 "Must not " do_test rsc_dep3 "Must " do_test rsc_dep5 "Must not 3 " do_test rsc_dep7 "Must 3 " do_test rsc_dep10 "Must (but cant)" do_test rsc_dep2 "Must (running) " do_test rsc_dep8 "Must (running : alt) " do_test rsc_dep4 "Must (running + move)" do_test asymmetric "Asymmetric - require explicit location constraints" echo "" do_test orphan-0 "Orphan ignore" do_test orphan-1 "Orphan stop" do_test orphan-2 "Orphan stop, remove failcount" echo "" do_test params-0 "Params: No change" do_test params-1 "Params: Changed" do_test params-2 "Params: Resource definition" do_test params-4 "Params: Reload" do_test params-5 "Params: Restart based on probe digest" do_test novell-251689 "Resource definition change + target_role=stopped" do_test bug-lf-2106 "Restart all anonymous clone instances after config change" do_test params-6 "Params: Detect reload in previously migrated resource" do_test nvpair-id-ref "Support id-ref in nvpair with optional name" do_test not-reschedule-unneeded-monitor "Do not reschedule unneeded monitors while resource definitions have changed" echo "" do_test target-0 "Target Role : baseline" do_test target-1 "Target Role : master" do_test target-2 "Target Role : invalid" echo "" do_test base-score "Set a node's default score for all nodes" echo "" do_test date-1 "Dates" -t "2005-020" do_test date-2 "Date Spec - Pass" -t "2005-020T12:30" do_test date-3 "Date Spec - Fail" -t "2005-020T11:30" do_test origin "Timing of recurring operations" -t "2014-05-07 00:28:00" do_test probe-0 "Probe (anon clone)" do_test probe-1 "Pending Probe" do_test probe-2 "Correctly re-probe cloned groups" do_test probe-3 "Probe (pending node)" do_test probe-4 "Probe (pending node + stopped resource)" do_test standby "Standby" do_test comments "Comments" echo "" do_test one-or-more-0 "Everything starts" do_test one-or-more-1 "Nothing starts because of A" do_test one-or-more-2 "D can start because of C" do_test one-or-more-3 "D cannot start because of B and C" do_test one-or-more-4 "D cannot start because of target-role" do_test one-or-more-5 "Start A and F even though C and D are stopped" do_test one-or-more-6 "Leave A running even though B is stopped" do_test one-or-more-7 "Leave A running even though C is stopped" do_test bug-5140-require-all-false "Allow basegrp:0 to stop" do_test clone-require-all-1 "clone B starts node 3 and 4" do_test clone-require-all-2 "clone B remains stopped everywhere" do_test clone-require-all-3 "clone B stops everywhere because A stops everywhere" do_test clone-require-all-4 "clone B remains on node 3 and 4 with only one instance of A remaining." do_test clone-require-all-5 "clone B starts on node 1 3 and 4" do_test clone-require-all-6 "clone B remains active after shutting down instances of A" do_test clone-require-all-7 "clone A and B both start at the same time. all instances of A start before B." do_test clone-require-all-no-interleave-1 "C starts everywhere after A and B" do_test clone-require-all-no-interleave-2 "C starts on nodes 1, 2, and 4 with only one active instance of B" do_test clone-require-all-no-interleave-3 "C remains active when instance of B is stopped on one node and started on another." do_test one-or-more-unrunnnable-instances "Avoid dependencies on instances that wont ever be started" echo "" do_test order1 "Order start 1 " do_test order2 "Order start 2 " do_test order3 "Order stop " do_test order4 "Order (multiple) " do_test order5 "Order (move) " do_test order6 "Order (move w/ restart) " do_test order7 "Order (mandatory) " do_test order-optional "Order (score=0) " do_test order-required "Order (score=INFINITY) " do_test bug-lf-2171 "Prevent group start when clone is stopped" do_test order-clone "Clone ordering should be able to prevent startup of dependent clones" do_test order-sets "Ordering for resource sets" do_test order-serialize "Serialize resources without inhibiting migration" do_test order-serialize-set "Serialize a set of resources without inhibiting migration" do_test clone-order-primitive "Order clone start after a primitive" do_test clone-order-16instances "Verify ordering of 16 cloned resources" do_test order-optional-keyword "Order (optional keyword)" do_test order-mandatory "Order (mandatory keyword)" do_test bug-lf-2493 "Don't imply colocation requirements when applying ordering constraints with clones" do_test ordered-set-basic-startup "Constraint set with default order settings." do_test ordered-set-natural "Allow natural set ordering" do_test order-wrong-kind "Order (error)" echo "" do_test coloc-loop "Colocation - loop" do_test coloc-many-one "Colocation - many-to-one" do_test coloc-list "Colocation - many-to-one with list" do_test coloc-group "Colocation - groups" do_test coloc-slave-anti "Anti-colocation with slave shouldn't prevent master colocation" do_test coloc-attr "Colocation based on node attributes" do_test coloc-negative-group "Negative colocation with a group" do_test coloc-intra-set "Intra-set colocation" do_test bug-lf-2435 "Colocation sets with a negative score" do_test coloc-clone-stays-active "Ensure clones don't get stopped/demoted because a dependent must stop" do_test coloc_fp_logic "Verify floating point calculations in colocation are working" do_test colo_master_w_native "cl#5070 - Verify promotion order is affected when colocating master to native rsc." do_test colo_slave_w_native "cl#5070 - Verify promotion order is affected when colocating slave to native rsc." do_test anti-colocation-order "cl#5187 - Prevent resources in an anti-colocation from even temporarily running on a same node" do_test anti-colocation-master "Organize order of actions for master resources in anti-colocations" do_test anti-colocation-slave "Organize order of actions for slave resources in anti-colocations" do_test enforce-colo1 "Always enforce B with A INFINITY." do_test complex_enforce_colo "Always enforce B with A INFINITY. (make sure heat-engine stops)" echo "" do_test rsc-sets-seq-true "Resource Sets - sequential=false" do_test rsc-sets-seq-false "Resource Sets - sequential=true" do_test rsc-sets-clone "Resource Sets - Clone" do_test rsc-sets-master "Resource Sets - Master" do_test rsc-sets-clone-1 "Resource Sets - Clone (lf#2404)" #echo "" #do_test agent1 "version: lt (empty)" #do_test agent2 "version: eq " #do_test agent3 "version: gt " echo "" do_test attrs1 "string: eq (and) " do_test attrs2 "string: lt / gt (and)" do_test attrs3 "string: ne (or) " do_test attrs4 "string: exists " do_test attrs5 "string: not_exists " do_test attrs6 "is_dc: true " do_test attrs7 "is_dc: false " do_test attrs8 "score_attribute " do_test per-node-attrs "Per node resource parameters" echo "" do_test mon-rsc-1 "Schedule Monitor - start" do_test mon-rsc-2 "Schedule Monitor - move " do_test mon-rsc-3 "Schedule Monitor - pending start " do_test mon-rsc-4 "Schedule Monitor - move/pending start" echo "" do_test rec-rsc-0 "Resource Recover - no start " do_test rec-rsc-1 "Resource Recover - start " do_test rec-rsc-2 "Resource Recover - monitor " do_test rec-rsc-3 "Resource Recover - stop - ignore" do_test rec-rsc-4 "Resource Recover - stop - block " do_test rec-rsc-5 "Resource Recover - stop - fence " do_test rec-rsc-6 "Resource Recover - multiple - restart" do_test rec-rsc-7 "Resource Recover - multiple - stop " do_test rec-rsc-8 "Resource Recover - multiple - block " do_test rec-rsc-9 "Resource Recover - group/group" do_test monitor-recovery "on-fail=block + resource recovery detected by recurring monitor" do_test stop-failure-no-quorum "Stop failure without quorum" do_test stop-failure-no-fencing "Stop failure without fencing available" do_test stop-failure-with-fencing "Stop failure with fencing available" do_test multiple-active-block-group "Support of multiple-active=block for resource groups" do_test multiple-monitor-one-failed "Consider resource failed if any of the configured monitor operations failed" echo "" do_test quorum-1 "No quorum - ignore" do_test quorum-2 "No quorum - freeze" do_test quorum-3 "No quorum - stop " do_test quorum-4 "No quorum - start anyway" do_test quorum-5 "No quorum - start anyway (group)" do_test quorum-6 "No quorum - start anyway (clone)" do_test bug-cl-5212 "No promotion with no-quorum-policy=freeze" echo "" do_test rec-node-1 "Node Recover - Startup - no fence" do_test rec-node-2 "Node Recover - Startup - fence " do_test rec-node-3 "Node Recover - HA down - no fence" do_test rec-node-4 "Node Recover - HA down - fence " do_test rec-node-5 "Node Recover - CRM down - no fence" do_test rec-node-6 "Node Recover - CRM down - fence " do_test rec-node-7 "Node Recover - no quorum - ignore " do_test rec-node-8 "Node Recover - no quorum - freeze " do_test rec-node-9 "Node Recover - no quorum - stop " do_test rec-node-10 "Node Recover - no quorum - stop w/fence" do_test rec-node-11 "Node Recover - CRM down w/ group - fence " do_test rec-node-12 "Node Recover - nothing active - fence " do_test rec-node-13 "Node Recover - failed resource + shutdown - fence " do_test rec-node-15 "Node Recover - unknown lrm section" do_test rec-node-14 "Serialize all stonith's" echo "" do_test multi1 "Multiple Active (stop/start)" echo "" do_test migrate-begin "Normal migration" do_test migrate-success "Completed migration" do_test migrate-partial-1 "Completed migration, missing stop on source" do_test migrate-partial-2 "Successful migrate_to only" do_test migrate-partial-3 "Successful migrate_to only, target down" do_test migrate-partial-4 "Migrate from the correct host after migrate_to+migrate_from" do_test bug-5186-partial-migrate "Handle partial migration when src node loses membership" do_test migrate-fail-2 "Failed migrate_from" do_test migrate-fail-3 "Failed migrate_from + stop on source" do_test migrate-fail-4 "Failed migrate_from + stop on target - ideally we wouldn't need to re-stop on target" do_test migrate-fail-5 "Failed migrate_from + stop on source and target" do_test migrate-fail-6 "Failed migrate_to" do_test migrate-fail-7 "Failed migrate_to + stop on source" do_test migrate-fail-8 "Failed migrate_to + stop on target - ideally we wouldn't need to re-stop on target" do_test migrate-fail-9 "Failed migrate_to + stop on source and target" do_test migrate-stop "Migration in a stopping stack" do_test migrate-start "Migration in a starting stack" do_test migrate-stop_start "Migration in a restarting stack" do_test migrate-stop-complex "Migration in a complex stopping stack" do_test migrate-start-complex "Migration in a complex starting stack" do_test migrate-stop-start-complex "Migration in a complex moving stack" do_test migrate-shutdown "Order the post-migration 'stop' before node shutdown" do_test migrate-1 "Migrate (migrate)" do_test migrate-2 "Migrate (stable)" do_test migrate-3 "Migrate (failed migrate_to)" do_test migrate-4 "Migrate (failed migrate_from)" do_test novell-252693 "Migration in a stopping stack" do_test novell-252693-2 "Migration in a starting stack" do_test novell-252693-3 "Non-Migration in a starting and stopping stack" do_test bug-1820 "Migration in a group" do_test bug-1820-1 "Non-migration in a group" do_test migrate-5 "Primitive migration with a clone" do_test migrate-fencing "Migration after Fencing" do_test migrate-both-vms "Migrate two VMs that have no colocation" do_test 1-a-then-bm-move-b "Advanced migrate logic. A then B. migrate B." do_test 2-am-then-b-move-a "Advanced migrate logic, A then B, migrate A without stopping B" do_test 3-am-then-bm-both-migrate "Advanced migrate logic. A then B. migrate both" do_test 4-am-then-bm-b-not-migratable "Advanced migrate logic, A then B, B not migratable" do_test 5-am-then-bm-a-not-migratable "Advanced migrate logic. A then B. move both, a not migratable" do_test 6-migrate-group "Advanced migrate logic, migrate a group" do_test 7-migrate-group-one-unmigratable "Advanced migrate logic, migrate group mixed with allow-migrate true/false" do_test 8-am-then-bm-a-migrating-b-stopping "Advanced migrate logic, A then B, A migrating, B stopping" do_test 9-am-then-bm-b-migrating-a-stopping "Advanced migrate logic, A then B, B migrate, A stopping" do_test 10-a-then-bm-b-move-a-clone "Advanced migrate logic, A clone then B, migrate B while stopping A" do_test 11-a-then-bm-b-move-a-clone-starting "Advanced migrate logic, A clone then B, B moving while A is start/stopping" do_test a-promote-then-b-migrate "A promote then B start. migrate B" do_test a-demote-then-b-migrate "A demote then B stop. migrate B" #echo "" #do_test complex1 "Complex " do_test bug-lf-2422 "Dependency on partially active group - stop ocfs:*" echo "" do_test clone-anon-probe-1 "Probe the correct (anonymous) clone instance for each node" do_test clone-anon-probe-2 "Avoid needless re-probing of anonymous clones" do_test clone-anon-failcount "Merge failcounts for anonymous clones" do_test inc0 "Incarnation start" do_test inc1 "Incarnation start order" do_test inc2 "Incarnation silent restart, stop, move" do_test inc3 "Inter-incarnation ordering, silent restart, stop, move" do_test inc4 "Inter-incarnation ordering, silent restart, stop, move (ordered)" do_test inc5 "Inter-incarnation ordering, silent restart, stop, move (restart 1)" do_test inc6 "Inter-incarnation ordering, silent restart, stop, move (restart 2)" do_test inc7 "Clone colocation" do_test inc8 "Clone anti-colocation" do_test inc9 "Non-unique clone" do_test inc10 "Non-unique clone (stop)" do_test inc11 "Primitive colocation with clones" do_test inc12 "Clone shutdown" do_test cloned-group "Make sure only the correct number of cloned groups are started" do_test cloned-group-stop "Ensure stopping qpidd also stops glance and cinder" do_test clone-no-shuffle "Don't prioritize allocation of instances that must be moved" do_test clone-max-zero "Orphan processing with clone-max=0" do_test clone-anon-dup "Bug LF#2087 - Correctly parse the state of anonymous clones that are active more than once per node" do_test bug-lf-2160 "Don't shuffle clones due to colocation" do_test bug-lf-2213 "clone-node-max enforcement for cloned groups" do_test bug-lf-2153 "Clone ordering constraints" do_test bug-lf-2361 "Ensure clones observe mandatory ordering constraints if the LHS is unrunnable" do_test bug-lf-2317 "Avoid needless restart of primitive depending on a clone" do_test clone-colocate-instance-1 "Colocation with a specific clone instance (negative example)" do_test clone-colocate-instance-2 "Colocation with a specific clone instance" do_test clone-order-instance "Ordering with specific clone instances" do_test bug-lf-2453 "Enforce mandatory clone ordering without colocation" do_test bug-lf-2508 "Correctly reconstruct the status of anonymous cloned groups" do_test bug-lf-2544 "Balanced clone placement" do_test bug-lf-2445 "Redistribute clones with node-max > 1 and stickiness = 0" do_test bug-lf-2574 "Avoid clone shuffle" do_test bug-lf-2581 "Avoid group restart due to unrelated clone (re)start" do_test bug-cl-5168 "Don't shuffle clones" do_test bug-cl-5170 "Prevent clone from starting with on-fail=block" do_test clone-fail-block-colocation "Move colocated group when failed clone has on-fail=block" do_test clone-interleave-1 "Clone-3 cannot start on pcmk-1 due to interleaved ordering (no colocation)" do_test clone-interleave-2 "Clone-3 must stop on pcmk-1 due to interleaved ordering (no colocation)" do_test clone-interleave-3 "Clone-3 must be recovered on pcmk-1 due to interleaved ordering (no colocation)" echo "" do_test cloned_start_one "order first clone then clone... first clone_min=2" do_test cloned_start_two "order first clone then clone... first clone_min=2" do_test cloned_stop_one "order first clone then clone... first clone_min=2" do_test cloned_stop_two "order first clone then clone... first clone_min=2" do_test clone_min_interleave_start_one "order first clone then clone... first clone_min=2 and then has interleave=true" do_test clone_min_interleave_start_two "order first clone then clone... first clone_min=2 and then has interleave=true" do_test clone_min_interleave_stop_one "order first clone then clone... first clone_min=2 and then has interleave=true" do_test clone_min_interleave_stop_two "order first clone then clone... first clone_min=2 and then has interleave=true" do_test clone_min_start_one "order first clone then primitive... first clone_min=2" do_test clone_min_start_two "order first clone then primitive... first clone_min=2" do_test clone_min_stop_all "order first clone then primitive... first clone_min=2" do_test clone_min_stop_one "order first clone then primitive... first clone_min=2" do_test clone_min_stop_two "order first clone then primitive... first clone_min=2" echo "" do_test unfence-startup "Clean unfencing" do_test unfence-definition "Unfencing when the agent changes" do_test unfence-parameters "Unfencing when the agent parameters changes" echo "" do_test master-0 "Stopped -> Slave" do_test master-1 "Stopped -> Promote" do_test master-2 "Stopped -> Promote : notify" do_test master-3 "Stopped -> Promote : master location" do_test master-4 "Started -> Promote : master location" do_test master-5 "Promoted -> Promoted" do_test master-6 "Promoted -> Promoted (2)" do_test master-7 "Promoted -> Fenced" do_test master-8 "Promoted -> Fenced -> Moved" do_test master-9 "Stopped + Promotable + No quorum" do_test master-10 "Stopped -> Promotable : notify with monitor" do_test master-11 "Stopped -> Promote : colocation" do_test novell-239082 "Demote/Promote ordering" do_test novell-239087 "Stable master placement" do_test master-12 "Promotion based solely on rsc_location constraints" do_test master-13 "Include preferences of colocated resources when placing master" do_test master-demote "Ordering when actions depends on demoting a slave resource" do_test master-ordering "Prevent resources from starting that need a master" do_test bug-1765 "Master-Master Colocation (dont stop the slaves)" do_test master-group "Promotion of cloned groups" do_test bug-lf-1852 "Don't shuffle master/slave instances unnecessarily" do_test master-failed-demote "Don't retry failed demote actions" do_test master-failed-demote-2 "Don't retry failed demote actions (notify=false)" do_test master-depend "Ensure resources that depend on the master don't get allocated until the master does" do_test master-reattach "Re-attach to a running master" do_test master-allow-start "Don't include master score if it would prevent allocation" do_test master-colocation "Allow master instances placemaker to be influenced by colocation constraints" do_test master-pseudo "Make sure promote/demote pseudo actions are created correctly" do_test master-role "Prevent target-role from promoting more than master-max instances" do_test bug-lf-2358 "Master-Master anti-colocation" do_test master-promotion-constraint "Mandatory master colocation constraints" do_test unmanaged-master "Ensure role is preserved for unmanaged resources" do_test master-unmanaged-monitor "Start the correct monitor operation for unmanaged masters" do_test master-demote-2 "Demote does not clear past failure" do_test master-move "Move master based on failure of colocated group" do_test master-probed-score "Observe the promotion score of probed resources" do_test colocation_constraint_stops_master "cl#5054 - Ensure master is demoted when stopped by colocation constraint" do_test colocation_constraint_stops_slave "cl#5054 - Ensure slave is not demoted when stopped by colocation constraint" do_test order_constraint_stops_master "cl#5054 - Ensure master is demoted when stopped by order constraint" do_test order_constraint_stops_slave "cl#5054 - Ensure slave is not demoted when stopped by order constraint" do_test master_monitor_restart "cl#5072 - Ensure master monitor operation will start after promotion." do_test bug-rh-880249 "Handle replacement of an m/s resource with a primitive" do_test bug-5143-ms-shuffle "Prevent master shuffling due to promotion score" do_test master-demote-block "Block promotion if demote fails with on-fail=block" do_test master-dependent-ban "Don't stop instances from being active because a dependent is banned from that host" do_test master-stop "Stop instances due to location constraint with role=Started" do_test master-partially-demoted-group "Allow partially demoted group to finish demoting" do_test bug-cl-5213 "Ensure role colocation with -INFINITY is enforced" do_test bug-cl-5219 "Allow unrelated resources with a common colocation target to remain promoted" do_test master-asymmetrical-order "Fix the behaviors of multi-state resources with asymmetrical ordering" do_test master-notify "Master promotion with notifies" echo "" do_test history-1 "Correctly parse stateful-1 resource state" echo "" do_test managed-0 "Managed (reference)" do_test managed-1 "Not managed - down " do_test managed-2 "Not managed - up " do_test bug-5028 "Shutdown should block if anything depends on an unmanaged resource" do_test bug-5028-detach "Ensure detach still works" do_test bug-5028-bottom "Ensure shutdown still blocks if the blocked resource is at the bottom of the stack" do_test unmanaged-stop-1 "cl#5155 - Block the stop of resources if any depending resource is unmanaged " do_test unmanaged-stop-2 "cl#5155 - Block the stop of resources if the first resource in a mandatory stop order is unmanaged " do_test unmanaged-stop-3 "cl#5155 - Block the stop of resources if any depending resource in a group is unmanaged " do_test unmanaged-stop-4 "cl#5155 - Block the stop of resources if any depending resource in the middle of a group is unmanaged " do_test unmanaged-block-restart "Block restart of resources if any dependent resource in a group is unmanaged" echo "" do_test interleave-0 "Interleave (reference)" do_test interleave-1 "coloc - not interleaved" do_test interleave-2 "coloc - interleaved " do_test interleave-3 "coloc - interleaved (2)" do_test interleave-pseudo-stop "Interleaved clone during stonith" do_test interleave-stop "Interleaved clone during stop" do_test interleave-restart "Interleaved clone during dependency restart" echo "" do_test notify-0 "Notify reference" do_test notify-1 "Notify simple" do_test notify-2 "Notify simple, confirm" do_test notify-3 "Notify move, confirm" do_test novell-239079 "Notification priority" #do_test notify-2 "Notify - 764" echo "" do_test 594 "OSDL #594 - Unrunnable actions scheduled in transition" do_test 662 "OSDL #662 - Two resources start on one node when incarnation_node_max = 1" do_test 696 "OSDL #696 - CRM starts stonith RA without monitor" do_test 726 "OSDL #726 - Attempting to schedule rsc_posic041_monitor_5000 _after_ a stop" do_test 735 "OSDL #735 - Correctly detect that rsc_hadev1 is stopped on hadev3" do_test 764 "OSDL #764 - Missing monitor op for DoFencing:child_DoFencing:1" do_test 797 "OSDL #797 - Assert triggered: task_id_i > max_call_id" do_test 829 "OSDL #829" do_test 994 "OSDL #994 - Stopping the last resource in a resource group causes the entire group to be restarted" do_test 994-2 "OSDL #994 - with a dependent resource" do_test 1360 "OSDL #1360 - Clone stickiness" do_test 1484 "OSDL #1484 - on_fail=stop" do_test 1494 "OSDL #1494 - Clone stability" do_test unrunnable-1 "Unrunnable" do_test unrunnable-2 "Unrunnable 2" do_test stonith-0 "Stonith loop - 1" do_test stonith-1 "Stonith loop - 2" do_test stonith-2 "Stonith loop - 3" do_test stonith-3 "Stonith startup" do_test stonith-4 "Stonith node state" do_test bug-1572-1 "Recovery of groups depending on master/slave" do_test bug-1572-2 "Recovery of groups depending on master/slave when the master is never re-promoted" do_test bug-1685 "Depends-on-master ordering" do_test bug-1822 "Don't promote partially active groups" do_test bug-pm-11 "New resource added to a m/s group" do_test bug-pm-12 "Recover only the failed portion of a cloned group" do_test bug-n-387749 "Don't shuffle clone instances" do_test bug-n-385265 "Don't ignore the failure stickiness of group children - resource_idvscommon should stay stopped" do_test bug-n-385265-2 "Ensure groups are migrated instead of remaining partially active on the current node" do_test bug-lf-1920 "Correctly handle probes that find active resources" do_test bnc-515172 "Location constraint with multiple expressions" do_test colocate-primitive-with-clone "Optional colocation with a clone" do_test use-after-free-merge "Use-after-free in native_merge_weights" do_test bug-lf-2551 "STONITH ordering for stop" do_test bug-lf-2606 "Stonith implies demote" do_test bug-lf-2474 "Ensure resource op timeout takes precedence over op_defaults" do_test bug-suse-707150 "Prevent vm-01 from starting due to colocation/ordering" do_test bug-5014-A-start-B-start "Verify when A starts B starts using symmetrical=false" do_test bug-5014-A-stop-B-started "Verify when A stops B does not stop if it has already started using symmetric=false" do_test bug-5014-A-stopped-B-stopped "Verify when A is stopped and B has not started, B does not start before A using symmetric=false" do_test bug-5014-CthenAthenB-C-stopped "Verify when C then A is symmetrical=true, A then B is symmetric=false, and C is stopped that nothing starts." do_test bug-5014-CLONE-A-start-B-start "Verify when A starts B starts using clone resources with symmetric=false" do_test bug-5014-CLONE-A-stop-B-started "Verify when A stops B does not stop if it has already started using clone resources with symmetric=false." do_test bug-5014-GROUP-A-start-B-start "Verify when A starts B starts when using group resources with symmetric=false." do_test bug-5014-GROUP-A-stopped-B-started "Verify when A stops B does not stop if it has already started using group resources with symmetric=false." do_test bug-5014-GROUP-A-stopped-B-stopped "Verify when A is stopped and B has not started, B does not start before A using group resources with symmetric=false." do_test bug-5014-ordered-set-symmetrical-false "Verify ordered sets work with symmetrical=false" do_test bug-5014-ordered-set-symmetrical-true "Verify ordered sets work with symmetrical=true" do_test bug-5007-masterslave_colocation "Verify use of colocation scores other than INFINITY and -INFINITY work on multi-state resources." do_test bug-5038 "Prevent restart of anonymous clones when clone-max decreases" do_test bug-5025-1 "Automatically clean up failcount after resource config change with reload" do_test bug-5025-2 "Make sure clear failcount action isn't set when config does not change." do_test bug-5025-3 "Automatically clean up failcount after resource config change with restart" do_test bug-5025-4 "Clear failcount when last failure is a start op and rsc attributes changed." do_test failcount "Ensure failcounts are correctly expired" do_test failcount-block "Ensure failcounts are not expired when on-fail=block is present" do_test monitor-onfail-restart "bug-5058 - Monitor failure with on-fail set to restart" do_test monitor-onfail-stop "bug-5058 - Monitor failure wiht on-fail set to stop" do_test bug-5059 "No need to restart p_stateful1:*" do_test bug-5069-op-enabled "Test on-fail=ignore with failure when monitor is enabled." do_test bug-5069-op-disabled "Test on-fail-ignore with failure when monitor is disabled." do_test obsolete-lrm-resource "cl#5115 - Do not use obsolete lrm_resource sections" do_test expire-non-blocked-failure "Ignore failure-timeout only if the failed operation has on-fail=block" do_test asymmetrical-order-move "Respect asymmetrical ordering when trying to move resources" do_test start-then-stop-with-unfence "Avoid graph loop with start-then-stop constraint plus unfencing" do_test ignore_stonith_rsc_order1 "cl#5056- Ignore order constraint between stonith and non-stonith rsc." do_test ignore_stonith_rsc_order2 "cl#5056- Ignore order constraint with group rsc containing mixed stonith and non-stonith." do_test ignore_stonith_rsc_order3 "cl#5056- Ignore order constraint, stonith clone and mixed group" do_test ignore_stonith_rsc_order4 "cl#5056- Ignore order constraint, stonith clone and clone with nested mixed group" do_test honor_stonith_rsc_order1 "cl#5056- Honor order constraint, stonith clone and pure stonith group(single rsc)." do_test honor_stonith_rsc_order2 "cl#5056- Honor order constraint, stonith clone and pure stonith group(multiple rsc)" do_test honor_stonith_rsc_order3 "cl#5056- Honor order constraint, stonith clones with nested pure stonith group." do_test honor_stonith_rsc_order4 "cl#5056- Honor order constraint, between two native stonith rscs." do_test probe-timeout "cl#5099 - Default probe timeout" do_test concurrent-fencing "Allow performing fencing operations in parallel" echo "" do_test systemhealth1 "System Health () #1" do_test systemhealth2 "System Health () #2" do_test systemhealth3 "System Health () #3" do_test systemhealthn1 "System Health (None) #1" do_test systemhealthn2 "System Health (None) #2" do_test systemhealthn3 "System Health (None) #3" do_test systemhealthm1 "System Health (Migrate On Red) #1" do_test systemhealthm2 "System Health (Migrate On Red) #2" do_test systemhealthm3 "System Health (Migrate On Red) #3" do_test systemhealtho1 "System Health (Only Green) #1" do_test systemhealtho2 "System Health (Only Green) #2" do_test systemhealtho3 "System Health (Only Green) #3" do_test systemhealthp1 "System Health (Progessive) #1" do_test systemhealthp2 "System Health (Progessive) #2" do_test systemhealthp3 "System Health (Progessive) #3" echo "" do_test utilization "Placement Strategy - utilization" do_test minimal "Placement Strategy - minimal" do_test balanced "Placement Strategy - balanced" echo "" do_test placement-stickiness "Optimized Placement Strategy - stickiness" do_test placement-priority "Optimized Placement Strategy - priority" do_test placement-location "Optimized Placement Strategy - location" do_test placement-capacity "Optimized Placement Strategy - capacity" echo "" do_test utilization-order1 "Utilization Order - Simple" do_test utilization-order2 "Utilization Order - Complex" do_test utilization-order3 "Utilization Order - Migrate" do_test utilization-order4 "Utilization Order - Live Mirgration (bnc#695440)" do_test utilization-shuffle "Don't displace prmExPostgreSQLDB2 on act2, Start prmExPostgreSQLDB1 on act3" do_test load-stopped-loop "Avoid transition loop due to load_stopped (cl#5044)" do_test load-stopped-loop-2 "cl#5235 - Prevent graph loops that can be introduced by load_stopped -> migrate_to ordering" echo "" do_test colocated-utilization-primitive-1 "Colocated Utilization - Primitive" do_test colocated-utilization-primitive-2 "Colocated Utilization - Choose the most capable node" do_test colocated-utilization-group "Colocated Utilization - Group" do_test colocated-utilization-clone "Colocated Utilization - Clone" do_test utilization-check-allowed-nodes "Only check the capacities of the nodes that can run the resource" echo "" do_test reprobe-target_rc "Ensure correct target_rc for reprobe of inactive resources" do_test node-maintenance-1 "cl#5128 - Node maintenance" do_test node-maintenance-2 "cl#5128 - Node maintenance (coming out of maintenance mode)" do_test rsc-maintenance "Per-resource maintenance" echo "" do_test not-installed-agent "The resource agent is missing" do_test not-installed-tools "Something the resource agent needs is missing" echo "" do_test stopped-monitor-00 "Stopped Monitor - initial start" do_test stopped-monitor-01 "Stopped Monitor - failed started" do_test stopped-monitor-02 "Stopped Monitor - started multi-up" do_test stopped-monitor-03 "Stopped Monitor - stop started" do_test stopped-monitor-04 "Stopped Monitor - failed stop" do_test stopped-monitor-05 "Stopped Monitor - start unmanaged" do_test stopped-monitor-06 "Stopped Monitor - unmanaged multi-up" do_test stopped-monitor-07 "Stopped Monitor - start unmanaged multi-up" do_test stopped-monitor-08 "Stopped Monitor - migrate" do_test stopped-monitor-09 "Stopped Monitor - unmanage started" do_test stopped-monitor-10 "Stopped Monitor - unmanaged started multi-up" do_test stopped-monitor-11 "Stopped Monitor - stop unmanaged started" do_test stopped-monitor-12 "Stopped Monitor - unmanaged started multi-up (targer-role="Stopped")" do_test stopped-monitor-20 "Stopped Monitor - initial stop" do_test stopped-monitor-21 "Stopped Monitor - stopped single-up" do_test stopped-monitor-22 "Stopped Monitor - stopped multi-up" do_test stopped-monitor-23 "Stopped Monitor - start stopped" do_test stopped-monitor-24 "Stopped Monitor - unmanage stopped" do_test stopped-monitor-25 "Stopped Monitor - unmanaged stopped multi-up" do_test stopped-monitor-26 "Stopped Monitor - start unmanaged stopped" do_test stopped-monitor-27 "Stopped Monitor - unmanaged stopped multi-up (target-role="Started")" do_test stopped-monitor-30 "Stopped Monitor - new node started" do_test stopped-monitor-31 "Stopped Monitor - new node stopped" echo"" do_test ticket-primitive-1 "Ticket - Primitive (loss-policy=stop, initial)" do_test ticket-primitive-2 "Ticket - Primitive (loss-policy=stop, granted)" do_test ticket-primitive-3 "Ticket - Primitive (loss-policy-stop, revoked)" do_test ticket-primitive-4 "Ticket - Primitive (loss-policy=demote, initial)" do_test ticket-primitive-5 "Ticket - Primitive (loss-policy=demote, granted)" do_test ticket-primitive-6 "Ticket - Primitive (loss-policy=demote, revoked)" do_test ticket-primitive-7 "Ticket - Primitive (loss-policy=fence, initial)" do_test ticket-primitive-8 "Ticket - Primitive (loss-policy=fence, granted)" do_test ticket-primitive-9 "Ticket - Primitive (loss-policy=fence, revoked)" do_test ticket-primitive-10 "Ticket - Primitive (loss-policy=freeze, initial)" do_test ticket-primitive-11 "Ticket - Primitive (loss-policy=freeze, granted)" do_test ticket-primitive-12 "Ticket - Primitive (loss-policy=freeze, revoked)" do_test ticket-primitive-13 "Ticket - Primitive (loss-policy=stop, standby, granted)" do_test ticket-primitive-14 "Ticket - Primitive (loss-policy=stop, granted, standby)" do_test ticket-primitive-15 "Ticket - Primitive (loss-policy=stop, standby, revoked)" do_test ticket-primitive-16 "Ticket - Primitive (loss-policy=demote, standby, granted)" do_test ticket-primitive-17 "Ticket - Primitive (loss-policy=demote, granted, standby)" do_test ticket-primitive-18 "Ticket - Primitive (loss-policy=demote, standby, revoked)" do_test ticket-primitive-19 "Ticket - Primitive (loss-policy=fence, standby, granted)" do_test ticket-primitive-20 "Ticket - Primitive (loss-policy=fence, granted, standby)" do_test ticket-primitive-21 "Ticket - Primitive (loss-policy=fence, standby, revoked)" do_test ticket-primitive-22 "Ticket - Primitive (loss-policy=freeze, standby, granted)" do_test ticket-primitive-23 "Ticket - Primitive (loss-policy=freeze, granted, standby)" do_test ticket-primitive-24 "Ticket - Primitive (loss-policy=freeze, standby, revoked)" echo"" do_test ticket-group-1 "Ticket - Group (loss-policy=stop, initial)" do_test ticket-group-2 "Ticket - Group (loss-policy=stop, granted)" do_test ticket-group-3 "Ticket - Group (loss-policy-stop, revoked)" do_test ticket-group-4 "Ticket - Group (loss-policy=demote, initial)" do_test ticket-group-5 "Ticket - Group (loss-policy=demote, granted)" do_test ticket-group-6 "Ticket - Group (loss-policy=demote, revoked)" do_test ticket-group-7 "Ticket - Group (loss-policy=fence, initial)" do_test ticket-group-8 "Ticket - Group (loss-policy=fence, granted)" do_test ticket-group-9 "Ticket - Group (loss-policy=fence, revoked)" do_test ticket-group-10 "Ticket - Group (loss-policy=freeze, initial)" do_test ticket-group-11 "Ticket - Group (loss-policy=freeze, granted)" do_test ticket-group-12 "Ticket - Group (loss-policy=freeze, revoked)" do_test ticket-group-13 "Ticket - Group (loss-policy=stop, standby, granted)" do_test ticket-group-14 "Ticket - Group (loss-policy=stop, granted, standby)" do_test ticket-group-15 "Ticket - Group (loss-policy=stop, standby, revoked)" do_test ticket-group-16 "Ticket - Group (loss-policy=demote, standby, granted)" do_test ticket-group-17 "Ticket - Group (loss-policy=demote, granted, standby)" do_test ticket-group-18 "Ticket - Group (loss-policy=demote, standby, revoked)" do_test ticket-group-19 "Ticket - Group (loss-policy=fence, standby, granted)" do_test ticket-group-20 "Ticket - Group (loss-policy=fence, granted, standby)" do_test ticket-group-21 "Ticket - Group (loss-policy=fence, standby, revoked)" do_test ticket-group-22 "Ticket - Group (loss-policy=freeze, standby, granted)" do_test ticket-group-23 "Ticket - Group (loss-policy=freeze, granted, standby)" do_test ticket-group-24 "Ticket - Group (loss-policy=freeze, standby, revoked)" echo"" do_test ticket-clone-1 "Ticket - Clone (loss-policy=stop, initial)" do_test ticket-clone-2 "Ticket - Clone (loss-policy=stop, granted)" do_test ticket-clone-3 "Ticket - Clone (loss-policy-stop, revoked)" do_test ticket-clone-4 "Ticket - Clone (loss-policy=demote, initial)" do_test ticket-clone-5 "Ticket - Clone (loss-policy=demote, granted)" do_test ticket-clone-6 "Ticket - Clone (loss-policy=demote, revoked)" do_test ticket-clone-7 "Ticket - Clone (loss-policy=fence, initial)" do_test ticket-clone-8 "Ticket - Clone (loss-policy=fence, granted)" do_test ticket-clone-9 "Ticket - Clone (loss-policy=fence, revoked)" do_test ticket-clone-10 "Ticket - Clone (loss-policy=freeze, initial)" do_test ticket-clone-11 "Ticket - Clone (loss-policy=freeze, granted)" do_test ticket-clone-12 "Ticket - Clone (loss-policy=freeze, revoked)" do_test ticket-clone-13 "Ticket - Clone (loss-policy=stop, standby, granted)" do_test ticket-clone-14 "Ticket - Clone (loss-policy=stop, granted, standby)" do_test ticket-clone-15 "Ticket - Clone (loss-policy=stop, standby, revoked)" do_test ticket-clone-16 "Ticket - Clone (loss-policy=demote, standby, granted)" do_test ticket-clone-17 "Ticket - Clone (loss-policy=demote, granted, standby)" do_test ticket-clone-18 "Ticket - Clone (loss-policy=demote, standby, revoked)" do_test ticket-clone-19 "Ticket - Clone (loss-policy=fence, standby, granted)" do_test ticket-clone-20 "Ticket - Clone (loss-policy=fence, granted, standby)" do_test ticket-clone-21 "Ticket - Clone (loss-policy=fence, standby, revoked)" do_test ticket-clone-22 "Ticket - Clone (loss-policy=freeze, standby, granted)" do_test ticket-clone-23 "Ticket - Clone (loss-policy=freeze, granted, standby)" do_test ticket-clone-24 "Ticket - Clone (loss-policy=freeze, standby, revoked)" echo"" do_test ticket-master-1 "Ticket - Master (loss-policy=stop, initial)" do_test ticket-master-2 "Ticket - Master (loss-policy=stop, granted)" do_test ticket-master-3 "Ticket - Master (loss-policy-stop, revoked)" do_test ticket-master-4 "Ticket - Master (loss-policy=demote, initial)" do_test ticket-master-5 "Ticket - Master (loss-policy=demote, granted)" do_test ticket-master-6 "Ticket - Master (loss-policy=demote, revoked)" do_test ticket-master-7 "Ticket - Master (loss-policy=fence, initial)" do_test ticket-master-8 "Ticket - Master (loss-policy=fence, granted)" do_test ticket-master-9 "Ticket - Master (loss-policy=fence, revoked)" do_test ticket-master-10 "Ticket - Master (loss-policy=freeze, initial)" do_test ticket-master-11 "Ticket - Master (loss-policy=freeze, granted)" do_test ticket-master-12 "Ticket - Master (loss-policy=freeze, revoked)" do_test ticket-master-13 "Ticket - Master (loss-policy=stop, standby, granted)" do_test ticket-master-14 "Ticket - Master (loss-policy=stop, granted, standby)" do_test ticket-master-15 "Ticket - Master (loss-policy=stop, standby, revoked)" do_test ticket-master-16 "Ticket - Master (loss-policy=demote, standby, granted)" do_test ticket-master-17 "Ticket - Master (loss-policy=demote, granted, standby)" do_test ticket-master-18 "Ticket - Master (loss-policy=demote, standby, revoked)" do_test ticket-master-19 "Ticket - Master (loss-policy=fence, standby, granted)" do_test ticket-master-20 "Ticket - Master (loss-policy=fence, granted, standby)" do_test ticket-master-21 "Ticket - Master (loss-policy=fence, standby, revoked)" do_test ticket-master-22 "Ticket - Master (loss-policy=freeze, standby, granted)" do_test ticket-master-23 "Ticket - Master (loss-policy=freeze, granted, standby)" do_test ticket-master-24 "Ticket - Master (loss-policy=freeze, standby, revoked)" echo "" do_test ticket-rsc-sets-1 "Ticket - Resource sets (1 ticket, initial)" do_test ticket-rsc-sets-2 "Ticket - Resource sets (1 ticket, granted)" do_test ticket-rsc-sets-3 "Ticket - Resource sets (1 ticket, revoked)" do_test ticket-rsc-sets-4 "Ticket - Resource sets (2 tickets, initial)" do_test ticket-rsc-sets-5 "Ticket - Resource sets (2 tickets, granted)" do_test ticket-rsc-sets-6 "Ticket - Resource sets (2 tickets, granted)" do_test ticket-rsc-sets-7 "Ticket - Resource sets (2 tickets, revoked)" do_test ticket-rsc-sets-8 "Ticket - Resource sets (1 ticket, standby, granted)" do_test ticket-rsc-sets-9 "Ticket - Resource sets (1 ticket, granted, standby)" do_test ticket-rsc-sets-10 "Ticket - Resource sets (1 ticket, standby, revoked)" do_test ticket-rsc-sets-11 "Ticket - Resource sets (2 tickets, standby, granted)" do_test ticket-rsc-sets-12 "Ticket - Resource sets (2 tickets, standby, granted)" do_test ticket-rsc-sets-13 "Ticket - Resource sets (2 tickets, granted, standby)" do_test ticket-rsc-sets-14 "Ticket - Resource sets (2 tickets, standby, revoked)" do_test cluster-specific-params "Cluster-specific instance attributes based on rules" do_test site-specific-params "Site-specific instance attributes based on rules" echo "" do_test template-1 "Template - 1" do_test template-2 "Template - 2" do_test template-3 "Template - 3 (merge operations)" do_test template-coloc-1 "Template - Colocation 1" do_test template-coloc-2 "Template - Colocation 2" do_test template-coloc-3 "Template - Colocation 3" do_test template-order-1 "Template - Order 1" do_test template-order-2 "Template - Order 2" do_test template-order-3 "Template - Order 3" do_test template-ticket "Template - Ticket" do_test template-rsc-sets-1 "Template - Resource Sets 1" do_test template-rsc-sets-2 "Template - Resource Sets 2" do_test template-rsc-sets-3 "Template - Resource Sets 3" do_test template-rsc-sets-4 "Template - Resource Sets 4" do_test template-clone-primitive "Cloned primitive from template" do_test template-clone-group "Cloned group from template" do_test location-sets-templates "Resource sets and templates - Location" do_test tags-coloc-order-1 "Tags - Colocation and Order (Simple)" do_test tags-coloc-order-2 "Tags - Colocation and Order (Resource Sets with Templates)" do_test tags-location "Tags - Location" do_test tags-ticket "Tags - Ticket" echo "" do_test container-1 "Container - initial" do_test container-2 "Container - monitor failed" do_test container-3 "Container - stop failed" do_test container-4 "Container - reached migration-threshold" do_test container-group-1 "Container in group - initial" do_test container-group-2 "Container in group - monitor failed" do_test container-group-3 "Container in group - stop failed" do_test container-group-4 "Container in group - reached migration-threshold" do_test container-is-remote-node "Place resource within container when container is remote-node" do_test bug-rh-1097457 "Kill user defined container/contents ordering" do_test bug-cl-5247 "Graph loop when recovering m/s resource in a container" echo "" do_test whitebox-fail1 "Fail whitebox container rsc." do_test whitebox-fail2 "Fail whitebox container rsc lrmd connection." do_test whitebox-fail3 "Failed containers should not run nested on remote nodes." do_test whitebox-start "Start whitebox container with resources assigned to it" do_test whitebox-stop "Stop whitebox container with resources assigned to it" do_test whitebox-move "Move whitebox container with resources assigned to it" do_test whitebox-asymmetric "Verify connection rsc opts-in based on container resource" do_test whitebox-ms-ordering "Verify promote/demote can not occur before connection is established" do_test whitebox-ms-ordering-move "Stop/Start cycle within a moving container" do_test whitebox-orphaned "Properly shutdown orphaned whitebox container" do_test whitebox-orphan-ms "Properly tear down orphan ms resources on remote-nodes" do_test whitebox-unexpectedly-running "Recover container nodes the cluster did not start." do_test whitebox-migrate1 "Migrate both container and connection resource" do_test whitebox-imply-stop-on-fence "imply stop action on container node rsc when host node is fenced" do_test whitebox-nested-group "Verify guest remote-node works nested in a group" echo "" do_test remote-startup-probes "Baremetal remote-node startup probes" do_test remote-startup "Startup a newly discovered remote-nodes with no status." do_test remote-fence-unclean "Fence unclean baremetal remote-node" do_test remote-fence-unclean2 "Fence baremetal remote-node after cluster node fails and connection can not be recovered" do_test remote-move "Move remote-node connection resource" do_test remote-disable "Disable a baremetal remote-node" do_test remote-orphaned "Properly shutdown orphaned connection resource" do_test remote-orphaned2 "verify we can handle orphaned remote connections with active resources on the remote" do_test remote-recover "Recover connection resource after cluster-node fails." do_test remote-stale-node-entry "Make sure we properly handle leftover remote-node entries in the node section" do_test remote-partial-migrate "Make sure partial migrations are handled before ops on the remote node." do_test remote-partial-migrate2 "Make sure partial migration target is prefered for remote connection." do_test remote-recover-fail "Make sure start failure causes fencing if rsc are active on remote." do_test remote-start-fail "Make sure a start failure does not result in fencing if no active resources are on remote." do_test remote-unclean2 "Make monitor failure always results in fencing, even if no rsc are active on remote." do_test remote-fence-before-reconnect "Fence before clearing recurring monitor failure" echo "" do_test resource-discovery "Exercises resource-discovery location constraint option." do_test rsc-discovery-per-node "Disable resource discovery per node" echo "" do_test isolation-start-all "Start docker isolated resources." do_test isolation-restart-all "Restart docker isolated resources." do_test isolation-clone "Cloned isolated primitive." +echo "" +do_test versioned-resources "Start resources with #ra-version rules" + echo "" test_results diff --git a/pengine/test10/versioned-resources.dot b/pengine/test10/versioned-resources.dot new file mode 100644 index 0000000000..438c8e0074 --- /dev/null +++ b/pengine/test10/versioned-resources.dot @@ -0,0 +1,152 @@ +digraph "g" { +"FencingPass_monitor_0 rhel7-1" -> "FencingPass_start_0 rhel7-2" [ style = bold] +"FencingPass_monitor_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"FencingPass_monitor_0 rhel7-2" -> "FencingPass_start_0 rhel7-2" [ style = bold] +"FencingPass_monitor_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +"FencingPass_monitor_0 rhel7-3" -> "FencingPass_start_0 rhel7-2" [ style = bold] +"FencingPass_monitor_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +"FencingPass_monitor_0 rhel7-4" -> "FencingPass_start_0 rhel7-2" [ style = bold] +"FencingPass_monitor_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"FencingPass_monitor_0 rhel7-5" -> "FencingPass_start_0 rhel7-2" [ style = bold] +"FencingPass_monitor_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"FencingPass_start_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +"grouptest2_running_0" [ style=bold color="green" fontcolor="orange"] +"grouptest2_start_0" -> "grouptest2_running_0" [ style = bold] +"grouptest2_start_0" -> "gvtest1_start_0 rhel7-4" [ style = bold] +"grouptest2_start_0" -> "gvtest2_start_0 rhel7-4" [ style = bold] +"grouptest2_start_0" -> "gvtest3_start_0 rhel7-4" [ style = bold] +"grouptest2_start_0" [ style=bold color="green" fontcolor="orange"] +"gvtest1_monitor_0 rhel7-1" -> "gvtest1_start_0 rhel7-4" [ style = bold] +"gvtest1_monitor_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"gvtest1_monitor_0 rhel7-2" -> "gvtest1_start_0 rhel7-4" [ style = bold] +"gvtest1_monitor_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +"gvtest1_monitor_0 rhel7-3" -> "gvtest1_start_0 rhel7-4" [ style = bold] +"gvtest1_monitor_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +"gvtest1_monitor_0 rhel7-4" -> "gvtest1_start_0 rhel7-4" [ style = bold] +"gvtest1_monitor_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"gvtest1_monitor_0 rhel7-5" -> "gvtest1_start_0 rhel7-4" [ style = bold] +"gvtest1_monitor_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"gvtest1_monitor_10000 rhel7-4" [ style=bold color="green" fontcolor="black"] +"gvtest1_start_0 rhel7-4" -> "grouptest2_running_0" [ style = bold] +"gvtest1_start_0 rhel7-4" -> "gvtest1_monitor_10000 rhel7-4" [ style = bold] +"gvtest1_start_0 rhel7-4" -> "gvtest2_start_0 rhel7-4" [ style = bold] +"gvtest1_start_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"gvtest2_monitor_0 rhel7-1" -> "gvtest2_start_0 rhel7-4" [ style = bold] +"gvtest2_monitor_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"gvtest2_monitor_0 rhel7-2" -> "gvtest2_start_0 rhel7-4" [ style = bold] +"gvtest2_monitor_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +"gvtest2_monitor_0 rhel7-3" -> "gvtest2_start_0 rhel7-4" [ style = bold] +"gvtest2_monitor_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +"gvtest2_monitor_0 rhel7-4" -> "gvtest2_start_0 rhel7-4" [ style = bold] +"gvtest2_monitor_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"gvtest2_monitor_0 rhel7-5" -> "gvtest2_start_0 rhel7-4" [ style = bold] +"gvtest2_monitor_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"gvtest2_monitor_10000 rhel7-4" [ style=bold color="green" fontcolor="black"] +"gvtest2_start_0 rhel7-4" -> "grouptest2_running_0" [ style = bold] +"gvtest2_start_0 rhel7-4" -> "gvtest2_monitor_10000 rhel7-4" [ style = bold] +"gvtest2_start_0 rhel7-4" -> "gvtest3_start_0 rhel7-4" [ style = bold] +"gvtest2_start_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"gvtest3_monitor_0 rhel7-1" -> "gvtest3_start_0 rhel7-4" [ style = bold] +"gvtest3_monitor_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"gvtest3_monitor_0 rhel7-2" -> "gvtest3_start_0 rhel7-4" [ style = bold] +"gvtest3_monitor_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +"gvtest3_monitor_0 rhel7-3" -> "gvtest3_start_0 rhel7-4" [ style = bold] +"gvtest3_monitor_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +"gvtest3_monitor_0 rhel7-4" -> "gvtest3_start_0 rhel7-4" [ style = bold] +"gvtest3_monitor_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"gvtest3_monitor_0 rhel7-5" -> "gvtest3_start_0 rhel7-4" [ style = bold] +"gvtest3_monitor_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"gvtest3_monitor_10000 rhel7-4" [ style=bold color="green" fontcolor="black"] +"gvtest3_start_0 rhel7-4" -> "grouptest2_running_0" [ style = bold] +"gvtest3_start_0 rhel7-4" -> "gvtest3_monitor_10000 rhel7-4" [ style = bold] +"gvtest3_start_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"vtest4_monitor_0 rhel7-1" -> "vtest4_start_0 rhel7-3" [ style = bold] +"vtest4_monitor_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"vtest4_monitor_0 rhel7-2" -> "vtest4_start_0 rhel7-3" [ style = bold] +"vtest4_monitor_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +"vtest4_monitor_0 rhel7-3" -> "vtest4_start_0 rhel7-3" [ style = bold] +"vtest4_monitor_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +"vtest4_monitor_0 rhel7-4" -> "vtest4_start_0 rhel7-3" [ style = bold] +"vtest4_monitor_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"vtest4_monitor_0 rhel7-5" -> "vtest4_start_0 rhel7-3" [ style = bold] +"vtest4_monitor_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"vtest4_monitor_10000 rhel7-3" [ style=bold color="green" fontcolor="black"] +"vtest4_start_0 rhel7-3" -> "vtest4_monitor_10000 rhel7-3" [ style = bold] +"vtest4_start_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +"vtest5-clone_running_0" [ style=bold color="green" fontcolor="orange"] +"vtest5-clone_start_0" -> "vtest5-clone_running_0" [ style = bold] +"vtest5-clone_start_0" -> "vtest5:0_start_0 rhel7-4" [ style = bold] +"vtest5-clone_start_0" -> "vtest5:1_start_0 rhel7-5" [ style = bold] +"vtest5-clone_start_0" -> "vtest5:2_start_0 rhel7-1" [ style = bold] +"vtest5-clone_start_0" -> "vtest5:3_start_0 rhel7-2" [ style = bold] +"vtest5-clone_start_0" -> "vtest5:4_start_0 rhel7-3" [ style = bold] +"vtest5-clone_start_0" [ style=bold color="green" fontcolor="orange"] +"vtest5:0_monitor_0 rhel7-4" -> "vtest5-clone_start_0" [ style = bold] +"vtest5:0_monitor_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"vtest5:0_monitor_10000 rhel7-4" [ style=bold color="green" fontcolor="black"] +"vtest5:0_start_0 rhel7-4" -> "vtest5-clone_running_0" [ style = bold] +"vtest5:0_start_0 rhel7-4" -> "vtest5:0_monitor_10000 rhel7-4" [ style = bold] +"vtest5:0_start_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"vtest5:1_monitor_0 rhel7-5" -> "vtest5-clone_start_0" [ style = bold] +"vtest5:1_monitor_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"vtest5:1_monitor_10000 rhel7-5" [ style=bold color="green" fontcolor="black"] +"vtest5:1_start_0 rhel7-5" -> "vtest5-clone_running_0" [ style = bold] +"vtest5:1_start_0 rhel7-5" -> "vtest5:1_monitor_10000 rhel7-5" [ style = bold] +"vtest5:1_start_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"vtest5:2_monitor_0 rhel7-1" -> "vtest5-clone_start_0" [ style = bold] +"vtest5:2_monitor_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"vtest5:2_monitor_10000 rhel7-1" [ style=bold color="green" fontcolor="black"] +"vtest5:2_start_0 rhel7-1" -> "vtest5-clone_running_0" [ style = bold] +"vtest5:2_start_0 rhel7-1" -> "vtest5:2_monitor_10000 rhel7-1" [ style = bold] +"vtest5:2_start_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"vtest5:3_monitor_0 rhel7-2" -> "vtest5-clone_start_0" [ style = bold] +"vtest5:3_monitor_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +"vtest5:3_monitor_10000 rhel7-2" [ style=bold color="green" fontcolor="black"] +"vtest5:3_start_0 rhel7-2" -> "vtest5-clone_running_0" [ style = bold] +"vtest5:3_start_0 rhel7-2" -> "vtest5:3_monitor_10000 rhel7-2" [ style = bold] +"vtest5:3_start_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +"vtest5:4_monitor_0 rhel7-3" -> "vtest5-clone_start_0" [ style = bold] +"vtest5:4_monitor_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +"vtest5:4_monitor_10000 rhel7-3" [ style=bold color="green" fontcolor="black"] +"vtest5:4_start_0 rhel7-3" -> "vtest5-clone_running_0" [ style = bold] +"vtest5:4_start_0 rhel7-3" -> "vtest5:4_monitor_10000 rhel7-3" [ style = bold] +"vtest5:4_start_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +"vtest7-master_running_0" [ style=bold color="green" fontcolor="orange"] +"vtest7-master_start_0" -> "vtest7-master_running_0" [ style = bold] +"vtest7-master_start_0" -> "vtest7:0_start_0 rhel7-4" [ style = bold] +"vtest7-master_start_0" -> "vtest7:1_start_0 rhel7-5" [ style = bold] +"vtest7-master_start_0" -> "vtest7:2_start_0 rhel7-1" [ style = bold] +"vtest7-master_start_0" -> "vtest7:3_start_0 rhel7-2" [ style = bold] +"vtest7-master_start_0" -> "vtest7:4_start_0 rhel7-3" [ style = bold] +"vtest7-master_start_0" [ style=bold color="green" fontcolor="orange"] +"vtest7:0_monitor_0 rhel7-4" -> "vtest7-master_start_0" [ style = bold] +"vtest7:0_monitor_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"vtest7:0_monitor_11000 rhel7-4" [ style=bold color="green" fontcolor="black"] +"vtest7:0_start_0 rhel7-4" -> "vtest7-master_running_0" [ style = bold] +"vtest7:0_start_0 rhel7-4" -> "vtest7:0_monitor_11000 rhel7-4" [ style = bold] +"vtest7:0_start_0 rhel7-4" [ style=bold color="green" fontcolor="black"] +"vtest7:1_monitor_0 rhel7-5" -> "vtest7-master_start_0" [ style = bold] +"vtest7:1_monitor_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"vtest7:1_monitor_11000 rhel7-5" [ style=bold color="green" fontcolor="black"] +"vtest7:1_start_0 rhel7-5" -> "vtest7-master_running_0" [ style = bold] +"vtest7:1_start_0 rhel7-5" -> "vtest7:1_monitor_11000 rhel7-5" [ style = bold] +"vtest7:1_start_0 rhel7-5" [ style=bold color="green" fontcolor="black"] +"vtest7:2_monitor_0 rhel7-1" -> "vtest7-master_start_0" [ style = bold] +"vtest7:2_monitor_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"vtest7:2_monitor_11000 rhel7-1" [ style=bold color="green" fontcolor="black"] +"vtest7:2_start_0 rhel7-1" -> "vtest7-master_running_0" [ style = bold] +"vtest7:2_start_0 rhel7-1" -> "vtest7:2_monitor_11000 rhel7-1" [ style = bold] +"vtest7:2_start_0 rhel7-1" [ style=bold color="green" fontcolor="black"] +"vtest7:3_monitor_0 rhel7-2" -> "vtest7-master_start_0" [ style = bold] +"vtest7:3_monitor_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +"vtest7:3_monitor_11000 rhel7-2" [ style=bold color="green" fontcolor="black"] +"vtest7:3_start_0 rhel7-2" -> "vtest7-master_running_0" [ style = bold] +"vtest7:3_start_0 rhel7-2" -> "vtest7:3_monitor_11000 rhel7-2" [ style = bold] +"vtest7:3_start_0 rhel7-2" [ style=bold color="green" fontcolor="black"] +"vtest7:4_monitor_0 rhel7-3" -> "vtest7-master_start_0" [ style = bold] +"vtest7:4_monitor_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +"vtest7:4_monitor_11000 rhel7-3" [ style=bold color="green" fontcolor="black"] +"vtest7:4_start_0 rhel7-3" -> "vtest7-master_running_0" [ style = bold] +"vtest7:4_start_0 rhel7-3" -> "vtest7:4_monitor_11000 rhel7-3" [ style = bold] +"vtest7:4_start_0 rhel7-3" [ style=bold color="green" fontcolor="black"] +} diff --git a/pengine/test10/versioned-resources.exp b/pengine/test10/versioned-resources.exp new file mode 100644 index 0000000000..bf69dfe65d --- /dev/null +++ b/pengine/test10/versioned-resources.exp @@ -0,0 +1,1676 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pengine/test10/versioned-resources.scores b/pengine/test10/versioned-resources.scores new file mode 100644 index 0000000000..ecb201b05f --- /dev/null +++ b/pengine/test10/versioned-resources.scores @@ -0,0 +1,166 @@ +Allocation scores: +clone_color: vtest5-clone allocation score on rhel7-1: 0 +clone_color: vtest5-clone allocation score on rhel7-2: 0 +clone_color: vtest5-clone allocation score on rhel7-3: 0 +clone_color: vtest5-clone allocation score on rhel7-4: 0 +clone_color: vtest5-clone allocation score on rhel7-5: 0 +clone_color: vtest5:0 allocation score on rhel7-1: 0 +clone_color: vtest5:0 allocation score on rhel7-2: 0 +clone_color: vtest5:0 allocation score on rhel7-3: 0 +clone_color: vtest5:0 allocation score on rhel7-4: 0 +clone_color: vtest5:0 allocation score on rhel7-5: 0 +clone_color: vtest5:1 allocation score on rhel7-1: 0 +clone_color: vtest5:1 allocation score on rhel7-2: 0 +clone_color: vtest5:1 allocation score on rhel7-3: 0 +clone_color: vtest5:1 allocation score on rhel7-4: 0 +clone_color: vtest5:1 allocation score on rhel7-5: 0 +clone_color: vtest5:2 allocation score on rhel7-1: 0 +clone_color: vtest5:2 allocation score on rhel7-2: 0 +clone_color: vtest5:2 allocation score on rhel7-3: 0 +clone_color: vtest5:2 allocation score on rhel7-4: 0 +clone_color: vtest5:2 allocation score on rhel7-5: 0 +clone_color: vtest5:3 allocation score on rhel7-1: 0 +clone_color: vtest5:3 allocation score on rhel7-2: 0 +clone_color: vtest5:3 allocation score on rhel7-3: 0 +clone_color: vtest5:3 allocation score on rhel7-4: 0 +clone_color: vtest5:3 allocation score on rhel7-5: 0 +clone_color: vtest5:4 allocation score on rhel7-1: 0 +clone_color: vtest5:4 allocation score on rhel7-2: 0 +clone_color: vtest5:4 allocation score on rhel7-3: 0 +clone_color: vtest5:4 allocation score on rhel7-4: 0 +clone_color: vtest5:4 allocation score on rhel7-5: 0 +clone_color: vtest7-master allocation score on rhel7-1: 0 +clone_color: vtest7-master allocation score on rhel7-2: 0 +clone_color: vtest7-master allocation score on rhel7-3: 0 +clone_color: vtest7-master allocation score on rhel7-4: 0 +clone_color: vtest7-master allocation score on rhel7-5: 0 +clone_color: vtest7:0 allocation score on rhel7-1: 0 +clone_color: vtest7:0 allocation score on rhel7-2: 0 +clone_color: vtest7:0 allocation score on rhel7-3: 0 +clone_color: vtest7:0 allocation score on rhel7-4: 0 +clone_color: vtest7:0 allocation score on rhel7-5: 0 +clone_color: vtest7:1 allocation score on rhel7-1: 0 +clone_color: vtest7:1 allocation score on rhel7-2: 0 +clone_color: vtest7:1 allocation score on rhel7-3: 0 +clone_color: vtest7:1 allocation score on rhel7-4: 0 +clone_color: vtest7:1 allocation score on rhel7-5: 0 +clone_color: vtest7:2 allocation score on rhel7-1: 0 +clone_color: vtest7:2 allocation score on rhel7-2: 0 +clone_color: vtest7:2 allocation score on rhel7-3: 0 +clone_color: vtest7:2 allocation score on rhel7-4: 0 +clone_color: vtest7:2 allocation score on rhel7-5: 0 +clone_color: vtest7:3 allocation score on rhel7-1: 0 +clone_color: vtest7:3 allocation score on rhel7-2: 0 +clone_color: vtest7:3 allocation score on rhel7-3: 0 +clone_color: vtest7:3 allocation score on rhel7-4: 0 +clone_color: vtest7:3 allocation score on rhel7-5: 0 +clone_color: vtest7:4 allocation score on rhel7-1: 0 +clone_color: vtest7:4 allocation score on rhel7-2: 0 +clone_color: vtest7:4 allocation score on rhel7-3: 0 +clone_color: vtest7:4 allocation score on rhel7-4: 0 +clone_color: vtest7:4 allocation score on rhel7-5: 0 +group_color: grouptest2 allocation score on rhel7-1: 0 +group_color: grouptest2 allocation score on rhel7-2: 0 +group_color: grouptest2 allocation score on rhel7-3: 0 +group_color: grouptest2 allocation score on rhel7-4: 0 +group_color: grouptest2 allocation score on rhel7-5: 0 +group_color: gvtest1 allocation score on rhel7-1: 0 +group_color: gvtest1 allocation score on rhel7-2: 0 +group_color: gvtest1 allocation score on rhel7-3: 0 +group_color: gvtest1 allocation score on rhel7-4: 0 +group_color: gvtest1 allocation score on rhel7-5: 0 +group_color: gvtest2 allocation score on rhel7-1: 0 +group_color: gvtest2 allocation score on rhel7-2: 0 +group_color: gvtest2 allocation score on rhel7-3: 0 +group_color: gvtest2 allocation score on rhel7-4: 0 +group_color: gvtest2 allocation score on rhel7-5: 0 +group_color: gvtest3 allocation score on rhel7-1: 0 +group_color: gvtest3 allocation score on rhel7-2: 0 +group_color: gvtest3 allocation score on rhel7-3: 0 +group_color: gvtest3 allocation score on rhel7-4: 0 +group_color: gvtest3 allocation score on rhel7-5: 0 +native_color: Fencing allocation score on rhel7-1: 0 +native_color: Fencing allocation score on rhel7-2: 0 +native_color: Fencing allocation score on rhel7-3: 0 +native_color: Fencing allocation score on rhel7-4: 0 +native_color: Fencing allocation score on rhel7-5: 0 +native_color: FencingPass allocation score on rhel7-1: 0 +native_color: FencingPass allocation score on rhel7-2: 0 +native_color: FencingPass allocation score on rhel7-3: 0 +native_color: FencingPass allocation score on rhel7-4: 0 +native_color: FencingPass allocation score on rhel7-5: 0 +native_color: gvtest1 allocation score on rhel7-1: 0 +native_color: gvtest1 allocation score on rhel7-2: 0 +native_color: gvtest1 allocation score on rhel7-3: 0 +native_color: gvtest1 allocation score on rhel7-4: 0 +native_color: gvtest1 allocation score on rhel7-5: 0 +native_color: gvtest2 allocation score on rhel7-1: -INFINITY +native_color: gvtest2 allocation score on rhel7-2: -INFINITY +native_color: gvtest2 allocation score on rhel7-3: -INFINITY +native_color: gvtest2 allocation score on rhel7-4: 0 +native_color: gvtest2 allocation score on rhel7-5: -INFINITY +native_color: gvtest3 allocation score on rhel7-1: -INFINITY +native_color: gvtest3 allocation score on rhel7-2: -INFINITY +native_color: gvtest3 allocation score on rhel7-3: -INFINITY +native_color: gvtest3 allocation score on rhel7-4: 0 +native_color: gvtest3 allocation score on rhel7-5: -INFINITY +native_color: vtest4 allocation score on rhel7-1: 0 +native_color: vtest4 allocation score on rhel7-2: 0 +native_color: vtest4 allocation score on rhel7-3: 0 +native_color: vtest4 allocation score on rhel7-4: 0 +native_color: vtest4 allocation score on rhel7-5: 0 +native_color: vtest5:0 allocation score on rhel7-1: 0 +native_color: vtest5:0 allocation score on rhel7-2: 0 +native_color: vtest5:0 allocation score on rhel7-3: 0 +native_color: vtest5:0 allocation score on rhel7-4: 0 +native_color: vtest5:0 allocation score on rhel7-5: 0 +native_color: vtest5:1 allocation score on rhel7-1: 0 +native_color: vtest5:1 allocation score on rhel7-2: 0 +native_color: vtest5:1 allocation score on rhel7-3: 0 +native_color: vtest5:1 allocation score on rhel7-4: -INFINITY +native_color: vtest5:1 allocation score on rhel7-5: 0 +native_color: vtest5:2 allocation score on rhel7-1: 0 +native_color: vtest5:2 allocation score on rhel7-2: 0 +native_color: vtest5:2 allocation score on rhel7-3: 0 +native_color: vtest5:2 allocation score on rhel7-4: -INFINITY +native_color: vtest5:2 allocation score on rhel7-5: -INFINITY +native_color: vtest5:3 allocation score on rhel7-1: -INFINITY +native_color: vtest5:3 allocation score on rhel7-2: 0 +native_color: vtest5:3 allocation score on rhel7-3: 0 +native_color: vtest5:3 allocation score on rhel7-4: -INFINITY +native_color: vtest5:3 allocation score on rhel7-5: -INFINITY +native_color: vtest5:4 allocation score on rhel7-1: -INFINITY +native_color: vtest5:4 allocation score on rhel7-2: -INFINITY +native_color: vtest5:4 allocation score on rhel7-3: 0 +native_color: vtest5:4 allocation score on rhel7-4: -INFINITY +native_color: vtest5:4 allocation score on rhel7-5: -INFINITY +native_color: vtest7:0 allocation score on rhel7-1: 0 +native_color: vtest7:0 allocation score on rhel7-2: 0 +native_color: vtest7:0 allocation score on rhel7-3: 0 +native_color: vtest7:0 allocation score on rhel7-4: 0 +native_color: vtest7:0 allocation score on rhel7-5: 0 +native_color: vtest7:1 allocation score on rhel7-1: 0 +native_color: vtest7:1 allocation score on rhel7-2: 0 +native_color: vtest7:1 allocation score on rhel7-3: 0 +native_color: vtest7:1 allocation score on rhel7-4: -INFINITY +native_color: vtest7:1 allocation score on rhel7-5: 0 +native_color: vtest7:2 allocation score on rhel7-1: 0 +native_color: vtest7:2 allocation score on rhel7-2: 0 +native_color: vtest7:2 allocation score on rhel7-3: 0 +native_color: vtest7:2 allocation score on rhel7-4: -INFINITY +native_color: vtest7:2 allocation score on rhel7-5: -INFINITY +native_color: vtest7:3 allocation score on rhel7-1: -INFINITY +native_color: vtest7:3 allocation score on rhel7-2: 0 +native_color: vtest7:3 allocation score on rhel7-3: 0 +native_color: vtest7:3 allocation score on rhel7-4: -INFINITY +native_color: vtest7:3 allocation score on rhel7-5: -INFINITY +native_color: vtest7:4 allocation score on rhel7-1: -INFINITY +native_color: vtest7:4 allocation score on rhel7-2: -INFINITY +native_color: vtest7:4 allocation score on rhel7-3: 0 +native_color: vtest7:4 allocation score on rhel7-4: -INFINITY +native_color: vtest7:4 allocation score on rhel7-5: -INFINITY +vtest7:0 promotion score on rhel7-4: -1 +vtest7:1 promotion score on rhel7-5: -1 +vtest7:2 promotion score on rhel7-1: -1 +vtest7:3 promotion score on rhel7-2: -1 +vtest7:4 promotion score on rhel7-3: -1 diff --git a/pengine/test10/versioned-resources.summary b/pengine/test10/versioned-resources.summary new file mode 100644 index 0000000000..78c361b0b1 --- /dev/null +++ b/pengine/test10/versioned-resources.summary @@ -0,0 +1,120 @@ + +Current cluster status: +Online: [ rhel7-1 rhel7-2 rhel7-3 rhel7-4 rhel7-5 ] + + Fencing (stonith:fence_xvm): Started rhel7-1 + FencingPass (stonith:fence_dummy): Stopped + vtest4 (ocf::kgaillot:vdummy): Stopped + Clone Set: vtest5-clone [vtest5] + Stopped: [ rhel7-1 rhel7-2 rhel7-3 rhel7-4 rhel7-5 ] + Master/Slave Set: vtest7-master [vtest7] + Stopped: [ rhel7-1 rhel7-2 rhel7-3 rhel7-4 rhel7-5 ] + Resource Group: grouptest2 + gvtest1 (ocf::kgaillot:vdummy): Stopped + gvtest2 (ocf::kgaillot:vdummy): Stopped + gvtest3 (ocf::kgaillot:vdummy): Stopped + +Transition Summary: + * Start FencingPass (rhel7-2) + * Start vtest4 (rhel7-3) + * Start vtest5:0 (rhel7-4) + * Start vtest5:1 (rhel7-5) + * Start vtest5:2 (rhel7-1) + * Start vtest5:3 (rhel7-2) + * Start vtest5:4 (rhel7-3) + * Start vtest7:0 (rhel7-4) + * Start vtest7:1 (rhel7-5) + * Start vtest7:2 (rhel7-1) + * Start vtest7:3 (rhel7-2) + * Start vtest7:4 (rhel7-3) + * Start gvtest1 (rhel7-4) + * Start gvtest2 (rhel7-4) + * Start gvtest3 (rhel7-4) + +Executing cluster transition: + * Resource action: FencingPass monitor on rhel7-5 + * Resource action: FencingPass monitor on rhel7-4 + * Resource action: FencingPass monitor on rhel7-3 + * Resource action: FencingPass monitor on rhel7-2 + * Resource action: FencingPass monitor on rhel7-1 + * Resource action: vtest4 monitor on rhel7-5 + * Resource action: vtest4 monitor on rhel7-4 + * Resource action: vtest4 monitor on rhel7-3 + * Resource action: vtest4 monitor on rhel7-2 + * Resource action: vtest4 monitor on rhel7-1 + * Resource action: vtest5:0 monitor on rhel7-4 + * Resource action: vtest5:1 monitor on rhel7-5 + * Resource action: vtest5:2 monitor on rhel7-1 + * Resource action: vtest5:3 monitor on rhel7-2 + * Resource action: vtest5:4 monitor on rhel7-3 + * Pseudo action: vtest5-clone_start_0 + * Resource action: vtest7:0 monitor on rhel7-4 + * Resource action: vtest7:1 monitor on rhel7-5 + * Resource action: vtest7:2 monitor on rhel7-1 + * Resource action: vtest7:3 monitor on rhel7-2 + * Resource action: vtest7:4 monitor on rhel7-3 + * Pseudo action: vtest7-master_start_0 + * Pseudo action: grouptest2_start_0 + * Resource action: gvtest1 monitor on rhel7-5 + * Resource action: gvtest1 monitor on rhel7-4 + * Resource action: gvtest1 monitor on rhel7-3 + * Resource action: gvtest1 monitor on rhel7-2 + * Resource action: gvtest1 monitor on rhel7-1 + * Resource action: gvtest2 monitor on rhel7-5 + * Resource action: gvtest2 monitor on rhel7-4 + * Resource action: gvtest2 monitor on rhel7-3 + * Resource action: gvtest2 monitor on rhel7-2 + * Resource action: gvtest2 monitor on rhel7-1 + * Resource action: gvtest3 monitor on rhel7-5 + * Resource action: gvtest3 monitor on rhel7-4 + * Resource action: gvtest3 monitor on rhel7-3 + * Resource action: gvtest3 monitor on rhel7-2 + * Resource action: gvtest3 monitor on rhel7-1 + * Resource action: FencingPass start on rhel7-2 + * Resource action: vtest4 start on rhel7-3 + * Resource action: vtest5:0 start on rhel7-4 + * Resource action: vtest5:1 start on rhel7-5 + * Resource action: vtest5:2 start on rhel7-1 + * Resource action: vtest5:3 start on rhel7-2 + * Resource action: vtest5:4 start on rhel7-3 + * Pseudo action: vtest5-clone_running_0 + * Resource action: vtest7:0 start on rhel7-4 + * Resource action: vtest7:1 start on rhel7-5 + * Resource action: vtest7:2 start on rhel7-1 + * Resource action: vtest7:3 start on rhel7-2 + * Resource action: vtest7:4 start on rhel7-3 + * Pseudo action: vtest7-master_running_0 + * Resource action: gvtest1 start on rhel7-4 + * Resource action: gvtest2 start on rhel7-4 + * Resource action: gvtest3 start on rhel7-4 + * Resource action: vtest4 monitor=10000 on rhel7-3 + * Resource action: vtest5:0 monitor=10000 on rhel7-4 + * Resource action: vtest5:1 monitor=10000 on rhel7-5 + * Resource action: vtest5:2 monitor=10000 on rhel7-1 + * Resource action: vtest5:3 monitor=10000 on rhel7-2 + * Resource action: vtest5:4 monitor=10000 on rhel7-3 + * Resource action: vtest7:0 monitor=11000 on rhel7-4 + * Resource action: vtest7:1 monitor=11000 on rhel7-5 + * Resource action: vtest7:2 monitor=11000 on rhel7-1 + * Resource action: vtest7:3 monitor=11000 on rhel7-2 + * Resource action: vtest7:4 monitor=11000 on rhel7-3 + * Pseudo action: grouptest2_running_0 + * Resource action: gvtest1 monitor=10000 on rhel7-4 + * Resource action: gvtest2 monitor=10000 on rhel7-4 + * Resource action: gvtest3 monitor=10000 on rhel7-4 + +Revised cluster status: +Online: [ rhel7-1 rhel7-2 rhel7-3 rhel7-4 rhel7-5 ] + + Fencing (stonith:fence_xvm): Started rhel7-1 + FencingPass (stonith:fence_dummy): Started rhel7-2 + vtest4 (ocf::kgaillot:vdummy): Started rhel7-3 + Clone Set: vtest5-clone [vtest5] + Started: [ rhel7-1 rhel7-2 rhel7-3 rhel7-4 rhel7-5 ] + Master/Slave Set: vtest7-master [vtest7] + Slaves: [ rhel7-1 rhel7-2 rhel7-3 rhel7-4 rhel7-5 ] + Resource Group: grouptest2 + gvtest1 (ocf::kgaillot:vdummy): Started rhel7-4 + gvtest2 (ocf::kgaillot:vdummy): Started rhel7-4 + gvtest3 (ocf::kgaillot:vdummy): Started rhel7-4 + diff --git a/pengine/test10/versioned-resources.xml b/pengine/test10/versioned-resources.xml new file mode 100644 index 0000000000..594c04284c --- /dev/null +++ b/pengine/test10/versioned-resources.xml @@ -0,0 +1,275 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +