diff --git a/daemons/based/based_common.c b/daemons/based/based_common.c
index 66f28d695c..76bcad9fba 100644
--- a/daemons/based/based_common.c
+++ b/daemons/based/based_common.c
@@ -1,362 +1,362 @@
 /*
  * Copyright 2008-2022 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ipc.h>
 #include <crm/cluster.h>
 
 #include <crm/common/xml.h>
 
 #include <pacemaker-based.h>
 
 gboolean stand_alone = FALSE;
 
 extern int cib_perform_command(xmlNode * request, xmlNode ** reply, xmlNode ** cib_diff,
                                gboolean privileged);
 
 static xmlNode *
 cib_prepare_common(xmlNode * root, const char *section)
 {
     xmlNode *data = NULL;
 
     /* extract the CIB from the fragment */
     if (root == NULL) {
         return NULL;
 
     } else if (pcmk__strcase_any_of(crm_element_name(root), XML_TAG_FRAGMENT,
                                     F_CRM_DATA, F_CIB_CALLDATA, NULL)) {
         data = first_named_child(root, XML_TAG_CIB);
 
     } else {
         data = root;
     }
 
     /* grab the section specified for the command */
     if (section != NULL && data != NULL && pcmk__str_eq(crm_element_name(data), XML_TAG_CIB, pcmk__str_none)) {
         data = pcmk_find_cib_element(data, section);
     }
 
     /* crm_log_xml_trace(root, "cib:input"); */
     return data;
 }
 
 static int
 cib_prepare_none(xmlNode * request, xmlNode ** data, const char **section)
 {
     *data = NULL;
     *section = crm_element_value(request, F_CIB_SECTION);
     return pcmk_ok;
 }
 
 static int
 cib_prepare_data(xmlNode * request, xmlNode ** data, const char **section)
 {
     xmlNode *input_fragment = get_message_xml(request, F_CIB_CALLDATA);
 
     *section = crm_element_value(request, F_CIB_SECTION);
     *data = cib_prepare_common(input_fragment, *section);
     /* crm_log_xml_debug(*data, "data"); */
     return pcmk_ok;
 }
 
 static int
 cib_prepare_sync(xmlNode * request, xmlNode ** data, const char **section)
 {
     *data = NULL;
     *section = crm_element_value(request, F_CIB_SECTION);
     return pcmk_ok;
 }
 
 static int
 cib_prepare_diff(xmlNode * request, xmlNode ** data, const char **section)
 {
     xmlNode *input_fragment = NULL;
 
     *data = NULL;
     *section = NULL;
 
     if (pcmk__xe_attr_is_true(request, F_CIB_GLOBAL_UPDATE)) {
         input_fragment = get_message_xml(request, F_CIB_UPDATE_DIFF);
     } else {
         input_fragment = get_message_xml(request, F_CIB_CALLDATA);
     }
 
     CRM_CHECK(input_fragment != NULL, crm_log_xml_warn(request, "no input"));
     *data = cib_prepare_common(input_fragment, NULL);
     return pcmk_ok;
 }
 
 static int
 cib_cleanup_query(int options, xmlNode ** data, xmlNode ** output)
 {
     CRM_LOG_ASSERT(*data == NULL);
     if ((options & cib_no_children)
         || pcmk__str_eq(crm_element_name(*output), "xpath-query", pcmk__str_casei)) {
         free_xml(*output);
     }
     return pcmk_ok;
 }
 
 static int
 cib_cleanup_data(int options, xmlNode ** data, xmlNode ** output)
 {
     free_xml(*output);
     *data = NULL;
     return pcmk_ok;
 }
 
 static int
 cib_cleanup_output(int options, xmlNode ** data, xmlNode ** output)
 {
     free_xml(*output);
     return pcmk_ok;
 }
 
 static int
 cib_cleanup_none(int options, xmlNode ** data, xmlNode ** output)
 {
     CRM_LOG_ASSERT(*data == NULL);
     CRM_LOG_ASSERT(*output == NULL);
     return pcmk_ok;
 }
 
 static cib_operation_t cib_server_ops[] = {
     // Booleans are modifies_cib, needs_privileges, needs_quorum
     {
         NULL, FALSE, FALSE, FALSE,
         cib_prepare_none, cib_cleanup_none, cib_process_default
     },
     {
         PCMK__CIB_REQUEST_QUERY, FALSE, FALSE, FALSE,
         cib_prepare_none, cib_cleanup_query, cib_process_query
     },
     {
         PCMK__CIB_REQUEST_MODIFY, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_modify
     },
     {
         CIB_OP_APPLY_DIFF, TRUE, TRUE, TRUE,
         cib_prepare_diff, cib_cleanup_data, cib_server_process_diff
     },
     {
         CIB_OP_REPLACE, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_replace_svr
     },
     {
         PCMK__CIB_REQUEST_CREATE, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_create
     },
     {
-        CIB_OP_DELETE, TRUE, TRUE, TRUE,
+        PCMK__CIB_REQUEST_DELETE, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_delete
     },
     {
         PCMK__CIB_REQUEST_SYNC_TO_ALL, FALSE, TRUE, FALSE,
         cib_prepare_sync, cib_cleanup_none, cib_process_sync
     },
     {
         PCMK__CIB_REQUEST_BUMP, TRUE, TRUE, TRUE,
         cib_prepare_none, cib_cleanup_output, cib_process_bump
     },
     {
         CIB_OP_ERASE, TRUE, TRUE, TRUE,
         cib_prepare_none, cib_cleanup_output, cib_process_erase
     },
     {
         CRM_OP_NOOP, FALSE, FALSE, FALSE,
         cib_prepare_none, cib_cleanup_none, cib_process_default
     },
     {
         CIB_OP_DELETE_ALT, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_delete_absolute
     },
     {
         CIB_OP_UPGRADE, TRUE, TRUE, TRUE,
         cib_prepare_none, cib_cleanup_output, cib_process_upgrade_server
     },
     {
         PCMK__CIB_REQUEST_SECONDARY, FALSE, TRUE, FALSE,
         cib_prepare_none, cib_cleanup_none, cib_process_readwrite
     },
     {
         PCMK__CIB_REQUEST_ALL_SECONDARY, FALSE, TRUE, FALSE,
         cib_prepare_none, cib_cleanup_none, cib_process_readwrite
     },
     {
         PCMK__CIB_REQUEST_SYNC_TO_ONE, FALSE, TRUE, FALSE,
         cib_prepare_sync, cib_cleanup_none, cib_process_sync_one
     },
     {
         PCMK__CIB_REQUEST_PRIMARY, TRUE, TRUE, FALSE,
         cib_prepare_data, cib_cleanup_data, cib_process_readwrite
     },
     {
         PCMK__CIB_REQUEST_IS_PRIMARY, FALSE, TRUE, FALSE,
         cib_prepare_none, cib_cleanup_none, cib_process_readwrite
     },
     {
         "cib_shutdown_req", FALSE, TRUE, FALSE,
         cib_prepare_sync, cib_cleanup_none, cib_process_shutdown_req
     },
     {
         CRM_OP_PING, FALSE, FALSE, FALSE,
         cib_prepare_none, cib_cleanup_output, cib_process_ping
     },
 };
 
 int
 cib_get_operation_id(const char *op, int *operation)
 {
     static GHashTable *operation_hash = NULL;
 
     if (operation_hash == NULL) {
         int lpc = 0;
         int max_msg_types = PCMK__NELEM(cib_server_ops);
 
         operation_hash = pcmk__strkey_table(NULL, free);
         for (lpc = 1; lpc < max_msg_types; lpc++) {
             int *value = malloc(sizeof(int));
 
             if(value) {
                 *value = lpc;
                 g_hash_table_insert(operation_hash, (gpointer) cib_server_ops[lpc].operation, value);
             }
         }
     }
 
     if (op != NULL) {
         int *value = g_hash_table_lookup(operation_hash, op);
 
         if (value) {
             *operation = *value;
             return pcmk_ok;
         }
     }
     crm_err("Operation %s is not valid", op);
     *operation = -1;
     return -EINVAL;
 }
 
 xmlNode *
 cib_msg_copy(xmlNode * msg, gboolean with_data)
 {
     int lpc = 0;
     const char *field = NULL;
     const char *value = NULL;
     xmlNode *value_struct = NULL;
 
     static const char *field_list[] = {
         F_XML_TAGNAME,
         F_TYPE,
         F_CIB_CLIENTID,
         F_CIB_CALLOPTS,
         F_CIB_CALLID,
         F_CIB_OPERATION,
         F_CIB_ISREPLY,
         F_CIB_SECTION,
         F_CIB_HOST,
         F_CIB_RC,
         F_CIB_DELEGATED,
         F_CIB_OBJID,
         F_CIB_OBJTYPE,
         F_CIB_EXISTING,
         F_CIB_SEENCOUNT,
         F_CIB_TIMEOUT,
         F_CIB_CALLBACK_TOKEN,
         F_CIB_GLOBAL_UPDATE,
         F_CIB_CLIENTNAME,
         F_CIB_USER,
         F_CIB_NOTIFY_TYPE,
         F_CIB_NOTIFY_ACTIVATE
     };
 
     static const char *data_list[] = {
         F_CIB_CALLDATA,
         F_CIB_UPDATE,
         F_CIB_UPDATE_RESULT
     };
 
     xmlNode *copy = create_xml_node(NULL, "copy");
 
     CRM_ASSERT(copy != NULL);
 
     for (lpc = 0; lpc < PCMK__NELEM(field_list); lpc++) {
         field = field_list[lpc];
         value = crm_element_value(msg, field);
         if (value != NULL) {
             crm_xml_add(copy, field, value);
         }
     }
     for (lpc = 0; with_data && lpc < PCMK__NELEM(data_list); lpc++) {
         field = data_list[lpc];
         value_struct = get_message_xml(msg, field);
         if (value_struct != NULL) {
             add_message_xml(copy, field, value_struct);
         }
     }
 
     return copy;
 }
 
 cib_op_t *
 cib_op_func(int call_type)
 {
     return &(cib_server_ops[call_type].fn);
 }
 
 gboolean
 cib_op_modifies(int call_type)
 {
     return cib_server_ops[call_type].modifies_cib;
 }
 
 int
 cib_op_can_run(int call_type, int call_options, gboolean privileged, gboolean global_update)
 {
     if (privileged == FALSE && cib_server_ops[call_type].needs_privileges) {
         /* abort */
         return -EACCES;
     }
 #if 0
     if (rc == pcmk_ok
         && stand_alone == FALSE
         && global_update == FALSE
         && (call_options & cib_quorum_override) == 0 && cib_server_ops[call_type].needs_quorum) {
         return -pcmk_err_no_quorum;
     }
 #endif
     return pcmk_ok;
 }
 
 int
 cib_op_prepare(int call_type, xmlNode * request, xmlNode ** input, const char **section)
 {
     crm_trace("Prepare %d", call_type);
     return cib_server_ops[call_type].prepare(request, input, section);
 }
 
 int
 cib_op_cleanup(int call_type, int options, xmlNode ** input, xmlNode ** output)
 {
     crm_trace("Cleanup %d", call_type);
     return cib_server_ops[call_type].cleanup(options, input, output);
 }
diff --git a/daemons/controld/controld_based.c b/daemons/controld/controld_based.c
index 9e96dc47cd..1b19522423 100644
--- a/daemons/controld/controld_based.c
+++ b/daemons/controld/controld_based.c
@@ -1,353 +1,353 @@
 /*
  * Copyright 2004-2022 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <unistd.h>  /* sleep */
 
 #include <crm/common/alerts_internal.h>
 #include <crm/common/xml.h>
 #include <crm/crm.h>
 #include <crm/msg_xml.h>
 
 #include <pacemaker-controld.h>
 
 int cib_retries = 0;
 
 void
 do_cib_updated(const char *event, xmlNode * msg)
 {
     if (pcmk__alert_in_patchset(msg, TRUE)) {
         mainloop_set_trigger(config_read);
     }
 }
 
 void
 do_cib_replaced(const char *event, xmlNode * msg)
 {
     int change_section = cib_change_section_nodes | cib_change_section_status;
 
     crm_debug("Updating the CIB after a replace: DC=%s", pcmk__btoa(AM_I_DC));
     if (AM_I_DC == FALSE) {
         return;
 
     } else if ((fsa_state == S_FINALIZE_JOIN)
                && pcmk_is_set(fsa_input_register, R_CIB_ASKED)) {
         /* no need to restart the join - we asked for this replace op */
         return;
     }
 
     crm_element_value_int(msg, F_CIB_CHANGE_SECTION, &change_section);
     if (change_section & (cib_change_section_nodes | cib_change_section_status)) {
         /* start the join process again so we get everyone's LRM status */
         populate_cib_nodes(node_update_quick|node_update_all, __func__);
 
         register_fsa_input(C_FSA_INTERNAL, I_ELECTION, NULL);
     }
 }
 
 void
 controld_disconnect_cib_manager(void)
 {
     CRM_ASSERT(fsa_cib_conn != NULL);
 
     crm_info("Disconnecting from the CIB manager");
 
     controld_clear_fsa_input_flags(R_CIB_CONNECTED);
 
     fsa_cib_conn->cmds->del_notify_callback(fsa_cib_conn, T_CIB_REPLACE_NOTIFY, do_cib_replaced);
     fsa_cib_conn->cmds->del_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY, do_cib_updated);
     cib_free_callbacks(fsa_cib_conn);
     if (fsa_cib_conn->state != cib_disconnected) {
         /* Does not require a set_slave() reply to sign out from based. */
         fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local | cib_discard_reply);
         fsa_cib_conn->cmds->signoff(fsa_cib_conn);
     }
 
     crm_notice("Disconnected from the CIB manager");
 }
 
 /* A_CIB_STOP, A_CIB_START, O_CIB_RESTART */
 void
 do_cib_control(long long action,
                enum crmd_fsa_cause cause,
                enum crmd_fsa_state cur_state,
                enum crmd_fsa_input current_input, fsa_data_t * msg_data)
 {
     CRM_ASSERT(fsa_cib_conn != NULL);
 
     if (action & A_CIB_STOP) {
 
         if (fsa_cib_conn->state != cib_disconnected && last_resource_update != 0) {
             crm_info("Waiting for resource update %d to complete", last_resource_update);
             crmd_fsa_stall(FALSE);
             return;
         }
 
         controld_disconnect_cib_manager();
 
     }
 
     if (action & A_CIB_START) {
         int rc = pcmk_ok;
 
         if (cur_state == S_STOPPING) {
             crm_err("Ignoring request to connect to the CIB manager after shutdown");
             return;
         }
 
         rc = fsa_cib_conn->cmds->signon(fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command_nonblocking);
 
         if (rc != pcmk_ok) {
             /* a short wait that usually avoids stalling the FSA */
             sleep(1);
             rc = fsa_cib_conn->cmds->signon(fsa_cib_conn, CRM_SYSTEM_CRMD, cib_command_nonblocking);
         }
 
         if (rc != pcmk_ok) {
             crm_info("Could not connect to the CIB manager: %s", pcmk_strerror(rc));
 
         } else if (pcmk_ok !=
                    fsa_cib_conn->cmds->set_connection_dnotify(fsa_cib_conn,
                                                               crmd_cib_connection_destroy)) {
             crm_err("Could not set dnotify callback");
 
         } else if (pcmk_ok !=
                    fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_REPLACE_NOTIFY,
                                                            do_cib_replaced)) {
             crm_err("Could not set CIB notification callback (replace)");
 
         } else if (pcmk_ok !=
                    fsa_cib_conn->cmds->add_notify_callback(fsa_cib_conn, T_CIB_DIFF_NOTIFY,
                                                            do_cib_updated)) {
             crm_err("Could not set CIB notification callback (update)");
 
         } else {
             controld_set_fsa_input_flags(R_CIB_CONNECTED);
             cib_retries = 0;
         }
 
         if (!pcmk_is_set(fsa_input_register, R_CIB_CONNECTED)) {
 
             cib_retries++;
             crm_warn("Couldn't complete CIB registration %d"
                      " times... pause and retry", cib_retries);
 
             if (cib_retries < 30) {
                 controld_start_timer(wait_timer);
                 crmd_fsa_stall(FALSE);
 
             } else {
                 crm_err("Could not complete CIB"
                         " registration  %d times..." " hard error", cib_retries);
                 register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
             }
         }
     }
 }
 
 /*!
  * \internal
  * \brief Get CIB call options to use local scope if master unavailable
  *
  * \return CIB call options
  */
 int
 crmd_cib_smart_opt(void)
 {
     int call_opt = cib_quorum_override;
 
     if (fsa_state == S_ELECTION || fsa_state == S_PENDING) {
         crm_info("Sending update to local CIB in state: %s", fsa_state2string(fsa_state));
         cib__set_call_options(call_opt, "update", cib_scope_local);
     }
     return call_opt;
 }
 
 /*!
  * \internal
  * \brief Check whether an action type should be recorded in the CIB
  *
  * \param[in] action  Action type
  *
  * \return TRUE if action should be recorded, FALSE otherwise
  */
 bool
 controld_action_is_recordable(const char *action)
 {
     return !pcmk__strcase_any_of(action, CRMD_ACTION_CANCEL, CRMD_ACTION_DELETE,
                             CRMD_ACTION_NOTIFY, CRMD_ACTION_METADATA, NULL);
 }
 
 static void
 cib_delete_callback(xmlNode *msg, int call_id, int rc, xmlNode *output,
                     void *user_data)
 {
     char *desc = user_data;
 
     if (rc == 0) {
         crm_debug("Deletion of %s (via CIB call %d) succeeded", desc, call_id);
     } else {
         crm_warn("Deletion of %s (via CIB call %d) failed: %s " CRM_XS " rc=%d",
                  desc, call_id, pcmk_strerror(rc), rc);
     }
 }
 
 // Searches for various portions of node_state to delete
 
 // Match a particular node's node_state (takes node name 1x)
 #define XPATH_NODE_STATE        "//" XML_CIB_TAG_STATE "[@" XML_ATTR_UNAME "='%s']"
 
 // Node's lrm section (name 1x)
 #define XPATH_NODE_LRM          XPATH_NODE_STATE "/" XML_CIB_TAG_LRM
 
 // Node's lrm_rsc_op entries and lrm_resource entries without lock (name 2x)
 #define XPATH_NODE_LRM_UNLOCKED XPATH_NODE_STATE "//" XML_LRM_TAG_RSC_OP    \
                                 "|" XPATH_NODE_STATE                        \
                                 "//" XML_LRM_TAG_RESOURCE                   \
                                 "[not(@" XML_CONFIG_ATTR_SHUTDOWN_LOCK ")]"
 
 // Node's transient_attributes section (name 1x)
 #define XPATH_NODE_ATTRS        XPATH_NODE_STATE "/" XML_TAG_TRANSIENT_NODEATTRS
 
 // Everything under node_state (name 1x)
 #define XPATH_NODE_ALL          XPATH_NODE_STATE "/*"
 
 // Unlocked history + transient attributes (name 3x)
 #define XPATH_NODE_ALL_UNLOCKED XPATH_NODE_LRM_UNLOCKED "|" XPATH_NODE_ATTRS
 
 /*!
  * \internal
  * \brief Delete subsection of a node's CIB node_state
  *
  * \param[in] uname    Desired node
  * \param[in] section  Subsection of node_state to delete
  * \param[in] options  CIB call options to use
  */
 void
 controld_delete_node_state(const char *uname, enum controld_section_e section,
                            int options)
 {
     char *xpath = NULL;
     char *desc = NULL;
 
     CRM_CHECK(uname != NULL, return);
     switch (section) {
         case controld_section_lrm:
             xpath = crm_strdup_printf(XPATH_NODE_LRM, uname);
             desc = crm_strdup_printf("resource history for node %s", uname);
             break;
         case controld_section_lrm_unlocked:
             xpath = crm_strdup_printf(XPATH_NODE_LRM_UNLOCKED, uname, uname);
             desc = crm_strdup_printf("resource history (other than shutdown "
                                      "locks) for node %s", uname);
             break;
         case controld_section_attrs:
             xpath = crm_strdup_printf(XPATH_NODE_ATTRS, uname);
             desc = crm_strdup_printf("transient attributes for node %s", uname);
             break;
         case controld_section_all:
             xpath = crm_strdup_printf(XPATH_NODE_ALL, uname);
             desc = crm_strdup_printf("all state for node %s", uname);
             break;
         case controld_section_all_unlocked:
             xpath = crm_strdup_printf(XPATH_NODE_ALL_UNLOCKED,
                                       uname, uname, uname);
             desc = crm_strdup_printf("all state (other than shutdown locks) "
                                      "for node %s", uname);
             break;
     }
 
     if (fsa_cib_conn == NULL) {
         crm_warn("Unable to delete %s: no CIB connection", desc);
         free(desc);
     } else {
         int call_id;
 
         cib__set_call_options(options, "node state deletion",
                               cib_quorum_override|cib_xpath|cib_multiple);
         call_id = fsa_cib_conn->cmds->remove(fsa_cib_conn, xpath, NULL, options);
         crm_info("Deleting %s (via CIB call %d) " CRM_XS " xpath=%s",
                  desc, call_id, xpath);
         fsa_register_cib_callback(call_id, FALSE, desc, cib_delete_callback);
         // CIB library handles freeing desc
     }
     free(xpath);
 }
 
 // Takes node name and resource ID
 #define XPATH_RESOURCE_HISTORY "//" XML_CIB_TAG_STATE                       \
                                "[@" XML_ATTR_UNAME "='%s']/"                \
                                XML_CIB_TAG_LRM "/" XML_LRM_TAG_RESOURCES    \
                                "/" XML_LRM_TAG_RESOURCE                     \
                                "[@" XML_ATTR_ID "='%s']"
 // @TODO could add "and @XML_CONFIG_ATTR_SHUTDOWN_LOCK" to limit to locks
 
 /*!
  * \internal
  * \brief Clear resource history from CIB for a given resource and node
  *
  * \param[in]  rsc_id        ID of resource to be cleared
  * \param[in]  node          Node whose resource history should be cleared
  * \param[in]  user_name     ACL user name to use
  * \param[in]  call_options  CIB call options
  *
  * \return Standard Pacemaker return code
  */
 int
 controld_delete_resource_history(const char *rsc_id, const char *node,
                                  const char *user_name, int call_options)
 {
     char *desc = NULL;
     char *xpath = NULL;
     int rc = pcmk_rc_ok;
 
     CRM_CHECK((rsc_id != NULL) && (node != NULL), return EINVAL);
 
     desc = crm_strdup_printf("resource history for %s on %s", rsc_id, node);
     if (fsa_cib_conn == NULL) {
         crm_err("Unable to clear %s: no CIB connection", desc);
         free(desc);
         return ENOTCONN;
     }
 
     // Ask CIB to delete the entry
     xpath = crm_strdup_printf(XPATH_RESOURCE_HISTORY, node, rsc_id);
-    rc = cib_internal_op(fsa_cib_conn, CIB_OP_DELETE, NULL, xpath, NULL,
-                         NULL, call_options|cib_xpath, user_name);
+    rc = cib_internal_op(fsa_cib_conn, PCMK__CIB_REQUEST_DELETE, NULL, xpath,
+                         NULL, NULL, call_options|cib_xpath, user_name);
 
     if (rc < 0) {
         rc = pcmk_legacy2rc(rc);
         crm_err("Could not delete resource status of %s on %s%s%s: %s "
                 CRM_XS " rc=%d", rsc_id, node,
                 (user_name? " for user " : ""), (user_name? user_name : ""),
                 pcmk_rc_str(rc), rc);
         free(desc);
         free(xpath);
         return rc;
     }
 
     if (pcmk_is_set(call_options, cib_sync_call)) {
         if (pcmk_is_set(call_options, cib_dryrun)) {
             crm_debug("Deletion of %s would succeed", desc);
         } else {
             crm_debug("Deletion of %s succeeded", desc);
         }
         free(desc);
 
     } else {
         crm_info("Clearing %s (via CIB call %d) " CRM_XS " xpath=%s",
                  desc, rc, xpath);
         fsa_register_cib_callback(rc, FALSE, desc, cib_delete_callback);
         // CIB library handles freeing desc
     }
 
     free(xpath);
     return pcmk_rc_ok;
 }
