diff --git a/.gitignore b/.gitignore index 397b2f2bd5..85dcf9149a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,213 +1,213 @@ # Common \#* .\#* GPATH GRTAGS GTAGS TAGS Makefile Makefile.in .deps .dirstamp .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-* libtool libtool.m4 ltdl.m4 libltdl ltmain.sh missing py-compile /m4/argz.m4 /m4/ltargz.m4 /m4/ltoptions.m4 /m4/ltsugar.m4 /m4/ltversion.m4 /m4/lt~obsolete.m4 test-driver ylwrap # Configure targets Doxyfile /cts/CTS.py /cts/CTSlab.py /cts/CTSvars.py /cts/LSBDummy /cts/OCFIPraTest.py /cts/benchmark/clubench /cts/cluster_test /cts/cts /cts/cts-cli /cts/cts-coverage /cts/cts-exec /cts/cts-fencing /cts/cts-log-watcher /cts/cts-regression /cts/cts-scheduler /cts/cts-support /cts/fence_dummy /cts/lxc_autogen.sh /cts/pacemaker-cts-dummyd /cts/pacemaker-cts-dummyd@.service /daemons/execd/pacemaker_remote /daemons/execd/pacemaker_remote.service /daemons/fenced/fence_legacy /daemons/pacemakerd/pacemaker /daemons/pacemakerd/pacemaker.combined.upstart /daemons/pacemakerd/pacemaker.service /daemons/pacemakerd/pacemaker.upstart /extra/logrotate/pacemaker /extra/resources/ClusterMon /extra/resources/HealthSMART /extra/resources/SysInfo /extra/resources/ifspeed /extra/resources/o2cb include/config.h include/config.h.in include/crm_config.h publican.cfg /tools/cibsecret /tools/crm_error /tools/crm_failcount /tools/crm_master /tools/crm_mon.service /tools/crm_mon.upstart /tools/crm_report /tools/crm_standby /tools/report.collector /tools/report.common # Build targets *.7 *.7.xml *.7.html *.8 *.8.xml *.8.html doc/*/en-US/images/*.png doc/*/tmp/** doc/*/publish /daemons/attrd/pacemaker-attrd /daemons/based/pacemaker-based /daemons/based/cibmon /daemons/controld/pacemaker-controld /daemons/execd/cts-exec-helper /daemons/execd/pacemaker-execd /daemons/execd/pacemaker-remoted /daemons/fenced/cts-fence-helper /daemons/fenced/pacemaker-fenced /daemons/fenced/pacemaker-fenced.xml /daemons/pacemakerd/pacemakerd /daemons/schedulerd/pacemaker-schedulerd /daemons/schedulerd/pacemaker-schedulerd.xml /daemons/schedulerd/ptest doc/api/* doc/Clusters_from_Scratch.txt doc/Pacemaker_Explained.txt doc/acls.html doc/crm_fencing.html doc/publican-catalog* scratch /tools/attrd_updater /tools/cibadmin /tools/crmadmin /tools/crm_attribute /tools/crm_diff /tools/crm_mon /tools/crm_node /tools/crm_resource /tools/crm_shadow /tools/crm_simulate /tools/crm_ticket /tools/crm_verify /tools/iso8601 /tools/stonith_admin 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_Administration.build doc/Pacemaker_Administration/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 # Test detritus /cts/.regression.failed.diff /cts/scheduler/*.ref /cts/scheduler/*.up /cts/scheduler/*.up.err /cts/scheduler/bug-rh-1097457.log /cts/scheduler/bug-rh-1097457.trs /cts/scheduler/shadow.* /cts/test-suite.log -/xml/test-2/*.up -/xml/test-2/*.up.err +/xml/test-*/*.up +/xml/test-*/*.up.err /xml/assets/diffview.js # Formerly built files (helps when jumping back and forth in checkout) /attrd /cib /coverage.sh /crmd /cts/HBDummy /fencing /lrmd /mcp /pengine #Other mock HTML pacemaker*.spec coverity-* compat_reports .ABI-build abi_dumps logs *.patch *.diff *.sed *.orig *.rej *.swp diff --git a/.travis.yml b/.travis.yml index 74614503c2..8c4546bfb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,89 +1,121 @@ # Control file for the Travis autobuilder # https://docs.travis-ci.com/user/customizing-the-build/ language: c -compiler: - - gcc - - clang -# - cov-build + +matrix: + include: + - compiler: gcc + env: MAINT_EXTRA=0 + - compiler: clang + env: MAINT_EXTRA=0 + #- compiler: cov-build + # env: MAINT_EXTRA=0 + - compiler: gcc + env: MAINT_EXTRA=1 env: global: # -- BEGIN Coverity Scan ENV # Used by https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh # The build command with all of the arguments that you would apply to a manual `cov-build` - COVERITY_SCAN_BUILD_COMMAND="make" # Email address for notifications related to this build - OWNER_EMAIL="andrew@beekhof.net" # Regular expression selects on which branches to run analysis # Be aware of quotas. Do not run on every branch/commit - COVERITY_SCAN_BRANCH_PATTERN="1.1" # COVERITY_SCAN_TOKEN via "travis encrypt" using the repo's public key - secure: "qnrF7L8RejLUY7URdNe7XP4Hu4R55C0tvAuMRg4EjVtelOpw+nIgA7BLiX19q/70VjFuKcGnMhW28TdYl0uwMMdWKKxmwTim04Sy3UfOE2BPeuQOBphr+8s9gd0U1MO8j2dZ84A40t5Mkk946wWZwT0okpjOr/PfBOZkU3o87FM=" # -- END Coverity Scan ENV # sudo add-apt-repository ppa:hotot-team before_install: - sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ trusty main" - sudo apt-get update -qq # To switch to Travis-CI's containerized (non-sudo) architecture, # all our dependencies need to be on Travis's whitelist: # https://github.com/travis-ci/apt-package-whitelist # # The only ones that aren't already are: # - cluster-glue-dev: see open issue: # https://github.com/travis-ci/apt-package-whitelist/issues/2936 # - resource-agents: see open issue: # https://github.com/travis-ci/apt-package-whitelist/issues/4261 # - libdbus-1-dev: see multiple open issues: # https://github.com/travis-ci/apt-package-whitelist/issues?utf8=%E2%9C%93&q=is%3Aissue+libdbus+-1-dev # (a workaround is to install libdbus-glib-1-dev, which depends on it and is whitelisted) install: - - sudo apt-get install -qq automake autoconf chrpath libtool perl python python-dev - - sudo apt-get install -qq libbz2-dev libdbus-1-dev libglib2.0-dev libgnutls-dev libltdl-dev - - sudo apt-get install -qq libncurses5-dev libpam0g-dev libxml2-dev libxslt1-dev uuid-dev - - sudo apt-get install -qq libqb-dev libcfg-dev libcmap-dev libcorosync-common-dev libcpg-dev - - sudo apt-get install -qq libquorum-dev libsam-dev libtotem-pg-dev libvotequorum-dev - - sudo apt-get install -qq cluster-glue-dev resource-agents + - test $MAINT_EXTRA -ne 0 + || sudo apt-get install -qq + automake autoconf libtool + python python-dev + libbz2-dev libdbus-1-dev libglib2.0-dev libgnutls-dev libltdl-dev + libncurses5-dev libpam0g-dev libxml2-dev libxslt1-dev uuid-dev + libqb-dev libcfg-dev libcmap-dev libcorosync-common-dev libcpg-dev + libquorum-dev libsam-dev libtotem-pg-dev libvotequorum-dev + cluster-glue-dev resource-agents + - test $MAINT_EXTRA -eq 0 + || sudo apt-get install -qq + make libxml2-utils xsltproc before_script: # Save and restore CC so that ./configure can pass - - export CC_SAVED=$CC - - export CC=`echo ${CC} | sed s/cov-build/gcc/` - - ./autogen.sh - - ./configure - - export CC=$CC_SAVED + - test $MAINT_EXTRA -ne 0 || { + export CC_SAVED=$CC; + export CC=$(echo ${CC} | sed s/cov-build/gcc/); + ./autogen.sh; + ./configure; + export CC=$CC_SAVED; + } + - test $MAINT_EXTRA -eq 0 || ( + cd xml; + { cat Makefile.am; printf 'hack_rng\x3a %s' '${RNG_generated}'; } + | make -f- top_srcdir=$(pwd)/.. top_builddir=$(pwd)/.. hack_rng + ) script: -- if test ${CC} != cov-build; then sudo make install-exec-local || true; fi -- if test ${CC} != cov-build; then make && ./cts/cts-regression -V cli scheduler exec; fi -- if test ${CC} = cov-build; then export CC=gcc; bash ./travisci_build_coverity_scan.sh; fi +# XXX Is the following item needed? +- test $MAINT_EXTRA -ne 0 || test ${CC} = cov-build + || sudo make install-exec-local || true +- test $MAINT_EXTRA -ne 0 || test ${CC} = cov-build + || { make && ./cts/cts-regression -V cli scheduler exec; } +- test $MAINT_EXTRA -ne 0 || test ${CC} != cov-build + || export CC=gcc; bash ./travisci_build_coverity_scan.sh +- test $MAINT_EXTRA -eq 0 || ( cd xml; + ./regression.sh && ./regression.sh -B && ./regression.sh -S && { + schemas=; for schema in *.rng; do + case ${schema} in *cibtr*) ;; *) schemas="${schemas} ${schema}";; esac; + done; + xmllint --noout --relaxng 'http://relaxng.org/relaxng.rng' ${schemas}; + } + ) #after_script: #after_success: after_failure: - lsb_release -a - sudo cat /etc/apt/sources.list - whoami - env | sort - cat include/config.h notifications: irc: "irc.freenode.org#pcmk" # email: # recipients: # - developers@clusterlabs.org # whitelist branches: only: - master - "1.1" - "2.0" diff --git a/cts/cli/regression.upgrade.exp b/cts/cli/regression.upgrade.exp new file mode 100644 index 0000000000..d2599f8ee2 --- /dev/null +++ b/cts/cli/regression.upgrade.exp @@ -0,0 +1,129 @@ +Created new pacemaker configuration +Setting up shadow instance +A new shadow instance was created. To begin using it paste the following into your shell: + CIB_shadow=cts-cli ; export CIB_shadow +=#=#=#= Begin test: Set stonith-enabled=false =#=#=#= +=#=#=#= Current cib after: Set stonith-enabled=false =#=#=#= + + + + + + + + + + + + + +=#=#=#= End test: Set stonith-enabled=false - OK (0) =#=#=#= +* Passed: crm_attribute - Set stonith-enabled=false +=#=#=#= Begin test: Configure the initial resource =#=#=#= +=#=#=#= Current cib after: Configure the initial resource =#=#=#= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +=#=#=#= End test: Configure the initial resource - OK (0) =#=#=#= +* Passed: cibadmin - Configure the initial resource +=#=#=#= Begin test: Upgrade to latest CIB schema (trigger 2.10.xsl + the wrapping) =#=#=#= +INFO: Resources-operation instance_attributes: mySmartFuse-monitor-inputpower (rsc=mySmartFuse, meta=mySmartFuse-inputpower-instanceparams): dropping requires +INFO: Resources-operation instance_attributes: ... only start/promote operation taken into account +INFO: Resources-operation instance_attributes: mySmartFuse-monitor-outputpower (rsc=mySmartFuse, meta=mySmartFuse-outputpower-instanceparams): dropping requires +INFO: Resources-operation instance_attributes: ... only start/promote operation taken into account +DEBUG: instance_attributes: original element pointed to with @id-ref (mySmartFuse-outputpower-instanceparams) disappeared during upgrade +=#=#=#= Current cib after: Upgrade to latest CIB schema (trigger 2.10.xsl + the wrapping) =#=#=#= + + + + + + + + + + + + + + + + + + + + + + + + + + + + +=#=#=#= End test: Upgrade to latest CIB schema (trigger 2.10.xsl + the wrapping) - OK (0) =#=#=#= +* Passed: cibadmin - Upgrade to latest CIB schema (trigger 2.10.xsl + the wrapping) +=#=#=#= Begin test: Query a resource instance attribute (shall survive) =#=#=#= +outputpower +=#=#=#= Current cib after: Query a resource instance attribute (shall survive) =#=#=#= + + + + + + + + + + + + + + + + + + + + + + + + + + + + +=#=#=#= End test: Query a resource instance attribute (shall survive) - OK (0) =#=#=#= +* Passed: crm_resource - Query a resource instance attribute (shall survive) diff --git a/cts/cli/regression.validity.exp b/cts/cli/regression.validity.exp index d195b13aad..e7d8d386eb 100644 --- a/cts/cli/regression.validity.exp +++ b/cts/cli/regression.validity.exp @@ -1,434 +1,448 @@ Created new pacemaker configuration Setting up shadow instance A new shadow instance was created. To begin using it paste the following into your shell: CIB_shadow=cts-cli ; export CIB_shadow =#=#=#= Begin test: Try to make resulting CIB invalid (enum violation) =#=#=#= 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Call failed: Update does not conform to the configured schema =#=#=#= Current cib after: Try to make resulting CIB invalid (enum violation) =#=#=#= =#=#=#= End test: Try to make resulting CIB invalid (enum violation) - Invalid configuration (78) =#=#=#= * Passed: cibadmin - Try to make resulting CIB invalid (enum violation) =#=#=#= Begin test: Run crm_simulate with invalid CIB (enum violation) =#=#=#= update_validation debug: Testing 'pacemaker-1.2' validation (1 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-1.2 validation failed update_validation debug: Testing 'pacemaker-1.3' validation (2 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-1.3 validation failed update_validation debug: Testing 'pacemaker-2.0' validation (3 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.0 validation failed update_validation debug: Testing 'pacemaker-2.1' validation (4 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.1 validation failed update_validation debug: Testing 'pacemaker-2.2' validation (5 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.2 validation failed update_validation debug: Testing 'pacemaker-2.3' validation (6 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.3 validation failed update_validation debug: Testing 'pacemaker-2.4' validation (7 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.4 validation failed update_validation debug: Testing 'pacemaker-2.5' validation (8 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.5 validation failed update_validation debug: Testing 'pacemaker-2.6' validation (9 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.6 validation failed update_validation debug: Testing 'pacemaker-2.7' validation (10 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.7 validation failed update_validation debug: Testing 'pacemaker-2.8' validation (11 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.8 validation failed update_validation debug: Testing 'pacemaker-2.9' validation (12 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.9 validation failed update_validation debug: Testing 'pacemaker-2.10' validation (13 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-2.10 validation failed update_validation debug: Testing 'pacemaker-3.0' validation (14 of X) element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order update_validation trace: pacemaker-3.0 validation failed -Your current configuration pacemaker-1.2 could not validate with any schema in range [pacemaker-1.2, pacemaker-3.0], cannot upgrade to pacemaker-3.0. +update_validation debug: Testing 'pacemaker-3.1' validation (15 of X) +element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order +element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order +update_validation trace: pacemaker-3.1 validation failed +Your current configuration pacemaker-1.2 could not validate with any schema in range [pacemaker-1.2, pacemaker-3.1], cannot upgrade to pacemaker-3.0. =#=#=#= End test: Run crm_simulate with invalid CIB (enum violation) - Invalid configuration (78) =#=#=#= * Passed: crm_simulate - Run crm_simulate with invalid CIB (enum violation) =#=#=#= Begin test: Try to make resulting CIB invalid (unrecognized validate-with) =#=#=#= 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Call failed: Update does not conform to the configured schema =#=#=#= Current cib after: Try to make resulting CIB invalid (unrecognized validate-with) =#=#=#= =#=#=#= End test: Try to make resulting CIB invalid (unrecognized validate-with) - Invalid configuration (78) =#=#=#= * Passed: cibadmin - Try to make resulting CIB invalid (unrecognized validate-with) =#=#=#= Begin test: Run crm_simulate with invalid CIB (unrecognized validate-with) =#=#=#= update_validation debug: Unknown validation schema update_validation debug: Testing 'pacemaker-1.0' validation (0 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-1.0 validation failed update_validation debug: Testing 'pacemaker-1.2' validation (1 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-1.2 validation failed update_validation debug: Testing 'pacemaker-1.3' validation (2 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-1.3 validation failed update_validation debug: Testing 'pacemaker-2.0' validation (3 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.0 validation failed update_validation debug: Testing 'pacemaker-2.1' validation (4 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.1 validation failed update_validation debug: Testing 'pacemaker-2.2' validation (5 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.2 validation failed update_validation debug: Testing 'pacemaker-2.3' validation (6 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.3 validation failed update_validation debug: Testing 'pacemaker-2.4' validation (7 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.4 validation failed update_validation debug: Testing 'pacemaker-2.5' validation (8 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.5 validation failed update_validation debug: Testing 'pacemaker-2.6' validation (9 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.6 validation failed update_validation debug: Testing 'pacemaker-2.7' validation (10 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.7 validation failed update_validation debug: Testing 'pacemaker-2.8' validation (11 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.8 validation failed update_validation debug: Testing 'pacemaker-2.9' validation (12 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.9 validation failed update_validation debug: Testing 'pacemaker-2.10' validation (13 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-2.10 validation failed update_validation debug: Testing 'pacemaker-3.0' validation (14 of X) element cib: Relax-NG validity error : Invalid attribute validate-with for element cib update_validation trace: pacemaker-3.0 validation failed -Your current configuration pacemaker-9999.0 could not validate with any schema in range [unknown, pacemaker-3.0], cannot upgrade to pacemaker-3.0. +update_validation debug: Testing 'pacemaker-3.1' validation (15 of X) +element cib: Relax-NG validity error : Invalid attribute validate-with for element cib +update_validation trace: pacemaker-3.1 validation failed +Your current configuration pacemaker-9999.0 could not validate with any schema in range [unknown, pacemaker-3.1], cannot upgrade to pacemaker-3.0. =#=#=#= End test: Run crm_simulate with invalid CIB (unrecognized validate-with) - Invalid configuration (78) =#=#=#= * Passed: crm_simulate - Run crm_simulate with invalid CIB (unrecognized validate-with) =#=#=#= Begin test: Try to make resulting CIB invalid, but possibly recoverable (valid with X.Y+1) =#=#=#= 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Call failed: Update does not conform to the configured schema =#=#=#= Current cib after: Try to make resulting CIB invalid, but possibly recoverable (valid with X.Y+1) =#=#=#= =#=#=#= End test: Try to make resulting CIB invalid, but possibly recoverable (valid with X.Y+1) - Invalid configuration (78) =#=#=#= * Passed: cibadmin - Try to make resulting CIB invalid, but possibly recoverable (valid with X.Y+1) =#=#=#= Begin test: Run crm_simulate with invalid, but possibly recoverable CIB (valid with X.Y+1) =#=#=#= update_validation debug: Testing 'pacemaker-1.2' validation (1 of X) element tags: Relax-NG validity error : Element configuration has extra content: tags update_validation trace: pacemaker-1.2 validation failed update_validation debug: Testing 'pacemaker-1.3' validation (2 of X) -update_validation debug: Upgrading pacemaker-1.3-style configuration to pacemaker-2.0 with upgrade-1.3.xsl -update_validation info: Transformation upgrade-1.3.xsl successful +update_validation debug: pacemaker-1.3-style configuration is also valid for pacemaker-2.0 update_validation debug: Testing 'pacemaker-2.0' validation (3 of X) +update_validation debug: Configuration valid for schema: pacemaker-2.0 update_validation debug: pacemaker-2.0-style configuration is also valid for pacemaker-2.1 update_validation debug: Testing 'pacemaker-2.1' validation (4 of X) update_validation debug: Configuration valid for schema: pacemaker-2.1 update_validation debug: pacemaker-2.1-style configuration is also valid for pacemaker-2.2 update_validation debug: Testing 'pacemaker-2.2' validation (5 of X) update_validation debug: Configuration valid for schema: pacemaker-2.2 update_validation debug: pacemaker-2.2-style configuration is also valid for pacemaker-2.3 update_validation debug: Testing 'pacemaker-2.3' validation (6 of X) update_validation debug: Configuration valid for schema: pacemaker-2.3 update_validation debug: pacemaker-2.3-style configuration is also valid for pacemaker-2.4 update_validation debug: Testing 'pacemaker-2.4' validation (7 of X) update_validation debug: Configuration valid for schema: pacemaker-2.4 update_validation debug: pacemaker-2.4-style configuration is also valid for pacemaker-2.5 update_validation debug: Testing 'pacemaker-2.5' validation (8 of X) update_validation debug: Configuration valid for schema: pacemaker-2.5 update_validation debug: pacemaker-2.5-style configuration is also valid for pacemaker-2.6 update_validation debug: Testing 'pacemaker-2.6' validation (9 of X) update_validation debug: Configuration valid for schema: pacemaker-2.6 update_validation debug: pacemaker-2.6-style configuration is also valid for pacemaker-2.7 update_validation debug: Testing 'pacemaker-2.7' validation (10 of X) update_validation debug: Configuration valid for schema: pacemaker-2.7 update_validation debug: pacemaker-2.7-style configuration is also valid for pacemaker-2.8 update_validation debug: Testing 'pacemaker-2.8' validation (11 of X) update_validation debug: Configuration valid for schema: pacemaker-2.8 update_validation debug: pacemaker-2.8-style configuration is also valid for pacemaker-2.9 update_validation debug: Testing 'pacemaker-2.9' validation (12 of X) update_validation debug: Configuration valid for schema: pacemaker-2.9 update_validation debug: pacemaker-2.9-style configuration is also valid for pacemaker-2.10 update_validation debug: Testing 'pacemaker-2.10' validation (13 of X) update_validation debug: Configuration valid for schema: pacemaker-2.10 -update_validation debug: Upgrading pacemaker-2.10-style configuration to pacemaker-3.0 with upgrade-2.10.xsl -update_validation info: Transformation upgrade-2.10.xsl successful +update_validation debug: pacemaker-2.10-style configuration is also valid for pacemaker-3.0 update_validation debug: Testing 'pacemaker-3.0' validation (14 of X) -update_validation trace: Stopping at pacemaker-3.0 -update_validation info: Transformed the configuration from pacemaker-1.2 to pacemaker-3.0 +update_validation debug: Configuration valid for schema: pacemaker-3.0 +update_validation debug: pacemaker-3.0-style configuration is also valid for pacemaker-3.1 +update_validation debug: Testing 'pacemaker-3.1' validation (15 of X) +update_validation debug: Configuration valid for schema: pacemaker-3.1 +update_validation trace: Stopping at pacemaker-3.1 +update_validation info: Transformed the configuration from pacemaker-1.2 to pacemaker-3.1 unpack_resources error: Resource start-up disabled since no STONITH resources have been defined unpack_resources error: Either configure some or disable STONITH with the stonith-enabled option unpack_resources error: NOTE: Clusters with shared data need STONITH to ensure data integrity Current cluster status: dummy1 (ocf::pacemaker:Dummy): Stopped dummy2 (ocf::pacemaker:Dummy): Stopped Transition Summary: unpack_resources error: Resource start-up disabled since no STONITH resources have been defined unpack_resources error: Either configure some or disable STONITH with the stonith-enabled option unpack_resources error: NOTE: Clusters with shared data need STONITH to ensure data integrity Executing cluster transition: Revised cluster status: dummy1 (ocf::pacemaker:Dummy): Stopped dummy2 (ocf::pacemaker:Dummy): Stopped =#=#=#= End test: Run crm_simulate with invalid, but possibly recoverable CIB (valid with X.Y+1) - OK (0) =#=#=#= * Passed: crm_simulate - Run crm_simulate with invalid, but possibly recoverable CIB (valid with X.Y+1) =#=#=#= Begin test: Make resulting CIB valid, although without validate-with attribute =#=#=#= =#=#=#= Current cib after: Make resulting CIB valid, although without validate-with attribute =#=#=#= =#=#=#= End test: Make resulting CIB valid, although without validate-with attribute - OK (0) =#=#=#= * Passed: cibadmin - Make resulting CIB valid, although without validate-with attribute =#=#=#= Begin test: Run crm_simulate with valid CIB, but without validate-with attribute =#=#=#= Configuration validation is currently disabled. It is highly encouraged and prevents many common cluster issues. unpack_resources error: Resource start-up disabled since no STONITH resources have been defined unpack_resources error: Either configure some or disable STONITH with the stonith-enabled option unpack_resources error: NOTE: Clusters with shared data need STONITH to ensure data integrity Current cluster status: dummy1 (ocf::pacemaker:Dummy): Stopped dummy2 (ocf::pacemaker:Dummy): Stopped Transition Summary: unpack_resources error: Resource start-up disabled since no STONITH resources have been defined unpack_resources error: Either configure some or disable STONITH with the stonith-enabled option unpack_resources error: NOTE: Clusters with shared data need STONITH to ensure data integrity Executing cluster transition: Revised cluster status: dummy1 (ocf::pacemaker:Dummy): Stopped dummy2 (ocf::pacemaker:Dummy): Stopped =#=#=#= End test: Run crm_simulate with valid CIB, but without validate-with attribute - OK (0) =#=#=#= * Passed: crm_simulate - Run crm_simulate with valid CIB, but without validate-with attribute =#=#=#= Begin test: Make resulting CIB invalid, and without validate-with attribute =#=#=#= element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order +element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order +element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order =#=#=#= Current cib after: Make resulting CIB invalid, and without validate-with attribute =#=#=#= =#=#=#= End test: Make resulting CIB invalid, and without validate-with attribute - OK (0) =#=#=#= * Passed: cibadmin - Make resulting CIB invalid, and without validate-with attribute =#=#=#= Begin test: Run crm_simulate with invalid CIB, also without validate-with attribute =#=#=#= Configuration validation is currently disabled. It is highly encouraged and prevents many common cluster issues. validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order +validity.bad.xml:10: element rsc_order: Relax-NG validity error : Invalid attribute first-action for element rsc_order +validity.bad.xml:10: element rsc_order: Relax-NG validity error : Element constraints has extra content: rsc_order unpack_resources error: Resource start-up disabled since no STONITH resources have been defined unpack_resources error: Either configure some or disable STONITH with the stonith-enabled option unpack_resources error: NOTE: Clusters with shared data need STONITH to ensure data integrity unpack_simple_rsc_order error: Cannot invert rsc_order constraint ord_1-2. Please specify the inverse manually. Current cluster status: dummy1 (ocf::pacemaker:Dummy): Stopped dummy2 (ocf::pacemaker:Dummy): Stopped Transition Summary: unpack_resources error: Resource start-up disabled since no STONITH resources have been defined unpack_resources error: Either configure some or disable STONITH with the stonith-enabled option unpack_resources error: NOTE: Clusters with shared data need STONITH to ensure data integrity Executing cluster transition: Revised cluster status: dummy1 (ocf::pacemaker:Dummy): Stopped dummy2 (ocf::pacemaker:Dummy): Stopped =#=#=#= End test: Run crm_simulate with invalid CIB, also without validate-with attribute - OK (0) =#=#=#= * Passed: crm_simulate - Run crm_simulate with invalid CIB, also without validate-with attribute diff --git a/cts/cts-cli.in b/cts/cts-cli.in index 7abe4bbf2c..a917e87259 100755 --- a/cts/cts-cli.in +++ b/cts/cts-cli.in @@ -1,914 +1,967 @@ #!@BASH_PATH@ # # Copyright 2008-2018 Andrew Beekhof # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # # # Note on portable usage of sed: GNU/POSIX/*BSD sed have a limited subset of # compatible functionality. Do not use the -i option, alternation (\|), # \0, or character sequences such as \n or \s. # USAGE_TEXT="Usage: cts-cli [] Options: --help Display this text, then exit -V, --verbose Display any differences from expected output - -t 'TEST [...]' Run only specified tests (default: 'dates tools acls validity') + -t 'TEST [...]' Run only specified tests (default: 'dates tools acls validity upgrade') -p DIR Look for executables in DIR (may be specified multiple times) -v, --valgrind Run all commands under valgrind -s Save actual output as expected output" # If readlink supports -e (i.e. GNU), use it readlink -e / >/dev/null 2>/dev/null if [ $? -eq 0 ]; then test_home="$(dirname $(readlink -e $0))" else test_home="$(dirname $0)" fi : ${shadow=cts-cli} shadow_dir=$(mktemp -d ${TMPDIR:-/tmp}/cts-cli.shadow.XXXXXXXXXX) num_errors=0 num_passed=0 GREP_OPTIONS= verbose=0 -tests="dates tools acls validity" +tests="dates tools acls validity upgrade" do_save=0 VALGRIND_CMD= VALGRIND_OPTS=" -q --gen-suppressions=all --show-reachable=no --leak-check=full --trace-children=no --time-stamp=yes --num-callers=20 --suppressions=$test_home/valgrind-pcmk.suppressions " # These constants must track crm_exit_t values CRM_EX_OK=0 CRM_EX_ERROR=1 CRM_EX_INSUFFICIENT_PRIV=4 CRM_EX_USAGE=64 CRM_EX_CONFIG=78 CRM_EX_OLD=103 CRM_EX_NOSUCH=105 CRM_EX_UNSAFE=107 CRM_EX_EXISTS=108 CRM_EX_MULTIPLE=109 function test_assert() { target=$1; shift cib=$1; shift app=`echo "$cmd" | sed 's/\ .*//'` printf "* Running: $app - $desc\n" 1>&2 printf "=#=#=#= Begin test: $desc =#=#=#=\n" eval $VALGRIND_CMD $cmd 2>&1 rc=$? if [ x$cib != x0 ]; then printf "=#=#=#= Current cib after: $desc =#=#=#=\n" CIB_user=root cibadmin -Q fi printf "=#=#=#= End test: $desc - $(crm_error --exit $rc) ($rc) =#=#=#=\n" if [ $rc -ne $target ]; then num_errors=$(( $num_errors + 1 )) printf "* Failed (rc=%.3d): %-14s - %s\n" $rc $app "$desc" printf "* Failed (rc=%.3d): %-14s - %s\n" $rc $app "$desc (`which $app`)" 1>&2 return exit $CRM_EX_ERROR else printf "* Passed: %-14s - %s\n" $app "$desc" num_passed=$(( $num_passed + 1 )) fi } function test_tools() { local TMPXML=$(mktemp ${TMPDIR:-/tmp}/cts-cli.tools.xml.XXXXXXXXXX) local TMPORIG=$(mktemp ${TMPDIR:-/tmp}/cts-cli.tools.existing.xml.XXXXXXXXXX) export CIB_shadow_dir="${shadow_dir}" $VALGRIND_CMD crm_shadow --batch --force --create-empty $shadow 2>&1 export CIB_shadow=$shadow desc="Validate CIB" cmd="cibadmin -Q" test_assert $CRM_EX_OK desc="Configure something before erasing" cmd="crm_attribute -n cluster-delay -v 60s" test_assert $CRM_EX_OK desc="Require --force for CIB erasure" cmd="cibadmin -E" test_assert $CRM_EX_UNSAFE desc="Allow CIB erasure with --force" cmd="cibadmin -E --force" test_assert $CRM_EX_OK desc="Query CIB" cmd="cibadmin -Q > $TMPORIG" test_assert $CRM_EX_OK desc="Set cluster option" cmd="crm_attribute -n cluster-delay -v 60s" test_assert $CRM_EX_OK desc="Query new cluster option" cmd="cibadmin -Q -o crm_config | grep cib-bootstrap-options-cluster-delay" test_assert $CRM_EX_OK desc="Query cluster options" cmd="cibadmin -Q -o crm_config > $TMPXML" test_assert $CRM_EX_OK desc="Set no-quorum policy" cmd="crm_attribute -n no-quorum-policy -v ignore" test_assert $CRM_EX_OK desc="Delete nvpair" cmd="cibadmin -D -o crm_config --xml-text ''" test_assert $CRM_EX_OK desc="Create operation should fail" cmd="cibadmin -C -o crm_config --xml-file $TMPXML" test_assert $CRM_EX_EXISTS desc="Modify cluster options section" cmd="cibadmin -M -o crm_config --xml-file $TMPXML" test_assert $CRM_EX_OK desc="Query updated cluster option" cmd="cibadmin -Q -o crm_config | grep cib-bootstrap-options-cluster-delay" test_assert $CRM_EX_OK desc="Set duplicate cluster option" cmd="crm_attribute -n cluster-delay -v 40s -s duplicate" test_assert $CRM_EX_OK desc="Setting multiply defined cluster option should fail" cmd="crm_attribute -n cluster-delay -v 30s" test_assert $CRM_EX_MULTIPLE desc="Set cluster option with -s" cmd="crm_attribute -n cluster-delay -v 30s -s duplicate" test_assert $CRM_EX_OK desc="Delete cluster option with -i" cmd="crm_attribute -n cluster-delay -D -i cib-bootstrap-options-cluster-delay" test_assert $CRM_EX_OK desc="Create node1 and bring it online" cmd="crm_simulate --live-check --in-place --node-up=node1" test_assert $CRM_EX_OK desc="Create node attribute" cmd="crm_attribute -n ram -v 1024M -N node1 -t nodes" test_assert $CRM_EX_OK desc="Query new node attribute" cmd="cibadmin -Q -o nodes | grep node1-ram" test_assert $CRM_EX_OK desc="Set a transient (fail-count) node attribute" cmd="crm_attribute -n fail-count-foo -v 3 -N node1 -t status" test_assert $CRM_EX_OK desc="Query a fail count" cmd="crm_failcount --query -r foo -N node1" test_assert $CRM_EX_OK desc="Delete a transient (fail-count) node attribute" cmd="crm_attribute -n fail-count-foo -D -N node1 -t status" test_assert $CRM_EX_OK desc="Digest calculation" cmd="cibadmin -Q | cibadmin -5 -p 2>&1 > /dev/null" test_assert $CRM_EX_OK # This update will fail because it has version numbers desc="Replace operation should fail" cmd="cibadmin -R --xml-file $TMPORIG" test_assert $CRM_EX_OLD desc="Default standby value" cmd="crm_standby -N node1 -G" test_assert $CRM_EX_OK desc="Set standby status" cmd="crm_standby -N node1 -v true" test_assert $CRM_EX_OK desc="Query standby value" cmd="crm_standby -N node1 -G" test_assert $CRM_EX_OK desc="Delete standby value" cmd="crm_standby -N node1 -D" test_assert $CRM_EX_OK desc="Create a resource" cmd="cibadmin -C -o resources --xml-text ''" test_assert $CRM_EX_OK desc="Create a resource meta attribute" cmd="crm_resource -r dummy --meta -p is-managed -v false" test_assert $CRM_EX_OK desc="Query a resource meta attribute" cmd="crm_resource -r dummy --meta -g is-managed" test_assert $CRM_EX_OK desc="Remove a resource meta attribute" cmd="crm_resource -r dummy --meta -d is-managed" test_assert $CRM_EX_OK desc="Create a resource attribute" cmd="crm_resource -r dummy -p delay -v 10s" test_assert $CRM_EX_OK desc="List the configured resources" cmd="crm_resource -L" test_assert $CRM_EX_OK desc="Require a destination when migrating a resource that is stopped" cmd="crm_resource -r dummy -M" test_assert $CRM_EX_USAGE desc="Don't support migration to non-existent locations" cmd="crm_resource -r dummy -M -N i.dont.exist" test_assert $CRM_EX_NOSUCH desc="Create a fencing resource" cmd="cibadmin -C -o resources --xml-text ''" test_assert $CRM_EX_OK desc="Bring resources online" cmd="crm_simulate --live-check --in-place -S" test_assert $CRM_EX_OK desc="Try to move a resource to its existing location" cmd="crm_resource -r dummy --move --host node1" test_assert $CRM_EX_EXISTS desc="Move a resource from its existing location" cmd="crm_resource -r dummy --move" test_assert $CRM_EX_OK desc="Clear out constraints generated by --move" cmd="crm_resource -r dummy --clear" test_assert $CRM_EX_OK desc="Default ticket granted state" cmd="crm_ticket -t ticketA -G granted -d false" test_assert $CRM_EX_OK desc="Set ticket granted state" cmd="crm_ticket -t ticketA -r --force" test_assert $CRM_EX_OK desc="Query ticket granted state" cmd="crm_ticket -t ticketA -G granted" test_assert $CRM_EX_OK desc="Delete ticket granted state" cmd="crm_ticket -t ticketA -D granted --force" test_assert $CRM_EX_OK desc="Make a ticket standby" cmd="crm_ticket -t ticketA -s" test_assert $CRM_EX_OK desc="Query ticket standby state" cmd="crm_ticket -t ticketA -G standby" test_assert $CRM_EX_OK desc="Activate a ticket" cmd="crm_ticket -t ticketA -a" test_assert $CRM_EX_OK desc="Delete ticket standby state" cmd="crm_ticket -t ticketA -D standby" test_assert $CRM_EX_OK desc="Ban a resource on unknown node" cmd="crm_resource -r dummy -B -N host1" test_assert $CRM_EX_NOSUCH desc="Create two more nodes and bring them online" cmd="crm_simulate --live-check --in-place --node-up=node2 --node-up=node3" test_assert $CRM_EX_OK desc="Ban dummy from node1" cmd="crm_resource -r dummy -B -N node1" test_assert $CRM_EX_OK desc="Ban dummy from node2" cmd="crm_resource -r dummy -B -N node2" test_assert $CRM_EX_OK desc="Relocate resources due to ban" cmd="crm_simulate --live-check --in-place -S" test_assert $CRM_EX_OK desc="Move dummy to node1" cmd="crm_resource -r dummy -M -N node1" test_assert $CRM_EX_OK desc="Clear implicit constraints for dummy on node2" cmd="crm_resource -r dummy -U -N node2" test_assert $CRM_EX_OK desc="Drop the status section" cmd="cibadmin -R -o status --xml-text ''" test_assert $CRM_EX_OK 0 desc="Create a clone" cmd="cibadmin -C -o resources --xml-text ''" test_assert $CRM_EX_OK 0 desc="Create a resource meta attribute" cmd="crm_resource -r test-primitive --meta -p is-managed -v false" test_assert $CRM_EX_OK desc="Create a resource meta attribute in the primitive" cmd="crm_resource -r test-primitive --meta -p is-managed -v false --force" test_assert $CRM_EX_OK desc="Update resource meta attribute with duplicates" cmd="crm_resource -r test-clone --meta -p is-managed -v true" test_assert $CRM_EX_OK desc="Update resource meta attribute with duplicates (force clone)" cmd="crm_resource -r test-clone --meta -p is-managed -v true --force" test_assert $CRM_EX_OK desc="Update child resource meta attribute with duplicates" cmd="crm_resource -r test-primitive --meta -p is-managed -v false" test_assert $CRM_EX_OK desc="Delete resource meta attribute with duplicates" cmd="crm_resource -r test-clone --meta -d is-managed" test_assert $CRM_EX_OK desc="Delete resource meta attribute in parent" cmd="crm_resource -r test-primitive --meta -d is-managed" test_assert $CRM_EX_OK desc="Create a resource meta attribute in the primitive" cmd="crm_resource -r test-primitive --meta -p is-managed -v false --force" test_assert $CRM_EX_OK desc="Update existing resource meta attribute" cmd="crm_resource -r test-clone --meta -p is-managed -v true" test_assert $CRM_EX_OK desc="Create a resource meta attribute in the parent" cmd="crm_resource -r test-clone --meta -p is-managed -v true --force" test_assert $CRM_EX_OK desc="Copy resources" cmd="cibadmin -Q -o resources > $TMPXML" test_assert $CRM_EX_OK 0 desc="Delete resource paremt meta attribute (force)" cmd="crm_resource -r test-clone --meta -d is-managed --force" test_assert $CRM_EX_OK desc="Restore duplicates" cmd="cibadmin -R -o resources --xml-file $TMPXML" test_assert $CRM_EX_OK desc="Delete resource child meta attribute" cmd="crm_resource -r test-primitive --meta -d is-managed" test_assert $CRM_EX_OK unset CIB_shadow_dir rm -f "$TMPXML" "$TMPORIG" } function test_dates() { desc="2014-01-01 00:30:00 - 1 Hour" cmd="iso8601 -d '2014-01-01 00:30:00Z' -D P-1H -E '2013-12-31 23:30:00Z'" test_assert $CRM_EX_OK 0 for y in 06 07 08 09 10 11 12 13 14 15 16 17 18; do desc="20$y-W01-7" cmd="iso8601 -d '20$y-W01-7 00Z'" test_assert $CRM_EX_OK 0 desc="20$y-W01-7 - round-trip" cmd="iso8601 -d '20$y-W01-7 00Z' -W -E '20$y-W01-7 00:00:00Z'" test_assert $CRM_EX_OK 0 desc="20$y-W01-1" cmd="iso8601 -d '20$y-W01-1 00Z'" test_assert $CRM_EX_OK 0 desc="20$y-W01-1 - round-trip" cmd="iso8601 -d '20$y-W01-1 00Z' -W -E '20$y-W01-1 00:00:00Z'" test_assert $CRM_EX_OK 0 done desc="2009-W53-07" cmd="iso8601 -d '2009-W53-7 00:00:00Z' -W -E '2009-W53-7 00:00:00Z'" test_assert $CRM_EX_OK 0 desc="2009-01-31 + 1 Month" cmd="iso8601 -d '2009-01-31 00:00:00Z' -D P1M -E '2009-02-28 00:00:00Z'" test_assert $CRM_EX_OK 0 desc="2009-01-31 + 2 Months" cmd="iso8601 -d '2009-01-31 00:00:00Z' -D P2M -E '2009-03-31 00:00:00Z'" test_assert $CRM_EX_OK 0 desc="2009-01-31 + 3 Months" cmd="iso8601 -d '2009-01-31 00:00:00Z' -D P3M -E '2009-04-30 00:00:00Z'" test_assert $CRM_EX_OK 0 desc="2009-03-31 - 1 Month" cmd="iso8601 -d '2009-03-31 00:00:00Z' -D P-1M -E '2009-02-28 00:00:00Z'" test_assert $CRM_EX_OK 0 } function test_acl_loop() { local TMPXML="$1" # Make sure we're rejecting things for the right reasons export PCMK_trace_functions=__xml_acl_check,__xml_acl_post_process export PCMK_stderr=1 CIB_user=root cibadmin --replace --xml-text '' export CIB_user=unknownguy desc="$CIB_user: Query configuration" cmd="cibadmin -Q" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 desc="$CIB_user: Set enable-acl" cmd="crm_attribute -n enable-acl -v false" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 desc="$CIB_user: Set stonith-enabled" cmd="crm_attribute -n stonith-enabled -v false" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 desc="$CIB_user: Create a resource" cmd="cibadmin -C -o resources --xml-text ''" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 export CIB_user=l33t-haxor desc="$CIB_user: Query configuration" cmd="cibadmin -Q" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 desc="$CIB_user: Set enable-acl" cmd="crm_attribute -n enable-acl -v false" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 desc="$CIB_user: Set stonith-enabled" cmd="crm_attribute -n stonith-enabled -v false" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 desc="$CIB_user: Create a resource" cmd="cibadmin -C -o resources --xml-text ''" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 export CIB_user=niceguy desc="$CIB_user: Query configuration" cmd="cibadmin -Q" test_assert $CRM_EX_OK 0 desc="$CIB_user: Set enable-acl" cmd="crm_attribute -n enable-acl -v false" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 desc="$CIB_user: Set stonith-enabled" cmd="crm_attribute -n stonith-enabled -v false" test_assert $CRM_EX_OK desc="$CIB_user: Create a resource" cmd="cibadmin -C -o resources --xml-text ''" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 export CIB_user=root desc="$CIB_user: Query configuration" cmd="cibadmin -Q" test_assert $CRM_EX_OK 0 desc="$CIB_user: Set stonith-enabled" cmd="crm_attribute -n stonith-enabled -v true" test_assert $CRM_EX_OK desc="$CIB_user: Create a resource" cmd="cibadmin -C -o resources --xml-text ''" test_assert $CRM_EX_OK export CIB_user=l33t-haxor desc="$CIB_user: Create a resource meta attribute" cmd="crm_resource -r dummy --meta -p target-role -v Stopped" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 desc="$CIB_user: Query a resource meta attribute" cmd="crm_resource -r dummy --meta -g target-role" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 desc="$CIB_user: Remove a resource meta attribute" cmd="crm_resource -r dummy --meta -d target-role" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 export CIB_user=niceguy desc="$CIB_user: Create a resource meta attribute" cmd="crm_resource -r dummy --meta -p target-role -v Stopped" test_assert $CRM_EX_OK desc="$CIB_user: Query a resource meta attribute" cmd="crm_resource -r dummy --meta -g target-role" test_assert $CRM_EX_OK desc="$CIB_user: Remove a resource meta attribute" cmd="crm_resource -r dummy --meta -d target-role" test_assert $CRM_EX_OK desc="$CIB_user: Create a resource meta attribute" cmd="crm_resource -r dummy --meta -p target-role -v Started" test_assert $CRM_EX_OK export CIB_user=badidea desc="$CIB_user: Query configuration - implied deny" cmd="cibadmin -Q" test_assert $CRM_EX_OK 0 export CIB_user=betteridea desc="$CIB_user: Query configuration - explicit deny" cmd="cibadmin -Q" test_assert $CRM_EX_OK 0 CIB_user=root cibadmin -Q > "$TMPXML" CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin --delete --xml-text '' CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin -Ql export CIB_user=niceguy desc="$CIB_user: Replace - remove acls" cmd="cibadmin --replace --xml-file $TMPXML" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 CIB_user=root cibadmin -Q > "$TMPXML" CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin -C -o resources --xml-text '' CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin -Ql desc="$CIB_user: Replace - create resource" cmd="cibadmin --replace --xml-file $TMPXML" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 CIB_user=root cibadmin -Q > "$TMPXML" CIB_user=root CIB_file="$TMPXML" CIB_shadow="" crm_attribute -n enable-acl -v false CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin -Ql desc="$CIB_user: Replace - modify attribute (deny)" cmd="cibadmin --replace --xml-file $TMPXML" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 CIB_user=root cibadmin -Q > "$TMPXML" CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin --replace --xml-text '' CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin -Ql desc="$CIB_user: Replace - delete attribute (deny)" cmd="cibadmin --replace --xml-file $TMPXML" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 CIB_user=root cibadmin -Q > "$TMPXML" CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin --modify --xml-text '' CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin -Ql desc="$CIB_user: Replace - create attribute (deny)" cmd="cibadmin --replace --xml-file $TMPXML" test_assert $CRM_EX_INSUFFICIENT_PRIV 0 CIB_user=bob CIB_user=root cibadmin -Q > "$TMPXML" CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin --modify --xml-text '' CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin -Ql desc="$CIB_user: Replace - create attribute (allow)" cmd="cibadmin --replace -o resources --xml-file $TMPXML" test_assert $CRM_EX_OK 0 CIB_user=root cibadmin -Q > "$TMPXML" CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin --modify --xml-text '' CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin -Ql desc="$CIB_user: Replace - modify attribute (allow)" cmd="cibadmin --replace -o resources --xml-file $TMPXML" test_assert $CRM_EX_OK 0 CIB_user=root cibadmin -Q > "$TMPXML" CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin --replace -o resources --xml-text '' CIB_user=root CIB_file="$TMPXML" CIB_shadow="" cibadmin -Ql desc="$CIB_user: Replace - delete attribute (allow)" cmd="cibadmin --replace -o resources --xml-file $TMPXML" test_assert $CRM_EX_OK 0 } function test_acls() { local SHADOWPATH local TMPXML=$(mktemp ${TMPDIR:-/tmp}/cts-cli.acls.xml.XXXXXXXXXX) export CIB_shadow_dir="${shadow_dir}" $VALGRIND_CMD crm_shadow --batch --force --create-empty $shadow --validate-with pacemaker-1.3 2>&1 export CIB_shadow=$shadow cat < "$TMPXML" EOF desc="Configure some ACLs" cmd="cibadmin -M -o acls --xml-file $TMPXML" test_assert $CRM_EX_OK desc="Enable ACLs" cmd="crm_attribute -n enable-acl -v true" test_assert $CRM_EX_OK desc="Set cluster option" cmd="crm_attribute -n no-quorum-policy -v ignore" test_assert $CRM_EX_OK desc="New ACL" cmd="cibadmin --create -o acls --xml-text ''" test_assert $CRM_EX_OK desc="Another ACL" cmd="cibadmin --create -o acls --xml-text ''" test_assert $CRM_EX_OK desc="Updated ACL" cmd="cibadmin --replace -o acls --xml-text ''" test_assert $CRM_EX_OK test_acl_loop "$TMPXML" printf "\n\n !#!#!#!#! Upgrading to latest CIB schema and re-testing !#!#!#!#!\n" printf "\nUpgrading to latest CIB schema and re-testing\n" 1>&2 export CIB_user=root desc="$CIB_user: Upgrade to latest CIB schema" cmd="cibadmin --upgrade --force -V" test_assert $CRM_EX_OK SHADOWPATH="$(crm_shadow --file)" # sed -i isn't portable :-( cp -p "$SHADOWPATH" "${SHADOWPATH}.$$" # to keep permissions sed -e 's/epoch=.2/epoch=\"6/g' -e 's/admin_epoch=.1/admin_epoch=\"0/g' \ "$SHADOWPATH" > "${SHADOWPATH}.$$" mv -- "${SHADOWPATH}.$$" "$SHADOWPATH" test_acl_loop "$TMPXML" unset CIB_shadow_dir rm -f "$TMPXML" } function test_validity() { local TMPGOOD=$(mktemp ${TMPDIR:-/tmp}/cts-cli.validity.good.xml.XXXXXXXXXX) local TMPBAD=$(mktemp ${TMPDIR:-/tmp}/cts-cli.validity.bad.xml.XXXXXXXXXX) export CIB_shadow_dir="${shadow_dir}" $VALGRIND_CMD crm_shadow --batch --force --create-empty $shadow --validate-with pacemaker-1.2 2>&1 export CIB_shadow=$shadow - export PCMK_trace_functions=update_validation,cli_config_update + export PCMK_trace_functions=apply_upgrade,update_validation,cli_config_update export PCMK_stderr=1 cibadmin -C -o resources --xml-text '' cibadmin -C -o resources --xml-text '' cibadmin -C -o constraints --xml-text '' cibadmin -Q > "$TMPGOOD" desc="Try to make resulting CIB invalid (enum violation)" cmd="cibadmin -M -o constraints --xml-text ''" test_assert $CRM_EX_CONFIG sed 's|"start"|"break"|' "$TMPGOOD" > "$TMPBAD" desc="Run crm_simulate with invalid CIB (enum violation)" cmd="crm_simulate -x $TMPBAD -S" test_assert $CRM_EX_CONFIG 0 desc="Try to make resulting CIB invalid (unrecognized validate-with)" cmd="cibadmin -M --xml-text ''" test_assert $CRM_EX_CONFIG sed 's|"pacemaker-1.2"|"pacemaker-9999.0"|' "$TMPGOOD" > "$TMPBAD" desc="Run crm_simulate with invalid CIB (unrecognized validate-with)" cmd="crm_simulate -x $TMPBAD -S" test_assert $CRM_EX_CONFIG 0 desc="Try to make resulting CIB invalid, but possibly recoverable (valid with X.Y+1)" cmd="cibadmin -C -o configuration --xml-text ''" test_assert $CRM_EX_CONFIG sed 's|||' "$TMPGOOD" > "$TMPBAD" desc="Run crm_simulate with invalid, but possibly recoverable CIB (valid with X.Y+1)" cmd="crm_simulate -x $TMPBAD -S" test_assert $CRM_EX_OK 0 sed 's|[ ][ ]*validate-with="[^"]*"||' "$TMPGOOD" > "$TMPBAD" desc="Make resulting CIB valid, although without validate-with attribute" cmd="cibadmin -R --xml-file $TMPBAD" test_assert $CRM_EX_OK desc="Run crm_simulate with valid CIB, but without validate-with attribute" cmd="crm_simulate -x $TMPBAD -S" test_assert $CRM_EX_OK 0 # this will just disable validation and accept the config, outputting # validation errors sed -e 's|[ ][ ]*validate-with="[^"]*"||' \ -e 's|\([ ][ ]*epoch="[^"]*\)"|\10"|' -e 's|"start"|"break"|' \ "$TMPGOOD" > "$TMPBAD" desc="Make resulting CIB invalid, and without validate-with attribute" cmd="cibadmin -R --xml-file $TMPBAD" test_assert $CRM_EX_OK desc="Run crm_simulate with invalid CIB, also without validate-with attribute" cmd="crm_simulate -x $TMPBAD -S" test_assert $CRM_EX_OK 0 unset CIB_shadow_dir rm -f "$TMPGOOD" "$TMPBAD" } +test_upgrade() { + local TMPXML=$(mktemp ${TMPDIR:-/tmp}/cts-cli.tools.xml.XXXXXXXXXX) + export CIB_shadow_dir="${shadow_dir}" + + $VALGRIND_CMD crm_shadow --batch --force --create-empty $shadow --validate-with pacemaker-2.10 2>&1 + export CIB_shadow=$shadow + + desc="Set stonith-enabled=false" + cmd="crm_attribute -n stonith-enabled -v false" + test_assert $CRM_EX_OK + + cat < "$TMPXML" + + + + + + + + + + + + + + + + + + + + + + +EOF + + desc="Configure the initial resource" + cmd="cibadmin -M -o resources --xml-file $TMPXML" + test_assert $CRM_EX_OK + + desc="Upgrade to latest CIB schema (trigger 2.10.xsl + the wrapping)" + cmd="cibadmin --upgrade --force -V -V" + test_assert $CRM_EX_OK + + desc="Query a resource instance attribute (shall survive)" + cmd="crm_resource -r mySmartFuse -g requires" + test_assert $CRM_EX_OK + + unset CIB_shadow_dir + rm -f "$TMPXML" +} + # Process command-line arguments while [ $# -gt 0 ]; do case "$1" in -t) tests="$2" shift 2 ;; -V|--verbose) verbose=1 shift ;; -v|--valgrind) export G_SLICE=always-malloc VALGRIND_CMD="valgrind $VALGRIND_OPTS" shift ;; -s) do_save=1 shift ;; -p) export PATH="$2:$PATH" shift ;; --help) echo "$USAGE_TEXT" exit $CRM_EX_OK ;; *) echo "error: unknown option $1" echo echo "$USAGE_TEXT" exit $CRM_EX_USAGE ;; esac done for t in $tests; do case "$t" in dates) ;; tools) ;; acls) ;; validity) ;; + upgrade) ;; *) echo "error: unknown test $t" echo echo "$USAGE_TEXT" exit $CRM_EX_USAGE ;; esac done # Check whether we're running from source directory SRCDIR=$(dirname $test_home) if [ -x "$SRCDIR/tools/crm_simulate" ]; then export PATH="$SRCDIR/tools:$PATH" echo "Using local binaries from: $SRCDIR/tools" if [ -x "$SRCDIR/xml" ]; then export PCMK_schema_directory="$SRCDIR/xml" echo "Using local schemas from: $PCMK_schema_directory" fi fi for t in $tests; do echo "Testing $t" TMPFILE=$(mktemp ${TMPDIR:-/tmp}/cts-cli.$t.XXXXXXXXXX) eval TMPFILE_$t="$TMPFILE" test_$t > "$TMPFILE" sed -e 's/cib-last-written.*>/>/'\ -e 's/ last-run=\"[0-9]*\"//'\ -e 's/crm_feature_set="[^"]*" //'\ -e 's/validate-with="[^"]*" //'\ -e 's/Created new pacemaker-.* configuration/Created new pacemaker configuration/'\ -e 's/.*\(__xml_.*\)@.*\.c:[0-9][0-9]*)/\1/g' \ -e 's/.*\(unpack_.*\)@.*\.c:[0-9][0-9]*)/\1/g' \ -e 's/.*\(update_validation\)@.*\.c:[0-9][0-9]*)/\1/g' \ -e 's/ last-rc-change=\"[0-9]*\"//'\ -e 's|^/tmp/cts-cli\.validity\.bad.xml\.[^:]*:|validity.bad.xml:|'\ -e 's/^Entity: line [0-9][0-9]*: //'\ -e 's/\(validation ([0-9][0-9]* of \)[0-9][0-9]*\().*\)/\1X\2/' \ "$TMPFILE" > "${TMPFILE}.$$" mv -- "${TMPFILE}.$$" "$TMPFILE" if [ $do_save -eq 1 ]; then cp "$TMPFILE" $test_home/cli/regression.$t.exp fi done rm -rf "${shadow_dir}" failed=0 if [ $verbose -eq 1 ]; then echo -e "\n\nResults" fi for t in $tests; do eval TMPFILE="\$TMPFILE_$t" if [ $verbose -eq 1 ]; then diff -wu $test_home/cli/regression.$t.exp "$TMPFILE" else diff -w $test_home/cli/regression.$t.exp "$TMPFILE" >/dev/null 2>&1 fi if [ $? -ne 0 ]; then failed=1 fi done echo -e "\n\nSummary" for t in $tests; do eval TMPFILE="\$TMPFILE_$t" grep -e "^*" "$TMPFILE" done if [ $num_errors -ne 0 ]; then echo "$num_errors tests failed; see output in:" for t in $tests; do eval TMPFILE="\$TMPFILE_$t" echo " $TMPFILE" done exit $CRM_EX_ERROR elif [ $failed -eq 1 ]; then echo "$num_passed tests passed but output was unexpected; see output in:" for t in $tests; do eval TMPFILE="\$TMPFILE_$t" echo " $TMPFILE" done exit $CRM_EX_DIGEST else echo $num_passed tests passed for t in $tests; do eval TMPFILE="\$TMPFILE_$t" rm -f "$TMPFILE" done crm_shadow --force --delete $shadow >/dev/null 2>&1 exit $CRM_EX_OK fi diff --git a/include/crm/common/xml.h b/include/crm/common/xml.h index 2697cece8c..fe2e1d51e5 100644 --- a/include/crm/common/xml.h +++ b/include/crm/common/xml.h @@ -1,395 +1,395 @@ /* * Copyright (C) 2004 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 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 Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CRM_COMMON_XML__H # define CRM_COMMON_XML__H #ifdef __cplusplus extern "C" { #endif /** * \file * \brief Wrappers for and extensions to libxml2 * \ingroup core */ # include # include # include # include # include # include # include # include # include /* Define compression parameters for IPC messages * * Compression costs a LOT, so we don't want to do it unless we're hitting * message limits. Currently, we use 128KB as the threshold, because higher * values don't play well with the heartbeat stack. With an earlier limit of * 10KB, compressing 184 of 1071 messages accounted for 23% of the total CPU * used by the cib. */ # define CRM_BZ2_BLOCKS 4 # define CRM_BZ2_WORK 20 # define CRM_BZ2_THRESHOLD 128 * 1024 # define XML_PARANOIA_CHECKS 0 gboolean add_message_xml(xmlNode * msg, const char *field, xmlNode * xml); xmlNode *get_message_xml(xmlNode * msg, const char *field); GHashTable *xml2list(xmlNode * parent); xmlNode *crm_create_nvpair_xml(xmlNode *parent, const char *id, const char *name, const char *value); void hash2nvpair(gpointer key, gpointer value, gpointer user_data); void hash2field(gpointer key, gpointer value, gpointer user_data); void hash2metafield(gpointer key, gpointer value, gpointer user_data); void hash2smartfield(gpointer key, gpointer value, gpointer user_data); xmlDoc *getDocPtr(xmlNode * node); /* * Replacement function for xmlCopyPropList which at the very least, * doesn't work the way *I* would expect it to. * * Copy all the attributes/properties from src into target. * * Not recursive, does not return anything. * */ void copy_in_properties(xmlNode * target, xmlNode * src); void expand_plus_plus(xmlNode * target, const char *name, const char *value); void fix_plus_plus_recursive(xmlNode * target); /* * Create a node named "name" as a child of "parent" * If parent is NULL, creates an unconnected node. * * Returns the created node * */ xmlNode *create_xml_node(xmlNode * parent, const char *name); /* * Make a copy of name and value and use the copied memory to create * an attribute for node. * * If node, name or value are NULL, nothing is done. * * If name or value are an empty string, nothing is done. * * Returns FALSE on failure and TRUE on success. * */ const char *crm_xml_add(xmlNode * node, const char *name, const char *value); const char *crm_xml_replace(xmlNode * node, const char *name, const char *value); const char *crm_xml_add_int(xmlNode * node, const char *name, int value); const char *crm_xml_add_ms(xmlNode *node, const char *name, guint ms); /*! * \brief Add a boolean attribute to an XML object * * Add an attribute with the value XML_BOOLEAN_TRUE or XML_BOOLEAN_FALSE * as appropriate to an XML object. * * \param[in,out] node XML object to add attribute to * \param[in] name Name of attribute to add * \param[in] value Boolean whose value will be tested * * \return Pointer to newly created XML attribute's content, or NULL on error */ static inline const char * crm_xml_add_boolean(xmlNode *node, const char *name, gboolean value) { return crm_xml_add(node, name, (value? "true" : "false")); } /* * */ void purge_diff_markers(xmlNode * a_node); /* * Returns a deep copy of src_node * */ xmlNode *copy_xml(xmlNode * src_node); /* * Add a copy of xml_node to new_parent */ xmlNode *add_node_copy(xmlNode * new_parent, xmlNode * xml_node); int add_node_nocopy(xmlNode * parent, const char *name, xmlNode * child); /* * XML I/O Functions * * Whitespace between tags is discarded. */ xmlNode *filename2xml(const char *filename); xmlNode *stdin2xml(void); xmlNode *string2xml(const char *input); int write_xml_fd(xmlNode * xml_node, const char *filename, int fd, gboolean compress); int write_xml_file(xmlNode * xml_node, const char *filename, gboolean compress); char *dump_xml_formatted(xmlNode * msg); /* Also dump the text node with xml_log_option_text enabled */ char *dump_xml_formatted_with_text(xmlNode * msg); char *dump_xml_unformatted(xmlNode * msg); /* * Diff related Functions */ xmlNode *diff_xml_object(xmlNode * left, xmlNode * right, gboolean suppress); xmlNode *subtract_xml_object(xmlNode * parent, xmlNode * left, xmlNode * right, gboolean full, gboolean * changed, const char *marker); gboolean can_prune_leaf(xmlNode * xml_node); gboolean apply_xml_diff(xmlNode *old_xml, xmlNode *diff, xmlNode **new_xml); /* * Searching & Modifying */ xmlNode *find_xml_node(xmlNode * cib, const char *node_path, gboolean must_find); xmlNode *find_entity(xmlNode * parent, const char *node_name, const char *id); void xml_remove_prop(xmlNode * obj, const char *name); gboolean replace_xml_child(xmlNode * parent, xmlNode * child, xmlNode * update, gboolean delete_only); gboolean update_xml_child(xmlNode * child, xmlNode * to_update); int find_xml_children(xmlNode ** children, xmlNode * root, const char *tag, const char *field, const char *value, gboolean search_matches); int crm_element_value_int(const xmlNode *data, const char *name, int *dest); int crm_element_value_ms(const xmlNode *data, const char *name, guint *dest); char *crm_element_value_copy(const xmlNode *data, const char *name); xmlNode *get_xpath_object(const char *xpath, xmlNode * xml_obj, int error_level); xmlNode *get_xpath_object_relative(const char *xpath, xmlNode * xml_obj, int error_level); static inline const char * crm_element_name(const xmlNode *xml) { return xml? (const char *)(xml->name) : NULL; } const char *crm_element_value(const xmlNode *data, const char *name); /*! * \brief Copy an element from one XML object to another * * \param[in] obj1 Source XML * \param[in,out] obj2 Destination XML * \param[in] element Name of element to copy * * \return Pointer to copied value (from source) */ static inline const char * crm_copy_xml_element(xmlNode *obj1, xmlNode *obj2, const char *element) { const char *value = crm_element_value(obj1, element); crm_xml_add(obj2, element, value); return value; } gboolean xml_has_children(const xmlNode * root); char *calculate_on_disk_digest(xmlNode * local_cib); char *calculate_operation_digest(xmlNode * local_cib, const char *version); char *calculate_xml_versioned_digest(xmlNode * input, gboolean sort, gboolean do_filter, const char *version); /* schema-related functions (from schemas.c) */ gboolean validate_xml(xmlNode * xml_blob, const char *validation, gboolean to_logs); gboolean validate_xml_verbose(xmlNode * xml_blob); /*! * \brief Update CIB XML to most recent schema version * * "Update" means either actively employ XSLT-based transformation(s) * (if intermediate product to transform valid per its declared schema version, * transformation available, proceeded successfully with a result valid per * expectated newer schema version), or just try to bump the marked validating * schema until all gradually rising schema versions attested or the first * such attempt subsequently fails to validate. Which of the two styles will * be used depends on \p transform parameter (positive/negative, respectively). * * \param[in,out] xml_blob XML tree representing CIB, may be swapped with * an "updated" one * \param[out] best The highest configuration version (per its index * in the global schemas table) it was possible to * reach during the update steps while ensuring * the validity of the result; if no validation * success was observed against possibly multiple * schemas, the value is less or equal the result - * of get_schema_version applied on the - * input \p xml_blob value (unless that function - * maps it to -1, then 0 would be used instead) + * of \c get_schema_version applied on the input + * \p xml_blob value (unless that function maps it + * to -1, then 0 would be used instead) * \param[in] max When \p transform is positive, this allows to * set upper boundary schema (per its index in the - * global schemas table) beyond which its forbidden + * global schemas table) beyond which it's forbidden * to update by the means of XSLT transformation * \param[in] transform Whether to employ XSLT-based transformation so - * as allow overcoming possible incompatibilities + * as to allow overcoming possible incompatibilities * between major schema versions (see above) * \param[in] to_logs If true, output notable progress info to * internal log streams; if false, to stderr * - * \return pcmk_ok if no non-recoverable error encountered (up to + * \return \c pcmk_ok if no non-recoverable error encountered (up to * caller to evaluate if the update satisfies the requirements * per returned \p best value), negative value carrying the reason * otherwise */ int update_validation(xmlNode **xml_blob, int *best, int max, gboolean transform, gboolean to_logs); int get_schema_version(const char *name); const char *get_schema_name(int version); const char *xml_latest_schema(void); gboolean cli_config_update(xmlNode ** xml, int *best_version, gboolean to_logs); void crm_xml_init(void); void crm_xml_cleanup(void); static inline xmlNode * __xml_first_child(const xmlNode *parent) { xmlNode *child = parent? parent->children : NULL; while (child && (child->type == XML_TEXT_NODE)) { child = child->next; } return child; } static inline xmlNode * __xml_next(const xmlNode *child) { xmlNode *next = child? child->next : NULL; while (next && (next->type == XML_TEXT_NODE)) { next = next->next; } return next; } static inline xmlNode * __xml_first_child_element(const xmlNode *parent) { xmlNode *child = parent? parent->children : NULL; while (child && (child->type != XML_ELEMENT_NODE)) { child = child->next; } return child; } static inline xmlNode * __xml_next_element(const xmlNode *child) { xmlNode *next = child? child->next : NULL; while (next && (next->type != XML_ELEMENT_NODE)) { next = next->next; } return next; } void free_xml(xmlNode * child); xmlNode *first_named_child(const xmlNode *parent, const char *name); xmlNode *crm_next_same_xml(const xmlNode *sibling); xmlNode *sorted_xml(xmlNode * input, xmlNode * parent, gboolean recursive); xmlXPathObjectPtr xpath_search(xmlNode * xml_top, const char *path); void crm_foreach_xpath_result(xmlNode *xml, const char *xpath, void (*helper)(xmlNode*, void*), void *user_data); xmlNode *expand_idref(xmlNode * input, xmlNode * top); void freeXpathObject(xmlXPathObjectPtr xpathObj); xmlNode *getXpathResult(xmlXPathObjectPtr xpathObj, int index); void dedupXpathResults(xmlXPathObjectPtr xpathObj); static inline int numXpathResults(xmlXPathObjectPtr xpathObj) { if(xpathObj == NULL || xpathObj->nodesetval == NULL) { return 0; } return xpathObj->nodesetval->nodeNr; } bool xml_acl_enabled(xmlNode *xml); void xml_acl_disable(xmlNode *xml); bool xml_acl_denied(xmlNode *xml); /* Part or all of a change was rejected */ bool xml_acl_filtered_copy(const char *user, xmlNode* acl_source, xmlNode *xml, xmlNode ** result); bool xml_tracking_changes(xmlNode * xml); bool xml_document_dirty(xmlNode *xml); void xml_track_changes(xmlNode * xml, const char *user, xmlNode *acl_source, bool enforce_acls); void xml_calculate_changes(xmlNode *old_xml, xmlNode *new_xml); void xml_calculate_significant_changes(xmlNode *old_xml, xmlNode *new_xml); void xml_accept_changes(xmlNode * xml); void xml_log_changes(uint8_t level, const char *function, xmlNode *xml); void xml_log_patchset(uint8_t level, const char *function, xmlNode *xml); bool xml_patch_versions(xmlNode *patchset, int add[3], int del[3]); xmlNode *xml_create_patchset( int format, xmlNode *source, xmlNode *target, bool *config, bool manage_version); int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version); void patchset_process_digest(xmlNode *patch, xmlNode *source, xmlNode *target, bool with_digest); void save_xml_to_file(xmlNode * xml, const char *desc, const char *filename); char *xml_get_path(xmlNode *xml); char * crm_xml_escape(const char *text); void crm_xml_sanitize_id(char *id); void crm_xml_set_id(xmlNode *xml, const char *format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); /*! * \brief xmlNode destructor which can be used in glib collections */ void crm_destroy_xml(gpointer data); #ifdef __cplusplus } #endif #endif diff --git a/lib/common/schemas.c b/lib/common/schemas.c index fc895daa2a..26f7aa5316 100644 --- a/lib/common/schemas.c +++ b/lib/common/schemas.c @@ -1,963 +1,1257 @@ /* * Copyright 2004-2018 Andrew Beekhof * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include #include #include #include #include #include #include #include #if HAVE_LIBXSLT # include # include # include #endif #include #include #include /* CRM_XML_LOG_BASE */ typedef struct { unsigned char v[2]; } schema_version_t; #define SCHEMA_ZERO { .v = { 0, 0 } } #define schema_scanf(s, prefix, version, suffix) \ sscanf((s), prefix "%hhu.%hhu" suffix, &((version).v[0]), &((version).v[1])) #define schema_strdup_printf(prefix, version, suffix) \ crm_strdup_printf(prefix "%u.%u" suffix, (version).v[0], (version).v[1]) typedef struct { xmlRelaxNGPtr rng; xmlRelaxNGValidCtxtPtr valid; xmlRelaxNGParserCtxtPtr parser; } relaxng_ctx_cache_t; enum schema_validator_e { schema_validator_none, schema_validator_rng }; struct schema_s { char *name; char *location; char *transform; void *cache; enum schema_validator_e validator; int after_transform; schema_version_t version; + char *transform_enter; + bool transform_onleave; }; static struct schema_s *known_schemas = NULL; static int xml_schema_max = 0; +static bool silent_logging = FALSE; static void xml_log(int priority, const char *fmt, ...) G_GNUC_PRINTF(2, 3); static void xml_log(int priority, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - /* XXX should not this enable dechunking as well? */ - CRM_XML_LOG_BASE(priority, FALSE, 0, NULL, fmt, ap); + if (silent_logging == FALSE) { + /* XXX should not this enable dechunking as well? */ + CRM_XML_LOG_BASE(priority, FALSE, 0, NULL, fmt, ap); + } va_end(ap); } static int xml_latest_schema_index(void) { return xml_schema_max - 3; // index from 0, ignore "pacemaker-next"/"none" } static int xml_minimum_schema_index(void) { static int best = 0; if (best == 0) { int lpc = 0; best = xml_latest_schema_index(); for (lpc = best; lpc > 0; lpc--) { if (known_schemas[lpc].version.v[0] < known_schemas[best].version.v[0]) { return best; } else { best = lpc; } } best = xml_latest_schema_index(); } return best; } const char * xml_latest_schema(void) { return get_schema_name(xml_latest_schema_index()); } static const char * get_schema_root(void) { static const char *base = NULL; if (base == NULL) { base = getenv("PCMK_schema_directory"); } if (base == NULL || strlen(base) == 0) { base = CRM_SCHEMA_DIRECTORY; } return base; } static char * get_schema_path(const char *name, const char *file) { const char *base = get_schema_root(); if (file) { return crm_strdup_printf("%s/%s", base, file); } return crm_strdup_printf("%s/%s.rng", base, name); } static inline bool version_from_filename(const char *filename, schema_version_t *version) { int rc = schema_scanf(filename, "pacemaker-", *version, ".rng"); return (rc == 2); } static int schema_filter(const struct dirent *a) { int rc = 0; schema_version_t version = SCHEMA_ZERO; if (strstr(a->d_name, "pacemaker-") != a->d_name) { /* crm_trace("%s - wrong prefix", a->d_name); */ } else if (!crm_ends_with_ext(a->d_name, ".rng")) { /* crm_trace("%s - wrong suffix", a->d_name); */ } else if (!version_from_filename(a->d_name, &version)) { /* crm_trace("%s - wrong format", a->d_name); */ } else { /* crm_debug("%s - candidate", a->d_name); */ rc = 1; } return rc; } static int schema_sort(const struct dirent **a, const struct dirent **b) { schema_version_t a_version = SCHEMA_ZERO; schema_version_t b_version = SCHEMA_ZERO; if (!version_from_filename(a[0]->d_name, &a_version) || !version_from_filename(b[0]->d_name, &b_version)) { // Shouldn't be possible, but makes static analysis happy return 0; } for (int i = 0; i < 2; ++i) { if (a_version.v[i] < b_version.v[i]) { return -1; } else if (a_version.v[i] > b_version.v[i]) { return 1; } } return 0; } +/*! + * \internal + * \brief Add given schema + auxiliary data to internal bookkeeping. + * + * \note When providing \p version, should not be called directly but + * through \c add_schema_by_version. + */ static void add_schema(enum schema_validator_e validator, const schema_version_t *version, const char *name, const char *location, const char *transform, + const char *transform_enter, bool transform_onleave, int after_transform) { int last = xml_schema_max; bool have_version = FALSE; xml_schema_max++; known_schemas = realloc_safe(known_schemas, xml_schema_max * sizeof(struct schema_s)); CRM_ASSERT(known_schemas != NULL); memset(known_schemas+last, 0, sizeof(struct schema_s)); known_schemas[last].validator = validator; known_schemas[last].after_transform = after_transform; for (int i = 0; i < 2; ++i) { known_schemas[last].version.v[i] = version->v[i]; if (version->v[i]) { have_version = TRUE; } } if (have_version) { known_schemas[last].name = schema_strdup_printf("pacemaker-", *version, ""); known_schemas[last].location = crm_strdup_printf("%s.rng", known_schemas[last].name); } else { CRM_ASSERT(name); CRM_ASSERT(location); schema_scanf(name, "%*[^-]-", known_schemas[last].version, ""); known_schemas[last].name = strdup(name); known_schemas[last].location = strdup(location); } if (transform) { known_schemas[last].transform = strdup(transform); } + if (transform_enter) { + known_schemas[last].transform_enter = strdup(transform_enter); + } + known_schemas[last].transform_onleave = transform_onleave; if (after_transform == 0) { after_transform = xml_schema_max; /* upgrade is a one-way */ } known_schemas[last].after_transform = after_transform; if (known_schemas[last].after_transform < 0) { crm_debug("Added supported schema %d: %s (%s)", last, known_schemas[last].name, known_schemas[last].location); } else if (known_schemas[last].transform) { crm_debug("Added supported schema %d: %s (%s upgrades to %d with %s)", last, known_schemas[last].name, known_schemas[last].location, known_schemas[last].after_transform, known_schemas[last].transform); } else { crm_debug("Added supported schema %d: %s (%s upgrades to %d)", last, known_schemas[last].name, known_schemas[last].location, known_schemas[last].after_transform); } } +/*! + * \internal + * \brief Add version-specified schema + auxiliary data to internal bookkeeping. + * \return \c -ENOENT when no upgrade schema associated, \c pcmk_ok otherwise. + * + * \note There's no reliance on the particular order of schemas entering here. + * + * \par A bit of theory + * We track 3 XSLT stylesheets that differ per usage: + * - "upgrade": + * . sparsely spread over the sequence of all available schemas, + * as they are only relevant when major version of the schema + * is getting bumped -- in that case, it MUST be set + * . name convention: upgrade-X.Y.xsl + * - "upgrade-enter": + * . may only accompany "upgrade" occurrence, but doesn't need to + * be present anytime such one is, i.e., it MAY not be set when + * "upgrade" is + * . name convention: upgrade-X.Y-enter.xsl, + * when not present: upgrade-enter.xsl + * - "upgrade-leave": + * . like "upgrade-enter", but SHOULD be present whenever + * "upgrade-enter" is + * . name convention: (see "upgrade-enter") + */ +static int +add_schema_by_version(const schema_version_t *version, int next, + bool transform_expected) +{ + bool transform_onleave = FALSE; + int rc = pcmk_ok; + struct stat s; + char *xslt = NULL, + *transform_upgrade = NULL, + *transform_enter = NULL; + + /* prologue for further transform_expected handling */ + if (transform_expected) { + /* check if there's suitable "upgrade" stylesheet */ + transform_upgrade = schema_strdup_printf("upgrade-", *version, ".xsl"); + xslt = get_schema_path(NULL, transform_upgrade); + } + + if (!transform_expected) { + /* jump directly to the end */ + + } else if (stat(xslt, &s) == 0) { + /* perhaps there's also a targeted "upgrade-enter" stylesheet */ + transform_enter = schema_strdup_printf("upgrade-", *version, "-enter.xsl"); + free(xslt); + xslt = get_schema_path(NULL, transform_enter); + if (stat(xslt, &s) != 0) { + /* or initially, at least a generic one */ + crm_debug("Upgrade-enter transform %s not found", xslt); + free(xslt); + xslt = get_schema_path(NULL, "upgrade-enter.xsl"); + if (stat(xslt, &s) != 0) { + crm_debug("Upgrade-enter transform %s not found, either", xslt); + free(xslt); + xslt = NULL; + } + } + /* xslt contains full path to "upgrade-enter" stylesheet */ + if (xslt != NULL) { + /* then there should be "upgrade-leave" counterpart */ + memcpy(strrchr(xslt, '-') + 1, "leave", 5); /* enter -> leave */ + transform_onleave = (stat(xslt, &s) == 0); + free(xslt); + } else { + free(transform_enter); + transform_enter = NULL; + } + + } else { + crm_err("Upgrade transform %s not found", xslt); + free(xslt); + free(transform_upgrade); + transform_upgrade = NULL; + next = -1; + rc = -ENOENT; + } + + add_schema(schema_validator_rng, version, NULL, NULL, + transform_upgrade, transform_enter, transform_onleave, next); + + free(transform_upgrade); + free(transform_enter); + + return rc; +} + /*! * \internal * \brief Load pacemaker schemas into cache */ void crm_schema_init(void) { int lpc, max; const char *base = get_schema_root(); struct dirent **namelist = NULL; const schema_version_t zero = SCHEMA_ZERO; max = scandir(base, &namelist, schema_filter, schema_sort); if (max < 0) { crm_notice("scandir(%s) failed: %s (%d)", base, strerror(errno), errno); } else { for (lpc = 0; lpc < max; lpc++) { + bool transform_expected = FALSE; int next = 0; schema_version_t version = SCHEMA_ZERO; - char *transform = NULL; if (!version_from_filename(namelist[lpc]->d_name, &version)) { // Shouldn't be possible, but makes static analysis happy crm_err("Skipping schema '%s': could not parse version", namelist[lpc]->d_name); continue; } if ((lpc + 1) < max) { schema_version_t next_version = SCHEMA_ZERO; if (version_from_filename(namelist[lpc+1]->d_name, &next_version) - && (version.v[0] < next_version.v[0])) { - - struct stat s; - char *xslt = NULL; - - transform = schema_strdup_printf("upgrade-", version, ".xsl"); - xslt = get_schema_path(NULL, transform); - if (stat(xslt, &s) != 0) { - crm_err("Transform %s not found", xslt); - free(xslt); - add_schema(schema_validator_rng, &version, NULL, NULL, - NULL, -1); - break; - } else { - free(xslt); - } + && (version.v[0] < next_version.v[0])) { + transform_expected = TRUE; } } else { next = -1; } - add_schema(schema_validator_rng, &version, NULL, NULL, transform, - next); - free(transform); + if (add_schema_by_version(&version, next, transform_expected) + == -ENOENT) { + break; + } } for (lpc = 0; lpc < max; lpc++) { free(namelist[lpc]); } free(namelist); } add_schema(schema_validator_rng, &zero, "pacemaker-next", - "pacemaker-next.rng", NULL, -1); + "pacemaker-next.rng", NULL, NULL, FALSE, -1); add_schema(schema_validator_none, &zero, "none", - "N/A", NULL, -1); + "N/A", NULL, NULL, FALSE, -1); } #if 0 static void relaxng_invalid_stderr(void *userData, xmlErrorPtr error) { /* Structure xmlError struct _xmlError { int domain : What part of the library raised this er int code : The error code, e.g. an xmlParserError char * message : human-readable informative error messag xmlErrorLevel level : how consequent is the error char * file : the filename int line : the line number if available char * str1 : extra string information char * str2 : extra string information char * str3 : extra string information int int1 : extra number information int int2 : column number of the error or 0 if N/A void * ctxt : the parser context if available void * node : the node in the tree } */ crm_err("Structured error: line=%d, level=%d %s", error->line, error->level, error->message); } #endif static gboolean validate_with_relaxng(xmlDocPtr doc, gboolean to_logs, const char *relaxng_file, relaxng_ctx_cache_t **cached_ctx) { int rc = 0; gboolean valid = TRUE; relaxng_ctx_cache_t *ctx = NULL; CRM_CHECK(doc != NULL, return FALSE); CRM_CHECK(relaxng_file != NULL, return FALSE); if (cached_ctx && *cached_ctx) { ctx = *cached_ctx; } else { crm_info("Creating RNG parser context"); ctx = calloc(1, sizeof(relaxng_ctx_cache_t)); xmlLoadExtDtdDefaultValue = 1; ctx->parser = xmlRelaxNGNewParserCtxt(relaxng_file); CRM_CHECK(ctx->parser != NULL, goto cleanup); if (to_logs) { xmlRelaxNGSetParserErrors(ctx->parser, (xmlRelaxNGValidityErrorFunc) xml_log, (xmlRelaxNGValidityWarningFunc) xml_log, GUINT_TO_POINTER(LOG_ERR)); } else { xmlRelaxNGSetParserErrors(ctx->parser, (xmlRelaxNGValidityErrorFunc) fprintf, (xmlRelaxNGValidityWarningFunc) fprintf, stderr); } ctx->rng = xmlRelaxNGParse(ctx->parser); CRM_CHECK(ctx->rng != NULL, crm_err("Could not find/parse %s", relaxng_file); goto cleanup); ctx->valid = xmlRelaxNGNewValidCtxt(ctx->rng); CRM_CHECK(ctx->valid != NULL, goto cleanup); if (to_logs) { xmlRelaxNGSetValidErrors(ctx->valid, (xmlRelaxNGValidityErrorFunc) xml_log, (xmlRelaxNGValidityWarningFunc) xml_log, GUINT_TO_POINTER(LOG_ERR)); } else { xmlRelaxNGSetValidErrors(ctx->valid, (xmlRelaxNGValidityErrorFunc) fprintf, (xmlRelaxNGValidityWarningFunc) fprintf, stderr); } } /* xmlRelaxNGSetValidStructuredErrors( */ /* valid, relaxng_invalid_stderr, valid); */ xmlLineNumbersDefault(1); rc = xmlRelaxNGValidateDoc(ctx->valid, doc); if (rc > 0) { valid = FALSE; } else if (rc < 0) { crm_err("Internal libxml error during validation"); } cleanup: if (cached_ctx) { *cached_ctx = ctx; } else { if (ctx->parser != NULL) { xmlRelaxNGFreeParserCtxt(ctx->parser); } if (ctx->valid != NULL) { xmlRelaxNGFreeValidCtxt(ctx->valid); } if (ctx->rng != NULL) { xmlRelaxNGFree(ctx->rng); } free(ctx); } return valid; } /*! * \internal * \brief Clean up global memory associated with XML schemas */ void crm_schema_cleanup(void) { int lpc; relaxng_ctx_cache_t *ctx = NULL; for (lpc = 0; lpc < xml_schema_max; lpc++) { switch (known_schemas[lpc].validator) { case schema_validator_none: // not cached break; case schema_validator_rng: // cached ctx = (relaxng_ctx_cache_t *) known_schemas[lpc].cache; if (ctx == NULL) { break; } if (ctx->parser != NULL) { xmlRelaxNGFreeParserCtxt(ctx->parser); } if (ctx->valid != NULL) { xmlRelaxNGFreeValidCtxt(ctx->valid); } if (ctx->rng != NULL) { xmlRelaxNGFree(ctx->rng); } free(ctx); known_schemas[lpc].cache = NULL; break; } free(known_schemas[lpc].name); free(known_schemas[lpc].location); free(known_schemas[lpc].transform); + free(known_schemas[lpc].transform_enter); } free(known_schemas); known_schemas = NULL; xsltCleanupGlobals(); /* XXX proper, explicit reshaking regarding init/fini routines is pending (pair of facade functions to express the intentions in a clean way) */ } static gboolean validate_with(xmlNode *xml, int method, gboolean to_logs) { xmlDocPtr doc = NULL; gboolean valid = FALSE; char *file = NULL; if (method < 0) { return FALSE; } if (known_schemas[method].validator == schema_validator_none) { return TRUE; } CRM_CHECK(xml != NULL, return FALSE); doc = getDocPtr(xml); file = get_schema_path(known_schemas[method].name, known_schemas[method].location); crm_trace("Validating with: %s (type=%d)", crm_str(file), known_schemas[method].validator); switch (known_schemas[method].validator) { case schema_validator_rng: valid = validate_with_relaxng(doc, to_logs, file, (relaxng_ctx_cache_t **) & (known_schemas[method].cache)); break; default: crm_err("Unknown validator type: %d", known_schemas[method].validator); break; } free(file); return valid; } +static bool +validate_with_silent(xmlNode *xml, int method) +{ + bool rc, sl_backup = silent_logging; + silent_logging = TRUE; + rc = validate_with(xml, method, TRUE); + silent_logging = sl_backup; + return rc; +} + static void dump_file(const char *filename) { FILE *fp = NULL; int ch, line = 0; CRM_CHECK(filename != NULL, return); fp = fopen(filename, "r"); if (fp == NULL) { crm_perror(LOG_ERR, "Could not open %s for reading", filename); return; } fprintf(stderr, "%4d ", ++line); do { ch = getc(fp); if (ch == EOF) { putc('\n', stderr); break; } else if (ch == '\n') { fprintf(stderr, "\n%4d ", ++line); } else { putc(ch, stderr); } } while (1); fclose(fp); } gboolean validate_xml_verbose(xmlNode *xml_blob) { int fd = 0; xmlDoc *doc = NULL; xmlNode *xml = NULL; gboolean rc = FALSE; char *filename = NULL; filename = crm_strdup_printf("%s/cib-invalid.XXXXXX", crm_get_tmpdir()); umask(S_IWGRP | S_IWOTH | S_IROTH); fd = mkstemp(filename); write_xml_fd(xml_blob, filename, fd, FALSE); dump_file(filename); doc = xmlParseFile(filename); xml = xmlDocGetRootElement(doc); rc = validate_xml(xml, NULL, FALSE); free_xml(xml); unlink(filename); free(filename); return rc; } gboolean validate_xml(xmlNode *xml_blob, const char *validation, gboolean to_logs) { int version = 0; if (validation == NULL) { validation = crm_element_value(xml_blob, XML_ATTR_VALIDATION); } if (validation == NULL) { int lpc = 0; bool valid = FALSE; for (lpc = 0; lpc < xml_schema_max; lpc++) { if (validate_with(xml_blob, lpc, FALSE)) { valid = TRUE; crm_xml_add(xml_blob, XML_ATTR_VALIDATION, known_schemas[lpc].name); crm_info("XML validated against %s", known_schemas[lpc].name); if(known_schemas[lpc].after_transform == 0) { break; } } } return valid; } version = get_schema_version(validation); if (strcmp(validation, "none") == 0) { return TRUE; } else if (version < xml_schema_max) { return validate_with(xml_blob, version, to_logs); } crm_err("Unknown validator: %s", validation); return FALSE; } #if HAVE_LIBXSLT static void cib_upgrade_err(void *ctx, const char *fmt, ...) G_GNUC_PRINTF(2, 3); +/* With this arrangement, an attempt to identify the message severity + as explicitly signalled directly from XSLT is performed in rather + a smart way (no reliance on formatting string + arguments being + always specified as ["%s", purposeful_string], as it can also be + ["%s: %s", some_prefix, purposeful_string] etc. so every argument + pertaining %s specifier is investigated), and if such a mark found, + the respective level is determined and, when the messages are to go + to the native logs, the mark itself gets dropped + (by the means of string shift). + + NOTE: whether the native logging is the right sink is decided per + the ctx parameter -- NULL denotes this case, otherwise it + carries a pointer to the numeric expression of the desired + target logging level (messages with higher level will be + suppressed) + + NOTE: on some architectures, this string shift may not have any + effect, but that's an acceptable tradeoff + + The logging level for not explicitly designated messages + (suspicious, likely internal errors or some runaways) is + LOG_WARNING. + */ static void cib_upgrade_err(void *ctx, const char *fmt, ...) { - va_list ap; + va_list ap, aq; + char *arg_cur; + + bool found = FALSE; + const char *fmt_iter = fmt; + uint8_t msg_log_level = LOG_WARNING; /* default for runaway messages */ + const unsigned * log_level = (const unsigned *) ctx; + enum { + escan_seennothing, + escan_seenpercent, + } scan_state = escan_seennothing; va_start(ap, fmt); - CRM_XML_LOG_BASE(LOG_WARNING, TRUE, 0, "CIB upgrade: ", fmt, ap); + va_copy(aq, ap); + + while (!found && *fmt_iter != '\0') { + /* while casing schema borrowed from libqb:qb_vsnprintf_serialize */ + switch (*fmt_iter++) { + case '%': + if (scan_state == escan_seennothing) { + scan_state = escan_seenpercent; + } else if (scan_state == escan_seenpercent) { + scan_state = escan_seennothing; + } + break; + case 's': + if (scan_state == escan_seenpercent) { + scan_state = escan_seennothing; + arg_cur = va_arg(aq, char *); + if (arg_cur != NULL) { + switch (arg_cur[0]) { + case 'W': + if (!strncmp(arg_cur, "WARNING: ", + sizeof("WARNING: ") - 1)) { + msg_log_level = LOG_WARNING; + } + if (ctx == NULL) { + memmove(arg_cur, arg_cur + sizeof("WARNING: ") - 1, + strlen(arg_cur + sizeof("WARNING: ") - 1) + 1); + } + found = TRUE; + break; + case 'I': + if (!strncmp(arg_cur, "INFO: ", + sizeof("INFO: ") - 1)) { + msg_log_level = LOG_INFO; + } + if (ctx == NULL) { + memmove(arg_cur, arg_cur + sizeof("INFO: ") - 1, + strlen(arg_cur + sizeof("INFO: ") - 1) + 1); + } + found = TRUE; + break; + case 'D': + if (!strncmp(arg_cur, "DEBUG: ", + sizeof("DEBUG: ") - 1)) { + msg_log_level = LOG_DEBUG; + } + if (ctx == NULL) { + memmove(arg_cur, arg_cur + sizeof("DEBUG: ") - 1, + strlen(arg_cur + sizeof("DEBUG: ") - 1) + 1); + } + found = TRUE; + break; + } + } + } + break; + case '#': case '-': case ' ': case '+': case '\'': case 'I': case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '*': + break; + case 'l': + case 'z': + case 't': + case 'j': + case 'd': case 'i': + case 'o': + case 'u': + case 'x': case 'X': + case 'e': case 'E': + case 'f': case 'F': + case 'g': case 'G': + case 'a': case 'A': + case 'c': + case 'p': + if (scan_state == escan_seenpercent) { + (void) va_arg(aq, void *); /* skip forward */ + scan_state = escan_seennothing; + } + break; + default: + scan_state = escan_seennothing; + break; + } + } + + if (log_level != NULL) { + /* intention of the following offset is: + cibadmin -V -> start showing INFO labelled messages */ + if (*log_level + 4 >= msg_log_level) { + vfprintf(stderr, fmt, ap); + } + } else { + CRM_XML_LOG_BASE(msg_log_level, TRUE, 0, "CIB upgrade: ", fmt, ap); + } + + va_end(aq); va_end(ap); } /* Denotes temporary emergency fix for "xmldiff'ing not text-node-ready"; proper fix is most likely to teach __xml_diff_object and friends to deal with XML_TEXT_NODE (and more?), i.e., those nodes currently missing "_private" field (implicitly as NULL) which clashes with unchecked accesses (e.g. in __xml_offset) -- the outcome may be that those unexpected XML nodes will simply be ignored for the purpose of diff'ing, or it may be made more robust, or per the user's preference (which then may be exposed as crm_diff switch). Said XML_TEXT_NODE may appear unexpectedly due to how upgrade-2.10.xsl is arranged. The emergency fix is simple: reparse XSLT output with blank-ignoring parser. */ #ifndef PCMK_SCHEMAS_EMERGENCY_XSLT #define PCMK_SCHEMAS_EMERGENCY_XSLT 1 #endif static xmlNode * apply_transformation(xmlNode *xml, const char *transform, gboolean to_logs) { char *xform = NULL; xmlNode *out = NULL; xmlDocPtr res = NULL; xmlDocPtr doc = NULL; xsltStylesheet *xslt = NULL; #if PCMK_SCHEMAS_EMERGENCY_XSLT != 0 xmlChar *emergency_result; int emergency_txt_len; int emergency_res; #endif CRM_CHECK(xml != NULL, return FALSE); doc = getDocPtr(xml); xform = get_schema_path(NULL, transform); xmlLoadExtDtdDefaultValue = 1; xmlSubstituteEntitiesDefault(1); /* for capturing, e.g., what's emitted via */ if (to_logs) { xsltSetGenericErrorFunc(NULL, cib_upgrade_err); } else { - xsltSetGenericErrorFunc((void *) stderr, (xmlGenericErrorFunc) fprintf); + xsltSetGenericErrorFunc(&crm_log_level, cib_upgrade_err); } xslt = xsltParseStylesheetFile((const xmlChar *)xform); CRM_CHECK(xslt != NULL, goto cleanup); res = xsltApplyStylesheet(xslt, doc, NULL); CRM_CHECK(res != NULL, goto cleanup); xsltSetGenericErrorFunc(NULL, NULL); /* restore default one */ #if PCMK_SCHEMAS_EMERGENCY_XSLT != 0 emergency_res = xsltSaveResultToString(&emergency_result, &emergency_txt_len, res, xslt); xmlFreeDoc(res); CRM_CHECK(emergency_res == 0, goto cleanup); out = string2xml((const char *) emergency_result); free(emergency_result); #else out = xmlDocGetRootElement(res); #endif cleanup: if (xslt) { xsltFreeStylesheet(xslt); } free(xform); return out; } -#endif + +/*! + * \internal + * \brief Possibly full enter->upgrade->leave trip per internal bookkeeping. + * + * \note Only emits warnings about enter/leave phases in case of issues. + */ +static xmlNode * +apply_upgrade(xmlNode *xml, const struct schema_s *schema, gboolean to_logs) +{ + bool transform_onleave = schema->transform_onleave; + char *transform_leave; + xmlNode *upgrade = NULL, + *final = NULL; + + if (schema->transform_enter) { + crm_debug("Upgrading %s-style configuration, pre-upgrade phase with %s", + schema->name, schema->transform_enter); + upgrade = apply_transformation(xml, schema->transform_enter, to_logs); + if (upgrade == NULL) { + crm_warn("Upgrade-enter transformation %s failed", + schema->transform_enter); + transform_onleave = FALSE; + } + } + if (upgrade == NULL) { + upgrade = xml; + } + + crm_debug("Upgrading %s-style configuration, main phase with %s", + schema->name, schema->transform); + final = apply_transformation(upgrade, schema->transform, to_logs); + + if (final != NULL && transform_onleave) { + free_xml(upgrade); + upgrade = final; + transform_leave = strdup(schema->transform_enter); + /* enter -> leave */ + memcpy(strrchr(transform_leave, '-') + 1, "leave", 5); + crm_debug("Upgrading %s-style configuration, post-upgrade phase with %s", + schema->name, transform_leave); + final = apply_transformation(upgrade, transform_leave, to_logs); + if (final == NULL) { + crm_warn("Upgrade-leave transformation %s failed", transform_leave); + final = upgrade; + } else { + free_xml(upgrade); + } + free(transform_leave); + } + + return final; +} + +#endif /* HAVE_LIBXSLT */ const char * get_schema_name(int version) { if (version < 0 || version >= xml_schema_max) { return "unknown"; } return known_schemas[version].name; } int get_schema_version(const char *name) { int lpc = 0; if (name == NULL) { name = "none"; } for (; lpc < xml_schema_max; lpc++) { if (safe_str_eq(name, known_schemas[lpc].name)) { return lpc; } } return -1; } /* set which validation to use */ int update_validation(xmlNode **xml_blob, int *best, int max, gboolean transform, gboolean to_logs) { xmlNode *xml = NULL; char *value = NULL; int max_stable_schemas = xml_latest_schema_index(); int lpc = 0, match = -1, rc = pcmk_ok; int next = -1; /* -1 denotes "inactive" value */ CRM_CHECK(best != NULL, return -EINVAL); *best = 0; CRM_CHECK(xml_blob != NULL, return -EINVAL); CRM_CHECK(*xml_blob != NULL, return -EINVAL); xml = *xml_blob; value = crm_element_value_copy(xml, XML_ATTR_VALIDATION); if (value != NULL) { match = get_schema_version(value); lpc = match; if (lpc >= 0 && transform == FALSE) { *best = lpc++; } else if (lpc < 0) { crm_debug("Unknown validation schema"); lpc = 0; } } if (match >= max_stable_schemas) { /* nothing to do */ free(value); *best = match; return pcmk_ok; } while (lpc <= max_stable_schemas) { crm_debug("Testing '%s' validation (%d of %d)", known_schemas[lpc].name ? known_schemas[lpc].name : "", lpc, max_stable_schemas); if (validate_with(xml, lpc, to_logs) == FALSE) { if (next != -1) { crm_info("Configuration not valid for schema: %s", known_schemas[lpc].name); next = -1; } else { crm_trace("%s validation failed", known_schemas[lpc].name ? known_schemas[lpc].name : ""); } if (*best) { /* we've satisfied the validation, no need to check further */ break; } rc = -pcmk_err_schema_validation; } else { if (next != -1) { crm_debug("Configuration valid for schema: %s", known_schemas[next].name); next = -1; } rc = pcmk_ok; } if (rc == pcmk_ok) { *best = lpc; } if (rc == pcmk_ok && transform) { xmlNode *upgrade = NULL; next = known_schemas[lpc].after_transform; if (next <= lpc) { /* There is no next version, or next would regress */ crm_trace("Stopping at %s", known_schemas[lpc].name); break; } else if (max > 0 && (lpc == max || next > max)) { crm_trace("Upgrade limit reached at %s (lpc=%d, next=%d, max=%d)", known_schemas[lpc].name, lpc, next, max); break; - } else if (known_schemas[lpc].transform == NULL) { + } else if (known_schemas[lpc].transform == NULL + /* possibly avoid transforming when readily valid + (in general more restricted when crossing the major + version boundary, as X.0 "transitional" version is + expected to be more strict than it's successors that + may re-allow constructs from previous major line) */ + || validate_with_silent(xml, next)) { crm_debug("%s-style configuration is also valid for %s", known_schemas[lpc].name, known_schemas[next].name); lpc = next; } else { crm_debug("Upgrading %s-style configuration to %s with %s", known_schemas[lpc].name, known_schemas[next].name, - known_schemas[lpc].transform ? known_schemas[lpc].transform : "no-op"); + known_schemas[lpc].transform); #if HAVE_LIBXSLT - upgrade = apply_transformation(xml, known_schemas[lpc].transform, to_logs); + upgrade = apply_upgrade(xml, &known_schemas[lpc], to_logs); #endif if (upgrade == NULL) { crm_err("Transformation %s failed", known_schemas[lpc].transform); rc = -pcmk_err_transform_failed; } else if (validate_with(upgrade, next, to_logs)) { crm_info("Transformation %s successful", known_schemas[lpc].transform); lpc = next; *best = next; free_xml(xml); xml = upgrade; rc = pcmk_ok; } else { crm_err("Transformation %s did not produce a valid configuration", known_schemas[lpc].transform); crm_log_xml_info(upgrade, "transform:bad"); free_xml(upgrade); rc = -pcmk_err_schema_validation; } next = -1; } } if (transform == FALSE || rc != pcmk_ok) { /* we need some progress! */ lpc++; } } if (*best > match && *best) { crm_info("%s the configuration from %s to %s", transform?"Transformed":"Upgraded", value ? value : "", known_schemas[*best].name); crm_xml_add(xml, XML_ATTR_VALIDATION, known_schemas[*best].name); } *xml_blob = xml; free(value); return rc; } gboolean cli_config_update(xmlNode **xml, int *best_version, gboolean to_logs) { gboolean rc = TRUE; const char *value = crm_element_value(*xml, XML_ATTR_VALIDATION); char *const orig_value = strdup(value == NULL ? "(none)" : value); int version = get_schema_version(value); int orig_version = version; int min_version = xml_minimum_schema_index(); if (version < min_version) { xmlNode *converted = NULL; converted = copy_xml(*xml); update_validation(&converted, &version, 0, TRUE, to_logs); value = crm_element_value(converted, XML_ATTR_VALIDATION); if (version < min_version) { if (version < orig_version || orig_version == -1) { if (to_logs) { crm_config_err("Your current configuration %s could not" " validate with any schema in range [%s, %s]," " cannot upgrade to %s.", orig_value, get_schema_name(orig_version), xml_latest_schema(), get_schema_name(min_version)); } else { fprintf(stderr, "Your current configuration %s could not" " validate with any schema in range [%s, %s]," " cannot upgrade to %s.\n", orig_value, get_schema_name(orig_version), xml_latest_schema(), get_schema_name(min_version)); } } else if (to_logs) { crm_config_err("Your current configuration could only be upgraded to %s... " "the minimum requirement is %s.", crm_str(value), get_schema_name(min_version)); } else { fprintf(stderr, "Your current configuration could only be upgraded to %s... " "the minimum requirement is %s.\n", crm_str(value), get_schema_name(min_version)); } free_xml(converted); converted = NULL; rc = FALSE; } else { free_xml(*xml); *xml = converted; if (version < xml_latest_schema_index()) { crm_config_warn("Your configuration was internally updated to %s... " "which is acceptable but not the most recent", get_schema_name(version)); } else if (to_logs) { crm_info("Your configuration was internally updated to the latest version (%s)", get_schema_name(version)); } } } else if (version >= get_schema_version("none")) { if (to_logs) { crm_config_warn("Configuration validation is currently disabled." " It is highly encouraged and prevents many common cluster issues."); } else { fprintf(stderr, "Configuration validation is currently disabled." " It is highly encouraged and prevents many common cluster issues.\n"); } } if (best_version) { *best_version = version; } free(orig_value); return rc; } diff --git a/xml/Makefile.am b/xml/Makefile.am index 0c3183a552..6fcb77c01d 100644 --- a/xml/Makefile.am +++ b/xml/Makefile.am @@ -1,172 +1,176 @@ # # Copyright (C) 2004 Andrew Beekhof # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MAINTAINERCLEANFILES = Makefile.in RNGdir = $(CRM_SCHEMA_DIRECTORY) xsltdir = $(RNGdir) -xslt_DATA = $(top_srcdir)/xml/upgrade-*.xsl +dist_xslt_DATA = $(top_srcdir)/xml/upgrade-1.3.xsl \ + $(top_srcdir)/xml/upgrade-2.10.xsl \ + $(top_srcdir)/xml/upgrade-*enter.xsl \ + $(top_srcdir)/xml/upgrade-*leave.xsl noinst_DATA = context-of.xsl # See Readme.md for details on updating schema files # Sorted list of available numeric RNG versions, # extracted from filenames like NAME-MAJOR[.MINOR][.MINOR-MINOR].rng RNG_numeric_versions = $(shell ls -1 $(top_srcdir)/xml/*.rng \ | sed -n -e 's/^.*-\([0-9][0-9.]*\).rng$$/\1/p' \ | sort -u -t. -k 1,1n -k 2,2n -k 3,3n) # The highest numeric version RNG_max ?= $(lastword $(RNG_numeric_versions)) # A sorted list of all RNG versions (numeric and "next") RNG_versions = next $(RNG_numeric_versions) RNG_version_pairs = $(join \ ${RNG_numeric_versions},$(addprefix \ -,$(wordlist \ 2,$(words ${RNG_numeric_versions}),${RNG_numeric_versions} \ ) next \ ) \ ) RNG_version_pairs_cnt = $(words ${RNG_version_pairs}) RNG_version_pairs_last = $(wordlist \ $(words \ $(wordlist \ 2,${RNG_version_pairs_cnt},${RNG_version_pairs} \ ) \ ),${RNG_version_pairs_cnt},${RNG_version_pairs} \ ) RNG_generated = pacemaker.rng $(foreach base,$(RNG_versions),pacemaker-$(base).rng) versions.rng -RNG_cfg_base = options nodes resources constraints fencing acls tags alerts -RNG_base = cib $(RNG_cfg_base) status score rule nvset -RNG_files = $(foreach base,$(RNG_base),$(wildcard $(base)*.rng)) +RNG_cfg_base = options nodes resources constraints fencing acls tags alerts +RNG_base = cib $(RNG_cfg_base) status score rule nvset +RNG_files = $(foreach base,$(RNG_base),$(wildcard $(base).rng $(base)-*.rng)) # List of non-Pacemaker RNGs RNG_extra = crm_mon.rng -RNG_DATA = $(RNG_files) $(RNG_generated) $(RNG_extra) +dist_RNG_DATA = $(RNG_files) $(RNG_extra) +nodist_RNG_DATA = $(RNG_generated) EXTRA_DIST = best-match.sh versions: echo "Max: $(RNG_max)" echo "Available: $(RNG_versions)" versions.rng: Makefile.am echo " RNG $@" echo '' > $@ echo '' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' none' >> $@ echo ' pacemaker-0.6' >> $@ echo ' transitional-0.6' >> $@ echo ' pacemaker-0.7' >> $@ echo ' pacemaker-1.1' >> $@ for rng in $(RNG_versions); do echo " pacemaker-$$rng" >> $@; done echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo '' >> $@ pacemaker.rng: pacemaker-$(RNG_max).rng echo " RNG $@" cp $(top_builddir)/xml/$< $@ pacemaker-%.rng: $(RNG_files) best-match.sh Makefile.am echo " RNG $@" echo '' > $@ echo '' >> $@ echo ' ' >> $@ echo ' ' >> $@ $(top_srcdir)/xml/best-match.sh cib $(*) $(@) " " echo ' ' >> $@ echo ' ' >> $@ for rng in $(RNG_cfg_base); do $(top_srcdir)/xml/best-match.sh $$rng $(*) $(@) " " || :; done echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ $(top_srcdir)/xml/best-match.sh status $(*) $(@) " " echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo ' ' >> $@ echo '' >> $@ # diff fails with ec=2 if no predecessor is found; # this uses '=' GNU extension to sed, if that's not available, # one can use: hline=`echo "$${p}" | grep -Fn "$${hunk}" | cut -d: -f1`; # XXX: use line information from hunk to avoid "not detected" for ambiguity version_diff = \ @for p in $(1); do \ set `echo "$${p}" | tr '-' ' '`; \ echo "\#\#\# *-$$2.rng vs. predecessor"; \ for v in *-$$2.rng; do \ echo "\#\#\#\# $${v} vs. predecessor"; b=`echo "$${v}" | cut -d- -f1`; \ old=`./best-match.sh $${b} $$1`; \ p=`diff -u "$${old}" "$${v}" 2>/dev/null`; \ case $$? in \ 1) echo "$${p}" | sed -n -e '/^@@ /!d;=;p' \ -e ':l;n;/^\([- ]\|+.*<[^ />]\+\([^/>]\+="ID\|>$$\)\)/bl;s/^[+ ]\(.*\)/\1/p' \ | while read hline; do \ read h && read i || break; \ iline=`grep -Fn "$${i}" "$${v}" | cut -d: -f1`; \ ctxt="(not detected)"; \ if test `echo "$${iline}" | wc -l` -eq 1; then \ ctxt=`{ sed -n -e "1,$$(($${iline}-1))p" "$${v}"; \ echo "$${i}"; \ sed -n -e "$$(($${iline}+1)),$$ p" "$${v}"; \ } | $(XSLTPROC) --param skip 1 context-of.xsl -`; \ fi; \ echo "$${p}" | sed -n -e "$$(($${hline}-2)),$${hline}!d" \ -e '/^\(+++\|---\)/p'; \ echo "$${h} context: $${ctxt}"; \ echo "$${p}" | sed -n -e "1,$${hline}d" \ -e '/^\(---\|@@ \)/be;p;d;:e;n;be'; \ done; \ ;; \ 2) echo "\#\#\#\#\# $${v} has no predecessor";; \ esac; \ done; \ done diff: best-match.sh @echo "# Comparing changes in + since $(RNG_max)" $(call version_diff,${RNG_version_pairs_last}) fulldiff: best-match.sh @echo "# Comparing all changes across all the subsequent increments" $(call version_diff,${RNG_version_pairs}) sync: git rm -f $(wildcard *-next.rng) make pacemaker-next.rng CLEANFILES = $(RNG_generated) diff --git a/xml/Readme.md b/xml/Readme.md index 73aa64f584..b8b04ca75b 100644 --- a/xml/Readme.md +++ b/xml/Readme.md @@ -1,122 +1,141 @@ # Schema Reference Pacemaker's XML schema has a version of its own, independent of the version of Pacemaker itself. ## Versioned Schema Evolution A versioned schema offers transparent backward and forward compatibility. - It reflects the timeline of schema-backed features (introduction, changes to the syntax, possibly deprecation) through the versioned stable schema increments, while keeping schema versions used by default by older Pacemaker versions untouched. - Pacemaker internally uses the latest stable schema version, and relies on supplemental transformations to promote cluster configurations based on older, incompatible schema versions into the desired form. - It allows experimental features with a possibly unstable configuration interface to be developed using the special `next` version of the schema. ## Mapping Pacemaker Versions to Schema Versions | Pacemaker | Latest Schema | Changed | --------- | ------------- | ---------------------------------------------- | `2.0.0` | `3.0` | `constraints`, `resources` | `1.1.18` | `2.10` | `resources`, `alerts` | `1.1.17` | `2.9` | `resources`, `rule` | `1.1.16` | `2.6` | `constraints` | `1.1.15` | `2.5` | `alerts` | `1.1.14` | `2.4` | `fencing` | `1.1.13` | `2.3` | `constraints` | `1.1.12` | `2.0` | `nodes`, `nvset`, `resources`, `tags`, `acls` | `1.1.8`+ | `1.2` | ## Schema generation Each logical portion of the schema goes into its own RNG file, named like `${base}-${X}.${Y}.rng`. `${base}` identifies the portion of the schema (e.g. constraints, resources); ${X}.${Y} is the latest schema version that contained changes in this portion of the schema. The complete, overall schema, `pacemaker-${X}.${Y}.rng`, is automatically generated from the other files via the Makefile. # Updating schema files # ## Experimental features ## Experimental features go into `${base}-next.rng` where `${base}` is the affected portion of the schema. If such a file does not already exist, create it by copying the most recent `${base}-${X}.${Y}.rng`. Pacemaker will not use the experimental schema by default; the cluster administrator must explicitly set the `validate-with` property appropriately to use it. ## Stable features ## The current stable version is determined at runtime when crm_schema_init() scans the CRM_SCHEMA_DIRECTORY. It will have the form `pacemaker-${X}.${Y}` and the highest `${X}.${Y}` wins. ### Simple Additions When the new syntax is a simple addition to the previous one, create a new entry, incrementing `${Y}`. ### Feature Removal or otherwise Incompatible Changes When the new syntax is not a simple addition to the previous one, create a new entry, incrementing `${X}` and setting `${Y} = 0`. An XSLT file is also required that converts an old syntax to the new one and must be named `upgrade-${Xold}.${Yold}.xsl`. See `xml/upgrade-1.3.xsl` for an example. Since `xml/upgrade-2.10.xsl`, rather self-descriptive approach is taken, separating metadata of the replacements and other modifications to perform from the actual executive parts, which is leveraged, e.g., with the on-the-fly overview as obtained with `./regression.sh -X test2to3`. Also this was the first time particular key names of `nvpair`s, i.e. below the granularity of the schemas so far, received attention, and consequently, no longer expected names became systemically banned in the after-upgrade schemas, using `` construct in the data type specification pertaining the affected XML path. +The implied complexity also resulted in establishing a new compound, +stepwise transformation, alleviating the procedural burden from the +core upgrade recipe. In particular, `id-ref` based syntactic +simplification granted in the CIB format introduces nonnegligible +internal "noise" because of the extra indirection encumbered with +generally non-bijective character of such a scheme (context-dependent +interpretation). To reduce this strain, a symmetric arrangement is +introduced as a pair of _enter_/_leave_ (pre-upgrade/post-upgrade) +transformations where the latter is meant to eventually reversibly +restore what the former intentionally simplified (normalized) for +upgrade transformation's peruse. It's optional (even the post-upgrade +counterpart is optional alone) and depends on whether the suitable +files are found along the upgrade transformation itself: e.g., for +`upgrade-2.10.xsl`, such files are `upgrade-2.10-enter.xsl` and +`upgrade-2.10-leave.xsl`. Note that unfolding + refolding `id-ref` +shortcuts is just a practically imposed individual case of how to +reversibly make the configuration space tractable in the upgrade +itself, allowing for more sophistication down the road. + ### General Procedure 1. Copy the most recent version of `${base}-*.rng` to `${base}-${X}.${Y}.rng` 1. Commit the copy, e.g. `"Low: xml: clone ${base} schema in preparation for changes"`. This way, the actual change will be obvious in the commit history. 1. Modify `${base}-${X}.${Y}.rng` as required. 1. If required, add an XSLT file, and update `xslt_SCRIPTS` in `xml/Makefile.am`. 1. Commit 1. `make -C xml clean; make -C xml all` to rebuild the schemas in the local source directory. 1. The CIB validity regression tests will break after the schema is updated. Run `tools/regression.sh` to get the new output, `diff tools/regression.validity.{out,exp}` to ensure the changes look correct, `cp tools/regression.validity.{out,exp}` to update the expected output, then commit the change. 1. Similarly, with the new major version `${X}`, it's advisable to refresh scheduler tests at some point, see the instructions in `cts/README.md`. ## Using a New Schema New features will not be available until the cluster administrator: 1. Updates all the nodes 1. Runs the equivalent of `cibadmin --upgrade --force` ## Random Notes From the source directory, run `make -C xml diff` to see the changes in the current schema (compared to the previous ones) and also the pending changes in `pacemaker-next`. Alternatively, if the intention is to grok the overall historical schema evolution, use `make -C xml fulldiff`. diff --git a/xml/assets/upgrade-2.10-htmldiff.xsl b/xml/assets/upgrade-2.10-htmldiff.xsl index 22922904c6..175bdb20c4 100644 --- a/xml/assets/upgrade-2.10-htmldiff.xsl +++ b/xml/assets/upgrade-2.10-htmldiff.xsl @@ -1,351 +1,358 @@ - + - + - - + <xsl:text>upgrade-2.10 on-the-fly in-browser transformation</xsl:text>

