diff --git a/daemons/based/based_common.c b/daemons/based/based_common.c
index 3b6832b23c..8146fc1a57 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
     },
     {
         CIB_OP_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
     },
     {
-        CIB_OP_CREATE, TRUE, TRUE, TRUE,
+        PCMK__CIB_REQUEST_CREATE, TRUE, TRUE, TRUE,
         cib_prepare_data, cib_cleanup_data, cib_process_create
     },
     {
         CIB_OP_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/include/crm/cib/internal.h b/include/crm/cib/internal.h
index 1f687f49bc..c54492030c 100644
--- a/include/crm/cib/internal.h
+++ b/include/crm/cib/internal.h
@@ -1,261 +1,261 @@
 /*
  * 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 CIB_OP_CREATE	"cib_create"
+#define PCMK__CIB_REQUEST_CREATE        "cib_create"
 #  define CIB_OP_MODIFY	"cib_modify"
 #  define CIB_OP_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
- *                              CIB_OP_CREATE, CIB_OP_MODIFY, and
+ *                              PCMK__CIB_REQUEST_CREATE, CIB_OP_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
- *                              CIB_OP_CREATE, CIB_OP_MODIFY, CIB_OP_DELETE, and
- *                              CIB_OP_REPLACE)
+ *                              PCMK__CIB_REQUEST_CREATE, CIB_OP_MODIFY,
+ *                              CIB_OP_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_client.c b/lib/cib/cib_client.c
index 5bfc1c23db..beaf7a3815 100644
--- a/lib/cib/cib_client.c
+++ b/lib/cib/cib_client.c
@@ -1,711 +1,712 @@
 /*
  * 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, CIB_OP_CREATE, NULL, section, data, NULL, call_options, NULL);
+    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, CIB_OP_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, CIB_OP_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);
 }
 
 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 13c27a5fd4..8e9e6f498c 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},
     {CIB_OP_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},
-    {CIB_OP_CREATE,     FALSE, cib_process_create},
+    { PCMK__CIB_REQUEST_CREATE,     FALSE,  cib_process_create },
     {CIB_OP_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 16cf91b66c..4a9fdc1d5c 100644
--- a/lib/cib/cib_ops.c
+++ b/lib/cib/cib_ops.c
@@ -1,854 +1,855 @@
 /*
  * 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(CIB_OP_CREATE, 0, path, NULL, tmp_section, NULL, result_cib, answer);
+        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(strcasecmp(CIB_OP_CREATE, op) == 0, return -EINVAL);
+    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)) {
         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)) {
         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 (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, CIB_OP_MODIFY, pcmk__str_casei)) {
             if (update_xml_child(match, input) == FALSE) {
                 rc = -ENXIO;
             } else if ((options & cib_multiple) == 0) {
                 break;
             }
 
-        } else if (pcmk__str_eq(op, CIB_OP_CREATE, pcmk__str_casei)) {
+        } 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 7b966bb84d..ab21a0b254 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 = CIB_OP_MODIFY;
                 break;
             case 'R':
                 cib_action = CIB_OP_REPLACE;
                 break;
             case 'C':
-                cib_action = CIB_OP_CREATE;
+                cib_action = PCMK__CIB_REQUEST_CREATE;
                 break;
             case 'D':
                 cib_action = CIB_OP_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__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);
     }
 }