diff --git a/include/crm/cib/internal.h b/include/crm/cib/internal.h
index 2cfa406a65..49860e10b3 100644
--- a/include/crm/cib/internal.h
+++ b/include/crm/cib/internal.h
@@ -1,263 +1,263 @@
 /*
  * Copyright 2004-2022 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.
  */
 
 #ifndef CIB_INTERNAL__H
 #  define CIB_INTERNAL__H
 #  include <crm/cib.h>
 #  include <crm/common/ipc_internal.h>
 #  include <crm/common/output_internal.h>
 
 // Request types for CIB manager IPC/CPG
 #define PCMK__CIB_REQUEST_SECONDARY     "cib_slave"
 #define PCMK__CIB_REQUEST_ALL_SECONDARY "cib_slave_all"
 #define PCMK__CIB_REQUEST_PRIMARY       "cib_master"
 #define PCMK__CIB_REQUEST_SYNC_TO_ALL   "cib_sync"
 #define PCMK__CIB_REQUEST_SYNC_TO_ONE   "cib_sync_one"
 #define PCMK__CIB_REQUEST_IS_PRIMARY    "cib_ismaster"
 #define PCMK__CIB_REQUEST_BUMP          "cib_bump"
 #define PCMK__CIB_REQUEST_QUERY         "cib_query"
 #define PCMK__CIB_REQUEST_CREATE        "cib_create"
 #define PCMK__CIB_REQUEST_MODIFY        "cib_modify"
-#  define CIB_OP_DELETE	"cib_delete"
+#define PCMK__CIB_REQUEST_DELETE        "cib_delete"
 #  define CIB_OP_ERASE	"cib_erase"
 #  define CIB_OP_REPLACE	"cib_replace"
 #  define CIB_OP_APPLY_DIFF "cib_apply_diff"
 #  define CIB_OP_UPGRADE    "cib_upgrade"
 #  define CIB_OP_DELETE_ALT	"cib_delete_alt"
 
 #  define F_CIB_CLIENTID  "cib_clientid"
 #  define F_CIB_CALLOPTS  "cib_callopt"
 #  define F_CIB_CALLID    "cib_callid"
 #  define F_CIB_CALLDATA  "cib_calldata"
 #  define F_CIB_OPERATION "cib_op"
 #  define F_CIB_ISREPLY   "cib_isreplyto"
 #  define F_CIB_SECTION   "cib_section"
 #  define F_CIB_HOST	"cib_host"
 #  define F_CIB_RC	"cib_rc"
 #  define F_CIB_UPGRADE_RC      "cib_upgrade_rc"
 #  define F_CIB_DELEGATED	"cib_delegated_from"
 #  define F_CIB_OBJID	"cib_object"
 #  define F_CIB_OBJTYPE	"cib_object_type"
 #  define F_CIB_EXISTING	"cib_existing_object"
 #  define F_CIB_SEENCOUNT	"cib_seen"
 #  define F_CIB_TIMEOUT	"cib_timeout"
 #  define F_CIB_UPDATE	"cib_update"
 #  define F_CIB_CALLBACK_TOKEN	"cib_async_id"
 #  define F_CIB_GLOBAL_UPDATE	"cib_update"
 #  define F_CIB_UPDATE_RESULT	"cib_update_result"
 #  define F_CIB_CLIENTNAME	"cib_clientname"
 #  define F_CIB_NOTIFY_TYPE	"cib_notify_type"
 #  define F_CIB_NOTIFY_ACTIVATE	"cib_notify_activate"
 #  define F_CIB_UPDATE_DIFF	"cib_update_diff"
 #  define F_CIB_USER		"cib_user"
 #  define F_CIB_LOCAL_NOTIFY_ID	"cib_local_notify_id"
 #  define F_CIB_PING_ID         "cib_ping_id"
 #  define F_CIB_SCHEMA_MAX      "cib_schema_max"
 #  define F_CIB_CHANGE_SECTION  "cib_change_section"
 
 #  define T_CIB			"cib"
 #  define T_CIB_NOTIFY		"cib_notify"
 /* notify sub-types */
 #  define T_CIB_PRE_NOTIFY	"cib_pre_notify"
 #  define T_CIB_POST_NOTIFY	"cib_post_notify"
 #  define T_CIB_UPDATE_CONFIRM	"cib_update_confirmation"
 #  define T_CIB_REPLACE_NOTIFY	"cib_refresh_notify"
 
 enum cib_change_section_info {
     cib_change_section_none     = 0x00000000,
     cib_change_section_nodes    = 0x00000001,
     cib_change_section_alerts   = 0x00000002,
     cib_change_section_status   = 0x00000004
 };
 
 
 gboolean cib_diff_version_details(xmlNode * diff, int *admin_epoch, int *epoch, int *updates,
                                   int *_admin_epoch, int *_epoch, int *_updates);
 
 gboolean cib_read_config(GHashTable * options, xmlNode * current_cib);
 void verify_cib_options(GHashTable * options);
 gboolean cib_internal_config_changed(xmlNode * diff);
 
 typedef struct cib_notify_client_s {
     const char *event;
     const char *obj_id;         /* implement one day */
     const char *obj_type;       /* implement one day */
     void (*callback) (const char *event, xmlNode * msg);
 
 } cib_notify_client_t;
 
 typedef struct cib_callback_client_s {
     void (*callback) (xmlNode *, int, int, xmlNode *, void *);
     const char *id;
     void *user_data;
     gboolean only_success;
     struct timer_rec_s *timer;
     void (*free_func)(void *);
 } cib_callback_client_t;
 
 struct timer_rec_s {
     int call_id;
     int timeout;
     guint ref;
     cib_t *cib;
 };
 
 #define cib__set_call_options(cib_call_opts, call_for, flags_to_set) do {   \
         cib_call_opts = pcmk__set_flags_as(__func__, __LINE__,              \
             LOG_TRACE, "CIB call", (call_for), (cib_call_opts),             \
             (flags_to_set), #flags_to_set); \
     } while (0)
 
 #define cib__clear_call_options(cib_call_opts, call_for, flags_to_clear) do {  \
         cib_call_opts = pcmk__clear_flags_as(__func__, __LINE__,               \
             LOG_TRACE, "CIB call", (call_for), (cib_call_opts),                \
             (flags_to_clear), #flags_to_clear);                                \
     } while (0)
 
 typedef int (*cib_op_t) (const char *, int, const char *, xmlNode *,
                          xmlNode *, xmlNode *, xmlNode **, xmlNode **);
 
 cib_t *cib_new_variant(void);
 
 int cib_perform_op(const char *op, int call_options, cib_op_t * fn, gboolean is_query,
                    const char *section, xmlNode * req, xmlNode * input,
                    gboolean manage_counters, gboolean * config_changed,
                    xmlNode * current_cib, xmlNode ** result_cib, xmlNode ** diff,
                    xmlNode ** output);
 
 xmlNode *cib_create_op(int call_id, const char *token, const char *op, const char *host,
                        const char *section, xmlNode * data, int call_options,
                        const char *user_name);
 
 void cib_native_callback(cib_t * cib, xmlNode * msg, int call_id, int rc);
 void cib_native_notify(gpointer data, gpointer user_data);
 int cib_native_register_notification(cib_t * cib, const char *callback, int enabled);
 gboolean cib_client_register_callback(cib_t * cib, int call_id, int timeout, gboolean only_success,
                                       void *user_data, const char *callback_name,
                                       void (*callback) (xmlNode *, int, int, xmlNode *, void *));
 gboolean cib_client_register_callback_full(cib_t *cib, int call_id,
                                            int timeout, gboolean only_success,
                                            void *user_data,
                                            const char *callback_name,
                                            void (*callback)(xmlNode *, int, int,
                                                             xmlNode *, void *),
                                            void (*free_func)(void *));
 
 int cib_process_query(const char *op, int options, const char *section, xmlNode * req,
                       xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                       xmlNode ** answer);
 
 int cib_process_erase(const char *op, int options, const char *section, xmlNode * req,
                       xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                       xmlNode ** answer);
 
 int cib_process_bump(const char *op, int options, const char *section, xmlNode * req,
                      xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                      xmlNode ** answer);
 
 int cib_process_replace(const char *op, int options, const char *section, xmlNode * req,
                         xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                         xmlNode ** answer);
 
 int cib_process_create(const char *op, int options, const char *section, xmlNode * req,
                        xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                        xmlNode ** answer);
 
 int cib_process_modify(const char *op, int options, const char *section, xmlNode * req,
                        xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                        xmlNode ** answer);
 
 int cib_process_delete(const char *op, int options, const char *section, xmlNode * req,
                        xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                        xmlNode ** answer);
 
 int cib_process_diff(const char *op, int options, const char *section, xmlNode * req,
                      xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                      xmlNode ** answer);
 
 int cib_process_upgrade(const char *op, int options, const char *section, xmlNode * req,
                         xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                         xmlNode ** answer);
 
 /*!
  * \internal
  * \brief Query or modify a CIB
  *
  * \param[in]     op            CIB_OP_* operation to be performed
  * \param[in]     options       Flag set of \c cib_call_options
  * \param[in]     section       XPath to query or modify
  * \param[in]     req           unused
  * \param[in]     input         Portion of CIB to modify (used with
  *                              PCMK__CIB_REQUEST_CREATE,
  *                              PCMK__CIB_REQUEST_MODIFY, and
  *                              CIB_OP_REPLACE)
  * \param[in]     existing_cib  Input CIB (used with PCMK__CIB_REQUEST_QUERY)
  * \param[in,out] result_cib    CIB copy to make changes in (used with
  *                              PCMK__CIB_REQUEST_CREATE,
  *                              PCMK__CIB_REQUEST_MODIFY,
- *                              CIB_OP_DELETE, and CIB_OP_REPLACE)
+ *                              PCMK__CIB_REQUEST_DELETE, and CIB_OP_REPLACE)
  * \param[out]    answer        Query result (used with PCMK__CIB_REQUEST_QUERY)
  *
  * \return Legacy Pacemaker return code
  */
 int cib_process_xpath(const char *op, int options, const char *section, xmlNode * req,
                       xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                       xmlNode ** answer);
 
 gboolean cib_config_changed(xmlNode * last, xmlNode * next, xmlNode ** diff);
 gboolean update_results(xmlNode * failed, xmlNode * target, const char *operation, int return_code);
 int cib_update_counter(xmlNode * xml_obj, const char *field, gboolean reset);
 
 int cib_internal_op(cib_t * cib, const char *op, const char *host,
                     const char *section, xmlNode * data,
                     xmlNode ** output_data, int call_options, const char *user_name);
 
 
 int cib_file_read_and_verify(const char *filename, const char *sigfile,
                              xmlNode **root);
 int cib_file_write_with_digest(xmlNode *cib_root, const char *cib_dirname,
                                const char *cib_filename);
 
 void cib__set_output(cib_t *cib, pcmk__output_t *out);
 
 cib_callback_client_t* cib__lookup_id (int call_id);
 
 /*!
  * \internal
  * \brief Connect to, query, and optionally disconnect from the CIB, returning
  *        the resulting XML object.
  *
  * \param[out] cib        If non-NULL, a pointer to where to store the CIB
  *                        connection.  In this case, it is up to the caller to
  *                        disconnect from the CIB when finished.
  * \param[out] cib_object A pointer to where to store the XML query result.
  *
  * \return A standard Pacemaker return code
  */
 int cib__signon_query(cib_t **cib, xmlNode **cib_object);
 
 int cib__clean_up_connection(cib_t **cib);
 
 int cib__update_node_attr(pcmk__output_t *out, cib_t *cib, int call_options,
                           const char *section, const char *node_uuid, const char *set_type,
                           const char *set_name, const char *attr_id, const char *attr_name,
                           const char *attr_value, const char *user_name,
                           const char *node_type);
 
 int cib__get_node_attrs(pcmk__output_t *out, cib_t *cib, const char *section,
                         const char *node_uuid, const char *set_type, const char *set_name,
                         const char *attr_id, const char *attr_name, const char *user_name,
                         xmlNode **result);
 
 int cib__delete_node_attr(pcmk__output_t *out, cib_t *cib, int options,
                           const char *section, const char *node_uuid, const char *set_type,
                           const char *set_name, const char *attr_id, const char *attr_name,
                           const char *attr_value, const char *user_name);
 
 #endif