test

Using upgrade-2.10 on-the-fly in-browser transformation [ previous and next, or use arrows ]

Differences highlight view to be loaded here.

Diagnostics

Open JS console (e.g. Ctrl + Shift + J, focusing JS + log combo) to check the actual messages from the in-browser transformation match the baseline:

-
+      

Expected diagnostic messages to be loaded here. -

+

Debugging

These are raw data (beware, already chewed with the view-source transformation, hence not very suitable for copying) entering the differential generating processs:

original+ original-

           
         

transformed+ transformed-

           
         


This generated page is based on the externally provided pacemaker XML configuration file (CIB), @basename@, which is the primary object of interest here. But the rendered page wouldn't be possible without the actual transformations and other auxiliary files that come with these notices:

diff --git a/xml/cibtr-2.rng b/xml/cibtr-2.rng index 0c7651b935..36e832817c 100644 --- a/xml/cibtr-2.rng +++ b/xml/cibtr-2.rng @@ -1,198 +1,211 @@ 1 1 1 + + + + WARNING + INFO + DEBUG + + + + 1 + + + diff --git a/xml/regression.sh b/xml/regression.sh index c3bce333c2..b078a1cd1a 100755 --- a/xml/regression.sh +++ b/xml/regression.sh @@ -1,640 +1,727 @@ #!/bin/sh # Copyright 2018 Red Hat, Inc. # Author: Jan Pokorny # Part of pacemaker project # SPDX-License-Identifier: GPL-2.0-or-later set -eu test -d assets && test -d test-2 \ || { echo 'Run me from source-tree-like location'; exit 1; } # $1=reference (can be '-' for stdin), $2=investigated # alt.: wdiff, colordiff, ... DIFF=${DIFF:-diff} DIFFOPTS=${DIFFOPTS--u} DIFFPAGER=${DIFFPAGER:-less -LRX} # $1=schema, $2=validated # alt.: jing -i RNGVALIDATOR=${RNGVALIDATOR:-xmllint --noout --relaxng} # $1=stylesheet, $2=source # alt.: Xalan, saxon, sabcmd/Sablotron (note: only validates reliably with -B) _xalan_wrapper() { { ${_XSLTPROCESSOR} "$2" "$1" 2>&1 >&3 \ | sed -e '/^Source tree node.*$/d' \ -e 's|^XSLT message: \(.*\) (Occurred.*)|\1|'; } 3>&- 3>&1 >&2 } # Sablotron doesn't translate '-' file specification to stdin # and limits the length of the output message _sabcmd_wrapper() { _sabw_sheet=${1:?} _sabw_source=${2:?} test "${_sabw_sheet}" != - || _sabw_sheet=/dev/stdin test "${_sabw_source}" != - || _sabw_source=/dev/stdin { ${_XSLTPROCESSOR} "${_sabw_sheet}" "${_sabw_source}" 2>&1 >&3 \ | sed -e '/^Warning \[code:89\]/d' \ -e 's|^ xsl:message (\(.*\))$|\1|'; } 3>&- 3>&1 >&2 } # filtered out message: https://bugzilla.redhat.com/show_bug.cgi?id=1577367 _saxon_wrapper() { { ${_XSLTPROCESSOR} "-xsl:$1" "-s:$2" -versionmsg:off 2>&1 >&3 \ | sed -e '/^Cannot find CatalogManager.properties$/d'; } 3>&- 3>&1 >&2 } XSLTPROCESSOR=${XSLTPROCESSOR:-xsltproc --nonet} _XSLTPROCESSOR=${XSLTPROCESSOR} case "${XSLTPROCESSOR}" in [Xx]alan*|*/[Xx]alan*) XSLTPROCESSOR=_xalan_wrapper;; sabcmd*|*/sabcmd*) XSLTPROCESSOR=_sabcmd_wrapper;; saxon*|*/saxon*) XSLTPROCESSOR=_saxon_wrapper;; esac HTTPPORT=${HTTPPORT:-8000} # Python's default WEBBROWSER=${WEBBROWSER:-firefox} tests= # test* names (should go first) here will become preselected default # # commons # emit_result() { _er_howmany=${1:?} # how many errors (0/anything else incl. strings) _er_subject=${2:?} _er_prefix=${3-} test -z "${_er_prefix}" || _er_prefix="${_er_prefix}: " if test "${_er_howmany}" = 0; then printf "%s%s finished OK\n" "${_er_prefix}" "${_er_subject}" else printf "%s%s encountered ${_er_howmany} errors\n" \ "${_er_prefix}" "${_er_subject}" fi } emit_error() { _ee_msg=${1:?} printf "%s\n" "${_ee_msg}" >&2 } # returns 1 + floor of base 2 logaritm for _lo0r_i in 1...255, # or 0 for _lo0r_i = 0 log2_or_0_return() { _lo0r_i=${1:?} return $(((!(_lo0r_i >> 1) && _lo0r_i) * 1 \ + (!(_lo0r_i >> 2) && _lo0r_i & (1 << 1)) * 2 \ + (!(_lo0r_i >> 3) && _lo0r_i & (1 << 2)) * 3 \ + (!(_lo0r_i >> 4) && _lo0r_i & (1 << 3)) * 4 \ + (!(_lo0r_i >> 5) && _lo0r_i & (1 << 4)) * 5 \ + (!(_lo0r_i >> 6) && _lo0r_i & (1 << 5)) * 6 \ + (!(_lo0r_i >> 7) && _lo0r_i & (1 << 6)) * 7 \ + !!(_lo0r_i >> 7) * 7 )) } # rough addition of two base 2 logarithms log2_or_0_add() { _lo0a_op1=${1:?} _lo0a_op2=${2:?} if test ${_lo0a_op1} -gt ${_lo0a_op2}; then return ${_lo0a_op1} elif test ${_lo0a_op2} -gt ${_lo0a_op1}; then return ${_lo0a_op2} elif test ${_lo0a_op1} -gt 0; then return $((_lo0a_op1 + 1)) else return ${_lo0a_op1} fi } # # test phases # # stdin: input file per line test_browser() { _tb_cleanref=0 _tb_serverpid= if ! read _tb_first; then return 1 fi cat >/dev/null 2>/dev/null # read out the rest test -f assets/diffview.js \ || curl -Lo assets/diffview.js \ 'https://raw.githubusercontent.com/prettydiff/prettydiff/2.2.8/lib/diffview.js' { which python3 >/dev/null 2>/dev/null \ && { python3 -m http.server "${HTTPPORT}" -b 127.0.0.1 \ || emit_error "Python3 HTTP server fail"; return; } \ || which python2 >/dev/null 2>/dev/null \ && { printf '%s %s\n' \ 'Python 2 backed HTTP server cannot listen at particular' \ 'address, discretion regarding firewall rules recommended!' python2 -m SimpleHTTPServer "${HTTPPORT}" \ || emit_error 'Python2 HTTP server fail'; return; } \ || emit_error 'Cannot run Python based HTTP server' ; } & _tb_serverpid=$! ${WEBBROWSER} "http://localhost:${HTTPPORT}/${_tb_first}" & printf "When finished, just press Ctrl+C or kill %d, please\n" \ "${_tb_serverpid}" wait } # -r ... whether to remove referential files as well # stdin: input file per line test_cleaner() { _tc_cleanref=0 while test $# -gt 0; do case "$1" in -r) _tc_cleanref=1;; esac shift done while read _tc_origin; do _tc_origin=${_tc_origin%.*} rm -f "${_tc_origin}.up" "${_tc_origin}.up.err" rm -f "$(dirname "${_tc_origin}")/.$(basename "${_tc_origin}").up" test ${_tc_cleanref} -eq 0 \ || rm -f "${_tc_origin}.ref" "${_tc_origin}.ref.err" done } +# -a= ... action modifier to derive template name from (if any; enter/leave) +# -o= ... which conventional version to deem as the transform origin test_selfcheck() { _tsc_ret=0 + _tsc_action= _tsc_template= _tsc_validator= while test $# -gt 0; do case "$1" in + -a=*) _tsc_action="${1#-a=}";; -o=*) _tsc_template="${1#-o=}";; esac shift done _tsc_validator="${_tsc_template:?}" _tsc_validator="cibtr-${_tsc_validator%%.*}.rng" - _tsc_template="upgrade-${_tsc_template}.xsl" + _tsc_action=${_tsc_action:+-${_tsc_action}} + _tsc_template="upgrade-${_tsc_template}${_tsc_action}.xsl" # check schema (sub-grammar) for custom transformation mapping alone - if ! ${RNGVALIDATOR} 'http://relaxng.org/relaxng.rng' "${_tsc_validator}"; then + if test -z "${_tsc_action}" \ + && ! ${RNGVALIDATOR} 'http://relaxng.org/relaxng.rng' "${_tsc_validator}"; then _tsc_ret=$((_tsc_ret + 1)) fi + # check the overall XSLT per the main grammar + said sub-grammar - if ! ${RNGVALIDATOR} "xslt_${_tsc_validator}" "${_tsc_template}"; then + if ! ${RNGVALIDATOR} \ + "$(test -f "${_tsc_validator}" \ + && echo "xslt_${_tsc_validator}" \ + || echo 'http://www.thaiopensource.com/relaxng/xslt.rng')" \ + "${_tsc_template}"; then _tsc_ret=$((_tsc_ret + 1)) fi log2_or_0_return ${_tsc_ret} } test_explanation() { _tsc_template= while test $# -gt 0; do case "$1" in -o=*) _tsc_template="upgrade-${1#-o=}.xsl";; esac shift done ${XSLTPROCESSOR} upgrade-detail.xsl "${_tsc_template}" } # stdout: filename of the transformed file test_runner_upgrade() { _tru_template=${1:?} _tru_source=${2:?} # filename _tru_mode=${3:?} # extra modes wrt. "referential" outcome, see below _tru_ref="${_tru_source%.*}.ref" { test "$((_tru_mode & (1 << 0)))" -ne 0 \ || test -f "${_tru_ref}.err"; } \ && _tru_ref_err="${_tru_ref}.err" || _tru_ref_err=/dev/null _tru_target="${_tru_source%.*}.up" _tru_target_err="${_tru_target}.err" if test $((_tru_mode & (1 << 2))) -eq 0; then ${XSLTPROCESSOR} "${_tru_template}" "${_tru_source}" \ > "${_tru_target}" 2> "${_tru_target_err}" \ || { _tru_ref=$?; echo "${_tru_target_err}" return ${_tru_ref}; } else # when -B (deblanked outcomes handling) requested, we: # - drop blanks from the source XML # (effectively emulating pacemaker handling) # - re-drop blanks from the XSLT outcome, # which is compared with referential outcome # processed with even greedier custom deblanking # (extraneous inter-element whitespace like blank # lines will not get removed otherwise, see lower) xmllint --noblanks "${_tru_source}" \ | ${XSLTPROCESSOR} "${_tru_template}" - \ > "${_tru_target}" 2> "${_tru_target_err}" \ || { _tru_ref=$?; echo "${_tru_target_err}" return ${_tru_ref}; } # reusing variable no longer needed _tru_template="$(dirname "${_tru_target}")" _tru_template="${_tru_template}/.$(basename "${_tru_target}")" mv "${_tru_target}" "${_tru_template}" ${XSLTPROCESSOR} - "${_tru_template}" > "${_tru_target}" <<-EOF EOF fi # only respond with the flags except for "-B", i.e., when both: # - _tru_mode non-zero # - "-B" in _tru_mode is zero (hence non-zero when flipped with XOR) if test "$((_tru_mode * ((_tru_mode ^ (1 << 2)) & (1 << 2))))" -ne 0; then if test $((_tru_mode & (1 << 0))) -ne 0; then cp -a "${_tru_target}" "${_tru_ref}" cp -a "${_tru_target_err}" "${_tru_ref_err}" fi if test $((_tru_mode & (1 << 1))) -ne 0; then - "${DIFF}" ${DIFFOPTS} "${_tru_source}" "${_tru_ref}" \ - | ${DIFFPAGER} >&2 + { "${DIFF}" ${DIFFOPTS} "${_tru_source}" "${_tru_ref}" \ + && printf '\n(files match)\n'; } | ${DIFFPAGER} >&2 if test $? -ne 0; then printf "\npager failure\n" >&2 return 1 fi printf '\nIs comparison OK? ' >&2 if read _tru_answer &2; return 1;; esac else return 1 fi fi elif test -f "${_tru_ref}" && test -e "${_tru_ref_err}"; then { test "$((_tru_mode & (1 << 2)))" -eq 0 && cat "${_tru_ref}" \ || ${XSLTPROCESSOR} - "${_tru_ref}" <<-EOF EOF } \ | "${DIFF}" ${DIFFOPTS} - "${_tru_target}" >&2 \ && "${DIFF}" ${DIFFOPTS} "${_tru_ref_err}" \ "${_tru_target_err}" >&2 if test $? -ne 0; then emit_error "Outputs differ from referential ones" echo "/dev/null" return 1 fi else emit_error "Referential file(s) missing: ${_tru_ref}" echo "/dev/null" return 1 fi echo "${_tru_target}" } test_runner_validate() { _trv_schema=${1:?} _trv_target=${2:?} # filename if ! ${RNGVALIDATOR} "${_trv_schema}" "${_trv_target}" \ 2>/dev/null; then ${RNGVALIDATOR} "${_trv_schema}" "${_trv_target}" fi } +# -a= ... action modifier completing template name (e.g. 2.10-(enter|leave)) # -o= ... which conventional version to deem as the transform origin # -t= ... which conventional version to deem as the transform target # -B # -D # -G ... see usage # stdin: input file per line test_runner() { _tr_mode=0 _tr_ret=0 + _tr_action= _tr_schema_o= _tr_schema_t= _tr_target= _tr_template= while test $# -gt 0; do case "$1" in - -o=*) _tr_template="upgrade-${1#-o=}.xsl" + -a=*) _tr_action="${1#-a=}";; + -o=*) _tr_template="${1#-o=}" _tr_schema_o="pacemaker-${1#-o=}.rng";; -t=*) _tr_schema_t="pacemaker-${1#-t=}.rng";; -G) _tr_mode=$((_tr_mode | (1 << 0)));; -D) _tr_mode=$((_tr_mode | (1 << 1)));; -B) _tr_mode=$((_tr_mode | (1 << 2)));; esac shift done + _tr_template="upgrade-${_tr_action:-${_tr_template:?}}.xsl" if ! test -f "${_tr_schema_o:?}" || ! test -f "${_tr_schema_t:?}"; then emit_error "Origin and/or target schema missing, rerun make" return 1 fi while read _tr_origin; do printf '%-60s' "${_tr_origin}... " # pre-validate if ! test_runner_validate "${_tr_schema_o}" "${_tr_origin}"; then _tr_ret=$((_tr_ret + 1)); echo "E:pre-validate"; continue fi # upgrade if ! _tr_target=$(test_runner_upgrade "${_tr_template}" \ "${_tr_origin}" "${_tr_mode}"); then _tr_ret=$((_tr_ret + 1)); test -n "${_tr_target}" || break echo "E:upgrade" test -s "${_tr_target}" \ && { echo ---; cat "${_tr_target}" || :; echo ---; } continue fi # post-validate if ! test_runner_validate "${_tr_schema_t}" "${_tr_target}"; then _tr_ret=$((_tr_ret + 1)); echo "E:post-validate"; continue fi echo "OK" done log2_or_0_return ${_tr_ret} } # # particular test variations +# -C +# -S +# -X +# -W ... see usage # stdin: granular test specification(s) if any # test2to3() { _t23_pattern= while read _t23_spec; do _t23_spec=${_t23_spec%.xml} _t23_spec=${_t23_spec%\*} _t23_pattern="${_t23_pattern} -name ${_t23_spec}*.xml -o" done test -z "${_t23_pattern}" || _t23_pattern="( ${_t23_pattern%-o} )" find test-2 -name test-2 -o -type d -prune \ -o -name '*.xml' ${_t23_pattern} -print | env LC_ALL=C sort \ | { case " $* " in *\ -C\ *) test_cleaner;; *\ -S\ *) test_selfcheck -o=2.10;; *\ -X\ *) test_explanation -o=2.10;; *\ -W\ *) test_browser;; *) test_runner -o=2.10 -t=3.0 "$@" || return $?;; esac; } } tests="${tests} test2to3" +test2to3enter() { + _t23e_pattern= + + while read _t23e_spec; do + _t23e_spec=${_t23e_spec%.xml} + _t23e_spec=${_t23e_spec%\*} + _t23e_pattern="${_t23e_pattern} -name ${_t23e_spec}*.xml -o" + done + test -z "${_t23e_pattern}" || _t23e_pattern="( ${_t23e_pattern%-o} )" + + find test-2-enter -name test-2-enter -o -type d -prune \ + -o -name '*.xml' ${_t23e_pattern} -print | env LC_ALL=C sort \ + | { case " $* " in + *\ -C\ *) test_cleaner;; + *\ -S\ *) test_selfcheck -a=enter -o=2.10;; + *\ -W\ *) emit_result "not implemented" "option -W";; + *\ -X\ *) emit_result "not implemented" "option -X";; + *) test_runner -a=2.10-enter -o=2.10 -t=2.10 "$@" || return $?;; + esac; } +} +tests="${tests} test2to3enter" + +test2to3leave() { + _t23l_pattern= + + while read _t23l_spec; do + _t23l_spec=${_t23l_spec%.xml} + _t23l_spec=${_t23l_spec%\*} + _t23l_pattern="${_t23l_pattern} -name ${_t23l_spec}*.xml -o" + done + test -z "${_t23l_pattern}" || _t23l_pattern="( ${_t23l_pattern%-o} )" + + find test-2-leave -name test-2-leave -o -type d -prune \ + -o -name '*.xml' ${_t23l_pattern} -print | env LC_ALL=C sort \ + | { case " $* " in + *\ -C\ *) test_cleaner;; + *\ -S\ *) test_selfcheck -a=leave -o=2.10;; + *\ -W\ *) emit_result "not implemented" "option -W";; + *\ -X\ *) emit_result "not implemented" "option -X";; + *) test_runner -a=2.10-leave -o=3.0 -t=3.0 "$@" || return $?;; + esac; } +} +tests="${tests} test2to3leave" + +test2to3roundtrip() { + _t23rt_pattern= + + while read _t23tr_spec; do + _t23rt_spec=${_t23rt_spec%.xml} + _t23rt_spec=${_t23rt_spec%\*} + _t23rt_pattern="${_t23rt_pattern} -name ${_t23rt_spec}*.xml -o" + done + test -z "${_t23rt_pattern}" || _t23rt_pattern="( ${_t23rt_pattern%-o} )" + + find test-2-roundtrip -name test-2-roundtrip -o -type d -prune \ + -o -name '*.xml' ${_t23rt_pattern} -print | env LC_ALL=C sort \ + | { case " $* " in + *\ -C\ *) test_cleaner;; + *\ -S\ *) test_selfcheck -a=roundtrip -o=2.10;; + *\ -W\ *) test_browser;; + *\ -X\ *) emit_result "not implemented" "option -X";; + *) test_runner -a=2.10-roundtrip -o=2.10 -t=3.0 "$@" || return $?;; + esac; } +} +tests="${tests} test2to3roundtrip" + # -B # -D # -G ... see usage cts_scheduler() { _tcp_mode=0 _tcp_ret=0 _tcp_validatewith= _tcp_schema_o= _tcp_schema_t= _tcp_template= find ../cts/scheduler -name scheduler -o -type d -prune \ -o -name '*.xml' -print | env LC_ALL=C sort \ | { case " $* " in *\ -C\ *) test_cleaner -r;; *\ -S\ *) emit_result "not implemented" "option -S";; + *\ -W\ *) emit_result "not implemented" "option -W";; *\ -X\ *) emit_result "not implemented" "option -X";; *) while test $# -gt 0; do case "$1" in -G) _tcp_mode=$((_tcp_mode | (1 << 0)));; -D) _tcp_mode=$((_tcp_mode | (1 << 1)));; -B) _tcp_mode=$((_tcp_mode | (1 << 2)));; esac shift done while read _tcp_origin; do _tcp_validatewith=$(${XSLTPROCESSOR} - "${_tcp_origin}" <<-EOF EOF ) _tcp_schema_t=${_tcp_validatewith} case "${_tcp_validatewith}" in 1) _tcp_schema_o=1.3;; 2) _tcp_schema_o=2.10;; # only for gradual refinement as upgrade-2.10.xsl under # active development, move to 3.x when schema v4 emerges 3) _tcp_schema_o=2.10 _tcp_schema_t=2;; *) emit_error \ "need to skip ${_tcp_origin} (schema: ${_tcp_validatewith})" continue;; esac _tcp_template="upgrade-${_tcp_schema_o}.xsl" _tcp_schema_t="pacemaker-$((_tcp_schema_t + 1)).0.rng" test "${_tcp_schema_o%%.*}" = "${_tcp_validatewith}" \ && _tcp_schema_o="pacemaker-${_tcp_schema_o}.rng" \ || _tcp_schema_o="${_tcp_schema_t}" # pre-validate if test "${_tcp_schema_o}" != "${_tcp_schema_t}" \ && ! test_runner_validate "${_tcp_schema_o}" "${_tcp_origin}"; then _tcp_ret=$((_tcp_ret + 1)); echo "E:pre-validate"; continue fi # upgrade test "$((_tcp_mode & (1 << 0)))" -ne 0 \ || ln -fs "$(pwd)/${_tcp_origin}" "${_tcp_origin%.*}.ref" if ! _tcp_target=$(test_runner_upgrade "${_tcp_template}" \ "${_tcp_origin}" "${_tcp_mode}"); then _tcp_ret=$((_tcp_ret + 1)); test -n "${_tcp_target}" || break echo "E:upgrade" test -s "${_tcp_target}" \ && { echo ---; cat "${_tcp_target}" || :; echo ---; } continue fi test "$((_tcp_mode & (1 << 0)))" -ne 0 \ || rm -f "${_tcp_origin%.*}.ref" # post-validate if ! test_runner_validate "${_tcp_schema_t}" "${_tcp_target}"; then _tcp_ret=$((_tcp_ret + 1)); echo "E:post-validate"; continue fi test "$((_tcp_mode & (1 << 0)))" -eq 0 \ || mv "${_tcp_target}" "${_tcp_origin}" done; log2_or_0_return ${_tcp_ret};; esac; } } tests="${tests} cts_scheduler" # # "framework" # # option-likes ... options to be passed down # argument-likes ... drives a test selection test_suite() { _ts_pass= _ts_select= _ts_select_full= _ts_test_specs= _ts_global_ret=0 _ts_ret=0 while test $# -gt 0; do case "$1" in -) printf '%s\n' 'waiting for tests specified at stdin...'; while read _ts_spec; do _ts_select="${_ts_spec}@$1"; done;; -*) _ts_pass="${_ts_pass} $1";; *) _ts_select_full="${_ts_select_full}@$1" _ts_select="${_ts_select}@${1%%/*}";; esac shift done _ts_select="${_ts_select}@" _ts_select_full="${_ts_select_full}@" for _ts_test in ${tests}; do while true; do case "${_ts_select}" in *@${_ts_test}@*) _ts_select="${_ts_select%@${_ts_test}@*}"\ "@${_ts_select#*@${_ts_test}@}" break ;; @) case "${_ts_test}" in test*) break;; esac ;; esac continue 2 # move on to matching with next local test done _ts_test_specs= while true; do case "${_ts_select_full}" in *@${_ts_test}/*) _ts_test_full="${_ts_test}/${_ts_select_full#*@${_ts_test}/}" _ts_test_full="${_ts_test_full%%@*}" _ts_select_full="${_ts_select_full%@${_ts_test_full}@*}"\ "@${_ts_select_full#*@${_ts_test_full}@}" _ts_test_specs="${_ts_test_specs} ${_ts_test_full#*/}" ;; *) break ;; esac done for _ts_test_spec in ${_ts_test_specs}; do printf '%s\n' "${_ts_test_spec}" done | "${_ts_test}" ${_ts_pass} || _ts_ret=$? test ${_ts_ret} = 0 \ && emit_result ${_ts_ret} "${_ts_test}" \ || emit_result "at least 2^$((_ts_ret - 1))" "${_ts_test}" log2_or_0_add ${_ts_global_ret} ${_ts_ret} _ts_global_ret=$? done if test "${_ts_select}" != @; then emit_error "Non-existing test(s):$(echo "${_ts_select}" \ | tr '@' ' ')" log2_or_0_add ${_ts_global_ret} 1 || _ts_global_ret=$? fi return ${_ts_global_ret} } # NOTE: big letters are dedicated for per-test-set behaviour, # small ones for generic/global behaviour usage() { printf \ - '%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ - "usage: $0 [-{B,C,D,G,S,X}]* [-|{${tests## }}*]" \ + '%s\n%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ + "usage: $0 [-{B,C,D,G,S,X}]* \\" \ + " [-|{${tests## }}*]" \ "- when no suites (arguments) provided, \"test*\" ones get used" \ "- with '-' suite specification the actual ones grabbed on stdin" \ "- use '-B' to run validate-only check suppressing blanks first" \ "- use '-C' to only cleanup ephemeral byproducts" \ "- use '-D' to review originals vs. \"referential\" outcomes" \ "- use '-G' to generate \"referential\" outcomes" \ "- use '-S' for template self-check (requires net access)" \ "- use '-W' to run browser-based, on-the-fly diff'ing test drive" \ "- use '-X' to show explanatory details about the upgrade" \ "- test specification can be granular, e.g. 'test2to3/022'" printf \ '\n%s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n' \ 'environment variables affecting the run + default/current values:' \ "- DIFF (${DIFF}): tool to compute and show differences of 2 files" \ "- DIFFOPTS (${DIFFOPTS}): options to the above tool" \ "- DIFFPAGER (${DIFFPAGER}): possibly accompanying the above tool" \ "- RNGVALIDATOR (${RNGVALIDATOR}): RelaxNG validator" \ "- XSLTPROCESSOR (${_XSLTPROCESSOR}): XSLT 1.0 capable processor" \ "- HTTPPORT (${HTTPPORT}): port used by test drive HTTP server run" \ "- WEBBROWSER (${WEBBROWSER}): used for in-browser test drive" } main() { _main_pass= _main_bailout=0 _main_ret=0 while test $# -gt 0; do case "$1" in -h) usage; exit;; -C|-G|-S|-X) _main_bailout=1;; esac _main_pass="${_main_pass} $1" shift done test_suite ${_main_pass} || _main_ret=$? - test ${_main_bailout} -eq 1 && return ${_main_ret} \ + test ${_main_bailout} -ne 0 \ || test_suite -C ${_main_pass} >/dev/null || true test ${_main_ret} = 0 && emit_result ${_main_ret} "Overall suite" \ || emit_result "at least 2^$((_main_ret - 1))" "Overall suite" return ${_main_ret} } main "$@" diff --git a/xml/resources-3.0.rng b/xml/resources-3.0.rng index 3000b78208..f5b915833b 100644 --- a/xml/resources-3.0.rng +++ b/xml/resources-3.0.rng @@ -1,465 +1,465 @@ - + isolation isolation-host isolation-instance isolation-wrapper pcmk_arg_map pcmk_list_cmd pcmk_monitor_cmd pcmk_off_cmd pcmk_on_cmd pcmk_reboot_cmd pcmk_status_cmd ([0-9\-]+) requires interval-origin start-delay enabled on-fail record-pending role timeout requires Stopped Started Slave Master ignore block stop restart standby fence restart-container ocf lsb heartbeat stonith upstart service systemd nagios diff --git a/xml/resources-3.0.rng b/xml/resources-3.1.rng similarity index 85% copy from xml/resources-3.0.rng copy to xml/resources-3.1.rng index 3000b78208..5558ee1fa9 100644 --- a/xml/resources-3.0.rng +++ b/xml/resources-3.1.rng @@ -1,465 +1,401 @@ - + isolation isolation-host isolation-instance isolation-wrapper - - - - - - - pcmk_arg_map - pcmk_list_cmd - pcmk_monitor_cmd - pcmk_off_cmd - pcmk_on_cmd - pcmk_reboot_cmd - pcmk_status_cmd - - - - - - - - - - - - - + ([0-9\-]+) requires - - - - - - - interval-origin - start-delay - - enabled - on-fail - record-pending - role - timeout - - requires - - - - - - - - - - - - - + Stopped Started Slave Master ignore block stop restart standby fence restart-container ocf lsb heartbeat stonith upstart service systemd nagios diff --git a/xml/test-2-enter/010-clu-props.ref b/xml/test-2-enter/010-clu-props.ref new file mode 100644 index 0000000000..86369fb3ab --- /dev/null +++ b/xml/test-2-enter/010-clu-props.ref @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/xml/test-2-enter/010-clu-props.ref.err b/xml/test-2-enter/010-clu-props.ref.err new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xml/test-2-enter/010-clu-props.xml b/xml/test-2-enter/010-clu-props.xml new file mode 100644 index 0000000000..e44f4dbc12 --- /dev/null +++ b/xml/test-2-enter/010-clu-props.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/xml/test-2-enter/020-instance_atributes-rsc.ref b/xml/test-2-enter/020-instance_atributes-rsc.ref new file mode 100644 index 0000000000..e746319593 --- /dev/null +++ b/xml/test-2-enter/020-instance_atributes-rsc.ref @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/test-2-enter/020-instance_atributes-rsc.ref.err b/xml/test-2-enter/020-instance_atributes-rsc.ref.err new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xml/test-2-enter/020-instance_atributes-rsc.xml b/xml/test-2-enter/020-instance_atributes-rsc.xml new file mode 100644 index 0000000000..0a651d0e95 --- /dev/null +++ b/xml/test-2-enter/020-instance_atributes-rsc.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/test-2-enter/021-instance_atributes-rsc-nonbijective.ref b/xml/test-2-enter/021-instance_atributes-rsc-nonbijective.ref new file mode 100644 index 0000000000..3a94fb075d --- /dev/null +++ b/xml/test-2-enter/021-instance_atributes-rsc-nonbijective.ref @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/test-2-enter/021-instance_atributes-rsc-nonbijective.ref.err b/xml/test-2-enter/021-instance_atributes-rsc-nonbijective.ref.err new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xml/test-2-enter/021-instance_atributes-rsc-nonbijective.xml b/xml/test-2-enter/021-instance_atributes-rsc-nonbijective.xml new file mode 100644 index 0000000000..7a12ebe403 --- /dev/null +++ b/xml/test-2-enter/021-instance_atributes-rsc-nonbijective.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/test-2-leave/010-clu-props-can.ref b/xml/test-2-leave/010-clu-props-can.ref new file mode 100644 index 0000000000..afa924d4db --- /dev/null +++ b/xml/test-2-leave/010-clu-props-can.ref @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/xml/test-2-leave/010-clu-props-can.ref.err b/xml/test-2-leave/010-clu-props-can.ref.err new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xml/test-2-leave/010-clu-props-can.xml b/xml/test-2-leave/010-clu-props-can.xml new file mode 100644 index 0000000000..cd82fa8eff --- /dev/null +++ b/xml/test-2-leave/010-clu-props-can.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/xml/test-2-leave/011-clu-props-cannot.ref b/xml/test-2-leave/011-clu-props-cannot.ref new file mode 100644 index 0000000000..c129f57df5 --- /dev/null +++ b/xml/test-2-leave/011-clu-props-cannot.ref @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/xml/test-2-leave/011-clu-props-cannot.ref.err b/xml/test-2-leave/011-clu-props-cannot.ref.err new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xml/test-2-leave/011-clu-props-cannot.xml b/xml/test-2-leave/011-clu-props-cannot.xml new file mode 100644 index 0000000000..c129f57df5 --- /dev/null +++ b/xml/test-2-leave/011-clu-props-cannot.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/xml/test-2-leave/021-instance_atributes-rsc-nonbijective.ref b/xml/test-2-leave/021-instance_atributes-rsc-nonbijective.ref new file mode 100644 index 0000000000..93ac06f674 --- /dev/null +++ b/xml/test-2-leave/021-instance_atributes-rsc-nonbijective.ref @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/test-2-leave/021-instance_atributes-rsc-nonbijective.ref.err b/xml/test-2-leave/021-instance_atributes-rsc-nonbijective.ref.err new file mode 100644 index 0000000000..70adf2787b --- /dev/null +++ b/xml/test-2-leave/021-instance_atributes-rsc-nonbijective.ref.err @@ -0,0 +1 @@ +DEBUG: instance_attributes: original element pointed to with @id-ref (mySmartFuse-outputpower-instanceparams) disappeared during upgrade diff --git a/xml/test-2-leave/021-instance_atributes-rsc-nonbijective.xml b/xml/test-2-leave/021-instance_atributes-rsc-nonbijective.xml new file mode 100644 index 0000000000..93ac06f674 --- /dev/null +++ b/xml/test-2-leave/021-instance_atributes-rsc-nonbijective.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/test-2-roundtrip/021-instance_atributes-rsc-nonbijective.ref b/xml/test-2-roundtrip/021-instance_atributes-rsc-nonbijective.ref new file mode 100644 index 0000000000..ee5819d59b --- /dev/null +++ b/xml/test-2-roundtrip/021-instance_atributes-rsc-nonbijective.ref @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/test-2-roundtrip/021-instance_atributes-rsc-nonbijective.ref.err b/xml/test-2-roundtrip/021-instance_atributes-rsc-nonbijective.ref.err new file mode 100644 index 0000000000..68de733116 --- /dev/null +++ b/xml/test-2-roundtrip/021-instance_atributes-rsc-nonbijective.ref.err @@ -0,0 +1,5 @@ +INFO: Resources-operation instance_attributes: mySmartFuse-monitor-inputpower (rsc=mySmartFuse, meta=mySmartFuse-inputpower-instanceparams): dropping requires +INFO: Resources-operation instance_attributes: ... only start/promote operation taken into account +INFO: Resources-operation instance_attributes: mySmartFuse-monitor-outputpower (rsc=mySmartFuse, meta=mySmartFuse-outputpower-instanceparams): dropping requires +INFO: Resources-operation instance_attributes: ... only start/promote operation taken into account +DEBUG: instance_attributes: original element pointed to with @id-ref (mySmartFuse-outputpower-instanceparams) disappeared during upgrade diff --git a/xml/test-2-roundtrip/021-instance_atributes-rsc-nonbijective.xml b/xml/test-2-roundtrip/021-instance_atributes-rsc-nonbijective.xml new file mode 100644 index 0000000000..a5d25a5c34 --- /dev/null +++ b/xml/test-2-roundtrip/021-instance_atributes-rsc-nonbijective.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.ref.err b/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.ref.err index 95985d568f..50791bf19c 100644 --- a/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.ref.err +++ b/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.ref.err @@ -1,2 +1,2 @@ -Constraints-colocation: colocation-addr-httpd: dropping score-attribute -Constraints-colocation: ... was actually never in effect +INFO: Constraints-colocation: colocation-addr-httpd: dropping score-attribute +INFO: Constraints-colocation: ... was actually never in effect diff --git a/xml/test-2/020-rsc-requires-inline.ref.err b/xml/test-2/020-rsc-requires-inline.ref.err index a13b4f27bd..9c6569747d 100644 --- a/xml/test-2/020-rsc-requires-inline.ref.err +++ b/xml/test-2/020-rsc-requires-inline.ref.err @@ -1 +1 @@ -Resources-operation: myAddr-start (rsc=myAddr): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: myAddr-start (rsc=myAddr): moving requires under meta_attributes as requires unless already defined there for matching start|promote diff --git a/xml/test-2/021-rsc-requires-nvpair.ref.err b/xml/test-2/021-rsc-requires-nvpair.ref.err index 9a04c4732e..6650f159f3 100644 --- a/xml/test-2/021-rsc-requires-nvpair.ref.err +++ b/xml/test-2/021-rsc-requires-nvpair.ref.err @@ -1 +1 @@ -Resources-operation: myAddr-start (rsc=myAddr, meta=myAddr-start-metaparams): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: myAddr-start (rsc=myAddr, meta=myAddr-start-metaparams): moving requires under meta_attributes as requires unless already defined there for matching start|promote diff --git a/xml/test-2/022-rsc-requires-counterexamples.ref.err b/xml/test-2/022-rsc-requires-counterexamples.ref.err index 5f89215b1b..6f6a9954fb 100644 --- a/xml/test-2/022-rsc-requires-counterexamples.ref.err +++ b/xml/test-2/022-rsc-requires-counterexamples.ref.err @@ -1,2 +1,2 @@ -Resources-operation: myAddr-stop (rsc=myAddr): dropping requires -Resources-operation: ... only start/promote operation taken into account +INFO: Resources-operation: myAddr-stop (rsc=myAddr): dropping requires +INFO: Resources-operation: ... only start/promote operation taken into account diff --git a/xml/test-2/023-rsc-requires-no-override.ref.err b/xml/test-2/023-rsc-requires-no-override.ref.err index 100fab93c6..ad680b6302 100644 --- a/xml/test-2/023-rsc-requires-no-override.ref.err +++ b/xml/test-2/023-rsc-requires-no-override.ref.err @@ -1,4 +1,4 @@ -Resources-operation: myAddr-start (rsc=myAddr): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: stateful-promote (rsc=stateful, meta=stateful-promote-meta): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: stateful-demote (rsc=stateful, meta=stateful-demote-meta): dropping requires -Resources-operation: ... only start/promote operation taken into account +DEBUG: Resources-operation: myAddr-start (rsc=myAddr): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: stateful-promote (rsc=stateful, meta=stateful-promote-meta): moving requires under meta_attributes as requires unless already defined there for matching start|promote +INFO: Resources-operation: stateful-demote (rsc=stateful, meta=stateful-demote-meta): dropping requires +INFO: Resources-operation: ... only start/promote operation taken into account diff --git a/xml/test-2/024-rsc-requires-no-selfclash.ref.err b/xml/test-2/024-rsc-requires-no-selfclash.ref.err index 49d9683336..b275532b33 100644 --- a/xml/test-2/024-rsc-requires-no-selfclash.ref.err +++ b/xml/test-2/024-rsc-requires-no-selfclash.ref.err @@ -1,14 +1,14 @@ -Resources-operation: myAddr1-start (rsc=myAddr1, meta=myAddr1-start-meta): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: myAddr1-start (rsc=myAddr1): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: myAddr2-start (rsc=myAddr2, meta=myAddr2-start-meta): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: myAddr2-start (rsc=myAddr2): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: stateful1-demote (rsc=stateful1, meta=stateful1-demote-meta): dropping requires -Resources-operation: ... only start/promote operation taken into account -Resources-operation: stateful1-promote (rsc=stateful1): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: stateful1-start (rsc=stateful1): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: stateful2-promote (rsc=stateful2, meta=stateful2-promote-meta1): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: stateful2-promote (rsc=stateful2, meta=stateful2-promote-meta1): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: stateful2-promote (rsc=stateful2, meta=stateful2-promote-meta2): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: stateful2-start (rsc=stateful2, meta=stateful2-promote-meta3): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: stateful2-demote (rsc=stateful2, meta=stateful2-promote-meta): dropping requires -Resources-operation: ... only start/promote operation taken into account +DEBUG: Resources-operation: myAddr1-start (rsc=myAddr1, meta=myAddr1-start-meta): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: myAddr1-start (rsc=myAddr1): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: myAddr2-start (rsc=myAddr2, meta=myAddr2-start-meta): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: myAddr2-start (rsc=myAddr2): moving requires under meta_attributes as requires unless already defined there for matching start|promote +INFO: Resources-operation: stateful1-demote (rsc=stateful1, meta=stateful1-demote-meta): dropping requires +INFO: Resources-operation: ... only start/promote operation taken into account +DEBUG: Resources-operation: stateful1-promote (rsc=stateful1): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: stateful1-start (rsc=stateful1): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: stateful2-promote (rsc=stateful2, meta=stateful2-promote-meta1): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: stateful2-promote (rsc=stateful2, meta=stateful2-promote-meta1): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: stateful2-promote (rsc=stateful2, meta=stateful2-promote-meta2): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: stateful2-start (rsc=stateful2, meta=stateful2-promote-meta3): moving requires under meta_attributes as requires unless already defined there for matching start|promote +INFO: Resources-operation: stateful2-demote (rsc=stateful2, meta=stateful2-promote-meta): dropping requires +INFO: Resources-operation: ... only start/promote operation taken into account diff --git a/xml/test-2/030-clu-props-plain-rename.ref.err b/xml/test-2/030-clu-props-plain-rename.ref.err index 32306f9f53..878c504320 100644 --- a/xml/test-2/030-clu-props-plain-rename.ref.err +++ b/xml/test-2/030-clu-props-plain-rename.ref.err @@ -1,13 +1,13 @@ -Cluster properties: cluster-opts-cluster_recheck_interval: renaming cluster_recheck_interval as cluster-recheck-interval -Cluster properties: cluster-opts-dc_deadtime: renaming dc_deadtime as dc-deadtime -Cluster properties: cluster-opts-election_timeout: renaming election_timeout as election-timeout -Cluster properties: cluster-opts-no_quorum_policy: renaming no_quorum_policy as no-quorum-policy -Cluster properties: cluster-opts-remove_after_stop: renaming remove_after_stop as remove-after-stop -Cluster properties: cluster-opts-shutdown_escalation: renaming shutdown_escalation as shutdown-escalation -Cluster properties: cluster-opts-startup_fencing: renaming startup_fencing as startup-fencing -Cluster properties: cluster-opts-stonith_action: renaming stonith_action as stonith-action -Cluster properties: cluster-opts-stonith_enabled: renaming stonith_enabled as stonith-enabled -Cluster properties: cluster-opts-stop_orphan_actions: renaming stop_orphan_actions as stop-orphan-actions -Cluster properties: cluster-opts-stop_orphan_resources: renaming stop_orphan_resources as stop-orphan-resources -Cluster properties: cluster-opts-symmetric_cluster: renaming symmetric_cluster as symmetric-cluster -Cluster properties: cluster-opts-transition_idle_timeout: renaming transition_idle_timeout as cluster-delay +DEBUG: Cluster properties: cluster-opts-cluster_recheck_interval: renaming cluster_recheck_interval as cluster-recheck-interval +DEBUG: Cluster properties: cluster-opts-dc_deadtime: renaming dc_deadtime as dc-deadtime +DEBUG: Cluster properties: cluster-opts-election_timeout: renaming election_timeout as election-timeout +DEBUG: Cluster properties: cluster-opts-no_quorum_policy: renaming no_quorum_policy as no-quorum-policy +DEBUG: Cluster properties: cluster-opts-remove_after_stop: renaming remove_after_stop as remove-after-stop +DEBUG: Cluster properties: cluster-opts-shutdown_escalation: renaming shutdown_escalation as shutdown-escalation +DEBUG: Cluster properties: cluster-opts-startup_fencing: renaming startup_fencing as startup-fencing +DEBUG: Cluster properties: cluster-opts-stonith_action: renaming stonith_action as stonith-action +DEBUG: Cluster properties: cluster-opts-stonith_enabled: renaming stonith_enabled as stonith-enabled +DEBUG: Cluster properties: cluster-opts-stop_orphan_actions: renaming stop_orphan_actions as stop-orphan-actions +DEBUG: Cluster properties: cluster-opts-stop_orphan_resources: renaming stop_orphan_resources as stop-orphan-resources +DEBUG: Cluster properties: cluster-opts-symmetric_cluster: renaming symmetric_cluster as symmetric-cluster +DEBUG: Cluster properties: cluster-opts-transition_idle_timeout: renaming transition_idle_timeout as cluster-delay diff --git a/xml/test-2/031-clu-props-drop.ref.err b/xml/test-2/031-clu-props-drop.ref.err index ca172ef2db..b26de82fc4 100644 --- a/xml/test-2/031-clu-props-drop.ref.err +++ b/xml/test-2/031-clu-props-drop.ref.err @@ -1,10 +1,10 @@ -Cluster properties: cluster-opts-cluster-infrastructure: dropping cluster-infrastructure for matching heartbeat|openais|classic openais|classic openais (with plugin)|cman -Cluster properties: ... corosync (2+) infrastructure can be used instead, though the value is not of significance -Cluster properties: cluster-opts-default-migration-threshold: dropping default-migration-threshold -Cluster properties: ... migration-threshold in rsc_defaults can be configured instead -Cluster properties: cluster-opts-default_migration_threshold: dropping default_migration_threshold -Cluster properties: ... migration-threshold in rsc_defaults can be configured instead -Cluster properties: cluster-opts-expected-quorum-votes: dropping expected-quorum-votes -Cluster properties: ... corosync (2+) infrastructure tracks quorum on its own -Cluster properties: cluster-opts-notification-agent: dropping notification-agent -Cluster properties: ... standalone alerts can be configured instead +INFO: Cluster properties: cluster-opts-cluster-infrastructure: dropping cluster-infrastructure for matching heartbeat|openais|classic openais|classic openais (with plugin)|cman +INFO: Cluster properties: ... corosync (2+) infrastructure can be used instead, though the value is not of significance +INFO: Cluster properties: cluster-opts-default-migration-threshold: dropping default-migration-threshold +INFO: Cluster properties: ... migration-threshold in rsc_defaults can be configured instead +INFO: Cluster properties: cluster-opts-default_migration_threshold: dropping default_migration_threshold +INFO: Cluster properties: ... migration-threshold in rsc_defaults can be configured instead +INFO: Cluster properties: cluster-opts-expected-quorum-votes: dropping expected-quorum-votes +INFO: Cluster properties: ... corosync (2+) infrastructure tracks quorum on its own +INFO: Cluster properties: cluster-opts-notification-agent: dropping notification-agent +INFO: Cluster properties: ... standalone alerts can be configured instead diff --git a/xml/test-2/032-clu-props-move.ref.err b/xml/test-2/032-clu-props-move.ref.err index 417b355df6..ed5d3d3e28 100644 --- a/xml/test-2/032-clu-props-move.ref.err +++ b/xml/test-2/032-clu-props-move.ref.err @@ -1,3 +1,3 @@ -Cluster properties: cluster-opts-default-action-timeout: moving default-action-timeout under op_defaults as timeout unless already defined there -Cluster properties: cluster-opts-default-resource-stickiness: moving default-resource-stickiness under rsc_defaults as resource-stickiness unless already defined there -Cluster properties: cluster-opts-is-managed-default: moving is-managed-default under rsc_defaults as is-managed unless already defined there +DEBUG: Cluster properties: cluster-opts-default-action-timeout: moving default-action-timeout under op_defaults as timeout unless already defined there +DEBUG: Cluster properties: cluster-opts-default-resource-stickiness: moving default-resource-stickiness under rsc_defaults as resource-stickiness unless already defined there +DEBUG: Cluster properties: cluster-opts-is-managed-default: moving is-managed-default under rsc_defaults as is-managed unless already defined there diff --git a/xml/test-2/033-clu-props-move-merge.ref.err b/xml/test-2/033-clu-props-move-merge.ref.err index 417b355df6..ed5d3d3e28 100644 --- a/xml/test-2/033-clu-props-move-merge.ref.err +++ b/xml/test-2/033-clu-props-move-merge.ref.err @@ -1,3 +1,3 @@ -Cluster properties: cluster-opts-default-action-timeout: moving default-action-timeout under op_defaults as timeout unless already defined there -Cluster properties: cluster-opts-default-resource-stickiness: moving default-resource-stickiness under rsc_defaults as resource-stickiness unless already defined there -Cluster properties: cluster-opts-is-managed-default: moving is-managed-default under rsc_defaults as is-managed unless already defined there +DEBUG: Cluster properties: cluster-opts-default-action-timeout: moving default-action-timeout under op_defaults as timeout unless already defined there +DEBUG: Cluster properties: cluster-opts-default-resource-stickiness: moving default-resource-stickiness under rsc_defaults as resource-stickiness unless already defined there +DEBUG: Cluster properties: cluster-opts-is-managed-default: moving is-managed-default under rsc_defaults as is-managed unless already defined there diff --git a/xml/test-2/034-clu-props-move-redef.ref.err b/xml/test-2/034-clu-props-move-redef.ref.err index 85db6428f3..f8c148f382 100644 --- a/xml/test-2/034-clu-props-move-redef.ref.err +++ b/xml/test-2/034-clu-props-move-redef.ref.err @@ -1,3 +1,3 @@ -Cluster properties: cluster-opts-default-resource-failure-stickiness: moving default-resource-failure-stickiness under rsc_defaults as migration-threshold unless already defined there, redefined as 1, for matching -INFINITY -Cluster properties: cluster-opts-default_resource_failure_stickiness: dropping default_resource_failure_stickiness -Cluster properties: ... migration-threshold in rsc_defaults can be configured instead +DEBUG: Cluster properties: cluster-opts-default-resource-failure-stickiness: moving default-resource-failure-stickiness under rsc_defaults as migration-threshold unless already defined there, redefined as 1, for matching -INFINITY +INFO: Cluster properties: cluster-opts-default_resource_failure_stickiness: dropping default_resource_failure_stickiness +INFO: Cluster properties: ... migration-threshold in rsc_defaults can be configured instead diff --git a/xml/test-2/040-nodes-rename-type.ref.err b/xml/test-2/040-nodes-rename-type.ref.err index e5a6b64a36..ce68fa4e9e 100644 --- a/xml/test-2/040-nodes-rename-type.ref.err +++ b/xml/test-2/040-nodes-rename-type.ref.err @@ -1,2 +1,2 @@ -Cluster node: virt-063 (id=virt-063): keeping type as type, redefined as member, for matching normal -Cluster node: virt-064 (id=virt-064): keeping type as type, redefined as member, for matching normal +DEBUG: Cluster node: virt-063 (id=virt-063): keeping type as type, redefined as member, for matching normal +DEBUG: Cluster node: virt-064 (id=virt-064): keeping type as type, redefined as member, for matching normal diff --git a/xml/test-2/050-rsc-attrs-instance-plain-rename.ref.err b/xml/test-2/050-rsc-attrs-instance-plain-rename.ref.err index 2d3b3b8c50..a3129e54c9 100644 --- a/xml/test-2/050-rsc-attrs-instance-plain-rename.ref.err +++ b/xml/test-2/050-rsc-attrs-instance-plain-rename.ref.err @@ -1 +1 @@ -Resource instance_attributes: fence-vbox-pcmk_monitor_cmd: renaming pcmk_monitor_cmd as pcmk_monitor_action +DEBUG: Resource instance_attributes: fence-vbox-pcmk_monitor_cmd: renaming pcmk_monitor_cmd as pcmk_monitor_action diff --git a/xml/test-2/051-rsc-attrs-instance-pcmk_arg_map.ref.err b/xml/test-2/051-rsc-attrs-instance-pcmk_arg_map.ref.err index b7dfd08fea..a0149c1661 100644 --- a/xml/test-2/051-rsc-attrs-instance-pcmk_arg_map.ref.err +++ b/xml/test-2/051-rsc-attrs-instance-pcmk_arg_map.ref.err @@ -1,3 +1,3 @@ -Resource instance_attributes: fence-vbox1-pcmk_arg_map: renaming pcmk_arg_map as pcmk_host_argument for matching port: prefix that will, meanwhile, get dropped -Resource instance_attributes: fence-vbox2-pcmk_arg_map: dropping pcmk_arg_map -Resource instance_attributes: fence-vbox3-pcmk_arg_map: dropping pcmk_arg_map +DEBUG: Resource instance_attributes: fence-vbox1-pcmk_arg_map: renaming pcmk_arg_map as pcmk_host_argument for matching port: prefix that will, meanwhile, get dropped +DEBUG: Resource instance_attributes: fence-vbox2-pcmk_arg_map: dropping pcmk_arg_map +DEBUG: Resource instance_attributes: fence-vbox3-pcmk_arg_map: dropping pcmk_arg_map diff --git a/xml/test-2/060-rsc-attrs-meta-isolation.ref.err b/xml/test-2/060-rsc-attrs-meta-isolation.ref.err index 32533f92fd..fb40cc4a5f 100644 --- a/xml/test-2/060-rsc-attrs-meta-isolation.ref.err +++ b/xml/test-2/060-rsc-attrs-meta-isolation.ref.err @@ -1,4 +1,4 @@ -Resource meta_attributes: fake (meta=fake-meta_attributes): renaming isolation-wrapper as target-role, redefined as Stopped -Resource meta_attributes: ... i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources -Resource meta_attributes: fake (meta=fake-meta_attributes): renaming isolation-wrapper as target-role, redefined as Stopped -Resource meta_attributes: ... i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources +WARNING: Resource meta_attributes: fake (meta=fake-meta_attributes): renaming isolation-wrapper as target-role, redefined as Stopped +WARNING: Resource meta_attributes: ... i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources +WARNING: Resource meta_attributes: fake (meta=fake-meta_attributes): renaming isolation-wrapper as target-role, redefined as Stopped +WARNING: Resource meta_attributes: ... i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources diff --git a/xml/test-2/061-rsc-attrs-meta-exchange.ref.err b/xml/test-2/061-rsc-attrs-meta-exchange.ref.err index 03c7a6fcbd..2938b77b13 100644 --- a/xml/test-2/061-rsc-attrs-meta-exchange.ref.err +++ b/xml/test-2/061-rsc-attrs-meta-exchange.ref.err @@ -1,3 +1,3 @@ -Resource meta_attributes: res1 (meta=res1-meta_attributes): renaming resource-failure-stickiness as migration-threshold, redefined as 1, for matching -INFINITY -Resource meta_attributes: res2 (meta=res2-meta_attributes): dropping resource-failure-stickiness -Resource meta_attributes: ... migration-threshold can be configured instead +DEBUG: Resource meta_attributes: res1 (meta=res1-meta_attributes): renaming resource-failure-stickiness as migration-threshold, redefined as 1, for matching -INFINITY +INFO: Resource meta_attributes: res2 (meta=res2-meta_attributes): dropping resource-failure-stickiness +INFO: Resource meta_attributes: ... migration-threshold can be configured instead diff --git a/xml/test-2/070-rsc-op-attrs-inst-requires-start.ref.err b/xml/test-2/070-rsc-op-attrs-inst-requires-start.ref.err index 1aa7937627..6f707bbfda 100644 --- a/xml/test-2/070-rsc-op-attrs-inst-requires-start.ref.err +++ b/xml/test-2/070-rsc-op-attrs-inst-requires-start.ref.err @@ -1 +1 @@ -Resources-operation instance_attributes: myAddr-start (rsc=myAddr, meta=myAddr-start-instanceparams): moving requires under per-resource-meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation instance_attributes: myAddr-start (rsc=myAddr, meta=myAddr-start-instanceparams): moving requires under per-resource-meta_attributes as requires unless already defined there for matching start|promote diff --git a/xml/test-2/071-rsc-op-attrs-inst-requires-nonstart.ref.err b/xml/test-2/071-rsc-op-attrs-inst-requires-nonstart.ref.err index 0865c594da..6b6f8f7b19 100644 --- a/xml/test-2/071-rsc-op-attrs-inst-requires-nonstart.ref.err +++ b/xml/test-2/071-rsc-op-attrs-inst-requires-nonstart.ref.err @@ -1,2 +1,2 @@ -Resources-operation instance_attributes: myAddr-stop (rsc=myAddr, meta=myAddr-stop-instanceparams): dropping requires -Resources-operation instance_attributes: ... only start/promote operation taken into account +INFO: Resources-operation instance_attributes: myAddr-stop (rsc=myAddr, meta=myAddr-stop-instanceparams): dropping requires +INFO: Resources-operation instance_attributes: ... only start/promote operation taken into account diff --git a/xml/test-2/072-rsc-op-attrs-inst-requires-no-override.ref.err b/xml/test-2/072-rsc-op-attrs-inst-requires-no-override.ref.err index bacdc09be7..cc5dd7d22a 100644 --- a/xml/test-2/072-rsc-op-attrs-inst-requires-no-override.ref.err +++ b/xml/test-2/072-rsc-op-attrs-inst-requires-no-override.ref.err @@ -1,4 +1,4 @@ -Resources-operation instance_attributes: myAddr-start (rsc=myAddr, meta=myAddr-start-instance): moving requires under per-resource-meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: myAddr-start (rsc=myAddr): moving requires under meta_attributes as requires unless already defined there for matching start|promote -Resources-operation instance_attributes: stateful-promote (rsc=stateful, meta=stateful-promote-instance): moving requires under per-resource-meta_attributes as requires unless already defined there for matching start|promote -Resources-operation: stateful-promote (rsc=stateful, meta=stateful-promote-meta): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation instance_attributes: myAddr-start (rsc=myAddr, meta=myAddr-start-instance): moving requires under per-resource-meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: myAddr-start (rsc=myAddr): moving requires under meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation instance_attributes: stateful-promote (rsc=stateful, meta=stateful-promote-instance): moving requires under per-resource-meta_attributes as requires unless already defined there for matching start|promote +DEBUG: Resources-operation: stateful-promote (rsc=stateful, meta=stateful-promote-meta): moving requires under meta_attributes as requires unless already defined there for matching start|promote diff --git a/xml/test-2/073-rsc-op-attrs-inst-meta-meaning.ref.err b/xml/test-2/073-rsc-op-attrs-inst-meta-meaning.ref.err index 0410a57811..18beb3aefa 100644 --- a/xml/test-2/073-rsc-op-attrs-inst-meta-meaning.ref.err +++ b/xml/test-2/073-rsc-op-attrs-inst-meta-meaning.ref.err @@ -1,4 +1,4 @@ -Resources-operation instance_attributes: myAddr-start (rsc=myAddr, meta=myAddr-start-instance): moving on-fail under meta_attributes as on-fail unless already defined there -Resources-operation instance_attributes: myAddr-start (rsc=myAddr, meta=myAddr-start-instance): moving record-pending under meta_attributes as record-pending unless already defined there -Resources-operation instance_attributes: myHttpd-monitor (rsc=myHttpd, meta=myHttpd-monitor-instance): moving timeout under meta_attributes as timeout unless already defined there -Resources-operation instance_attributes: myHttpd-monitor (rsc=myHttpd, meta=myHttpd-monitor-instance2): moving timeout under meta_attributes as timeout unless already defined there +DEBUG: Resources-operation instance_attributes: myAddr-start (rsc=myAddr, meta=myAddr-start-instance): moving on-fail under meta_attributes as on-fail unless already defined there +DEBUG: Resources-operation instance_attributes: myAddr-start (rsc=myAddr, meta=myAddr-start-instance): moving record-pending under meta_attributes as record-pending unless already defined there +DEBUG: Resources-operation instance_attributes: myHttpd-monitor (rsc=myHttpd, meta=myHttpd-monitor-instance): moving timeout under meta_attributes as timeout unless already defined there +DEBUG: Resources-operation instance_attributes: myHttpd-monitor (rsc=myHttpd, meta=myHttpd-monitor-instance2): moving timeout under meta_attributes as timeout unless already defined there diff --git a/xml/upgrade-2.10-enter.xsl b/xml/upgrade-2.10-enter.xsl new file mode 100644 index 0000000000..e7eb1ba323 --- /dev/null +++ b/xml/upgrade-2.10-enter.xsl @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/upgrade-2.10-leave.xsl b/xml/upgrade-2.10-leave.xsl new file mode 100644 index 0000000000..6e3fe65eda --- /dev/null +++ b/xml/upgrade-2.10-leave.xsl @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A + P + + + + + + + + + + + C + T + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/upgrade-2.10-roundtrip.xsl b/xml/upgrade-2.10-roundtrip.xsl new file mode 100644 index 0000000000..18d73c8558 --- /dev/null +++ b/xml/upgrade-2.10-roundtrip.xsl @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/upgrade-2.10.xsl b/xml/upgrade-2.10.xsl index 321b3c22ba..526ef6d2d9 100644 --- a/xml/upgrade-2.10.xsl +++ b/xml/upgrade-2.10.xsl @@ -1,2532 +1,2569 @@ + + + + + + + msg-extra="i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources" + msg-severity="WARNING"/> + msg-extra="i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources" + msg-severity="WARNING"/> + msg-extra="i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources" + msg-severity="WARNING"/> + msg-extra="i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources" + msg-severity="WARNING"/> - - - - - - + - - - - - - - - - - - - - - - - - - - - - + + + + + - + - - - - - - + + - - + + - - + + - - + + + + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +