diff --git a/cts/cli/regression.acls.exp b/cts/cli/regression.acls.exp index 182232844d..eaba0c6600 100644 --- a/cts/cli/regression.acls.exp +++ b/cts/cli/regression.acls.exp @@ -1,4398 +1,4398 @@ Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Configure some ACLs =#=#=#= =#=#=#= Current cib after: Configure some ACLs =#=#=#= =#=#=#= End test: Configure some ACLs - OK (0) =#=#=#= * Passed: cibadmin - Configure some ACLs =#=#=#= Begin test: Enable ACLs =#=#=#= =#=#=#= Current cib after: Enable ACLs =#=#=#= =#=#=#= End test: Enable ACLs - OK (0) =#=#=#= * Passed: crm_attribute - Enable ACLs =#=#=#= Begin test: Set cluster option =#=#=#= =#=#=#= Current cib after: Set cluster option =#=#=#= =#=#=#= End test: Set cluster option - OK (0) =#=#=#= * Passed: crm_attribute - Set cluster option =#=#=#= Begin test: New ACL =#=#=#= =#=#=#= Current cib after: New ACL =#=#=#= =#=#=#= End test: New ACL - OK (0) =#=#=#= * Passed: cibadmin - New ACL =#=#=#= Begin test: Another ACL =#=#=#= =#=#=#= Current cib after: Another ACL =#=#=#= =#=#=#= End test: Another ACL - OK (0) =#=#=#= * Passed: cibadmin - Another ACL =#=#=#= Begin test: Updated ACL =#=#=#= =#=#=#= Current cib after: Updated ACL =#=#=#= =#=#=#= End test: Updated ACL - OK (0) =#=#=#= * Passed: cibadmin - Updated ACL =#=#=#= Begin test: unknownguy: Query configuration =#=#=#= Call failed: Permission denied =#=#=#= End test: unknownguy: Query configuration - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - unknownguy: Query configuration =#=#=#= Begin test: unknownguy: Set enable-acl =#=#=#= crm_attribute: Error performing operation: Permission denied =#=#=#= End test: unknownguy: Set enable-acl - Insufficient privileges (4) =#=#=#= * Passed: crm_attribute - unknownguy: Set enable-acl =#=#=#= Begin test: unknownguy: Set stonith-enabled =#=#=#= crm_attribute: Error performing operation: Permission denied =#=#=#= End test: unknownguy: Set stonith-enabled - Insufficient privileges (4) =#=#=#= * Passed: crm_attribute - unknownguy: Set stonith-enabled =#=#=#= Begin test: unknownguy: Create a resource =#=#=#= pcmk__check_acl trace: User 'unknownguy' without ACLs denied read/write access to /cib/configuration/resources/primitive[@id='dummy'] pcmk__apply_creation_acl trace: ACLs disallow creation of with id="dummy" Call failed: Permission denied =#=#=#= End test: unknownguy: Create a resource - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - unknownguy: Create a resource =#=#=#= Begin test: l33t-haxor: Query configuration =#=#=#= Call failed: Permission denied =#=#=#= End test: l33t-haxor: Query configuration - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - l33t-haxor: Query configuration =#=#=#= Begin test: l33t-haxor: Set enable-acl =#=#=#= crm_attribute: Error performing operation: Permission denied =#=#=#= End test: l33t-haxor: Set enable-acl - Insufficient privileges (4) =#=#=#= * Passed: crm_attribute - l33t-haxor: Set enable-acl =#=#=#= Begin test: l33t-haxor: Set stonith-enabled =#=#=#= crm_attribute: Error performing operation: Permission denied =#=#=#= End test: l33t-haxor: Set stonith-enabled - Insufficient privileges (4) =#=#=#= * Passed: crm_attribute - l33t-haxor: Set stonith-enabled =#=#=#= Begin test: l33t-haxor: Create a resource =#=#=#= pcmk__check_acl trace: Parent ACL denies user 'l33t-haxor' read/write access to /cib/configuration/resources/primitive[@id='dummy'] pcmk__apply_creation_acl trace: ACLs disallow creation of with id="dummy" Call failed: Permission denied =#=#=#= End test: l33t-haxor: Create a resource - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - l33t-haxor: Create a resource =#=#=#= Begin test: niceguy: Query configuration =#=#=#= - + =#=#=#= End test: niceguy: Query configuration - OK (0) =#=#=#= * Passed: cibadmin - niceguy: Query configuration =#=#=#= Begin test: niceguy: Set enable-acl =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value] Error setting enable-acl=false (section=crm_config, set=): Permission denied crm_attribute: Error performing operation: Permission denied =#=#=#= End test: niceguy: Set enable-acl - Insufficient privileges (4) =#=#=#= * Passed: crm_attribute - niceguy: Set enable-acl =#=#=#= Begin test: niceguy: Set stonith-enabled =#=#=#= pcmk__apply_creation_acl trace: ACLs allow creation of with id="cib-bootstrap-options-stonith-enabled" =#=#=#= Current cib after: niceguy: Set stonith-enabled =#=#=#= - + =#=#=#= End test: niceguy: Set stonith-enabled - OK (0) =#=#=#= * Passed: crm_attribute - niceguy: Set stonith-enabled =#=#=#= Begin test: niceguy: Create a resource =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/resources/primitive[@id='dummy'] pcmk__apply_creation_acl trace: ACLs disallow creation of with id="dummy" Call failed: Permission denied =#=#=#= End test: niceguy: Create a resource - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Create a resource =#=#=#= Begin test: root: Query configuration =#=#=#= - + =#=#=#= End test: root: Query configuration - OK (0) =#=#=#= * Passed: cibadmin - root: Query configuration =#=#=#= Begin test: root: Set stonith-enabled =#=#=#= =#=#=#= Current cib after: root: Set stonith-enabled =#=#=#= - + =#=#=#= End test: root: Set stonith-enabled - OK (0) =#=#=#= * Passed: crm_attribute - root: Set stonith-enabled =#=#=#= Begin test: root: Create a resource =#=#=#= =#=#=#= Current cib after: root: Create a resource =#=#=#= - + =#=#=#= End test: root: Create a resource - OK (0) =#=#=#= * Passed: cibadmin - root: Create a resource =#=#=#= Begin test: l33t-haxor: Create a resource meta attribute =#=#=#= crm_resource: Error performing operation: Insufficient privileges =#=#=#= End test: l33t-haxor: Create a resource meta attribute - Insufficient privileges (4) =#=#=#= * Passed: crm_resource - l33t-haxor: Create a resource meta attribute =#=#=#= Begin test: l33t-haxor: Query a resource meta attribute =#=#=#= crm_resource: Error performing operation: Insufficient privileges =#=#=#= End test: l33t-haxor: Query a resource meta attribute - Insufficient privileges (4) =#=#=#= * Passed: crm_resource - l33t-haxor: Query a resource meta attribute =#=#=#= Begin test: l33t-haxor: Remove a resource meta attribute =#=#=#= crm_resource: Error performing operation: Insufficient privileges =#=#=#= End test: l33t-haxor: Remove a resource meta attribute - Insufficient privileges (4) =#=#=#= * Passed: crm_resource - l33t-haxor: Remove a resource meta attribute =#=#=#= Begin test: niceguy: Create a resource meta attribute =#=#=#= 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 pcmk__apply_creation_acl trace: Creation of scaffolding with id="dummy-meta_attributes" is implicitly allowed pcmk__apply_creation_acl trace: ACLs allow creation of with id="dummy-meta_attributes-target-role" Set 'dummy' option: id=dummy-meta_attributes-target-role set=dummy-meta_attributes name=target-role value=Stopped =#=#=#= Current cib after: niceguy: Create a resource meta attribute =#=#=#= - + =#=#=#= End test: niceguy: Create a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Create a resource meta attribute =#=#=#= Begin test: niceguy: Query a resource meta attribute =#=#=#= 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 Stopped =#=#=#= Current cib after: niceguy: Query a resource meta attribute =#=#=#= - + =#=#=#= End test: niceguy: Query a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Query a resource meta attribute =#=#=#= Begin test: niceguy: Remove a resource meta attribute =#=#=#= 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 Deleted 'dummy' option: id=dummy-meta_attributes-target-role name=target-role =#=#=#= Current cib after: niceguy: Remove a resource meta attribute =#=#=#= - + =#=#=#= End test: niceguy: Remove a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Remove a resource meta attribute =#=#=#= Begin test: niceguy: Create a resource meta attribute =#=#=#= 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 pcmk__apply_creation_acl trace: ACLs allow creation of with id="dummy-meta_attributes-target-role" Set 'dummy' option: id=dummy-meta_attributes-target-role set=dummy-meta_attributes name=target-role value=Started =#=#=#= Current cib after: niceguy: Create a resource meta attribute =#=#=#= - + =#=#=#= End test: niceguy: Create a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Create a resource meta attribute =#=#=#= Begin test: badidea: Query configuration - implied deny =#=#=#= =#=#=#= End test: badidea: Query configuration - implied deny - OK (0) =#=#=#= * Passed: cibadmin - badidea: Query configuration - implied deny =#=#=#= Begin test: betteridea: Query configuration - explicit deny =#=#=#= =#=#=#= End test: betteridea: Query configuration - explicit deny - OK (0) =#=#=#= * Passed: cibadmin - betteridea: Query configuration - explicit deny - + =#=#=#= Begin test: niceguy: Replace - remove acls =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib[@epoch] pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/acls Call failed: Permission denied =#=#=#= End test: niceguy: Replace - remove acls - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Replace - remove acls - + =#=#=#= Begin test: niceguy: Replace - create resource =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib[@epoch] pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/resources/primitive[@id='dummy2'] pcmk__apply_creation_acl trace: ACLs disallow creation of with id="dummy2" Call failed: Permission denied =#=#=#= End test: niceguy: Replace - create resource - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Replace - create resource - + =#=#=#= Begin test: niceguy: Replace - modify attribute (deny) =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib[@epoch] pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value] Call failed: Permission denied =#=#=#= End test: niceguy: Replace - modify attribute (deny) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Replace - modify attribute (deny) - + =#=#=#= Begin test: niceguy: Replace - delete attribute (deny) =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib[@epoch] pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'] Call failed: Permission denied =#=#=#= End test: niceguy: Replace - delete attribute (deny) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Replace - delete attribute (deny) - + =#=#=#= Begin test: niceguy: Replace - create attribute (deny) =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib[@epoch] pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/resources/primitive[@id='dummy'][@description] Call failed: Permission denied =#=#=#= End test: niceguy: Replace - create attribute (deny) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Replace - create attribute (deny) - + =#=#=#= Begin test: bob: Replace - create attribute (direct allow) =#=#=#= =#=#=#= End test: bob: Replace - create attribute (direct allow) - OK (0) =#=#=#= * Passed: cibadmin - bob: Replace - create attribute (direct allow) - + =#=#=#= Begin test: bob: Replace - modify attribute (direct allow) =#=#=#= =#=#=#= End test: bob: Replace - modify attribute (direct allow) - OK (0) =#=#=#= * Passed: cibadmin - bob: Replace - modify attribute (direct allow) - + =#=#=#= Begin test: bob: Replace - delete attribute (direct allow) =#=#=#= =#=#=#= End test: bob: Replace - delete attribute (direct allow) - OK (0) =#=#=#= * Passed: cibadmin - bob: Replace - delete attribute (direct allow) - + =#=#=#= Begin test: joe: Replace - create attribute (inherited allow) =#=#=#= =#=#=#= End test: joe: Replace - create attribute (inherited allow) - OK (0) =#=#=#= * Passed: cibadmin - joe: Replace - create attribute (inherited allow) - + =#=#=#= Begin test: joe: Replace - modify attribute (inherited allow) =#=#=#= =#=#=#= End test: joe: Replace - modify attribute (inherited allow) - OK (0) =#=#=#= * Passed: cibadmin - joe: Replace - modify attribute (inherited allow) - + =#=#=#= Begin test: joe: Replace - delete attribute (inherited allow) =#=#=#= =#=#=#= End test: joe: Replace - delete attribute (inherited allow) - OK (0) =#=#=#= * Passed: cibadmin - joe: Replace - delete attribute (inherited allow) - + =#=#=#= Begin test: mike: Replace - create attribute (allow overrides deny) =#=#=#= =#=#=#= End test: mike: Replace - create attribute (allow overrides deny) - OK (0) =#=#=#= * Passed: cibadmin - mike: Replace - create attribute (allow overrides deny) - + =#=#=#= Begin test: mike: Replace - modify attribute (allow overrides deny) =#=#=#= =#=#=#= End test: mike: Replace - modify attribute (allow overrides deny) - OK (0) =#=#=#= * Passed: cibadmin - mike: Replace - modify attribute (allow overrides deny) - + =#=#=#= Begin test: mike: Replace - delete attribute (allow overrides deny) =#=#=#= =#=#=#= End test: mike: Replace - delete attribute (allow overrides deny) - OK (0) =#=#=#= * Passed: cibadmin - mike: Replace - delete attribute (allow overrides deny) - + =#=#=#= Begin test: chris: Replace - create attribute (deny overrides allow) =#=#=#= pcmk__check_acl trace: Parent ACL denies user 'chris' read/write access to /cib/configuration/resources/primitive[@id='dummy'][@description] Call failed: Permission denied =#=#=#= End test: chris: Replace - create attribute (deny overrides allow) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - chris: Replace - create attribute (deny overrides allow) - + =#=#=#= Begin test: chris: Replace - modify attribute (deny overrides allow) =#=#=#= pcmk__check_acl trace: Parent ACL denies user 'chris' read/write access to /cib/configuration/resources/primitive[@id='dummy'][@description] Call failed: Permission denied =#=#=#= End test: chris: Replace - modify attribute (deny overrides allow) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - chris: Replace - modify attribute (deny overrides allow) - + =#=#=#= Begin test: chris: Replace - delete attribute (deny overrides allow) =#=#=#= pcmk__check_acl trace: Parent ACL denies user 'chris' read/write access to /cib/configuration/resources/primitive[@id='dummy'] Call failed: Permission denied =#=#=#= End test: chris: Replace - delete attribute (deny overrides allow) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - chris: Replace - delete attribute (deny overrides allow) !#!#!#!#! Upgrading to latest CIB schema and re-testing !#!#!#!#! =#=#=#= Begin test: root: Upgrade to latest CIB schema =#=#=#= =#=#=#= Current cib after: root: Upgrade to latest CIB schema =#=#=#= =#=#=#= End test: root: Upgrade to latest CIB schema - OK (0) =#=#=#= * Passed: cibadmin - root: Upgrade to latest CIB schema =#=#=#= Begin test: unknownguy: Query configuration =#=#=#= Call failed: Permission denied =#=#=#= End test: unknownguy: Query configuration - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - unknownguy: Query configuration =#=#=#= Begin test: unknownguy: Set enable-acl =#=#=#= crm_attribute: Error performing operation: Permission denied =#=#=#= End test: unknownguy: Set enable-acl - Insufficient privileges (4) =#=#=#= * Passed: crm_attribute - unknownguy: Set enable-acl =#=#=#= Begin test: unknownguy: Set stonith-enabled =#=#=#= crm_attribute: Error performing operation: Permission denied =#=#=#= End test: unknownguy: Set stonith-enabled - Insufficient privileges (4) =#=#=#= * Passed: crm_attribute - unknownguy: Set stonith-enabled =#=#=#= Begin test: unknownguy: Create a resource =#=#=#= pcmk__check_acl trace: User 'unknownguy' without ACLs denied read/write access to /cib/configuration/resources/primitive[@id='dummy'] pcmk__apply_creation_acl trace: ACLs disallow creation of with id="dummy" Call failed: Permission denied =#=#=#= End test: unknownguy: Create a resource - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - unknownguy: Create a resource =#=#=#= Begin test: l33t-haxor: Query configuration =#=#=#= Call failed: Permission denied =#=#=#= End test: l33t-haxor: Query configuration - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - l33t-haxor: Query configuration =#=#=#= Begin test: l33t-haxor: Set enable-acl =#=#=#= crm_attribute: Error performing operation: Permission denied =#=#=#= End test: l33t-haxor: Set enable-acl - Insufficient privileges (4) =#=#=#= * Passed: crm_attribute - l33t-haxor: Set enable-acl =#=#=#= Begin test: l33t-haxor: Set stonith-enabled =#=#=#= crm_attribute: Error performing operation: Permission denied =#=#=#= End test: l33t-haxor: Set stonith-enabled - Insufficient privileges (4) =#=#=#= * Passed: crm_attribute - l33t-haxor: Set stonith-enabled =#=#=#= Begin test: l33t-haxor: Create a resource =#=#=#= pcmk__check_acl trace: Parent ACL denies user 'l33t-haxor' read/write access to /cib/configuration/resources/primitive[@id='dummy'] pcmk__apply_creation_acl trace: ACLs disallow creation of with id="dummy" Call failed: Permission denied =#=#=#= End test: l33t-haxor: Create a resource - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - l33t-haxor: Create a resource =#=#=#= Begin test: niceguy: Query configuration =#=#=#= =#=#=#= End test: niceguy: Query configuration - OK (0) =#=#=#= * Passed: cibadmin - niceguy: Query configuration =#=#=#= Begin test: niceguy: Set enable-acl =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value] Error setting enable-acl=false (section=crm_config, set=): Permission denied crm_attribute: Error performing operation: Permission denied =#=#=#= End test: niceguy: Set enable-acl - Insufficient privileges (4) =#=#=#= * Passed: crm_attribute - niceguy: Set enable-acl =#=#=#= Begin test: niceguy: Set stonith-enabled =#=#=#= =#=#=#= Current cib after: niceguy: Set stonith-enabled =#=#=#= =#=#=#= End test: niceguy: Set stonith-enabled - OK (0) =#=#=#= * Passed: crm_attribute - niceguy: Set stonith-enabled =#=#=#= Begin test: niceguy: Create a resource =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/resources/primitive[@id='dummy'] pcmk__apply_creation_acl trace: ACLs disallow creation of with id="dummy" Call failed: Permission denied =#=#=#= End test: niceguy: Create a resource - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Create a resource =#=#=#= Begin test: root: Query configuration =#=#=#= =#=#=#= End test: root: Query configuration - OK (0) =#=#=#= * Passed: cibadmin - root: Query configuration =#=#=#= Begin test: root: Set stonith-enabled =#=#=#= =#=#=#= Current cib after: root: Set stonith-enabled =#=#=#= =#=#=#= End test: root: Set stonith-enabled - OK (0) =#=#=#= * Passed: crm_attribute - root: Set stonith-enabled =#=#=#= Begin test: root: Create a resource =#=#=#= =#=#=#= Current cib after: root: Create a resource =#=#=#= =#=#=#= End test: root: Create a resource - OK (0) =#=#=#= * Passed: cibadmin - root: Create a resource =#=#=#= Begin test: l33t-haxor: Create a resource meta attribute =#=#=#= crm_resource: Error performing operation: Insufficient privileges =#=#=#= End test: l33t-haxor: Create a resource meta attribute - Insufficient privileges (4) =#=#=#= * Passed: crm_resource - l33t-haxor: Create a resource meta attribute =#=#=#= Begin test: l33t-haxor: Query a resource meta attribute =#=#=#= crm_resource: Error performing operation: Insufficient privileges =#=#=#= End test: l33t-haxor: Query a resource meta attribute - Insufficient privileges (4) =#=#=#= * Passed: crm_resource - l33t-haxor: Query a resource meta attribute =#=#=#= Begin test: l33t-haxor: Remove a resource meta attribute =#=#=#= crm_resource: Error performing operation: Insufficient privileges =#=#=#= End test: l33t-haxor: Remove a resource meta attribute - Insufficient privileges (4) =#=#=#= * Passed: crm_resource - l33t-haxor: Remove a resource meta attribute =#=#=#= Begin test: niceguy: Create a resource meta attribute =#=#=#= 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 pcmk__apply_creation_acl trace: Creation of scaffolding with id="dummy-meta_attributes" is implicitly allowed pcmk__apply_creation_acl trace: ACLs allow creation of with id="dummy-meta_attributes-target-role" Set 'dummy' option: id=dummy-meta_attributes-target-role set=dummy-meta_attributes name=target-role value=Stopped =#=#=#= Current cib after: niceguy: Create a resource meta attribute =#=#=#= =#=#=#= End test: niceguy: Create a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Create a resource meta attribute =#=#=#= Begin test: niceguy: Query a resource meta attribute =#=#=#= 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 Stopped =#=#=#= Current cib after: niceguy: Query a resource meta attribute =#=#=#= =#=#=#= End test: niceguy: Query a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Query a resource meta attribute =#=#=#= Begin test: niceguy: Remove a resource meta attribute =#=#=#= 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 Deleted 'dummy' option: id=dummy-meta_attributes-target-role name=target-role =#=#=#= Current cib after: niceguy: Remove a resource meta attribute =#=#=#= =#=#=#= End test: niceguy: Remove a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Remove a resource meta attribute =#=#=#= Begin test: niceguy: Create a resource meta attribute =#=#=#= 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 pcmk__apply_creation_acl trace: ACLs allow creation of with id="dummy-meta_attributes-target-role" Set 'dummy' option: id=dummy-meta_attributes-target-role set=dummy-meta_attributes name=target-role value=Started =#=#=#= Current cib after: niceguy: Create a resource meta attribute =#=#=#= =#=#=#= End test: niceguy: Create a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - niceguy: Create a resource meta attribute =#=#=#= Begin test: badidea: Query configuration - implied deny =#=#=#= =#=#=#= End test: badidea: Query configuration - implied deny - OK (0) =#=#=#= * Passed: cibadmin - badidea: Query configuration - implied deny =#=#=#= Begin test: betteridea: Query configuration - explicit deny =#=#=#= =#=#=#= End test: betteridea: Query configuration - explicit deny - OK (0) =#=#=#= * Passed: cibadmin - betteridea: Query configuration - explicit deny =#=#=#= Begin test: niceguy: Replace - remove acls =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib[@epoch] pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/acls Call failed: Permission denied =#=#=#= End test: niceguy: Replace - remove acls - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Replace - remove acls =#=#=#= Begin test: niceguy: Replace - create resource =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib[@epoch] pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/resources/primitive[@id='dummy2'] pcmk__apply_creation_acl trace: ACLs disallow creation of with id="dummy2" Call failed: Permission denied =#=#=#= End test: niceguy: Replace - create resource - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Replace - create resource =#=#=#= Begin test: niceguy: Replace - modify attribute (deny) =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib[@epoch] pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'][@value] Call failed: Permission denied =#=#=#= End test: niceguy: Replace - modify attribute (deny) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Replace - modify attribute (deny) =#=#=#= Begin test: niceguy: Replace - delete attribute (deny) =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib[@epoch] pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options']/nvpair[@id='cib-bootstrap-options-enable-acl'] Call failed: Permission denied =#=#=#= End test: niceguy: Replace - delete attribute (deny) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Replace - delete attribute (deny) =#=#=#= Begin test: niceguy: Replace - create attribute (deny) =#=#=#= pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib[@epoch] pcmk__check_acl trace: Default ACL denies user 'niceguy' read/write access to /cib/configuration/resources/primitive[@id='dummy'][@description] Call failed: Permission denied =#=#=#= End test: niceguy: Replace - create attribute (deny) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - niceguy: Replace - create attribute (deny) =#=#=#= Begin test: bob: Replace - create attribute (direct allow) =#=#=#= =#=#=#= End test: bob: Replace - create attribute (direct allow) - OK (0) =#=#=#= * Passed: cibadmin - bob: Replace - create attribute (direct allow) =#=#=#= Begin test: bob: Replace - modify attribute (direct allow) =#=#=#= =#=#=#= End test: bob: Replace - modify attribute (direct allow) - OK (0) =#=#=#= * Passed: cibadmin - bob: Replace - modify attribute (direct allow) =#=#=#= Begin test: bob: Replace - delete attribute (direct allow) =#=#=#= =#=#=#= End test: bob: Replace - delete attribute (direct allow) - OK (0) =#=#=#= * Passed: cibadmin - bob: Replace - delete attribute (direct allow) =#=#=#= Begin test: joe: Replace - create attribute (inherited allow) =#=#=#= =#=#=#= End test: joe: Replace - create attribute (inherited allow) - OK (0) =#=#=#= * Passed: cibadmin - joe: Replace - create attribute (inherited allow) =#=#=#= Begin test: joe: Replace - modify attribute (inherited allow) =#=#=#= =#=#=#= End test: joe: Replace - modify attribute (inherited allow) - OK (0) =#=#=#= * Passed: cibadmin - joe: Replace - modify attribute (inherited allow) =#=#=#= Begin test: joe: Replace - delete attribute (inherited allow) =#=#=#= =#=#=#= End test: joe: Replace - delete attribute (inherited allow) - OK (0) =#=#=#= * Passed: cibadmin - joe: Replace - delete attribute (inherited allow) =#=#=#= Begin test: mike: Replace - create attribute (allow overrides deny) =#=#=#= =#=#=#= End test: mike: Replace - create attribute (allow overrides deny) - OK (0) =#=#=#= * Passed: cibadmin - mike: Replace - create attribute (allow overrides deny) =#=#=#= Begin test: mike: Replace - modify attribute (allow overrides deny) =#=#=#= =#=#=#= End test: mike: Replace - modify attribute (allow overrides deny) - OK (0) =#=#=#= * Passed: cibadmin - mike: Replace - modify attribute (allow overrides deny) =#=#=#= Begin test: mike: Replace - delete attribute (allow overrides deny) =#=#=#= =#=#=#= End test: mike: Replace - delete attribute (allow overrides deny) - OK (0) =#=#=#= * Passed: cibadmin - mike: Replace - delete attribute (allow overrides deny) =#=#=#= Begin test: chris: Replace - create attribute (deny overrides allow) =#=#=#= pcmk__check_acl trace: Parent ACL denies user 'chris' read/write access to /cib/configuration/resources/primitive[@id='dummy'][@description] Call failed: Permission denied =#=#=#= End test: chris: Replace - create attribute (deny overrides allow) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - chris: Replace - create attribute (deny overrides allow) =#=#=#= Begin test: chris: Replace - modify attribute (deny overrides allow) =#=#=#= pcmk__check_acl trace: Parent ACL denies user 'chris' read/write access to /cib/configuration/resources/primitive[@id='dummy'][@description] Call failed: Permission denied =#=#=#= End test: chris: Replace - modify attribute (deny overrides allow) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - chris: Replace - modify attribute (deny overrides allow) =#=#=#= Begin test: chris: Replace - delete attribute (deny overrides allow) =#=#=#= pcmk__check_acl trace: Parent ACL denies user 'chris' read/write access to /cib/configuration/resources/primitive[@id='dummy'] Call failed: Permission denied =#=#=#= End test: chris: Replace - delete attribute (deny overrides allow) - Insufficient privileges (4) =#=#=#= * Passed: cibadmin - chris: Replace - delete attribute (deny overrides allow) diff --git a/cts/cli/regression.tools.exp b/cts/cli/regression.tools.exp index ecd9b197ca..94b6330752 100644 --- a/cts/cli/regression.tools.exp +++ b/cts/cli/regression.tools.exp @@ -1,10383 +1,10383 @@ Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Validate CIB =#=#=#= =#=#=#= Current cib after: Validate CIB =#=#=#= =#=#=#= End test: Validate CIB - OK (0) =#=#=#= * Passed: cibadmin - Validate CIB =#=#=#= Begin test: List all available options (invalid type) =#=#=#= crm_attribute: Invalid --list-options value 'asdf'. Allowed values: cluster =#=#=#= End test: List all available options (invalid type) - Incorrect usage (64) =#=#=#= * Passed: crm_attribute - List all available options (invalid type) =#=#=#= Begin test: List all available options (invalid type) (XML) =#=#=#= crm_attribute: Invalid --list-options value 'asdf'. Allowed values: cluster =#=#=#= End test: List all available options (invalid type) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_attribute - List all available options (invalid type) (XML) =#=#=#= Begin test: List non-advanced cluster options =#=#=#= Pacemaker cluster options Also known as properties, these are options that affect behavior across the entire cluster. They are configured within cluster_property_set elements inside the crm_config subsection of the CIB configuration section. * dc-version: Pacemaker version on cluster node elected Designated Controller (DC) * Includes a hash which identifies the exact revision the code was built from. Used for diagnostic purposes. * Possible values (generated by Pacemaker): version (no default) * cluster-infrastructure: The messaging layer on which Pacemaker is currently running * Used for informational and diagnostic purposes. * Possible values (generated by Pacemaker): string (no default) * cluster-name: An arbitrary name for the cluster * This optional value is mostly for users' convenience as desired in administration, but may also be used in Pacemaker configuration rules via the #cluster-name node attribute, and by higher-level tools and resource agents. * Possible values: string (no default) * dc-deadtime: How long to wait for a response from other nodes during start-up * The optimal value will depend on the speed and load of your network and the type of switches used. * Possible values: duration (default: ) * cluster-recheck-interval: Polling interval to recheck cluster state and evaluate rules with date specifications * Pacemaker is primarily event-driven, and looks ahead to know when to recheck cluster state for failure-timeout settings and most time-based rules. However, it will also recheck the cluster after this amount of inactivity, to evaluate rules with date specifications and serve as a fail-safe for certain types of scheduler bugs. A value of 0 disables polling. A positive value sets an interval in seconds, unless other units are specified (for example, "5min"). * Possible values: duration (default: ) * fence-reaction: How a cluster node should react if notified of its own fencing * A cluster node may receive notification of a "succeeded" fencing that targeted it if fencing is misconfigured, or if fabric fencing is in use that doesn't cut cluster communication. Use "stop" to attempt to immediately stop Pacemaker and stay stopped, or "panic" to attempt to immediately reboot the local node, falling back to stop on failure. * Possible values: "stop" (default), "panic" * no-quorum-policy: What to do when the cluster does not have quorum * Possible values: "stop" (default), "freeze", "ignore", "demote", "fence", "suicide" * shutdown-lock: Whether to lock resources to a cleanly shut down node * When true, resources active on a node when it is cleanly shut down are kept "locked" to that node (not allowed to run elsewhere) until they start again on that node after it rejoins (or for at most shutdown-lock-limit, if set). Stonith resources and Pacemaker Remote connections are never locked. Clone and bundle instances and the promoted role of promotable clones are currently never locked, though support could be added in a future release. * Possible values: boolean (default: ) * shutdown-lock-limit: Do not lock resources to a cleanly shut down node longer than this * If shutdown-lock is true and this is set to a nonzero time duration, shutdown locks will expire after this much time has passed since the shutdown was initiated, even if the node has not rejoined. * Possible values: duration (default: ) * enable-acl: Enable Access Control Lists (ACLs) for the CIB * Possible values: boolean (default: ) * symmetric-cluster: Whether resources can run on any node by default * Possible values: boolean (default: ) * maintenance-mode: Whether the cluster should refrain from monitoring, starting, and stopping resources * Possible values: boolean (default: ) * start-failure-is-fatal: Whether a start failure should prevent a resource from being recovered on the same node * When true, the cluster will immediately ban a resource from a node if it fails to start there. When false, the cluster will instead check the resource's fail count against its migration-threshold. * Possible values: boolean (default: ) * enable-startup-probes: Whether the cluster should check for active resources during start-up * Possible values: boolean (default: ) * stonith-action: Action to send to fence device when a node needs to be fenced ("poweroff" is a deprecated alias for "off") * Possible values: "reboot" (default), "off", "poweroff" * stonith-timeout: How long to wait for on, off, and reboot fence actions to complete by default * Possible values: duration (default: ) * have-watchdog: Whether watchdog integration is enabled * This is set automatically by the cluster according to whether SBD is detected to be in use. User-configured values are ignored. The value `true` is meaningful if diskless SBD is used and `stonith-watchdog-timeout` is nonzero. In that case, if fencing is required, watchdog-based self-fencing will be performed via SBD without requiring a fencing resource explicitly configured. * Possible values (generated by Pacemaker): boolean (default: ) * stonith-watchdog-timeout: How long before nodes can be assumed to be safely down when watchdog-based self-fencing via SBD is in use * If this is set to a positive value, lost nodes are assumed to achieve self-fencing using watchdog-based SBD within this much time. This does not require a fencing resource to be explicitly configured, though a fence_watchdog resource can be configured, to limit use to specific nodes. If this is set to 0 (the default), the cluster will never assume watchdog-based self-fencing. If this is set to a negative value, the cluster will use twice the local value of the `SBD_WATCHDOG_TIMEOUT` environment variable if that is positive, or otherwise treat this as 0. WARNING: When used, this timeout must be larger than `SBD_WATCHDOG_TIMEOUT` on all nodes that use watchdog-based SBD, and Pacemaker will refuse to start on any of those nodes where this is not true for the local value or SBD is not active. When this is set to a negative value, `SBD_WATCHDOG_TIMEOUT` must be set to the same value on all nodes that use SBD, otherwise data corruption or loss could occur. * Possible values: timeout (default: ) * stonith-max-attempts: How many times fencing can fail before it will no longer be immediately re-attempted on a target * Possible values: score (default: ) * concurrent-fencing: Allow performing fencing operations in parallel * Possible values: boolean (default: ) * priority-fencing-delay: Apply fencing delay targeting the lost nodes with the highest total resource priority * Apply specified delay for the fencings that are targeting the lost nodes with the highest total resource priority in case we don't have the majority of the nodes in our cluster partition, so that the more significant nodes potentially win any fencing match, which is especially meaningful under split-brain of 2-node cluster. A promoted resource instance takes the base priority + 1 on calculation if the base priority is not 0. Any static/random delays that are introduced by `pcmk_delay_base/max` configured for the corresponding fencing resources will be added to this delay. This delay should be significantly greater than, safely twice, the maximum `pcmk_delay_base/max`. By default, priority fencing delay is disabled. * Possible values: duration (default: ) * node-pending-timeout: How long to wait for a node that has joined the cluster to join the controller process group * Fence nodes that do not join the controller process group within this much time after joining the cluster, to allow the cluster to continue managing resources. A value of 0 means never fence pending nodes. Setting the value to 2h means fence nodes after 2 hours. * Possible values: duration (default: ) * cluster-delay: Maximum time for node-to-node communication * The node elected Designated Controller (DC) will consider an action failed if it does not get a response from the node executing the action within this time (after considering the action's own timeout). The "correct" value will depend on the speed and load of your network and cluster nodes. * Possible values: duration (default: ) * load-threshold: Maximum amount of system load that should be used by cluster nodes * The cluster will slow down its recovery process when the amount of system resources used (currently CPU) approaches this limit * Possible values: percentage (default: ) * node-action-limit: Maximum number of jobs that can be scheduled per node (defaults to 2x cores) * Possible values: integer (default: ) * batch-limit: Maximum number of jobs that the cluster may execute in parallel across all nodes * The "correct" value will depend on the speed and load of your network and cluster nodes. If set to 0, the cluster will impose a dynamically calculated limit when any node has a high load. * Possible values: integer (default: ) * migration-limit: The number of live migration actions that the cluster is allowed to execute in parallel on a node (-1 means no limit) * Possible values: integer (default: ) * cluster-ipc-limit: Maximum IPC message backlog before disconnecting a cluster daemon * Raise this if log has "Evicting client" messages for cluster daemon PIDs (a good value is the number of resources in the cluster multiplied by the number of nodes). * Possible values: nonnegative_integer (default: ) * stop-all-resources: Whether the cluster should stop all active resources * Possible values: boolean (default: ) * stop-orphan-resources: Whether to stop resources that were removed from the configuration * Possible values: boolean (default: ) * stop-orphan-actions: Whether to cancel recurring actions removed from the configuration * Possible values: boolean (default: ) * pe-error-series-max: The number of scheduler inputs resulting in errors to save * Zero to disable, -1 to store unlimited. * Possible values: integer (default: ) * pe-warn-series-max: The number of scheduler inputs resulting in warnings to save * Zero to disable, -1 to store unlimited. * Possible values: integer (default: ) * pe-input-series-max: The number of scheduler inputs without errors or warnings to save * Zero to disable, -1 to store unlimited. * Possible values: integer (default: ) * node-health-strategy: How cluster should react to node health attributes * Requires external entities to create node attributes (named with the prefix "#health") with values "red", "yellow", or "green". * Possible values: "none" (default), "migrate-on-red", "only-green", "progressive", "custom" * node-health-base: Base health score assigned to a node * Only used when "node-health-strategy" is set to "progressive". * Possible values: score (default: ) * node-health-green: The score to use for a node health attribute whose value is "green" * Only used when "node-health-strategy" is set to "custom" or "progressive". * Possible values: score (default: ) * node-health-yellow: The score to use for a node health attribute whose value is "yellow" * Only used when "node-health-strategy" is set to "custom" or "progressive". * Possible values: score (default: ) * node-health-red: The score to use for a node health attribute whose value is "red" * Only used when "node-health-strategy" is set to "custom" or "progressive". * Possible values: score (default: ) * placement-strategy: How the cluster should allocate resources to nodes * Possible values: "default" (default), "utilization", "minimal", "balanced" =#=#=#= End test: List non-advanced cluster options - OK (0) =#=#=#= * Passed: crm_attribute - List non-advanced cluster options =#=#=#= Begin test: List non-advanced cluster options (XML) (shows all) =#=#=#= 1.1 Also known as properties, these are options that affect behavior across the entire cluster. They are configured within cluster_property_set elements inside the crm_config subsection of the CIB configuration section. Pacemaker cluster options Includes a hash which identifies the exact revision the code was built from. Used for diagnostic purposes. Pacemaker version on cluster node elected Designated Controller (DC) Used for informational and diagnostic purposes. The messaging layer on which Pacemaker is currently running This optional value is mostly for users' convenience as desired in administration, but may also be used in Pacemaker configuration rules via the #cluster-name node attribute, and by higher-level tools and resource agents. An arbitrary name for the cluster The optimal value will depend on the speed and load of your network and the type of switches used. How long to wait for a response from other nodes during start-up Pacemaker is primarily event-driven, and looks ahead to know when to recheck cluster state for failure-timeout settings and most time-based rules. However, it will also recheck the cluster after this amount of inactivity, to evaluate rules with date specifications and serve as a fail-safe for certain types of scheduler bugs. A value of 0 disables polling. A positive value sets an interval in seconds, unless other units are specified (for example, "5min"). Polling interval to recheck cluster state and evaluate rules with date specifications A cluster node may receive notification of a "succeeded" fencing that targeted it if fencing is misconfigured, or if fabric fencing is in use that doesn't cut cluster communication. Use "stop" to attempt to immediately stop Pacemaker and stay stopped, or "panic" to attempt to immediately reboot the local node, falling back to stop on failure. How a cluster node should react if notified of its own fencing Declare an election failed if it is not decided within this much time. If you need to adjust this value, it probably indicates the presence of a bug. Declare an election failed if it is not decided within this much time. If you need to adjust this value, it probably indicates the presence of a bug. Exit immediately if shutdown does not complete within this much time. If you need to adjust this value, it probably indicates the presence of a bug. Exit immediately if shutdown does not complete within this much time. If you need to adjust this value, it probably indicates the presence of a bug. If you need to adjust this value, it probably indicates the presence of a bug. If you need to adjust this value, it probably indicates the presence of a bug. If you need to adjust this value, it probably indicates the presence of a bug. If you need to adjust this value, it probably indicates the presence of a bug. Delay cluster recovery for this much time to allow for additional events to occur. Useful if your configuration is sensitive to the order in which ping updates arrive. Enabling this option will slow down cluster recovery under all conditions What to do when the cluster does not have quorum What to do when the cluster does not have quorum When true, resources active on a node when it is cleanly shut down are kept "locked" to that node (not allowed to run elsewhere) until they start again on that node after it rejoins (or for at most shutdown-lock-limit, if set). Stonith resources and Pacemaker Remote connections are never locked. Clone and bundle instances and the promoted role of promotable clones are currently never locked, though support could be added in a future release. Whether to lock resources to a cleanly shut down node If shutdown-lock is true and this is set to a nonzero time duration, shutdown locks will expire after this much time has passed since the shutdown was initiated, even if the node has not rejoined. Do not lock resources to a cleanly shut down node longer than this Enable Access Control Lists (ACLs) for the CIB Enable Access Control Lists (ACLs) for the CIB Whether resources can run on any node by default Whether resources can run on any node by default Whether the cluster should refrain from monitoring, starting, and stopping resources Whether the cluster should refrain from monitoring, starting, and stopping resources When true, the cluster will immediately ban a resource from a node if it fails to start there. When false, the cluster will instead check the resource's fail count against its migration-threshold. Whether a start failure should prevent a resource from being recovered on the same node Whether the cluster should check for active resources during start-up Whether the cluster should check for active resources during start-up If false, unresponsive nodes are immediately assumed to be harmless, and resources that were active on them may be recovered elsewhere. This can result in a "split-brain" situation, potentially leading to data loss and/or service unavailability. Whether nodes may be fenced as part of recovery Action to send to fence device when a node needs to be fenced ("poweroff" is a deprecated alias for "off") Action to send to fence device when a node needs to be fenced ("poweroff" is a deprecated alias for "off") How long to wait for on, off, and reboot fence actions to complete by default How long to wait for on, off, and reboot fence actions to complete by default This is set automatically by the cluster according to whether SBD is detected to be in use. User-configured values are ignored. The value `true` is meaningful if diskless SBD is used and `stonith-watchdog-timeout` is nonzero. In that case, if fencing is required, watchdog-based self-fencing will be performed via SBD without requiring a fencing resource explicitly configured. Whether watchdog integration is enabled If this is set to a positive value, lost nodes are assumed to achieve self-fencing using watchdog-based SBD within this much time. This does not require a fencing resource to be explicitly configured, though a fence_watchdog resource can be configured, to limit use to specific nodes. If this is set to 0 (the default), the cluster will never assume watchdog-based self-fencing. If this is set to a negative value, the cluster will use twice the local value of the `SBD_WATCHDOG_TIMEOUT` environment variable if that is positive, or otherwise treat this as 0. WARNING: When used, this timeout must be larger than `SBD_WATCHDOG_TIMEOUT` on all nodes that use watchdog-based SBD, and Pacemaker will refuse to start on any of those nodes where this is not true for the local value or SBD is not active. When this is set to a negative value, `SBD_WATCHDOG_TIMEOUT` must be set to the same value on all nodes that use SBD, otherwise data corruption or loss could occur. How long before nodes can be assumed to be safely down when watchdog-based self-fencing via SBD is in use How many times fencing can fail before it will no longer be immediately re-attempted on a target How many times fencing can fail before it will no longer be immediately re-attempted on a target Allow performing fencing operations in parallel Allow performing fencing operations in parallel Setting this to false may lead to a "split-brain" situation, potentially leading to data loss and/or service unavailability. Whether to fence unseen nodes at start-up Apply specified delay for the fencings that are targeting the lost nodes with the highest total resource priority in case we don't have the majority of the nodes in our cluster partition, so that the more significant nodes potentially win any fencing match, which is especially meaningful under split-brain of 2-node cluster. A promoted resource instance takes the base priority + 1 on calculation if the base priority is not 0. Any static/random delays that are introduced by `pcmk_delay_base/max` configured for the corresponding fencing resources will be added to this delay. This delay should be significantly greater than, safely twice, the maximum `pcmk_delay_base/max`. By default, priority fencing delay is disabled. Apply fencing delay targeting the lost nodes with the highest total resource priority Fence nodes that do not join the controller process group within this much time after joining the cluster, to allow the cluster to continue managing resources. A value of 0 means never fence pending nodes. Setting the value to 2h means fence nodes after 2 hours. How long to wait for a node that has joined the cluster to join the controller process group The node elected Designated Controller (DC) will consider an action failed if it does not get a response from the node executing the action within this time (after considering the action's own timeout). The "correct" value will depend on the speed and load of your network and cluster nodes. Maximum time for node-to-node communication The cluster will slow down its recovery process when the amount of system resources used (currently CPU) approaches this limit Maximum amount of system load that should be used by cluster nodes Maximum number of jobs that can be scheduled per node (defaults to 2x cores) Maximum number of jobs that can be scheduled per node (defaults to 2x cores) The "correct" value will depend on the speed and load of your network and cluster nodes. If set to 0, the cluster will impose a dynamically calculated limit when any node has a high load. Maximum number of jobs that the cluster may execute in parallel across all nodes The number of live migration actions that the cluster is allowed to execute in parallel on a node (-1 means no limit) The number of live migration actions that the cluster is allowed to execute in parallel on a node (-1 means no limit) Raise this if log has "Evicting client" messages for cluster daemon PIDs (a good value is the number of resources in the cluster multiplied by the number of nodes). Maximum IPC message backlog before disconnecting a cluster daemon Whether the cluster should stop all active resources Whether the cluster should stop all active resources Whether to stop resources that were removed from the configuration Whether to stop resources that were removed from the configuration Whether to cancel recurring actions removed from the configuration Whether to cancel recurring actions removed from the configuration Values other than default are poorly tested and potentially dangerous. Whether to remove stopped resources from the executor Zero to disable, -1 to store unlimited. The number of scheduler inputs resulting in errors to save Zero to disable, -1 to store unlimited. The number of scheduler inputs resulting in warnings to save Zero to disable, -1 to store unlimited. The number of scheduler inputs without errors or warnings to save Requires external entities to create node attributes (named with the prefix "#health") with values "red", "yellow", or "green". How cluster should react to node health attributes Only used when "node-health-strategy" is set to "progressive". Base health score assigned to a node Only used when "node-health-strategy" is set to "custom" or "progressive". The score to use for a node health attribute whose value is "green" Only used when "node-health-strategy" is set to "custom" or "progressive". The score to use for a node health attribute whose value is "yellow" Only used when "node-health-strategy" is set to "custom" or "progressive". The score to use for a node health attribute whose value is "red" How the cluster should allocate resources to nodes How the cluster should allocate resources to nodes =#=#=#= End test: List non-advanced cluster options (XML) (shows all) - OK (0) =#=#=#= * Passed: crm_attribute - List non-advanced cluster options (XML) (shows all) =#=#=#= Begin test: List all available cluster options =#=#=#= Pacemaker cluster options Also known as properties, these are options that affect behavior across the entire cluster. They are configured within cluster_property_set elements inside the crm_config subsection of the CIB configuration section. * dc-version: Pacemaker version on cluster node elected Designated Controller (DC) * Includes a hash which identifies the exact revision the code was built from. Used for diagnostic purposes. * Possible values (generated by Pacemaker): version (no default) * cluster-infrastructure: The messaging layer on which Pacemaker is currently running * Used for informational and diagnostic purposes. * Possible values (generated by Pacemaker): string (no default) * cluster-name: An arbitrary name for the cluster * This optional value is mostly for users' convenience as desired in administration, but may also be used in Pacemaker configuration rules via the #cluster-name node attribute, and by higher-level tools and resource agents. * Possible values: string (no default) * dc-deadtime: How long to wait for a response from other nodes during start-up * The optimal value will depend on the speed and load of your network and the type of switches used. * Possible values: duration (default: ) * cluster-recheck-interval: Polling interval to recheck cluster state and evaluate rules with date specifications * Pacemaker is primarily event-driven, and looks ahead to know when to recheck cluster state for failure-timeout settings and most time-based rules. However, it will also recheck the cluster after this amount of inactivity, to evaluate rules with date specifications and serve as a fail-safe for certain types of scheduler bugs. A value of 0 disables polling. A positive value sets an interval in seconds, unless other units are specified (for example, "5min"). * Possible values: duration (default: ) * fence-reaction: How a cluster node should react if notified of its own fencing * A cluster node may receive notification of a "succeeded" fencing that targeted it if fencing is misconfigured, or if fabric fencing is in use that doesn't cut cluster communication. Use "stop" to attempt to immediately stop Pacemaker and stay stopped, or "panic" to attempt to immediately reboot the local node, falling back to stop on failure. * Possible values: "stop" (default), "panic" * no-quorum-policy: What to do when the cluster does not have quorum * Possible values: "stop" (default), "freeze", "ignore", "demote", "fence", "suicide" * shutdown-lock: Whether to lock resources to a cleanly shut down node * When true, resources active on a node when it is cleanly shut down are kept "locked" to that node (not allowed to run elsewhere) until they start again on that node after it rejoins (or for at most shutdown-lock-limit, if set). Stonith resources and Pacemaker Remote connections are never locked. Clone and bundle instances and the promoted role of promotable clones are currently never locked, though support could be added in a future release. * Possible values: boolean (default: ) * shutdown-lock-limit: Do not lock resources to a cleanly shut down node longer than this * If shutdown-lock is true and this is set to a nonzero time duration, shutdown locks will expire after this much time has passed since the shutdown was initiated, even if the node has not rejoined. * Possible values: duration (default: ) * enable-acl: Enable Access Control Lists (ACLs) for the CIB * Possible values: boolean (default: ) * symmetric-cluster: Whether resources can run on any node by default * Possible values: boolean (default: ) * maintenance-mode: Whether the cluster should refrain from monitoring, starting, and stopping resources * Possible values: boolean (default: ) * start-failure-is-fatal: Whether a start failure should prevent a resource from being recovered on the same node * When true, the cluster will immediately ban a resource from a node if it fails to start there. When false, the cluster will instead check the resource's fail count against its migration-threshold. * Possible values: boolean (default: ) * enable-startup-probes: Whether the cluster should check for active resources during start-up * Possible values: boolean (default: ) * stonith-action: Action to send to fence device when a node needs to be fenced ("poweroff" is a deprecated alias for "off") * Possible values: "reboot" (default), "off", "poweroff" * stonith-timeout: How long to wait for on, off, and reboot fence actions to complete by default * Possible values: duration (default: ) * have-watchdog: Whether watchdog integration is enabled * This is set automatically by the cluster according to whether SBD is detected to be in use. User-configured values are ignored. The value `true` is meaningful if diskless SBD is used and `stonith-watchdog-timeout` is nonzero. In that case, if fencing is required, watchdog-based self-fencing will be performed via SBD without requiring a fencing resource explicitly configured. * Possible values (generated by Pacemaker): boolean (default: ) * stonith-watchdog-timeout: How long before nodes can be assumed to be safely down when watchdog-based self-fencing via SBD is in use * If this is set to a positive value, lost nodes are assumed to achieve self-fencing using watchdog-based SBD within this much time. This does not require a fencing resource to be explicitly configured, though a fence_watchdog resource can be configured, to limit use to specific nodes. If this is set to 0 (the default), the cluster will never assume watchdog-based self-fencing. If this is set to a negative value, the cluster will use twice the local value of the `SBD_WATCHDOG_TIMEOUT` environment variable if that is positive, or otherwise treat this as 0. WARNING: When used, this timeout must be larger than `SBD_WATCHDOG_TIMEOUT` on all nodes that use watchdog-based SBD, and Pacemaker will refuse to start on any of those nodes where this is not true for the local value or SBD is not active. When this is set to a negative value, `SBD_WATCHDOG_TIMEOUT` must be set to the same value on all nodes that use SBD, otherwise data corruption or loss could occur. * Possible values: timeout (default: ) * stonith-max-attempts: How many times fencing can fail before it will no longer be immediately re-attempted on a target * Possible values: score (default: ) * concurrent-fencing: Allow performing fencing operations in parallel * Possible values: boolean (default: ) * priority-fencing-delay: Apply fencing delay targeting the lost nodes with the highest total resource priority * Apply specified delay for the fencings that are targeting the lost nodes with the highest total resource priority in case we don't have the majority of the nodes in our cluster partition, so that the more significant nodes potentially win any fencing match, which is especially meaningful under split-brain of 2-node cluster. A promoted resource instance takes the base priority + 1 on calculation if the base priority is not 0. Any static/random delays that are introduced by `pcmk_delay_base/max` configured for the corresponding fencing resources will be added to this delay. This delay should be significantly greater than, safely twice, the maximum `pcmk_delay_base/max`. By default, priority fencing delay is disabled. * Possible values: duration (default: ) * node-pending-timeout: How long to wait for a node that has joined the cluster to join the controller process group * Fence nodes that do not join the controller process group within this much time after joining the cluster, to allow the cluster to continue managing resources. A value of 0 means never fence pending nodes. Setting the value to 2h means fence nodes after 2 hours. * Possible values: duration (default: ) * cluster-delay: Maximum time for node-to-node communication * The node elected Designated Controller (DC) will consider an action failed if it does not get a response from the node executing the action within this time (after considering the action's own timeout). The "correct" value will depend on the speed and load of your network and cluster nodes. * Possible values: duration (default: ) * load-threshold: Maximum amount of system load that should be used by cluster nodes * The cluster will slow down its recovery process when the amount of system resources used (currently CPU) approaches this limit * Possible values: percentage (default: ) * node-action-limit: Maximum number of jobs that can be scheduled per node (defaults to 2x cores) * Possible values: integer (default: ) * batch-limit: Maximum number of jobs that the cluster may execute in parallel across all nodes * The "correct" value will depend on the speed and load of your network and cluster nodes. If set to 0, the cluster will impose a dynamically calculated limit when any node has a high load. * Possible values: integer (default: ) * migration-limit: The number of live migration actions that the cluster is allowed to execute in parallel on a node (-1 means no limit) * Possible values: integer (default: ) * cluster-ipc-limit: Maximum IPC message backlog before disconnecting a cluster daemon * Raise this if log has "Evicting client" messages for cluster daemon PIDs (a good value is the number of resources in the cluster multiplied by the number of nodes). * Possible values: nonnegative_integer (default: ) * stop-all-resources: Whether the cluster should stop all active resources * Possible values: boolean (default: ) * stop-orphan-resources: Whether to stop resources that were removed from the configuration * Possible values: boolean (default: ) * stop-orphan-actions: Whether to cancel recurring actions removed from the configuration * Possible values: boolean (default: ) * pe-error-series-max: The number of scheduler inputs resulting in errors to save * Zero to disable, -1 to store unlimited. * Possible values: integer (default: ) * pe-warn-series-max: The number of scheduler inputs resulting in warnings to save * Zero to disable, -1 to store unlimited. * Possible values: integer (default: ) * pe-input-series-max: The number of scheduler inputs without errors or warnings to save * Zero to disable, -1 to store unlimited. * Possible values: integer (default: ) * node-health-strategy: How cluster should react to node health attributes * Requires external entities to create node attributes (named with the prefix "#health") with values "red", "yellow", or "green". * Possible values: "none" (default), "migrate-on-red", "only-green", "progressive", "custom" * node-health-base: Base health score assigned to a node * Only used when "node-health-strategy" is set to "progressive". * Possible values: score (default: ) * node-health-green: The score to use for a node health attribute whose value is "green" * Only used when "node-health-strategy" is set to "custom" or "progressive". * Possible values: score (default: ) * node-health-yellow: The score to use for a node health attribute whose value is "yellow" * Only used when "node-health-strategy" is set to "custom" or "progressive". * Possible values: score (default: ) * node-health-red: The score to use for a node health attribute whose value is "red" * Only used when "node-health-strategy" is set to "custom" or "progressive". * Possible values: score (default: ) * placement-strategy: How the cluster should allocate resources to nodes * Possible values: "default" (default), "utilization", "minimal", "balanced" * ADVANCED OPTIONS: * election-timeout: Declare an election failed if it is not decided within this much time. If you need to adjust this value, it probably indicates the presence of a bug. * Possible values: duration (default: ) * shutdown-escalation: Exit immediately if shutdown does not complete within this much time. If you need to adjust this value, it probably indicates the presence of a bug. * Possible values: duration (default: ) * join-integration-timeout: If you need to adjust this value, it probably indicates the presence of a bug. * Possible values: duration (default: ) * join-finalization-timeout: If you need to adjust this value, it probably indicates the presence of a bug. * Possible values: duration (default: ) * transition-delay: Enabling this option will slow down cluster recovery under all conditions * Delay cluster recovery for this much time to allow for additional events to occur. Useful if your configuration is sensitive to the order in which ping updates arrive. * Possible values: duration (default: ) * stonith-enabled: Whether nodes may be fenced as part of recovery * If false, unresponsive nodes are immediately assumed to be harmless, and resources that were active on them may be recovered elsewhere. This can result in a "split-brain" situation, potentially leading to data loss and/or service unavailability. * Possible values: boolean (default: ) * startup-fencing: Whether to fence unseen nodes at start-up * Setting this to false may lead to a "split-brain" situation, potentially leading to data loss and/or service unavailability. * Possible values: boolean (default: ) * DEPRECATED OPTIONS (will be removed in a future release): * remove-after-stop: Whether to remove stopped resources from the executor * Values other than default are poorly tested and potentially dangerous. * Possible values: boolean (default: ) =#=#=#= End test: List all available cluster options - OK (0) =#=#=#= * Passed: crm_attribute - List all available cluster options =#=#=#= Begin test: List all available cluster options (XML) =#=#=#= 1.1 Also known as properties, these are options that affect behavior across the entire cluster. They are configured within cluster_property_set elements inside the crm_config subsection of the CIB configuration section. Pacemaker cluster options Includes a hash which identifies the exact revision the code was built from. Used for diagnostic purposes. Pacemaker version on cluster node elected Designated Controller (DC) Used for informational and diagnostic purposes. The messaging layer on which Pacemaker is currently running This optional value is mostly for users' convenience as desired in administration, but may also be used in Pacemaker configuration rules via the #cluster-name node attribute, and by higher-level tools and resource agents. An arbitrary name for the cluster The optimal value will depend on the speed and load of your network and the type of switches used. How long to wait for a response from other nodes during start-up Pacemaker is primarily event-driven, and looks ahead to know when to recheck cluster state for failure-timeout settings and most time-based rules. However, it will also recheck the cluster after this amount of inactivity, to evaluate rules with date specifications and serve as a fail-safe for certain types of scheduler bugs. A value of 0 disables polling. A positive value sets an interval in seconds, unless other units are specified (for example, "5min"). Polling interval to recheck cluster state and evaluate rules with date specifications A cluster node may receive notification of a "succeeded" fencing that targeted it if fencing is misconfigured, or if fabric fencing is in use that doesn't cut cluster communication. Use "stop" to attempt to immediately stop Pacemaker and stay stopped, or "panic" to attempt to immediately reboot the local node, falling back to stop on failure. How a cluster node should react if notified of its own fencing Declare an election failed if it is not decided within this much time. If you need to adjust this value, it probably indicates the presence of a bug. Declare an election failed if it is not decided within this much time. If you need to adjust this value, it probably indicates the presence of a bug. Exit immediately if shutdown does not complete within this much time. If you need to adjust this value, it probably indicates the presence of a bug. Exit immediately if shutdown does not complete within this much time. If you need to adjust this value, it probably indicates the presence of a bug. If you need to adjust this value, it probably indicates the presence of a bug. If you need to adjust this value, it probably indicates the presence of a bug. If you need to adjust this value, it probably indicates the presence of a bug. If you need to adjust this value, it probably indicates the presence of a bug. Delay cluster recovery for this much time to allow for additional events to occur. Useful if your configuration is sensitive to the order in which ping updates arrive. Enabling this option will slow down cluster recovery under all conditions What to do when the cluster does not have quorum What to do when the cluster does not have quorum When true, resources active on a node when it is cleanly shut down are kept "locked" to that node (not allowed to run elsewhere) until they start again on that node after it rejoins (or for at most shutdown-lock-limit, if set). Stonith resources and Pacemaker Remote connections are never locked. Clone and bundle instances and the promoted role of promotable clones are currently never locked, though support could be added in a future release. Whether to lock resources to a cleanly shut down node If shutdown-lock is true and this is set to a nonzero time duration, shutdown locks will expire after this much time has passed since the shutdown was initiated, even if the node has not rejoined. Do not lock resources to a cleanly shut down node longer than this Enable Access Control Lists (ACLs) for the CIB Enable Access Control Lists (ACLs) for the CIB Whether resources can run on any node by default Whether resources can run on any node by default Whether the cluster should refrain from monitoring, starting, and stopping resources Whether the cluster should refrain from monitoring, starting, and stopping resources When true, the cluster will immediately ban a resource from a node if it fails to start there. When false, the cluster will instead check the resource's fail count against its migration-threshold. Whether a start failure should prevent a resource from being recovered on the same node Whether the cluster should check for active resources during start-up Whether the cluster should check for active resources during start-up If false, unresponsive nodes are immediately assumed to be harmless, and resources that were active on them may be recovered elsewhere. This can result in a "split-brain" situation, potentially leading to data loss and/or service unavailability. Whether nodes may be fenced as part of recovery Action to send to fence device when a node needs to be fenced ("poweroff" is a deprecated alias for "off") Action to send to fence device when a node needs to be fenced ("poweroff" is a deprecated alias for "off") How long to wait for on, off, and reboot fence actions to complete by default How long to wait for on, off, and reboot fence actions to complete by default This is set automatically by the cluster according to whether SBD is detected to be in use. User-configured values are ignored. The value `true` is meaningful if diskless SBD is used and `stonith-watchdog-timeout` is nonzero. In that case, if fencing is required, watchdog-based self-fencing will be performed via SBD without requiring a fencing resource explicitly configured. Whether watchdog integration is enabled If this is set to a positive value, lost nodes are assumed to achieve self-fencing using watchdog-based SBD within this much time. This does not require a fencing resource to be explicitly configured, though a fence_watchdog resource can be configured, to limit use to specific nodes. If this is set to 0 (the default), the cluster will never assume watchdog-based self-fencing. If this is set to a negative value, the cluster will use twice the local value of the `SBD_WATCHDOG_TIMEOUT` environment variable if that is positive, or otherwise treat this as 0. WARNING: When used, this timeout must be larger than `SBD_WATCHDOG_TIMEOUT` on all nodes that use watchdog-based SBD, and Pacemaker will refuse to start on any of those nodes where this is not true for the local value or SBD is not active. When this is set to a negative value, `SBD_WATCHDOG_TIMEOUT` must be set to the same value on all nodes that use SBD, otherwise data corruption or loss could occur. How long before nodes can be assumed to be safely down when watchdog-based self-fencing via SBD is in use How many times fencing can fail before it will no longer be immediately re-attempted on a target How many times fencing can fail before it will no longer be immediately re-attempted on a target Allow performing fencing operations in parallel Allow performing fencing operations in parallel Setting this to false may lead to a "split-brain" situation, potentially leading to data loss and/or service unavailability. Whether to fence unseen nodes at start-up Apply specified delay for the fencings that are targeting the lost nodes with the highest total resource priority in case we don't have the majority of the nodes in our cluster partition, so that the more significant nodes potentially win any fencing match, which is especially meaningful under split-brain of 2-node cluster. A promoted resource instance takes the base priority + 1 on calculation if the base priority is not 0. Any static/random delays that are introduced by `pcmk_delay_base/max` configured for the corresponding fencing resources will be added to this delay. This delay should be significantly greater than, safely twice, the maximum `pcmk_delay_base/max`. By default, priority fencing delay is disabled. Apply fencing delay targeting the lost nodes with the highest total resource priority Fence nodes that do not join the controller process group within this much time after joining the cluster, to allow the cluster to continue managing resources. A value of 0 means never fence pending nodes. Setting the value to 2h means fence nodes after 2 hours. How long to wait for a node that has joined the cluster to join the controller process group The node elected Designated Controller (DC) will consider an action failed if it does not get a response from the node executing the action within this time (after considering the action's own timeout). The "correct" value will depend on the speed and load of your network and cluster nodes. Maximum time for node-to-node communication The cluster will slow down its recovery process when the amount of system resources used (currently CPU) approaches this limit Maximum amount of system load that should be used by cluster nodes Maximum number of jobs that can be scheduled per node (defaults to 2x cores) Maximum number of jobs that can be scheduled per node (defaults to 2x cores) The "correct" value will depend on the speed and load of your network and cluster nodes. If set to 0, the cluster will impose a dynamically calculated limit when any node has a high load. Maximum number of jobs that the cluster may execute in parallel across all nodes The number of live migration actions that the cluster is allowed to execute in parallel on a node (-1 means no limit) The number of live migration actions that the cluster is allowed to execute in parallel on a node (-1 means no limit) Raise this if log has "Evicting client" messages for cluster daemon PIDs (a good value is the number of resources in the cluster multiplied by the number of nodes). Maximum IPC message backlog before disconnecting a cluster daemon Whether the cluster should stop all active resources Whether the cluster should stop all active resources Whether to stop resources that were removed from the configuration Whether to stop resources that were removed from the configuration Whether to cancel recurring actions removed from the configuration Whether to cancel recurring actions removed from the configuration Values other than default are poorly tested and potentially dangerous. Whether to remove stopped resources from the executor Zero to disable, -1 to store unlimited. The number of scheduler inputs resulting in errors to save Zero to disable, -1 to store unlimited. The number of scheduler inputs resulting in warnings to save Zero to disable, -1 to store unlimited. The number of scheduler inputs without errors or warnings to save Requires external entities to create node attributes (named with the prefix "#health") with values "red", "yellow", or "green". How cluster should react to node health attributes Only used when "node-health-strategy" is set to "progressive". Base health score assigned to a node Only used when "node-health-strategy" is set to "custom" or "progressive". The score to use for a node health attribute whose value is "green" Only used when "node-health-strategy" is set to "custom" or "progressive". The score to use for a node health attribute whose value is "yellow" Only used when "node-health-strategy" is set to "custom" or "progressive". The score to use for a node health attribute whose value is "red" How the cluster should allocate resources to nodes How the cluster should allocate resources to nodes =#=#=#= End test: List all available cluster options (XML) - OK (0) =#=#=#= * Passed: crm_attribute - List all available cluster options (XML) =#=#=#= Begin test: Query the value of an attribute that does not exist =#=#=#= crm_attribute: Error performing operation: No such device or address =#=#=#= End test: Query the value of an attribute that does not exist - No such object (105) =#=#=#= * Passed: crm_attribute - Query the value of an attribute that does not exist =#=#=#= Begin test: Configure something before erasing =#=#=#= =#=#=#= Current cib after: Configure something before erasing =#=#=#= =#=#=#= End test: Configure something before erasing - OK (0) =#=#=#= * Passed: crm_attribute - Configure something before erasing =#=#=#= Begin test: Test '++' XML attribute update syntax =#=#=#= =#=#=#= Current cib after: Test '++' XML attribute update syntax =#=#=#= =#=#=#= End test: Test '++' XML attribute update syntax - OK (0) =#=#=#= * Passed: cibadmin - Test '++' XML attribute update syntax =#=#=#= Begin test: Test '+=' XML attribute update syntax =#=#=#= =#=#=#= Current cib after: Test '+=' XML attribute update syntax =#=#=#= =#=#=#= End test: Test '+=' XML attribute update syntax - OK (0) =#=#=#= * Passed: cibadmin - Test '+=' XML attribute update syntax =#=#=#= Begin test: Test '++' nvpair value update syntax =#=#=#= =#=#=#= Current cib after: Test '++' nvpair value update syntax =#=#=#= =#=#=#= End test: Test '++' nvpair value update syntax - OK (0) =#=#=#= * Passed: crm_attribute - Test '++' nvpair value update syntax =#=#=#= Begin test: Test '++' nvpair value update syntax (XML) =#=#=#= =#=#=#= Current cib after: Test '++' nvpair value update syntax (XML) =#=#=#= =#=#=#= End test: Test '++' nvpair value update syntax (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Test '++' nvpair value update syntax (XML) =#=#=#= Begin test: Test '+=' nvpair value update syntax =#=#=#= =#=#=#= Current cib after: Test '+=' nvpair value update syntax =#=#=#= =#=#=#= End test: Test '+=' nvpair value update syntax - OK (0) =#=#=#= * Passed: crm_attribute - Test '+=' nvpair value update syntax =#=#=#= Begin test: Test '+=' nvpair value update syntax (XML) =#=#=#= =#=#=#= Current cib after: Test '+=' nvpair value update syntax (XML) =#=#=#= =#=#=#= End test: Test '+=' nvpair value update syntax (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Test '+=' nvpair value update syntax (XML) =#=#=#= Begin test: Test '++' XML attribute update syntax (--score not set) =#=#=#= =#=#=#= Current cib after: Test '++' XML attribute update syntax (--score not set) =#=#=#= =#=#=#= End test: Test '++' XML attribute update syntax (--score not set) - OK (0) =#=#=#= * Passed: cibadmin - Test '++' XML attribute update syntax (--score not set) =#=#=#= Begin test: Test '+=' XML attribute update syntax (--score not set) =#=#=#= =#=#=#= Current cib after: Test '+=' XML attribute update syntax (--score not set) =#=#=#= =#=#=#= End test: Test '+=' XML attribute update syntax (--score not set) - OK (0) =#=#=#= * Passed: cibadmin - Test '+=' XML attribute update syntax (--score not set) =#=#=#= Begin test: Test '++' nvpair value update syntax (--score not set) =#=#=#= =#=#=#= Current cib after: Test '++' nvpair value update syntax (--score not set) =#=#=#= =#=#=#= End test: Test '++' nvpair value update syntax (--score not set) - OK (0) =#=#=#= * Passed: crm_attribute - Test '++' nvpair value update syntax (--score not set) =#=#=#= Begin test: Test '++' nvpair value update syntax (--score not set) (XML) =#=#=#= =#=#=#= Current cib after: Test '++' nvpair value update syntax (--score not set) (XML) =#=#=#= =#=#=#= End test: Test '++' nvpair value update syntax (--score not set) (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Test '++' nvpair value update syntax (--score not set) (XML) =#=#=#= Begin test: Test '+=' nvpair value update syntax (--score not set) =#=#=#= =#=#=#= Current cib after: Test '+=' nvpair value update syntax (--score not set) =#=#=#= =#=#=#= End test: Test '+=' nvpair value update syntax (--score not set) - OK (0) =#=#=#= * Passed: crm_attribute - Test '+=' nvpair value update syntax (--score not set) =#=#=#= Begin test: Test '+=' nvpair value update syntax (--score not set) (XML) =#=#=#= =#=#=#= Current cib after: Test '+=' nvpair value update syntax (--score not set) (XML) =#=#=#= =#=#=#= End test: Test '+=' nvpair value update syntax (--score not set) (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Test '+=' nvpair value update syntax (--score not set) (XML) =#=#=#= Begin test: Require --force for CIB erasure =#=#=#= cibadmin: The supplied command is considered dangerous. To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= Current cib after: Require --force for CIB erasure =#=#=#= =#=#=#= End test: Require --force for CIB erasure - Operation not safe (107) =#=#=#= * Passed: cibadmin - Require --force for CIB erasure =#=#=#= Begin test: Allow CIB erasure with --force =#=#=#= =#=#=#= End test: Allow CIB erasure with --force - OK (0) =#=#=#= * Passed: cibadmin - Allow CIB erasure with --force =#=#=#= Begin test: Query CIB =#=#=#= =#=#=#= Current cib after: Query CIB =#=#=#= =#=#=#= End test: Query CIB - OK (0) =#=#=#= * Passed: cibadmin - Query CIB =#=#=#= Begin test: Set cluster option =#=#=#= =#=#=#= Current cib after: Set cluster option =#=#=#= =#=#=#= End test: Set cluster option - OK (0) =#=#=#= * Passed: crm_attribute - Set cluster option =#=#=#= Begin test: Query new cluster option =#=#=#= =#=#=#= Current cib after: Query new cluster option =#=#=#= =#=#=#= End test: Query new cluster option - OK (0) =#=#=#= * Passed: cibadmin - Query new cluster option =#=#=#= Begin test: Query cluster options =#=#=#= =#=#=#= Current cib after: Query cluster options =#=#=#= =#=#=#= End test: Query cluster options - OK (0) =#=#=#= * Passed: cibadmin - Query cluster options =#=#=#= Begin test: Set no-quorum policy =#=#=#= =#=#=#= Current cib after: Set no-quorum policy =#=#=#= =#=#=#= End test: Set no-quorum policy - OK (0) =#=#=#= * Passed: crm_attribute - Set no-quorum policy =#=#=#= Begin test: Delete nvpair =#=#=#= =#=#=#= Current cib after: Delete nvpair =#=#=#= =#=#=#= End test: Delete nvpair - OK (0) =#=#=#= * Passed: cibadmin - Delete nvpair =#=#=#= Begin test: Create operation should fail =#=#=#= Call failed: File exists =#=#=#= Current cib after: Create operation should fail =#=#=#= =#=#=#= End test: Create operation should fail - Requested item already exists (108) =#=#=#= * Passed: cibadmin - Create operation should fail =#=#=#= Begin test: Modify cluster options section =#=#=#= =#=#=#= Current cib after: Modify cluster options section =#=#=#= =#=#=#= End test: Modify cluster options section - OK (0) =#=#=#= * Passed: cibadmin - Modify cluster options section =#=#=#= Begin test: Query updated cluster option =#=#=#= =#=#=#= Current cib after: Query updated cluster option =#=#=#= =#=#=#= End test: Query updated cluster option - OK (0) =#=#=#= * Passed: cibadmin - Query updated cluster option =#=#=#= Begin test: Set duplicate cluster option =#=#=#= =#=#=#= Current cib after: Set duplicate cluster option =#=#=#= =#=#=#= End test: Set duplicate cluster option - OK (0) =#=#=#= * Passed: crm_attribute - Set duplicate cluster option =#=#=#= Begin test: Setting multiply defined cluster option should fail =#=#=#= crm_attribute: Please choose from one of the matches below and supply the 'id' with --attr-id Multiple attributes match name=cluster-delay Value: 60s (id=cib-bootstrap-options-cluster-delay) Value: 40s (id=duplicate-cluster-delay) =#=#=#= Current cib after: Setting multiply defined cluster option should fail =#=#=#= =#=#=#= End test: Setting multiply defined cluster option should fail - Multiple items match request (109) =#=#=#= * Passed: crm_attribute - Setting multiply defined cluster option should fail =#=#=#= Begin test: Set cluster option with -s =#=#=#= =#=#=#= Current cib after: Set cluster option with -s =#=#=#= =#=#=#= End test: Set cluster option with -s - OK (0) =#=#=#= * Passed: crm_attribute - Set cluster option with -s =#=#=#= Begin test: Delete cluster option with -i =#=#=#= Deleted crm_config option: id=(null) name=cluster-delay =#=#=#= Current cib after: Delete cluster option with -i =#=#=#= =#=#=#= End test: Delete cluster option with -i - OK (0) =#=#=#= * Passed: crm_attribute - Delete cluster option with -i =#=#=#= Begin test: Create node1 and bring it online =#=#=#= 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_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_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: * Full List of Resources: * No resources Performing Requested Modifications: * Bringing node node1 online Transition Summary: Executing Cluster Transition: Revised Cluster Status: * Node List: * Online: [ node1 ] * Full List of Resources: * No resources =#=#=#= Current cib after: Create node1 and bring it online =#=#=#= =#=#=#= End test: Create node1 and bring it online - OK (0) =#=#=#= * Passed: crm_simulate - Create node1 and bring it online =#=#=#= Begin test: Create node attribute =#=#=#= =#=#=#= Current cib after: Create node attribute =#=#=#= =#=#=#= End test: Create node attribute - OK (0) =#=#=#= * Passed: crm_attribute - Create node attribute =#=#=#= Begin test: Query new node attribute =#=#=#= =#=#=#= Current cib after: Query new node attribute =#=#=#= =#=#=#= End test: Query new node attribute - OK (0) =#=#=#= * Passed: cibadmin - Query new node attribute =#=#=#= Begin test: Create second node attribute =#=#=#= =#=#=#= Current cib after: Create second node attribute =#=#=#= =#=#=#= End test: Create second node attribute - OK (0) =#=#=#= * Passed: crm_attribute - Create second node attribute =#=#=#= Begin test: Query node attributes by pattern =#=#=#= scope=nodes name=ram value=1024M scope=nodes name=rattr value=XYZ =#=#=#= End test: Query node attributes by pattern - OK (0) =#=#=#= * Passed: crm_attribute - Query node attributes by pattern =#=#=#= Begin test: Update node attributes by pattern =#=#=#= =#=#=#= Current cib after: Update node attributes by pattern =#=#=#= =#=#=#= End test: Update node attributes by pattern - OK (0) =#=#=#= * Passed: crm_attribute - Update node attributes by pattern =#=#=#= Begin test: Delete node attributes by pattern =#=#=#= Deleted nodes attribute: id=nodes-node1-rattr name=rattr =#=#=#= Current cib after: Delete node attributes by pattern =#=#=#= =#=#=#= End test: Delete node attributes by pattern - OK (0) =#=#=#= * Passed: crm_attribute - Delete node attributes by pattern =#=#=#= Begin test: Set a transient (fail-count) node attribute =#=#=#= =#=#=#= Current cib after: Set a transient (fail-count) node attribute =#=#=#= =#=#=#= End test: Set a transient (fail-count) node attribute - OK (0) =#=#=#= * Passed: crm_attribute - Set a transient (fail-count) node attribute =#=#=#= Begin test: Query a fail count =#=#=#= scope=status name=fail-count-foo value=3 =#=#=#= Current cib after: Query a fail count =#=#=#= =#=#=#= End test: Query a fail count - OK (0) =#=#=#= * Passed: crm_failcount - Query a fail count =#=#=#= Begin test: Show node attributes with crm_simulate =#=#=#= 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: * Node List: * Online: [ node1 ] * Full List of Resources: * No resources * Node Attributes: * Node: node1: * ram : 1024M =#=#=#= End test: Show node attributes with crm_simulate - OK (0) =#=#=#= * Passed: crm_simulate - Show node attributes with crm_simulate =#=#=#= Begin test: Set a second transient node attribute =#=#=#= =#=#=#= Current cib after: Set a second transient node attribute =#=#=#= =#=#=#= End test: Set a second transient node attribute - OK (0) =#=#=#= * Passed: crm_attribute - Set a second transient node attribute =#=#=#= Begin test: Query transient node attributes by pattern =#=#=#= scope=status name=fail-count-foo value=3 scope=status name=fail-count-bar value=5 =#=#=#= End test: Query transient node attributes by pattern - OK (0) =#=#=#= * Passed: crm_attribute - Query transient node attributes by pattern =#=#=#= Begin test: Update transient node attributes by pattern =#=#=#= =#=#=#= Current cib after: Update transient node attributes by pattern =#=#=#= =#=#=#= End test: Update transient node attributes by pattern - OK (0) =#=#=#= * Passed: crm_attribute - Update transient node attributes by pattern =#=#=#= Begin test: Delete transient node attributes by pattern =#=#=#= Deleted status attribute: id=status-node1-fail-count-foo name=fail-count-foo Deleted status attribute: id=status-node1-fail-count-bar name=fail-count-bar =#=#=#= Current cib after: Delete transient node attributes by pattern =#=#=#= =#=#=#= End test: Delete transient node attributes by pattern - OK (0) =#=#=#= * Passed: crm_attribute - Delete transient node attributes by pattern =#=#=#= Begin test: crm_attribute given invalid delete usage =#=#=#= crm_attribute: Error: must specify attribute name or pattern to delete =#=#=#= End test: crm_attribute given invalid delete usage - Incorrect usage (64) =#=#=#= * Passed: crm_attribute - crm_attribute given invalid delete usage =#=#=#= Begin test: Set a utilization node attribute =#=#=#= =#=#=#= Current cib after: Set a utilization node attribute =#=#=#= =#=#=#= End test: Set a utilization node attribute - OK (0) =#=#=#= * Passed: crm_attribute - Set a utilization node attribute =#=#=#= Begin test: Query utilization node attribute =#=#=#= scope=nodes name=cpu value=1 =#=#=#= End test: Query utilization node attribute - OK (0) =#=#=#= * Passed: crm_attribute - Query utilization node attribute =#=#=#= Begin test: Digest calculation =#=#=#= Digest: =#=#=#= Current cib after: Digest calculation =#=#=#= =#=#=#= End test: Digest calculation - OK (0) =#=#=#= * Passed: cibadmin - Digest calculation =#=#=#= Begin test: Replace operation should fail =#=#=#= Call failed: Update was older than existing configuration =#=#=#= Current cib after: Replace operation should fail =#=#=#= =#=#=#= End test: Replace operation should fail - Update was older than existing configuration (103) =#=#=#= * Passed: cibadmin - Replace operation should fail =#=#=#= Begin test: Default standby value =#=#=#= scope=status name=standby value=off =#=#=#= Current cib after: Default standby value =#=#=#= =#=#=#= End test: Default standby value - OK (0) =#=#=#= * Passed: crm_standby - Default standby value =#=#=#= Begin test: Set standby status =#=#=#= =#=#=#= Current cib after: Set standby status =#=#=#= =#=#=#= End test: Set standby status - OK (0) =#=#=#= * Passed: crm_standby - Set standby status =#=#=#= Begin test: Query standby value =#=#=#= scope=nodes name=standby value=true =#=#=#= Current cib after: Query standby value =#=#=#= =#=#=#= End test: Query standby value - OK (0) =#=#=#= * Passed: crm_standby - Query standby value =#=#=#= Begin test: Delete standby value =#=#=#= Deleted nodes attribute: id=nodes-node1-standby name=standby =#=#=#= Current cib after: Delete standby value =#=#=#= =#=#=#= End test: Delete standby value - OK (0) =#=#=#= * Passed: crm_standby - Delete standby value =#=#=#= Begin test: Create a resource =#=#=#= =#=#=#= Current cib after: Create a resource =#=#=#= =#=#=#= End test: Create a resource - OK (0) =#=#=#= * Passed: cibadmin - Create a resource =#=#=#= Begin test: crm_resource run with extra arguments =#=#=#= crm_resource: non-option ARGV-elements: [1 of 2] foo [2 of 2] bar =#=#=#= End test: crm_resource run with extra arguments - Incorrect usage (64) =#=#=#= * Passed: crm_resource - crm_resource run with extra arguments =#=#=#= Begin test: List all available resource options (invalid type) =#=#=#= crm_resource: Error parsing option --list-options =#=#=#= End test: List all available resource options (invalid type) - Incorrect usage (64) =#=#=#= * Passed: crm_resource - List all available resource options (invalid type) =#=#=#= Begin test: List all available resource options (invalid type) (XML) =#=#=#= crm_resource: Error parsing option --list-options =#=#=#= End test: List all available resource options (invalid type) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_resource - List all available resource options (invalid type) (XML) =#=#=#= Begin test: List non-advanced primitive meta-attributes =#=#=#= Primitive meta-attributes Meta-attributes applicable to primitive resources * priority: Resource assignment priority * If not all resources can be active, the cluster will stop lower-priority resources in order to keep higher-priority ones active. * Possible values: score (default: ) * critical: Default value for influence in colocation constraints * Use this value as the default for influence in all colocation constraints involving this resource, as well as in the implicit colocation constraints created if this resource is in a group. * Possible values: boolean (default: ) * target-role: State the cluster should attempt to keep this resource in * "Stopped" forces the resource to be stopped. "Started" allows the resource to be started (and in the case of promotable clone resources, promoted if appropriate). "Unpromoted" allows the resource to be started, but only in the unpromoted role if the resource is promotable. "Promoted" is equivalent to "Started". * Possible values: "Stopped", "Started" (default), "Unpromoted", "Promoted" * is-managed: Whether the cluster is allowed to actively change the resource's state * If false, the cluster will not start, stop, promote, or demote the resource on any node. Recurring actions for the resource are unaffected. If true, a true value for the maintenance-mode cluster option, the maintenance node attribute, or the maintenance resource meta-attribute overrides this. * Possible values: boolean (default: ) * maintenance: If true, the cluster will not schedule any actions involving the resource * If true, the cluster will not start, stop, promote, or demote the resource on any node, and will pause any recurring monitors (except those specifying role as "Stopped"). If false, a true value for the maintenance-mode cluster option or maintenance node attribute overrides this. * Possible values: boolean (default: ) * resource-stickiness: Score to add to the current node when a resource is already active * Score to add to the current node when a resource is already active. This allows running resources to stay where they are, even if they would be placed elsewhere if they were being started from a stopped state. The default is 1 for individual clone instances, and 0 for all other resources. * Possible values: score (no default) * requires: Conditions under which the resource can be started * Conditions under which the resource can be started. "nothing" means the cluster can always start this resource. "quorum" means the cluster can start this resource only if a majority of the configured nodes are active. "fencing" means the cluster can start this resource only if a majority of the configured nodes are active and any failed or unknown nodes have been fenced. "unfencing" means the cluster can start this resource only if a majority of the configured nodes are active and any failed or unknown nodes have been fenced, and only on nodes that have been unfenced. The default is "quorum" for resources with a class of stonith; otherwise, "unfencing" if unfencing is active in the cluster; otherwise, "fencing" if the stonith-enabled cluster option is true; otherwise, "quorum". * Possible values: "nothing", "quorum", "fencing", "unfencing" * migration-threshold: Number of failures on a node before the resource becomes ineligible to run there. * Number of failures that may occur for this resource on a node, before that node is marked ineligible to host this resource. A value of 0 indicates that this feature is disabled (the node will never be marked ineligible). By contrast, the cluster treats "INFINITY" (the default) as a very large but finite number. This option has an effect only if the failed operation specifies its on-fail attribute as "restart" (the default), and additionally for failed start operations, if the start-failure-is-fatal cluster property is set to false. * Possible values: score (default: ) * failure-timeout: Number of seconds before acting as if a failure had not occurred * Number of seconds after a failed action for this resource before acting as if the failure had not occurred, and potentially allowing the resource back to the node on which it failed. A value of 0 indicates that this feature is disabled. * Possible values: duration (default: ) * multiple-active: What to do if the cluster finds the resource active on more than one node * What to do if the cluster finds the resource active on more than one node. "block" means to mark the resource as unmanaged. "stop_only" means to stop all active instances of this resource and leave them stopped. "stop_start" means to stop all active instances of this resource and start the resource in one location only. "stop_unexpected" means to stop all active instances of this resource except where the resource should be active. (This should be used only when extra instances are not expected to disrupt existing instances, and the resource agent's monitor of an existing instance is capable of detecting any problems that could be caused. Note that any resources ordered after this one will still need to be restarted.) * Possible values: "block", "stop_only", "stop_start" (default), "stop_unexpected" * allow-migrate: Whether the cluster should try to "live migrate" this resource when it needs to be moved * Whether the cluster should try to "live migrate" this resource when it needs to be moved. The default is true for ocf:pacemaker:remote resources, and false otherwise. * Possible values: boolean (no default) * allow-unhealthy-nodes: Whether the resource should be allowed to run on a node even if the node's health score would otherwise prevent it * Possible values: boolean (default: ) * container-attribute-target: Where to check user-defined node attributes * Whether to check user-defined node attributes on the physical host where a container is running or on the local node. This is usually set for a bundle resource and inherited by the bundle's primitive resource. A value of "host" means to check user-defined node attributes on the underlying physical host. Any other value means to check user-defined node attributes on the local node (for a bundled primitive resource, this is the bundle node). * Possible values: string (no default) * remote-node: Name of the Pacemaker Remote guest node this resource is associated with, if any * Name of the Pacemaker Remote guest node this resource is associated with, if any. If specified, this both enables the resource as a guest node and defines the unique name used to identify the guest node. The guest must be configured to run the Pacemaker Remote daemon when it is started. WARNING: This value cannot overlap with any resource or node IDs. * Possible values: string (no default) * remote-addr: If remote-node is specified, the IP address or hostname used to connect to the guest via Pacemaker Remote * If remote-node is specified, the IP address or hostname used to connect to the guest via Pacemaker Remote. The Pacemaker Remote daemon on the guest must be configured to accept connections on this address. The default is the value of the remote-node meta-attribute. * Possible values: string (no default) * remote-port: If remote-node is specified, port on the guest used for its Pacemaker Remote connection * If remote-node is specified, the port on the guest used for its Pacemaker Remote connection. The Pacemaker Remote daemon on the guest must be configured to listen on this port. * Possible values: port (default: ) * remote-connect-timeout: If remote-node is specified, how long before a pending Pacemaker Remote guest connection times out. * Possible values: timeout (default: ) * remote-allow-migrate: If remote-node is specified, this acts as the allow-migrate meta-attribute for the implicit remote connection resource (ocf:pacemaker:remote). * Possible values: boolean (default: ) =#=#=#= End test: List non-advanced primitive meta-attributes - OK (0) =#=#=#= * Passed: crm_resource - List non-advanced primitive meta-attributes =#=#=#= Begin test: List non-advanced primitive meta-attributes (XML) (shows all) =#=#=#= 1.1 Meta-attributes applicable to primitive resources Primitive meta-attributes If not all resources can be active, the cluster will stop lower-priority resources in order to keep higher-priority ones active. Resource assignment priority Use this value as the default for influence in all colocation constraints involving this resource, as well as in the implicit colocation constraints created if this resource is in a group. Default value for influence in colocation constraints "Stopped" forces the resource to be stopped. "Started" allows the resource to be started (and in the case of promotable clone resources, promoted if appropriate). "Unpromoted" allows the resource to be started, but only in the unpromoted role if the resource is promotable. "Promoted" is equivalent to "Started". State the cluster should attempt to keep this resource in If false, the cluster will not start, stop, promote, or demote the resource on any node. Recurring actions for the resource are unaffected. If true, a true value for the maintenance-mode cluster option, the maintenance node attribute, or the maintenance resource meta-attribute overrides this. Whether the cluster is allowed to actively change the resource's state If true, the cluster will not start, stop, promote, or demote the resource on any node, and will pause any recurring monitors (except those specifying role as "Stopped"). If false, a true value for the maintenance-mode cluster option or maintenance node attribute overrides this. If true, the cluster will not schedule any actions involving the resource Score to add to the current node when a resource is already active. This allows running resources to stay where they are, even if they would be placed elsewhere if they were being started from a stopped state. The default is 1 for individual clone instances, and 0 for all other resources. Score to add to the current node when a resource is already active Conditions under which the resource can be started. "nothing" means the cluster can always start this resource. "quorum" means the cluster can start this resource only if a majority of the configured nodes are active. "fencing" means the cluster can start this resource only if a majority of the configured nodes are active and any failed or unknown nodes have been fenced. "unfencing" means the cluster can start this resource only if a majority of the configured nodes are active and any failed or unknown nodes have been fenced, and only on nodes that have been unfenced. The default is "quorum" for resources with a class of stonith; otherwise, "unfencing" if unfencing is active in the cluster; otherwise, "fencing" if the stonith-enabled cluster option is true; otherwise, "quorum". Conditions under which the resource can be started Number of failures that may occur for this resource on a node, before that node is marked ineligible to host this resource. A value of 0 indicates that this feature is disabled (the node will never be marked ineligible). By contrast, the cluster treats "INFINITY" (the default) as a very large but finite number. This option has an effect only if the failed operation specifies its on-fail attribute as "restart" (the default), and additionally for failed start operations, if the start-failure-is-fatal cluster property is set to false. Number of failures on a node before the resource becomes ineligible to run there. Number of seconds after a failed action for this resource before acting as if the failure had not occurred, and potentially allowing the resource back to the node on which it failed. A value of 0 indicates that this feature is disabled. Number of seconds before acting as if a failure had not occurred What to do if the cluster finds the resource active on more than one node. "block" means to mark the resource as unmanaged. "stop_only" means to stop all active instances of this resource and leave them stopped. "stop_start" means to stop all active instances of this resource and start the resource in one location only. "stop_unexpected" means to stop all active instances of this resource except where the resource should be active. (This should be used only when extra instances are not expected to disrupt existing instances, and the resource agent's monitor of an existing instance is capable of detecting any problems that could be caused. Note that any resources ordered after this one will still need to be restarted.) What to do if the cluster finds the resource active on more than one node Whether the cluster should try to "live migrate" this resource when it needs to be moved. The default is true for ocf:pacemaker:remote resources, and false otherwise. Whether the cluster should try to "live migrate" this resource when it needs to be moved Whether the resource should be allowed to run on a node even if the node's health score would otherwise prevent it Whether the resource should be allowed to run on a node even if the node's health score would otherwise prevent it Whether to check user-defined node attributes on the physical host where a container is running or on the local node. This is usually set for a bundle resource and inherited by the bundle's primitive resource. A value of "host" means to check user-defined node attributes on the underlying physical host. Any other value means to check user-defined node attributes on the local node (for a bundled primitive resource, this is the bundle node). Where to check user-defined node attributes Name of the Pacemaker Remote guest node this resource is associated with, if any. If specified, this both enables the resource as a guest node and defines the unique name used to identify the guest node. The guest must be configured to run the Pacemaker Remote daemon when it is started. WARNING: This value cannot overlap with any resource or node IDs. Name of the Pacemaker Remote guest node this resource is associated with, if any If remote-node is specified, the IP address or hostname used to connect to the guest via Pacemaker Remote. The Pacemaker Remote daemon on the guest must be configured to accept connections on this address. The default is the value of the remote-node meta-attribute. If remote-node is specified, the IP address or hostname used to connect to the guest via Pacemaker Remote If remote-node is specified, the port on the guest used for its Pacemaker Remote connection. The Pacemaker Remote daemon on the guest must be configured to listen on this port. If remote-node is specified, port on the guest used for its Pacemaker Remote connection If remote-node is specified, how long before a pending Pacemaker Remote guest connection times out. If remote-node is specified, how long before a pending Pacemaker Remote guest connection times out. If remote-node is specified, this acts as the allow-migrate meta-attribute for the implicit remote connection resource (ocf:pacemaker:remote). If remote-node is specified, this acts as the allow-migrate meta-attribute for the implicit remote connection resource (ocf:pacemaker:remote). =#=#=#= End test: List non-advanced primitive meta-attributes (XML) (shows all) - OK (0) =#=#=#= * Passed: crm_resource - List non-advanced primitive meta-attributes (XML) (shows all) =#=#=#= Begin test: List all available primitive meta-attributes =#=#=#= Primitive meta-attributes Meta-attributes applicable to primitive resources * priority: Resource assignment priority * If not all resources can be active, the cluster will stop lower-priority resources in order to keep higher-priority ones active. * Possible values: score (default: ) * critical: Default value for influence in colocation constraints * Use this value as the default for influence in all colocation constraints involving this resource, as well as in the implicit colocation constraints created if this resource is in a group. * Possible values: boolean (default: ) * target-role: State the cluster should attempt to keep this resource in * "Stopped" forces the resource to be stopped. "Started" allows the resource to be started (and in the case of promotable clone resources, promoted if appropriate). "Unpromoted" allows the resource to be started, but only in the unpromoted role if the resource is promotable. "Promoted" is equivalent to "Started". * Possible values: "Stopped", "Started" (default), "Unpromoted", "Promoted" * is-managed: Whether the cluster is allowed to actively change the resource's state * If false, the cluster will not start, stop, promote, or demote the resource on any node. Recurring actions for the resource are unaffected. If true, a true value for the maintenance-mode cluster option, the maintenance node attribute, or the maintenance resource meta-attribute overrides this. * Possible values: boolean (default: ) * maintenance: If true, the cluster will not schedule any actions involving the resource * If true, the cluster will not start, stop, promote, or demote the resource on any node, and will pause any recurring monitors (except those specifying role as "Stopped"). If false, a true value for the maintenance-mode cluster option or maintenance node attribute overrides this. * Possible values: boolean (default: ) * resource-stickiness: Score to add to the current node when a resource is already active * Score to add to the current node when a resource is already active. This allows running resources to stay where they are, even if they would be placed elsewhere if they were being started from a stopped state. The default is 1 for individual clone instances, and 0 for all other resources. * Possible values: score (no default) * requires: Conditions under which the resource can be started * Conditions under which the resource can be started. "nothing" means the cluster can always start this resource. "quorum" means the cluster can start this resource only if a majority of the configured nodes are active. "fencing" means the cluster can start this resource only if a majority of the configured nodes are active and any failed or unknown nodes have been fenced. "unfencing" means the cluster can start this resource only if a majority of the configured nodes are active and any failed or unknown nodes have been fenced, and only on nodes that have been unfenced. The default is "quorum" for resources with a class of stonith; otherwise, "unfencing" if unfencing is active in the cluster; otherwise, "fencing" if the stonith-enabled cluster option is true; otherwise, "quorum". * Possible values: "nothing", "quorum", "fencing", "unfencing" * migration-threshold: Number of failures on a node before the resource becomes ineligible to run there. * Number of failures that may occur for this resource on a node, before that node is marked ineligible to host this resource. A value of 0 indicates that this feature is disabled (the node will never be marked ineligible). By contrast, the cluster treats "INFINITY" (the default) as a very large but finite number. This option has an effect only if the failed operation specifies its on-fail attribute as "restart" (the default), and additionally for failed start operations, if the start-failure-is-fatal cluster property is set to false. * Possible values: score (default: ) * failure-timeout: Number of seconds before acting as if a failure had not occurred * Number of seconds after a failed action for this resource before acting as if the failure had not occurred, and potentially allowing the resource back to the node on which it failed. A value of 0 indicates that this feature is disabled. * Possible values: duration (default: ) * multiple-active: What to do if the cluster finds the resource active on more than one node * What to do if the cluster finds the resource active on more than one node. "block" means to mark the resource as unmanaged. "stop_only" means to stop all active instances of this resource and leave them stopped. "stop_start" means to stop all active instances of this resource and start the resource in one location only. "stop_unexpected" means to stop all active instances of this resource except where the resource should be active. (This should be used only when extra instances are not expected to disrupt existing instances, and the resource agent's monitor of an existing instance is capable of detecting any problems that could be caused. Note that any resources ordered after this one will still need to be restarted.) * Possible values: "block", "stop_only", "stop_start" (default), "stop_unexpected" * allow-migrate: Whether the cluster should try to "live migrate" this resource when it needs to be moved * Whether the cluster should try to "live migrate" this resource when it needs to be moved. The default is true for ocf:pacemaker:remote resources, and false otherwise. * Possible values: boolean (no default) * allow-unhealthy-nodes: Whether the resource should be allowed to run on a node even if the node's health score would otherwise prevent it * Possible values: boolean (default: ) * container-attribute-target: Where to check user-defined node attributes * Whether to check user-defined node attributes on the physical host where a container is running or on the local node. This is usually set for a bundle resource and inherited by the bundle's primitive resource. A value of "host" means to check user-defined node attributes on the underlying physical host. Any other value means to check user-defined node attributes on the local node (for a bundled primitive resource, this is the bundle node). * Possible values: string (no default) * remote-node: Name of the Pacemaker Remote guest node this resource is associated with, if any * Name of the Pacemaker Remote guest node this resource is associated with, if any. If specified, this both enables the resource as a guest node and defines the unique name used to identify the guest node. The guest must be configured to run the Pacemaker Remote daemon when it is started. WARNING: This value cannot overlap with any resource or node IDs. * Possible values: string (no default) * remote-addr: If remote-node is specified, the IP address or hostname used to connect to the guest via Pacemaker Remote * If remote-node is specified, the IP address or hostname used to connect to the guest via Pacemaker Remote. The Pacemaker Remote daemon on the guest must be configured to accept connections on this address. The default is the value of the remote-node meta-attribute. * Possible values: string (no default) * remote-port: If remote-node is specified, port on the guest used for its Pacemaker Remote connection * If remote-node is specified, the port on the guest used for its Pacemaker Remote connection. The Pacemaker Remote daemon on the guest must be configured to listen on this port. * Possible values: port (default: ) * remote-connect-timeout: If remote-node is specified, how long before a pending Pacemaker Remote guest connection times out. * Possible values: timeout (default: ) * remote-allow-migrate: If remote-node is specified, this acts as the allow-migrate meta-attribute for the implicit remote connection resource (ocf:pacemaker:remote). * Possible values: boolean (default: ) =#=#=#= End test: List all available primitive meta-attributes - OK (0) =#=#=#= * Passed: crm_resource - List all available primitive meta-attributes =#=#=#= Begin test: List all available primitive meta-attributes (XML) =#=#=#= 1.1 Meta-attributes applicable to primitive resources Primitive meta-attributes If not all resources can be active, the cluster will stop lower-priority resources in order to keep higher-priority ones active. Resource assignment priority Use this value as the default for influence in all colocation constraints involving this resource, as well as in the implicit colocation constraints created if this resource is in a group. Default value for influence in colocation constraints "Stopped" forces the resource to be stopped. "Started" allows the resource to be started (and in the case of promotable clone resources, promoted if appropriate). "Unpromoted" allows the resource to be started, but only in the unpromoted role if the resource is promotable. "Promoted" is equivalent to "Started". State the cluster should attempt to keep this resource in If false, the cluster will not start, stop, promote, or demote the resource on any node. Recurring actions for the resource are unaffected. If true, a true value for the maintenance-mode cluster option, the maintenance node attribute, or the maintenance resource meta-attribute overrides this. Whether the cluster is allowed to actively change the resource's state If true, the cluster will not start, stop, promote, or demote the resource on any node, and will pause any recurring monitors (except those specifying role as "Stopped"). If false, a true value for the maintenance-mode cluster option or maintenance node attribute overrides this. If true, the cluster will not schedule any actions involving the resource Score to add to the current node when a resource is already active. This allows running resources to stay where they are, even if they would be placed elsewhere if they were being started from a stopped state. The default is 1 for individual clone instances, and 0 for all other resources. Score to add to the current node when a resource is already active Conditions under which the resource can be started. "nothing" means the cluster can always start this resource. "quorum" means the cluster can start this resource only if a majority of the configured nodes are active. "fencing" means the cluster can start this resource only if a majority of the configured nodes are active and any failed or unknown nodes have been fenced. "unfencing" means the cluster can start this resource only if a majority of the configured nodes are active and any failed or unknown nodes have been fenced, and only on nodes that have been unfenced. The default is "quorum" for resources with a class of stonith; otherwise, "unfencing" if unfencing is active in the cluster; otherwise, "fencing" if the stonith-enabled cluster option is true; otherwise, "quorum". Conditions under which the resource can be started Number of failures that may occur for this resource on a node, before that node is marked ineligible to host this resource. A value of 0 indicates that this feature is disabled (the node will never be marked ineligible). By contrast, the cluster treats "INFINITY" (the default) as a very large but finite number. This option has an effect only if the failed operation specifies its on-fail attribute as "restart" (the default), and additionally for failed start operations, if the start-failure-is-fatal cluster property is set to false. Number of failures on a node before the resource becomes ineligible to run there. Number of seconds after a failed action for this resource before acting as if the failure had not occurred, and potentially allowing the resource back to the node on which it failed. A value of 0 indicates that this feature is disabled. Number of seconds before acting as if a failure had not occurred What to do if the cluster finds the resource active on more than one node. "block" means to mark the resource as unmanaged. "stop_only" means to stop all active instances of this resource and leave them stopped. "stop_start" means to stop all active instances of this resource and start the resource in one location only. "stop_unexpected" means to stop all active instances of this resource except where the resource should be active. (This should be used only when extra instances are not expected to disrupt existing instances, and the resource agent's monitor of an existing instance is capable of detecting any problems that could be caused. Note that any resources ordered after this one will still need to be restarted.) What to do if the cluster finds the resource active on more than one node Whether the cluster should try to "live migrate" this resource when it needs to be moved. The default is true for ocf:pacemaker:remote resources, and false otherwise. Whether the cluster should try to "live migrate" this resource when it needs to be moved Whether the resource should be allowed to run on a node even if the node's health score would otherwise prevent it Whether the resource should be allowed to run on a node even if the node's health score would otherwise prevent it Whether to check user-defined node attributes on the physical host where a container is running or on the local node. This is usually set for a bundle resource and inherited by the bundle's primitive resource. A value of "host" means to check user-defined node attributes on the underlying physical host. Any other value means to check user-defined node attributes on the local node (for a bundled primitive resource, this is the bundle node). Where to check user-defined node attributes Name of the Pacemaker Remote guest node this resource is associated with, if any. If specified, this both enables the resource as a guest node and defines the unique name used to identify the guest node. The guest must be configured to run the Pacemaker Remote daemon when it is started. WARNING: This value cannot overlap with any resource or node IDs. Name of the Pacemaker Remote guest node this resource is associated with, if any If remote-node is specified, the IP address or hostname used to connect to the guest via Pacemaker Remote. The Pacemaker Remote daemon on the guest must be configured to accept connections on this address. The default is the value of the remote-node meta-attribute. If remote-node is specified, the IP address or hostname used to connect to the guest via Pacemaker Remote If remote-node is specified, the port on the guest used for its Pacemaker Remote connection. The Pacemaker Remote daemon on the guest must be configured to listen on this port. If remote-node is specified, port on the guest used for its Pacemaker Remote connection If remote-node is specified, how long before a pending Pacemaker Remote guest connection times out. If remote-node is specified, how long before a pending Pacemaker Remote guest connection times out. If remote-node is specified, this acts as the allow-migrate meta-attribute for the implicit remote connection resource (ocf:pacemaker:remote). If remote-node is specified, this acts as the allow-migrate meta-attribute for the implicit remote connection resource (ocf:pacemaker:remote). =#=#=#= End test: List all available primitive meta-attributes (XML) - OK (0) =#=#=#= * Passed: crm_resource - List all available primitive meta-attributes (XML) =#=#=#= Begin test: List non-advanced fencing parameters =#=#=#= Fencing resource common parameters Special parameters that are available for all fencing resources, regardless of type. They are processed by Pacemaker, rather than by the fence agent or the fencing library. * pcmk_host_map: A mapping of node names to port numbers for devices that do not support node names. * For example, "node1:1;node2:2,3" would tell the cluster to use port 1 for node1 and ports 2 and 3 for node2. * Possible values: string (no default) * pcmk_host_list: Nodes targeted by this device * Comma-separated list of nodes that can be targeted by this device (for example, "node1,node2,node3"). If pcmk_host_check is "static-list", either this or pcmk_host_map must be set. * Possible values: string (no default) * pcmk_host_check: How to determine which nodes can be targeted by the device * Use "dynamic-list" to query the device via the 'list' command; "static-list" to check the pcmk_host_list attribute; "status" to query the device via the 'status' command; or "none" to assume every device can fence every node. The default value is "static-list" if pcmk_host_map or pcmk_host_list is set; otherwise "dynamic-list" if the device supports the list operation; otherwise "status" if the device supports the status operation; otherwise "none" * Possible values: "dynamic-list", "static-list", "status", "none" * pcmk_delay_max: Enable a delay of no more than the time specified before executing fencing actions. * Enable a delay of no more than the time specified before executing fencing actions. Pacemaker derives the overall delay by taking the value of pcmk_delay_base and adding a random delay value such that the sum is kept below this maximum. * Possible values: duration (default: ) * pcmk_delay_base: Enable a base delay for fencing actions and specify base delay value. * This enables a static delay for fencing actions, which can help avoid "death matches" where two nodes try to fence each other at the same time. If pcmk_delay_max is also used, a random delay will be added such that the total delay is kept below that value. This can be set to a single time value to apply to any node targeted by this device (useful if a separate device is configured for each target), or to a node map (for example, "node1:1s;node2:5") to set a different value for each target. * Possible values: string (default: ) * pcmk_action_limit: The maximum number of actions can be performed in parallel on this device * Cluster property concurrent-fencing="true" needs to be configured first. Then use this to specify the maximum number of actions can be performed in parallel on this device. A value of -1 means an unlimited number of actions can be performed in parallel. * Possible values: integer (default: ) =#=#=#= End test: List non-advanced fencing parameters - OK (0) =#=#=#= * Passed: crm_resource - List non-advanced fencing parameters =#=#=#= Begin test: List non-advanced fencing parameters (XML) (shows all) =#=#=#= 1.1 Special parameters that are available for all fencing resources, regardless of type. They are processed by Pacemaker, rather than by the fence agent or the fencing library. Fencing resource common parameters Some devices do not support the standard 'port' parameter or may provide additional ones. Use this to specify an alternate, device-specific, parameter that should indicate the machine to be fenced. A value of "none" can be used to tell the cluster not to supply any additional parameters. An alternate parameter to supply instead of 'port' For example, "node1:1;node2:2,3" would tell the cluster to use port 1 for node1 and ports 2 and 3 for node2. A mapping of node names to port numbers for devices that do not support node names. Comma-separated list of nodes that can be targeted by this device (for example, "node1,node2,node3"). If pcmk_host_check is "static-list", either this or pcmk_host_map must be set. Nodes targeted by this device Use "dynamic-list" to query the device via the 'list' command; "static-list" to check the pcmk_host_list attribute; "status" to query the device via the 'status' command; or "none" to assume every device can fence every node. The default value is "static-list" if pcmk_host_map or pcmk_host_list is set; otherwise "dynamic-list" if the device supports the list operation; otherwise "status" if the device supports the status operation; otherwise "none" How to determine which nodes can be targeted by the device Enable a delay of no more than the time specified before executing fencing actions. Pacemaker derives the overall delay by taking the value of pcmk_delay_base and adding a random delay value such that the sum is kept below this maximum. Enable a delay of no more than the time specified before executing fencing actions. This enables a static delay for fencing actions, which can help avoid "death matches" where two nodes try to fence each other at the same time. If pcmk_delay_max is also used, a random delay will be added such that the total delay is kept below that value. This can be set to a single time value to apply to any node targeted by this device (useful if a separate device is configured for each target), or to a node map (for example, "node1:1s;node2:5") to set a different value for each target. Enable a base delay for fencing actions and specify base delay value. Cluster property concurrent-fencing="true" needs to be configured first. Then use this to specify the maximum number of actions can be performed in parallel on this device. A value of -1 means an unlimited number of actions can be performed in parallel. The maximum number of actions can be performed in parallel on this device Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'reboot' action. An alternate command to run instead of 'reboot' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'reboot' actions. Specify an alternate timeout to use for 'reboot' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'reboot' action before giving up. The maximum number of times to try the 'reboot' command within the timeout period Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'off' action. An alternate command to run instead of 'off' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'off' actions. Specify an alternate timeout to use for 'off' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'off' action before giving up. The maximum number of times to try the 'off' command within the timeout period Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'on' action. An alternate command to run instead of 'on' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'on' actions. Specify an alternate timeout to use for 'on' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'on' action before giving up. The maximum number of times to try the 'on' command within the timeout period Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'list' action. An alternate command to run instead of 'list' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'list' actions. Specify an alternate timeout to use for 'list' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'list' action before giving up. The maximum number of times to try the 'list' command within the timeout period Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'monitor' action. An alternate command to run instead of 'monitor' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'monitor' actions. Specify an alternate timeout to use for 'monitor' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'monitor' action before giving up. The maximum number of times to try the 'monitor' command within the timeout period Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'status' action. An alternate command to run instead of 'status' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'status' actions. Specify an alternate timeout to use for 'status' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'status' action before giving up. The maximum number of times to try the 'status' command within the timeout period =#=#=#= End test: List non-advanced fencing parameters (XML) (shows all) - OK (0) =#=#=#= * Passed: crm_resource - List non-advanced fencing parameters (XML) (shows all) =#=#=#= Begin test: List all available fencing parameters =#=#=#= Fencing resource common parameters Special parameters that are available for all fencing resources, regardless of type. They are processed by Pacemaker, rather than by the fence agent or the fencing library. * pcmk_host_map: A mapping of node names to port numbers for devices that do not support node names. * For example, "node1:1;node2:2,3" would tell the cluster to use port 1 for node1 and ports 2 and 3 for node2. * Possible values: string (no default) * pcmk_host_list: Nodes targeted by this device * Comma-separated list of nodes that can be targeted by this device (for example, "node1,node2,node3"). If pcmk_host_check is "static-list", either this or pcmk_host_map must be set. * Possible values: string (no default) * pcmk_host_check: How to determine which nodes can be targeted by the device * Use "dynamic-list" to query the device via the 'list' command; "static-list" to check the pcmk_host_list attribute; "status" to query the device via the 'status' command; or "none" to assume every device can fence every node. The default value is "static-list" if pcmk_host_map or pcmk_host_list is set; otherwise "dynamic-list" if the device supports the list operation; otherwise "status" if the device supports the status operation; otherwise "none" * Possible values: "dynamic-list", "static-list", "status", "none" * pcmk_delay_max: Enable a delay of no more than the time specified before executing fencing actions. * Enable a delay of no more than the time specified before executing fencing actions. Pacemaker derives the overall delay by taking the value of pcmk_delay_base and adding a random delay value such that the sum is kept below this maximum. * Possible values: duration (default: ) * pcmk_delay_base: Enable a base delay for fencing actions and specify base delay value. * This enables a static delay for fencing actions, which can help avoid "death matches" where two nodes try to fence each other at the same time. If pcmk_delay_max is also used, a random delay will be added such that the total delay is kept below that value. This can be set to a single time value to apply to any node targeted by this device (useful if a separate device is configured for each target), or to a node map (for example, "node1:1s;node2:5") to set a different value for each target. * Possible values: string (default: ) * pcmk_action_limit: The maximum number of actions can be performed in parallel on this device * Cluster property concurrent-fencing="true" needs to be configured first. Then use this to specify the maximum number of actions can be performed in parallel on this device. A value of -1 means an unlimited number of actions can be performed in parallel. * Possible values: integer (default: ) * ADVANCED OPTIONS: * pcmk_host_argument: An alternate parameter to supply instead of 'port' * Some devices do not support the standard 'port' parameter or may provide additional ones. Use this to specify an alternate, device-specific, parameter that should indicate the machine to be fenced. A value of "none" can be used to tell the cluster not to supply any additional parameters. * Possible values: string (default: ) * pcmk_reboot_action: An alternate command to run instead of 'reboot' * Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'reboot' action. * Possible values: string (default: ) * pcmk_reboot_timeout: Specify an alternate timeout to use for 'reboot' actions instead of stonith-timeout * Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'reboot' actions. * Possible values: timeout (default: ) * pcmk_reboot_retries: The maximum number of times to try the 'reboot' command within the timeout period * Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'reboot' action before giving up. * Possible values: integer (default: ) * pcmk_off_action: An alternate command to run instead of 'off' * Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'off' action. * Possible values: string (default: ) * pcmk_off_timeout: Specify an alternate timeout to use for 'off' actions instead of stonith-timeout * Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'off' actions. * Possible values: timeout (default: ) * pcmk_off_retries: The maximum number of times to try the 'off' command within the timeout period * Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'off' action before giving up. * Possible values: integer (default: ) * pcmk_on_action: An alternate command to run instead of 'on' * Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'on' action. * Possible values: string (default: ) * pcmk_on_timeout: Specify an alternate timeout to use for 'on' actions instead of stonith-timeout * Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'on' actions. * Possible values: timeout (default: ) * pcmk_on_retries: The maximum number of times to try the 'on' command within the timeout period * Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'on' action before giving up. * Possible values: integer (default: ) * pcmk_list_action: An alternate command to run instead of 'list' * Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'list' action. * Possible values: string (default: ) * pcmk_list_timeout: Specify an alternate timeout to use for 'list' actions instead of stonith-timeout * Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'list' actions. * Possible values: timeout (default: ) * pcmk_list_retries: The maximum number of times to try the 'list' command within the timeout period * Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'list' action before giving up. * Possible values: integer (default: ) * pcmk_monitor_action: An alternate command to run instead of 'monitor' * Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'monitor' action. * Possible values: string (default: ) * pcmk_monitor_timeout: Specify an alternate timeout to use for 'monitor' actions instead of stonith-timeout * Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'monitor' actions. * Possible values: timeout (default: ) * pcmk_monitor_retries: The maximum number of times to try the 'monitor' command within the timeout period * Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'monitor' action before giving up. * Possible values: integer (default: ) * pcmk_status_action: An alternate command to run instead of 'status' * Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'status' action. * Possible values: string (default: ) * pcmk_status_timeout: Specify an alternate timeout to use for 'status' actions instead of stonith-timeout * Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'status' actions. * Possible values: timeout (default: ) * pcmk_status_retries: The maximum number of times to try the 'status' command within the timeout period * Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'status' action before giving up. * Possible values: integer (default: ) =#=#=#= End test: List all available fencing parameters - OK (0) =#=#=#= * Passed: crm_resource - List all available fencing parameters =#=#=#= Begin test: List all available fencing parameters (XML) =#=#=#= 1.1 Special parameters that are available for all fencing resources, regardless of type. They are processed by Pacemaker, rather than by the fence agent or the fencing library. Fencing resource common parameters Some devices do not support the standard 'port' parameter or may provide additional ones. Use this to specify an alternate, device-specific, parameter that should indicate the machine to be fenced. A value of "none" can be used to tell the cluster not to supply any additional parameters. An alternate parameter to supply instead of 'port' For example, "node1:1;node2:2,3" would tell the cluster to use port 1 for node1 and ports 2 and 3 for node2. A mapping of node names to port numbers for devices that do not support node names. Comma-separated list of nodes that can be targeted by this device (for example, "node1,node2,node3"). If pcmk_host_check is "static-list", either this or pcmk_host_map must be set. Nodes targeted by this device Use "dynamic-list" to query the device via the 'list' command; "static-list" to check the pcmk_host_list attribute; "status" to query the device via the 'status' command; or "none" to assume every device can fence every node. The default value is "static-list" if pcmk_host_map or pcmk_host_list is set; otherwise "dynamic-list" if the device supports the list operation; otherwise "status" if the device supports the status operation; otherwise "none" How to determine which nodes can be targeted by the device Enable a delay of no more than the time specified before executing fencing actions. Pacemaker derives the overall delay by taking the value of pcmk_delay_base and adding a random delay value such that the sum is kept below this maximum. Enable a delay of no more than the time specified before executing fencing actions. This enables a static delay for fencing actions, which can help avoid "death matches" where two nodes try to fence each other at the same time. If pcmk_delay_max is also used, a random delay will be added such that the total delay is kept below that value. This can be set to a single time value to apply to any node targeted by this device (useful if a separate device is configured for each target), or to a node map (for example, "node1:1s;node2:5") to set a different value for each target. Enable a base delay for fencing actions and specify base delay value. Cluster property concurrent-fencing="true" needs to be configured first. Then use this to specify the maximum number of actions can be performed in parallel on this device. A value of -1 means an unlimited number of actions can be performed in parallel. The maximum number of actions can be performed in parallel on this device Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'reboot' action. An alternate command to run instead of 'reboot' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'reboot' actions. Specify an alternate timeout to use for 'reboot' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'reboot' action before giving up. The maximum number of times to try the 'reboot' command within the timeout period Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'off' action. An alternate command to run instead of 'off' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'off' actions. Specify an alternate timeout to use for 'off' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'off' action before giving up. The maximum number of times to try the 'off' command within the timeout period Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'on' action. An alternate command to run instead of 'on' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'on' actions. Specify an alternate timeout to use for 'on' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'on' action before giving up. The maximum number of times to try the 'on' command within the timeout period Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'list' action. An alternate command to run instead of 'list' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'list' actions. Specify an alternate timeout to use for 'list' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'list' action before giving up. The maximum number of times to try the 'list' command within the timeout period Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'monitor' action. An alternate command to run instead of 'monitor' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'monitor' actions. Specify an alternate timeout to use for 'monitor' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'monitor' action before giving up. The maximum number of times to try the 'monitor' command within the timeout period Some devices do not support the standard commands or may provide additional ones. Use this to specify an alternate, device-specific, command that implements the 'status' action. An alternate command to run instead of 'status' Some devices need much more/less time to complete than normal. Use this to specify an alternate, device-specific, timeout for 'status' actions. Specify an alternate timeout to use for 'status' actions instead of stonith-timeout Some devices do not support multiple connections. Operations may "fail" if the device is busy with another task. In that case, Pacemaker will automatically retry the operation if there is time remaining. Use this option to alter the number of times Pacemaker tries a 'status' action before giving up. The maximum number of times to try the 'status' command within the timeout period =#=#=#= End test: List all available fencing parameters (XML) - OK (0) =#=#=#= * Passed: crm_resource - List all available fencing parameters (XML) =#=#=#= Begin test: crm_resource given both -r and resource config =#=#=#= crm_resource: --resource cannot be used with --class, --agent, and --provider =#=#=#= End test: crm_resource given both -r and resource config - Incorrect usage (64) =#=#=#= * Passed: crm_resource - crm_resource given both -r and resource config =#=#=#= Begin test: crm_resource given resource config with invalid action =#=#=#= crm_resource: --class, --agent, and --provider can only be used with --validate and --force-* =#=#=#= End test: crm_resource given resource config with invalid action - Incorrect usage (64) =#=#=#= * Passed: crm_resource - crm_resource given resource config with invalid action =#=#=#= Begin test: Create a resource meta attribute =#=#=#= 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 Set 'dummy' option: id=dummy-meta_attributes-is-managed set=dummy-meta_attributes name=is-managed value=false =#=#=#= Current cib after: Create a resource meta attribute =#=#=#= =#=#=#= End test: Create a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - Create a resource meta attribute =#=#=#= Begin test: Query a resource meta attribute =#=#=#= 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 false =#=#=#= Current cib after: Query a resource meta attribute =#=#=#= =#=#=#= End test: Query a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - Query a resource meta attribute =#=#=#= Begin test: Remove a resource meta attribute =#=#=#= 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 Deleted 'dummy' option: id=dummy-meta_attributes-is-managed name=is-managed =#=#=#= Current cib after: Remove a resource meta attribute =#=#=#= =#=#=#= End test: Remove a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - Remove a resource meta attribute =#=#=#= Begin test: Create another resource meta attribute =#=#=#= 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 =#=#=#= End test: Create another resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - Create another resource meta attribute =#=#=#= Begin test: Show why a resource is not running =#=#=#= 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 =#=#=#= End test: Show why a resource is not running - OK (0) =#=#=#= * Passed: crm_resource - Show why a resource is not running =#=#=#= Begin test: Remove another resource meta attribute =#=#=#= 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 =#=#=#= End test: Remove another resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - Remove another resource meta attribute =#=#=#= Begin test: Get a non-existent attribute from a resource element with output-as=xml =#=#=#= 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 Attribute 'nonexistent' not found for 'dummy' =#=#=#= End test: Get a non-existent attribute from a resource element with output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Get a non-existent attribute from a resource element with output-as=xml =#=#=#= Begin test: Get a non-existent attribute from a resource element without output-as=xml =#=#=#= 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 Attribute 'nonexistent' not found for 'dummy' =#=#=#= Current cib after: Get a non-existent attribute from a resource element without output-as=xml =#=#=#= =#=#=#= End test: Get a non-existent attribute from a resource element without output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Get a non-existent attribute from a resource element without output-as=xml =#=#=#= Begin test: Get an existent attribute from a resource element with output-as=xml =#=#=#= 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 ocf =#=#=#= End test: Get an existent attribute from a resource element with output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Get an existent attribute from a resource element with output-as=xml =#=#=#= Begin test: Get an existent attribute from a resource element without output-as=xml =#=#=#= 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 ocf =#=#=#= Current cib after: Get an existent attribute from a resource element without output-as=xml =#=#=#= =#=#=#= End test: Get an existent attribute from a resource element without output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Get an existent attribute from a resource element without output-as=xml =#=#=#= Begin test: Set a non-existent attribute for a resource element with output-as=xml =#=#=#= 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 cib after: Set a non-existent attribute for a resource element with output-as=xml =#=#=#= =#=#=#= End test: Set a non-existent attribute for a resource element with output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Set a non-existent attribute for a resource element with output-as=xml =#=#=#= Begin test: Set an existent attribute for a resource element with output-as=xml =#=#=#= 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 cib after: Set an existent attribute for a resource element with output-as=xml =#=#=#= - + =#=#=#= End test: Set an existent attribute for a resource element with output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Set an existent attribute for a resource element with output-as=xml =#=#=#= Begin test: Delete an existent attribute for a resource element with output-as=xml =#=#=#= 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 cib after: Delete an existent attribute for a resource element with output-as=xml =#=#=#= - + =#=#=#= End test: Delete an existent attribute for a resource element with output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Delete an existent attribute for a resource element with output-as=xml =#=#=#= Begin test: Delete a non-existent attribute for a resource element with output-as=xml =#=#=#= 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 cib after: Delete a non-existent attribute for a resource element with output-as=xml =#=#=#= - + =#=#=#= End test: Delete a non-existent attribute for a resource element with output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Delete a non-existent attribute for a resource element with output-as=xml =#=#=#= Begin test: Set a non-existent attribute for a resource element without output-as=xml =#=#=#= 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 Set attribute: name=description value=test_description =#=#=#= Current cib after: Set a non-existent attribute for a resource element without output-as=xml =#=#=#= - + =#=#=#= End test: Set a non-existent attribute for a resource element without output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Set a non-existent attribute for a resource element without output-as=xml =#=#=#= Begin test: Set an existent attribute for a resource element without output-as=xml =#=#=#= 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 Set attribute: name=description value=test_description =#=#=#= Current cib after: Set an existent attribute for a resource element without output-as=xml =#=#=#= - + =#=#=#= End test: Set an existent attribute for a resource element without output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Set an existent attribute for a resource element without output-as=xml =#=#=#= Begin test: Delete an existent attribute for a resource element without output-as=xml =#=#=#= 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 Deleted attribute: description =#=#=#= Current cib after: Delete an existent attribute for a resource element without output-as=xml =#=#=#= - + =#=#=#= End test: Delete an existent attribute for a resource element without output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Delete an existent attribute for a resource element without output-as=xml =#=#=#= Begin test: Delete a non-existent attribute for a resource element without output-as=xml =#=#=#= 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 Deleted attribute: description =#=#=#= Current cib after: Delete a non-existent attribute for a resource element without output-as=xml =#=#=#= - + =#=#=#= End test: Delete a non-existent attribute for a resource element without output-as=xml - OK (0) =#=#=#= * Passed: crm_resource - Delete a non-existent attribute for a resource element without output-as=xml =#=#=#= Begin test: Create a resource attribute =#=#=#= 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 Set 'dummy' option: id=dummy-instance_attributes-delay set=dummy-instance_attributes name=delay value=10s =#=#=#= Current cib after: Create a resource attribute =#=#=#= - + =#=#=#= End test: Create a resource attribute - OK (0) =#=#=#= * Passed: crm_resource - Create a resource attribute =#=#=#= Begin test: List the configured resources =#=#=#= 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 Full List of Resources: * dummy (ocf:pacemaker:Dummy): Stopped =#=#=#= Current cib after: List the configured resources =#=#=#= - + =#=#=#= End test: List the configured resources - OK (0) =#=#=#= * Passed: crm_resource - List the configured resources =#=#=#= Begin test: List the configured resources in XML =#=#=#= 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 =#=#=#= End test: List the configured resources in XML - OK (0) =#=#=#= * Passed: crm_resource - List the configured resources in XML =#=#=#= Begin test: Implicitly list the configured resources =#=#=#= 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 Full List of Resources: * dummy (ocf:pacemaker:Dummy): Stopped =#=#=#= End test: Implicitly list the configured resources - OK (0) =#=#=#= * Passed: crm_resource - Implicitly list the configured resources =#=#=#= Begin test: List IDs of instantiated resources =#=#=#= 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 dummy =#=#=#= End test: List IDs of instantiated resources - OK (0) =#=#=#= * Passed: crm_resource - List IDs of instantiated resources =#=#=#= Begin test: Show XML configuration of resource =#=#=#= 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 dummy (ocf:pacemaker:Dummy): Stopped Resource XML: =#=#=#= End test: Show XML configuration of resource - OK (0) =#=#=#= * Passed: crm_resource - Show XML configuration of resource =#=#=#= Begin test: Show XML configuration of resource, output as XML =#=#=#= 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 ]]> =#=#=#= End test: Show XML configuration of resource, output as XML - OK (0) =#=#=#= * Passed: crm_resource - Show XML configuration of resource, output as XML =#=#=#= Begin test: Require a destination when migrating a resource that is stopped =#=#=#= 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 crm_resource: Resource 'dummy' not moved: active in 0 locations. To prevent 'dummy' from running on a specific location, specify a node. =#=#=#= Current cib after: Require a destination when migrating a resource that is stopped =#=#=#= - + =#=#=#= End test: Require a destination when migrating a resource that is stopped - Incorrect usage (64) =#=#=#= * Passed: crm_resource - Require a destination when migrating a resource that is stopped =#=#=#= Begin test: Don't support migration to non-existent locations =#=#=#= 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 crm_resource: Node 'i.do.not.exist' not found Error performing operation: No such object =#=#=#= Current cib after: Don't support migration to non-existent locations =#=#=#= - + =#=#=#= End test: Don't support migration to non-existent locations - No such object (105) =#=#=#= * Passed: crm_resource - Don't support migration to non-existent locations =#=#=#= Begin test: Create a fencing resource =#=#=#= =#=#=#= Current cib after: Create a fencing resource =#=#=#= - + =#=#=#= End test: Create a fencing resource - OK (0) =#=#=#= * Passed: cibadmin - Create a fencing resource =#=#=#= Begin test: Bring resources online =#=#=#= Current cluster status: * Node List: * Online: [ node1 ] * Full List of Resources: * dummy (ocf:pacemaker:Dummy): Stopped * Fence (stonith:fence_true): Stopped Transition Summary: * Start dummy ( node1 ) * Start Fence ( node1 ) Executing Cluster Transition: * Resource action: dummy monitor on node1 * Resource action: Fence monitor on node1 * Resource action: dummy start on node1 * Resource action: Fence start on node1 Revised Cluster Status: * Node List: * Online: [ node1 ] * Full List of Resources: * dummy (ocf:pacemaker:Dummy): Started node1 * Fence (stonith:fence_true): Started node1 =#=#=#= Current cib after: Bring resources online =#=#=#= - + =#=#=#= End test: Bring resources online - OK (0) =#=#=#= * Passed: crm_simulate - Bring resources online =#=#=#= Begin test: Try to move a resource to its existing location =#=#=#= crm_resource: Error performing operation: Requested item already exists =#=#=#= Current cib after: Try to move a resource to its existing location =#=#=#= - + =#=#=#= End test: Try to move a resource to its existing location - Requested item already exists (108) =#=#=#= * Passed: crm_resource - Try to move a resource to its existing location =#=#=#= Begin test: Try to move a resource that doesn't exist =#=#=#= crm_resource: Resource 'xyz' not found Error performing operation: No such object =#=#=#= End test: Try to move a resource that doesn't exist - No such object (105) =#=#=#= * Passed: crm_resource - Try to move a resource that doesn't exist =#=#=#= Begin test: Move a resource from its existing location =#=#=#= WARNING: Creating rsc_location constraint 'cli-ban-dummy-on-node1' with a score of -INFINITY for resource dummy on node1. This will prevent dummy from running on node1 until the constraint is removed using the clear option or by editing the CIB with an appropriate tool. This will be the case even if node1 is the last node in the cluster =#=#=#= Current cib after: Move a resource from its existing location =#=#=#= - + =#=#=#= End test: Move a resource from its existing location - OK (0) =#=#=#= * Passed: crm_resource - Move a resource from its existing location =#=#=#= Begin test: Clear out constraints generated by --move =#=#=#= Removing constraint: cli-ban-dummy-on-node1 =#=#=#= Current cib after: Clear out constraints generated by --move =#=#=#= - + =#=#=#= End test: Clear out constraints generated by --move - OK (0) =#=#=#= * Passed: crm_resource - Clear out constraints generated by --move =#=#=#= Begin test: Default ticket granted state =#=#=#= false =#=#=#= Current cib after: Default ticket granted state =#=#=#= - + =#=#=#= End test: Default ticket granted state - OK (0) =#=#=#= * Passed: crm_ticket - Default ticket granted state =#=#=#= Begin test: Set ticket granted state =#=#=#= =#=#=#= Current cib after: Set ticket granted state =#=#=#= - + =#=#=#= End test: Set ticket granted state - OK (0) =#=#=#= * Passed: crm_ticket - Set ticket granted state =#=#=#= Begin test: List ticket IDs =#=#=#= ticketA =#=#=#= End test: List ticket IDs - OK (0) =#=#=#= * Passed: crm_ticket - List ticket IDs =#=#=#= Begin test: List ticket IDs, outputting in XML =#=#=#= =#=#=#= End test: List ticket IDs, outputting in XML - OK (0) =#=#=#= * Passed: crm_ticket - List ticket IDs, outputting in XML =#=#=#= Begin test: Query ticket state =#=#=#= State XML: =#=#=#= End test: Query ticket state - OK (0) =#=#=#= * Passed: crm_ticket - Query ticket state =#=#=#= Begin test: Query ticket state, outputting as xml =#=#=#= =#=#=#= End test: Query ticket state, outputting as xml - OK (0) =#=#=#= * Passed: crm_ticket - Query ticket state, outputting as xml =#=#=#= Begin test: Query ticket granted state =#=#=#= false =#=#=#= Current cib after: Query ticket granted state =#=#=#= - + =#=#=#= End test: Query ticket granted state - OK (0) =#=#=#= * Passed: crm_ticket - Query ticket granted state =#=#=#= Begin test: Query ticket granted state, outputting as xml =#=#=#= =#=#=#= End test: Query ticket granted state, outputting as xml - OK (0) =#=#=#= * Passed: crm_ticket - Query ticket granted state, outputting as xml =#=#=#= Begin test: Delete ticket granted state =#=#=#= =#=#=#= Current cib after: Delete ticket granted state =#=#=#= - + =#=#=#= End test: Delete ticket granted state - OK (0) =#=#=#= * Passed: crm_ticket - Delete ticket granted state =#=#=#= Begin test: Make a ticket standby =#=#=#= =#=#=#= Current cib after: Make a ticket standby =#=#=#= - + =#=#=#= End test: Make a ticket standby - OK (0) =#=#=#= * Passed: crm_ticket - Make a ticket standby =#=#=#= Begin test: Query ticket standby state =#=#=#= true =#=#=#= Current cib after: Query ticket standby state =#=#=#= - + =#=#=#= End test: Query ticket standby state - OK (0) =#=#=#= * Passed: crm_ticket - Query ticket standby state =#=#=#= Begin test: Activate a ticket =#=#=#= =#=#=#= Current cib after: Activate a ticket =#=#=#= - + =#=#=#= End test: Activate a ticket - OK (0) =#=#=#= * Passed: crm_ticket - Activate a ticket =#=#=#= Begin test: List ticket details =#=#=#= ticketA revoked (standby=false) =#=#=#= End test: List ticket details - OK (0) =#=#=#= * Passed: crm_ticket - List ticket details =#=#=#= Begin test: List ticket details, outputting as XML =#=#=#= =#=#=#= End test: List ticket details, outputting as XML - OK (0) =#=#=#= * Passed: crm_ticket - List ticket details, outputting as XML =#=#=#= Begin test: Add a second ticket =#=#=#= false =#=#=#= Current cib after: Add a second ticket =#=#=#= - + =#=#=#= End test: Add a second ticket - OK (0) =#=#=#= * Passed: crm_ticket - Add a second ticket =#=#=#= Begin test: Set second ticket granted state =#=#=#= =#=#=#= Current cib after: Set second ticket granted state =#=#=#= - + =#=#=#= End test: Set second ticket granted state - OK (0) =#=#=#= * Passed: crm_ticket - Set second ticket granted state =#=#=#= Begin test: List tickets =#=#=#= ticketA revoked ticketB revoked =#=#=#= End test: List tickets - OK (0) =#=#=#= * Passed: crm_ticket - List tickets =#=#=#= Begin test: List tickets, outputting as XML =#=#=#= =#=#=#= End test: List tickets, outputting as XML - OK (0) =#=#=#= * Passed: crm_ticket - List tickets, outputting as XML =#=#=#= Begin test: Delete second ticket =#=#=#= =#=#=#= Current cib after: Delete second ticket =#=#=#= - + =#=#=#= End test: Delete second ticket - OK (0) =#=#=#= * Passed: cibadmin - Delete second ticket =#=#=#= Begin test: Delete ticket standby state =#=#=#= =#=#=#= Current cib after: Delete ticket standby state =#=#=#= - + =#=#=#= End test: Delete ticket standby state - OK (0) =#=#=#= * Passed: crm_ticket - Delete ticket standby state =#=#=#= Begin test: Delete ticket standby state =#=#=#= =#=#=#= Current cib after: Delete ticket standby state =#=#=#= - + =#=#=#= End test: Delete ticket standby state - OK (0) =#=#=#= * Passed: cibadmin - Delete ticket standby state =#=#=#= Begin test: Query ticket constraints =#=#=#= Constraints XML: =#=#=#= End test: Query ticket constraints - OK (0) =#=#=#= * Passed: crm_ticket - Query ticket constraints =#=#=#= Begin test: Query ticket constraints, outputting as xml =#=#=#= =#=#=#= End test: Query ticket constraints, outputting as xml - OK (0) =#=#=#= * Passed: crm_ticket - Query ticket constraints, outputting as xml =#=#=#= Begin test: Delete ticket constraint =#=#=#= =#=#=#= Current cib after: Delete ticket constraint =#=#=#= - + =#=#=#= End test: Delete ticket constraint - OK (0) =#=#=#= * Passed: cibadmin - Delete ticket constraint =#=#=#= Begin test: Ban a resource on unknown node =#=#=#= crm_resource: Node 'host1' not found Error performing operation: No such object =#=#=#= Current cib after: Ban a resource on unknown node =#=#=#= - + =#=#=#= End test: Ban a resource on unknown node - No such object (105) =#=#=#= * Passed: crm_resource - Ban a resource on unknown node =#=#=#= Begin test: Create two more nodes and bring them online =#=#=#= Current cluster status: * Node List: * Online: [ node1 ] * Full List of Resources: * dummy (ocf:pacemaker:Dummy): Started node1 * Fence (stonith:fence_true): Started node1 Performing Requested Modifications: * Bringing node node2 online * Bringing node node3 online Transition Summary: * Move Fence ( node1 -> node2 ) Executing Cluster Transition: * Resource action: dummy monitor on node3 * Resource action: dummy monitor on node2 * Resource action: Fence stop on node1 * Resource action: Fence monitor on node3 * Resource action: Fence monitor on node2 * Resource action: Fence start on node2 Revised Cluster Status: * Node List: * Online: [ node1 node2 node3 ] * Full List of Resources: * dummy (ocf:pacemaker:Dummy): Started node1 * Fence (stonith:fence_true): Started node2 =#=#=#= Current cib after: Create two more nodes and bring them online =#=#=#= - + =#=#=#= End test: Create two more nodes and bring them online - OK (0) =#=#=#= * Passed: crm_simulate - Create two more nodes and bring them online =#=#=#= Begin test: Ban dummy from node1 =#=#=#= WARNING: Creating rsc_location constraint 'cli-ban-dummy-on-node1' with a score of -INFINITY for resource dummy on node1. This will prevent dummy from running on node1 until the constraint is removed using the clear option or by editing the CIB with an appropriate tool. This will be the case even if node1 is the last node in the cluster =#=#=#= Current cib after: Ban dummy from node1 =#=#=#= - + =#=#=#= End test: Ban dummy from node1 - OK (0) =#=#=#= * Passed: crm_resource - Ban dummy from node1 =#=#=#= Begin test: Show where a resource is running =#=#=#= resource dummy is running on: node1 =#=#=#= End test: Show where a resource is running - OK (0) =#=#=#= * Passed: crm_resource - Show where a resource is running =#=#=#= Begin test: Show constraints on a resource =#=#=#= Locations: * Node node1 (score=-INFINITY, id=cli-ban-dummy-on-node1, rsc=dummy) =#=#=#= End test: Show constraints on a resource - OK (0) =#=#=#= * Passed: crm_resource - Show constraints on a resource =#=#=#= Begin test: Ban dummy from node2 =#=#=#= =#=#=#= Current cib after: Ban dummy from node2 =#=#=#= - + =#=#=#= End test: Ban dummy from node2 - OK (0) =#=#=#= * Passed: crm_resource - Ban dummy from node2 =#=#=#= Begin test: Relocate resources due to ban =#=#=#= Current cluster status: * Node List: * Online: [ node1 node2 node3 ] * Full List of Resources: * dummy (ocf:pacemaker:Dummy): Started node1 * Fence (stonith:fence_true): Started node2 Transition Summary: * Move dummy ( node1 -> node3 ) Executing Cluster Transition: * Resource action: dummy stop on node1 * Resource action: dummy start on node3 Revised Cluster Status: * Node List: * Online: [ node1 node2 node3 ] * Full List of Resources: * dummy (ocf:pacemaker:Dummy): Started node3 * Fence (stonith:fence_true): Started node2 =#=#=#= Current cib after: Relocate resources due to ban =#=#=#= - + =#=#=#= End test: Relocate resources due to ban - OK (0) =#=#=#= * Passed: crm_simulate - Relocate resources due to ban =#=#=#= Begin test: Move dummy to node1 =#=#=#= =#=#=#= Current cib after: Move dummy to node1 =#=#=#= - + =#=#=#= End test: Move dummy to node1 - OK (0) =#=#=#= * Passed: crm_resource - Move dummy to node1 =#=#=#= Begin test: Clear implicit constraints for dummy on node2 =#=#=#= Removing constraint: cli-ban-dummy-on-node2 =#=#=#= Current cib after: Clear implicit constraints for dummy on node2 =#=#=#= - + =#=#=#= End test: Clear implicit constraints for dummy on node2 - OK (0) =#=#=#= * Passed: crm_resource - Clear implicit constraints for dummy on node2 =#=#=#= Begin test: Drop the status section =#=#=#= =#=#=#= End test: Drop the status section - OK (0) =#=#=#= * Passed: cibadmin - Drop the status section =#=#=#= Begin test: Create a clone =#=#=#= =#=#=#= End test: Create a clone - OK (0) =#=#=#= * Passed: cibadmin - Create a clone =#=#=#= Begin test: Create a resource meta attribute =#=#=#= Performing update of 'is-managed' on 'test-clone', the parent of 'test-primitive' Set 'test-clone' option: id=test-clone-meta_attributes-is-managed set=test-clone-meta_attributes name=is-managed value=false =#=#=#= Current cib after: Create a resource meta attribute =#=#=#= - + =#=#=#= End test: Create a resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - Create a resource meta attribute =#=#=#= Begin test: Create a resource meta attribute in the primitive =#=#=#= Set 'test-primitive' option: id=test-primitive-meta_attributes-is-managed set=test-primitive-meta_attributes name=is-managed value=false =#=#=#= Current cib after: Create a resource meta attribute in the primitive =#=#=#= - + =#=#=#= End test: Create a resource meta attribute in the primitive - OK (0) =#=#=#= * Passed: crm_resource - Create a resource meta attribute in the primitive =#=#=#= Begin test: Update resource meta attribute with duplicates =#=#=#= Multiple attributes match name=is-managed Value: false (id=test-primitive-meta_attributes-is-managed) Value: false (id=test-clone-meta_attributes-is-managed) A value for 'is-managed' already exists in child 'test-primitive', performing update on that instead of 'test-clone' Set 'test-primitive' option: id=test-primitive-meta_attributes-is-managed name=is-managed value=true =#=#=#= Current cib after: Update resource meta attribute with duplicates =#=#=#= - + =#=#=#= End test: Update resource meta attribute with duplicates - OK (0) =#=#=#= * Passed: crm_resource - Update resource meta attribute with duplicates =#=#=#= Begin test: Update resource meta attribute with duplicates (force clone) =#=#=#= Set 'test-clone' option: id=test-clone-meta_attributes-is-managed name=is-managed value=true =#=#=#= Current cib after: Update resource meta attribute with duplicates (force clone) =#=#=#= - + =#=#=#= End test: Update resource meta attribute with duplicates (force clone) - OK (0) =#=#=#= * Passed: crm_resource - Update resource meta attribute with duplicates (force clone) =#=#=#= Begin test: Update child resource meta attribute with duplicates =#=#=#= Multiple attributes match name=is-managed Value: true (id=test-primitive-meta_attributes-is-managed) Value: true (id=test-clone-meta_attributes-is-managed) Set 'test-primitive' option: id=test-primitive-meta_attributes-is-managed name=is-managed value=false =#=#=#= Current cib after: Update child resource meta attribute with duplicates =#=#=#= - + =#=#=#= End test: Update child resource meta attribute with duplicates - OK (0) =#=#=#= * Passed: crm_resource - Update child resource meta attribute with duplicates =#=#=#= Begin test: Delete resource meta attribute with duplicates =#=#=#= Multiple attributes match name=is-managed Value: false (id=test-primitive-meta_attributes-is-managed) Value: true (id=test-clone-meta_attributes-is-managed) A value for 'is-managed' already exists in child 'test-primitive', performing delete on that instead of 'test-clone' Deleted 'test-primitive' option: id=test-primitive-meta_attributes-is-managed name=is-managed =#=#=#= Current cib after: Delete resource meta attribute with duplicates =#=#=#= - + =#=#=#= End test: Delete resource meta attribute with duplicates - OK (0) =#=#=#= * Passed: crm_resource - Delete resource meta attribute with duplicates =#=#=#= Begin test: Delete resource meta attribute in parent =#=#=#= Performing delete of 'is-managed' on 'test-clone', the parent of 'test-primitive' Deleted 'test-clone' option: id=test-clone-meta_attributes-is-managed name=is-managed =#=#=#= Current cib after: Delete resource meta attribute in parent =#=#=#= - + =#=#=#= End test: Delete resource meta attribute in parent - OK (0) =#=#=#= * Passed: crm_resource - Delete resource meta attribute in parent =#=#=#= Begin test: Create a resource meta attribute in the primitive =#=#=#= Set 'test-primitive' option: id=test-primitive-meta_attributes-is-managed set=test-primitive-meta_attributes name=is-managed value=false =#=#=#= Current cib after: Create a resource meta attribute in the primitive =#=#=#= - + =#=#=#= End test: Create a resource meta attribute in the primitive - OK (0) =#=#=#= * Passed: crm_resource - Create a resource meta attribute in the primitive =#=#=#= Begin test: Update existing resource meta attribute =#=#=#= A value for 'is-managed' already exists in child 'test-primitive', performing update on that instead of 'test-clone' Set 'test-primitive' option: id=test-primitive-meta_attributes-is-managed name=is-managed value=true =#=#=#= Current cib after: Update existing resource meta attribute =#=#=#= - + =#=#=#= End test: Update existing resource meta attribute - OK (0) =#=#=#= * Passed: crm_resource - Update existing resource meta attribute =#=#=#= Begin test: Create a resource meta attribute in the parent =#=#=#= Set 'test-clone' option: id=test-clone-meta_attributes-is-managed set=test-clone-meta_attributes name=is-managed value=true =#=#=#= Current cib after: Create a resource meta attribute in the parent =#=#=#= - + =#=#=#= End test: Create a resource meta attribute in the parent - OK (0) =#=#=#= * Passed: crm_resource - Create a resource meta attribute in the parent =#=#=#= Begin test: Copy resources =#=#=#= =#=#=#= End test: Copy resources - OK (0) =#=#=#= * Passed: cibadmin - Copy resources =#=#=#= Begin test: Delete resource parent meta attribute (force) =#=#=#= Deleted 'test-clone' option: id=test-clone-meta_attributes-is-managed name=is-managed =#=#=#= Current cib after: Delete resource parent meta attribute (force) =#=#=#= - + =#=#=#= End test: Delete resource parent meta attribute (force) - OK (0) =#=#=#= * Passed: crm_resource - Delete resource parent meta attribute (force) =#=#=#= Begin test: Restore duplicates =#=#=#= =#=#=#= Current cib after: Restore duplicates =#=#=#= - + =#=#=#= End test: Restore duplicates - OK (0) =#=#=#= * Passed: cibadmin - Restore duplicates =#=#=#= Begin test: Delete resource child meta attribute =#=#=#= Multiple attributes match name=is-managed Value: true (id=test-primitive-meta_attributes-is-managed) Value: true (id=test-clone-meta_attributes-is-managed) Deleted 'test-primitive' option: id=test-primitive-meta_attributes-is-managed name=is-managed =#=#=#= Current cib after: Delete resource child meta attribute =#=#=#= - + =#=#=#= End test: Delete resource child meta attribute - OK (0) =#=#=#= * Passed: crm_resource - Delete resource child meta attribute =#=#=#= Begin test: Create the dummy-group resource group =#=#=#= =#=#=#= Current cib after: Create the dummy-group resource group =#=#=#= - + =#=#=#= End test: Create the dummy-group resource group - OK (0) =#=#=#= * Passed: cibadmin - Create the dummy-group resource group =#=#=#= Begin test: Create a resource meta attribute in dummy1 =#=#=#= Set 'dummy1' option: id=dummy1-meta_attributes-is-managed set=dummy1-meta_attributes name=is-managed value=true =#=#=#= Current cib after: Create a resource meta attribute in dummy1 =#=#=#= - + =#=#=#= End test: Create a resource meta attribute in dummy1 - OK (0) =#=#=#= * Passed: crm_resource - Create a resource meta attribute in dummy1 =#=#=#= Begin test: Create a resource meta attribute in dummy-group =#=#=#= Set 'dummy1' option: id=dummy1-meta_attributes-is-managed name=is-managed value=false Set 'dummy-group' option: id=dummy-group-meta_attributes-is-managed set=dummy-group-meta_attributes name=is-managed value=false =#=#=#= Current cib after: Create a resource meta attribute in dummy-group =#=#=#= - + =#=#=#= End test: Create a resource meta attribute in dummy-group - OK (0) =#=#=#= * Passed: crm_resource - Create a resource meta attribute in dummy-group =#=#=#= Begin test: Delete the dummy-group resource group =#=#=#= =#=#=#= Current cib after: Delete the dummy-group resource group =#=#=#= - + =#=#=#= End test: Delete the dummy-group resource group - OK (0) =#=#=#= * Passed: cibadmin - Delete the dummy-group resource group =#=#=#= Begin test: Specify a lifetime when moving a resource =#=#=#= Migration will take effect until: =#=#=#= Current cib after: Specify a lifetime when moving a resource =#=#=#= - + =#=#=#= End test: Specify a lifetime when moving a resource - OK (0) =#=#=#= * Passed: crm_resource - Specify a lifetime when moving a resource =#=#=#= Begin test: Try to move a resource previously moved with a lifetime =#=#=#= =#=#=#= Current cib after: Try to move a resource previously moved with a lifetime =#=#=#= - + =#=#=#= End test: Try to move a resource previously moved with a lifetime - OK (0) =#=#=#= * Passed: crm_resource - Try to move a resource previously moved with a lifetime =#=#=#= Begin test: Ban dummy from node1 for a short time =#=#=#= Migration will take effect until: WARNING: Creating rsc_location constraint 'cli-ban-dummy-on-node1' with a score of -INFINITY for resource dummy on node1. This will prevent dummy from running on node1 until the constraint is removed using the clear option or by editing the CIB with an appropriate tool. This will be the case even if node1 is the last node in the cluster =#=#=#= Current cib after: Ban dummy from node1 for a short time =#=#=#= - + =#=#=#= End test: Ban dummy from node1 for a short time - OK (0) =#=#=#= * Passed: crm_resource - Ban dummy from node1 for a short time =#=#=#= Begin test: Remove expired constraints =#=#=#= Removing constraint: cli-ban-dummy-on-node1 =#=#=#= Current cib after: Remove expired constraints =#=#=#= - + =#=#=#= End test: Remove expired constraints - OK (0) =#=#=#= * Passed: crm_resource - Remove expired constraints =#=#=#= Begin test: Clear all implicit constraints for dummy =#=#=#= Removing constraint: cli-prefer-dummy =#=#=#= Current cib after: Clear all implicit constraints for dummy =#=#=#= - + =#=#=#= End test: Clear all implicit constraints for dummy - OK (0) =#=#=#= * Passed: crm_resource - Clear all implicit constraints for dummy =#=#=#= Begin test: Set a node health strategy =#=#=#= =#=#=#= Current cib after: Set a node health strategy =#=#=#= - + =#=#=#= End test: Set a node health strategy - OK (0) =#=#=#= * Passed: crm_attribute - Set a node health strategy =#=#=#= Begin test: Set a node health attribute =#=#=#= =#=#=#= Current cib after: Set a node health attribute =#=#=#= - + =#=#=#= End test: Set a node health attribute - OK (0) =#=#=#= * Passed: crm_attribute - Set a node health attribute =#=#=#= Begin test: Show why a resource is not running on an unhealthy node =#=#=#= =#=#=#= End test: Show why a resource is not running on an unhealthy node - OK (0) =#=#=#= * Passed: crm_resource - Show why a resource is not running on an unhealthy node =#=#=#= Begin test: Delete a resource =#=#=#= =#=#=#= Current cib after: Delete a resource =#=#=#= - + =#=#=#= End test: Delete a resource - OK (0) =#=#=#= * Passed: crm_resource - Delete a resource =#=#=#= Begin test: Create an XML patchset =#=#=#= =#=#=#= End test: Create an XML patchset - Error occurred (1) =#=#=#= * Passed: crm_diff - Create an XML patchset =#=#=#= Begin test: Check locations and constraints for prim1 =#=#=#= =#=#=#= End test: Check locations and constraints for prim1 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim1 =#=#=#= Begin test: Recursively check locations and constraints for prim1 =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim1 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim1 =#=#=#= Begin test: Check locations and constraints for prim1 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim1 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim1 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim1 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim1 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim1 in XML =#=#=#= Begin test: Check locations and constraints for prim2 =#=#=#= Locations: * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2) Resources prim2 is colocated with: * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY) =#=#=#= End test: Check locations and constraints for prim2 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim2 =#=#=#= Begin test: Recursively check locations and constraints for prim2 =#=#=#= Locations: * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2) Resources prim2 is colocated with: * prim3 (score=INFINITY, id=colocation-prim2-prim3-INFINITY) * Resources prim3 is colocated with: * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY) * Locations: * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4) * Resources prim4 is colocated with: * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY) =#=#=#= End test: Recursively check locations and constraints for prim2 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim2 =#=#=#= Begin test: Check locations and constraints for prim2 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim2 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim2 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim2 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim2 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim2 in XML =#=#=#= Begin test: Check locations and constraints for prim3 =#=#=#= Resources colocated with prim3: * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY) * Locations: * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2) Resources prim3 is colocated with: * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY) * Locations: * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4) =#=#=#= End test: Check locations and constraints for prim3 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim3 =#=#=#= Begin test: Recursively check locations and constraints for prim3 =#=#=#= Resources colocated with prim3: * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY) * Locations: * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2) Resources prim3 is colocated with: * prim4 (score=INFINITY, id=colocation-prim3-prim4-INFINITY) * Locations: * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4) * Resources prim4 is colocated with: * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY) =#=#=#= End test: Recursively check locations and constraints for prim3 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim3 =#=#=#= Begin test: Check locations and constraints for prim3 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim3 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim3 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim3 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim3 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim3 in XML =#=#=#= Begin test: Check locations and constraints for prim4 =#=#=#= Locations: * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4) Resources colocated with prim4: * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY) * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY) Resources prim4 is colocated with: * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY) =#=#=#= End test: Check locations and constraints for prim4 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim4 =#=#=#= Begin test: Recursively check locations and constraints for prim4 =#=#=#= Locations: * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4) Resources colocated with prim4: * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY) * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY) * Resources colocated with prim3: * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY) * Locations: * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2) Resources prim4 is colocated with: * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY) =#=#=#= End test: Recursively check locations and constraints for prim4 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim4 =#=#=#= Begin test: Check locations and constraints for prim4 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim4 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim4 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim4 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim4 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim4 in XML =#=#=#= Begin test: Check locations and constraints for prim5 =#=#=#= Resources colocated with prim5: * prim4 (score=INFINITY, id=colocation-prim4-prim5-INFINITY) * Locations: * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4) =#=#=#= End test: Check locations and constraints for prim5 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim5 =#=#=#= Begin test: Recursively check locations and constraints for prim5 =#=#=#= Resources colocated with prim5: * prim4 (score=INFINITY, id=colocation-prim4-prim5-INFINITY) * Locations: * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4) * Resources colocated with prim4: * prim10 (score=INFINITY, id=colocation-prim10-prim4-INFINITY) * prim3 (score=INFINITY, id=colocation-prim3-prim4-INFINITY) * Resources colocated with prim3: * prim2 (score=INFINITY, id=colocation-prim2-prim3-INFINITY) * Locations: * Node cluster01 (score=INFINITY, id=prim2-on-cluster1, rsc=prim2) =#=#=#= End test: Recursively check locations and constraints for prim5 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim5 =#=#=#= Begin test: Check locations and constraints for prim5 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim5 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim5 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim5 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim5 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim5 in XML =#=#=#= Begin test: Check locations and constraints for prim6 =#=#=#= Locations: * Node cluster02 (score=-INFINITY, id=prim6-not-on-cluster2, rsc=prim6) =#=#=#= End test: Check locations and constraints for prim6 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim6 =#=#=#= Begin test: Recursively check locations and constraints for prim6 =#=#=#= Locations: * Node cluster02 (score=-INFINITY, id=prim6-not-on-cluster2, rsc=prim6) =#=#=#= End test: Recursively check locations and constraints for prim6 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim6 =#=#=#= Begin test: Check locations and constraints for prim6 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim6 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim6 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim6 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim6 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim6 in XML =#=#=#= Begin test: Check locations and constraints for prim7 =#=#=#= Resources prim7 is colocated with: * group (score=INFINITY, id=colocation-prim7-group-INFINITY) =#=#=#= End test: Check locations and constraints for prim7 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim7 =#=#=#= Begin test: Recursively check locations and constraints for prim7 =#=#=#= Resources prim7 is colocated with: * group (score=INFINITY, id=colocation-prim7-group-INFINITY) =#=#=#= End test: Recursively check locations and constraints for prim7 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim7 =#=#=#= Begin test: Check locations and constraints for prim7 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim7 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim7 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim7 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim7 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim7 in XML =#=#=#= Begin test: Check locations and constraints for prim8 =#=#=#= Resources prim8 is colocated with: * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY) =#=#=#= End test: Check locations and constraints for prim8 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim8 =#=#=#= Begin test: Recursively check locations and constraints for prim8 =#=#=#= Resources prim8 is colocated with: * gr2 (score=INFINITY, id=colocation-prim8-gr2-INFINITY) =#=#=#= End test: Recursively check locations and constraints for prim8 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim8 =#=#=#= Begin test: Check locations and constraints for prim8 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim8 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim8 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim8 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim8 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim8 in XML =#=#=#= Begin test: Check locations and constraints for prim9 =#=#=#= Resources prim9 is colocated with: * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY) =#=#=#= End test: Check locations and constraints for prim9 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim9 =#=#=#= Begin test: Recursively check locations and constraints for prim9 =#=#=#= Resources prim9 is colocated with: * clone (score=INFINITY, id=colocation-prim9-clone-INFINITY) =#=#=#= End test: Recursively check locations and constraints for prim9 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim9 =#=#=#= Begin test: Check locations and constraints for prim9 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim9 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim9 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim9 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim9 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim9 in XML =#=#=#= Begin test: Check locations and constraints for prim10 =#=#=#= Resources prim10 is colocated with: * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY) * Locations: * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4) =#=#=#= End test: Check locations and constraints for prim10 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim10 =#=#=#= Begin test: Recursively check locations and constraints for prim10 =#=#=#= Resources prim10 is colocated with: * prim4 (score=INFINITY, id=colocation-prim10-prim4-INFINITY) * Locations: * Node cluster02 (score=INFINITY, id=prim4-on-cluster2, rsc=prim4) * Resources prim4 is colocated with: * prim5 (score=INFINITY, id=colocation-prim4-prim5-INFINITY) =#=#=#= End test: Recursively check locations and constraints for prim10 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim10 =#=#=#= Begin test: Check locations and constraints for prim10 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim10 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim10 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim10 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim10 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim10 in XML =#=#=#= Begin test: Check locations and constraints for prim11 =#=#=#= Resources colocated with prim11: * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY) Resources prim11 is colocated with: * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY) =#=#=#= End test: Check locations and constraints for prim11 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim11 =#=#=#= Begin test: Recursively check locations and constraints for prim11 =#=#=#= Resources colocated with prim11: * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY) * Resources colocated with prim13: * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY) * Resources colocated with prim12: * prim11 (id=colocation-prim11-prim12-INFINITY - loop) Resources prim11 is colocated with: * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY) * Resources prim12 is colocated with: * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY) * Resources prim13 is colocated with: * prim11 (id=colocation-prim13-prim11-INFINITY - loop) =#=#=#= End test: Recursively check locations and constraints for prim11 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim11 =#=#=#= Begin test: Check locations and constraints for prim11 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim11 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim11 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim11 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim11 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim11 in XML =#=#=#= Begin test: Check locations and constraints for prim12 =#=#=#= Resources colocated with prim12: * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY) Resources prim12 is colocated with: * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY) =#=#=#= End test: Check locations and constraints for prim12 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim12 =#=#=#= Begin test: Recursively check locations and constraints for prim12 =#=#=#= Resources colocated with prim12: * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY) * Resources colocated with prim11: * prim13 (score=INFINITY, id=colocation-prim13-prim11-INFINITY) * Resources colocated with prim13: * prim12 (id=colocation-prim12-prim13-INFINITY - loop) Resources prim12 is colocated with: * prim13 (score=INFINITY, id=colocation-prim12-prim13-INFINITY) * Resources prim13 is colocated with: * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY) * Resources prim11 is colocated with: * prim12 (id=colocation-prim11-prim12-INFINITY - loop) =#=#=#= End test: Recursively check locations and constraints for prim12 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim12 =#=#=#= Begin test: Check locations and constraints for prim12 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim12 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim12 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim12 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim12 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim12 in XML =#=#=#= Begin test: Check locations and constraints for prim13 =#=#=#= Resources colocated with prim13: * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY) Resources prim13 is colocated with: * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY) =#=#=#= End test: Check locations and constraints for prim13 - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim13 =#=#=#= Begin test: Recursively check locations and constraints for prim13 =#=#=#= Resources colocated with prim13: * prim12 (score=INFINITY, id=colocation-prim12-prim13-INFINITY) * Resources colocated with prim12: * prim11 (score=INFINITY, id=colocation-prim11-prim12-INFINITY) * Resources colocated with prim11: * prim13 (id=colocation-prim13-prim11-INFINITY - loop) Resources prim13 is colocated with: * prim11 (score=INFINITY, id=colocation-prim13-prim11-INFINITY) * Resources prim11 is colocated with: * prim12 (score=INFINITY, id=colocation-prim11-prim12-INFINITY) * Resources prim12 is colocated with: * prim13 (id=colocation-prim12-prim13-INFINITY - loop) =#=#=#= End test: Recursively check locations and constraints for prim13 - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim13 =#=#=#= Begin test: Check locations and constraints for prim13 in XML =#=#=#= =#=#=#= End test: Check locations and constraints for prim13 in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for prim13 in XML =#=#=#= Begin test: Recursively check locations and constraints for prim13 in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for prim13 in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for prim13 in XML =#=#=#= Begin test: Check locations and constraints for group =#=#=#= Resources colocated with group: * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY) =#=#=#= End test: Check locations and constraints for group - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for group =#=#=#= Begin test: Recursively check locations and constraints for group =#=#=#= Resources colocated with group: * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY) =#=#=#= End test: Recursively check locations and constraints for group - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for group =#=#=#= Begin test: Check locations and constraints for group in XML =#=#=#= =#=#=#= End test: Check locations and constraints for group in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for group in XML =#=#=#= Begin test: Recursively check locations and constraints for group in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for group in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for group in XML =#=#=#= Begin test: Check locations and constraints for clone =#=#=#= Resources colocated with clone: * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY) =#=#=#= End test: Check locations and constraints for clone - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for clone =#=#=#= Begin test: Recursively check locations and constraints for clone =#=#=#= Resources colocated with clone: * prim9 (score=INFINITY, id=colocation-prim9-clone-INFINITY) =#=#=#= End test: Recursively check locations and constraints for clone - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for clone =#=#=#= Begin test: Check locations and constraints for clone in XML =#=#=#= =#=#=#= End test: Check locations and constraints for clone in XML - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for clone in XML =#=#=#= Begin test: Recursively check locations and constraints for clone in XML =#=#=#= =#=#=#= End test: Recursively check locations and constraints for clone in XML - OK (0) =#=#=#= * Passed: crm_resource - Recursively check locations and constraints for clone in XML =#=#=#= Begin test: Check locations and constraints for group member (referring to group) =#=#=#= Resources colocated with group: * prim7 (score=INFINITY, id=colocation-prim7-group-INFINITY) =#=#=#= End test: Check locations and constraints for group member (referring to group) - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for group member (referring to group) =#=#=#= Begin test: Check locations and constraints for group member (without referring to group) =#=#=#= Resources colocated with gr2: * prim8 (score=INFINITY, id=colocation-prim8-gr2-INFINITY) =#=#=#= End test: Check locations and constraints for group member (without referring to group) - OK (0) =#=#=#= * Passed: crm_resource - Check locations and constraints for group member (without referring to group) A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Set a meta-attribute for primitive and resources colocated with it =#=#=#= =#=#=#= End test: Set a meta-attribute for primitive and resources colocated with it - OK (0) =#=#=#= * Passed: crm_resource - Set a meta-attribute for primitive and resources colocated with it =#=#=#= Begin test: Set a meta-attribute for group and resource colocated with it =#=#=#= Set 'group' option: id=group-meta_attributes-target-role set=group-meta_attributes name=target-role value=Stopped Set 'prim7' option: id=prim7-meta_attributes-target-role set=prim7-meta_attributes name=target-role value=Stopped =#=#=#= End test: Set a meta-attribute for group and resource colocated with it - OK (0) =#=#=#= * Passed: crm_resource - Set a meta-attribute for group and resource colocated with it =#=#=#= Begin test: Set a meta-attribute for clone and resource colocated with it =#=#=#= =#=#=#= End test: Set a meta-attribute for clone and resource colocated with it - OK (0) =#=#=#= * Passed: crm_resource - Set a meta-attribute for clone and resource colocated with it =#=#=#= Begin test: Show resource digests =#=#=#= =#=#=#= End test: Show resource digests - OK (0) =#=#=#= * Passed: crm_resource - Show resource digests =#=#=#= Begin test: Show resource digests with overrides =#=#=#= =#=#=#= End test: Show resource digests with overrides - OK (0) =#=#=#= * Passed: crm_resource - Show resource digests with overrides =#=#=#= Begin test: Show resource operations =#=#=#= rsc1 (ocf:pacemaker:Dummy): Started: rsc1_monitor_0 (node=node4, call=136, rc=7, exec=28ms): complete Fencing (stonith:fence_xvm): Started: Fencing_monitor_0 (node=node4, call=5, rc=7, exec=2ms): complete rsc1 (ocf:pacemaker:Dummy): Started: rsc1_monitor_0 (node=node2, call=101, rc=7, exec=45ms): complete Fencing (stonith:fence_xvm): Started: Fencing_monitor_0 (node=node2, call=5, rc=7, exec=4ms): complete Fencing (stonith:fence_xvm): Started: Fencing_monitor_0 (node=node3, call=5, rc=7, exec=24ms): complete rsc1 (ocf:pacemaker:Dummy): Started: rsc1_monitor_0 (node=node5, call=99, rc=193, exec=27ms): pending Fencing (stonith:fence_xvm): Started: Fencing_monitor_0 (node=node5, call=5, rc=7, exec=14ms): complete rsc1 (ocf:pacemaker:Dummy): Started: rsc1_start_0 (node=node1, call=104, rc=0, exec=22ms): complete rsc1 (ocf:pacemaker:Dummy): Started: rsc1_monitor_10000 (node=node1, call=106, rc=0, exec=20ms): complete Fencing (stonith:fence_xvm): Started: Fencing_start_0 (node=node1, call=10, rc=0, exec=59ms): complete Fencing (stonith:fence_xvm): Started: Fencing_monitor_120000 (node=node1, call=12, rc=0, exec=70ms): complete =#=#=#= End test: Show resource operations - OK (0) =#=#=#= * Passed: crm_resource - Show resource operations =#=#=#= Begin test: Show resource operations (XML) =#=#=#= =#=#=#= End test: Show resource operations (XML) - OK (0) =#=#=#= * Passed: crm_resource - Show resource operations (XML) =#=#=#= Begin test: List all nodes =#=#=#= cluster node: overcloud-controller-0 (1) cluster node: overcloud-controller-1 (2) cluster node: overcloud-controller-2 (3) cluster node: overcloud-galera-0 (4) cluster node: overcloud-galera-1 (5) cluster node: overcloud-galera-2 (6) guest node: lxc1 (lxc1) guest node: lxc2 (lxc2) remote node: overcloud-rabbit-0 (overcloud-rabbit-0) remote node: overcloud-rabbit-1 (overcloud-rabbit-1) remote node: overcloud-rabbit-2 (overcloud-rabbit-2) =#=#=#= End test: List all nodes - OK (0) =#=#=#= * Passed: crmadmin - List all nodes =#=#=#= Begin test: Minimally list all nodes =#=#=#= overcloud-controller-0 overcloud-controller-1 overcloud-controller-2 overcloud-galera-0 overcloud-galera-1 overcloud-galera-2 lxc1 lxc2 overcloud-rabbit-0 overcloud-rabbit-1 overcloud-rabbit-2 =#=#=#= End test: Minimally list all nodes - OK (0) =#=#=#= * Passed: crmadmin - Minimally list all nodes =#=#=#= Begin test: List all nodes as bash exports =#=#=#= export overcloud-controller-0=1 export overcloud-controller-1=2 export overcloud-controller-2=3 export overcloud-galera-0=4 export overcloud-galera-1=5 export overcloud-galera-2=6 export lxc1=lxc1 export lxc2=lxc2 export overcloud-rabbit-0=overcloud-rabbit-0 export overcloud-rabbit-1=overcloud-rabbit-1 export overcloud-rabbit-2=overcloud-rabbit-2 =#=#=#= End test: List all nodes as bash exports - OK (0) =#=#=#= * Passed: crmadmin - List all nodes as bash exports =#=#=#= Begin test: List cluster nodes =#=#=#= 6 =#=#=#= End test: List cluster nodes - OK (0) =#=#=#= * Passed: crmadmin - List cluster nodes =#=#=#= Begin test: List guest nodes =#=#=#= 2 =#=#=#= End test: List guest nodes - OK (0) =#=#=#= * Passed: crmadmin - List guest nodes =#=#=#= Begin test: List remote nodes =#=#=#= 3 =#=#=#= End test: List remote nodes - OK (0) =#=#=#= * Passed: crmadmin - List remote nodes =#=#=#= Begin test: List cluster,remote nodes =#=#=#= 9 =#=#=#= End test: List cluster,remote nodes - OK (0) =#=#=#= * Passed: crmadmin - List cluster,remote nodes =#=#=#= Begin test: List guest,remote nodes =#=#=#= 5 =#=#=#= End test: List guest,remote nodes - OK (0) =#=#=#= * Passed: crmadmin - List guest,remote nodes =#=#=#= Begin test: Show allocation scores with crm_simulate =#=#=#= =#=#=#= End test: Show allocation scores with crm_simulate - OK (0) =#=#=#= * Passed: crm_simulate - Show allocation scores with crm_simulate =#=#=#= Begin test: Show utilization with crm_simulate =#=#=#= 4 of 32 resource instances DISABLED and 0 BLOCKED from further action due to failure Current cluster status: * Node List: * Online: [ cluster01 cluster02 ] * GuestOnline: [ httpd-bundle-0 httpd-bundle-1 ] * Full List of Resources: * Clone Set: ping-clone [ping]: * Started: [ cluster01 cluster02 ] * Fencing (stonith:fence_xvm): Started cluster01 * dummy (ocf:pacemaker:Dummy): Started cluster02 * Clone Set: inactive-clone [inactive-dhcpd] (disabled): * Stopped (disabled): [ cluster01 cluster02 ] * Resource Group: inactive-group (disabled): * inactive-dummy-1 (ocf:pacemaker:Dummy): Stopped (disabled) * inactive-dummy-2 (ocf:pacemaker:Dummy): Stopped (disabled) * Container bundle set: httpd-bundle [pcmk:http]: * httpd-bundle-0 (192.168.122.131) (ocf:heartbeat:apache): Started cluster01 * httpd-bundle-1 (192.168.122.132) (ocf:heartbeat:apache): Started cluster02 * httpd-bundle-2 (192.168.122.133) (ocf:heartbeat:apache): Stopped * Resource Group: exim-group: * Public-IP (ocf:heartbeat:IPaddr): Started cluster02 * Email (lsb:exim): Started cluster02 * Clone Set: mysql-clone-group [mysql-group]: * Started: [ cluster01 cluster02 ] * Clone Set: promotable-clone [promotable-rsc] (promotable): * Promoted: [ cluster02 ] * Unpromoted: [ cluster01 ] Utilization Information: Only 'private' parameters to 1m-interval monitor for dummy on cluster02 changed: 0:0;16:2:0:4a9e64d6-e1dd-4395-917c-1596312eafe4 * Original: cluster01 capacity: * Original: cluster02 capacity: * Original: httpd-bundle-0 capacity: * Original: httpd-bundle-1 capacity: * Original: httpd-bundle-2 capacity: * pcmk__assign_resource: ping:0 utilization on cluster02: * pcmk__assign_resource: ping:1 utilization on cluster01: * pcmk__assign_resource: Fencing utilization on cluster01: * pcmk__assign_resource: dummy utilization on cluster02: * pcmk__assign_resource: httpd-bundle-docker-0 utilization on cluster01: * pcmk__assign_resource: httpd-bundle-docker-1 utilization on cluster02: * pcmk__assign_resource: httpd-bundle-ip-192.168.122.131 utilization on cluster01: * pcmk__assign_resource: httpd-bundle-0 utilization on cluster01: * pcmk__assign_resource: httpd:0 utilization on httpd-bundle-0: * pcmk__assign_resource: httpd-bundle-ip-192.168.122.132 utilization on cluster02: * pcmk__assign_resource: httpd-bundle-1 utilization on cluster02: * pcmk__assign_resource: httpd:1 utilization on httpd-bundle-1: * pcmk__assign_resource: httpd-bundle-2 utilization on cluster01: * pcmk__assign_resource: httpd:2 utilization on httpd-bundle-2: * pcmk__assign_resource: Public-IP utilization on cluster02: * pcmk__assign_resource: Email utilization on cluster02: * pcmk__assign_resource: mysql-proxy:0 utilization on cluster02: * pcmk__assign_resource: mysql-proxy:1 utilization on cluster01: * pcmk__assign_resource: promotable-rsc:0 utilization on cluster02: * pcmk__assign_resource: promotable-rsc:1 utilization on cluster01: * Remaining: cluster01 capacity: * Remaining: cluster02 capacity: * Remaining: httpd-bundle-0 capacity: * Remaining: httpd-bundle-1 capacity: * Remaining: httpd-bundle-2 capacity: Transition Summary: * Start httpd-bundle-2 ( cluster01 ) due to unrunnable httpd-bundle-docker-2 start (blocked) * Start httpd:2 ( httpd-bundle-2 ) due to unrunnable httpd-bundle-docker-2 start (blocked) =#=#=#= End test: Show utilization with crm_simulate - OK (0) =#=#=#= * Passed: crm_simulate - Show utilization with crm_simulate =#=#=#= Begin test: Simulate injecting a failure =#=#=#= 4 of 32 resource instances DISABLED and 0 BLOCKED from further action due to failure Current cluster status: * Node List: * Online: [ cluster01 cluster02 ] * GuestOnline: [ httpd-bundle-0 httpd-bundle-1 ] * Full List of Resources: * Clone Set: ping-clone [ping]: * Started: [ cluster01 cluster02 ] * Fencing (stonith:fence_xvm): Started cluster01 * dummy (ocf:pacemaker:Dummy): Started cluster02 * Clone Set: inactive-clone [inactive-dhcpd] (disabled): * Stopped (disabled): [ cluster01 cluster02 ] * Resource Group: inactive-group (disabled): * inactive-dummy-1 (ocf:pacemaker:Dummy): Stopped (disabled) * inactive-dummy-2 (ocf:pacemaker:Dummy): Stopped (disabled) * Container bundle set: httpd-bundle [pcmk:http]: * httpd-bundle-0 (192.168.122.131) (ocf:heartbeat:apache): Started cluster01 * httpd-bundle-1 (192.168.122.132) (ocf:heartbeat:apache): Started cluster02 * httpd-bundle-2 (192.168.122.133) (ocf:heartbeat:apache): Stopped * Resource Group: exim-group: * Public-IP (ocf:heartbeat:IPaddr): Started cluster02 * Email (lsb:exim): Started cluster02 * Clone Set: mysql-clone-group [mysql-group]: * Started: [ cluster01 cluster02 ] * Clone Set: promotable-clone [promotable-rsc] (promotable): * Promoted: [ cluster02 ] * Unpromoted: [ cluster01 ] Performing Requested Modifications: * Injecting ping_monitor_10000@cluster02=1 into the configuration * Injecting attribute fail-count-ping#monitor_10000=1 into /node_state '2' * Injecting attribute last-failure-ping#monitor_10000= into /node_state '2' Transition Summary: * Recover ping:0 ( cluster02 ) * Start httpd-bundle-2 ( cluster01 ) due to unrunnable httpd-bundle-docker-2 start (blocked) * Start httpd:2 ( httpd-bundle-2 ) due to unrunnable httpd-bundle-docker-2 start (blocked) Executing Cluster Transition: * Cluster action: clear_failcount for ping on cluster02 * Pseudo action: ping-clone_stop_0 * Pseudo action: httpd-bundle_start_0 * Resource action: ping stop on cluster02 * Pseudo action: ping-clone_stopped_0 * Pseudo action: ping-clone_start_0 * Pseudo action: httpd-bundle-clone_start_0 * Resource action: ping start on cluster02 * Resource action: ping monitor=10000 on cluster02 * Pseudo action: ping-clone_running_0 * Pseudo action: httpd-bundle-clone_running_0 * Pseudo action: httpd-bundle_running_0 Revised Cluster Status: * Node List: * Online: [ cluster01 cluster02 ] * GuestOnline: [ httpd-bundle-0 httpd-bundle-1 ] * Full List of Resources: * Clone Set: ping-clone [ping]: * Started: [ cluster01 cluster02 ] * Fencing (stonith:fence_xvm): Started cluster01 * dummy (ocf:pacemaker:Dummy): Started cluster02 * Clone Set: inactive-clone [inactive-dhcpd] (disabled): * Stopped (disabled): [ cluster01 cluster02 ] * Resource Group: inactive-group (disabled): * inactive-dummy-1 (ocf:pacemaker:Dummy): Stopped (disabled) * inactive-dummy-2 (ocf:pacemaker:Dummy): Stopped (disabled) * Container bundle set: httpd-bundle [pcmk:http]: * httpd-bundle-0 (192.168.122.131) (ocf:heartbeat:apache): Started cluster01 * httpd-bundle-1 (192.168.122.132) (ocf:heartbeat:apache): Started cluster02 * httpd-bundle-2 (192.168.122.133) (ocf:heartbeat:apache): Stopped * Resource Group: exim-group: * Public-IP (ocf:heartbeat:IPaddr): Started cluster02 * Email (lsb:exim): Started cluster02 * Clone Set: mysql-clone-group [mysql-group]: * Started: [ cluster01 cluster02 ] * Clone Set: promotable-clone [promotable-rsc] (promotable): * Promoted: [ cluster02 ] * Unpromoted: [ cluster01 ] =#=#=#= End test: Simulate injecting a failure - OK (0) =#=#=#= * Passed: crm_simulate - Simulate injecting a failure =#=#=#= Begin test: Simulate bringing a node down =#=#=#= 4 of 32 resource instances DISABLED and 0 BLOCKED from further action due to failure Current cluster status: * Node List: * Online: [ cluster01 cluster02 ] * GuestOnline: [ httpd-bundle-0 httpd-bundle-1 ] * Full List of Resources: * Clone Set: ping-clone [ping]: * Started: [ cluster01 cluster02 ] * Fencing (stonith:fence_xvm): Started cluster01 * dummy (ocf:pacemaker:Dummy): Started cluster02 * Clone Set: inactive-clone [inactive-dhcpd] (disabled): * Stopped (disabled): [ cluster01 cluster02 ] * Resource Group: inactive-group (disabled): * inactive-dummy-1 (ocf:pacemaker:Dummy): Stopped (disabled) * inactive-dummy-2 (ocf:pacemaker:Dummy): Stopped (disabled) * Container bundle set: httpd-bundle [pcmk:http]: * httpd-bundle-0 (192.168.122.131) (ocf:heartbeat:apache): Started cluster01 * httpd-bundle-1 (192.168.122.132) (ocf:heartbeat:apache): Started cluster02 * httpd-bundle-2 (192.168.122.133) (ocf:heartbeat:apache): Stopped * Resource Group: exim-group: * Public-IP (ocf:heartbeat:IPaddr): Started cluster02 * Email (lsb:exim): Started cluster02 * Clone Set: mysql-clone-group [mysql-group]: * Started: [ cluster01 cluster02 ] * Clone Set: promotable-clone [promotable-rsc] (promotable): * Promoted: [ cluster02 ] * Unpromoted: [ cluster01 ] Performing Requested Modifications: * Taking node cluster01 offline Transition Summary: * Fence (off) httpd-bundle-0 (resource: httpd-bundle-docker-0) 'guest is unclean' * Start Fencing ( cluster02 ) * Start httpd-bundle-0 ( cluster02 ) due to unrunnable httpd-bundle-docker-0 start (blocked) * Stop httpd:0 ( httpd-bundle-0 ) due to unrunnable httpd-bundle-docker-0 start * Start httpd-bundle-2 ( cluster02 ) due to unrunnable httpd-bundle-docker-2 start (blocked) * Start httpd:2 ( httpd-bundle-2 ) due to unrunnable httpd-bundle-docker-2 start (blocked) Executing Cluster Transition: * Resource action: Fencing start on cluster02 * Pseudo action: stonith-httpd-bundle-0-off on httpd-bundle-0 * Pseudo action: httpd-bundle_stop_0 * Pseudo action: httpd-bundle_start_0 * Resource action: Fencing monitor=60000 on cluster02 * Pseudo action: httpd-bundle-clone_stop_0 * Pseudo action: httpd_stop_0 * Pseudo action: httpd-bundle-clone_stopped_0 * Pseudo action: httpd-bundle-clone_start_0 * Pseudo action: httpd-bundle_stopped_0 * Pseudo action: httpd-bundle-clone_running_0 * Pseudo action: httpd-bundle_running_0 Revised Cluster Status: * Node List: * Online: [ cluster02 ] * OFFLINE: [ cluster01 ] * GuestOnline: [ httpd-bundle-1 ] * Full List of Resources: * Clone Set: ping-clone [ping]: * Started: [ cluster02 ] * Stopped: [ cluster01 ] * Fencing (stonith:fence_xvm): Started cluster02 * dummy (ocf:pacemaker:Dummy): Started cluster02 * Clone Set: inactive-clone [inactive-dhcpd] (disabled): * Stopped (disabled): [ cluster01 cluster02 ] * Resource Group: inactive-group (disabled): * inactive-dummy-1 (ocf:pacemaker:Dummy): Stopped (disabled) * inactive-dummy-2 (ocf:pacemaker:Dummy): Stopped (disabled) * Container bundle set: httpd-bundle [pcmk:http]: * httpd-bundle-0 (192.168.122.131) (ocf:heartbeat:apache): FAILED * httpd-bundle-1 (192.168.122.132) (ocf:heartbeat:apache): Started cluster02 * httpd-bundle-2 (192.168.122.133) (ocf:heartbeat:apache): Stopped * Resource Group: exim-group: * Public-IP (ocf:heartbeat:IPaddr): Started cluster02 * Email (lsb:exim): Started cluster02 * Clone Set: mysql-clone-group [mysql-group]: * Started: [ cluster02 ] * Stopped: [ cluster01 ] * Clone Set: promotable-clone [promotable-rsc] (promotable): * Promoted: [ cluster02 ] * Stopped: [ cluster01 ] =#=#=#= End test: Simulate bringing a node down - OK (0) =#=#=#= * Passed: crm_simulate - Simulate bringing a node down =#=#=#= Begin test: Simulate a node failing =#=#=#= 4 of 32 resource instances DISABLED and 0 BLOCKED from further action due to failure Current cluster status: * Node List: * Online: [ cluster01 cluster02 ] * GuestOnline: [ httpd-bundle-0 httpd-bundle-1 ] * Full List of Resources: * Clone Set: ping-clone [ping]: * Started: [ cluster01 cluster02 ] * Fencing (stonith:fence_xvm): Started cluster01 * dummy (ocf:pacemaker:Dummy): Started cluster02 * Clone Set: inactive-clone [inactive-dhcpd] (disabled): * Stopped (disabled): [ cluster01 cluster02 ] * Resource Group: inactive-group (disabled): * inactive-dummy-1 (ocf:pacemaker:Dummy): Stopped (disabled) * inactive-dummy-2 (ocf:pacemaker:Dummy): Stopped (disabled) * Container bundle set: httpd-bundle [pcmk:http]: * httpd-bundle-0 (192.168.122.131) (ocf:heartbeat:apache): Started cluster01 * httpd-bundle-1 (192.168.122.132) (ocf:heartbeat:apache): Started cluster02 * httpd-bundle-2 (192.168.122.133) (ocf:heartbeat:apache): Stopped * Resource Group: exim-group: * Public-IP (ocf:heartbeat:IPaddr): Started cluster02 * Email (lsb:exim): Started cluster02 * Clone Set: mysql-clone-group [mysql-group]: * Started: [ cluster01 cluster02 ] * Clone Set: promotable-clone [promotable-rsc] (promotable): * Promoted: [ cluster02 ] * Unpromoted: [ cluster01 ] Performing Requested Modifications: * Failing node cluster02 Transition Summary: * Fence (off) httpd-bundle-1 (resource: httpd-bundle-docker-1) 'guest is unclean' * Fence (reboot) cluster02 'peer is no longer part of the cluster' * Stop ping:0 ( cluster02 ) due to node availability * Stop dummy ( cluster02 ) due to node availability * Stop httpd-bundle-ip-192.168.122.132 ( cluster02 ) due to node availability * Stop httpd-bundle-docker-1 ( cluster02 ) due to node availability * Stop httpd-bundle-1 ( cluster02 ) due to unrunnable httpd-bundle-docker-1 start * Stop httpd:1 ( httpd-bundle-1 ) due to unrunnable httpd-bundle-docker-1 start * Start httpd-bundle-2 ( cluster01 ) due to unrunnable httpd-bundle-docker-2 start (blocked) * Start httpd:2 ( httpd-bundle-2 ) due to unrunnable httpd-bundle-docker-2 start (blocked) * Move Public-IP ( cluster02 -> cluster01 ) * Move Email ( cluster02 -> cluster01 ) * Stop mysql-proxy:0 ( cluster02 ) due to node availability * Stop promotable-rsc:0 ( Promoted cluster02 ) due to node availability Executing Cluster Transition: * Pseudo action: httpd-bundle-1_stop_0 * Pseudo action: promotable-clone_demote_0 * Pseudo action: httpd-bundle_stop_0 * Pseudo action: httpd-bundle_start_0 * Fencing cluster02 (reboot) * Pseudo action: ping-clone_stop_0 * Pseudo action: dummy_stop_0 * Pseudo action: httpd-bundle-docker-1_stop_0 * Pseudo action: exim-group_stop_0 * Pseudo action: Email_stop_0 * Pseudo action: mysql-clone-group_stop_0 * Pseudo action: promotable-rsc_demote_0 * Pseudo action: promotable-clone_demoted_0 * Pseudo action: promotable-clone_stop_0 * Pseudo action: stonith-httpd-bundle-1-off on httpd-bundle-1 * Pseudo action: ping_stop_0 * Pseudo action: ping-clone_stopped_0 * Pseudo action: httpd-bundle-clone_stop_0 * Pseudo action: httpd-bundle-ip-192.168.122.132_stop_0 * Pseudo action: Public-IP_stop_0 * Pseudo action: mysql-group:0_stop_0 * Pseudo action: mysql-proxy_stop_0 * Pseudo action: promotable-rsc_stop_0 * Pseudo action: promotable-clone_stopped_0 * Pseudo action: httpd_stop_0 * Pseudo action: httpd-bundle-clone_stopped_0 * Pseudo action: httpd-bundle-clone_start_0 * Pseudo action: exim-group_stopped_0 * Pseudo action: exim-group_start_0 * Resource action: Public-IP start on cluster01 * Resource action: Email start on cluster01 * Pseudo action: mysql-group:0_stopped_0 * Pseudo action: mysql-clone-group_stopped_0 * Pseudo action: httpd-bundle_stopped_0 * Pseudo action: httpd-bundle-clone_running_0 * Pseudo action: exim-group_running_0 * Pseudo action: httpd-bundle_running_0 Revised Cluster Status: * Node List: * Online: [ cluster01 ] * OFFLINE: [ cluster02 ] * GuestOnline: [ httpd-bundle-0 ] * Full List of Resources: * Clone Set: ping-clone [ping]: * Started: [ cluster01 ] * Stopped: [ cluster02 ] * Fencing (stonith:fence_xvm): Started cluster01 * dummy (ocf:pacemaker:Dummy): Stopped * Clone Set: inactive-clone [inactive-dhcpd] (disabled): * Stopped (disabled): [ cluster01 cluster02 ] * Resource Group: inactive-group (disabled): * inactive-dummy-1 (ocf:pacemaker:Dummy): Stopped (disabled) * inactive-dummy-2 (ocf:pacemaker:Dummy): Stopped (disabled) * Container bundle set: httpd-bundle [pcmk:http]: * httpd-bundle-0 (192.168.122.131) (ocf:heartbeat:apache): Started cluster01 * httpd-bundle-1 (192.168.122.132) (ocf:heartbeat:apache): FAILED * httpd-bundle-2 (192.168.122.133) (ocf:heartbeat:apache): Stopped * Resource Group: exim-group: * Public-IP (ocf:heartbeat:IPaddr): Started cluster01 * Email (lsb:exim): Started cluster01 * Clone Set: mysql-clone-group [mysql-group]: * Started: [ cluster01 ] * Stopped: [ cluster02 ] * Clone Set: promotable-clone [promotable-rsc] (promotable): * Unpromoted: [ cluster01 ] * Stopped: [ cluster02 ] =#=#=#= End test: Simulate a node failing - OK (0) =#=#=#= * Passed: crm_simulate - Simulate a node failing =#=#=#= Begin test: List a promotable clone resource =#=#=#= resource promotable-clone is running on: cluster01 resource promotable-clone is running on: cluster02 Promoted =#=#=#= End test: List a promotable clone resource - OK (0) =#=#=#= * Passed: crm_resource - List a promotable clone resource =#=#=#= Begin test: List the primitive of a promotable clone resource =#=#=#= resource promotable-rsc is running on: cluster01 resource promotable-rsc is running on: cluster02 Promoted =#=#=#= End test: List the primitive of a promotable clone resource - OK (0) =#=#=#= * Passed: crm_resource - List the primitive of a promotable clone resource =#=#=#= Begin test: List a single instance of a promotable clone resource =#=#=#= resource promotable-rsc:0 is running on: cluster02 Promoted =#=#=#= End test: List a single instance of a promotable clone resource - OK (0) =#=#=#= * Passed: crm_resource - List a single instance of a promotable clone resource =#=#=#= Begin test: List another instance of a promotable clone resource =#=#=#= resource promotable-rsc:1 is running on: cluster01 =#=#=#= End test: List another instance of a promotable clone resource - OK (0) =#=#=#= * Passed: crm_resource - List another instance of a promotable clone resource =#=#=#= Begin test: List a promotable clone resource in XML =#=#=#= cluster01 cluster02 =#=#=#= End test: List a promotable clone resource in XML - OK (0) =#=#=#= * Passed: crm_resource - List a promotable clone resource in XML =#=#=#= Begin test: List the primitive of a promotable clone resource in XML =#=#=#= cluster01 cluster02 =#=#=#= End test: List the primitive of a promotable clone resource in XML - OK (0) =#=#=#= * Passed: crm_resource - List the primitive of a promotable clone resource in XML =#=#=#= Begin test: List a single instance of a promotable clone resource in XML =#=#=#= cluster02 =#=#=#= End test: List a single instance of a promotable clone resource in XML - OK (0) =#=#=#= * Passed: crm_resource - List a single instance of a promotable clone resource in XML =#=#=#= Begin test: List another instance of a promotable clone resource in XML =#=#=#= cluster01 =#=#=#= End test: List another instance of a promotable clone resource in XML - OK (0) =#=#=#= * Passed: crm_resource - List another instance of a promotable clone resource in XML =#=#=#= Begin test: Try to move an instance of a cloned resource =#=#=#= crm_resource: Cannot operate on clone resource instance 'promotable-rsc:0' Error performing operation: Invalid parameter =#=#=#= End test: Try to move an instance of a cloned resource - Invalid parameter (2) =#=#=#= * Passed: crm_resource - Try to move an instance of a cloned resource =#=#=#= Begin test: Query a nonexistent promotable score attribute =#=#=#= crm_attribute: Error performing operation: No such device or address =#=#=#= End test: Query a nonexistent promotable score attribute - No such object (105) =#=#=#= * Passed: crm_attribute - Query a nonexistent promotable score attribute =#=#=#= Begin test: Query a nonexistent promotable score attribute (XML) =#=#=#= crm_attribute: Error performing operation: No such device or address =#=#=#= End test: Query a nonexistent promotable score attribute (XML) - No such object (105) =#=#=#= * Passed: crm_attribute - Query a nonexistent promotable score attribute (XML) =#=#=#= Begin test: Delete a nonexistent promotable score attribute =#=#=#= =#=#=#= End test: Delete a nonexistent promotable score attribute - OK (0) =#=#=#= * Passed: crm_attribute - Delete a nonexistent promotable score attribute =#=#=#= Begin test: Delete a nonexistent promotable score attribute (XML) =#=#=#= =#=#=#= End test: Delete a nonexistent promotable score attribute (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Delete a nonexistent promotable score attribute (XML) =#=#=#= Begin test: Query after deleting a nonexistent promotable score attribute =#=#=#= crm_attribute: Error performing operation: No such device or address =#=#=#= End test: Query after deleting a nonexistent promotable score attribute - No such object (105) =#=#=#= * Passed: crm_attribute - Query after deleting a nonexistent promotable score attribute =#=#=#= Begin test: Query after deleting a nonexistent promotable score attribute (XML) =#=#=#= crm_attribute: Error performing operation: No such device or address =#=#=#= End test: Query after deleting a nonexistent promotable score attribute (XML) - No such object (105) =#=#=#= * Passed: crm_attribute - Query after deleting a nonexistent promotable score attribute (XML) =#=#=#= Begin test: Update a nonexistent promotable score attribute =#=#=#= =#=#=#= End test: Update a nonexistent promotable score attribute - OK (0) =#=#=#= * Passed: crm_attribute - Update a nonexistent promotable score attribute =#=#=#= Begin test: Update a nonexistent promotable score attribute (XML) =#=#=#= =#=#=#= End test: Update a nonexistent promotable score attribute (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Update a nonexistent promotable score attribute (XML) =#=#=#= Begin test: Query after updating a nonexistent promotable score attribute =#=#=#= scope=status name=master-promotable-rsc value=1 =#=#=#= End test: Query after updating a nonexistent promotable score attribute - OK (0) =#=#=#= * Passed: crm_attribute - Query after updating a nonexistent promotable score attribute =#=#=#= Begin test: Query after updating a nonexistent promotable score attribute (XML) =#=#=#= =#=#=#= End test: Query after updating a nonexistent promotable score attribute (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Query after updating a nonexistent promotable score attribute (XML) =#=#=#= Begin test: Update an existing promotable score attribute =#=#=#= =#=#=#= End test: Update an existing promotable score attribute - OK (0) =#=#=#= * Passed: crm_attribute - Update an existing promotable score attribute =#=#=#= Begin test: Update an existing promotable score attribute (XML) =#=#=#= =#=#=#= End test: Update an existing promotable score attribute (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Update an existing promotable score attribute (XML) =#=#=#= Begin test: Query after updating an existing promotable score attribute =#=#=#= scope=status name=master-promotable-rsc value=5 =#=#=#= End test: Query after updating an existing promotable score attribute - OK (0) =#=#=#= * Passed: crm_attribute - Query after updating an existing promotable score attribute =#=#=#= Begin test: Query after updating an existing promotable score attribute (XML) =#=#=#= =#=#=#= End test: Query after updating an existing promotable score attribute (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Query after updating an existing promotable score attribute (XML) =#=#=#= Begin test: Delete an existing promotable score attribute =#=#=#= Deleted status attribute: id=status-1-master-promotable-rsc name=master-promotable-rsc =#=#=#= End test: Delete an existing promotable score attribute - OK (0) =#=#=#= * Passed: crm_attribute - Delete an existing promotable score attribute =#=#=#= Begin test: Delete an existing promotable score attribute (XML) =#=#=#= =#=#=#= End test: Delete an existing promotable score attribute (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Delete an existing promotable score attribute (XML) =#=#=#= Begin test: Query after deleting an existing promotable score attribute =#=#=#= crm_attribute: Error performing operation: No such device or address =#=#=#= End test: Query after deleting an existing promotable score attribute - No such object (105) =#=#=#= * Passed: crm_attribute - Query after deleting an existing promotable score attribute =#=#=#= Begin test: Query after deleting an existing promotable score attribute (XML) =#=#=#= crm_attribute: Error performing operation: No such device or address =#=#=#= End test: Query after deleting an existing promotable score attribute (XML) - No such object (105) =#=#=#= * Passed: crm_attribute - Query after deleting an existing promotable score attribute (XML) =#=#=#= Begin test: Update a promotable score attribute to -INFINITY =#=#=#= =#=#=#= End test: Update a promotable score attribute to -INFINITY - OK (0) =#=#=#= * Passed: crm_attribute - Update a promotable score attribute to -INFINITY =#=#=#= Begin test: Update a promotable score attribute to -INFINITY (XML) =#=#=#= =#=#=#= End test: Update a promotable score attribute to -INFINITY (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Update a promotable score attribute to -INFINITY (XML) =#=#=#= Begin test: Query after updating a promotable score attribute to -INFINITY =#=#=#= scope=status name=master-promotable-rsc value=-INFINITY =#=#=#= End test: Query after updating a promotable score attribute to -INFINITY - OK (0) =#=#=#= * Passed: crm_attribute - Query after updating a promotable score attribute to -INFINITY =#=#=#= Begin test: Query after updating a promotable score attribute to -INFINITY (XML) =#=#=#= =#=#=#= End test: Query after updating a promotable score attribute to -INFINITY (XML) - OK (0) =#=#=#= * Passed: crm_attribute - Query after updating a promotable score attribute to -INFINITY (XML) =#=#=#= Begin test: Try OCF_RESOURCE_INSTANCE if -p is specified with an empty string =#=#=#= scope=status name=master-promotable-rsc value=-INFINITY =#=#=#= End test: Try OCF_RESOURCE_INSTANCE if -p is specified with an empty string - OK (0) =#=#=#= * Passed: crm_attribute - Try OCF_RESOURCE_INSTANCE if -p is specified with an empty string =#=#=#= Begin test: Return usage error if both -p and OCF_RESOURCE_INSTANCE are empty strings =#=#=#= crm_attribute: -p/--promotion must be called from an OCF resource agent or with a resource ID specified =#=#=#= End test: Return usage error if both -p and OCF_RESOURCE_INSTANCE are empty strings - Incorrect usage (64) =#=#=#= * Passed: crm_attribute - Return usage error if both -p and OCF_RESOURCE_INSTANCE are empty strings =#=#=#= Begin test: Check that CIB_file="-" works - crm_mon =#=#=#= Cluster Summary: * Stack: corosync * Current DC: cluster02 (version) - partition with quorum * Last updated: * Last change: * 5 nodes configured * 32 resource instances configured (4 DISABLED) Node List: * Online: [ cluster01 cluster02 ] * GuestOnline: [ httpd-bundle-0 httpd-bundle-1 ] Active Resources: * Clone Set: ping-clone [ping]: * Started: [ cluster01 cluster02 ] * Fencing (stonith:fence_xvm): Started cluster01 * dummy (ocf:pacemaker:Dummy): Started cluster02 * Container bundle set: httpd-bundle [pcmk:http]: * httpd-bundle-0 (192.168.122.131) (ocf:heartbeat:apache): Started cluster01 * httpd-bundle-1 (192.168.122.132) (ocf:heartbeat:apache): Started cluster02 * httpd-bundle-2 (192.168.122.133) (ocf:heartbeat:apache): Stopped * Resource Group: exim-group: * Public-IP (ocf:heartbeat:IPaddr): Started cluster02 * Email (lsb:exim): Started cluster02 * Clone Set: mysql-clone-group [mysql-group]: * Started: [ cluster01 cluster02 ] * Clone Set: promotable-clone [promotable-rsc] (promotable): * Promoted: [ cluster02 ] * Unpromoted: [ cluster01 ] =#=#=#= End test: Check that CIB_file="-" works - crm_mon - OK (0) =#=#=#= * Passed: cat - Check that CIB_file="-" works - crm_mon =#=#=#= Begin test: Check that CIB_file="-" works - crm_resource =#=#=#= =#=#=#= End test: Check that CIB_file="-" works - crm_resource - OK (0) =#=#=#= * Passed: cat - Check that CIB_file="-" works - crm_resource =#=#=#= Begin test: Check that CIB_file="-" works - crmadmin =#=#=#= 11 =#=#=#= End test: Check that CIB_file="-" works - crmadmin - OK (0) =#=#=#= * Passed: cat - Check that CIB_file="-" works - crmadmin =#=#=#= Begin test: Get active shadow instance (no active instance) =#=#=#= crm_shadow: No active shadow configuration defined =#=#=#= End test: Get active shadow instance (no active instance) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance (no active instance) =#=#=#= Begin test: Get active shadow instance (no active instance) (XML) =#=#=#= crm_shadow: No active shadow configuration defined =#=#=#= End test: Get active shadow instance (no active instance) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance (no active instance) (XML) =#=#=#= Begin test: Get active shadow instance's file name (no active instance) =#=#=#= crm_shadow: No active shadow configuration defined =#=#=#= End test: Get active shadow instance's file name (no active instance) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance's file name (no active instance) =#=#=#= Begin test: Get active shadow instance's file name (no active instance) (XML) =#=#=#= crm_shadow: No active shadow configuration defined =#=#=#= End test: Get active shadow instance's file name (no active instance) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance's file name (no active instance) (XML) =#=#=#= Begin test: Get active shadow instance's contents (no active instance) =#=#=#= crm_shadow: No active shadow configuration defined =#=#=#= End test: Get active shadow instance's contents (no active instance) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance's contents (no active instance) =#=#=#= Begin test: Get active shadow instance's contents (no active instance) (XML) =#=#=#= crm_shadow: No active shadow configuration defined =#=#=#= End test: Get active shadow instance's contents (no active instance) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance's contents (no active instance) (XML) =#=#=#= Begin test: Get active shadow instance's diff (no active instance) =#=#=#= crm_shadow: No active shadow configuration defined =#=#=#= End test: Get active shadow instance's diff (no active instance) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (no active instance) =#=#=#= Begin test: Get active shadow instance's diff (no active instance) (XML) =#=#=#= crm_shadow: No active shadow configuration defined =#=#=#= End test: Get active shadow instance's diff (no active instance) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (no active instance) (XML) =#=#=#= Begin test: Create copied shadow instance =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create copied shadow instance - OK (0) =#=#=#= * Passed: crm_shadow - Create copied shadow instance =#=#=#= Begin test: Create copied shadow instance (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create copied shadow instance (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (XML) =#=#=#= Begin test: Get active shadow instance (copied) =#=#=#= cts-cli =#=#=#= End test: Get active shadow instance (copied) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance (copied) =#=#=#= Begin test: Get active shadow instance (copied) (XML) =#=#=#= =#=#=#= End test: Get active shadow instance (copied) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance (copied) (XML) =#=#=#= Begin test: Get active shadow instance's file name (copied) =#=#=#= /tmp/cts-cli.shadow/shadow.cts-cli =#=#=#= End test: Get active shadow instance's file name (copied) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance's file name (copied) =#=#=#= Begin test: Get active shadow instance's file name (copied) (XML) =#=#=#= =#=#=#= End test: Get active shadow instance's file name (copied) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance's file name (copied) (XML) =#=#=#= Begin test: Get active shadow instance's contents (copied) =#=#=#= =#=#=#= End test: Get active shadow instance's contents (copied) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance's contents (copied) =#=#=#= Begin test: Get active shadow instance's contents (copied) (XML) =#=#=#= ]]> =#=#=#= End test: Get active shadow instance's contents (copied) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance's contents (copied) (XML) =#=#=#= Begin test: Get active shadow instance's diff (copied) =#=#=#= =#=#=#= End test: Get active shadow instance's diff (copied) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (copied) =#=#=#= Begin test: Get active shadow instance's diff (copied) (XML) =#=#=#= =#=#=#= End test: Get active shadow instance's diff (copied) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (copied) (XML) =#=#=#= Begin test: Get active shadow instance's diff (after changes) =#=#=#= Diff: --- 1.1.173 2 Diff: +++ 1.4.1 (null) -- /cib/configuration/op_defaults + /cib: @epoch=4, @num_updates=1 + /cib/configuration/resources/primitive[@id='dummy']: @description=desc ++ /cib/configuration/resources: ++ /cib/status: =#=#=#= End test: Get active shadow instance's diff (after changes) - Error occurred (1) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (after changes) =#=#=#= Begin test: Get active shadow instance's diff (after changes) (XML) =#=#=#= ]]> =#=#=#= End test: Get active shadow instance's diff (after changes) (XML) - Error occurred (1) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (after changes) (XML) =#=#=#= Begin test: Commit shadow instance =#=#=#= crm_shadow: The commit command overwrites the active cluster configuration. To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= End test: Commit shadow instance - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Commit shadow instance =#=#=#= Begin test: Commit shadow instance (force) =#=#=#= =#=#=#= End test: Commit shadow instance (force) - OK (0) =#=#=#= * Passed: crm_shadow - Commit shadow instance (force) =#=#=#= Begin test: Get active shadow instance's diff (after commit) =#=#=#= Diff: --- 1.2.0 2 Diff: +++ 1.4.1 (null) + /cib: @epoch=4, @num_updates=1 ++ /cib/status: =#=#=#= End test: Get active shadow instance's diff (after commit) - Error occurred (1) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (after commit) =#=#=#= Begin test: Commit shadow instance (force) (all) =#=#=#= =#=#=#= End test: Commit shadow instance (force) (all) - OK (0) =#=#=#= * Passed: crm_shadow - Commit shadow instance (force) (all) =#=#=#= Begin test: Get active shadow instance's diff (after commit all) =#=#=#= Diff: --- 1.4.2 2 Diff: +++ 1.4.1 (null) + /cib: @num_updates=1 =#=#=#= End test: Get active shadow instance's diff (after commit all) - Error occurred (1) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (after commit all) =#=#=#= Begin test: Commit shadow instance (XML) =#=#=#= crm_shadow: The commit command overwrites the active cluster configuration. To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= End test: Commit shadow instance (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Commit shadow instance (XML) =#=#=#= Begin test: Commit shadow instance (force) (XML) =#=#=#= =#=#=#= End test: Commit shadow instance (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Commit shadow instance (force) (XML) =#=#=#= Begin test: Get active shadow instance's diff (after commit) (XML) =#=#=#= ]]> =#=#=#= End test: Get active shadow instance's diff (after commit) (XML) - Error occurred (1) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (after commit) (XML) =#=#=#= Begin test: Commit shadow instance (force) (all) (XML) =#=#=#= =#=#=#= End test: Commit shadow instance (force) (all) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Commit shadow instance (force) (all) (XML) =#=#=#= Begin test: Get active shadow instance's diff (after commit all) (XML) =#=#=#= ]]> =#=#=#= End test: Get active shadow instance's diff (after commit all) (XML) - Error occurred (1) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (after commit all) (XML) =#=#=#= Begin test: Commit shadow instance (no active instance) =#=#=#= crm_shadow: The commit command overwrites the active cluster configuration. To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= End test: Commit shadow instance (no active instance) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Commit shadow instance (no active instance) =#=#=#= Begin test: Commit shadow instance (no active instance) (force) =#=#=#= =#=#=#= End test: Commit shadow instance (no active instance) (force) - OK (0) =#=#=#= * Passed: crm_shadow - Commit shadow instance (no active instance) (force) =#=#=#= Begin test: Commit shadow instance (no active instance) (XML) =#=#=#= crm_shadow: The commit command overwrites the active cluster configuration. To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= End test: Commit shadow instance (no active instance) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Commit shadow instance (no active instance) (XML) =#=#=#= Begin test: Commit shadow instance (no active instance) (force) (XML) =#=#=#= =#=#=#= End test: Commit shadow instance (no active instance) (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Commit shadow instance (no active instance) (force) (XML) =#=#=#= Begin test: Commit shadow instance (mismatch) =#=#=#= crm_shadow: The commit command overwrites the active cluster configuration. Additionally, the supplied shadow instance (cts-cli) is not the same as the active one (nonexistent_shadow). To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= End test: Commit shadow instance (mismatch) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Commit shadow instance (mismatch) =#=#=#= Begin test: Commit shadow instance (mismatch) (force) =#=#=#= =#=#=#= End test: Commit shadow instance (mismatch) (force) - OK (0) =#=#=#= * Passed: crm_shadow - Commit shadow instance (mismatch) (force) =#=#=#= Begin test: Commit shadow instance (mismatch) (XML) =#=#=#= crm_shadow: The commit command overwrites the active cluster configuration. Additionally, the supplied shadow instance (cts-cli) is not the same as the active one (nonexistent_shadow). To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= End test: Commit shadow instance (mismatch) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Commit shadow instance (mismatch) (XML) =#=#=#= Begin test: Commit shadow instance (mismatch) (force) (XML) =#=#=#= =#=#=#= End test: Commit shadow instance (mismatch) (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Commit shadow instance (mismatch) (force) (XML) =#=#=#= Begin test: Commit shadow instance (nonexistent shadow file) =#=#=#= crm_shadow: The commit command overwrites the active cluster configuration. To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= End test: Commit shadow instance (nonexistent shadow file) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Commit shadow instance (nonexistent shadow file) =#=#=#= Begin test: Commit shadow instance (nonexistent shadow file) (force) =#=#=#= crm_shadow: Could not access shadow instance 'nonexistent_shadow': No such file or directory =#=#=#= End test: Commit shadow instance (nonexistent shadow file) (force) - No such object (105) =#=#=#= * Passed: crm_shadow - Commit shadow instance (nonexistent shadow file) (force) =#=#=#= Begin test: Get active shadow instance's diff (nonexistent shadow file) =#=#=#= crm_shadow: Could not access shadow instance 'nonexistent_shadow': No such file or directory =#=#=#= End test: Get active shadow instance's diff (nonexistent shadow file) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (nonexistent shadow file) =#=#=#= Begin test: Commit shadow instance (nonexistent shadow file) (XML) =#=#=#= crm_shadow: The commit command overwrites the active cluster configuration. To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= End test: Commit shadow instance (nonexistent shadow file) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Commit shadow instance (nonexistent shadow file) (XML) =#=#=#= Begin test: Commit shadow instance (nonexistent shadow file) (force) (XML) =#=#=#= crm_shadow: Could not access shadow instance 'nonexistent_shadow': No such file or directory =#=#=#= End test: Commit shadow instance (nonexistent shadow file) (force) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Commit shadow instance (nonexistent shadow file) (force) (XML) =#=#=#= Begin test: Get active shadow instance's diff (nonexistent shadow file) (XML) =#=#=#= crm_shadow: Could not access shadow instance 'nonexistent_shadow': No such file or directory =#=#=#= End test: Get active shadow instance's diff (nonexistent shadow file) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (nonexistent shadow file) (XML) =#=#=#= Begin test: Commit shadow instance (nonexistent CIB file) =#=#=#= crm_shadow: The commit command overwrites the active cluster configuration. To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= End test: Commit shadow instance (nonexistent CIB file) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Commit shadow instance (nonexistent CIB file) =#=#=#= Begin test: Commit shadow instance (nonexistent CIB file) (force) =#=#=#= crm_shadow: Could not connect to CIB: No such device or address =#=#=#= End test: Commit shadow instance (nonexistent CIB file) (force) - No such object (105) =#=#=#= * Passed: crm_shadow - Commit shadow instance (nonexistent CIB file) (force) =#=#=#= Begin test: Get active shadow instance's diff (nonexistent CIB file) =#=#=#= crm_shadow: Could not connect to CIB: No such device or address =#=#=#= End test: Get active shadow instance's diff (nonexistent CIB file) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (nonexistent CIB file) =#=#=#= Begin test: Commit shadow instance (nonexistent CIB file) (XML) =#=#=#= crm_shadow: The commit command overwrites the active cluster configuration. To prevent accidental destruction of the cluster, the --force flag is required in order to proceed. =#=#=#= End test: Commit shadow instance (nonexistent CIB file) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Commit shadow instance (nonexistent CIB file) (XML) =#=#=#= Begin test: Commit shadow instance (nonexistent CIB file) (force) (XML) =#=#=#= crm_shadow: Could not connect to CIB: No such device or address =#=#=#= End test: Commit shadow instance (nonexistent CIB file) (force) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Commit shadow instance (nonexistent CIB file) (force) (XML) =#=#=#= Begin test: Get active shadow instance's diff (nonexistent CIB file) (XML) =#=#=#= crm_shadow: Could not connect to CIB: No such device or address =#=#=#= End test: Get active shadow instance's diff (nonexistent CIB file) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (nonexistent CIB file) (XML) =#=#=#= Begin test: Delete shadow instance =#=#=#= crm_shadow: The delete command removes the specified shadow file. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Delete shadow instance - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Delete shadow instance =#=#=#= Begin test: Delete shadow instance (force) =#=#=#= Remember to unset the CIB_shadow variable by entering the following into your shell: unset CIB_shadow =#=#=#= End test: Delete shadow instance (force) - OK (0) =#=#=#= * Passed: crm_shadow - Delete shadow instance (force) A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Delete shadow instance (XML) =#=#=#= crm_shadow: The delete command removes the specified shadow file. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Delete shadow instance (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Delete shadow instance (XML) =#=#=#= Begin test: Delete shadow instance (force) (XML) =#=#=#= Remember to unset the CIB_shadow variable by entering the following into your shell: unset CIB_shadow =#=#=#= End test: Delete shadow instance (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Delete shadow instance (force) (XML) A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Delete shadow instance (no active instance) =#=#=#= crm_shadow: The delete command removes the specified shadow file. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Delete shadow instance (no active instance) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Delete shadow instance (no active instance) =#=#=#= Begin test: Delete shadow instance (no active instance) (force) =#=#=#= =#=#=#= End test: Delete shadow instance (no active instance) (force) - OK (0) =#=#=#= * Passed: crm_shadow - Delete shadow instance (no active instance) (force) A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Delete shadow instance (no active instance) (XML) =#=#=#= crm_shadow: The delete command removes the specified shadow file. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Delete shadow instance (no active instance) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Delete shadow instance (no active instance) (XML) =#=#=#= Begin test: Delete shadow instance (no active instance) (force) (XML) =#=#=#= =#=#=#= End test: Delete shadow instance (no active instance) (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Delete shadow instance (no active instance) (force) (XML) A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Delete shadow instance (mismatch) =#=#=#= crm_shadow: The delete command removes the specified shadow file. Additionally, the supplied shadow instance (cts-cli) is not the same as the active one (nonexistent_shadow). To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Delete shadow instance (mismatch) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Delete shadow instance (mismatch) =#=#=#= Begin test: Delete shadow instance (mismatch) (force) =#=#=#= =#=#=#= End test: Delete shadow instance (mismatch) (force) - OK (0) =#=#=#= * Passed: crm_shadow - Delete shadow instance (mismatch) (force) A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Delete shadow instance (mismatch) (XML) =#=#=#= crm_shadow: The delete command removes the specified shadow file. Additionally, the supplied shadow instance (cts-cli) is not the same as the active one (nonexistent_shadow). To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Delete shadow instance (mismatch) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Delete shadow instance (mismatch) (XML) =#=#=#= Begin test: Delete shadow instance (mismatch) (force) (XML) =#=#=#= =#=#=#= End test: Delete shadow instance (mismatch) (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Delete shadow instance (mismatch) (force) (XML) =#=#=#= Begin test: Delete shadow instance (nonexistent shadow file) =#=#=#= crm_shadow: The delete command removes the specified shadow file. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Delete shadow instance (nonexistent shadow file) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Delete shadow instance (nonexistent shadow file) =#=#=#= Begin test: Delete shadow instance (nonexistent shadow file) (force) =#=#=#= Remember to unset the CIB_shadow variable by entering the following into your shell: unset CIB_shadow =#=#=#= End test: Delete shadow instance (nonexistent shadow file) (force) - OK (0) =#=#=#= * Passed: crm_shadow - Delete shadow instance (nonexistent shadow file) (force) =#=#=#= Begin test: Delete shadow instance (nonexistent shadow file) (XML) =#=#=#= crm_shadow: The delete command removes the specified shadow file. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Delete shadow instance (nonexistent shadow file) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Delete shadow instance (nonexistent shadow file) (XML) =#=#=#= Begin test: Delete shadow instance (nonexistent shadow file) (force) (XML) =#=#=#= Remember to unset the CIB_shadow variable by entering the following into your shell: unset CIB_shadow =#=#=#= End test: Delete shadow instance (nonexistent shadow file) (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Delete shadow instance (nonexistent shadow file) (force) (XML) A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Delete shadow instance (nonexistent CIB file) =#=#=#= crm_shadow: The delete command removes the specified shadow file. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Delete shadow instance (nonexistent CIB file) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Delete shadow instance (nonexistent CIB file) =#=#=#= Begin test: Delete shadow instance (nonexistent CIB file) (force) =#=#=#= Remember to unset the CIB_shadow variable by entering the following into your shell: unset CIB_shadow =#=#=#= End test: Delete shadow instance (nonexistent CIB file) (force) - OK (0) =#=#=#= * Passed: crm_shadow - Delete shadow instance (nonexistent CIB file) (force) A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Delete shadow instance (nonexistent CIB file) (XML) =#=#=#= crm_shadow: The delete command removes the specified shadow file. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Delete shadow instance (nonexistent CIB file) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Delete shadow instance (nonexistent CIB file) (XML) =#=#=#= Begin test: Delete shadow instance (nonexistent CIB file) (force) (XML) =#=#=#= Remember to unset the CIB_shadow variable by entering the following into your shell: unset CIB_shadow =#=#=#= End test: Delete shadow instance (nonexistent CIB file) (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Delete shadow instance (nonexistent CIB file) (force) (XML) =#=#=#= Begin test: Create copied shadow instance (no active instance) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create copied shadow instance (no active instance) - OK (0) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (no active instance) =#=#=#= Begin test: Create copied shadow instance (no active instance) (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create copied shadow instance (no active instance) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (no active instance) (XML) =#=#=#= Begin test: Create copied shadow instance (mismatch) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create copied shadow instance (mismatch) - OK (0) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (mismatch) =#=#=#= Begin test: Create copied shadow instance (mismatch) (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create copied shadow instance (mismatch) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (mismatch) (XML) =#=#=#= Begin test: Create copied shadow instance (file already exists) =#=#=#= crm_shadow: A shadow instance 'cts-cli' already exists. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Create copied shadow instance (file already exists) - Cannot create output file (73) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (file already exists) =#=#=#= Begin test: Create copied shadow instance (file already exists) (force) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create copied shadow instance (file already exists) (force) - OK (0) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (file already exists) (force) =#=#=#= Begin test: Create copied shadow instance (file already exists) (XML) =#=#=#= crm_shadow: A shadow instance 'cts-cli' already exists. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Create copied shadow instance (file already exists) (XML) - Cannot create output file (73) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (file already exists) (XML) =#=#=#= Begin test: Create copied shadow instance (file already exists) (force) (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create copied shadow instance (file already exists) (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (file already exists) (force) (XML) =#=#=#= Begin test: Create copied shadow instance (nonexistent CIB file) (force) =#=#=#= crm_shadow: Could not connect to CIB: No such device or address =#=#=#= End test: Create copied shadow instance (nonexistent CIB file) (force) - No such object (105) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (nonexistent CIB file) (force) =#=#=#= Begin test: Create copied shadow instance (nonexistent CIB file) (force) (XML) =#=#=#= crm_shadow: Could not connect to CIB: No such device or address =#=#=#= End test: Create copied shadow instance (nonexistent CIB file) (force) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Create copied shadow instance (nonexistent CIB file) (force) (XML) =#=#=#= Begin test: Create empty shadow instance =#=#=#= Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create empty shadow instance - OK (0) =#=#=#= * Passed: crm_shadow - Create empty shadow instance =#=#=#= Begin test: Create empty shadow instance (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create empty shadow instance (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (XML) =#=#=#= Begin test: Create empty shadow instance (no active instance) =#=#=#= Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create empty shadow instance (no active instance) - OK (0) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (no active instance) =#=#=#= Begin test: Create empty shadow instance (no active instance) (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create empty shadow instance (no active instance) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (no active instance) (XML) =#=#=#= Begin test: Create empty shadow instance (mismatch) =#=#=#= Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create empty shadow instance (mismatch) - OK (0) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (mismatch) =#=#=#= Begin test: Create empty shadow instance (mismatch) (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create empty shadow instance (mismatch) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (mismatch) (XML) =#=#=#= Begin test: Create empty shadow instance (nonexistent CIB file) =#=#=#= Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create empty shadow instance (nonexistent CIB file) - OK (0) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (nonexistent CIB file) =#=#=#= Begin test: Create empty shadow instance (nonexistent CIB file) (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create empty shadow instance (nonexistent CIB file) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (nonexistent CIB file) (XML) =#=#=#= Begin test: Create empty shadow instance (file already exists) =#=#=#= crm_shadow: A shadow instance 'cts-cli' already exists. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Create empty shadow instance (file already exists) - Cannot create output file (73) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (file already exists) =#=#=#= Begin test: Create empty shadow instance (file already exists) (force) =#=#=#= Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create empty shadow instance (file already exists) (force) - OK (0) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (file already exists) (force) =#=#=#= Begin test: Create empty shadow instance (file already exists) (XML) =#=#=#= crm_shadow: A shadow instance 'cts-cli' already exists. To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Create empty shadow instance (file already exists) (XML) - Cannot create output file (73) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (file already exists) (XML) =#=#=#= Begin test: Create empty shadow instance (file already exists) (force) (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Create empty shadow instance (file already exists) (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Create empty shadow instance (file already exists) (force) (XML) =#=#=#= Begin test: Get active shadow instance's contents (empty CIB) =#=#=#= =#=#=#= End test: Get active shadow instance's contents (empty CIB) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance's contents (empty CIB) =#=#=#= Begin test: Get active shadow instance's contents (empty CIB) (XML) =#=#=#= ]]> =#=#=#= End test: Get active shadow instance's contents (empty CIB) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance's contents (empty CIB) (XML) =#=#=#= Begin test: Get active shadow instance's diff (empty CIB) =#=#=#= Diff: --- 1.1.173 2 Diff: +++ 0.1.0 (null) -- /cib/configuration/crm_config/cluster_property_set[@id='cib-bootstrap-options'] -- /cib/configuration/nodes/node[@id='1'] -- /cib/configuration/nodes/node[@id='2'] -- /cib/configuration/resources/clone[@id='ping-clone'] -- /cib/configuration/resources/primitive[@id='Fencing'] -- /cib/configuration/resources/primitive[@id='dummy'] -- /cib/configuration/resources/clone[@id='inactive-clone'] -- /cib/configuration/resources/group[@id='inactive-group'] -- /cib/configuration/resources/bundle[@id='httpd-bundle'] -- /cib/configuration/resources/group[@id='exim-group'] -- /cib/configuration/resources/clone[@id='mysql-clone-group'] -- /cib/configuration/resources/clone[@id='promotable-clone'] -- /cib/configuration/constraints/rsc_location[@id='not-on-cluster1'] -- /cib/configuration/constraints/rsc_location[@id='loc-promotable-clone'] -- /cib/configuration/tags -- /cib/configuration/op_defaults -- /cib/status/node_state[@id='2'] -- /cib/status/node_state[@id='1'] -- /cib/status/node_state[@id='httpd-bundle-0'] -- /cib/status/node_state[@id='httpd-bundle-1'] + /cib: @validate-with=pacemaker-X, @num_updates=0, @admin_epoch=0 -- /cib: @cib-last-written, @update-origin, @update-client, @update-user, @have-quorum, @dc-uuid =#=#=#= End test: Get active shadow instance's diff (empty CIB) - Error occurred (1) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (empty CIB) =#=#=#= Begin test: Get active shadow instance's diff (empty CIB) (XML) =#=#=#= ]]> =#=#=#= End test: Get active shadow instance's diff (empty CIB) (XML) - Error occurred (1) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (empty CIB) (XML) =#=#=#= Begin test: Reset shadow instance =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Reset shadow instance - OK (0) =#=#=#= * Passed: crm_shadow - Reset shadow instance =#=#=#= Begin test: Get active shadow instance's diff (after reset) =#=#=#= =#=#=#= End test: Get active shadow instance's diff (after reset) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (after reset) Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Reset shadow instance (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Reset shadow instance (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Reset shadow instance (XML) =#=#=#= Begin test: Get active shadow instance's diff (after reset) (XML) =#=#=#= =#=#=#= End test: Get active shadow instance's diff (after reset) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Get active shadow instance's diff (after reset) (XML) =#=#=#= Begin test: Reset shadow instance (no active instance) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Reset shadow instance (no active instance) - OK (0) =#=#=#= * Passed: crm_shadow - Reset shadow instance (no active instance) Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Reset shadow instance (no active instance) (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Reset shadow instance (no active instance) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Reset shadow instance (no active instance) (XML) =#=#=#= Begin test: Reset shadow instance (mismatch) =#=#=#= crm_shadow: The supplied shadow instance (cts-cli) is not the same as the active one (nonexistent_shadow). To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Reset shadow instance (mismatch) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Reset shadow instance (mismatch) =#=#=#= Begin test: Reset shadow instance (mismatch) (force) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Reset shadow instance (mismatch) (force) - OK (0) =#=#=#= * Passed: crm_shadow - Reset shadow instance (mismatch) (force) Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Reset shadow instance (mismatch) (XML) =#=#=#= crm_shadow: The supplied shadow instance (cts-cli) is not the same as the active one (nonexistent_shadow). To prevent accidental destruction of the shadow file, the --force flag is required in order to proceed. =#=#=#= End test: Reset shadow instance (mismatch) (XML) - Incorrect usage (64) =#=#=#= * Passed: crm_shadow - Reset shadow instance (mismatch) (XML) =#=#=#= Begin test: Reset shadow instance (mismatch) (force) (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Reset shadow instance (mismatch) (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Reset shadow instance (mismatch) (force) (XML) Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Reset shadow instance (nonexistent CIB file) =#=#=#= crm_shadow: Could not connect to CIB: No such device or address =#=#=#= End test: Reset shadow instance (nonexistent CIB file) - No such object (105) =#=#=#= * Passed: crm_shadow - Reset shadow instance (nonexistent CIB file) =#=#=#= Begin test: Reset shadow instance (nonexistent CIB file) (XML) =#=#=#= crm_shadow: Could not connect to CIB: No such device or address =#=#=#= End test: Reset shadow instance (nonexistent CIB file) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Reset shadow instance (nonexistent CIB file) (XML) =#=#=#= Begin test: Reset shadow instance (nonexistent CIB file) (force) =#=#=#= crm_shadow: Could not connect to CIB: No such device or address =#=#=#= End test: Reset shadow instance (nonexistent CIB file) (force) - No such object (105) =#=#=#= * Passed: crm_shadow - Reset shadow instance (nonexistent CIB file) (force) =#=#=#= Begin test: Reset shadow instance (nonexistent CIB file) (force) (XML) =#=#=#= crm_shadow: Could not connect to CIB: No such device or address =#=#=#= End test: Reset shadow instance (nonexistent CIB file) (force) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Reset shadow instance (nonexistent CIB file) (force) (XML) =#=#=#= Begin test: Reset shadow instance (nonexistent shadow file) =#=#=#= crm_shadow: Could not access shadow instance 'cts-cli': No such file or directory =#=#=#= End test: Reset shadow instance (nonexistent shadow file) - No such object (105) =#=#=#= * Passed: crm_shadow - Reset shadow instance (nonexistent shadow file) =#=#=#= Begin test: Reset shadow instance (nonexistent shadow file) (force) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Reset shadow instance (nonexistent shadow file) (force) - OK (0) =#=#=#= * Passed: crm_shadow - Reset shadow instance (nonexistent shadow file) (force) =#=#=#= Begin test: Reset shadow instance (nonexistent shadow file) (XML) =#=#=#= crm_shadow: Could not access shadow instance 'cts-cli': No such file or directory =#=#=#= End test: Reset shadow instance (nonexistent shadow file) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Reset shadow instance (nonexistent shadow file) (XML) =#=#=#= Begin test: Reset shadow instance (nonexistent shadow file) (force) (XML) =#=#=#= A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Reset shadow instance (nonexistent shadow file) (force) (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Reset shadow instance (nonexistent shadow file) (force) (XML) Created new pacemaker configuration A new shadow instance was created. To begin using it, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= Begin test: Switch to new shadow instance =#=#=#= To switch to the named shadow instance, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Switch to new shadow instance - OK (0) =#=#=#= * Passed: crm_shadow - Switch to new shadow instance =#=#=#= Begin test: Switch to new shadow instance (XML) =#=#=#= To switch to the named shadow instance, enter the following into your shell: export CIB_shadow=cts-cli =#=#=#= End test: Switch to new shadow instance (XML) - OK (0) =#=#=#= * Passed: crm_shadow - Switch to new shadow instance (XML) =#=#=#= Begin test: Switch to nonexistent shadow instance =#=#=#= crm_shadow: Could not access shadow instance 'cts-cli': No such file or directory =#=#=#= End test: Switch to nonexistent shadow instance - No such object (105) =#=#=#= * Passed: crm_shadow - Switch to nonexistent shadow instance =#=#=#= Begin test: Switch to nonexistent shadow instance (force) =#=#=#= crm_shadow: Could not access shadow instance 'cts-cli': No such file or directory =#=#=#= End test: Switch to nonexistent shadow instance (force) - No such object (105) =#=#=#= * Passed: crm_shadow - Switch to nonexistent shadow instance (force) =#=#=#= Begin test: Switch to nonexistent shadow instance (XML) =#=#=#= crm_shadow: Could not access shadow instance 'cts-cli': No such file or directory =#=#=#= End test: Switch to nonexistent shadow instance (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Switch to nonexistent shadow instance (XML) =#=#=#= Begin test: Switch to nonexistent shadow instance (force) (XML) =#=#=#= crm_shadow: Could not access shadow instance 'cts-cli': No such file or directory =#=#=#= End test: Switch to nonexistent shadow instance (force) (XML) - No such object (105) =#=#=#= * Passed: crm_shadow - Switch to nonexistent shadow instance (force) (XML) =#=#=#= Begin test: Verbosely verify a file-specified configuration with an unallowed fencing level ID =#=#=#= warning: Ignoring topology registration with invalid level 10 Warnings found during check: config not valid =#=#=#= End test: Verbosely verify a file-specified configuration with an unallowed fencing level ID - Invalid configuration (78) =#=#=#= * Passed: crm_verify - Verbosely verify a file-specified configuration with an unallowed fencing level ID =#=#=#= Begin test: Verify a file-specified invalid configuration (text output) =#=#=#= Errors found during check: config not valid -V may provide more details =#=#=#= End test: Verify a file-specified invalid configuration (text output) - Invalid configuration (78) =#=#=#= * Passed: crm_verify - Verify a file-specified invalid configuration (text output) =#=#=#= Begin test: Verify a file-specified invalid configuration (verbose text output) =#=#=#= unpack_config warning: Blind faith: not fencing unseen nodes error: Resource test2:0 is of type systemd and therefore cannot be used as a promotable clone resource error: Ignoring resource 'test2-clone' because configuration is invalid error: CIB did not pass schema validation Errors found during check: config not valid =#=#=#= End test: Verify a file-specified invalid configuration (verbose text output) - Invalid configuration (78) =#=#=#= * Passed: crm_verify - Verify a file-specified invalid configuration (verbose text output) =#=#=#= Begin test: Verify a file-specified invalid configuration (quiet text output) =#=#=#= =#=#=#= End test: Verify a file-specified invalid configuration (quiet text output) - Invalid configuration (78) =#=#=#= * Passed: crm_verify - Verify a file-specified invalid configuration (quiet text output) =#=#=#= Begin test: Verify a file-specified invalid configuration (XML output) =#=#=#= error: Resource test2:0 is of type systemd and therefore cannot be used as a promotable clone resource error: Ignoring <clone> resource 'test2-clone' because configuration is invalid error: CIB did not pass schema validation Errors found during check: config not valid =#=#=#= End test: Verify a file-specified invalid configuration (XML output) - Invalid configuration (78) =#=#=#= * Passed: crm_verify - Verify a file-specified invalid configuration (XML output) =#=#=#= Begin test: Verify a file-specified invalid configuration (verbose XML output) =#=#=#= unpack_config warning: Blind faith: not fencing unseen nodes error: Resource test2:0 is of type systemd and therefore cannot be used as a promotable clone resource error: Ignoring <clone> resource 'test2-clone' because configuration is invalid error: CIB did not pass schema validation Errors found during check: config not valid =#=#=#= End test: Verify a file-specified invalid configuration (verbose XML output) - Invalid configuration (78) =#=#=#= * Passed: crm_verify - Verify a file-specified invalid configuration (verbose XML output) =#=#=#= Begin test: Verify a file-specified invalid configuration (quiet XML output) =#=#=#= error: Resource test2:0 is of type systemd and therefore cannot be used as a promotable clone resource error: Ignoring <clone> resource 'test2-clone' because configuration is invalid error: CIB did not pass schema validation =#=#=#= End test: Verify a file-specified invalid configuration (quiet XML output) - Invalid configuration (78) =#=#=#= * Passed: crm_verify - Verify a file-specified invalid configuration (quiet XML output) =#=#=#= Begin test: Verify another file-specified invalid configuration (XML output) =#=#=#= error: Resource start-up disabled since no STONITH resources have been defined error: Either configure some or disable STONITH with the stonith-enabled option error: NOTE: Clusters with shared data need STONITH to ensure data integrity warning: Node pcmk-1 is unclean but cannot be fenced warning: Node pcmk-2 is unclean but cannot be fenced error: CIB did not pass schema validation Errors found during check: config not valid =#=#=#= End test: Verify another file-specified invalid configuration (XML output) - Invalid configuration (78) =#=#=#= * Passed: crm_verify - Verify another file-specified invalid configuration (XML output) =#=#=#= Begin test: Verify a file-specified valid configuration, outputting as xml =#=#=#= =#=#=#= End test: Verify a file-specified valid configuration, outputting as xml - OK (0) =#=#=#= * Passed: crm_verify - Verify a file-specified valid configuration, outputting as xml =#=#=#= Begin test: Verify a piped-in valid configuration, outputting as xml =#=#=#= =#=#=#= End test: Verify a piped-in valid configuration, outputting as xml - OK (0) =#=#=#= * Passed: cat - Verify a piped-in valid configuration, outputting as xml =#=#=#= Begin test: Verbosely verify a file-specified valid configuration, outputting as xml =#=#=#= =#=#=#= End test: Verbosely verify a file-specified valid configuration, outputting as xml - OK (0) =#=#=#= * Passed: crm_verify - Verbosely verify a file-specified valid configuration, outputting as xml =#=#=#= Begin test: Verbosely verify a piped-in valid configuration, outputting as xml =#=#=#= =#=#=#= End test: Verbosely verify a piped-in valid configuration, outputting as xml - OK (0) =#=#=#= * Passed: cat - Verbosely verify a piped-in valid configuration, outputting as xml =#=#=#= Begin test: Verify a string-supplied valid configuration, outputting as xml =#=#=#= =#=#=#= End test: Verify a string-supplied valid configuration, outputting as xml - OK (0) =#=#=#= * Passed: crm_verify - Verify a string-supplied valid configuration, outputting as xml =#=#=#= Begin test: Verbosely verify a string-supplied valid configuration, outputting as xml =#=#=#= =#=#=#= End test: Verbosely verify a string-supplied valid configuration, outputting as xml - OK (0) =#=#=#= * Passed: crm_verify - Verbosely verify a string-supplied valid configuration, outputting as xml diff --git a/lib/common/patchset.c b/lib/common/patchset.c index c625f04eab..5271b9019a 100644 --- a/lib/common/patchset.c +++ b/lib/common/patchset.c @@ -1,1595 +1,1584 @@ /* * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include #include #include #include #include #include #include #include #include #include #include #include #include // CRM_XML_LOG_BASE, etc. #include "crmcommon_private.h" /* Add changes for specified XML to patchset. * For patchset format, refer to diff schema. */ static void add_xml_changes_to_patchset(xmlNode *xml, xmlNode *patchset) { xmlNode *cIter = NULL; xmlAttr *pIter = NULL; xmlNode *change = NULL; xml_node_private_t *nodepriv = xml->_private; const char *value = NULL; if (nodepriv == NULL) { /* Elements that shouldn't occur in a CIB don't have _private set. They * should be stripped out, ignored, or have an error thrown by any code * that processes their parent, so we ignore any changes to them. */ return; } // If this XML node is new, just report that if (patchset && pcmk_is_set(nodepriv->flags, pcmk__xf_created)) { GString *xpath = pcmk__element_xpath(xml->parent); if (xpath != NULL) { int position = pcmk__xml_position(xml, pcmk__xf_deleted); change = pcmk__xe_create(patchset, PCMK_XE_CHANGE); crm_xml_add(change, PCMK_XA_OPERATION, PCMK_VALUE_CREATE); crm_xml_add(change, PCMK_XA_PATH, (const char *) xpath->str); crm_xml_add_int(change, PCMK_XE_POSITION, position); pcmk__xml_copy(change, xml); g_string_free(xpath, TRUE); } return; } // Check each of the XML node's attributes for changes for (pIter = pcmk__xe_first_attr(xml); pIter != NULL; pIter = pIter->next) { xmlNode *attr = NULL; nodepriv = pIter->_private; if (!pcmk_any_flags_set(nodepriv->flags, pcmk__xf_deleted|pcmk__xf_dirty)) { continue; } if (change == NULL) { GString *xpath = pcmk__element_xpath(xml); if (xpath != NULL) { change = pcmk__xe_create(patchset, PCMK_XE_CHANGE); crm_xml_add(change, PCMK_XA_OPERATION, PCMK_VALUE_MODIFY); crm_xml_add(change, PCMK_XA_PATH, (const char *) xpath->str); change = pcmk__xe_create(change, PCMK_XE_CHANGE_LIST); g_string_free(xpath, TRUE); } } attr = pcmk__xe_create(change, PCMK_XE_CHANGE_ATTR); crm_xml_add(attr, PCMK_XA_NAME, (const char *) pIter->name); if (nodepriv->flags & pcmk__xf_deleted) { crm_xml_add(attr, PCMK_XA_OPERATION, "unset"); } else { crm_xml_add(attr, PCMK_XA_OPERATION, "set"); value = pcmk__xml_attr_value(pIter); crm_xml_add(attr, PCMK_XA_VALUE, value); } } if (change) { xmlNode *result = NULL; change = pcmk__xe_create(change->parent, PCMK_XE_CHANGE_RESULT); result = pcmk__xe_create(change, (const char *)xml->name); for (pIter = pcmk__xe_first_attr(xml); pIter != NULL; pIter = pIter->next) { nodepriv = pIter->_private; if (!pcmk_is_set(nodepriv->flags, pcmk__xf_deleted)) { value = crm_element_value(xml, (const char *) pIter->name); crm_xml_add(result, (const char *)pIter->name, value); } } } // Now recursively do the same for each child node of this node for (cIter = pcmk__xml_first_child(xml); cIter != NULL; cIter = pcmk__xml_next(cIter)) { add_xml_changes_to_patchset(cIter, patchset); } nodepriv = xml->_private; if (patchset && pcmk_is_set(nodepriv->flags, pcmk__xf_moved)) { GString *xpath = pcmk__element_xpath(xml); crm_trace("%s.%s moved to position %d", xml->name, pcmk__xe_id(xml), pcmk__xml_position(xml, pcmk__xf_skip)); if (xpath != NULL) { change = pcmk__xe_create(patchset, PCMK_XE_CHANGE); crm_xml_add(change, PCMK_XA_OPERATION, PCMK_VALUE_MOVE); crm_xml_add(change, PCMK_XA_PATH, (const char *) xpath->str); crm_xml_add_int(change, PCMK_XE_POSITION, pcmk__xml_position(xml, pcmk__xf_deleted)); g_string_free(xpath, TRUE); } } } static bool is_config_change(xmlNode *xml) { GList *gIter = NULL; xml_node_private_t *nodepriv = NULL; xml_doc_private_t *docpriv; xmlNode *config = pcmk__xe_first_child(xml, PCMK_XE_CONFIGURATION, NULL, NULL); if (config) { nodepriv = config->_private; } if ((nodepriv != NULL) && pcmk_is_set(nodepriv->flags, pcmk__xf_dirty)) { return TRUE; } if ((xml->doc != NULL) && (xml->doc->_private != NULL)) { docpriv = xml->doc->_private; for (gIter = docpriv->deleted_objs; gIter; gIter = gIter->next) { pcmk__deleted_xml_t *deleted_obj = gIter->data; if (strstr(deleted_obj->path, "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION) != NULL) { return TRUE; } } } return FALSE; } // @COMPAT Remove when v1 patchsets are removed static void xml_repair_v1_diff(xmlNode *last, xmlNode *next, xmlNode *local_diff, gboolean changed) { int lpc = 0; xmlNode *cib = NULL; xmlNode *diff_child = NULL; const char *tag = NULL; const char *vfields[] = { PCMK_XA_ADMIN_EPOCH, PCMK_XA_EPOCH, PCMK_XA_NUM_UPDATES, }; if (local_diff == NULL) { crm_trace("Nothing to do"); return; } tag = PCMK__XE_DIFF_REMOVED; diff_child = pcmk__xe_first_child(local_diff, tag, NULL, NULL); if (diff_child == NULL) { diff_child = pcmk__xe_create(local_diff, tag); } tag = PCMK_XE_CIB; cib = pcmk__xe_first_child(diff_child, tag, NULL, NULL); if (cib == NULL) { cib = pcmk__xe_create(diff_child, tag); } for (lpc = 0; (last != NULL) && (lpc < PCMK__NELEM(vfields)); lpc++) { const char *value = crm_element_value(last, vfields[lpc]); crm_xml_add(diff_child, vfields[lpc], value); if (changed || lpc == 2) { crm_xml_add(cib, vfields[lpc], value); } } tag = PCMK__XE_DIFF_ADDED; diff_child = pcmk__xe_first_child(local_diff, tag, NULL, NULL); if (diff_child == NULL) { diff_child = pcmk__xe_create(local_diff, tag); } tag = PCMK_XE_CIB; cib = pcmk__xe_first_child(diff_child, tag, NULL, NULL); if (cib == NULL) { cib = pcmk__xe_create(diff_child, tag); } for (lpc = 0; next && lpc < PCMK__NELEM(vfields); lpc++) { const char *value = crm_element_value(next, vfields[lpc]); crm_xml_add(diff_child, vfields[lpc], value); } for (xmlAttrPtr a = pcmk__xe_first_attr(next); a != NULL; a = a->next) { const char *p_value = pcmk__xml_attr_value(a); pcmk__xe_set_attr_force(cib, (const char *) a->name, p_value); } crm_log_xml_explicit(local_diff, "Repaired-diff"); } // @COMPAT Remove when v1 patchsets are removed static xmlNode * xml_create_patchset_v1(xmlNode *source, xmlNode *target, bool config, bool suppress) { xmlNode *patchset = pcmk__diff_v1_xml_object(source, target, suppress); if (patchset) { CRM_LOG_ASSERT(xml_document_dirty(target)); xml_repair_v1_diff(source, target, patchset, config); crm_xml_add(patchset, PCMK_XA_FORMAT, "1"); } return patchset; } static xmlNode * xml_create_patchset_v2(xmlNode *source, xmlNode *target) { int lpc = 0; GList *gIter = NULL; xml_doc_private_t *docpriv; xmlNode *v = NULL; xmlNode *version = NULL; xmlNode *patchset = NULL; const char *vfields[] = { PCMK_XA_ADMIN_EPOCH, PCMK_XA_EPOCH, PCMK_XA_NUM_UPDATES, }; CRM_ASSERT(target); if (!xml_document_dirty(target)) { return NULL; } CRM_ASSERT(target->doc); docpriv = target->doc->_private; patchset = pcmk__xe_create(NULL, PCMK_XE_DIFF); crm_xml_add_int(patchset, PCMK_XA_FORMAT, 2); version = pcmk__xe_create(patchset, PCMK_XE_VERSION); v = pcmk__xe_create(version, PCMK_XE_SOURCE); for (lpc = 0; lpc < PCMK__NELEM(vfields); lpc++) { const char *value = crm_element_value(source, vfields[lpc]); if (value == NULL) { value = "1"; } crm_xml_add(v, vfields[lpc], value); } v = pcmk__xe_create(version, PCMK_XE_TARGET); for (lpc = 0; lpc < PCMK__NELEM(vfields); lpc++) { const char *value = crm_element_value(target, vfields[lpc]); if (value == NULL) { value = "1"; } crm_xml_add(v, vfields[lpc], value); } for (gIter = docpriv->deleted_objs; gIter; gIter = gIter->next) { pcmk__deleted_xml_t *deleted_obj = gIter->data; xmlNode *change = pcmk__xe_create(patchset, PCMK_XE_CHANGE); crm_xml_add(change, PCMK_XA_OPERATION, PCMK_VALUE_DELETE); crm_xml_add(change, PCMK_XA_PATH, deleted_obj->path); if (deleted_obj->position >= 0) { crm_xml_add_int(change, PCMK_XE_POSITION, deleted_obj->position); } } add_xml_changes_to_patchset(target, patchset); return patchset; } xmlNode * xml_create_patchset(int format, xmlNode *source, xmlNode *target, bool *config_changed, bool manage_version) { int counter = 0; bool config = FALSE; xmlNode *patch = NULL; const char *version = crm_element_value(source, PCMK_XA_CRM_FEATURE_SET); xml_acl_disable(target); if (!xml_document_dirty(target)) { crm_trace("No change %d", format); return NULL; /* No change */ } config = is_config_change(target); if (config_changed) { *config_changed = config; } if (manage_version && config) { crm_trace("Config changed %d", format); crm_xml_add(target, PCMK_XA_NUM_UPDATES, "0"); crm_element_value_int(target, PCMK_XA_EPOCH, &counter); crm_xml_add_int(target, PCMK_XA_EPOCH, counter+1); } else if (manage_version) { crm_element_value_int(target, PCMK_XA_NUM_UPDATES, &counter); crm_trace("Status changed %d - %d %s", format, counter, crm_element_value(source, PCMK_XA_NUM_UPDATES)); crm_xml_add_int(target, PCMK_XA_NUM_UPDATES, (counter + 1)); } if (format == 0) { if (compare_version("3.0.8", version) < 0) { format = 2; } else { format = 1; } crm_trace("Using patch format %d for version: %s", format, version); } switch (format) { case 1: // @COMPAT Remove when v1 patchsets are removed patch = xml_create_patchset_v1(source, target, config, FALSE); break; case 2: patch = xml_create_patchset_v2(source, target); break; default: crm_err("Unknown patch format: %d", format); return NULL; } return patch; } void patchset_process_digest(xmlNode *patch, xmlNode *source, xmlNode *target, bool with_digest) { int format = 1; const char *version = NULL; char *digest = NULL; if ((patch == NULL) || (source == NULL) || (target == NULL)) { return; } /* We should always call xml_accept_changes() before calculating a digest. * Otherwise, with an on-tracking dirty target, we could get a wrong digest. */ CRM_LOG_ASSERT(!xml_document_dirty(target)); crm_element_value_int(patch, PCMK_XA_FORMAT, &format); if ((format > 1) && !with_digest) { return; } version = crm_element_value(source, PCMK_XA_CRM_FEATURE_SET); digest = calculate_xml_versioned_digest(target, FALSE, TRUE, version); crm_xml_add(patch, PCMK__XA_DIGEST, digest); free(digest); return; } // @COMPAT Remove when v1 patchsets are removed static xmlNode * subtract_v1_xml_comment(xmlNode *parent, xmlNode *left, xmlNode *right, gboolean *changed) { CRM_CHECK(left != NULL, return NULL); CRM_CHECK(left->type == XML_COMMENT_NODE, return NULL); if ((right == NULL) || !pcmk__str_eq((const char *)left->content, (const char *)right->content, pcmk__str_casei)) { xmlNode *deleted = NULL; deleted = pcmk__xml_copy(parent, left); *changed = TRUE; return deleted; } return NULL; } // @COMPAT Remove when v1 patchsets are removed static xmlNode * subtract_v1_xml_object(xmlNode *parent, xmlNode *left, xmlNode *right, bool full, gboolean *changed, const char *marker) { gboolean dummy = FALSE; xmlNode *diff = NULL; xmlNode *right_child = NULL; xmlNode *left_child = NULL; xmlAttrPtr xIter = NULL; const char *id = NULL; const char *name = NULL; const char *value = NULL; const char *right_val = NULL; if (changed == NULL) { changed = &dummy; } if (left == NULL) { return NULL; } if (left->type == XML_COMMENT_NODE) { return subtract_v1_xml_comment(parent, left, right, changed); } id = pcmk__xe_id(left); name = (const char *) left->name; if (right == NULL) { xmlNode *deleted = NULL; crm_trace("Processing <%s " PCMK_XA_ID "=%s> (complete copy)", name, id); deleted = pcmk__xml_copy(parent, left); crm_xml_add(deleted, PCMK__XA_CRM_DIFF_MARKER, marker); *changed = TRUE; return deleted; } CRM_CHECK(name != NULL, return NULL); CRM_CHECK(pcmk__xe_is(left, (const char *) right->name), return NULL); // Check for PCMK__XA_CRM_DIFF_MARKER in a child value = crm_element_value(right, PCMK__XA_CRM_DIFF_MARKER); if ((value != NULL) && (strcmp(value, "removed:top") == 0)) { crm_trace("We are the root of the deletion: %s.id=%s", name, id); *changed = TRUE; return NULL; } // @TODO Avoiding creating the full hierarchy would save work here diff = pcmk__xe_create(parent, name); // Changes to child objects for (left_child = pcmk__xml_first_child(left); left_child != NULL; left_child = pcmk__xml_next(left_child)) { gboolean child_changed = FALSE; right_child = pcmk__xml_match(right, left_child, false); subtract_v1_xml_object(diff, left_child, right_child, full, &child_changed, marker); if (child_changed) { *changed = TRUE; } } if (!*changed) { /* Nothing to do */ } else if (full) { xmlAttrPtr pIter = NULL; for (pIter = pcmk__xe_first_attr(left); pIter != NULL; pIter = pIter->next) { const char *p_name = (const char *)pIter->name; const char *p_value = pcmk__xml_attr_value(pIter); pcmk__xe_set_attr_force(diff, p_name, p_value); } // We have everything we need goto done; } // Changes to name/value pairs for (xIter = pcmk__xe_first_attr(left); xIter != NULL; xIter = xIter->next) { const char *prop_name = (const char *) xIter->name; xmlAttrPtr right_attr = NULL; xml_node_private_t *nodepriv = NULL; if (strcmp(prop_name, PCMK_XA_ID) == 0) { // id already obtained when present ~ this case, so just reuse pcmk__xe_set_attr_force(diff, PCMK_XA_ID, id); continue; } if (pcmk__xa_filterable(prop_name)) { continue; } right_attr = xmlHasProp(right, (pcmkXmlStr) prop_name); if (right_attr) { nodepriv = right_attr->_private; } right_val = crm_element_value(right, prop_name); if ((right_val == NULL) || (nodepriv && pcmk_is_set(nodepriv->flags, pcmk__xf_deleted))) { /* new */ *changed = TRUE; if (full) { xmlAttrPtr pIter = NULL; for (pIter = pcmk__xe_first_attr(left); pIter != NULL; pIter = pIter->next) { const char *p_name = (const char *) pIter->name; const char *p_value = pcmk__xml_attr_value(pIter); pcmk__xe_set_attr_force(diff, p_name, p_value); } break; } else { const char *left_value = pcmk__xml_attr_value(xIter); pcmk__xe_set_attr_force(diff, prop_name, value); crm_xml_add(diff, prop_name, left_value); } } else { /* Only now do we need the left value */ const char *left_value = pcmk__xml_attr_value(xIter); if (strcmp(left_value, right_val) == 0) { /* unchanged */ } else { *changed = TRUE; if (full) { xmlAttrPtr pIter = NULL; crm_trace("Changes detected to %s in " "<%s " PCMK_XA_ID "=%s>", prop_name, name, id); for (pIter = pcmk__xe_first_attr(left); pIter != NULL; pIter = pIter->next) { const char *p_name = (const char *) pIter->name; const char *p_value = pcmk__xml_attr_value(pIter); pcmk__xe_set_attr_force(diff, p_name, p_value); } break; } else { crm_trace("Changes detected to %s (%s -> %s) in " "<%s " PCMK_XA_ID "=%s>", prop_name, left_value, right_val, name, id); crm_xml_add(diff, prop_name, left_value); } } } } if (!*changed) { free_xml(diff); return NULL; } else if (!full && (id != NULL)) { crm_xml_add(diff, PCMK_XA_ID, id); } done: return diff; } /* @COMPAT Remove when v1 patchsets are removed. * * Return true if attribute name is not \c PCMK_XML_ID. */ static bool not_id(xmlAttrPtr attr, void *user_data) { return strcmp((const char *) attr->name, PCMK_XA_ID) != 0; } /* @COMPAT Remove when v1 patchsets are removed. * * Apply the removals section of a v1 patchset to an XML node. */ static void process_v1_removals(xmlNode *target, xmlNode *patch) { xmlNode *patch_child = NULL; xmlNode *cIter = NULL; char *id = NULL; const char *value = NULL; if ((target == NULL) || (patch == NULL)) { return; } if (target->type == XML_COMMENT_NODE) { gboolean dummy; subtract_v1_xml_comment(target->parent, target, patch, &dummy); } CRM_CHECK(pcmk__xe_is(target, (const char *) patch->name), return); CRM_CHECK(pcmk__str_eq(pcmk__xe_id(target), pcmk__xe_id(patch), pcmk__str_none), return); // Check for PCMK__XA_CRM_DIFF_MARKER in a child id = crm_element_value_copy(target, PCMK_XA_ID); value = crm_element_value(patch, PCMK__XA_CRM_DIFF_MARKER); if ((value != NULL) && (strcmp(value, "removed:top") == 0)) { crm_trace("We are the root of the deletion: %s.id=%s", target->name, id); free_xml(target); free(id); return; } // Removing then restoring id would change ordering of properties pcmk__xe_remove_matching_attrs(patch, not_id, NULL); // Changes to child objects cIter = pcmk__xml_first_child(target); while (cIter) { xmlNode *target_child = cIter; cIter = pcmk__xml_next(cIter); patch_child = pcmk__xml_match(patch, target_child, false); process_v1_removals(target_child, patch_child); } free(id); } /* @COMPAT Remove when v1 patchsets are removed. * * Apply the additions section of a v1 patchset to an XML node. */ static void process_v1_additions(xmlNode *parent, xmlNode *target, xmlNode *patch) { xmlNode *patch_child = NULL; xmlNode *target_child = NULL; xmlAttrPtr xIter = NULL; const char *id = NULL; const char *name = NULL; const char *value = NULL; if (patch == NULL) { return; } else if ((parent == NULL) && (target == NULL)) { return; } // Check for PCMK__XA_CRM_DIFF_MARKER in a child name = (const char *) patch->name; value = crm_element_value(patch, PCMK__XA_CRM_DIFF_MARKER); if ((target == NULL) && (value != NULL) && (strcmp(value, "added:top") == 0)) { id = pcmk__xe_id(patch); crm_trace("We are the root of the addition: %s.id=%s", name, id); pcmk__xml_copy(parent, patch); return; } else if (target == NULL) { id = pcmk__xe_id(patch); crm_err("Could not locate: %s.id=%s", name, id); return; } if (target->type == XML_COMMENT_NODE) { pcmk__xc_update(parent, target, patch); } CRM_CHECK(pcmk__xe_is(target, name), return); CRM_CHECK(pcmk__str_eq(pcmk__xe_id(target), pcmk__xe_id(patch), pcmk__str_none), return); for (xIter = pcmk__xe_first_attr(patch); xIter != NULL; xIter = xIter->next) { const char *p_name = (const char *) xIter->name; const char *p_value = pcmk__xml_attr_value(xIter); pcmk__xe_remove_attr(target, p_name); // Preserve patch order crm_xml_add(target, p_name, p_value); } // Changes to child objects for (patch_child = pcmk__xml_first_child(patch); patch_child != NULL; patch_child = pcmk__xml_next(patch_child)) { target_child = pcmk__xml_match(target, patch_child, false); process_v1_additions(target, target_child, patch_child); } } /*! * \internal * \brief Find additions or removals in a patch set * * \param[in] patchset XML of patch * \param[in] format Patch version * \param[in] added TRUE if looking for additions, FALSE if removals * \param[in,out] patch_node Will be set to node if found * * \return TRUE if format is valid, FALSE if invalid */ static bool find_patch_xml_node(const xmlNode *patchset, int format, bool added, xmlNode **patch_node) { xmlNode *cib_node; const char *label; switch (format) { case 1: // @COMPAT Remove when v1 patchsets are removed label = added? PCMK__XE_DIFF_ADDED : PCMK__XE_DIFF_REMOVED; *patch_node = pcmk__xe_first_child(patchset, label, NULL, NULL); cib_node = pcmk__xe_first_child(*patch_node, PCMK_XE_CIB, NULL, NULL); if (cib_node != NULL) { *patch_node = cib_node; } break; case 2: label = added? PCMK_XE_TARGET : PCMK_XE_SOURCE; *patch_node = pcmk__xe_first_child(patchset, PCMK_XE_VERSION, NULL, NULL); *patch_node = pcmk__xe_first_child(*patch_node, label, NULL, NULL); break; default: crm_warn("Unknown patch format: %d", format); *patch_node = NULL; return FALSE; } return TRUE; } // Get CIB versions used for additions and deletions in a patchset bool xml_patch_versions(const xmlNode *patchset, int add[3], int del[3]) { int lpc = 0; int format = 1; xmlNode *tmp = NULL; const char *vfields[] = { PCMK_XA_ADMIN_EPOCH, PCMK_XA_EPOCH, PCMK_XA_NUM_UPDATES, }; crm_element_value_int(patchset, PCMK_XA_FORMAT, &format); /* Process removals */ if (!find_patch_xml_node(patchset, format, FALSE, &tmp)) { return -EINVAL; } if (tmp != NULL) { for (lpc = 0; lpc < PCMK__NELEM(vfields); lpc++) { crm_element_value_int(tmp, vfields[lpc], &(del[lpc])); crm_trace("Got %d for del[%s]", del[lpc], vfields[lpc]); } } /* Process additions */ if (!find_patch_xml_node(patchset, format, TRUE, &tmp)) { return -EINVAL; } if (tmp != NULL) { for (lpc = 0; lpc < PCMK__NELEM(vfields); lpc++) { crm_element_value_int(tmp, vfields[lpc], &(add[lpc])); crm_trace("Got %d for add[%s]", add[lpc], vfields[lpc]); } } return pcmk_ok; } /*! * \internal * \brief Check whether patchset can be applied to current CIB * * \param[in] xml Root of current CIB * \param[in] patchset Patchset to check * * \return Standard Pacemaker return code */ static int xml_patch_version_check(const xmlNode *xml, const xmlNode *patchset) { int lpc = 0; bool changed = FALSE; int this[] = { 0, 0, 0 }; int add[] = { 0, 0, 0 }; int del[] = { 0, 0, 0 }; const char *vfields[] = { PCMK_XA_ADMIN_EPOCH, PCMK_XA_EPOCH, PCMK_XA_NUM_UPDATES, }; for (lpc = 0; lpc < PCMK__NELEM(vfields); lpc++) { crm_element_value_int(xml, vfields[lpc], &(this[lpc])); crm_trace("Got %d for this[%s]", this[lpc], vfields[lpc]); if (this[lpc] < 0) { this[lpc] = 0; } } /* Set some defaults in case nothing is present */ add[0] = this[0]; add[1] = this[1]; add[2] = this[2] + 1; for (lpc = 0; lpc < PCMK__NELEM(vfields); lpc++) { del[lpc] = this[lpc]; } xml_patch_versions(patchset, add, del); for (lpc = 0; lpc < PCMK__NELEM(vfields); lpc++) { if (this[lpc] < del[lpc]) { crm_debug("Current %s is too low (%d.%d.%d < %d.%d.%d --> %d.%d.%d)", vfields[lpc], this[0], this[1], this[2], del[0], del[1], del[2], add[0], add[1], add[2]); return pcmk_rc_diff_resync; } else if (this[lpc] > del[lpc]) { crm_info("Current %s is too high (%d.%d.%d > %d.%d.%d --> %d.%d.%d) %p", vfields[lpc], this[0], this[1], this[2], del[0], del[1], del[2], add[0], add[1], add[2], patchset); crm_log_xml_info(patchset, "OldPatch"); return pcmk_rc_old_data; } } for (lpc = 0; lpc < PCMK__NELEM(vfields); lpc++) { if (add[lpc] > del[lpc]) { changed = TRUE; } } if (!changed) { crm_notice("Versions did not change in patch %d.%d.%d", add[0], add[1], add[2]); return pcmk_rc_old_data; } crm_debug("Can apply patch %d.%d.%d to %d.%d.%d", add[0], add[1], add[2], this[0], this[1], this[2]); return pcmk_rc_ok; } // @COMPAT Remove when v1 patchsets are removed static void purge_v1_diff_markers(xmlNode *node) { xmlNode *child = NULL; CRM_CHECK(node != NULL, return); pcmk__xe_remove_attr(node, PCMK__XA_CRM_DIFF_MARKER); for (child = pcmk__xml_first_child(node); child != NULL; child = pcmk__xml_next(child)) { purge_v1_diff_markers(child); } } // @COMPAT Remove when v1 patchsets are removed /*! * \internal * \brief Apply a version 1 patchset to an XML node * * \param[in,out] xml XML to apply patchset to * \param[in] patchset Patchset to apply * * \return Standard Pacemaker return code */ static int apply_v1_patchset(xmlNode *xml, const xmlNode *patchset) { int rc = pcmk_rc_ok; int root_nodes_seen = 0; xmlNode *child_diff = NULL; xmlNode *added = pcmk__xe_first_child(patchset, PCMK__XE_DIFF_ADDED, NULL, NULL); xmlNode *removed = pcmk__xe_first_child(patchset, PCMK__XE_DIFF_REMOVED, NULL, NULL); xmlNode *old = pcmk__xml_copy(NULL, xml); crm_trace("Subtraction Phase"); for (child_diff = pcmk__xml_first_child(removed); child_diff != NULL; child_diff = pcmk__xml_next(child_diff)) { CRM_CHECK(root_nodes_seen == 0, rc = FALSE); if (root_nodes_seen == 0) { process_v1_removals(xml, child_diff); } root_nodes_seen++; } if (root_nodes_seen > 1) { crm_err("(-) Diffs cannot contain more than one change set... saw %d", root_nodes_seen); rc = ENOTUNIQ; } root_nodes_seen = 0; crm_trace("Addition Phase"); if (rc == pcmk_rc_ok) { xmlNode *child_diff = NULL; for (child_diff = pcmk__xml_first_child(added); child_diff != NULL; child_diff = pcmk__xml_next(child_diff)) { CRM_CHECK(root_nodes_seen == 0, rc = FALSE); if (root_nodes_seen == 0) { process_v1_additions(NULL, xml, child_diff); } root_nodes_seen++; } } if (root_nodes_seen > 1) { crm_err("(+) Diffs cannot contain more than one change set... saw %d", root_nodes_seen); rc = ENOTUNIQ; } purge_v1_diff_markers(xml); // Purge prior to checking digest free_xml(old); return rc; } // Return first child matching element name and optionally id or position static xmlNode * first_matching_xml_child(const xmlNode *parent, const char *name, const char *id, int position) { xmlNode *cIter = NULL; for (cIter = pcmk__xml_first_child(parent); cIter != NULL; cIter = pcmk__xml_next(cIter)) { if (strcmp((const char *) cIter->name, name) != 0) { continue; } else if (id) { const char *cid = pcmk__xe_id(cIter); if ((cid == NULL) || (strcmp(cid, id) != 0)) { continue; } } // "position" makes sense only for XML comments for now if ((cIter->type == XML_COMMENT_NODE) && (position >= 0) && (pcmk__xml_position(cIter, pcmk__xf_skip) != position)) { continue; } return cIter; } return NULL; } /*! * \internal * \brief Simplified, more efficient alternative to get_xpath_object() * * \param[in] top Root of XML to search * \param[in] key Search xpath * \param[in] target_position If deleting, where to delete * * \return XML child matching xpath if found, NULL otherwise * * \note This only works on simplified xpaths found in v2 patchset diffs, * i.e. the only allowed search predicate is [@id='XXX']. */ static xmlNode * search_v2_xpath(const xmlNode *top, const char *key, int target_position) { xmlNode *target = (xmlNode *) top->doc; const char *current = key; char *section; char *remainder; char *id; char *tag; char *path = NULL; int rc; size_t key_len; CRM_CHECK(key != NULL, return NULL); key_len = strlen(key); /* These are scanned from key after a slash, so they can't be bigger * than key_len - 1 characters plus a null terminator. */ remainder = pcmk__assert_alloc(key_len, sizeof(char)); section = pcmk__assert_alloc(key_len, sizeof(char)); id = pcmk__assert_alloc(key_len, sizeof(char)); tag = pcmk__assert_alloc(key_len, sizeof(char)); do { // Look for /NEXT_COMPONENT/REMAINING_COMPONENTS rc = sscanf(current, "/%[^/]%s", section, remainder); if (rc > 0) { // Separate FIRST_COMPONENT into TAG[@id='ID'] int f = sscanf(section, "%[^[][@" PCMK_XA_ID "='%[^']", tag, id); int current_position = -1; /* The target position is for the final component tag, so only use * it if there is nothing left to search after this component. */ if ((rc == 1) && (target_position >= 0)) { current_position = target_position; } switch (f) { case 1: // @COMPAT Remove when v1 patchsets are removed target = first_matching_xml_child(target, tag, NULL, current_position); break; case 2: target = first_matching_xml_child(target, tag, id, current_position); break; default: // This should not be possible target = NULL; break; } current = remainder; } // Continue if something remains to search, and we've matched so far } while ((rc == 2) && target); if (target) { crm_trace("Found %s for %s", (path = (char *) xmlGetNodePath(target)), key); free(path); } else { crm_debug("No match for %s", key); } free(remainder); free(section); free(tag); free(id); return target; } typedef struct xml_change_obj_s { const xmlNode *change; xmlNode *match; } xml_change_obj_t; static gint sort_change_obj_by_position(gconstpointer a, gconstpointer b) { const xml_change_obj_t *change_obj_a = a; const xml_change_obj_t *change_obj_b = b; int position_a = -1; int position_b = -1; crm_element_value_int(change_obj_a->change, PCMK_XE_POSITION, &position_a); crm_element_value_int(change_obj_b->change, PCMK_XE_POSITION, &position_b); if (position_a < position_b) { return -1; } else if (position_a > position_b) { return 1; } return 0; } /*! * \internal * \brief Apply a version 2 patchset to an XML node * * \param[in,out] xml XML to apply patchset to * \param[in] patchset Patchset to apply * * \return Standard Pacemaker return code */ static int apply_v2_patchset(xmlNode *xml, const xmlNode *patchset) { int rc = pcmk_rc_ok; const xmlNode *change = NULL; GList *change_objs = NULL; GList *gIter = NULL; for (change = pcmk__xml_first_child(patchset); change != NULL; change = pcmk__xml_next(change)) { xmlNode *match = NULL; const char *op = crm_element_value(change, PCMK_XA_OPERATION); const char *xpath = crm_element_value(change, PCMK_XA_PATH); int position = -1; if (op == NULL) { continue; } crm_trace("Processing %s %s", change->name, op); /* PCMK_VALUE_DELETE changes for XML comments are generated with * PCMK_XE_POSITION */ if (strcmp(op, PCMK_VALUE_DELETE) == 0) { crm_element_value_int(change, PCMK_XE_POSITION, &position); } match = search_v2_xpath(xml, xpath, position); crm_trace("Performing %s on %s with %p", op, xpath, match); if ((match == NULL) && (strcmp(op, PCMK_VALUE_DELETE) == 0)) { crm_debug("No %s match for %s in %p", op, xpath, xml->doc); continue; } else if (match == NULL) { crm_err("No %s match for %s in %p", op, xpath, xml->doc); rc = pcmk_rc_diff_failed; continue; } else if (pcmk__str_any_of(op, PCMK_VALUE_CREATE, PCMK_VALUE_MOVE, NULL)) { // Delay the adding of a PCMK_VALUE_CREATE object xml_change_obj_t *change_obj = pcmk__assert_alloc(1, sizeof(xml_change_obj_t)); change_obj->change = change; change_obj->match = match; change_objs = g_list_append(change_objs, change_obj); if (strcmp(op, PCMK_VALUE_MOVE) == 0) { // Temporarily put the PCMK_VALUE_MOVE object after the last sibling if ((match->parent != NULL) && (match->parent->last != NULL)) { xmlAddNextSibling(match->parent->last, match); } } } else if (strcmp(op, PCMK_VALUE_DELETE) == 0) { free_xml(match); } else if (strcmp(op, PCMK_VALUE_MODIFY) == 0) { const xmlNode *child = pcmk__xe_first_child(change, PCMK_XE_CHANGE_RESULT, NULL, NULL); const xmlNode *attrs = pcmk__xml_first_child(child); if (attrs == NULL) { rc = ENOMSG; continue; } pcmk__xe_remove_matching_attrs(match, NULL, NULL); // Remove all for (xmlAttrPtr pIter = pcmk__xe_first_attr(attrs); pIter != NULL; pIter = pIter->next) { const char *name = (const char *) pIter->name; const char *value = pcmk__xml_attr_value(pIter); crm_xml_add(match, name, value); } } else { crm_err("Unknown operation: %s", op); rc = pcmk_rc_diff_failed; } } // Changes should be generated in the right order. Double checking. change_objs = g_list_sort(change_objs, sort_change_obj_by_position); for (gIter = change_objs; gIter; gIter = gIter->next) { xml_change_obj_t *change_obj = gIter->data; xmlNode *match = change_obj->match; const char *op = NULL; const char *xpath = NULL; change = change_obj->change; op = crm_element_value(change, PCMK_XA_OPERATION); xpath = crm_element_value(change, PCMK_XA_PATH); crm_trace("Continue performing %s on %s with %p", op, xpath, match); if (strcmp(op, PCMK_VALUE_CREATE) == 0) { int position = 0; xmlNode *child = NULL; xmlNode *match_child = NULL; match_child = match->children; crm_element_value_int(change, PCMK_XE_POSITION, &position); while ((match_child != NULL) && (position != pcmk__xml_position(match_child, pcmk__xf_skip))) { match_child = match_child->next; } - child = xmlDocCopyNode(change->children, match->doc, 1); - if (child == NULL) { - return ENOMEM; - } + child = pcmk__xml_copy(match, change->children); - if (match_child) { + if (match_child != NULL) { crm_trace("Adding %s at position %d", child->name, position); xmlAddPrevSibling(match_child, child); - } else if (match->last) { - crm_trace("Adding %s at position %d (end)", - child->name, position); - xmlAddNextSibling(match->last, child); - } else { - crm_trace("Adding %s at position %d (first)", + crm_trace("Adding %s at position %d (end)", child->name, position); - CRM_LOG_ASSERT(position == 0); - xmlAddChild(match, child); } - pcmk__xml_mark_created(child); } else if (strcmp(op, PCMK_VALUE_MOVE) == 0) { int position = 0; crm_element_value_int(change, PCMK_XE_POSITION, &position); if (position != pcmk__xml_position(match, pcmk__xf_skip)) { xmlNode *match_child = NULL; int p = position; if (p > pcmk__xml_position(match, pcmk__xf_skip)) { p++; // Skip ourselves } CRM_ASSERT(match->parent != NULL); match_child = match->parent->children; while ((match_child != NULL) && (p != pcmk__xml_position(match_child, pcmk__xf_skip))) { match_child = match_child->next; } crm_trace("Moving %s to position %d (was %d, prev %p, %s %p)", match->name, position, pcmk__xml_position(match, pcmk__xf_skip), match->prev, (match_child? "next":"last"), (match_child? match_child : match->parent->last)); if (match_child) { xmlAddPrevSibling(match_child, match); } else { CRM_ASSERT(match->parent->last != NULL); xmlAddNextSibling(match->parent->last, match); } } else { crm_trace("%s is already in position %d", match->name, position); } if (position != pcmk__xml_position(match, pcmk__xf_skip)) { crm_err("Moved %s.%s to position %d instead of %d (%p)", match->name, pcmk__xe_id(match), pcmk__xml_position(match, pcmk__xf_skip), position, match->prev); rc = pcmk_rc_diff_failed; } } } g_list_free_full(change_objs, free); return rc; } int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version) { int format = 1; int rc = pcmk_ok; xmlNode *old = NULL; const char *digest = NULL; if (patchset == NULL) { return rc; } pcmk__log_xml_patchset(LOG_TRACE, patchset); if (check_version) { rc = pcmk_rc2legacy(xml_patch_version_check(xml, patchset)); if (rc != pcmk_ok) { return rc; } } digest = crm_element_value(patchset, PCMK__XA_DIGEST); if (digest != NULL) { /* Make original XML available for logging in case result doesn't have * expected digest */ pcmk__if_tracing(old = pcmk__xml_copy(NULL, xml), {}); } if (rc == pcmk_ok) { crm_element_value_int(patchset, PCMK_XA_FORMAT, &format); switch (format) { case 1: // @COMPAT Remove when v1 patchsets are removed rc = pcmk_rc2legacy(apply_v1_patchset(xml, patchset)); break; case 2: rc = pcmk_rc2legacy(apply_v2_patchset(xml, patchset)); break; default: crm_err("Unknown patch format: %d", format); rc = -EINVAL; } } if ((rc == pcmk_ok) && (digest != NULL)) { char *new_digest = NULL; char *version = crm_element_value_copy(xml, PCMK_XA_CRM_FEATURE_SET); new_digest = calculate_xml_versioned_digest(xml, FALSE, TRUE, version); if (!pcmk__str_eq(new_digest, digest, pcmk__str_casei)) { crm_info("v%d digest mis-match: expected %s, calculated %s", format, digest, new_digest); rc = -pcmk_err_diff_failed; pcmk__if_tracing( { save_xml_to_file(old, "PatchDigest:input", NULL); save_xml_to_file(xml, "PatchDigest:result", NULL); save_xml_to_file(patchset, "PatchDigest:diff", NULL); }, {} ); } else { crm_trace("v%d digest matched: expected %s, calculated %s", format, digest, new_digest); } free(new_digest); free(version); } free_xml(old); return rc; } // @COMPAT Remove when v1 patchsets are removed static bool can_prune_leaf_v1(xmlNode *node) { xmlNode *cIter = NULL; bool can_prune = true; CRM_CHECK(node != NULL, return false); /* @COMPAT PCMK__XE_ROLE_REF was deprecated in Pacemaker 1.1.12 (needed for * rolling upgrades) */ if (pcmk__strcase_any_of((const char *) node->name, PCMK_XE_RESOURCE_REF, PCMK_XE_OBJ_REF, PCMK_XE_ROLE, PCMK__XE_ROLE_REF, NULL)) { return false; } for (xmlAttrPtr a = pcmk__xe_first_attr(node); a != NULL; a = a->next) { const char *p_name = (const char *) a->name; if (strcmp(p_name, PCMK_XA_ID) == 0) { continue; } can_prune = false; } cIter = pcmk__xml_first_child(node); while (cIter) { xmlNode *child = cIter; cIter = pcmk__xml_next(cIter); if (can_prune_leaf_v1(child)) { free_xml(child); } else { can_prune = false; } } return can_prune; } // @COMPAT Remove when v1 patchsets are removed xmlNode * pcmk__diff_v1_xml_object(xmlNode *old, xmlNode *new, bool suppress) { xmlNode *tmp1 = NULL; xmlNode *diff = pcmk__xe_create(NULL, PCMK_XE_DIFF); xmlNode *removed = pcmk__xe_create(diff, PCMK__XE_DIFF_REMOVED); xmlNode *added = pcmk__xe_create(diff, PCMK__XE_DIFF_ADDED); crm_xml_add(diff, PCMK_XA_CRM_FEATURE_SET, CRM_FEATURE_SET); tmp1 = subtract_v1_xml_object(removed, old, new, false, NULL, "removed:top"); if (suppress && (tmp1 != NULL) && can_prune_leaf_v1(tmp1)) { free_xml(tmp1); } tmp1 = subtract_v1_xml_object(added, new, old, true, NULL, "added:top"); if (suppress && (tmp1 != NULL) && can_prune_leaf_v1(tmp1)) { free_xml(tmp1); } if ((added->children == NULL) && (removed->children == NULL)) { free_xml(diff); diff = NULL; } return diff; } // Deprecated functions kept only for backward API compatibility // LCOV_EXCL_START #include gboolean apply_xml_diff(xmlNode *old_xml, xmlNode *diff, xmlNode **new_xml) { gboolean result = TRUE; int root_nodes_seen = 0; const char *digest = crm_element_value(diff, PCMK__XA_DIGEST); const char *version = crm_element_value(diff, PCMK_XA_CRM_FEATURE_SET); xmlNode *child_diff = NULL; xmlNode *added = pcmk__xe_first_child(diff, PCMK__XE_DIFF_ADDED, NULL, NULL); xmlNode *removed = pcmk__xe_first_child(diff, PCMK__XE_DIFF_REMOVED, NULL, NULL); CRM_CHECK(new_xml != NULL, return FALSE); crm_trace("Subtraction Phase"); for (child_diff = pcmk__xml_first_child(removed); child_diff != NULL; child_diff = pcmk__xml_next(child_diff)) { CRM_CHECK(root_nodes_seen == 0, result = FALSE); if (root_nodes_seen == 0) { *new_xml = subtract_v1_xml_object(NULL, old_xml, child_diff, false, NULL, NULL); } root_nodes_seen++; } if (root_nodes_seen == 0) { *new_xml = pcmk__xml_copy(NULL, old_xml); } else if (root_nodes_seen > 1) { crm_err("(-) Diffs cannot contain more than one change set... saw %d", root_nodes_seen); result = FALSE; } root_nodes_seen = 0; crm_trace("Addition Phase"); if (result) { xmlNode *child_diff = NULL; for (child_diff = pcmk__xml_first_child(added); child_diff != NULL; child_diff = pcmk__xml_next(child_diff)) { CRM_CHECK(root_nodes_seen == 0, result = FALSE); if (root_nodes_seen == 0) { pcmk__xml_update(NULL, *new_xml, child_diff, pcmk__xaf_none, true); } root_nodes_seen++; } } if (root_nodes_seen > 1) { crm_err("(+) Diffs cannot contain more than one change set... saw %d", root_nodes_seen); result = FALSE; } else if (result && (digest != NULL)) { char *new_digest = NULL; purge_v1_diff_markers(*new_xml); // Purge now so diff is ok new_digest = calculate_xml_versioned_digest(*new_xml, FALSE, TRUE, version); if (!pcmk__str_eq(new_digest, digest, pcmk__str_casei)) { crm_info("Digest mis-match: expected %s, calculated %s", digest, new_digest); result = FALSE; pcmk__if_tracing( { save_xml_to_file(old_xml, "diff:original", NULL); save_xml_to_file(diff, "diff:input", NULL); save_xml_to_file(*new_xml, "diff:new", NULL); }, {} ); } else { crm_trace("Digest matched: expected %s, calculated %s", digest, new_digest); } free(new_digest); } else if (result) { purge_v1_diff_markers(*new_xml); // Purge now so diff is ok } return result; } void purge_diff_markers(xmlNode *a_node) { purge_v1_diff_markers(a_node); } xmlNode * diff_xml_object(xmlNode *old, xmlNode *new, gboolean suppress) { return pcmk__diff_v1_xml_object(old, new, suppress); } xmlNode * subtract_xml_object(xmlNode *parent, xmlNode *left, xmlNode *right, gboolean full, gboolean *changed, const char *marker) { return subtract_v1_xml_object(parent, left, right, full, changed, marker); } gboolean can_prune_leaf(xmlNode *xml_node) { return can_prune_leaf_v1(xml_node); } // LCOV_EXCL_STOP // End deprecated API diff --git a/lib/common/xml.c b/lib/common/xml.c index 066f1adbd2..0b41a16442 100644 --- a/lib/common/xml.c +++ b/lib/common/xml.c @@ -1,2657 +1,2668 @@ /* * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include #include #include // uint32_t #include #include #include #include // stat(), S_ISREG, etc. #include #include #include #include #include #include // PCMK__XML_LOG_BASE, etc. #include "crmcommon_private.h" //! libxml2 supports only XML version 1.0, at least as of libxml2-2.12.5 #define XML_VERSION ((pcmkXmlStr) "1.0") /*! * \internal * \brief Apply a function to each XML node in a tree (pre-order, depth-first) * * \param[in,out] xml XML tree to traverse * \param[in,out] fn Function to call for each node (returns \c true to * continue traversing the tree or \c false to stop) * \param[in,out] user_data Argument to \p fn * * \return \c false if any \p fn call returned \c false, or \c true otherwise * * \note This function is recursive. */ bool pcmk__xml_tree_foreach(xmlNode *xml, bool (*fn)(xmlNode *, void *), void *user_data) { if (xml == NULL) { return true; } if (!fn(xml, user_data)) { return false; } for (xml = pcmk__xml_first_child(xml); xml != NULL; xml = pcmk__xml_next(xml)) { if (!pcmk__xml_tree_foreach(xml, fn, user_data)) { return false; } } return true; } bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy) { if(xml == NULL || xml->doc == NULL || xml->doc->_private == NULL) { return FALSE; } else if (!pcmk_is_set(((xml_doc_private_t *)xml->doc->_private)->flags, pcmk__xf_tracking)) { return FALSE; } else if (lazy && !pcmk_is_set(((xml_doc_private_t *)xml->doc->_private)->flags, pcmk__xf_lazy)) { return FALSE; } return TRUE; } void pcmk__xml_set_parent_flags(xmlNode *xml, uint64_t flags) { for (; xml != NULL; xml = xml->parent) { xml_node_private_t *nodepriv = xml->_private; if (nodepriv != NULL) { /* During calls to xmlDocCopyNode(), _private will be unset for * parent nodes */ pcmk__set_xml_flags(nodepriv, flags); } } } void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag) { if(xml && xml->doc && xml->doc->_private){ /* During calls to xmlDocCopyNode(), xml->doc may be unset */ xml_doc_private_t *docpriv = xml->doc->_private; pcmk__set_xml_flags(docpriv, flag); } } // Mark document, element, and all element's parents as changed void pcmk__mark_xml_node_dirty(xmlNode *xml) { pcmk__set_xml_doc_flag(xml, pcmk__xf_dirty); pcmk__xml_set_parent_flags(xml, pcmk__xf_dirty); } /*! * \internal * \brief Clear flags on an XML node * * \param[in,out] xml XML node whose flags to reset * \param[in,out] user_data Ignored * * \return \c true (to continue traversing the tree) * * \note This is compatible with \c pcmk__xml_tree_foreach(). */ static bool reset_xml_node_flags(xmlNode *xml, void *user_data) { xml_node_private_t *nodepriv = xml->_private; if (nodepriv != NULL) { nodepriv->flags = pcmk__xf_none; } return true; } /*! * \internal * \brief Set the \c pcmk__xf_dirty and \c pcmk__xf_created flags on an XML node * * \param[in,out] xml Node whose flags to set * \param[in] user_data Ignored * * \return \c true (to continue traversing the tree) * * \note This is compatible with \c pcmk__xml_tree_foreach(). */ static bool mark_xml_dirty_created(xmlNode *xml, void *user_data) { xml_node_private_t *nodepriv = xml->_private; if (nodepriv != NULL) { pcmk__set_xml_flags(nodepriv, pcmk__xf_dirty|pcmk__xf_created); } return true; } /*! * \internal * \brief Mark an XML tree as dirty and created, and mark its parents dirty * * Also mark the document dirty. * * \param[in,out] xml Tree to mark as dirty and created */ void pcmk__xml_mark_created(xmlNode *xml) { CRM_ASSERT(xml != NULL); if (!pcmk__tracking_xml_changes(xml, false)) { // Tracking is disabled for entire document return; } // Mark all parents and document dirty pcmk__mark_xml_node_dirty(xml); pcmk__xml_tree_foreach(xml, mark_xml_dirty_created, NULL); } // Free an XML object previously marked as deleted static void free_deleted_object(void *data) { if(data) { pcmk__deleted_xml_t *deleted_obj = data; g_free(deleted_obj->path); free(deleted_obj); } } // Free and NULL user, ACLs, and deleted objects in an XML node's private data static void reset_xml_private_data(xml_doc_private_t *docpriv) { if (docpriv != NULL) { CRM_ASSERT(docpriv->check == PCMK__XML_DOC_PRIVATE_MAGIC); free(docpriv->user); docpriv->user = NULL; if (docpriv->acls != NULL) { pcmk__free_acls(docpriv->acls); docpriv->acls = NULL; } if(docpriv->deleted_objs) { g_list_free_full(docpriv->deleted_objs, free_deleted_object); docpriv->deleted_objs = NULL; } } } // Free all private data associated with an XML node static void free_private_data(xmlNode *node) { /* Note: This function frees private data assosciated with an XML node, unless the function is being called as a result of internal XSLT cleanup. That could happen through, for example, the following chain of function calls: xsltApplyStylesheetInternal -> xsltFreeTransformContext -> xsltFreeRVTs -> xmlFreeDoc And in that case, the node would fulfill three conditions: 1. It would be a standalone document (i.e. it wouldn't be part of a document) 2. It would have a space-prefixed name (for reference, please see xsltInternals.h: XSLT_MARK_RES_TREE_FRAG) 3. It would carry its own payload in the _private field. We do not free data in this circumstance to avoid a failed assertion on the PCMK__XML_*_PRIVATE_MAGIC later. */ if (node->name == NULL || node->name[0] != ' ') { if (node->_private) { if (node->type == XML_DOCUMENT_NODE) { reset_xml_private_data(node->_private); } else { CRM_ASSERT(((xml_node_private_t *) node->_private)->check == PCMK__XML_NODE_PRIVATE_MAGIC); /* nothing dynamically allocated nested */ } free(node->_private); node->_private = NULL; } } } // Allocate and initialize private data for an XML node static void new_private_data(xmlNode *node) { switch (node->type) { case XML_DOCUMENT_NODE: { xml_doc_private_t *docpriv = pcmk__assert_alloc(1, sizeof(xml_doc_private_t)); docpriv->check = PCMK__XML_DOC_PRIVATE_MAGIC; /* Flags will be reset if necessary when tracking is enabled */ pcmk__set_xml_flags(docpriv, pcmk__xf_dirty|pcmk__xf_created); node->_private = docpriv; break; } case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: case XML_COMMENT_NODE: { xml_node_private_t *nodepriv = pcmk__assert_alloc(1, sizeof(xml_node_private_t)); nodepriv->check = PCMK__XML_NODE_PRIVATE_MAGIC; /* Flags will be reset if necessary when tracking is enabled */ pcmk__set_xml_flags(nodepriv, pcmk__xf_dirty|pcmk__xf_created); node->_private = nodepriv; if (pcmk__tracking_xml_changes(node, FALSE)) { /* XML_ELEMENT_NODE doesn't get picked up here, node->doc is * not hooked up at the point we are called */ pcmk__mark_xml_node_dirty(node); } break; } case XML_TEXT_NODE: case XML_DTD_NODE: case XML_CDATA_SECTION_NODE: break; default: /* Ignore */ crm_trace("Ignoring %p %d", node, node->type); CRM_LOG_ASSERT(node->type == XML_ELEMENT_NODE); break; } } void xml_track_changes(xmlNode * xml, const char *user, xmlNode *acl_source, bool enforce_acls) { xml_accept_changes(xml); crm_trace("Tracking changes%s to %p", enforce_acls?" with ACLs":"", xml); pcmk__set_xml_doc_flag(xml, pcmk__xf_tracking); if(enforce_acls) { if(acl_source == NULL) { acl_source = xml; } pcmk__set_xml_doc_flag(xml, pcmk__xf_acl_enabled); pcmk__unpack_acl(acl_source, xml, user); pcmk__apply_acl(xml); } } bool xml_tracking_changes(xmlNode * xml) { return (xml != NULL) && (xml->doc != NULL) && (xml->doc->_private != NULL) && pcmk_is_set(((xml_doc_private_t *)(xml->doc->_private))->flags, pcmk__xf_tracking); } bool xml_document_dirty(xmlNode *xml) { return (xml != NULL) && (xml->doc != NULL) && (xml->doc->_private != NULL) && pcmk_is_set(((xml_doc_private_t *)(xml->doc->_private))->flags, pcmk__xf_dirty); } /*! * \internal * \brief Return ordinal position of an XML node among its siblings * * \param[in] xml XML node to check * \param[in] ignore_if_set Don't count siblings with this flag set * * \return Ordinal position of \p xml (starting with 0) */ int pcmk__xml_position(const xmlNode *xml, enum xml_private_flags ignore_if_set) { int position = 0; for (const xmlNode *cIter = xml; cIter->prev; cIter = cIter->prev) { xml_node_private_t *nodepriv = ((xmlNode*)cIter->prev)->_private; if (!pcmk_is_set(nodepriv->flags, ignore_if_set)) { position++; } } return position; } /*! * \internal * \brief Remove all attributes marked as deleted from an XML node * * \param[in,out] xml XML node whose deleted attributes to remove * \param[in,out] user_data Ignored * * \return \c true (to continue traversing the tree) * * \note This is compatible with \c pcmk__xml_tree_foreach(). */ static bool accept_attr_deletions(xmlNode *xml, void *user_data) { reset_xml_node_flags(xml, NULL); pcmk__xe_remove_matching_attrs(xml, pcmk__marked_as_deleted, NULL); return true; } /*! * \internal * \brief Find first child XML node matching another given XML node * * \param[in] haystack XML whose children should be checked * \param[in] needle XML to match (comment content or element name and ID) * \param[in] exact If true and needle is a comment, position must match */ xmlNode * pcmk__xml_match(const xmlNode *haystack, const xmlNode *needle, bool exact) { CRM_CHECK(needle != NULL, return NULL); if (needle->type == XML_COMMENT_NODE) { return pcmk__xc_match(haystack, needle, exact); } else { const char *id = pcmk__xe_id(needle); const char *attr = (id == NULL)? NULL : PCMK_XA_ID; return pcmk__xe_first_child(haystack, (const char *) needle->name, attr, id); } } void xml_accept_changes(xmlNode * xml) { xmlNode *top = NULL; xml_doc_private_t *docpriv = NULL; if(xml == NULL) { return; } crm_trace("Accepting changes to %p", xml); docpriv = xml->doc->_private; top = xmlDocGetRootElement(xml->doc); reset_xml_private_data(xml->doc->_private); if (!pcmk_is_set(docpriv->flags, pcmk__xf_dirty)) { docpriv->flags = pcmk__xf_none; return; } docpriv->flags = pcmk__xf_none; pcmk__xml_tree_foreach(top, accept_attr_deletions, NULL); } /*! * \internal * \brief Find first XML child element matching given criteria * * \param[in] parent XML element to search (can be \c NULL) * \param[in] node_name If not \c NULL, only match children of this type * \param[in] attr_n If not \c NULL, only match children with an attribute * of this name. * \param[in] attr_v If \p attr_n and this are not NULL, only match children * with an attribute named \p attr_n and this value * * \return Matching XML child element, or \c NULL if none found */ xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v) { xmlNode *child = NULL; const char *parent_name = ""; CRM_CHECK((attr_v == NULL) || (attr_n != NULL), return NULL); if (parent != NULL) { child = parent->children; while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) { child = child->next; } parent_name = (const char *) parent->name; } for (; child != NULL; child = pcmk__xe_next(child)) { const char *value = NULL; if ((node_name != NULL) && !pcmk__xe_is(child, node_name)) { // Node name mismatch continue; } if (attr_n == NULL) { // No attribute match needed return child; } value = crm_element_value(child, attr_n); if ((attr_v == NULL) && (value != NULL)) { // attr_v == NULL: Attribute attr_n must be set (to any value) return child; } if ((attr_v != NULL) && (pcmk__str_eq(value, attr_v, pcmk__str_none))) { // attr_v != NULL: Attribute attr_n must be set to value attr_v return child; } } if (node_name == NULL) { node_name = "(any)"; // For logging } if (attr_n != NULL) { crm_trace("XML child node <%s %s=%s> not found in %s", node_name, attr_n, attr_v, parent_name); } else { crm_trace("XML child node <%s> not found in %s", node_name, parent_name); } return NULL; } /*! * \internal * \brief Set an XML attribute, expanding \c ++ and \c += where appropriate * * If \p target already has an attribute named \p name set to an integer value * and \p value is an addition assignment expression on \p name, then expand * \p value to an integer and set attribute \p name to the expanded value in * \p target. * * Otherwise, set attribute \p name on \p target using the literal \p value. * * The original attribute value in \p target and the number in an assignment * expression in \p value are parsed and added as scores (that is, their values * are capped at \c INFINITY and \c -INFINITY). For more details, refer to * \c char2score(). * * For example, suppose \p target has an attribute named \c "X" with value * \c "5", and that \p name is \c "X". * * If \p value is \c "X++", the new value of \c "X" in \p target is \c "6". * * If \p value is \c "X+=3", the new value of \c "X" in \p target is \c "8". * * If \p value is \c "val", the new value of \c "X" in \p target is \c "val". * * If \p value is \c "Y++", the new value of \c "X" in \p target is \c "Y++". * * \param[in,out] target XML node whose attribute to set * \param[in] name Name of the attribute to set * \param[in] value New value of attribute to set * * \return Standard Pacemaker return code (specifically, \c EINVAL on invalid * argument, or \c pcmk_rc_ok otherwise) */ int pcmk__xe_set_score(xmlNode *target, const char *name, const char *value) { const char *old_value = NULL; CRM_CHECK((target != NULL) && (name != NULL), return EINVAL); if (value == NULL) { return pcmk_rc_ok; } old_value = crm_element_value(target, name); // If no previous value, skip to default case and set the value unexpanded. if (old_value != NULL) { const char *n = name; const char *v = value; // Stop at first character that differs between name and value for (; (*n == *v) && (*n != '\0'); n++, v++); // If value begins with name followed by a "++" or "+=" if ((*n == '\0') && (*v++ == '+') && ((*v == '+') || (*v == '='))) { // If we're expanding ourselves, no previous value was set; use 0 int old_value_i = (old_value != value)? char2score(old_value) : 0; /* value="X++": new value of X is old_value + 1 * value="X+=Y": new value of X is old_value + Y (for some number Y) */ int add = (*v == '+')? 1 : char2score(++v); crm_xml_add_int(target, name, pcmk__add_scores(old_value_i, add)); return pcmk_rc_ok; } } // Default case: set the attribute unexpanded (with value treated literally) if (old_value != value) { crm_xml_add(target, name, value); } return pcmk_rc_ok; } /*! * \internal * \brief Copy XML attributes from a source element to a target element * * This is similar to \c xmlCopyPropList() except that attributes are marked * as dirty for change tracking purposes. * * \param[in,out] target XML element to receive copied attributes from \p src * \param[in] src XML element whose attributes to copy to \p target * \param[in] flags Group of enum pcmk__xa_flags * * \return Standard Pacemaker return code */ int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags) { CRM_CHECK((src != NULL) && (target != NULL), return EINVAL); for (xmlAttr *attr = pcmk__xe_first_attr(src); attr != NULL; attr = attr->next) { const char *name = (const char *) attr->name; const char *value = pcmk__xml_attr_value(attr); if (pcmk_is_set(flags, pcmk__xaf_no_overwrite) && (crm_element_value(target, name) != NULL)) { continue; } if (pcmk_is_set(flags, pcmk__xaf_score_update)) { pcmk__xe_set_score(target, name, value); } else { crm_xml_add(target, name, value); } } return pcmk_rc_ok; } /*! * \internal * \brief Remove a named attribute from an XML element * * \param[in,out] element XML element to remove an attribute from * \param[in] name Name of attribute to remove */ void pcmk__xe_remove_attr(xmlNode *element, const char *name) { if (name != NULL) { pcmk__xa_remove(xmlHasProp(element, (pcmkXmlStr) name), false); } } /*! * \internal * \brief Remove a named attribute from an XML element * * This is a wrapper for \c pcmk__xe_remove_attr() for use with * \c pcmk__xml_tree_foreach(). * * \param[in,out] xml XML element to remove an attribute from * \param[in] user_data Name of attribute to remove * * \return \c true (to continue traversing the tree) * * \note This is compatible with \c pcmk__xml_tree_foreach(). */ bool pcmk__xe_remove_attr_cb(xmlNode *xml, void *user_data) { const char *name = user_data; pcmk__xe_remove_attr(xml, name); return true; } /*! * \internal * \brief Remove an XML element's attributes that match some criteria * * \param[in,out] element XML element to modify * \param[in] match If not NULL, only remove attributes for which * this function returns true * \param[in,out] user_data Data to pass to \p match */ void pcmk__xe_remove_matching_attrs(xmlNode *element, bool (*match)(xmlAttrPtr, void *), void *user_data) { xmlAttrPtr next = NULL; for (xmlAttrPtr a = pcmk__xe_first_attr(element); a != NULL; a = next) { next = a->next; // Grab now because attribute might get removed if ((match == NULL) || match(a, user_data)) { if (pcmk__xa_remove(a, false) != pcmk_rc_ok) { return; } } } } /*! * \internal * \brief Create a new XML element under a given parent * * \param[in,out] parent XML element that will be the new element's parent * (\c NULL to create a new XML document with the new * node as root) * \param[in] name Name of new element * * \return Newly created XML element (guaranteed not to be \c NULL) */ xmlNode * pcmk__xe_create(xmlNode *parent, const char *name) { xmlNode *node = NULL; CRM_ASSERT(!pcmk__str_empty(name)); if (parent == NULL) { xmlDoc *doc = pcmk__xml_new_doc(); node = xmlNewDocRawNode(doc, NULL, (pcmkXmlStr) name, NULL); pcmk__mem_assert(node); xmlDocSetRootElement(doc, node); } else { node = xmlNewChild(parent, NULL, (pcmkXmlStr) name, NULL); pcmk__mem_assert(node); } pcmk__xml_mark_created(node); return node; } /*! * \internal * \brief Create a new XML document * * \return Newly allocated XML document (guaranteed not to be \c NULL) * * \note The caller is responsible for freeing the return value using * \c pcmk__xml_free_doc(). */ xmlDoc * pcmk__xml_new_doc(void) { /* @TODO Allocate document private data here when we drop * new_private_data()/free_private_data() */ xmlDoc *doc = xmlNewDoc(XML_VERSION); pcmk__mem_assert(doc); return doc; } /*! * \internal * \brief Free a new XML document * * \param[in,out] doc XML document to free */ void pcmk__xml_free_doc(xmlDoc *doc) { /* @TODO Free document private data here when we drop * new_private_data()/free_private_data() */ if (doc != NULL) { xmlFreeDoc(doc); } } /*! * \internal * \brief Set a formatted string as an XML node's content * * \param[in,out] node Node whose content to set * \param[in] format printf(3)-style format string * \param[in] ... Arguments for \p format * * \note This function escapes special characters. \c xmlNodeSetContent() does * not. */ G_GNUC_PRINTF(2, 3) void pcmk__xe_set_content(xmlNode *node, const char *format, ...) { if (node != NULL) { const char *content = NULL; char *buf = NULL; if (strchr(format, '%') == NULL) { // Nothing to format content = format; } else { va_list ap; va_start(ap, format); if (pcmk__str_eq(format, "%s", pcmk__str_none)) { // No need to make a copy content = va_arg(ap, const char *); } else { CRM_ASSERT(vasprintf(&buf, format, ap) >= 0); content = buf; } va_end(ap); } xmlNodeSetContent(node, (pcmkXmlStr) content); free(buf); } } /*! * Free an XML element and all of its children, removing it from its parent * * \param[in,out] xml XML element to free */ void pcmk_free_xml_subtree(xmlNode *xml) { /* @TODO Free tree private data here when we drop * new_private_data()/free_private_data() */ xmlUnlinkNode(xml); // Detaches from parent and siblings xmlFreeNode(xml); // Frees } static void free_xml_with_position(xmlNode *child, int position) { xmlDoc *doc = NULL; xml_node_private_t *nodepriv = NULL; if (child == NULL) { return; } doc = child->doc; nodepriv = child->_private; if ((doc != NULL) && (xmlDocGetRootElement(doc) == child)) { // Free everything pcmk__xml_free_doc(doc); return; } if (!pcmk__check_acl(child, NULL, pcmk__xf_acl_write)) { GString *xpath = NULL; pcmk__if_tracing({}, return); xpath = pcmk__element_xpath(child); qb_log_from_external_source(__func__, __FILE__, "Cannot remove %s %x", LOG_TRACE, __LINE__, 0, xpath->str, nodepriv->flags); g_string_free(xpath, TRUE); return; } if ((doc != NULL) && pcmk__tracking_xml_changes(child, false) && !pcmk_is_set(nodepriv->flags, pcmk__xf_created)) { xml_doc_private_t *docpriv = doc->_private; GString *xpath = pcmk__element_xpath(child); if (xpath != NULL) { pcmk__deleted_xml_t *deleted_obj = NULL; crm_trace("Deleting %s %p from %p", xpath->str, child, doc); deleted_obj = pcmk__assert_alloc(1, sizeof(pcmk__deleted_xml_t)); deleted_obj->path = g_string_free(xpath, FALSE); deleted_obj->position = -1; // Record the position only for XML comments for now if (child->type == XML_COMMENT_NODE) { if (position >= 0) { deleted_obj->position = position; } else { deleted_obj->position = pcmk__xml_position(child, pcmk__xf_skip); } } docpriv->deleted_objs = g_list_append(docpriv->deleted_objs, deleted_obj); pcmk__set_xml_doc_flag(child, pcmk__xf_dirty); } } pcmk_free_xml_subtree(child); } void free_xml(xmlNode * child) { free_xml_with_position(child, -1); } /*! * \internal * \brief Make a deep copy of an XML node under a given parent * * \param[in,out] parent XML element that will be the copy's parent (\c NULL * to create a new XML document with the copy as root) * \param[in] src XML node to copy * * \return Deep copy of \p src, or \c NULL if \p src is \c NULL */ xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src) { + /* @TODO Allocate the copy tree's private data here when we drop + * new_private_data()/free_private_data() + */ xmlNode *copy = NULL; if (src == NULL) { return NULL; } if (parent == NULL) { xmlDoc *doc = NULL; // The copy will be the root element of a new document CRM_ASSERT(src->type == XML_ELEMENT_NODE); doc = pcmk__xml_new_doc(); copy = xmlDocCopyNode(src, doc, 1); pcmk__mem_assert(copy); xmlDocSetRootElement(doc, copy); } else { copy = xmlDocCopyNode(src, parent->doc, 1); pcmk__mem_assert(copy); xmlAddChild(parent, copy); } pcmk__xml_mark_created(copy); return copy; } /*! * \internal * \brief Remove XML text nodes from specified XML and all its children * * \param[in,out] xml XML to strip text from */ void pcmk__strip_xml_text(xmlNode *xml) { xmlNode *iter = xml->children; while (iter) { xmlNode *next = iter->next; switch (iter->type) { case XML_TEXT_NODE: /* Remove it */ pcmk_free_xml_subtree(iter); break; case XML_ELEMENT_NODE: /* Search it */ pcmk__strip_xml_text(iter); break; default: /* Leave it */ break; } iter = next; } } /*! * \internal * \brief Add a "last written" attribute to an XML element, set to current time * * \param[in,out] xe XML element to add attribute to * * \return Value that was set, or NULL on error */ const char * pcmk__xe_add_last_written(xmlNode *xe) { char *now_s = pcmk__epoch2str(NULL, 0); const char *result = NULL; result = crm_xml_add(xe, PCMK_XA_CIB_LAST_WRITTEN, pcmk__s(now_s, "Could not determine current time")); free(now_s); return result; } /*! * \brief Sanitize a string so it is usable as an XML ID * * \param[in,out] id String to sanitize */ void crm_xml_sanitize_id(char *id) { char *c; for (c = id; *c; ++c) { /* @TODO Sanitize more comprehensively */ switch (*c) { case ':': case '#': *c = '.'; } } } /*! * \brief Set the ID of an XML element using a format * * \param[in,out] xml XML element * \param[in] fmt printf-style format * \param[in] ... any arguments required by format */ void crm_xml_set_id(xmlNode *xml, const char *format, ...) { va_list ap; int len = 0; char *id = NULL; /* equivalent to crm_strdup_printf() */ va_start(ap, format); len = vasprintf(&id, format, ap); va_end(ap); CRM_ASSERT(len > 0); crm_xml_sanitize_id(id); crm_xml_add(xml, PCMK_XA_ID, id); free(id); } /*! * \internal * \brief Check whether a string has XML special characters that must be escaped * * See \c pcmk__xml_escape() and \c pcmk__xml_escape_type for more details. * * \param[in] text String to check * \param[in] type Type of escaping * * \return \c true if \p text has special characters that need to be escaped, or * \c false otherwise */ bool pcmk__xml_needs_escape(const char *text, enum pcmk__xml_escape_type type) { if (text == NULL) { return false; } while (*text != '\0') { switch (type) { case pcmk__xml_escape_text: switch (*text) { case '<': case '>': case '&': return true; case '\n': case '\t': break; default: if (g_ascii_iscntrl(*text)) { return true; } break; } break; case pcmk__xml_escape_attr: switch (*text) { case '<': case '>': case '&': case '"': return true; default: if (g_ascii_iscntrl(*text)) { return true; } break; } break; case pcmk__xml_escape_attr_pretty: switch (*text) { case '\n': case '\r': case '\t': case '"': return true; default: break; } break; default: // Invalid enum value CRM_ASSERT(false); break; } text = g_utf8_next_char(text); } return false; } /*! * \internal * \brief Replace special characters with their XML escape sequences * * \param[in] text Text to escape * \param[in] type Type of escaping * * \return Newly allocated string equivalent to \p text but with special * characters replaced with XML escape sequences (or \c NULL if \p text * is \c NULL). If \p text is not \c NULL, the return value is * guaranteed not to be \c NULL. * * \note There are libxml functions that purport to do this: * \c xmlEncodeEntitiesReentrant() and \c xmlEncodeSpecialChars(). * However, their escaping is incomplete. See: * https://discourse.gnome.org/t/intended-use-of-xmlencodeentitiesreentrant-vs-xmlencodespecialchars/19252 * \note The caller is responsible for freeing the return value using * \c g_free(). */ gchar * pcmk__xml_escape(const char *text, enum pcmk__xml_escape_type type) { GString *copy = NULL; if (text == NULL) { return NULL; } copy = g_string_sized_new(strlen(text)); while (*text != '\0') { // Don't escape any non-ASCII characters if ((*text & 0x80) != 0) { size_t bytes = g_utf8_next_char(text) - text; g_string_append_len(copy, text, bytes); text += bytes; continue; } switch (type) { case pcmk__xml_escape_text: switch (*text) { case '<': g_string_append(copy, PCMK__XML_ENTITY_LT); break; case '>': g_string_append(copy, PCMK__XML_ENTITY_GT); break; case '&': g_string_append(copy, PCMK__XML_ENTITY_AMP); break; case '\n': case '\t': g_string_append_c(copy, *text); break; default: if (g_ascii_iscntrl(*text)) { g_string_append_printf(copy, "&#x%.2X;", *text); } else { g_string_append_c(copy, *text); } break; } break; case pcmk__xml_escape_attr: switch (*text) { case '<': g_string_append(copy, PCMK__XML_ENTITY_LT); break; case '>': g_string_append(copy, PCMK__XML_ENTITY_GT); break; case '&': g_string_append(copy, PCMK__XML_ENTITY_AMP); break; case '"': g_string_append(copy, PCMK__XML_ENTITY_QUOT); break; default: if (g_ascii_iscntrl(*text)) { g_string_append_printf(copy, "&#x%.2X;", *text); } else { g_string_append_c(copy, *text); } break; } break; case pcmk__xml_escape_attr_pretty: switch (*text) { case '"': g_string_append(copy, "\\\""); break; case '\n': g_string_append(copy, "\\n"); break; case '\r': g_string_append(copy, "\\r"); break; case '\t': g_string_append(copy, "\\t"); break; default: g_string_append_c(copy, *text); break; } break; default: // Invalid enum value CRM_ASSERT(false); break; } text = g_utf8_next_char(text); } return g_string_free(copy, FALSE); } /*! * \internal * \brief Set a flag on all attributes of an XML element * * \param[in,out] xml XML node to set flags on * \param[in] flag XML private flag to set */ static void set_attrs_flag(xmlNode *xml, enum xml_private_flags flag) { for (xmlAttr *attr = pcmk__xe_first_attr(xml); attr; attr = attr->next) { pcmk__set_xml_flags((xml_node_private_t *) (attr->_private), flag); } } /*! * \internal * \brief Add an XML attribute to a node, marked as deleted * * When calculating XML changes, we need to know when an attribute has been * deleted. Add the attribute back to the new XML, so that we can check the * removal against ACLs, and mark it as deleted for later removal after * differences have been calculated. * * \param[in,out] new_xml XML to modify * \param[in] element Name of XML element that changed (for logging) * \param[in] attr_name Name of attribute that was deleted * \param[in] old_value Value of attribute that was deleted */ static void mark_attr_deleted(xmlNode *new_xml, const char *element, const char *attr_name, const char *old_value) { xml_doc_private_t *docpriv = new_xml->doc->_private; xmlAttr *attr = NULL; xml_node_private_t *nodepriv; /* Restore the old value (without setting dirty flag recursively upwards or * checking ACLs) */ pcmk__clear_xml_flags(docpriv, pcmk__xf_tracking); crm_xml_add(new_xml, attr_name, old_value); pcmk__set_xml_flags(docpriv, pcmk__xf_tracking); // Reset flags (so the attribute doesn't appear as newly created) attr = xmlHasProp(new_xml, (pcmkXmlStr) attr_name); nodepriv = attr->_private; nodepriv->flags = 0; // Check ACLs and mark restored value for later removal pcmk__xa_remove(attr, false); crm_trace("XML attribute %s=%s was removed from %s", attr_name, old_value, element); } /* * \internal * \brief Check ACLs for a changed XML attribute */ static void mark_attr_changed(xmlNode *new_xml, const char *element, const char *attr_name, const char *old_value) { xml_doc_private_t *docpriv = new_xml->doc->_private; char *vcopy = crm_element_value_copy(new_xml, attr_name); crm_trace("XML attribute %s was changed from '%s' to '%s' in %s", attr_name, old_value, vcopy, element); // Restore the original value (without checking ACLs) pcmk__clear_xml_flags(docpriv, pcmk__xf_tracking); crm_xml_add(new_xml, attr_name, old_value); pcmk__set_xml_flags(docpriv, pcmk__xf_tracking); // Change it back to the new value, to check ACLs crm_xml_add(new_xml, attr_name, vcopy); free(vcopy); } /*! * \internal * \brief Mark an XML attribute as having changed position * * \param[in,out] new_xml XML to modify * \param[in] element Name of XML element that changed (for logging) * \param[in,out] old_attr Attribute that moved, in original XML * \param[in,out] new_attr Attribute that moved, in \p new_xml * \param[in] p_old Ordinal position of \p old_attr in original XML * \param[in] p_new Ordinal position of \p new_attr in \p new_xml */ static void mark_attr_moved(xmlNode *new_xml, const char *element, xmlAttr *old_attr, xmlAttr *new_attr, int p_old, int p_new) { xml_node_private_t *nodepriv = new_attr->_private; crm_trace("XML attribute %s moved from position %d to %d in %s", old_attr->name, p_old, p_new, element); // Mark document, element, and all element's parents as changed pcmk__mark_xml_node_dirty(new_xml); // Mark attribute as changed pcmk__set_xml_flags(nodepriv, pcmk__xf_dirty|pcmk__xf_moved); nodepriv = (p_old > p_new)? old_attr->_private : new_attr->_private; pcmk__set_xml_flags(nodepriv, pcmk__xf_skip); } /*! * \internal * \brief Calculate differences in all previously existing XML attributes * * \param[in,out] old_xml Original XML to compare * \param[in,out] new_xml New XML to compare */ static void xml_diff_old_attrs(xmlNode *old_xml, xmlNode *new_xml) { xmlAttr *attr_iter = pcmk__xe_first_attr(old_xml); while (attr_iter != NULL) { const char *name = (const char *) attr_iter->name; xmlAttr *old_attr = attr_iter; xmlAttr *new_attr = xmlHasProp(new_xml, attr_iter->name); const char *old_value = pcmk__xml_attr_value(attr_iter); attr_iter = attr_iter->next; if (new_attr == NULL) { mark_attr_deleted(new_xml, (const char *) old_xml->name, name, old_value); } else { xml_node_private_t *nodepriv = new_attr->_private; int new_pos = pcmk__xml_position((xmlNode*) new_attr, pcmk__xf_skip); int old_pos = pcmk__xml_position((xmlNode*) old_attr, pcmk__xf_skip); const char *new_value = crm_element_value(new_xml, name); // This attribute isn't new pcmk__clear_xml_flags(nodepriv, pcmk__xf_created); if (strcmp(new_value, old_value) != 0) { mark_attr_changed(new_xml, (const char *) old_xml->name, name, old_value); } else if ((old_pos != new_pos) && !pcmk__tracking_xml_changes(new_xml, TRUE)) { mark_attr_moved(new_xml, (const char *) old_xml->name, old_attr, new_attr, old_pos, new_pos); } } } } /*! * \internal * \brief Check all attributes in new XML for creation * * For each of a given XML element's attributes marked as newly created, accept * (and mark as dirty) or reject the creation according to ACLs. * * \param[in,out] new_xml XML to check */ static void mark_created_attrs(xmlNode *new_xml) { xmlAttr *attr_iter = pcmk__xe_first_attr(new_xml); while (attr_iter != NULL) { xmlAttr *new_attr = attr_iter; xml_node_private_t *nodepriv = attr_iter->_private; attr_iter = attr_iter->next; if (pcmk_is_set(nodepriv->flags, pcmk__xf_created)) { const char *attr_name = (const char *) new_attr->name; crm_trace("Created new attribute %s=%s in %s", attr_name, pcmk__xml_attr_value(new_attr), new_xml->name); /* Check ACLs (we can't use the remove-then-create trick because it * would modify the attribute position). */ if (pcmk__check_acl(new_xml, attr_name, pcmk__xf_acl_write)) { pcmk__mark_xml_attr_dirty(new_attr); } else { // Creation was not allowed, so remove the attribute pcmk__xa_remove(new_attr, true); } } } } /*! * \internal * \brief Calculate differences in attributes between two XML nodes * * \param[in,out] old_xml Original XML to compare * \param[in,out] new_xml New XML to compare */ static void xml_diff_attrs(xmlNode *old_xml, xmlNode *new_xml) { set_attrs_flag(new_xml, pcmk__xf_created); // cleared later if not really new xml_diff_old_attrs(old_xml, new_xml); mark_created_attrs(new_xml); } /*! * \internal * \brief Add an XML child element to a node, marked as deleted * * When calculating XML changes, we need to know when a child element has been * deleted. Add the child back to the new XML, so that we can check the removal * against ACLs, and mark it as deleted for later removal after differences have * been calculated. * * \param[in,out] old_child Child element from original XML * \param[in,out] new_parent New XML to add marked copy to */ static void mark_child_deleted(xmlNode *old_child, xmlNode *new_parent) { // Re-create the child element so we can check ACLs xmlNode *candidate = pcmk__xml_copy(new_parent, old_child); // Clear flags on new child and its children pcmk__xml_tree_foreach(candidate, reset_xml_node_flags, NULL); // Check whether ACLs allow the deletion pcmk__apply_acl(xmlDocGetRootElement(candidate->doc)); // Remove the child again (which will track it in document's deleted_objs) free_xml_with_position(candidate, pcmk__xml_position(old_child, pcmk__xf_skip)); if (pcmk__xml_match(new_parent, old_child, true) == NULL) { pcmk__set_xml_flags((xml_node_private_t *) (old_child->_private), pcmk__xf_skip); } } static void mark_child_moved(xmlNode *old_child, xmlNode *new_parent, xmlNode *new_child, int p_old, int p_new) { xml_node_private_t *nodepriv = new_child->_private; crm_trace("Child element %s with " PCMK_XA_ID "='%s' moved from position %d to %d under %s", new_child->name, pcmk__s(pcmk__xe_id(new_child), ""), p_old, p_new, new_parent->name); pcmk__mark_xml_node_dirty(new_parent); pcmk__set_xml_flags(nodepriv, pcmk__xf_moved); if (p_old > p_new) { nodepriv = old_child->_private; } else { nodepriv = new_child->_private; } pcmk__set_xml_flags(nodepriv, pcmk__xf_skip); } // Given original and new XML, mark new XML portions that have changed static void mark_xml_changes(xmlNode *old_xml, xmlNode *new_xml, bool check_top) { xmlNode *old_child = NULL; xmlNode *new_child = NULL; xml_node_private_t *nodepriv = NULL; CRM_CHECK(new_xml != NULL, return); if (old_xml == NULL) { pcmk__xml_mark_created(new_xml); pcmk__apply_creation_acl(new_xml, check_top); return; } nodepriv = new_xml->_private; CRM_CHECK(nodepriv != NULL, return); if(nodepriv->flags & pcmk__xf_processed) { /* Avoid re-comparing nodes */ return; } pcmk__set_xml_flags(nodepriv, pcmk__xf_processed); xml_diff_attrs(old_xml, new_xml); // Check for differences in the original children for (old_child = pcmk__xml_first_child(old_xml); old_child != NULL; old_child = pcmk__xml_next(old_child)) { new_child = pcmk__xml_match(new_xml, old_child, true); if (new_child != NULL) { mark_xml_changes(old_child, new_child, true); } else { mark_child_deleted(old_child, new_xml); } } // Check for moved or created children new_child = pcmk__xml_first_child(new_xml); while (new_child != NULL) { xmlNode *next = pcmk__xml_next(new_child); old_child = pcmk__xml_match(old_xml, new_child, true); if (old_child == NULL) { // This is a newly created child nodepriv = new_child->_private; pcmk__set_xml_flags(nodepriv, pcmk__xf_skip); // May free new_child mark_xml_changes(old_child, new_child, true); } else { /* Check for movement, we already checked for differences */ int p_new = pcmk__xml_position(new_child, pcmk__xf_skip); int p_old = pcmk__xml_position(old_child, pcmk__xf_skip); if(p_old != p_new) { mark_child_moved(old_child, new_xml, new_child, p_old, p_new); } } new_child = next; } } void xml_calculate_significant_changes(xmlNode *old_xml, xmlNode *new_xml) { pcmk__set_xml_doc_flag(new_xml, pcmk__xf_lazy); xml_calculate_changes(old_xml, new_xml); } // Called functions may set the \p pcmk__xf_skip flag on parts of \p old_xml void xml_calculate_changes(xmlNode *old_xml, xmlNode *new_xml) { CRM_CHECK((old_xml != NULL) && (new_xml != NULL) && pcmk__xe_is(old_xml, (const char *) new_xml->name) && pcmk__str_eq(pcmk__xe_id(old_xml), pcmk__xe_id(new_xml), pcmk__str_none), return); if(xml_tracking_changes(new_xml) == FALSE) { xml_track_changes(new_xml, NULL, NULL, FALSE); } mark_xml_changes(old_xml, new_xml, FALSE); } /*! * \internal * \brief Merge one XML tree into another * * Here, "merge" means: * 1. Copy attribute values from \p update to the target, overwriting in case of * conflict. * 2. Descend through \p update and the target in parallel. At each level, for * each child of \p update, look for a matching child of the target. * a. For each child, if a match is found, go to step 1, recursively merging * the child of \p update into the child of the target. * b. Otherwise, copy the child of \p update as a child of the target. * * A match is defined as the first child of the same type within the target, * with: * * the \c PCMK_XA_ID attribute matching, if set in \p update; otherwise, * * the \c PCMK_XA_ID_REF attribute matching, if set in \p update * * This function does not delete any elements or attributes from the target. It * may add elements or overwrite attributes, as described above. * * \param[in,out] parent If \p target is NULL and this is not, add or update * child of this XML node that matches \p update * \param[in,out] target If not NULL, update this XML * \param[in] update Make the desired XML match this (must not be \c NULL) * \param[in] flags Group of enum pcmk__xa_flags * \param[in] as_diff If \c true, preserve order of attributes (deprecated * since 2.0.5) * * \note At least one of \p parent and \p target must be non-NULL. * \note This function is recursive. For the top-level call, \p parent is * \c NULL and \p target is not \c NULL. For recursive calls, \p target is * \c NULL and \p parent is not \c NULL. */ void pcmk__xml_update(xmlNode *parent, xmlNode *target, xmlNode *update, uint32_t flags, bool as_diff) { /* @COMPAT Refactor further and staticize after v1 patchset deprecation. * * @COMPAT Drop as_diff argument when apply_xml_diff() is dropped. */ const char *update_name = NULL; const char *update_id_attr = NULL; const char *update_id_val = NULL; char *trace_s = NULL; crm_log_xml_trace(update, "update"); crm_log_xml_trace(target, "target"); CRM_CHECK(update != NULL, goto done); if (update->type == XML_COMMENT_NODE) { pcmk__xc_update(parent, target, update); goto done; } update_name = (const char *) update->name; CRM_CHECK(update_name != NULL, goto done); CRM_CHECK((target != NULL) || (parent != NULL), goto done); update_id_val = pcmk__xe_id(update); if (update_id_val != NULL) { update_id_attr = PCMK_XA_ID; } else { update_id_val = crm_element_value(update, PCMK_XA_ID_REF); if (update_id_val != NULL) { update_id_attr = PCMK_XA_ID_REF; } } pcmk__if_tracing( { if (update_id_attr != NULL) { trace_s = crm_strdup_printf("<%s %s=%s/>", update_name, update_id_attr, update_id_val); } else { trace_s = crm_strdup_printf("<%s/>", update_name); } }, {} ); if (target == NULL) { // Recursive call target = pcmk__xe_first_child(parent, update_name, update_id_attr, update_id_val); } if (target == NULL) { // Recursive call with no existing matching child target = pcmk__xe_create(parent, update_name); crm_trace("Added %s", pcmk__s(trace_s, update_name)); } else { // Either recursive call with match, or top-level call crm_trace("Found node %s to update", pcmk__s(trace_s, update_name)); } CRM_CHECK(pcmk__xe_is(target, (const char *) update->name), return); if (!as_diff) { pcmk__xe_copy_attrs(target, update, flags); } else { // Preserve order of attributes. Don't use pcmk__xe_copy_attrs(). for (xmlAttrPtr a = pcmk__xe_first_attr(update); a != NULL; a = a->next) { const char *p_value = pcmk__xml_attr_value(a); xmlAttr *old_attr = xmlHasProp(target, a->name); /* Remove it first so the ordering of the update is preserved */ if (old_attr != NULL) { pcmk__xa_remove(old_attr, true); } pcmk__xe_set_attr_force(target, (const char *) a->name, p_value); } } for (xmlNode *child = pcmk__xml_first_child(update); child != NULL; child = pcmk__xml_next(child)) { crm_trace("Updating child of %s", pcmk__s(trace_s, update_name)); pcmk__xml_update(target, NULL, child, flags, as_diff); } crm_trace("Finished with %s", pcmk__s(trace_s, update_name)); done: free(trace_s); } /*! * \internal * \brief Delete an XML subtree if it matches a search element * * A match is defined as follows: * * \p xml and \p user_data are both element nodes of the same type. * * If \p user_data has attributes set, \p xml has those attributes set to the * same values. (\p xml may have additional attributes set to arbitrary * values.) * * \param[in,out] xml XML subtree to delete upon match * \param[in] user_data Search element * * \return \c true to continue traversing the tree, or \c false to stop (because * \p xml was deleted) * * \note This is compatible with \c pcmk__xml_tree_foreach(). */ static bool delete_xe_if_matching(xmlNode *xml, void *user_data) { xmlNode *search = user_data; if (!pcmk__xe_is(search, (const char *) xml->name)) { // No match: either not both elements, or different element types return true; } for (const xmlAttr *attr = pcmk__xe_first_attr(search); attr != NULL; attr = attr->next) { const char *search_val = pcmk__xml_attr_value(attr); const char *xml_val = crm_element_value(xml, (const char *) attr->name); if (!pcmk__str_eq(search_val, xml_val, pcmk__str_casei)) { // No match: an attr in xml doesn't match the attr in search return true; } } crm_log_xml_trace(xml, "delete-match"); crm_log_xml_trace(search, "delete-search"); free_xml(xml); // Found a match and deleted it; stop traversing tree return false; } /*! * \internal * \brief Search an XML tree depth-first and delete the first matching element * * This function does not attempt to match the tree root (\p xml). * * A match with a node \c node is defined as follows: * * \c node and \p search are both element nodes of the same type. * * If \p search has attributes set, \c node has those attributes set to the * same values. (\c node may have additional attributes set to arbitrary * values.) * * \param[in,out] xml XML subtree to search * \param[in] search Element to match against * * \return Standard Pacemaker return code (specifically, \c pcmk_rc_ok on * successful deletion and an error code otherwise) */ int pcmk__xe_delete_match(xmlNode *xml, xmlNode *search) { // See @COMPAT comment in pcmk__xe_replace_match() CRM_CHECK((xml != NULL) && (search != NULL), return EINVAL); for (xml = pcmk__xe_first_child(xml, NULL, NULL, NULL); xml != NULL; xml = pcmk__xe_next(xml)) { if (!pcmk__xml_tree_foreach(xml, delete_xe_if_matching, search)) { // Found and deleted an element return pcmk_rc_ok; } } // No match found in this subtree return ENXIO; } /*! * \internal * \brief Replace one XML node with a copy of another XML node * * This function handles change tracking and applies ACLs. * * \param[in,out] old XML node to replace * \param[in] new XML node to copy as replacement for \p old * * \note This frees \p old. */ static void replace_node(xmlNode *old, xmlNode *new) { - new = xmlCopyNode(new, 1); - pcmk__mem_assert(new); + // Pass old for its doc; it won't remain the parent of new + new = pcmk__xml_copy(old, new); + old = xmlReplaceNode(old, new); + + // old == NULL means memory allocation error + CRM_ASSERT(old != NULL); // May be unnecessary but avoids slight changes to some test outputs pcmk__xml_tree_foreach(new, reset_xml_node_flags, NULL); - old = xmlReplaceNode(old, new); - if (xml_tracking_changes(new)) { // Replaced sections may have included relevant ACLs pcmk__apply_acl(new); } xml_calculate_changes(old, new); pcmk_free_xml_subtree(old); } /*! * \internal * \brief Replace one XML subtree with a copy of another if the two match * * A match is defined as follows: * * \p xml and \p user_data are both element nodes of the same type. * * If \p user_data has the \c PCMK_XA_ID attribute set, then \p xml has * \c PCMK_XA_ID set to the same value. * * \param[in,out] xml XML subtree to replace with \p user_data upon match * \param[in] user_data XML to replace \p xml with a copy of upon match * * \return \c true to continue traversing the tree, or \c false to stop (because * \p xml was replaced by \p user_data) * * \note This is compatible with \c pcmk__xml_tree_foreach(). */ static bool replace_xe_if_matching(xmlNode *xml, void *user_data) { xmlNode *replace = user_data; const char *xml_id = NULL; const char *replace_id = NULL; xml_id = pcmk__xe_id(xml); replace_id = pcmk__xe_id(replace); if (!pcmk__xe_is(replace, (const char *) xml->name)) { // No match: either not both elements, or different element types return true; } if ((replace_id != NULL) && !pcmk__str_eq(replace_id, xml_id, pcmk__str_none)) { // No match: ID was provided in replace and doesn't match xml's ID return true; } crm_log_xml_trace(xml, "replace-match"); crm_log_xml_trace(replace, "replace-with"); replace_node(xml, replace); // Found a match and replaced it; stop traversing tree return false; } /*! * \internal * \brief Search an XML tree depth-first and replace the first matching element * * This function does not attempt to match the tree root (\p xml). * * A match with a node \c node is defined as follows: * * \c node and \p replace are both element nodes of the same type. * * If \p replace has the \c PCMK_XA_ID attribute set, then \c node has * \c PCMK_XA_ID set to the same value. * * \param[in,out] xml XML tree to search * \param[in] replace XML to replace a matching element with a copy of * * \return Standard Pacemaker return code (specifically, \c pcmk_rc_ok on * successful replacement and an error code otherwise) */ int pcmk__xe_replace_match(xmlNode *xml, xmlNode *replace) { /* @COMPAT Some of this behavior (like not matching the tree root, which is * allowed by pcmk__xe_update_match()) is questionable for general use but * required for backward compatibility by cib_process_replace() and * cib_process_delete(). Behavior can change at a major version release if * desired. */ CRM_CHECK((xml != NULL) && (replace != NULL), return EINVAL); for (xml = pcmk__xe_first_child(xml, NULL, NULL, NULL); xml != NULL; xml = pcmk__xe_next(xml)) { if (!pcmk__xml_tree_foreach(xml, replace_xe_if_matching, replace)) { // Found and replaced an element return pcmk_rc_ok; } } // No match found in this subtree return ENXIO; } //! User data for \c update_xe_if_matching() struct update_data { xmlNode *update; //!< Update source uint32_t flags; //!< Group of enum pcmk__xa_flags }; /*! * \internal * \brief Update one XML subtree with another if the two match * * "Update" means to merge a source subtree into a target subtree (see * \c pcmk__xml_update()). * * A match is defined as follows: * * \p xml and \p user_data->update are both element nodes of the same type. * * \p xml and \p user_data->update have the same \c PCMK_XA_ID attribute * value, or \c PCMK_XA_ID is unset in both * * \param[in,out] xml XML subtree to update with \p user_data->update * upon match * \param[in] user_data struct update_data object * * \return \c true to continue traversing the tree, or \c false to stop (because * \p xml was updated by \p user_data->update) * * \note This is compatible with \c pcmk__xml_tree_foreach(). */ static bool update_xe_if_matching(xmlNode *xml, void *user_data) { struct update_data *data = user_data; xmlNode *update = data->update; if (!pcmk__xe_is(update, (const char *) xml->name)) { // No match: either not both elements, or different element types return true; } if (!pcmk__str_eq(pcmk__xe_id(xml), pcmk__xe_id(update), pcmk__str_none)) { // No match: ID mismatch return true; } crm_log_xml_trace(xml, "update-match"); crm_log_xml_trace(update, "update-with"); pcmk__xml_update(NULL, xml, update, data->flags, false); // Found a match and replaced it; stop traversing tree return false; } /*! * \internal * \brief Search an XML tree depth-first and update the first matching element * * "Update" means to merge a source subtree into a target subtree (see * \c pcmk__xml_update()). * * A match with a node \c node is defined as follows: * * \c node and \p update are both element nodes of the same type. * * \c node and \p update have the same \c PCMK_XA_ID attribute value, or * \c PCMK_XA_ID is unset in both * * \param[in,out] xml XML tree to search * \param[in] update XML to update a matching element with * \param[in] flags Group of enum pcmk__xa_flags * * \return Standard Pacemaker return code (specifically, \c pcmk_rc_ok on * successful update and an error code otherwise) */ int pcmk__xe_update_match(xmlNode *xml, xmlNode *update, uint32_t flags) { /* @COMPAT In pcmk__xe_delete_match() and pcmk__xe_replace_match(), we * compare IDs only if the equivalent of the update argument has an ID. * Here, we're stricter: we consider it a mismatch if only one element has * an ID attribute, or if both elements have IDs but they don't match. * * Perhaps we should align the behavior at a major version release. */ struct update_data data = { .update = update, .flags = flags, }; CRM_CHECK((xml != NULL) && (update != NULL), return EINVAL); if (!pcmk__xml_tree_foreach(xml, update_xe_if_matching, &data)) { // Found and updated an element return pcmk_rc_ok; } // No match found in this subtree return ENXIO; } xmlNode * sorted_xml(xmlNode *input, xmlNode *parent, gboolean recursive) { xmlNode *child = NULL; GSList *nvpairs = NULL; xmlNode *result = NULL; CRM_CHECK(input != NULL, return NULL); result = pcmk__xe_create(parent, (const char *) input->name); nvpairs = pcmk_xml_attrs2nvpairs(input); nvpairs = pcmk_sort_nvpairs(nvpairs); pcmk_nvpairs2xml_attrs(nvpairs, result); pcmk_free_nvpairs(nvpairs); for (child = pcmk__xe_first_child(input, NULL, NULL, NULL); child != NULL; child = pcmk__xe_next(child)) { if (recursive) { sorted_xml(child, result, recursive); } else { pcmk__xml_copy(result, child); } } return result; } /*! * \internal * \brief Get next sibling XML element with the same name as a given element * * \param[in] node XML element to start from * * \return Next sibling XML element with same name */ xmlNode * pcmk__xe_next_same(const xmlNode *node) { for (xmlNode *match = pcmk__xe_next(node); match != NULL; match = pcmk__xe_next(match)) { if (pcmk__xe_is(match, (const char *) node->name)) { return match; } } return NULL; } void crm_xml_init(void) { static bool init = true; if(init) { init = false; /* The default allocator XML_BUFFER_ALLOC_EXACT does far too many * pcmk__realloc()s and it can take upwards of 18 seconds (yes, seconds) * to dump a 28kb tree which XML_BUFFER_ALLOC_DOUBLEIT can do in * less than 1 second. */ xmlSetBufferAllocationScheme(XML_BUFFER_ALLOC_DOUBLEIT); /* Populate and free the _private field when nodes are created and destroyed */ xmlDeregisterNodeDefault(free_private_data); xmlRegisterNodeDefault(new_private_data); crm_schema_init(); } } void crm_xml_cleanup(void) { crm_schema_cleanup(); xmlCleanupParser(); } #define XPATH_MAX 512 xmlNode * expand_idref(xmlNode * input, xmlNode * top) { char *xpath = NULL; const char *ref = NULL; xmlNode *result = NULL; if (input == NULL) { return NULL; } ref = crm_element_value(input, PCMK_XA_ID_REF); if (ref == NULL) { return input; } if (top == NULL) { top = input; } xpath = crm_strdup_printf("//%s[@" PCMK_XA_ID "='%s']", input->name, ref); result = get_xpath_object(xpath, top, LOG_DEBUG); if (result == NULL) { // Not possible with schema validation enabled pcmk__config_err("Ignoring invalid %s configuration: " PCMK_XA_ID_REF " '%s' does not reference " "a valid object " CRM_XS " xpath=%s", input->name, ref, xpath); } free(xpath); return result; } char * pcmk__xml_artefact_root(enum pcmk__xml_artefact_ns ns) { static const char *base = NULL; char *ret = NULL; if (base == NULL) { base = pcmk__env_option(PCMK__ENV_SCHEMA_DIRECTORY); } if (pcmk__str_empty(base)) { base = CRM_SCHEMA_DIRECTORY; } switch (ns) { case pcmk__xml_artefact_ns_legacy_rng: case pcmk__xml_artefact_ns_legacy_xslt: ret = strdup(base); break; case pcmk__xml_artefact_ns_base_rng: case pcmk__xml_artefact_ns_base_xslt: ret = crm_strdup_printf("%s/base", base); break; default: crm_err("XML artefact family specified as %u not recognized", ns); } return ret; } static char * find_artefact(enum pcmk__xml_artefact_ns ns, const char *path, const char *filespec) { char *ret = NULL; switch (ns) { case pcmk__xml_artefact_ns_legacy_rng: case pcmk__xml_artefact_ns_base_rng: if (pcmk__ends_with(filespec, ".rng")) { ret = crm_strdup_printf("%s/%s", path, filespec); } else { ret = crm_strdup_printf("%s/%s.rng", path, filespec); } break; case pcmk__xml_artefact_ns_legacy_xslt: case pcmk__xml_artefact_ns_base_xslt: if (pcmk__ends_with(filespec, ".xsl")) { ret = crm_strdup_printf("%s/%s", path, filespec); } else { ret = crm_strdup_printf("%s/%s.xsl", path, filespec); } break; default: crm_err("XML artefact family specified as %u not recognized", ns); } return ret; } char * pcmk__xml_artefact_path(enum pcmk__xml_artefact_ns ns, const char *filespec) { struct stat sb; char *base = pcmk__xml_artefact_root(ns); char *ret = NULL; ret = find_artefact(ns, base, filespec); free(base); if (stat(ret, &sb) != 0 || !S_ISREG(sb.st_mode)) { const char *remote_schema_dir = pcmk__remote_schema_dir(); free(ret); ret = find_artefact(ns, remote_schema_dir, filespec); } return ret; } void pcmk__xe_set_propv(xmlNodePtr node, va_list pairs) { while (true) { const char *name, *value; name = va_arg(pairs, const char *); if (name == NULL) { return; } value = va_arg(pairs, const char *); if (value != NULL) { crm_xml_add(node, name, value); } } } void pcmk__xe_set_props(xmlNodePtr node, ...) { va_list pairs; va_start(pairs, node); pcmk__xe_set_propv(node, pairs); va_end(pairs); } int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int (*handler)(xmlNode *xml, void *userdata), void *userdata) { xmlNode *children = (xml? xml->children : NULL); CRM_ASSERT(handler != NULL); for (xmlNode *node = children; node != NULL; node = node->next) { if ((node->type == XML_ELEMENT_NODE) && ((child_element_name == NULL) || pcmk__xe_is(node, child_element_name))) { int rc = handler(node, userdata); if (rc != pcmk_rc_ok) { return rc; } } } return pcmk_rc_ok; } // Deprecated functions kept only for backward API compatibility // LCOV_EXCL_START #include xmlNode * find_entity(xmlNode *parent, const char *node_name, const char *id) { return pcmk__xe_first_child(parent, node_name, ((id == NULL)? id : PCMK_XA_ID), id); } void crm_destroy_xml(gpointer data) { free_xml(data); } xmlDoc * getDocPtr(xmlNode *node) { xmlDoc *doc = NULL; CRM_CHECK(node != NULL, return NULL); doc = node->doc; if (doc == NULL) { doc = pcmk__xml_new_doc(); xmlDocSetRootElement(doc, node); } return doc; } xmlNode * add_node_copy(xmlNode *parent, xmlNode *src_node) { + /* @TODO Allocate the copy tree's private data here when we drop + * new_private_data()/free_private_data() + */ xmlNode *child = NULL; CRM_CHECK((parent != NULL) && (src_node != NULL), return NULL); child = xmlDocCopyNode(src_node, parent->doc, 1); if (child == NULL) { return NULL; } xmlAddChild(parent, child); pcmk__xml_mark_created(child); return child; } int add_node_nocopy(xmlNode *parent, const char *name, xmlNode *child) { add_node_copy(parent, child); free_xml(child); return 1; } gboolean xml_has_children(const xmlNode * xml_root) { if (xml_root != NULL && xml_root->children != NULL) { return TRUE; } return FALSE; } static char * replace_text(char *text, size_t *index, size_t *length, const char *replace) { // We have space for 1 char already size_t offset = strlen(replace) - 1; if (offset > 0) { *length += offset; text = pcmk__realloc(text, *length + 1); // Shift characters to the right to make room for the replacement string for (size_t i = *length; i > (*index + offset); i--) { text[i] = text[i - offset]; } } // Replace the character at index by the replacement string memcpy(text + *index, replace, offset + 1); // Reset index to the end of replacement string *index += offset; return text; } char * crm_xml_escape(const char *text) { size_t length = 0; char *copy = NULL; if (text == NULL) { return NULL; } length = strlen(text); copy = pcmk__str_copy(text); for (size_t index = 0; index <= length; index++) { if(copy[index] & 0x80 && copy[index+1] & 0x80){ index++; continue; } switch (copy[index]) { case 0: // Sanity only; loop should stop at the last non-null byte break; case '<': copy = replace_text(copy, &index, &length, "<"); break; case '>': copy = replace_text(copy, &index, &length, ">"); break; case '"': copy = replace_text(copy, &index, &length, """); break; case '\'': copy = replace_text(copy, &index, &length, "'"); break; case '&': copy = replace_text(copy, &index, &length, "&"); break; case '\t': /* Might as well just expand to a few spaces... */ copy = replace_text(copy, &index, &length, " "); break; case '\n': copy = replace_text(copy, &index, &length, "\\n"); break; case '\r': copy = replace_text(copy, &index, &length, "\\r"); break; default: /* Check for and replace non-printing characters with their octal equivalent */ if(copy[index] < ' ' || copy[index] > '~') { char *replace = crm_strdup_printf("\\%.3o", copy[index]); copy = replace_text(copy, &index, &length, replace); free(replace); } } } return copy; } xmlNode * copy_xml(xmlNode *src) { + /* @TODO Allocate the copy tree's private data here when we drop + * new_private_data()/free_private_data() + */ xmlDoc *doc = pcmk__xml_new_doc(); xmlNode *copy = NULL; copy = xmlDocCopyNode(src, doc, 1); pcmk__mem_assert(copy); xmlDocSetRootElement(doc, copy); return copy; } xmlNode * create_xml_node(xmlNode *parent, const char *name) { // Like pcmk__xe_create(), but returns NULL on failure xmlNode *node = NULL; CRM_CHECK(!pcmk__str_empty(name), return NULL); if (parent == NULL) { xmlDoc *doc = pcmk__xml_new_doc(); node = xmlNewDocRawNode(doc, NULL, (pcmkXmlStr) name, NULL); if (node == NULL) { pcmk__xml_free_doc(doc); return NULL; } xmlDocSetRootElement(doc, node); } else { node = xmlNewChild(parent, NULL, (pcmkXmlStr) name, NULL); if (node == NULL) { return NULL; } } pcmk__xml_mark_created(node); return node; } xmlNode * pcmk_create_xml_text_node(xmlNode *parent, const char *name, const char *content) { xmlNode *node = pcmk__xe_create(parent, name); pcmk__xe_set_content(node, "%s", content); return node; } xmlNode * pcmk_create_html_node(xmlNode *parent, const char *element_name, const char *id, const char *class_name, const char *text) { xmlNode *node = pcmk__html_create(parent, element_name, id, class_name); pcmk__xe_set_content(node, "%s", text); return node; } xmlNode * first_named_child(const xmlNode *parent, const char *name) { return pcmk__xe_first_child(parent, name, NULL, NULL); } xmlNode * find_xml_node(const xmlNode *root, const char *search_path, gboolean must_find) { xmlNode *result = NULL; if (search_path == NULL) { crm_warn("Will never find "); return NULL; } result = pcmk__xe_first_child(root, search_path, NULL, NULL); if (must_find && (result == NULL)) { crm_warn("Could not find %s in %s", search_path, ((root != NULL)? (const char *) root->name : "")); } return result; } xmlNode * crm_next_same_xml(const xmlNode *sibling) { return pcmk__xe_next_same(sibling); } void xml_remove_prop(xmlNode * obj, const char *name) { pcmk__xe_remove_attr(obj, name); } gboolean replace_xml_child(xmlNode * parent, xmlNode * child, xmlNode * update, gboolean delete_only) { bool is_match = false; const char *child_id = NULL; const char *update_id = NULL; CRM_CHECK(child != NULL, return FALSE); CRM_CHECK(update != NULL, return FALSE); child_id = pcmk__xe_id(child); update_id = pcmk__xe_id(update); /* Match element name and (if provided in update XML) element ID. Don't * match search root (child is search root if parent == NULL). */ is_match = (parent != NULL) && pcmk__xe_is(update, (const char *) child->name) && ((update_id == NULL) || pcmk__str_eq(update_id, child_id, pcmk__str_none)); /* For deletion, match all attributes provided in update. A matching node * can have additional attributes, but values must match for provided ones. */ if (is_match && delete_only) { for (xmlAttr *attr = pcmk__xe_first_attr(update); attr != NULL; attr = attr->next) { const char *name = (const char *) attr->name; const char *update_val = pcmk__xml_attr_value(attr); const char *child_val = crm_element_value(child, name); if (!pcmk__str_eq(update_val, child_val, pcmk__str_casei)) { is_match = false; break; } } } if (is_match) { if (delete_only) { crm_log_xml_trace(child, "delete-match"); crm_log_xml_trace(update, "delete-search"); free_xml(child); } else { crm_log_xml_trace(child, "replace-match"); crm_log_xml_trace(update, "replace-with"); replace_node(child, update); } return TRUE; } // Current node not a match; search the rest of the subtree depth-first parent = child; for (child = pcmk__xml_first_child(parent); child != NULL; child = pcmk__xml_next(child)) { // Only delete/replace the first match if (replace_xml_child(parent, child, update, delete_only)) { return TRUE; } } // No match found in this subtree return FALSE; } gboolean update_xml_child(xmlNode *child, xmlNode *to_update) { return pcmk__xe_update_match(child, to_update, pcmk__xaf_score_update) == pcmk_rc_ok; } int find_xml_children(xmlNode **children, xmlNode *root, const char *tag, const char *field, const char *value, gboolean search_matches) { int match_found = 0; CRM_CHECK(root != NULL, return FALSE); CRM_CHECK(children != NULL, return FALSE); if ((tag != NULL) && !pcmk__xe_is(root, tag)) { } else if ((value != NULL) && !pcmk__str_eq(value, crm_element_value(root, field), pcmk__str_casei)) { } else { if (*children == NULL) { *children = pcmk__xe_create(NULL, __func__); } pcmk__xml_copy(*children, root); match_found = 1; } if (search_matches || match_found == 0) { xmlNode *child = NULL; for (child = pcmk__xml_first_child(root); child != NULL; child = pcmk__xml_next(child)) { match_found += find_xml_children(children, child, tag, field, value, search_matches); } } return match_found; } void fix_plus_plus_recursive(xmlNode *target) { /* TODO: Remove recursion and use xpath searches for value++ */ xmlNode *child = NULL; for (xmlAttrPtr a = pcmk__xe_first_attr(target); a != NULL; a = a->next) { const char *p_name = (const char *) a->name; const char *p_value = pcmk__xml_attr_value(a); expand_plus_plus(target, p_name, p_value); } for (child = pcmk__xe_first_child(target, NULL, NULL, NULL); child != NULL; child = pcmk__xe_next(child)) { fix_plus_plus_recursive(child); } } void copy_in_properties(xmlNode *target, const xmlNode *src) { if (src == NULL) { crm_warn("No node to copy properties from"); } else if (target == NULL) { crm_err("No node to copy properties into"); } else { for (xmlAttrPtr a = pcmk__xe_first_attr(src); a != NULL; a = a->next) { const char *p_name = (const char *) a->name; const char *p_value = pcmk__xml_attr_value(a); expand_plus_plus(target, p_name, p_value); if (xml_acl_denied(target)) { crm_trace("Cannot copy %s=%s to %s", p_name, p_value, target->name); return; } } } } void expand_plus_plus(xmlNode * target, const char *name, const char *value) { pcmk__xe_set_score(target, name, value); } // LCOV_EXCL_STOP // End deprecated API