diff --git a/lib/cib/cib_attrs.c b/lib/cib/cib_attrs.c
index c21848a5af..ee82e5affe 100644
--- a/lib/cib/cib_attrs.c
+++ b/lib/cib/cib_attrs.c
@@ -1,749 +1,749 @@
 /*
  * Copyright 2004-2022 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 <crm_internal.h>
 
 #include <sys/param.h>
 
 #include <crm/crm.h>
 
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
 
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/xml_internal.h>
 #include <crm/common/output_internal.h>
 #include <crm/cib/internal.h>
 
 /* could also check for possible truncation */
 #define attr_snprintf(_str, _offset, _limit, ...) do {              \
     _offset += snprintf(_str + _offset,                             \
                         (_limit > _offset) ? _limit - _offset : 0,  \
                         __VA_ARGS__);                               \
     } while(0)
 
 #define XPATH_MAX 1024
 
 static pcmk__output_t *
 new_output_object(const char *ty)
 {
     int rc = pcmk_rc_ok;
     pcmk__output_t *out = NULL;
     const char* argv[] = { "", NULL };
     pcmk__supported_format_t formats[] = {
         PCMK__SUPPORTED_FORMAT_LOG,
         PCMK__SUPPORTED_FORMAT_TEXT,
         { NULL, NULL, NULL }
     };
 
     pcmk__register_formats(NULL, formats);
     rc = pcmk__output_new(&out, ty, NULL, (char**)argv);
     if ((rc != pcmk_rc_ok) || (out == NULL)) {
         crm_err("Can't out due to internal error: %s", pcmk_rc_str(rc));
         return NULL;
     }
 
     return out;
 }
 
 static int
 find_attr(cib_t *cib, const char *section, const char *node_uuid,
           const char *attr_set_type, const char *set_name, const char *attr_id,
           const char *attr_name, const char *user_name, xmlNode **result)
 {
     int offset = 0;
     int rc = pcmk_rc_ok;
 
     const char *xpath_base = NULL;
     char *xpath_string = NULL;
     xmlNode *xml_search = NULL;
     const char *set_type = NULL;
     const char *node_type = NULL;
 
     if (attr_set_type) {
         set_type = attr_set_type;
     } else {
         set_type = XML_TAG_ATTR_SETS;
     }
 
     if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
         node_uuid = NULL;
         set_type = XML_CIB_TAG_PROPSET;
 
     } else if (pcmk__strcase_any_of(section, XML_CIB_TAG_OPCONFIG, XML_CIB_TAG_RSCCONFIG,
                                     NULL)) {
         node_uuid = NULL;
         set_type = XML_TAG_META_SETS;
 
     } else if (pcmk__str_eq(section, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
         node_uuid = NULL;
         section = XML_CIB_TAG_STATUS;
         node_type = XML_CIB_TAG_TICKETS;
 
     } else if (node_uuid == NULL) {
         return EINVAL;
     }
 
     xpath_base = pcmk_cib_xpath_for(section);
     if (xpath_base == NULL) {
         crm_warn("%s CIB section not known", section);
         return ENOMSG;
     }
 
     xpath_string = calloc(1, XPATH_MAX);
     if (xpath_string == NULL) {
         crm_perror(LOG_CRIT, "Could not create xpath");
         return ENOMEM;
     }
     attr_snprintf(xpath_string, offset, XPATH_MAX, "%s", xpath_base);
 
     if (pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
         attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s", node_type);
 
     } else if (node_uuid) {
         const char *node_type = XML_CIB_TAG_NODE;
 
         if (pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
             node_type = XML_CIB_TAG_STATE;
             set_type = XML_TAG_TRANSIENT_NODEATTRS;
         }
         attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s[@id='%s']", node_type,
                       node_uuid);
     }
 
     if (set_name) {
         attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s[@id='%.128s']", set_type,
                       set_name);
     } else {
         attr_snprintf(xpath_string, offset, XPATH_MAX, "//%s", set_type);
     }
 
     attr_snprintf(xpath_string, offset, XPATH_MAX, "//nvpair");
 
     if (attr_id && attr_name) {
         attr_snprintf(xpath_string, offset, XPATH_MAX, "[@id='%s' and @name='%.128s']",
                       attr_id, attr_name);
     } else if (attr_id) {
         attr_snprintf(xpath_string, offset, XPATH_MAX, "[@id='%s']", attr_id);
     } else if (attr_name) {
         attr_snprintf(xpath_string, offset, XPATH_MAX, "[@name='%.128s']", attr_name);
     }
 
     CRM_LOG_ASSERT(offset > 0);
 
     rc = cib_internal_op(cib, PCMK__CIB_REQUEST_QUERY, NULL, xpath_string, NULL,
                          &xml_search, cib_sync_call|cib_scope_local| cib_xpath,
                          user_name);
     if (rc < 0) {
         rc = pcmk_legacy2rc(rc);
         crm_trace("Query failed for attribute %s (section=%s, node=%s, set=%s, xpath=%s): %s",
                   attr_name, section, pcmk__s(node_uuid, "<null>"),
                   pcmk__s(set_name, "<null>"), xpath_string,
                   pcmk_rc_str(rc));
         goto done;
     } else {
         rc = pcmk_rc_ok;
     }
 
     crm_log_xml_debug(xml_search, "Match");
 
   done:
     free(xpath_string);
     *result = xml_search;
     return rc;
 }
 
 static int
 handle_multiples(pcmk__output_t *out, xmlNode *search, const char *attr_name)
 {
     if (xml_has_children(search)) {
         xmlNode *child = NULL;
         out->info(out, "Multiple attributes match name=%s", attr_name);
 
         for (child = pcmk__xml_first_child(search); child != NULL;
              child = pcmk__xml_next(child)) {
             out->info(out, "  Value: %s \t(id=%s)",
                       crm_element_value(child, XML_NVPAIR_ATTR_VALUE), ID(child));
         }
 
         return ENOTUNIQ;
 
     } else {
         return pcmk_rc_ok;
     }
 }
 
 int
 cib__update_node_attr(pcmk__output_t *out, cib_t *cib, int call_options, const char *section,
                       const char *node_uuid, const char *set_type, const char *set_name,
                       const char *attr_id, const char *attr_name, const char *attr_value,
                       const char *user_name, const char *node_type)
 {
     const char *tag = NULL;
     int rc = pcmk_rc_ok;
     xmlNode *xml_top = NULL;
     xmlNode *xml_obj = NULL;
     xmlNode *xml_search = NULL;
 
     char *local_attr_id = NULL;
     char *local_set_name = NULL;
 
     CRM_CHECK(section != NULL, return EINVAL);
     CRM_CHECK(attr_value != NULL, return EINVAL);
     CRM_CHECK(attr_name != NULL || attr_id != NULL, return EINVAL);
 
     rc = find_attr(cib, section, node_uuid, set_type, set_name, attr_id,
                    attr_name, user_name, &xml_search);
 
     if (rc == pcmk_rc_ok) {
         if (handle_multiples(out, xml_search, attr_name) == ENOTUNIQ) {
             free_xml(xml_search);
             return ENOTUNIQ;
         } else {
             pcmk__str_update(&local_attr_id, crm_element_value(xml_search, XML_ATTR_ID));
             attr_id = local_attr_id;
             free_xml(xml_search);
             goto do_modify;
         }
 
     } else if (rc != ENXIO) {
         free_xml(xml_search);
         return rc;
 
         /* } else if(attr_id == NULL) { */
         /*     return EINVAL; */
 
     } else {
         free_xml(xml_search);
         crm_trace("%s does not exist, create it", attr_name);
         if (pcmk__str_eq(section, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
             node_uuid = NULL;
             section = XML_CIB_TAG_STATUS;
             node_type = XML_CIB_TAG_TICKETS;
 
             xml_top = create_xml_node(xml_obj, XML_CIB_TAG_STATUS);
             xml_obj = create_xml_node(xml_top, XML_CIB_TAG_TICKETS);
 
         } else if (pcmk__str_eq(section, XML_CIB_TAG_NODES, pcmk__str_casei)) {
 
             if (node_uuid == NULL) {
                 return EINVAL;
             }
 
             if (pcmk__str_eq(node_type, "remote", pcmk__str_casei)) {
                 xml_top = create_xml_node(xml_obj, XML_CIB_TAG_NODES);
                 xml_obj = create_xml_node(xml_top, XML_CIB_TAG_NODE);
                 crm_xml_add(xml_obj, XML_ATTR_TYPE, "remote");
                 crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid);
                 crm_xml_add(xml_obj, XML_ATTR_UNAME, node_uuid);
             } else {
                 tag = XML_CIB_TAG_NODE;
             }
 
         } else if (pcmk__str_eq(section, XML_CIB_TAG_STATUS, pcmk__str_casei)) {
             tag = XML_TAG_TRANSIENT_NODEATTRS;
             if (node_uuid == NULL) {
                 return EINVAL;
             }
 
             xml_top = create_xml_node(xml_obj, XML_CIB_TAG_STATE);
             crm_xml_add(xml_top, XML_ATTR_ID, node_uuid);
             xml_obj = xml_top;
 
         } else {
             tag = section;
             node_uuid = NULL;
         }
 
         if (set_name == NULL) {
             if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
                 local_set_name = strdup(CIB_OPTIONS_FIRST);
 
             } else if (pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
                 local_set_name = crm_strdup_printf("%s-%s", section,
                                                    XML_CIB_TAG_TICKETS);
 
             } else if (node_uuid) {
                 local_set_name = crm_strdup_printf("%s-%s", section, node_uuid);
 
                 if (set_type) {
                     char *tmp_set_name = local_set_name;
 
                     local_set_name = crm_strdup_printf("%s-%s", tmp_set_name,
                                                        set_type);
                     free(tmp_set_name);
                 }
             } else {
                 local_set_name = crm_strdup_printf("%s-options", section);
             }
             set_name = local_set_name;
         }
 
         if (attr_id == NULL) {
             local_attr_id = crm_strdup_printf("%s-%s", set_name, attr_name);
             crm_xml_sanitize_id(local_attr_id);
             attr_id = local_attr_id;
 
         } else if (attr_name == NULL) {
             attr_name = attr_id;
         }
 
         crm_trace("Creating %s/%s", section, tag);
         if (tag != NULL) {
             xml_obj = create_xml_node(xml_obj, tag);
             crm_xml_add(xml_obj, XML_ATTR_ID, node_uuid);
             if (xml_top == NULL) {
                 xml_top = xml_obj;
             }
         }
 
         if (node_uuid == NULL && !pcmk__str_eq(node_type, XML_CIB_TAG_TICKETS, pcmk__str_casei)) {
             if (pcmk__str_eq(section, XML_CIB_TAG_CRMCONFIG, pcmk__str_casei)) {
                 xml_obj = create_xml_node(xml_obj, XML_CIB_TAG_PROPSET);
             } else {
                 xml_obj = create_xml_node(xml_obj, XML_TAG_META_SETS);
             }
 
         } else if (set_type) {
             xml_obj = create_xml_node(xml_obj, set_type);
 
         } else {
             xml_obj = create_xml_node(xml_obj, XML_TAG_ATTR_SETS);
         }
         crm_xml_add(xml_obj, XML_ATTR_ID, set_name);
 
         if (xml_top == NULL) {
             xml_top = xml_obj;
         }
     }
 
   do_modify:
     xml_obj = crm_create_nvpair_xml(xml_obj, attr_id, attr_name, attr_value);
     if (xml_top == NULL) {
         xml_top = xml_obj;
     }
 
     crm_log_xml_trace(xml_top, "update_attr");
     rc = cib_internal_op(cib, PCMK__CIB_REQUEST_MODIFY, NULL, section, xml_top,
                          NULL, call_options|cib_quorum_override, user_name);
     if (rc < 0) {
         rc = pcmk_legacy2rc(rc);
 
         out->err(out, "Error setting %s=%s (section=%s, set=%s): %s",
                  attr_name, attr_value, section, pcmk__s(set_name, "<null>"),
                  pcmk_rc_str(rc));
         crm_log_xml_info(xml_top, "Update");
     } else {
         rc = pcmk_rc_ok;
     }
 
     free(local_set_name);
     free(local_attr_id);
     free_xml(xml_top);
 
     return rc;
 }
 
 int
 cib__get_node_attrs(pcmk__output_t *out, cib_t *cib, const char *section,
                     const char *node_uuid, const char *set_type, const char *set_name,
                     const char *attr_id, const char *attr_name, const char *user_name,
                     xmlNode **result)
 {
     int rc = pcmk_rc_ok;
 
     CRM_ASSERT(result != NULL);
     CRM_CHECK(section != NULL, return EINVAL);
 
     *result = NULL;
 
     rc = find_attr(cib, section, node_uuid, set_type, set_name, attr_id, attr_name,
                    user_name, result);
 
     if (rc != pcmk_rc_ok) {
         crm_trace("Query failed for attribute %s (section=%s node=%s set=%s): %s",
                   pcmk__s(attr_name, "with unspecified name"),
                   section, pcmk__s(set_name, "<null>"),
                   pcmk__s(node_uuid, "<null>"), pcmk_strerror(rc));
     }
 
     return rc;
 }
 
 int
 cib__delete_node_attr(pcmk__output_t *out, cib_t *cib, int options, const char *section,
                       const char *node_uuid, const char *set_type, const char *set_name,
                       const char *attr_id, const char *attr_name, const char *attr_value,
                       const char *user_name)
 {
     int rc = pcmk_rc_ok;
     xmlNode *xml_obj = NULL;
     xmlNode *xml_search = NULL;
     char *local_attr_id = NULL;
 
     CRM_CHECK(section != NULL, return EINVAL);
     CRM_CHECK(attr_name != NULL || attr_id != NULL, return EINVAL);
 
     if (attr_id == NULL) {
         rc = find_attr(cib, section, node_uuid, set_type, set_name, attr_id,
                        attr_name, user_name, &xml_search);
 
         if (rc != pcmk_rc_ok || handle_multiples(out, xml_search, attr_name) == ENOTUNIQ) {
             free_xml(xml_search);
             return rc;
         } else {
             pcmk__str_update(&local_attr_id, crm_element_value(xml_search, XML_ATTR_ID));
             attr_id = local_attr_id;
             free_xml(xml_search);
         }
     }
 
     xml_obj = crm_create_nvpair_xml(NULL, attr_id, attr_name, attr_value);
 
-    rc = cib_internal_op(cib, CIB_OP_DELETE, NULL, section, xml_obj, NULL,
-                         options | cib_quorum_override, user_name);
+    rc = cib_internal_op(cib, PCMK__CIB_REQUEST_DELETE, NULL, section, xml_obj,
+                         NULL, options|cib_quorum_override, user_name);
     if (rc < 0) {
         rc = pcmk_legacy2rc(rc);
     } else {
         rc = pcmk_rc_ok;
         out->info(out, "Deleted %s %s: id=%s%s%s%s%s",
                   section, node_uuid ? "attribute" : "option", local_attr_id,
                   set_name ? " set=" : "", set_name ? set_name : "",
                   attr_name ? " name=" : "", attr_name ? attr_name : "");
     }
 
     free(local_attr_id);
     free_xml(xml_obj);
     return rc;
 }
 
 int
 find_nvpair_attr_delegate(cib_t *cib, const char *attr, const char *section,
                           const char *node_uuid, const char *attr_set_type, const char *set_name,
                           const char *attr_id, const char *attr_name, gboolean to_console,
                           char **value, const char *user_name)
 {
     pcmk__output_t *out = NULL;
     xmlNode *xml_search = NULL;
     int rc = pcmk_ok;
 
     out = new_output_object(to_console ? "text" : "log");
     if (out == NULL) {
         return pcmk_err_generic;
     }
 
     rc = find_attr(cib, section, node_uuid, attr_set_type, set_name, attr_id,
                    attr_name, user_name, &xml_search);
 
     if (rc == pcmk_rc_ok) {
         rc = handle_multiples(out, xml_search, attr_name);
 
         if (rc == pcmk_rc_ok) {
             pcmk__str_update(value, crm_element_value(xml_search, attr));
         }
     }
 
     out->finish(out, CRM_EX_OK, true, NULL);
     free_xml(xml_search);
     pcmk__output_free(out);
     return pcmk_rc2legacy(rc);
 }
 
 int
 update_attr_delegate(cib_t *cib, int call_options, const char *section,
                      const char *node_uuid, const char *set_type, const char *set_name,
                      const char *attr_id, const char *attr_name, const char *attr_value,
                      gboolean to_console, const char *user_name, const char *node_type)
 {
     pcmk__output_t *out = NULL;
     int rc = pcmk_ok;
 
     out = new_output_object(to_console ? "text" : "log");
     if (out == NULL) {
         return pcmk_err_generic;
     }
 
     rc = cib__update_node_attr(out, cib, call_options, section, node_uuid, set_type,
                                set_name, attr_id, attr_name, attr_value, user_name,
                                node_type);
 
     out->finish(out, CRM_EX_OK, true, NULL);
     pcmk__output_free(out);
     return pcmk_rc2legacy(rc);
 }
 
 int
 read_attr_delegate(cib_t *cib, const char *section, const char *node_uuid,
                    const char *set_type, const char *set_name, const char *attr_id,
                    const char *attr_name, char **attr_value, gboolean to_console,
                    const char *user_name)
 {
     pcmk__output_t *out = NULL;
     xmlNode *result = NULL;
     int rc = pcmk_ok;
 
     out = new_output_object(to_console ? "text" : "log");
     if (out == NULL) {
         return pcmk_err_generic;
     }
 
     rc = cib__get_node_attrs(out, cib, section, node_uuid, set_type, set_name,
                              attr_id, attr_name, user_name, &result);
 
     if (rc == pcmk_rc_ok) {
         if (!xml_has_children(result)) {
             pcmk__str_update(attr_value, crm_element_value(result, XML_NVPAIR_ATTR_VALUE));
         } else {
             rc = ENOTUNIQ;
         }
     }
 
     out->finish(out, CRM_EX_OK, true, NULL);
     free_xml(result);
     pcmk__output_free(out);
     return pcmk_rc2legacy(rc);
 }
 
 int
 delete_attr_delegate(cib_t *cib, int options, const char *section, const char *node_uuid,
                      const char *set_type, const char *set_name, const char *attr_id,
                      const char *attr_name, const char *attr_value, gboolean to_console,
                      const char *user_name)
 {
     pcmk__output_t *out = NULL;
     int rc = pcmk_ok;
 
     out = new_output_object(to_console ? "text" : "log");
     if (out == NULL) {
         return pcmk_err_generic;
     }
 
     rc = cib__delete_node_attr(out, cib, options, section, node_uuid, set_type,
                                set_name, attr_id, attr_name, attr_value, user_name);
 
     out->finish(out, CRM_EX_OK, true, NULL);
     pcmk__output_free(out);
     return pcmk_rc2legacy(rc);
 }
 
 /*!
  * \internal
  * \brief Parse node UUID from search result
  *
  * \param[in]  result     XML search result
  * \param[out] uuid       If non-NULL, where to store parsed UUID
  * \param[out] is_remote  If non-NULL, set TRUE if result is remote node
  *
  * \return pcmk_ok if UUID was successfully parsed, -ENXIO otherwise
  */
 static int
 get_uuid_from_result(xmlNode *result, char **uuid, int *is_remote)
 {
     int rc = -ENXIO;
     const char *tag;
     const char *parsed_uuid = NULL;
     int parsed_is_remote = FALSE;
 
     if (result == NULL) {
         return rc;
     }
 
     /* If there are multiple results, the first is sufficient */
     tag = (const char *) (result->name);
     if (pcmk__str_eq(tag, "xpath-query", pcmk__str_casei)) {
         result = pcmk__xml_first_child(result);
         CRM_CHECK(result != NULL, return rc);
         tag = (const char *) (result->name);
     }
 
     if (pcmk__str_eq(tag, XML_CIB_TAG_NODE, pcmk__str_casei)) {
         /* Result is <node> tag from <nodes> section */
 
         if (pcmk__str_eq(crm_element_value(result, XML_ATTR_TYPE), "remote", pcmk__str_casei)) {
             parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
             parsed_is_remote = TRUE;
         } else {
             parsed_uuid = ID(result);
             parsed_is_remote = FALSE;
         }
 
     } else if (pcmk__str_eq(tag, XML_CIB_TAG_RESOURCE, pcmk__str_casei)) {
         /* Result is <primitive> for ocf:pacemaker:remote resource */
 
         parsed_uuid = ID(result);
         parsed_is_remote = TRUE;
 
     } else if (pcmk__str_eq(tag, XML_CIB_TAG_NVPAIR, pcmk__str_casei)) {
         /* Result is remote-node parameter of <primitive> for guest node */
 
         parsed_uuid = crm_element_value(result, XML_NVPAIR_ATTR_VALUE);
         parsed_is_remote = TRUE;
 
     } else if (pcmk__str_eq(tag, XML_CIB_TAG_STATE, pcmk__str_casei)) {
         /* Result is <node_state> tag from <status> section */
 
         parsed_uuid = crm_element_value(result, XML_ATTR_UNAME);
         if (pcmk__xe_attr_is_true(result, XML_NODE_IS_REMOTE)) {
             parsed_is_remote = TRUE;
         }
     }
 
     if (parsed_uuid) {
         if (uuid) {
             *uuid = strdup(parsed_uuid);
         }
         if (is_remote) {
             *is_remote = parsed_is_remote;
         }
         rc = pcmk_ok;
     }
 
     return rc;
 }
 
 /* Search string to find a node by name, as:
  * - cluster or remote node in nodes section
  * - remote node in resources section
  * - guest node in resources section
  * - orphaned remote node or bundle guest node in status section
  */
 #define XPATH_UPPER_TRANS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 #define XPATH_LOWER_TRANS "abcdefghijklmnopqrstuvwxyz"
 #define XPATH_NODE \
     "/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES \
         "/" XML_CIB_TAG_NODE "[translate(@" XML_ATTR_UNAME ",'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
     "|/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_RESOURCES \
         "/" XML_CIB_TAG_RESOURCE \
         "[@class='ocf'][@provider='pacemaker'][@type='remote'][translate(@id,'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
     "|/" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_RESOURCES \
         "/" XML_CIB_TAG_RESOURCE "/" XML_TAG_META_SETS "/" XML_CIB_TAG_NVPAIR \
         "[@name='" XML_RSC_ATTR_REMOTE_NODE "'][translate(@value,'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']" \
     "|/" XML_TAG_CIB "/" XML_CIB_TAG_STATUS "/" XML_CIB_TAG_STATE \
         "[@" XML_NODE_IS_REMOTE "='true'][translate(@" XML_ATTR_UUID ",'" XPATH_UPPER_TRANS "','" XPATH_LOWER_TRANS "') ='%s']"
 
 int
 query_node_uuid(cib_t * the_cib, const char *uname, char **uuid, int *is_remote_node)
 {
     int rc = pcmk_ok;
     char *xpath_string;
     xmlNode *xml_search = NULL;
     char *host_lowercase = NULL;
 
     CRM_ASSERT(uname != NULL);
 
     host_lowercase = g_ascii_strdown(uname, -1);
 
     if (uuid) {
         *uuid = NULL;
     }
     if (is_remote_node) {
         *is_remote_node = FALSE;
     }
 
     xpath_string = crm_strdup_printf(XPATH_NODE, host_lowercase, host_lowercase, host_lowercase, host_lowercase);
     if (cib_internal_op(the_cib, PCMK__CIB_REQUEST_QUERY, NULL, xpath_string,
                         NULL, &xml_search,
                         cib_sync_call|cib_scope_local|cib_xpath,
                         NULL) == pcmk_ok) {
         rc = get_uuid_from_result(xml_search, uuid, is_remote_node);
     } else {
         rc = -ENXIO;
     }
     free(xpath_string);
     free_xml(xml_search);
     g_free(host_lowercase);
 
     if (rc != pcmk_ok) {
         crm_debug("Could not map node name '%s' to a UUID: %s",
                   uname, pcmk_strerror(rc));
     } else {
         crm_info("Mapped node name '%s' to UUID %s", uname, (uuid? *uuid : ""));
     }
     return rc;
 }
 
 int
 query_node_uname(cib_t * the_cib, const char *uuid, char **uname)
 {
     int rc = pcmk_ok;
     xmlNode *a_child = NULL;
     xmlNode *xml_obj = NULL;
     xmlNode *fragment = NULL;
     const char *child_name = NULL;
 
     CRM_ASSERT(uname != NULL);
     CRM_ASSERT(uuid != NULL);
 
     rc = the_cib->cmds->query(the_cib, XML_CIB_TAG_NODES, &fragment,
                               cib_sync_call | cib_scope_local);
     if (rc != pcmk_ok) {
         return rc;
     }
 
     xml_obj = fragment;
     CRM_CHECK(pcmk__str_eq(crm_element_name(xml_obj), XML_CIB_TAG_NODES, pcmk__str_casei),
               return -ENOMSG);
     CRM_ASSERT(xml_obj != NULL);
     crm_log_xml_trace(xml_obj, "Result section");
 
     rc = -ENXIO;
     *uname = NULL;
 
     for (a_child = pcmk__xml_first_child(xml_obj); a_child != NULL;
          a_child = pcmk__xml_next(a_child)) {
 
         if (pcmk__str_eq((const char *)a_child->name, XML_CIB_TAG_NODE,
                          pcmk__str_none)) {
             child_name = ID(a_child);
             if (pcmk__str_eq(uuid, child_name, pcmk__str_casei)) {
                 child_name = crm_element_value(a_child, XML_ATTR_UNAME);
                 if (child_name != NULL) {
                     *uname = strdup(child_name);
                     rc = pcmk_ok;
                 }
                 break;
             }
         }
     }
 
     free_xml(fragment);
     return rc;
 }
 
 int
 set_standby(cib_t * the_cib, const char *uuid, const char *scope, const char *standby_value)
 {
     int rc = pcmk_ok;
     char *attr_id = NULL;
 
     CRM_CHECK(uuid != NULL, return -EINVAL);
     CRM_CHECK(standby_value != NULL, return -EINVAL);
 
     if (pcmk__strcase_any_of(scope, "reboot", XML_CIB_TAG_STATUS, NULL)) {
         scope = XML_CIB_TAG_STATUS;
         attr_id = crm_strdup_printf("transient-standby-%.256s", uuid);
 
     } else {
         scope = XML_CIB_TAG_NODES;
         attr_id = crm_strdup_printf("standby-%.256s", uuid);
     }
 
     rc = update_attr_delegate(the_cib, cib_sync_call, scope, uuid, NULL, NULL,
                               attr_id, "standby", standby_value, TRUE, NULL, NULL);
 
     free(attr_id);
     return rc;
 }
diff --git a/lib/cib/cib_client.c b/lib/cib/cib_client.c
index ce1953a283..ec276cf32e 100644
--- a/lib/cib/cib_client.c
+++ b/lib/cib/cib_client.c
@@ -1,714 +1,715 @@
 /*
  * Copyright 2004-2022 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 <crm_internal.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
 #include <pwd.h>
 
 #include <sys/stat.h>
 #include <sys/types.h>
 
 #include <glib.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 
 static GHashTable *cib_op_callback_table = NULL;
 
 int cib_client_set_op_callback(cib_t * cib, void (*callback) (const xmlNode * msg, int call_id,
                                                               int rc, xmlNode * output));
 
 int cib_client_add_notify_callback(cib_t * cib, const char *event,
                                    void (*callback) (const char *event, xmlNode * msg));
 
 int cib_client_del_notify_callback(cib_t * cib, const char *event,
                                    void (*callback) (const char *event, xmlNode * msg));
 
 gint ciblib_GCompareFunc(gconstpointer a, gconstpointer b);
 
 #define op_common(cib) do {                                             \
         if(cib == NULL) {                                               \
             return -EINVAL;						\
         } else if(cib->delegate_fn == NULL) {                           \
             return -EPROTONOSUPPORT;                                    \
         }                                                               \
     } while(0)
 
 static int
 cib_client_noop(cib_t * cib, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, CRM_OP_NOOP, NULL, NULL, NULL, NULL, call_options, NULL);
 }
 
 static int
 cib_client_ping(cib_t * cib, xmlNode ** output_data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, CRM_OP_PING, NULL, NULL, NULL, output_data, call_options, NULL);
 }
 
 static int
 cib_client_query(cib_t * cib, const char *section, xmlNode ** output_data, int call_options)
 {
     return cib->cmds->query_from(cib, NULL, section, output_data, call_options);
 }
 
 static int
 cib_client_query_from(cib_t * cib, const char *host, const char *section,
                       xmlNode ** output_data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_QUERY, host, section, NULL,
                            output_data, call_options, NULL);
 }
 
 static int
 cib_client_is_master(cib_t * cib)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_IS_PRIMARY, NULL, NULL, NULL,
                            NULL, cib_scope_local|cib_sync_call, NULL);
 }
 
 static int
 cib_client_set_slave(cib_t * cib, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_SECONDARY, NULL, NULL, NULL,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_set_slave_all(cib_t * cib, int call_options)
 {
     return -EPROTONOSUPPORT;
 }
 
 static int
 cib_client_set_master(cib_t * cib, int call_options)
 {
     op_common(cib);
     crm_trace("Adding cib_scope_local to options");
     return cib_internal_op(cib, PCMK__CIB_REQUEST_PRIMARY, NULL, NULL, NULL,
                            NULL, call_options|cib_scope_local, NULL);
 }
 
 static int
 cib_client_bump_epoch(cib_t * cib, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_BUMP, NULL, NULL, NULL, NULL,
                            call_options, NULL);
 }
 
 static int
 cib_client_upgrade(cib_t * cib, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, CIB_OP_UPGRADE, NULL, NULL, NULL, NULL, call_options, NULL);
 }
 
 static int
 cib_client_sync(cib_t * cib, const char *section, int call_options)
 {
     return cib->cmds->sync_from(cib, NULL, section, call_options);
 }
 
 static int
 cib_client_sync_from(cib_t * cib, const char *host, const char *section, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_SYNC_TO_ALL, host, section,
                            NULL, NULL, call_options, NULL);
 }
 
 static int
 cib_client_create(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_CREATE, NULL, section, data,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_modify(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_MODIFY, NULL, section, data,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_update(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, PCMK__CIB_REQUEST_MODIFY, NULL, section, data,
                            NULL, call_options, NULL);
 }
 
 static int
 cib_client_replace(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, CIB_OP_REPLACE, NULL, section, data, NULL, call_options, NULL);
 }
 
 static int
 cib_client_delete(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
-    return cib_internal_op(cib, CIB_OP_DELETE, NULL, section, data, NULL, call_options, NULL);
+    return cib_internal_op(cib, PCMK__CIB_REQUEST_DELETE, NULL, section, data,
+                           NULL, call_options, NULL);
 }
 
 static int
 cib_client_delete_absolute(cib_t * cib, const char *section, xmlNode * data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, CIB_OP_DELETE_ALT, NULL, section, data, NULL, call_options, NULL);
 }
 
 static int
 cib_client_erase(cib_t * cib, xmlNode ** output_data, int call_options)
 {
     op_common(cib);
     return cib_internal_op(cib, CIB_OP_ERASE, NULL, NULL, NULL, output_data, call_options, NULL);
 }
 
 static void
 cib_destroy_op_callback(gpointer data)
 {
     cib_callback_client_t *blob = data;
 
     if (blob->timer && blob->timer->ref > 0) {
         g_source_remove(blob->timer->ref);
     }
     free(blob->timer);
 
     if (blob->user_data && blob->free_func) {
         blob->free_func(blob->user_data);
     }
 
     free(blob);
 }
 
 static void
 destroy_op_callback_table(void)
 {
     if (cib_op_callback_table != NULL) {
         g_hash_table_destroy(cib_op_callback_table);
         cib_op_callback_table = NULL;
     }
 }
 
 char *
 get_shadow_file(const char *suffix)
 {
     char *cib_home = NULL;
     char *fullname = NULL;
     char *name = crm_strdup_printf("shadow.%s", suffix);
     const char *dir = getenv("CIB_shadow_dir");
 
     if (dir == NULL) {
         uid_t uid = geteuid();
         struct passwd *pwent = getpwuid(uid);
         const char *user = NULL;
 
         if (pwent) {
             user = pwent->pw_name;
         } else {
             user = getenv("USER");
             crm_perror(LOG_ERR,
                        "Assuming %s because cannot get user details for user ID %d",
                        (user? user : "unprivileged user"), uid);
         }
 
         if (pcmk__strcase_any_of(user, "root", CRM_DAEMON_USER, NULL)) {
             dir = CRM_CONFIG_DIR;
 
         } else {
             const char *home = NULL;
 
             if ((home = getenv("HOME")) == NULL) {
                 if (pwent) {
                     home = pwent->pw_dir;
                 }
             }
 
             dir = pcmk__get_tmpdir();
             if (home && home[0] == '/') {
                 int rc = 0;
 
                 cib_home = crm_strdup_printf("%s/.cib", home);
 
                 rc = mkdir(cib_home, 0700);
                 if (rc < 0 && errno != EEXIST) {
                     crm_perror(LOG_ERR, "Couldn't create user-specific shadow directory: %s",
                                cib_home);
                     errno = 0;
 
                 } else {
                     dir = cib_home;
                 }
             }
         }
     }
 
     fullname = crm_strdup_printf("%s/%s", dir, name);
     free(cib_home);
     free(name);
 
     return fullname;
 }
 
 cib_t *
 cib_shadow_new(const char *shadow)
 {
     cib_t *new_cib = NULL;
     char *shadow_file = NULL;
 
     CRM_CHECK(shadow != NULL, return NULL);
 
     shadow_file = get_shadow_file(shadow);
     new_cib = cib_file_new(shadow_file);
     free(shadow_file);
 
     return new_cib;
 }
 
 cib_t *
 cib_new_no_shadow(void)
 {
     unsetenv("CIB_shadow");
     return cib_new();
 }
 
 cib_t *
 cib_new(void)
 {
     const char *value = getenv("CIB_shadow");
     int port;
 
     if (value && value[0] != 0) {
         return cib_shadow_new(value);
     }
 
     value = getenv("CIB_file");
     if (value) {
         return cib_file_new(value);
     }
 
     value = getenv("CIB_port");
     if (value) {
         gboolean encrypted = TRUE;
         const char *server = getenv("CIB_server");
         const char *user = getenv("CIB_user");
         const char *pass = getenv("CIB_passwd");
 
         /* We don't ensure port is valid (>= 0) because cib_new() currently
          * can't return NULL in practice, and introducing a NULL return here
          * could cause core dumps that would previously just cause signon()
          * failures.
          */
         pcmk__scan_port(value, &port);
 
         value = getenv("CIB_encrypted");
         if (value && crm_is_true(value) == FALSE) {
             crm_info("Disabling TLS");
             encrypted = FALSE;
         }
 
         if (user == NULL) {
             user = CRM_DAEMON_USER;
             crm_info("Defaulting to user: %s", user);
         }
 
         if (server == NULL) {
             server = "localhost";
             crm_info("Defaulting to localhost");
         }
 
         return cib_remote_new(server, user, pass, port, encrypted);
     }
 
     return cib_native_new();
 }
 
 /*!
  * \internal
  * \brief Create a generic CIB connection instance
  *
  * \return Newly allocated and initialized cib_t instance
  *
  * \note This is called by each variant's cib_*_new() function before setting
  *       variant-specific values.
  */
 cib_t *
 cib_new_variant(void)
 {
     cib_t *new_cib = NULL;
 
     new_cib = calloc(1, sizeof(cib_t));
 
     if (new_cib == NULL) {
         return NULL;
     }
 
     remove_cib_op_callback(0, TRUE); /* remove all */
 
     new_cib->call_id = 1;
     new_cib->variant = cib_undefined;
 
     new_cib->type = cib_no_connection;
     new_cib->state = cib_disconnected;
 
     new_cib->op_callback = NULL;
     new_cib->variant_opaque = NULL;
     new_cib->notify_list = NULL;
 
     /* the rest will get filled in by the variant constructor */
     new_cib->cmds = calloc(1, sizeof(cib_api_operations_t));
 
     if (new_cib->cmds == NULL) {
         free(new_cib);
         return NULL;
     }
 
     new_cib->cmds->set_op_callback = cib_client_set_op_callback;
     new_cib->cmds->add_notify_callback = cib_client_add_notify_callback;
     new_cib->cmds->del_notify_callback = cib_client_del_notify_callback;
     new_cib->cmds->register_callback = cib_client_register_callback;
     new_cib->cmds->register_callback_full = cib_client_register_callback_full;
 
     new_cib->cmds->noop = cib_client_noop;
     new_cib->cmds->ping = cib_client_ping;
     new_cib->cmds->query = cib_client_query;
     new_cib->cmds->sync = cib_client_sync;
 
     new_cib->cmds->query_from = cib_client_query_from;
     new_cib->cmds->sync_from = cib_client_sync_from;
 
     new_cib->cmds->is_master = cib_client_is_master;
     new_cib->cmds->set_master = cib_client_set_master;
     new_cib->cmds->set_slave = cib_client_set_slave;
     new_cib->cmds->set_slave_all = cib_client_set_slave_all;
 
     new_cib->cmds->upgrade = cib_client_upgrade;
     new_cib->cmds->bump_epoch = cib_client_bump_epoch;
 
     new_cib->cmds->create = cib_client_create;
     new_cib->cmds->modify = cib_client_modify;
     new_cib->cmds->update = cib_client_update;
     new_cib->cmds->replace = cib_client_replace;
     new_cib->cmds->remove = cib_client_delete;
     new_cib->cmds->erase = cib_client_erase;
 
     new_cib->cmds->delete_absolute = cib_client_delete_absolute;
 
     return new_cib;
 }
 
 void 
 cib_free_notify(cib_t *cib)
 {
 
     if (cib) {
         GList *list = cib->notify_list;
 
         while (list != NULL) {
             cib_notify_client_t *client = g_list_nth_data(list, 0);
 
             list = g_list_remove(list, client);
             free(client);
         }
         cib->notify_list = NULL;
     }
 }
 /*!
  * \brief Free all callbacks for a CIB connection
  *
  * \param[in] cib  CIB connection to clean up
  */
 void
 cib_free_callbacks(cib_t *cib)
 {
     cib_free_notify(cib);
 
     destroy_op_callback_table();
 }
 
 /*!
  * \brief Free all memory used by CIB connection
  *
  * \param[in] cib  CIB connection to delete
  */
 void
 cib_delete(cib_t *cib)
 {
     cib_free_callbacks(cib);
     if (cib) {
         cib->cmds->free(cib);
     }
 }
 
 int
 cib_client_set_op_callback(cib_t * cib, void (*callback) (const xmlNode * msg, int call_id,
                                                           int rc, xmlNode * output))
 {
     if (callback == NULL) {
         crm_info("Un-Setting operation callback");
 
     } else {
         crm_trace("Setting operation callback");
     }
     cib->op_callback = callback;
     return pcmk_ok;
 }
 
 int
 cib_client_add_notify_callback(cib_t * cib, const char *event,
                                void (*callback) (const char *event, xmlNode * msg))
 {
     GList *list_item = NULL;
     cib_notify_client_t *new_client = NULL;
 
     if (cib->variant != cib_native && cib->variant != cib_remote) {
         return -EPROTONOSUPPORT;
     }
 
     crm_trace("Adding callback for %s events (%d)", event, g_list_length(cib->notify_list));
 
     new_client = calloc(1, sizeof(cib_notify_client_t));
     new_client->event = event;
     new_client->callback = callback;
 
     list_item = g_list_find_custom(cib->notify_list, new_client, ciblib_GCompareFunc);
 
     if (list_item != NULL) {
         crm_warn("Callback already present");
         free(new_client);
         return -EINVAL;
 
     } else {
         cib->notify_list = g_list_append(cib->notify_list, new_client);
 
         cib->cmds->register_notification(cib, event, 1);
 
         crm_trace("Callback added (%d)", g_list_length(cib->notify_list));
     }
     return pcmk_ok;
 }
 
 static int 
 get_notify_list_event_count(cib_t * cib, const char *event)
 {
     GList *l = NULL;
     int count = 0;
 
     for (l = g_list_first(cib->notify_list); l; l = g_list_next(l)) {
         cib_notify_client_t *client = (cib_notify_client_t *)l->data;
         
         if (strcmp(client->event, event) == 0) {
             count++;
         }
     }
     crm_trace("event(%s) count : %d", event, count);
     return count;
 }
 
 int
 cib_client_del_notify_callback(cib_t * cib, const char *event,
                                void (*callback) (const char *event, xmlNode * msg))
 {
     GList *list_item = NULL;
     cib_notify_client_t *new_client = NULL;
 
     if (cib->variant != cib_native && cib->variant != cib_remote) {
         return -EPROTONOSUPPORT;
     }
 
     if (get_notify_list_event_count(cib, event) == 0) {
         crm_debug("The callback of the event does not exist(%s)", event);
         return pcmk_ok;
     }
 
     crm_debug("Removing callback for %s events", event);
 
     new_client = calloc(1, sizeof(cib_notify_client_t));
     new_client->event = event;
     new_client->callback = callback;
 
     list_item = g_list_find_custom(cib->notify_list, new_client, ciblib_GCompareFunc);
 
     if (list_item != NULL) {
         cib_notify_client_t *list_client = list_item->data;
 
         cib->notify_list = g_list_remove(cib->notify_list, list_client);
         free(list_client);
 
         crm_trace("Removed callback");
 
     } else {
         crm_trace("Callback not present");
     }
 
     if (get_notify_list_event_count(cib, event) == 0) {
         /* When there is not the registration of the event, the processing turns off a notice. */
         cib->cmds->register_notification(cib, event, 0);
     }
 
     free(new_client);
     return pcmk_ok;
 }
 
 gint
 ciblib_GCompareFunc(gconstpointer a, gconstpointer b)
 {
     int rc = 0;
     const cib_notify_client_t *a_client = a;
     const cib_notify_client_t *b_client = b;
 
     CRM_CHECK(a_client->event != NULL && b_client->event != NULL, return 0);
     rc = strcmp(a_client->event, b_client->event);
     if (rc == 0) {
         if (a_client->callback == b_client->callback) {
             return 0;
         } else if (((long)a_client->callback) < ((long)b_client->callback)) {
             crm_trace("callbacks for %s are not equal: %p < %p",
                       a_client->event, a_client->callback, b_client->callback);
             return -1;
         }
         crm_trace("callbacks for %s are not equal: %p > %p",
                   a_client->event, a_client->callback, b_client->callback);
         return 1;
     }
     return rc;
 }
 
 static gboolean
 cib_async_timeout_handler(gpointer data)
 {
     struct timer_rec_s *timer = data;
 
     crm_debug("Async call %d timed out after %ds", timer->call_id, timer->timeout);
     cib_native_callback(timer->cib, NULL, timer->call_id, -ETIME);
 
     /* Always return TRUE, never remove the handler
      * We do that in remove_cib_op_callback()
      */
     return TRUE;
 }
 
 gboolean
 cib_client_register_callback(cib_t * cib, int call_id, int timeout, gboolean only_success,
                              void *user_data, const char *callback_name,
                              void (*callback) (xmlNode *, int, int, xmlNode *, void *))
 {
     return cib_client_register_callback_full(cib, call_id, timeout,
                                              only_success, user_data,
                                              callback_name, callback, NULL);
 }
 
 gboolean
 cib_client_register_callback_full(cib_t *cib, int call_id, int timeout,
                                   gboolean only_success, void *user_data,
                                   const char *callback_name,
                                   void (*callback)(xmlNode *, int, int,
                                                    xmlNode *, void *),
                                   void (*free_func)(void *))
 {
     cib_callback_client_t *blob = NULL;
 
     if (call_id < 0) {
         if (only_success == FALSE) {
             callback(NULL, call_id, call_id, NULL, user_data);
         } else {
             crm_warn("CIB call failed: %s", pcmk_strerror(call_id));
         }
         if (user_data && free_func) {
             free_func(user_data);
         }
         return FALSE;
     }
 
     blob = calloc(1, sizeof(cib_callback_client_t));
     blob->id = callback_name;
     blob->only_success = only_success;
     blob->user_data = user_data;
     blob->callback = callback;
     blob->free_func = free_func;
 
     if (timeout > 0) {
         struct timer_rec_s *async_timer = NULL;
 
         async_timer = calloc(1, sizeof(struct timer_rec_s));
         blob->timer = async_timer;
 
         async_timer->cib = cib;
         async_timer->call_id = call_id;
         async_timer->timeout = timeout * 1000;
         async_timer->ref =
             g_timeout_add(async_timer->timeout, cib_async_timeout_handler, async_timer);
     }
 
     crm_trace("Adding callback %s for call %d", callback_name, call_id);
     pcmk__intkey_table_insert(cib_op_callback_table, call_id, blob);
 
     return TRUE;
 }
 
 void
 remove_cib_op_callback(int call_id, gboolean all_callbacks)
 {
     if (all_callbacks) {
         destroy_op_callback_table();
         cib_op_callback_table = pcmk__intkey_table(cib_destroy_op_callback);
     } else {
         pcmk__intkey_table_remove(cib_op_callback_table, call_id);
     }
 }
 
 int
 num_cib_op_callbacks(void)
 {
     if (cib_op_callback_table == NULL) {
         return 0;
     }
     return g_hash_table_size(cib_op_callback_table);
 }
 
 static void
 cib_dump_pending_op(gpointer key, gpointer value, gpointer user_data)
 {
     int call = GPOINTER_TO_INT(key);
     cib_callback_client_t *blob = value;
 
     crm_debug("Call %d (%s): pending", call, pcmk__s(blob->id, "without ID"));
 }
 
 void
 cib_dump_pending_callbacks(void)
 {
     if (cib_op_callback_table == NULL) {
         return;
     }
     return g_hash_table_foreach(cib_op_callback_table, cib_dump_pending_op, NULL);
 }
 
 cib_callback_client_t*
 cib__lookup_id (int call_id)
 {
     return pcmk__intkey_table_lookup(cib_op_callback_table, call_id);
 }
diff --git a/lib/cib/cib_file.c b/lib/cib/cib_file.c
index 4d0d3e273e..422019dd29 100644
--- a/lib/cib/cib_file.c
+++ b/lib/cib/cib_file.c
@@ -1,897 +1,897 @@
 /*
  * Original copyright 2004 International Business Machines
  * Later changes copyright 2008-2022 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 <crm_internal.h>
 #include <unistd.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
 #include <pwd.h>
 
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <glib.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ipc.h>
 #include <crm/common/xml.h>
 #include <crm/common/xml_internal.h>
 
 enum cib_file_flags {
     cib_file_flag_dirty = (1 << 0),
     cib_file_flag_live  = (1 << 1),
 };
 
 typedef struct cib_file_opaque_s {
     uint32_t flags; // Group of enum cib_file_flags
     char *filename;
 } cib_file_opaque_t;
 
 #define cib_set_file_flags(cibfile, flags_to_set) do {                  \
         (cibfile)->flags = pcmk__set_flags_as(__func__, __LINE__,       \
                                               LOG_TRACE, "CIB file",    \
                                               cibfile->filename,        \
                                               (cibfile)->flags,         \
                                               (flags_to_set),           \
                                               #flags_to_set);           \
     } while (0)
 
 #define cib_clear_file_flags(cibfile, flags_to_clear) do {              \
         (cibfile)->flags = pcmk__clear_flags_as(__func__, __LINE__,     \
                                                 LOG_TRACE, "CIB file",  \
                                                 cibfile->filename,      \
                                                 (cibfile)->flags,       \
                                                 (flags_to_clear),       \
                                                 #flags_to_clear);       \
     } while (0)
 
 int cib_file_perform_op(cib_t * cib, const char *op, const char *host, const char *section,
                         xmlNode * data, xmlNode ** output_data, int call_options);
 
 int cib_file_perform_op_delegate(cib_t * cib, const char *op, const char *host, const char *section,
                                  xmlNode * data, xmlNode ** output_data, int call_options,
                                  const char *user_name);
 
 int cib_file_signon(cib_t * cib, const char *name, enum cib_conn_type type);
 int cib_file_signoff(cib_t * cib);
 int cib_file_free(cib_t * cib);
 
 static int
 cib_file_inputfd(cib_t * cib)
 {
     return -EPROTONOSUPPORT;
 }
 
 static int
 cib_file_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data))
 {
     return -EPROTONOSUPPORT;
 }
 
 static int
 cib_file_register_notification(cib_t * cib, const char *callback, int enabled)
 {
     return -EPROTONOSUPPORT;
 }
 
 /*!
  * \internal
  * \brief Compare the calculated digest of an XML tree against a signature file
  *
  * \param[in] root Root of XML tree to compare
  * \param[in] sigfile Name of signature file containing digest to compare
  *
  * \return TRUE if digests match or signature file does not exist, else FALSE
  */
 static gboolean
 cib_file_verify_digest(xmlNode *root, const char *sigfile)
 {
     gboolean passed = FALSE;
     char *expected;
     int rc = pcmk__file_contents(sigfile, &expected);
 
     switch (rc) {
         case pcmk_rc_ok:
             if (expected == NULL) {
                 crm_err("On-disk digest at %s is empty", sigfile);
                 return FALSE;
             }
             break;
         case ENOENT:
             crm_warn("No on-disk digest present at %s", sigfile);
             return TRUE;
         default:
             crm_err("Could not read on-disk digest from %s: %s",
                     sigfile, pcmk_rc_str(rc));
             return FALSE;
     }
     passed = pcmk__verify_digest(root, expected);
     free(expected);
     return passed;
 }
 
 /*!
  * \internal
  * \brief Read an XML tree from a file and verify its digest
  *
  * \param[in] filename Name of XML file to read
  * \param[in] sigfile Name of signature file containing digest to compare
  * \param[in] root If non-NULL, will be set to pointer to parsed XML tree
  *
  * \return 0 if file was successfully read, parsed and verified, otherwise:
  *         -errno on stat() failure,
  *         -pcmk_err_cib_corrupt if file size is 0 or XML is not parseable, or
  *         -pcmk_err_cib_modified if digests do not match
  * \note If root is non-NULL, it is the caller's responsibility to free *root on
  *       successful return.
  */
 int
 cib_file_read_and_verify(const char *filename, const char *sigfile, xmlNode **root)
 {
     int s_res;
     struct stat buf;
     char *local_sigfile = NULL;
     xmlNode *local_root = NULL;
 
     CRM_ASSERT(filename != NULL);
     if (root) {
         *root = NULL;
     }
 
     /* Verify that file exists and its size is nonzero */
     s_res = stat(filename, &buf);
     if (s_res < 0) {
         crm_perror(LOG_WARNING, "Could not verify cluster configuration file %s", filename);
         return -errno;
     } else if (buf.st_size == 0) {
         crm_warn("Cluster configuration file %s is corrupt (size is zero)", filename);
         return -pcmk_err_cib_corrupt;
     }
 
     /* Parse XML */
     local_root = filename2xml(filename);
     if (local_root == NULL) {
         crm_warn("Cluster configuration file %s is corrupt (unparseable as XML)", filename);
         return -pcmk_err_cib_corrupt;
     }
 
     /* If sigfile is not specified, use original file name plus .sig */
     if (sigfile == NULL) {
         sigfile = local_sigfile = crm_strdup_printf("%s.sig", filename);
     }
 
     /* Verify that digests match */
     if (cib_file_verify_digest(local_root, sigfile) == FALSE) {
         free(local_sigfile);
         free_xml(local_root);
         return -pcmk_err_cib_modified;
     }
 
     free(local_sigfile);
     if (root) {
         *root = local_root;
     } else {
         free_xml(local_root);
     }
     return pcmk_ok;
 }
 
 #define CIB_SERIES "cib"
 #define CIB_SERIES_MAX 100
 #define CIB_SERIES_BZIP FALSE /* Must be false because archived copies are
                                  created with hard links
                                */
 
 #define CIB_LIVE_NAME CIB_SERIES ".xml"
 
 /*!
  * \internal
  * \brief Check whether a file is the live CIB
  *
  * \param[in] filename Name of file to check
  *
  * \return TRUE if file exists and its real path is same as live CIB's
  */
 static gboolean
 cib_file_is_live(const char *filename)
 {
     gboolean same = FALSE;
 
     if (filename != NULL) {
         // Canonicalize file names for true comparison
         char *real_filename = NULL;
 
         if (pcmk__real_path(filename, &real_filename) == pcmk_rc_ok) {
             char *real_livename = NULL;
 
             if (pcmk__real_path(CRM_CONFIG_DIR "/" CIB_LIVE_NAME,
                                 &real_livename) == pcmk_rc_ok) {
                 same = !strcmp(real_filename, real_livename);
                 free(real_livename);
             }
             free(real_filename);
         }
     }
     return same;
 }
 
 /* cib_file_backup() and cib_file_write_with_digest() need to chown the
  * written files only in limited circumstances, so these variables allow
  * that to be indicated without affecting external callers
  */
 static uid_t cib_file_owner = 0;
 static uid_t cib_file_group = 0;
 static gboolean cib_do_chown = FALSE;
 
 /*!
  * \internal
  * \brief Back up a CIB
  *
  * \param[in] cib_dirname Directory containing CIB file and backups
  * \param[in] cib_filename Name (relative to cib_dirname) of CIB file to back up
  *
  * \return 0 on success, -1 on error
  */
 static int
 cib_file_backup(const char *cib_dirname, const char *cib_filename)
 {
     int rc = 0;
     unsigned int seq;
     char *cib_path = crm_strdup_printf("%s/%s", cib_dirname, cib_filename);
     char *cib_digest = crm_strdup_printf("%s.sig", cib_path);
     char *backup_path;
     char *backup_digest;
 
     // Determine backup and digest file names
     if (pcmk__read_series_sequence(cib_dirname, CIB_SERIES,
                                    &seq) != pcmk_rc_ok) {
         // @TODO maybe handle errors better ...
         seq = 0;
     }
     backup_path = pcmk__series_filename(cib_dirname, CIB_SERIES, seq,
                                         CIB_SERIES_BZIP);
     backup_digest = crm_strdup_printf("%s.sig", backup_path);
 
     /* Remove the old backups if they exist */
     unlink(backup_path);
     unlink(backup_digest);
 
     /* Back up the CIB, by hard-linking it to the backup name */
     if ((link(cib_path, backup_path) < 0) && (errno != ENOENT)) {
         crm_perror(LOG_ERR, "Could not archive %s by linking to %s",
                    cib_path, backup_path);
         rc = -1;
 
     /* Back up the CIB signature similarly */
     } else if ((link(cib_digest, backup_digest) < 0) && (errno != ENOENT)) {
         crm_perror(LOG_ERR, "Could not archive %s by linking to %s",
                    cib_digest, backup_digest);
         rc = -1;
 
     /* Update the last counter and ensure everything is sync'd to media */
     } else {
         pcmk__write_series_sequence(cib_dirname, CIB_SERIES, ++seq,
                                     CIB_SERIES_MAX);
         if (cib_do_chown) {
             int rc2;
 
             if ((chown(backup_path, cib_file_owner, cib_file_group) < 0)
                     && (errno != ENOENT)) {
                 crm_perror(LOG_ERR, "Could not set owner of %s", backup_path);
                 rc = -1;
             }
             if ((chown(backup_digest, cib_file_owner, cib_file_group) < 0)
                     && (errno != ENOENT)) {
                 crm_perror(LOG_ERR, "Could not set owner of %s", backup_digest);
                 rc = -1;
             }
             rc2 = pcmk__chown_series_sequence(cib_dirname, CIB_SERIES,
                                               cib_file_owner, cib_file_group);
             if (rc2 != pcmk_rc_ok) {
                 crm_err("Could not set owner of sequence file in %s: %s",
                         cib_dirname, pcmk_rc_str(rc2));
                 rc = -1;
             }
         }
         pcmk__sync_directory(cib_dirname);
         crm_info("Archived previous version as %s", backup_path);
     }
 
     free(cib_path);
     free(cib_digest);
     free(backup_path);
     free(backup_digest);
     return rc;
 }
 
 /*!
  * \internal
  * \brief Prepare CIB XML to be written to disk
  *
  * Set num_updates to 0, set cib-last-written to the current timestamp,
  * and strip out the status section.
  *
  * \param[in] root Root of CIB XML tree
  *
  * \return void
  */
 static void
 cib_file_prepare_xml(xmlNode *root)
 {
     xmlNode *cib_status_root = NULL;
 
     /* Always write out with num_updates=0 and current last-written timestamp */
     crm_xml_add(root, XML_ATTR_NUMUPDATES, "0");
     pcmk__xe_add_last_written(root);
 
     /* Delete status section before writing to file, because
      * we discard it on startup anyway, and users get confused by it */
     cib_status_root = find_xml_node(root, XML_CIB_TAG_STATUS, TRUE);
     CRM_LOG_ASSERT(cib_status_root != NULL);
     if (cib_status_root != NULL) {
         free_xml(cib_status_root);
     }
 }
 
 /*!
  * \internal
  * \brief Write CIB to disk, along with a signature file containing its digest
  *
  * \param[in] cib_root Root of XML tree to write
  * \param[in] cib_dirname Directory containing CIB and signature files
  * \param[in] cib_filename Name (relative to cib_dirname) of file to write
  *
  * \return pcmk_ok on success,
  *         pcmk_err_cib_modified if existing cib_filename doesn't match digest,
  *         pcmk_err_cib_backup if existing cib_filename couldn't be backed up,
  *         or pcmk_err_cib_save if new cib_filename couldn't be saved
  */
 int
 cib_file_write_with_digest(xmlNode *cib_root, const char *cib_dirname,
                            const char *cib_filename)
 {
     int exit_rc = pcmk_ok;
     int rc, fd;
     char *digest = NULL;
 
     /* Detect CIB version for diagnostic purposes */
     const char *epoch = crm_element_value(cib_root, XML_ATTR_GENERATION);
     const char *admin_epoch = crm_element_value(cib_root,
                                                 XML_ATTR_GENERATION_ADMIN);
 
     /* Determine full CIB and signature pathnames */
     char *cib_path = crm_strdup_printf("%s/%s", cib_dirname, cib_filename);
     char *digest_path = crm_strdup_printf("%s.sig", cib_path);
 
     /* Create temporary file name patterns for writing out CIB and signature */
     char *tmp_cib = crm_strdup_printf("%s/cib.XXXXXX", cib_dirname);
     char *tmp_digest = crm_strdup_printf("%s/cib.XXXXXX", cib_dirname);
 
     CRM_ASSERT((cib_path != NULL) && (digest_path != NULL)
                && (tmp_cib != NULL) && (tmp_digest != NULL));
 
     /* Ensure the admin didn't modify the existing CIB underneath us */
     crm_trace("Reading cluster configuration file %s", cib_path);
     rc = cib_file_read_and_verify(cib_path, NULL, NULL);
     if ((rc != pcmk_ok) && (rc != -ENOENT)) {
         crm_err("%s was manually modified while the cluster was active!",
                 cib_path);
         exit_rc = pcmk_err_cib_modified;
         goto cleanup;
     }
 
     /* Back up the existing CIB */
     if (cib_file_backup(cib_dirname, cib_filename) < 0) {
         exit_rc = pcmk_err_cib_backup;
         goto cleanup;
     }
 
     crm_debug("Writing CIB to disk");
     umask(S_IWGRP | S_IWOTH | S_IROTH);
     cib_file_prepare_xml(cib_root);
 
     /* Write the CIB to a temporary file, so we can deploy (near) atomically */
     fd = mkstemp(tmp_cib);
     if (fd < 0) {
         crm_perror(LOG_ERR, "Couldn't open temporary file %s for writing CIB",
                    tmp_cib);
         exit_rc = pcmk_err_cib_save;
         goto cleanup;
     }
 
     /* Protect the temporary file */
     if (fchmod(fd, S_IRUSR | S_IWUSR) < 0) {
         crm_perror(LOG_ERR, "Couldn't protect temporary file %s for writing CIB",
                    tmp_cib);
         exit_rc = pcmk_err_cib_save;
         goto cleanup;
     }
     if (cib_do_chown && (fchown(fd, cib_file_owner, cib_file_group) < 0)) {
         crm_perror(LOG_ERR, "Couldn't protect temporary file %s for writing CIB",
                    tmp_cib);
         exit_rc = pcmk_err_cib_save;
         goto cleanup;
     }
 
     /* Write out the CIB */
     if (write_xml_fd(cib_root, tmp_cib, fd, FALSE) <= 0) {
         crm_err("Changes couldn't be written to %s", tmp_cib);
         exit_rc = pcmk_err_cib_save;
         goto cleanup;
     }
 
     /* Calculate CIB digest */
     digest = calculate_on_disk_digest(cib_root);
     CRM_ASSERT(digest != NULL);
     crm_info("Wrote version %s.%s.0 of the CIB to disk (digest: %s)",
              (admin_epoch ? admin_epoch : "0"), (epoch ? epoch : "0"), digest);
 
     /* Write the CIB digest to a temporary file */
     fd = mkstemp(tmp_digest);
     if (fd < 0) {
         crm_perror(LOG_ERR, "Could not create temporary file for CIB digest");
         exit_rc = pcmk_err_cib_save;
         goto cleanup;
     }
     if (cib_do_chown && (fchown(fd, cib_file_owner, cib_file_group) < 0)) {
         crm_perror(LOG_ERR, "Couldn't protect temporary file %s for writing CIB",
                    tmp_cib);
         exit_rc = pcmk_err_cib_save;
         close(fd);
         goto cleanup;
     }
     rc = pcmk__write_sync(fd, digest);
     if (rc != pcmk_rc_ok) {
         crm_err("Could not write digest to %s: %s",
                 tmp_digest, pcmk_rc_str(rc));
         exit_rc = pcmk_err_cib_save;
         close(fd);
         goto cleanup;
     }
     close(fd);
     crm_debug("Wrote digest %s to disk", digest);
 
     /* Verify that what we wrote is sane */
     crm_info("Reading cluster configuration file %s (digest: %s)",
              tmp_cib, tmp_digest);
     rc = cib_file_read_and_verify(tmp_cib, tmp_digest, NULL);
     CRM_ASSERT(rc == 0);
 
     /* Rename temporary files to live, and sync directory changes to media */
     crm_debug("Activating %s", tmp_cib);
     if (rename(tmp_cib, cib_path) < 0) {
         crm_perror(LOG_ERR, "Couldn't rename %s as %s", tmp_cib, cib_path);
         exit_rc = pcmk_err_cib_save;
     }
     if (rename(tmp_digest, digest_path) < 0) {
         crm_perror(LOG_ERR, "Couldn't rename %s as %s", tmp_digest,
                    digest_path);
         exit_rc = pcmk_err_cib_save;
     }
     pcmk__sync_directory(cib_dirname);
 
   cleanup:
     free(cib_path);
     free(digest_path);
     free(digest);
     free(tmp_digest);
     free(tmp_cib);
     return exit_rc;
 }
 
 cib_t *
 cib_file_new(const char *cib_location)
 {
     cib_file_opaque_t *private = NULL;
     cib_t *cib = cib_new_variant();
 
     if (cib == NULL) {
         return NULL;
     }
 
     private = calloc(1, sizeof(cib_file_opaque_t));
 
     if (private == NULL) {
         free(cib);
         return NULL;
     }
 
     cib->variant = cib_file;
     cib->variant_opaque = private;
 
     if (cib_location == NULL) {
         cib_location = getenv("CIB_file");
         CRM_CHECK(cib_location != NULL, return NULL); // Shouldn't be possible
     }
     private->flags = 0;
     if (cib_file_is_live(cib_location)) {
         cib_set_file_flags(private, cib_file_flag_live);
         crm_trace("File %s detected as live CIB", cib_location);
     }
     private->filename = strdup(cib_location);
 
     /* assign variant specific ops */
     cib->delegate_fn = cib_file_perform_op_delegate;
     cib->cmds->signon = cib_file_signon;
     cib->cmds->signoff = cib_file_signoff;
     cib->cmds->free = cib_file_free;
     cib->cmds->inputfd = cib_file_inputfd;
 
     cib->cmds->register_notification = cib_file_register_notification;
     cib->cmds->set_connection_dnotify = cib_file_set_connection_dnotify;
 
     return cib;
 }
 
 static xmlNode *in_mem_cib = NULL;
 
 /*!
  * \internal
  * \brief Read CIB from disk and validate it against XML schema
  *
  * \param[in] filename Name of file to read CIB from
  *
  * \return pcmk_ok on success,
  *         -ENXIO if file does not exist (or stat() otherwise fails), or
  *         -pcmk_err_schema_validation if XML doesn't parse or validate
  * \note If filename is the live CIB, this will *not* verify its digest,
  *       though that functionality would be trivial to add here.
  *       Also, this will *not* verify that the file is writable,
  *       because some callers might not need to write.
  */
 static int
 load_file_cib(const char *filename)
 {
     struct stat buf;
     xmlNode *root = NULL;
 
     /* Ensure file is readable */
     if (strcmp(filename, "-") && (stat(filename, &buf) < 0)) {
         return -ENXIO;
     }
 
     /* Parse XML from file */
     root = filename2xml(filename);
     if (root == NULL) {
         return -pcmk_err_schema_validation;
     }
 
     /* Add a status section if not already present */
     if (find_xml_node(root, XML_CIB_TAG_STATUS, FALSE) == NULL) {
         create_xml_node(root, XML_CIB_TAG_STATUS);
     }
 
     /* Validate XML against its specified schema */
     if (validate_xml(root, NULL, TRUE) == FALSE) {
         const char *schema = crm_element_value(root, XML_ATTR_VALIDATION);
 
         crm_err("CIB does not validate against %s", schema);
         free_xml(root);
         return -pcmk_err_schema_validation;
     }
 
     /* Remember the parsed XML for later use */
     in_mem_cib = root;
     return pcmk_ok;
 }
 
 int
 cib_file_signon(cib_t * cib, const char *name, enum cib_conn_type type)
 {
     int rc = pcmk_ok;
     cib_file_opaque_t *private = cib->variant_opaque;
 
     if (private->filename == NULL) {
         rc = -EINVAL;
     } else {
         rc = load_file_cib(private->filename);
     }
 
     if (rc == pcmk_ok) {
         crm_debug("Opened connection to local file '%s' for %s",
                   private->filename, name);
         cib->state = cib_connected_command;
         cib->type = cib_command;
 
     } else {
         crm_info("Connection to local file '%s' for %s failed: %s\n",
                  private->filename, name, pcmk_strerror(rc));
     }
     return rc;
 }
 
 /*!
  * \internal
  * \brief Write out the in-memory CIB to a live CIB file
  *
  * param[in] path Full path to file to write
  *
  * \return 0 on success, -1 on failure
  */
 static int
 cib_file_write_live(char *path)
 {
     uid_t uid = geteuid();
     struct passwd *daemon_pwent;
     char *sep = strrchr(path, '/');
     const char *cib_dirname, *cib_filename;
     int rc = 0;
 
     /* Get the desired uid/gid */
     errno = 0;
     daemon_pwent = getpwnam(CRM_DAEMON_USER);
     if (daemon_pwent == NULL) {
         crm_perror(LOG_ERR, "Could not find %s user", CRM_DAEMON_USER);
         return -1;
     }
 
     /* If we're root, we can change the ownership;
      * if we're daemon, anything we create will be OK;
      * otherwise, block access so we don't create wrong owner
      */
     if ((uid != 0) && (uid != daemon_pwent->pw_uid)) {
         crm_perror(LOG_ERR, "Must be root or %s to modify live CIB",
                    CRM_DAEMON_USER);
         return 0;
     }
 
     /* fancy footwork to separate dirname from filename
      * (we know the canonical name maps to the live CIB,
      * but the given name might be relative, or symlinked)
      */
     if (sep == NULL) { /* no directory component specified */
         cib_dirname = "./";
         cib_filename = path;
     } else if (sep == path) { /* given name is in / */
         cib_dirname = "/";
         cib_filename = path + 1;
     } else { /* typical case; split given name into parts */
         *sep = '\0';
         cib_dirname = path;
         cib_filename = sep + 1;
     }
 
     /* if we're root, we want to update the file ownership */
     if (uid == 0) {
         cib_file_owner = daemon_pwent->pw_uid;
         cib_file_group = daemon_pwent->pw_gid;
         cib_do_chown = TRUE;
     }
 
     /* write the file */
     if (cib_file_write_with_digest(in_mem_cib, cib_dirname,
                                    cib_filename) != pcmk_ok) {
         rc = -1;
     }
 
     /* turn off file ownership changes, for other callers */
     if (uid == 0) {
         cib_do_chown = FALSE;
     }
 
     /* undo fancy stuff */
     if ((sep != NULL) && (*sep == '\0')) {
         *sep = '/';
     }
 
     return rc;
 }
 
 /*!
  * \internal
  * \brief Sign-off method for CIB file variants
  *
  * This will write the file to disk if needed, and free the in-memory CIB. If
  * the file is the live CIB, it will compute and write a signature as well.
  *
  * \param[in] cib CIB object to sign off
  *
  * \return pcmk_ok on success, pcmk_err_generic on failure
  * \todo This method should refuse to write the live CIB if the CIB manager is
  *       running.
  */
 int
 cib_file_signoff(cib_t * cib)
 {
     int rc = pcmk_ok;
     cib_file_opaque_t *private = cib->variant_opaque;
 
     crm_debug("Disconnecting from the CIB manager");
     cib->state = cib_disconnected;
     cib->type = cib_no_connection;
 
     /* If the in-memory CIB has been changed, write it to disk */
     if (pcmk_is_set(private->flags, cib_file_flag_dirty)) {
 
         /* If this is the live CIB, write it out with a digest */
         if (pcmk_is_set(private->flags, cib_file_flag_live)) {
             if (cib_file_write_live(private->filename) < 0) {
                 rc = pcmk_err_generic;
             }
 
         /* Otherwise, it's a simple write */
         } else {
             gboolean do_bzip = pcmk__ends_with_ext(private->filename, ".bz2");
 
             if (write_xml_file(in_mem_cib, private->filename, do_bzip) <= 0) {
                 rc = pcmk_err_generic;
             }
         }
 
         if (rc == pcmk_ok) {
             crm_info("Wrote CIB to %s", private->filename);
             cib_clear_file_flags(private, cib_file_flag_dirty);
         } else {
             crm_err("Could not write CIB to %s", private->filename);
         }
     }
 
     /* Free the in-memory CIB */
     free_xml(in_mem_cib);
     in_mem_cib = NULL;
     return rc;
 }
 
 int
 cib_file_free(cib_t * cib)
 {
     int rc = pcmk_ok;
 
     if (cib->state != cib_disconnected) {
         rc = cib_file_signoff(cib);
     }
 
     if (rc == pcmk_ok) {
         cib_file_opaque_t *private = cib->variant_opaque;
 
         free(private->filename);
         free(cib->cmds);
         free(private);
         free(cib);
 
     } else {
         fprintf(stderr, "Couldn't sign off: %d\n", rc);
     }
 
     return rc;
 }
 
 struct cib_func_entry {
     const char *op;
     gboolean read_only;
     cib_op_t fn;
 };
 
 /* *INDENT-OFF* */
 static struct cib_func_entry cib_file_ops[] = {
     { PCMK__CIB_REQUEST_QUERY,      TRUE,   cib_process_query},
     { PCMK__CIB_REQUEST_MODIFY,     FALSE,  cib_process_modify},
     {CIB_OP_APPLY_DIFF, FALSE, cib_process_diff},
     { PCMK__CIB_REQUEST_BUMP,       FALSE,  cib_process_bump },
     {CIB_OP_REPLACE,    FALSE, cib_process_replace},
     { PCMK__CIB_REQUEST_CREATE,     FALSE,  cib_process_create },
-    {CIB_OP_DELETE,     FALSE, cib_process_delete},
+    { PCMK__CIB_REQUEST_DELETE,     FALSE,  cib_process_delete},
     {CIB_OP_ERASE,      FALSE, cib_process_erase},
     {CIB_OP_UPGRADE,    FALSE, cib_process_upgrade},
 };
 /* *INDENT-ON* */
 
 int
 cib_file_perform_op(cib_t * cib, const char *op, const char *host, const char *section,
                     xmlNode * data, xmlNode ** output_data, int call_options)
 {
     return cib_file_perform_op_delegate(cib, op, host, section, data, output_data, call_options,
                                         NULL);
 }
 
 int
 cib_file_perform_op_delegate(cib_t * cib, const char *op, const char *host, const char *section,
                              xmlNode * data, xmlNode ** output_data, int call_options,
                              const char *user_name)
 {
     int rc = pcmk_ok;
     char *effective_user = NULL;
     gboolean query = FALSE;
     gboolean changed = FALSE;
     xmlNode *request = NULL;
     xmlNode *output = NULL;
     xmlNode *cib_diff = NULL;
     xmlNode *result_cib = NULL;
     cib_op_t *fn = NULL;
     int lpc = 0;
     static int max_msg_types = PCMK__NELEM(cib_file_ops);
     cib_file_opaque_t *private = cib->variant_opaque;
 
     crm_info("Handling %s operation for %s as %s",
              (op? op : "invalid"), (section? section : "entire CIB"),
              (user_name? user_name : "default user"));
 
     cib__set_call_options(call_options, "file operation",
                           cib_no_mtime|cib_inhibit_bcast|cib_scope_local);
 
     if (cib->state == cib_disconnected) {
         return -ENOTCONN;
     }
 
     if (output_data != NULL) {
         *output_data = NULL;
     }
 
     if (op == NULL) {
         return -EINVAL;
     }
 
     for (lpc = 0; lpc < max_msg_types; lpc++) {
         if (pcmk__str_eq(op, cib_file_ops[lpc].op, pcmk__str_casei)) {
             fn = &(cib_file_ops[lpc].fn);
             query = cib_file_ops[lpc].read_only;
             break;
         }
     }
 
     if (fn == NULL) {
         return -EPROTONOSUPPORT;
     }
 
     cib->call_id++;
     request = cib_create_op(cib->call_id, "dummy-token", op, host, section, data, call_options, user_name);
     if(user_name) {
         crm_xml_add(request, XML_ACL_TAG_USER, user_name);
     }
 
     /* Mirror the logic in cib_prepare_common() */
     if (section != NULL && data != NULL && pcmk__str_eq(crm_element_name(data), XML_TAG_CIB, pcmk__str_none)) {
         data = pcmk_find_cib_element(data, section);
     }
 
     rc = cib_perform_op(op, call_options, fn, query,
                         section, request, data, TRUE, &changed, in_mem_cib, &result_cib, &cib_diff,
                         &output);
 
     free_xml(request);
     if (rc == -pcmk_err_schema_validation) {
         validate_xml_verbose(result_cib);
     }
 
     if (rc != pcmk_ok) {
         free_xml(result_cib);
 
     } else if (query == FALSE) {
         xml_log_patchset(LOG_DEBUG, "cib:diff", cib_diff);
         free_xml(in_mem_cib);
         in_mem_cib = result_cib;
         cib_set_file_flags(private, cib_file_flag_dirty);
     }
 
     free_xml(cib_diff);
 
     if (cib->op_callback != NULL) {
         cib->op_callback(NULL, cib->call_id, rc, output);
     }
 
     if (output_data && output) {
         if(output == in_mem_cib) {
             *output_data = copy_xml(output);
         } else {
             *output_data = output;
         }
 
     } else if(output != in_mem_cib) {
         free_xml(output);
     }
 
     free(effective_user);
     return rc;
 }
diff --git a/lib/cib/cib_ops.c b/lib/cib/cib_ops.c
index 042da613ef..cb1094c7d9 100644
--- a/lib/cib/cib_ops.c
+++ b/lib/cib/cib_ops.c
@@ -1,855 +1,857 @@
 /*
  * Copyright 2004-2022 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 <crm_internal.h>
 
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <time.h>
 
 #include <sys/param.h>
 #include <sys/types.h>
 
 #include <crm/crm.h>
 #include <crm/cib/internal.h>
 #include <crm/msg_xml.h>
 
 #include <crm/common/xml.h>
 #include <crm/common/xml_internal.h>
 
 int
 cib_process_query(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                   xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     xmlNode *obj_root = NULL;
     int result = pcmk_ok;
 
     crm_trace("Processing %s for %s section",
               op, pcmk__s(section, "unspecified"));
 
     if (options & cib_xpath) {
         return cib_process_xpath(op, options, section, req, input,
                                  existing_cib, result_cib, answer);
     }
 
     CRM_CHECK(*answer == NULL, free_xml(*answer));
     *answer = NULL;
 
     if (pcmk__str_eq(XML_CIB_TAG_SECTION_ALL, section, pcmk__str_casei)) {
         section = NULL;
     }
 
     obj_root = pcmk_find_cib_element(existing_cib, section);
 
     if (obj_root == NULL) {
         result = -ENXIO;
 
     } else if (options & cib_no_children) {
         const char *tag = TYPE(obj_root);
         xmlNode *shallow = create_xml_node(*answer, tag);
 
         copy_in_properties(shallow, obj_root);
         *answer = shallow;
 
     } else {
         *answer = obj_root;
     }
 
     if (result == pcmk_ok && *answer == NULL) {
         crm_err("Error creating query response");
         result = -ENOMSG;
     }
 
     return result;
 }
 
 int
 cib_process_erase(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                   xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     int result = pcmk_ok;
 
     crm_trace("Processing \"%s\" event", op);
     *answer = NULL;
     free_xml(*result_cib);
     *result_cib = createEmptyCib(0);
 
     copy_in_properties(*result_cib, existing_cib);
     cib_update_counter(*result_cib, XML_ATTR_GENERATION_ADMIN, FALSE);
 
     return result;
 }
 
 int
 cib_process_upgrade(const char *op, int options, const char *section, xmlNode * req,
                     xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                     xmlNode ** answer)
 {
     int rc = 0;
     int new_version = 0;
     int current_version = 0;
     int max_version = 0;
     const char *max = crm_element_value(req, F_CIB_SCHEMA_MAX);
     const char *value = crm_element_value(existing_cib, XML_ATTR_VALIDATION);
 
     *answer = NULL;
     crm_trace("Processing \"%s\" event with max=%s", op, max);
 
     if (value != NULL) {
         current_version = get_schema_version(value);
     }
 
     if (max) {
         max_version = get_schema_version(max);
     }
 
     rc = update_validation(result_cib, &new_version, max_version, TRUE,
                            !(options & cib_verbose));
     if (new_version > current_version) {
         cib_update_counter(*result_cib, XML_ATTR_GENERATION_ADMIN, FALSE);
         cib_update_counter(*result_cib, XML_ATTR_GENERATION, TRUE);
         cib_update_counter(*result_cib, XML_ATTR_NUMUPDATES, TRUE);
         return pcmk_ok;
     }
 
     return rc;
 }
 
 int
 cib_process_bump(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                  xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     int result = pcmk_ok;
 
     crm_trace("Processing %s for epoch='%s'", op,
               pcmk__s(crm_element_value(existing_cib, XML_ATTR_GENERATION), ""));
 
     *answer = NULL;
     cib_update_counter(*result_cib, XML_ATTR_GENERATION, FALSE);
 
     return result;
 }
 
 int
 cib_update_counter(xmlNode * xml_obj, const char *field, gboolean reset)
 {
     char *new_value = NULL;
     char *old_value = NULL;
     int int_value = -1;
 
     if (reset == FALSE && crm_element_value(xml_obj, field) != NULL) {
         old_value = crm_element_value_copy(xml_obj, field);
     }
     if (old_value != NULL) {
         int_value = atoi(old_value);
         new_value = pcmk__itoa(++int_value);
     } else {
         new_value = strdup("1");
         CRM_ASSERT(new_value != NULL);
     }
 
     crm_trace("Update %s from %s to %s",
               field, pcmk__s(old_value, "unset"), new_value);
     crm_xml_add(xml_obj, field, new_value);
 
     free(new_value);
     free(old_value);
 
     return pcmk_ok;
 }
 
 int
 cib_process_replace(const char *op, int options, const char *section, xmlNode * req,
                     xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
                     xmlNode ** answer)
 {
     const char *tag = NULL;
     int result = pcmk_ok;
 
     crm_trace("Processing %s for %s section",
               op, pcmk__s(section, "unspecified"));
 
     if (options & cib_xpath) {
         return cib_process_xpath(op, options, section, req, input,
                                  existing_cib, result_cib, answer);
     }
 
     *answer = NULL;
 
     if (input == NULL) {
         return -EINVAL;
     }
 
     tag = crm_element_name(input);
 
     if (pcmk__str_eq(XML_CIB_TAG_SECTION_ALL, section, pcmk__str_casei)) {
         section = NULL;
 
     } else if (pcmk__str_eq(tag, section, pcmk__str_casei)) {
         section = NULL;
     }
 
     if (pcmk__str_eq(tag, XML_TAG_CIB, pcmk__str_casei)) {
         int updates = 0;
         int epoch = 0;
         int admin_epoch = 0;
 
         int replace_updates = 0;
         int replace_epoch = 0;
         int replace_admin_epoch = 0;
 
         const char *reason = NULL;
         const char *peer = crm_element_value(req, F_ORIG);
         const char *digest = crm_element_value(req, XML_ATTR_DIGEST);
 
         if (digest) {
             const char *version = crm_element_value(req, XML_ATTR_CRM_VERSION);
             char *digest_verify = calculate_xml_versioned_digest(input, FALSE, TRUE,
                                                                  version ? version :
                                                                  CRM_FEATURE_SET);
 
             if (!pcmk__str_eq(digest_verify, digest, pcmk__str_casei)) {
                 crm_err("Digest mis-match on replace from %s: %s vs. %s (expected)", peer,
                         digest_verify, digest);
                 reason = "digest mismatch";
 
             } else {
                 crm_info("Digest matched on replace from %s: %s", peer, digest);
             }
             free(digest_verify);
 
         } else {
             crm_trace("No digest to verify");
         }
 
         cib_version_details(existing_cib, &admin_epoch, &epoch, &updates);
         cib_version_details(input, &replace_admin_epoch, &replace_epoch, &replace_updates);
 
         if (replace_admin_epoch < admin_epoch) {
             reason = XML_ATTR_GENERATION_ADMIN;
 
         } else if (replace_admin_epoch > admin_epoch) {
             /* no more checks */
 
         } else if (replace_epoch < epoch) {
             reason = XML_ATTR_GENERATION;
 
         } else if (replace_epoch > epoch) {
             /* no more checks */
 
         } else if (replace_updates < updates) {
             reason = XML_ATTR_NUMUPDATES;
         }
 
         if (reason != NULL) {
             crm_info("Replacement %d.%d.%d from %s not applied to %d.%d.%d:"
                      " current %s is greater than the replacement",
                      replace_admin_epoch, replace_epoch,
                      replace_updates, peer, admin_epoch, epoch, updates, reason);
             result = -pcmk_err_old_data;
         } else {
             crm_info("Replaced %d.%d.%d with %d.%d.%d from %s",
                      admin_epoch, epoch, updates,
                      replace_admin_epoch, replace_epoch, replace_updates, peer);
         }
 
         free_xml(*result_cib);
         *result_cib = copy_xml(input);
 
     } else {
         xmlNode *obj_root = NULL;
         gboolean ok = TRUE;
 
         obj_root = pcmk_find_cib_element(*result_cib, section);
         ok = replace_xml_child(NULL, obj_root, input, FALSE);
         if (ok == FALSE) {
             crm_trace("No matching object to replace");
             result = -ENXIO;
         }
     }
 
     return result;
 }
 
 int
 cib_process_delete(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                    xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     xmlNode *obj_root = NULL;
 
     crm_trace("Processing \"%s\" event", op);
 
     if (options & cib_xpath) {
         return cib_process_xpath(op, options, section, req, input,
                                  existing_cib, result_cib, answer);
     }
 
     if (input == NULL) {
         crm_err("Cannot perform modification with no data");
         return -EINVAL;
     }
 
     obj_root = pcmk_find_cib_element(*result_cib, section);
     if(pcmk__str_eq(crm_element_name(input), section, pcmk__str_casei)) {
         xmlNode *child = NULL;
         for (child = pcmk__xml_first_child(input); child;
              child = pcmk__xml_next(child)) {
             if (replace_xml_child(NULL, obj_root, child, TRUE) == FALSE) {
                 crm_trace("No matching object to delete: %s=%s", child->name, ID(child));
             }
         }
 
     } else if (replace_xml_child(NULL, obj_root, input, TRUE) == FALSE) {
             crm_trace("No matching object to delete: %s=%s", input->name, ID(input));
     }
 
     return pcmk_ok;
 }
 
 int
 cib_process_modify(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                    xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     xmlNode *obj_root = NULL;
 
     crm_trace("Processing \"%s\" event", op);
 
     if (options & cib_xpath) {
         return cib_process_xpath(op, options, section, req, input,
                                  existing_cib, result_cib, answer);
     }
 
     if (input == NULL) {
         crm_err("Cannot perform modification with no data");
         return -EINVAL;
     }
 
     obj_root = pcmk_find_cib_element(*result_cib, section);
     if (obj_root == NULL) {
         xmlNode *tmp_section = NULL;
         const char *path = pcmk_cib_parent_name_for(section);
 
         if (path == NULL) {
             return -EINVAL;
         }
 
         tmp_section = create_xml_node(NULL, section);
         cib_process_xpath(PCMK__CIB_REQUEST_CREATE, 0, path, NULL, tmp_section,
                           NULL, result_cib, answer);
         free_xml(tmp_section);
 
         obj_root = pcmk_find_cib_element(*result_cib, section);
     }
 
     CRM_CHECK(obj_root != NULL, return -EINVAL);
 
     if (update_xml_child(obj_root, input) == FALSE) {
         if (options & cib_can_create) {
             add_node_copy(obj_root, input);
         } else {
             return -ENXIO;
         }
     }
 
     if(options & cib_mixed_update) {
         int max = 0, lpc;
         xmlXPathObjectPtr xpathObj = xpath_search(*result_cib, "//@__delete__");
 
         if (xpathObj) {
             max = numXpathResults(xpathObj);
             crm_log_xml_trace(*result_cib, "Mixed result");
         }
 
         for (lpc = 0; lpc < max; lpc++) {
             xmlNode *match = getXpathResult(xpathObj, lpc);
             xmlChar *match_path = xmlGetNodePath(match);
 
             crm_debug("Destroying %s", match_path);
             free(match_path);
             free_xml(match);
         }
 
         freeXpathObject(xpathObj);
     }
     return pcmk_ok;
 }
 
 static int
 update_cib_object(xmlNode * parent, xmlNode * update)
 {
     int result = pcmk_ok;
     xmlNode *target = NULL;
     xmlNode *a_child = NULL;
     const char *replace = NULL;
     const char *object_id = NULL;
     const char *object_name = NULL;
 
     CRM_CHECK(update != NULL, return -EINVAL);
     CRM_CHECK(parent != NULL, return -EINVAL);
 
     object_name = crm_element_name(update);
     CRM_CHECK(object_name != NULL, return -EINVAL);
 
     object_id = ID(update);
     crm_trace("Processing update for <%s%s%s%s>", object_name,
               ((object_id == NULL)? "" : " id='"), pcmk__s(object_id, ""),
               ((object_id == NULL)? "" : "'"));
 
     if (object_id == NULL) {
         /*  placeholder object */
         target = find_xml_node(parent, object_name, FALSE);
 
     } else {
         target = pcmk__xe_match(parent, object_name, XML_ATTR_ID, object_id);
     }
 
     if (target == NULL) {
         target = create_xml_node(parent, object_name);
     }
 
     crm_trace("Found node <%s%s%s%s> to update", object_name,
               ((object_id == NULL)? "" : " id='"), pcmk__s(object_id, ""),
               ((object_id == NULL)? "" : "'"));
 
     replace = crm_element_value(update, XML_CIB_ATTR_REPLACE);
     if (replace != NULL) {
         xmlNode *remove = NULL;
         int last = 0, lpc = 0, len = 0;
 
         len = strlen(replace);
         while (lpc <= len) {
             if (replace[lpc] == ',' || replace[lpc] == 0) {
                 char *replace_item = NULL;
 
                 if (last == lpc) {
                     /* nothing to do */
                     last = lpc + 1;
                     goto incr;
                 }
 
                 replace_item = strndup(replace + last, lpc - last);
                 remove = find_xml_node(target, replace_item, FALSE);
                 if (remove != NULL) {
                     crm_trace("Replacing node <%s> in <%s>",
                               replace_item, crm_element_name(target));
                     free_xml(remove);
                     remove = NULL;
                 }
                 free(replace_item);
                 last = lpc + 1;
             }
   incr:
             lpc++;
         }
         xml_remove_prop(update, XML_CIB_ATTR_REPLACE);
         xml_remove_prop(target, XML_CIB_ATTR_REPLACE);
     }
 
     copy_in_properties(target, update);
 
     if (xml_acl_denied(target)) {
         crm_notice("Cannot update <%s id=%s>", pcmk__s(object_name, "<null>"), pcmk__s(object_id, "<null>"));
         return -EACCES;
     }
 
     crm_trace("Processing children of <%s%s%s%s>", object_name,
               ((object_id == NULL)? "" : " id='"), pcmk__s(object_id, ""),
               ((object_id == NULL)? "" : "'"));
 
     for (a_child = pcmk__xml_first_child(update); a_child != NULL;
          a_child = pcmk__xml_next(a_child)) {
         int tmp_result = 0;
 
         crm_trace("Updating child <%s%s%s%s>", crm_element_name(a_child),
                   ((ID(a_child) == NULL)? "" : " id='"),
                   pcmk__s(ID(a_child), ""), ((ID(a_child) == NULL)? "" : "'"));
 
         tmp_result = update_cib_object(target, a_child);
 
         /*  only the first error is likely to be interesting */
         if (tmp_result != pcmk_ok) {
             crm_err("Error updating child <%s%s%s%s>",
                     crm_element_name(a_child),
                     ((ID(a_child) == NULL)? "" : " id='"),
                     pcmk__s(ID(a_child), ""),
                     ((ID(a_child) == NULL)? "" : "'"));
 
             if (result == pcmk_ok) {
                 result = tmp_result;
             }
         }
     }
 
     crm_trace("Finished handling update for <%s%s%s%s>", object_name,
               ((object_id == NULL)? "" : " id='"), pcmk__s(object_id, ""),
               ((object_id == NULL)? "" : "'"));
 
     return result;
 }
 
 static int
 add_cib_object(xmlNode * parent, xmlNode * new_obj)
 {
     const char *object_name = NULL;
     const char *object_id = NULL;
     xmlNode *equiv_node = NULL;
 
     if ((parent == NULL) || (new_obj == NULL)) {
         return -EINVAL;
     }
 
     object_name = crm_element_name(new_obj);
     if (object_name == NULL) {
         return -EINVAL;
     }
 
     object_id = ID(new_obj);
 
     crm_trace("Processing creation of <%s%s%s%s>", object_name,
               ((object_id == NULL)? "" : " id='"), pcmk__s(object_id, ""),
               ((object_id == NULL)? "" : "'"));
 
     if (object_id == NULL) {
         equiv_node = find_xml_node(parent, object_name, FALSE);
     } else {
         equiv_node = pcmk__xe_match(parent, object_name, XML_ATTR_ID,
                                     object_id);
     }
     if (equiv_node != NULL) {
         return -EEXIST;
     }
 
     return update_cib_object(parent, new_obj);
 }
 
 int
 cib_process_create(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                    xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     xmlNode *failed = NULL;
     int result = pcmk_ok;
     xmlNode *update_section = NULL;
 
     crm_trace("Processing %s for %s section",
               op, pcmk__s(section, "unspecified"));
     if (pcmk__str_eq(XML_CIB_TAG_SECTION_ALL, section, pcmk__str_casei)) {
         section = NULL;
 
     } else if (pcmk__str_eq(XML_TAG_CIB, section, pcmk__str_casei)) {
         section = NULL;
 
     } else if (pcmk__str_eq(crm_element_name(input), XML_TAG_CIB, pcmk__str_casei)) {
         section = NULL;
     }
 
     CRM_CHECK(strcmp(op, PCMK__CIB_REQUEST_CREATE) == 0, return -EINVAL);
 
     if (input == NULL) {
         crm_err("Cannot perform modification with no data");
         return -EINVAL;
     }
 
     if (section == NULL) {
         return cib_process_modify(op, options, section, req, input, existing_cib, result_cib,
                                   answer);
     }
 
     failed = create_xml_node(NULL, XML_TAG_FAILED);
 
     update_section = pcmk_find_cib_element(*result_cib, section);
     if (pcmk__str_eq(crm_element_name(input), section, pcmk__str_casei)) {
         xmlNode *a_child = NULL;
 
         for (a_child = pcmk__xml_first_child(input); a_child != NULL;
              a_child = pcmk__xml_next(a_child)) {
             result = add_cib_object(update_section, a_child);
             if (update_results(failed, a_child, op, result)) {
                 break;
             }
         }
 
     } else {
         result = add_cib_object(update_section, input);
         update_results(failed, input, op, result);
     }
 
     if ((result == pcmk_ok) && xml_has_children(failed)) {
         result = -EINVAL;
     }
 
     if (result != pcmk_ok) {
         crm_log_xml_err(failed, "CIB Update failures");
         *answer = failed;
 
     } else {
         free_xml(failed);
     }
 
     return result;
 }
 
 int
 cib_process_diff(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                  xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     const char *originator = NULL;
 
     if (req != NULL) {
         originator = crm_element_value(req, F_ORIG);
     }
 
     crm_trace("Processing \"%s\" event from %s%s",
               op, originator,
               (pcmk_is_set(options, cib_force_diff)? " (global update)" : ""));
 
     free_xml(*result_cib);
     *result_cib = copy_xml(existing_cib);
     return xml_apply_patchset(*result_cib, input, TRUE);
 }
 
 gboolean
 cib_config_changed(xmlNode * last, xmlNode * next, xmlNode ** diff)
 {
     int lpc = 0, max = 0;
     gboolean config_changes = FALSE;
     xmlXPathObject *xpathObj = NULL;
     int format = 1;
 
     CRM_ASSERT(diff != NULL);
 
     if (*diff == NULL && last != NULL && next != NULL) {
         *diff = diff_xml_object(last, next, FALSE);
     }
 
     if (*diff == NULL) {
         goto done;
     }
 
     crm_element_value_int(*diff, "format", &format);
     /* This function only applies to v1 diffs. */
     CRM_LOG_ASSERT(format == 1);
 
     xpathObj = xpath_search(*diff, "//" XML_CIB_TAG_CONFIGURATION);
     if (numXpathResults(xpathObj) > 0) {
         config_changes = TRUE;
         goto done;
     }
     freeXpathObject(xpathObj);
 
     /*
      * Do not check XML_TAG_DIFF_ADDED "//" XML_TAG_CIB
      * This always contains every field and would produce a false positive
      * every time if the checked value existed
      */
     xpathObj = xpath_search(*diff, "//" XML_TAG_DIFF_REMOVED "//" XML_TAG_CIB);
     max = numXpathResults(xpathObj);
 
     for (lpc = 0; lpc < max; lpc++) {
         xmlNode *top = getXpathResult(xpathObj, lpc);
 
         if (crm_element_value(top, XML_ATTR_GENERATION) != NULL) {
             config_changes = TRUE;
             goto done;
         }
         if (crm_element_value(top, XML_ATTR_GENERATION_ADMIN) != NULL) {
             config_changes = TRUE;
             goto done;
         }
 
         if (crm_element_value(top, XML_ATTR_VALIDATION) != NULL) {
             config_changes = TRUE;
             goto done;
         }
         if (crm_element_value(top, XML_ATTR_CRM_VERSION) != NULL) {
             config_changes = TRUE;
             goto done;
         }
         if (crm_element_value(top, "remote-clear-port") != NULL) {
             config_changes = TRUE;
             goto done;
         }
         if (crm_element_value(top, "remote-tls-port") != NULL) {
             config_changes = TRUE;
             goto done;
         }
     }
 
   done:
     freeXpathObject(xpathObj);
     return config_changes;
 }
 
 int
 cib_process_xpath(const char *op, int options, const char *section, xmlNode * req, xmlNode * input,
                   xmlNode * existing_cib, xmlNode ** result_cib, xmlNode ** answer)
 {
     int lpc = 0;
     int max = 0;
     int rc = pcmk_ok;
     bool is_query = pcmk__str_eq(op, PCMK__CIB_REQUEST_QUERY, pcmk__str_none);
 
     xmlXPathObjectPtr xpathObj = NULL;
 
     crm_trace("Processing \"%s\" event", op);
 
     if (is_query) {
         xpathObj = xpath_search(existing_cib, section);
     } else {
         xpathObj = xpath_search(*result_cib, section);
     }
 
     max = numXpathResults(xpathObj);
 
-    if (max < 1 && pcmk__str_eq(op, CIB_OP_DELETE, pcmk__str_casei)) {
+    if ((max < 1)
+        && pcmk__str_eq(op, PCMK__CIB_REQUEST_DELETE, pcmk__str_none)) {
         crm_debug("%s was already removed", section);
 
     } else if (max < 1) {
         crm_debug("%s: %s does not exist", op, section);
         rc = -ENXIO;
 
     } else if (is_query) {
         if (max > 1) {
             *answer = create_xml_node(NULL, "xpath-query");
         }
     }
 
-    if (pcmk__str_eq(op, CIB_OP_DELETE, pcmk__str_casei) && (options & cib_multiple)) {
+    if (pcmk_is_set(options, cib_multiple)
+        && pcmk__str_eq(op, PCMK__CIB_REQUEST_DELETE, pcmk__str_none)) {
         dedupXpathResults(xpathObj);
     }
 
     for (lpc = 0; lpc < max; lpc++) {
         xmlChar *path = NULL;
         xmlNode *match = getXpathResult(xpathObj, lpc);
 
         if (match == NULL) {
             continue;
         }
 
         path = xmlGetNodePath(match);
         crm_debug("Processing %s op for %s with %s", op, section, path);
         free(path);
 
-        if (pcmk__str_eq(op, CIB_OP_DELETE, pcmk__str_casei)) {
+        if (pcmk__str_eq(op, PCMK__CIB_REQUEST_DELETE, pcmk__str_none)) {
             if (match == *result_cib) {
                 /* Attempting to delete the whole "/cib" */
                 crm_warn("Cannot perform %s for %s: The xpath is addressing the whole /cib", op, section);
                 rc = -EINVAL;
                 break;
             }
 
             free_xml(match);
             if ((options & cib_multiple) == 0) {
                 break;
             }
 
         } else if (pcmk__str_eq(op, PCMK__CIB_REQUEST_MODIFY, pcmk__str_none)) {
             if (update_xml_child(match, input) == FALSE) {
                 rc = -ENXIO;
             } else if ((options & cib_multiple) == 0) {
                 break;
             }
 
         } else if (pcmk__str_eq(op, PCMK__CIB_REQUEST_CREATE, pcmk__str_none)) {
             add_node_copy(match, input);
             break;
 
         } else if (pcmk__str_eq(op, PCMK__CIB_REQUEST_QUERY, pcmk__str_none)) {
 
             if (options & cib_no_children) {
                 const char *tag = TYPE(match);
                 xmlNode *shallow = create_xml_node(*answer, tag);
 
                 copy_in_properties(shallow, match);
 
                 if (*answer == NULL) {
                     *answer = shallow;
                 }
 
             } else if (options & cib_xpath_address) {
                 char *path = NULL;
                 xmlNode *parent = match;
 
                 while (parent && parent->type == XML_ELEMENT_NODE) {
                     const char *id = crm_element_value(parent, XML_ATTR_ID);
                     char *new_path = NULL;
 
                     if (id) {
                         new_path = crm_strdup_printf("/%s[@id='%s']%s",
                                                      parent->name, id,
                                                      (path? path : ""));
                     } else {
                         new_path = crm_strdup_printf("/%s%s", parent->name,
                                                      (path? path : ""));
                     }
                     free(path);
                     path = new_path;
                     parent = parent->parent;
                 }
                 crm_trace("Got: %s", path);
 
                 if (*answer == NULL) {
                     *answer = create_xml_node(NULL, "xpath-query");
                 }
                 parent = create_xml_node(*answer, "xpath-query-path");
                 crm_xml_add(parent, XML_ATTR_ID, path);
                 free(path);
 
             } else if (*answer) {
                 add_node_copy(*answer, match);
 
             } else {
                 *answer = match;
             }
 
         } else if (pcmk__str_eq(op, CIB_OP_REPLACE, pcmk__str_casei)) {
             xmlNode *parent = match->parent;
 
             free_xml(match);
             if (input != NULL) {
                 add_node_copy(parent, input);
             }
 
             if ((options & cib_multiple) == 0) {
                 break;
             }
         }
     }
 
     freeXpathObject(xpathObj);
     return rc;
 }
 
 /* remove this function */
 gboolean
 update_results(xmlNode * failed, xmlNode * target, const char *operation, int return_code)
 {
     xmlNode *xml_node = NULL;
     gboolean was_error = FALSE;
     const char *error_msg = NULL;
 
     if (return_code != pcmk_ok) {
         error_msg = pcmk_strerror(return_code);
 
         was_error = TRUE;
         xml_node = create_xml_node(failed, XML_FAIL_TAG_CIB);
         add_node_copy(xml_node, target);
 
         crm_xml_add(xml_node, XML_FAILCIB_ATTR_ID, ID(target));
         crm_xml_add(xml_node, XML_FAILCIB_ATTR_OBJTYPE, TYPE(target));
         crm_xml_add(xml_node, XML_FAILCIB_ATTR_OP, operation);
         crm_xml_add(xml_node, XML_FAILCIB_ATTR_REASON, error_msg);
 
         crm_warn("Action %s failed: %s (cde=%d)", operation, error_msg, return_code);
     }
 
     return was_error;
 }
diff --git a/tools/cibadmin.c b/tools/cibadmin.c
index 92255ca7e6..5a6af7c9f0 100644
--- a/tools/cibadmin.c
+++ b/tools/cibadmin.c
@@ -1,918 +1,918 @@
 /*
  * Copyright 2004-2022 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 #include <stdio.h>
 #include <crm/crm.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/ipc.h>
 #include <crm/cib/internal.h>
 
 #include <pacemaker-internal.h>
 
 static int message_timeout_ms = 30;
 static int command_options = 0;
 static int request_id = 0;
 static int bump_log_num = 0;
 
 static char *host = NULL;
 static const char *cib_user = NULL;
 static const char *cib_action = NULL;
 static const char *obj_type = NULL;
 
 static cib_t *the_cib = NULL;
 static GMainLoop *mainloop = NULL;
 static gboolean force_flag = FALSE;
 static crm_exit_t exit_code = CRM_EX_OK;
 
 int do_init(void);
 int do_work(xmlNode *input, int command_options, xmlNode **output);
 void cibadmin_op_callback(xmlNode *msg, int call_id, int rc, xmlNode *output,
                           void *user_data);
 
 static pcmk__cli_option_t long_options[] = {
     // long option, argument type, storage, short option, description, flags
     {
         "help", no_argument, NULL, '?',
         "\tThis text", pcmk__option_default
     },
     {
         "version", no_argument, NULL, '$',
         "\tVersion information", pcmk__option_default
     },
     {
         "verbose", no_argument, NULL, 'V',
         "\tIncrease debug output\n", pcmk__option_default
     },
 
     {
         "-spacer-", no_argument, NULL, '-',
         "Commands:", pcmk__option_default
     },
     {
         "upgrade", no_argument, NULL, 'u',
         "\tUpgrade the configuration to the latest syntax", pcmk__option_default
     },
     {
         "query", no_argument, NULL, 'Q',
         "\tQuery the contents of the CIB", pcmk__option_default
     },
     {
         "erase", no_argument, NULL, 'E',
         "\tErase the contents of the whole CIB", pcmk__option_default
     },
     {
         "bump", no_argument, NULL, 'B',
         "\tIncrease the CIB's epoch value by 1", pcmk__option_default
     },
     {
         "create", no_argument, NULL, 'C',
         "\tCreate an object in the CIB (will fail if object already exists)",
         pcmk__option_default
     },
     {
         "modify", no_argument, NULL, 'M',
         "\tFind object somewhere in CIB's XML tree and update it "
             "(fails if object does not exist unless -c is also specified)",
         pcmk__option_default
     },
     {
         "patch", no_argument, NULL, 'P',
         "\tSupply an update in the form of an XML diff (see crm_diff(8))",
         pcmk__option_default
     },
     {
         "replace", no_argument, NULL, 'R',
         "\tRecursively replace an object in the CIB", pcmk__option_default
     },
     {
         "delete", no_argument, NULL, 'D',
         "\tDelete first object matching supplied criteria "
             "(for example, <op id=\"rsc1_op1\" name=\"monitor\"/>)",
         pcmk__option_default
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "\n\tThe XML element name and all attributes must match "
             "in order for the element to be deleted.\n",
         pcmk__option_default
     },
     {
         "delete-all", no_argument, NULL, 'd',
         "When used with --xpath, remove all matching objects in the "
             "configuration instead of just the first one",
         pcmk__option_default
     },
     {
         "empty", no_argument, NULL, 'a',
         "\tOutput an empty CIB", pcmk__option_default
     },
     {
         "md5-sum", no_argument, NULL, '5',
         "\tCalculate the on-disk CIB digest", pcmk__option_default
     },
     {
         "md5-sum-versioned", no_argument, NULL, '6',
         "Calculate an on-the-wire versioned CIB digest", pcmk__option_default
     },
     {
         "show-access", optional_argument, NULL, 'S',
         "Whether to use syntax highlighting for ACLs "
             "(with -Q/--query and -U/--user)",
         pcmk__option_default
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "\n\tThat amounts to one of \"color\" (default for terminal),"
             " \"text\" (otherwise), \"namespace\", or \"auto\""
             " (per former defaults).",
         pcmk__option_default
     },
     {
         "blank", no_argument, NULL, '-',
         NULL, pcmk__option_hidden
     },
 
     {
         "-spacer-", required_argument, NULL, '-',
         "\nAdditional options:", pcmk__option_default
     },
     {
         "force", no_argument, NULL, 'f',
         NULL, pcmk__option_default
     },
     {
         "timeout", required_argument, NULL, 't',
         "Time (in seconds) to wait before declaring the operation failed",
         pcmk__option_default
     },
     {
         "user", required_argument, NULL, 'U',
         "Run the command with permissions of the named user (valid only for "
             "the root and " CRM_DAEMON_USER " accounts)",
         pcmk__option_default
     },
     {
         "sync-call", no_argument, NULL, 's',
         "Wait for call to complete before returning", pcmk__option_default
     },
     {
         "local", no_argument, NULL, 'l',
         "\tCommand takes effect locally (should be used only for queries)",
         pcmk__option_default
     },
     {
         "allow-create", no_argument, NULL, 'c',
         "(Advanced) Allow target of --modify/-M to be created "
             "if it does not exist",
         pcmk__option_default
     },
     {
         "no-children", no_argument, NULL, 'n',
         "(Advanced) When querying an object, do not include its children "
             "in the result",
         pcmk__option_default
     },
     {
         "no-bcast", no_argument, NULL, 'b',
         NULL, pcmk__option_hidden
     },
 
     {
         "-spacer-", no_argument, NULL, '-',
         "\nData:", pcmk__option_default
     },
     {
         "xml-text", required_argument, NULL, 'X',
         "Retrieve XML from the supplied string", pcmk__option_default
     },
     {
         "xml-file", required_argument, NULL, 'x',
         "Retrieve XML from the named file", pcmk__option_default
     },
     {
         "xml-pipe", no_argument, NULL, 'p',
         "Retrieve XML from stdin\n", pcmk__option_default
     },
 
     {
         "scope", required_argument, NULL, 'o',
         "Limit scope of operation to specific section of CIB",
         pcmk__option_default
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "\tValid values: configuration, nodes, resources, constraints, "
             "crm_config, rsc_defaults, op_defaults, acls, fencing-topology, "
             "tags, alerts",
         pcmk__option_default
     },
 
     {
         "xpath", required_argument, NULL, 'A',
         "A valid XPath to use instead of --scope/-o", pcmk__option_default
     },
     {
         "node-path", no_argument, NULL, 'e',
         "When performing XPath queries, return path of any matches found",
         pcmk__option_default
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "\t(for example, \"/cib/configuration/resources/clone[@id='ms_RH1_SCS']"
             "/primitive[@id='prm_RH1_SCS']\")",
         pcmk__option_paragraph
     },
     {
         "node", required_argument, NULL, 'N',
         "(Advanced) Send command to the specified host", pcmk__option_default
     },
     {
         "-spacer-", no_argument, NULL, '!',
         NULL, pcmk__option_hidden
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "\n\nExamples:\n", pcmk__option_default
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "Query the configuration from the local node:", pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --query --local", pcmk__option_example
     },
 
     {
         "-spacer-", no_argument, NULL, '-',
         "Query just the cluster options configuration:", pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --query --scope crm_config", pcmk__option_example
     },
 
     {
         "-spacer-", no_argument, NULL, '-',
         "Query all 'target-role' settings:", pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --query --xpath \"//nvpair[@name='target-role']\"",
         pcmk__option_example
     },
 
     {
         "-spacer-", no_argument, NULL, '-',
         "Remove all 'is-managed' settings:", pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --delete-all --xpath \"//nvpair[@name='is-managed']\"",
         pcmk__option_example
     },
 
     {
         "-spacer-", no_argument, NULL, '-',
         "Remove the resource named 'old':", pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --delete --xml-text '<primitive id=\"old\"/>'",
         pcmk__option_example
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "Remove all resources from the configuration:", pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --replace --scope resources --xml-text '<resources/>'",
         pcmk__option_example
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "Replace complete configuration with contents of $HOME/pacemaker.xml:",
         pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --replace --xml-file $HOME/pacemaker.xml",
         pcmk__option_example
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "Replace constraints section of configuration with contents of "
             "$HOME/constraints.xml:",
         pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --replace --scope constraints --xml-file "
             "$HOME/constraints.xml",
         pcmk__option_example
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "Increase configuration version to prevent old configurations from "
             "being loaded accidentally:",
         pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --modify --xml-text '<cib admin_epoch=\"admin_epoch++\"/>'",
         pcmk__option_example
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "Edit the configuration with your favorite $EDITOR:",
         pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --query > $HOME/local.xml", pcmk__option_example
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " $EDITOR $HOME/local.xml", pcmk__option_example
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --replace --xml-file $HOME/local.xml", pcmk__option_example
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "Assuming terminal, render configuration in color (green for writable, blue for readable, red for denied) to visualize permissions for user tony:",
         pcmk__option_paragraph
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " cibadmin --show-access=color --query --user tony | less -r",
         pcmk__option_example
     },
     {
         "-spacer-", no_argument, NULL, '-',
         "SEE ALSO:", pcmk__option_default
     },
     {
         "-spacer-", no_argument, NULL, '-',
         " crm(8), pcs(8), crm_shadow(8), crm_diff(8)", pcmk__option_default
     },
     {
         "host", required_argument, NULL, 'h',
         "deprecated", pcmk__option_hidden
     },
     { 0, 0, 0, 0 }
 };
 
 static void
 print_xml_output(xmlNode * xml)
 {
     char *buffer;
 
     if (!xml) {
         return;
     } else if (xml->type != XML_ELEMENT_NODE) {
         return;
     }
 
     if (command_options & cib_xpath_address) {
         const char *id = crm_element_value(xml, XML_ATTR_ID);
 
         if (pcmk__str_eq((const char *)xml->name, "xpath-query", pcmk__str_casei)) {
             xmlNode *child = NULL;
 
             for (child = xml->children; child; child = child->next) {
                 print_xml_output(child);
             }
 
         } else if (id) {
             printf("%s\n", id);
         }
 
     } else {
         buffer = dump_xml_formatted(xml);
         fprintf(stdout, "%s", pcmk__s(buffer, "<null>\n"));
         free(buffer);
     }
 }
 
 // Upgrade requested but already at latest schema
 static void
 report_schema_unchanged(void)
 {
     const char *err = pcmk_rc_str(pcmk_rc_schema_unchanged);
 
     crm_info("Upgrade unnecessary: %s\n", err);
     printf("Upgrade unnecessary: %s\n", err);
     exit_code = CRM_EX_OK;
 }
 
 int
 main(int argc, char **argv)
 {
     int argerr = 0;
     int rc = pcmk_ok;
     int flag;
     const char *source = NULL;
     const char *admin_input_xml = NULL;
     const char *admin_input_file = NULL;
     gboolean dangerous_cmd = FALSE;
     gboolean admin_input_stdin = FALSE;
     xmlNode *output = NULL;
     xmlNode *input = NULL;
     char *username = NULL;
     const char *acl_cred = NULL;
     enum acl_eval_how {
         acl_eval_unused,
         acl_eval_auto,
         acl_eval_namespace,
         acl_eval_text,
         acl_eval_color,
     } acl_eval_how = acl_eval_unused;
 
     int option_index = 0;
 
     pcmk__cli_init_logging("cibadmin", 0);
     set_crm_log_level(LOG_CRIT);
     pcmk__set_cli_options(NULL, "<command> [options]", long_options,
                           "query and edit the Pacemaker configuration");
 
     if (argc < 2) {
         pcmk__cli_help('?', CRM_EX_USAGE);
     }
 
     while (1) {
         flag = pcmk__next_cli_option(argc, argv, &option_index, NULL);
         if (flag == -1)
             break;
 
         switch (flag) {
             case 't':
                 message_timeout_ms = atoi(optarg);
                 if (message_timeout_ms < 1) {
                     message_timeout_ms = 30;
                 }
                 break;
             case 'A':
                 obj_type = optarg;
                 cib__set_call_options(command_options, crm_system_name,
                                       cib_xpath);
                 break;
             case 'e':
                 cib__set_call_options(command_options, crm_system_name,
                                       cib_xpath_address);
                 break;
             case 'u':
                 cib_action = CIB_OP_UPGRADE;
                 dangerous_cmd = TRUE;
                 break;
             case 'E':
                 cib_action = CIB_OP_ERASE;
                 dangerous_cmd = TRUE;
                 break;
             case 'S':
                 if (optarg != NULL) {
                     if (!strcmp(optarg, "auto")) {
                         acl_eval_how = acl_eval_auto;
                     } else if (!strcmp(optarg, "namespace")) {
                         acl_eval_how = acl_eval_namespace;
                     } else if (!strcmp(optarg, "text")) {
                         acl_eval_how = acl_eval_text;
                     } else if (!strcmp(optarg, "color")) {
                         acl_eval_how = acl_eval_color;
                     } else {
                         fprintf(stderr, "Unrecognized value for --show-access: \"%s\"\n",
                                optarg);
                         ++argerr;
                     }
                 } else {
                     acl_eval_how = acl_eval_auto;
                 }
                 /* XXX this is a workaround until we unify happy paths for
                        both a/sync handling; the respective extra code is
                        only in sync path now, but does it matter at all for
                        query-like request wrt. what blackbox users observe? */
                 command_options |= cib_sync_call;
                 break;
             case 'Q':
                 cib_action = PCMK__CIB_REQUEST_QUERY;
                 break;
             case 'P':
                 cib_action = CIB_OP_APPLY_DIFF;
                 break;
             case 'U':
                 cib_user = optarg;
                 break;
             case 'M':
                 cib_action = PCMK__CIB_REQUEST_MODIFY;
                 break;
             case 'R':
                 cib_action = CIB_OP_REPLACE;
                 break;
             case 'C':
                 cib_action = PCMK__CIB_REQUEST_CREATE;
                 break;
             case 'D':
-                cib_action = CIB_OP_DELETE;
+                cib_action = PCMK__CIB_REQUEST_DELETE;
                 break;
             case '5':
                 cib_action = "md5-sum";
                 break;
             case '6':
                 cib_action = "md5-sum-versioned";
                 break;
             case 'c':
                 cib__set_call_options(command_options, crm_system_name,
                                       cib_can_create);
                 break;
             case 'n':
                 cib__set_call_options(command_options, crm_system_name,
                                       cib_no_children);
                 break;
             case 'B':
                 cib_action = PCMK__CIB_REQUEST_BUMP;
                 crm_log_args(argc, argv);
                 break;
             case 'V':
                 cib__set_call_options(command_options, crm_system_name,
                                       cib_verbose);
                 bump_log_num++;
                 break;
             case '?':
             case '$':
             case '!':
                 pcmk__cli_help(flag, CRM_EX_OK);
                 break;
             case 'o':
                 crm_trace("Option %c => %s", flag, optarg);
                 obj_type = optarg;
                 break;
             case 'X':
                 crm_trace("Option %c => %s", flag, optarg);
                 admin_input_xml = optarg;
                 crm_log_args(argc, argv);
                 break;
             case 'x':
                 crm_trace("Option %c => %s", flag, optarg);
                 admin_input_file = optarg;
                 crm_log_args(argc, argv);
                 break;
             case 'p':
                 admin_input_stdin = TRUE;
                 crm_log_args(argc, argv);
                 break;
             case 'N':
             case 'h':
                 pcmk__str_update(&host, optarg);
                 break;
             case 'l':
                 cib__set_call_options(command_options, crm_system_name,
                                       cib_scope_local);
                 break;
             case 'd':
-                cib_action = CIB_OP_DELETE;
+                cib_action = PCMK__CIB_REQUEST_DELETE;
                 cib__set_call_options(command_options, crm_system_name,
                                       cib_multiple);
                 dangerous_cmd = TRUE;
                 break;
             case 'b':
                 dangerous_cmd = TRUE;
                 cib__set_call_options(command_options, crm_system_name,
                                       cib_inhibit_bcast|cib_scope_local);
                 break;
             case 's':
                 cib__set_call_options(command_options, crm_system_name,
                                       cib_sync_call);
                 break;
             case 'f':
                 force_flag = TRUE;
                 cib__set_call_options(command_options, crm_system_name,
                                       cib_quorum_override);
                 crm_log_args(argc, argv);
                 break;
             case 'a':
                 output = createEmptyCib(1);
                 if (optind < argc) {
                     crm_xml_add(output, XML_ATTR_VALIDATION, argv[optind]);
                 }
                 admin_input_xml = dump_xml_formatted(output);
                 fprintf(stdout, "%s", pcmk__s(admin_input_xml, "<null>\n"));
                 crm_exit(CRM_EX_OK);
                 break;
             default:
                 printf("Argument code 0%o (%c)" " is not (?yet?) supported\n", flag, flag);
                 ++argerr;
                 break;
         }
     }
 
     while (bump_log_num > 0) {
         crm_bump_log_level(argc, argv);
         bump_log_num--;
     }
 
     if (optind < argc) {
         printf("non-option ARGV-elements: ");
         while (optind < argc)
             printf("%s ", argv[optind++]);
         printf("\n");
         pcmk__cli_help('?', CRM_EX_USAGE);
     }
 
     if (optind > argc || cib_action == NULL) {
         ++argerr;
     }
 
     if (argerr) {
         pcmk__cli_help('?', CRM_EX_USAGE);
     }
 
     if (dangerous_cmd && force_flag == FALSE) {
         fprintf(stderr, "The supplied command is considered dangerous."
                 "  To prevent accidental destruction of the cluster,"
                 " the --force flag is required in order to proceed.\n");
         fflush(stderr);
         crm_exit(CRM_EX_UNSAFE);
     }
 
     if (admin_input_file != NULL) {
         input = filename2xml(admin_input_file);
         source = admin_input_file;
 
     } else if (admin_input_xml != NULL) {
         source = "input string";
         input = string2xml(admin_input_xml);
 
     } else if (admin_input_stdin) {
         source = "STDIN";
         input = stdin2xml();
 
     } else if (acl_eval_how != acl_eval_unused) {
         username = pcmk__uid2username(geteuid());
         if (pcmk_acl_required(username)) {
             if (force_flag) {
                 fprintf(stderr, "The supplied command can provide skewed"
                                  " result since it is run under user that also"
                                  " gets guarded per ACLs on their own right."
                                  " Continuing since --force flag was"
                                  " provided.\n");
 
             } else {
                 fprintf(stderr, "The supplied command can provide skewed"
                                  " result since it is run under user that also"
                                  " gets guarded per ACLs in their own right."
                                  " To accept the risk of such a possible"
                                  " distortion (without even knowing it at this"
                                  " time), use the --force flag.\n");
                 crm_exit(CRM_EX_UNSAFE);
             }
 
         }
         free(username);
         username = NULL;
 
         if (cib_user == NULL) {
             fprintf(stderr, "The supplied command requires -U user specified.\n");
             crm_exit(CRM_EX_USAGE);
         }
 
         /* we already stopped/warned ACL-controlled users about consequences */
         acl_cred = cib_user;
         cib_user = NULL;
     }
 
     if (input != NULL) {
         crm_log_xml_debug(input, "[admin input]");
 
     } else if (source) {
         fprintf(stderr, "Couldn't parse input from %s.\n", source);
         crm_exit(CRM_EX_CONFIG);
     }
 
     if (pcmk__str_eq(cib_action, "md5-sum", pcmk__str_casei)) {
         char *digest = NULL;
 
         if (input == NULL) {
             fprintf(stderr, "Please supply XML to process with -X, -x or -p\n");
             crm_exit(CRM_EX_USAGE);
         }
 
         digest = calculate_on_disk_digest(input);
         fprintf(stderr, "Digest: ");
         fprintf(stdout, "%s\n", pcmk__s(digest, "<null>"));
         free(digest);
         free_xml(input);
         crm_exit(CRM_EX_OK);
 
     } else if (pcmk__str_eq(cib_action, "md5-sum-versioned", pcmk__str_casei)) {
         char *digest = NULL;
         const char *version = NULL;
 
         if (input == NULL) {
             fprintf(stderr, "Please supply XML to process with -X, -x or -p\n");
             crm_exit(CRM_EX_USAGE);
         }
 
         version = crm_element_value(input, XML_ATTR_CRM_VERSION);
         digest = calculate_xml_versioned_digest(input, FALSE, TRUE, version);
         fprintf(stderr, "Versioned (%s) digest: ", version);
         fprintf(stdout, "%s\n", pcmk__s(digest, "<null>"));
         free(digest);
         free_xml(input);
         crm_exit(CRM_EX_OK);
     }
 
     rc = do_init();
     if (rc != pcmk_ok) {
         crm_err("Init failed, could not perform requested operations");
         fprintf(stderr, "Init failed, could not perform requested operations\n");
         free_xml(input);
         crm_exit(pcmk_rc2exitc(pcmk_legacy2rc(rc)));
     }
 
     rc = do_work(input, command_options, &output);
     if (rc > 0) {
         /* wait for the reply by creating a mainloop and running it until
          * the callbacks are invoked...
          */
         request_id = rc;
 
         the_cib->cmds->register_callback(the_cib, request_id, message_timeout_ms, FALSE, NULL,
                                          "cibadmin_op_callback", cibadmin_op_callback);
 
         mainloop = g_main_loop_new(NULL, FALSE);
 
         crm_trace("%s waiting for reply from the local CIB", crm_system_name);
 
         crm_info("Starting mainloop");
         g_main_loop_run(mainloop);
 
     } else if ((rc == -pcmk_err_schema_unchanged)
                && pcmk__str_eq(cib_action, CIB_OP_UPGRADE, pcmk__str_none)) {
         report_schema_unchanged();
 
     } else if (rc < 0) {
         rc = pcmk_legacy2rc(rc);
         crm_err("Call failed: %s", pcmk_rc_str(rc));
         fprintf(stderr, "Call failed: %s\n", pcmk_rc_str(rc));
 
         if (rc == pcmk_rc_schema_validation) {
             if (pcmk__str_eq(cib_action, CIB_OP_UPGRADE, pcmk__str_none)) {
                 xmlNode *obj = NULL;
                 int version = 0;
 
                 if (the_cib->cmds->query(the_cib, NULL, &obj,
                                          command_options) == pcmk_ok) {
                     update_validation(&obj, &version, 0, TRUE, FALSE);
                 }
 
             } else if (output) {
                 validate_xml_verbose(output);
             }
         }
         exit_code = pcmk_rc2exitc(rc);
     }
 
     if (output != NULL && acl_eval_how != acl_eval_unused) {
         xmlDoc *acl_evaled_doc;
         rc = pcmk__acl_annotate_permissions(acl_cred, output->doc, &acl_evaled_doc);
         if (rc == pcmk_rc_ok) {
             enum pcmk__acl_render_how how;
             xmlChar *rendered = NULL;
             free_xml(output);
             switch(acl_eval_how) {
                 case acl_eval_text:
                     how = pcmk__acl_render_text;
                     break;
                 case acl_eval_color:
                     how = pcmk__acl_render_color;
                     break;
                 case acl_eval_namespace:
                     how = pcmk__acl_render_namespace;
                     break;
                 default:
                     if (/*acl_eval_auto*/ isatty(STDOUT_FILENO)) {
                         how = pcmk__acl_render_color;
                     } else {
                         how = pcmk__acl_render_text;
                     }
                     break;
             }
 
             if (!pcmk__acl_evaled_render(acl_evaled_doc, how,
                                             &rendered)) {
                 printf("%s\n", (char *) rendered);
                 free(rendered);
             } else {
                 fprintf(stderr, "Could not render evaluated access\n");
                 crm_exit(CRM_EX_CONFIG);
             }
             output = NULL;
         } else {
             fprintf(stderr, "Could not evaluate access per request (%s, error: %s)\n", acl_cred, pcmk_rc_str(rc));
             crm_exit(CRM_EX_CONFIG);
         }
     }
 
     if (output != NULL) {
         print_xml_output(output);
         free_xml(output);
     }
 
     crm_trace("%s exiting normally", crm_system_name);
 
     free_xml(input);
     rc = cib__clean_up_connection(&the_cib);
     if (exit_code == CRM_EX_OK) {
         exit_code = pcmk_rc2exitc(rc);
     }
 
     free(host);
     crm_exit(exit_code);
 }
 
 int
 do_work(xmlNode * input, int call_options, xmlNode ** output)
 {
     /* construct the request */
     the_cib->call_timeout = message_timeout_ms;
     if (strcasecmp(CIB_OP_REPLACE, cib_action) == 0
         && pcmk__str_eq(crm_element_name(input), XML_TAG_CIB, pcmk__str_casei)) {
         xmlNode *status = pcmk_find_cib_element(input, XML_CIB_TAG_STATUS);
 
         if (status == NULL) {
             create_xml_node(input, XML_CIB_TAG_STATUS);
         }
     }
 
     if (cib_action != NULL) {
         crm_trace("Passing \"%s\" to variant_op...", cib_action);
         return cib_internal_op(the_cib, cib_action, host, obj_type, input, output, call_options, cib_user);
 
     } else {
         crm_err("You must specify an operation");
     }
     return -EINVAL;
 }
 
 int
 do_init(void)
 {
     int rc = pcmk_ok;
 
     the_cib = cib_new();
     rc = the_cib->cmds->signon(the_cib, crm_system_name, cib_command);
     if (rc != pcmk_ok) {
         crm_err("Could not connect to the CIB: %s", pcmk_strerror(rc));
         fprintf(stderr, "Could not connect to the CIB: %s\n",
                 pcmk_strerror(rc));
     }
 
     return rc;
 }
 
 void
 cibadmin_op_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
 {
     rc = pcmk_legacy2rc(rc);
     exit_code = pcmk_rc2exitc(rc);
 
     if (rc == pcmk_rc_schema_unchanged) {
         report_schema_unchanged();
 
     } else if (rc != pcmk_rc_ok) {
         crm_warn("Call %s failed: %s " CRM_XS " rc=%d",
                  cib_action, pcmk_rc_str(rc), rc);
         fprintf(stderr, "Call %s failed: %s\n", cib_action, pcmk_rc_str(rc));
         print_xml_output(output);
 
     } else if (pcmk__str_eq(cib_action, PCMK__CIB_REQUEST_QUERY, pcmk__str_none)
                && (output == NULL)) {
         crm_err("Query returned no output");
         crm_log_xml_err(msg, "no output");
 
     } else if (output == NULL) {
         crm_info("Call passed");
 
     } else {
         crm_info("Call passed");
         print_xml_output(output);
     }
 
     if (call_id == request_id) {
         g_main_loop_quit(mainloop);
 
     } else {
         crm_info("Message was not the response we were looking for (%d vs. %d)",
                  call_id, request_id);
     }
 }