summaryrefslogtreecommitdiffstats
path: root/include/crm/cib
diff options
context:
space:
mode:
Diffstat (limited to 'include/crm/cib')
-rw-r--r--include/crm/cib/cib_types.h139
-rw-r--r--include/crm/cib/internal.h124
2 files changed, 238 insertions, 25 deletions
diff --git a/include/crm/cib/cib_types.h b/include/crm/cib/cib_types.h
index 5bd10e4..a803311 100644
--- a/include/crm/cib/cib_types.h
+++ b/include/crm/cib/cib_types.h
@@ -59,12 +59,54 @@ enum cib_call_options {
cib_discard_reply = (1 << 4),
cib_no_children = (1 << 5),
cib_xpath_address = (1 << 6),
+
+ //! \deprecated This value will be removed in a future release
cib_mixed_update = (1 << 7),
+
+ /* @COMPAT: cib_scope_local is processed only in the legacy function
+ * parse_local_options_v1().
+ *
+ * If (host == NULL):
+ * * In legacy mode, the CIB manager forwards a request to the primary
+ * instance unless cib_scope_local is set or the local node is primary.
+ * * Outside of legacy mode:
+ * * If a request modifies the CIB, the CIB manager forwards it to all
+ * nodes.
+ * * Otherwise, the CIB manager processes the request locally.
+ *
+ * There is no current use case for this implementing this flag in
+ * non-legacy mode.
+ */
+
+ //! \deprecated This value will be removed in a future release
cib_scope_local = (1 << 8),
+
cib_dryrun = (1 << 9),
+
+ /*!
+ * \brief Process request when the client commits the active transaction
+ *
+ * Add the request to the client's active transaction instead of processing
+ * it immediately. If the client has no active transaction, or if the
+ * request is not supported in transactions, the call will fail.
+ *
+ * The request is added to the transaction synchronously, and the return
+ * value indicates whether it was added successfully.
+ *
+ * Refer to \p cib_api_operations_t:init_transaction() and
+ * \p cib_api_operations_t:end_transaction() for more details on CIB
+ * transactions.
+ */
+ cib_transaction = (1 << 10),
+
cib_sync_call = (1 << 12),
cib_no_mtime = (1 << 13),
+
+#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
+ //! \deprecated This value will be removed in a future release
cib_zero_copy = (1 << 14),
+#endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
+
cib_inhibit_notify = (1 << 16),
#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
@@ -82,13 +124,19 @@ typedef struct cib_s cib_t;
typedef struct cib_api_operations_s {
int (*signon) (cib_t *cib, const char *name, enum cib_conn_type type);
+
+ //! \deprecated This method will be removed and should not be used
int (*signon_raw) (cib_t *cib, const char *name, enum cib_conn_type type,
int *event_fd);
+
int (*signoff) (cib_t *cib);
int (*free) (cib_t *cib);
+
+ //! \deprecated This method will be removed and should not be used
int (*set_op_callback) (cib_t *cib, void (*callback) (const xmlNode *msg,
int callid, int rc,
xmlNode *output));
+
int (*add_notify_callback) (cib_t *cib, const char *event,
void (*callback) (const char *event,
xmlNode *msg));
@@ -97,8 +145,13 @@ typedef struct cib_api_operations_s {
xmlNode *msg));
int (*set_connection_dnotify) (cib_t *cib,
void (*dnotify) (gpointer user_data));
+
+ //! \deprecated This method will be removed and should not be used
int (*inputfd) (cib_t *cib);
+
+ //! \deprecated This method will be removed and should not be used
int (*noop) (cib_t *cib, int call_options);
+
int (*ping) (cib_t *cib, xmlNode **output_data, int call_options);
int (*query) (cib_t *cib, const char *section, xmlNode **output_data,
int call_options);
@@ -141,7 +194,9 @@ typedef struct cib_api_operations_s {
int (*delete_absolute) (cib_t *cib, const char *section, xmlNode *data,
int call_options);
+ //! \deprecated This method is not implemented and should not be used
int (*quit) (cib_t *cib, int call_options);
+
int (*register_notification) (cib_t *cib, const char *callback,
int enabled);
gboolean (*register_callback) (cib_t *cib, int call_id, int timeout,
@@ -190,14 +245,85 @@ typedef struct cib_api_operations_s {
*
* \return Legacy Pacemaker return code
*
- * \note The client IDs are assigned by \p pacemaker-based when the client
- * connects. \p cib_t variants that don't connect to
- * \p pacemaker-based may never be assigned a client ID.
* \note Some variants may have only one client for both asynchronous and
* synchronous requests.
*/
int (*client_id)(const cib_t *cib, const char **async_id,
const char **sync_id);
+
+ /*!
+ * \brief Initiate an atomic CIB transaction for this client
+ *
+ * If the client has initiated a transaction and a new request's call
+ * options contain \p cib_transaction, the new request is appended to the
+ * transaction for later processing.
+ *
+ * Supported requests are those that meet the following conditions:
+ * * can be processed synchronously (with any changes applied to a working
+ * CIB copy)
+ * * are not queries
+ * * do not involve other nodes
+ * * do not affect the state of pacemaker-based itself
+ *
+ * Currently supported CIB API functions include:
+ * * \p bump_epoch()
+ * * \p create()
+ * * \p erase()
+ * * \p modify()
+ * * \p remove()
+ * * \p replace()
+ * * \p upgrade()
+ *
+ * Because the transaction is atomic, individual requests do not trigger
+ * callbacks or notifications when they are processed, and they do not
+ * receive output XML. The commit request itself can trigger callbacks and
+ * notifications if any are registered.
+ *
+ * An \c init_transaction() call is always synchronous.
+ *
+ * \param[in,out] cib CIB connection
+ *
+ * \return Legacy Pacemaker return code
+ */
+ int (*init_transaction)(cib_t *cib);
+
+ /*!
+ * \brief End and optionally commit this client's CIB transaction
+ *
+ * When a client commits a transaction, all requests in the transaction are
+ * processed in a FIFO manner until either a request fails or all requests
+ * have been processed. Changes are applied to a working copy of the CIB.
+ * If a request fails, the transaction and working CIB copy are discarded,
+ * and an error is returned. If all requests succeed, the working CIB copy
+ * replaces the initial CIB copy.
+ *
+ * Callbacks and notifications can be triggered by the commit request itself
+ * but not by the individual requests in a transaction.
+ *
+ * An \c end_transaction() call with \p commit set to \c false is always
+ * synchronous.
+ *
+ * \param[in,out] cib CIB connection
+ * \param[in] commit If \p true, commit transaction; otherwise,
+ * discard it
+ * \param[in] call_options Group of <tt>enum cib_call_options</tt>
+ * flags
+ *
+ * \return Legacy Pacemaker return code
+ */
+ int (*end_transaction)(cib_t *cib, bool commit, int call_options);
+
+ /*!
+ * \brief Set the user as whom all CIB requests via methods will be executed
+ *
+ * By default, the value of the \c CIB_user environment variable is used if
+ * set. Otherwise, \c root is used.
+ *
+ * \param[in,out] cib CIB connection
+ * \param[in] user Name of user whose permissions to use when
+ * processing requests
+ */
+ void (*set_user)(cib_t *cib, const char *user);
} cib_api_operations_t;
struct cib_s {
@@ -211,9 +337,16 @@ struct cib_s {
void *delegate_fn;
GList *notify_list;
+
+ //! \deprecated This method will be removed in a future release
void (*op_callback) (const xmlNode *msg, int call_id, int rc,
xmlNode *output);
+
cib_api_operations_t *cmds;
+
+ xmlNode *transaction;
+
+ char *user;
};
#ifdef __cplusplus
diff --git a/include/crm/cib/internal.h b/include/crm/cib/internal.h
index 374902b..20059ec 100644
--- a/include/crm/cib/internal.h
+++ b/include/crm/cib/internal.h
@@ -15,7 +15,6 @@
// 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"
@@ -32,6 +31,7 @@
#define PCMK__CIB_REQUEST_ABS_DELETE "cib_delete_alt"
#define PCMK__CIB_REQUEST_NOOP "noop"
#define PCMK__CIB_REQUEST_SHUTDOWN "cib_shutdown_req"
+#define PCMK__CIB_REQUEST_COMMIT_TRANSACT "cib_commit_transact"
# define F_CIB_CLIENTID "cib_clientid"
# define F_CIB_CALLOPTS "cib_callopt"
@@ -60,34 +60,72 @@
# 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_COMMAND "cib_command"
# 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_TRANSACTION "cib_transaction"
# define T_CIB_UPDATE_CONFIRM "cib_update_confirmation"
-# define T_CIB_REPLACE_NOTIFY "cib_refresh_notify"
/*!
* \internal
- * \enum cib_change_section_info
- * \brief Flags to indicate which sections of the CIB have changed
+ * \enum cib__op_attr
+ * \brief Flags for CIB operation attributes
*/
-enum cib_change_section_info {
- cib_change_section_none = 0, //!< No sections have changed
- cib_change_section_nodes = (1 << 0), //!< The nodes section has changed
- cib_change_section_alerts = (1 << 1), //!< The alerts section has changed
- cib_change_section_status = (1 << 2), //!< The status section has changed
+enum cib__op_attr {
+ cib__op_attr_none = 0, //!< No special attributes
+ cib__op_attr_modifies = (1 << 1), //!< Modifies CIB
+ cib__op_attr_privileged = (1 << 2), //!< Requires privileges
+ cib__op_attr_local = (1 << 3), //!< Must only be processed locally
+ cib__op_attr_replaces = (1 << 4), //!< Replaces CIB
+ cib__op_attr_writes_through = (1 << 5), //!< Writes to disk on success
+ cib__op_attr_transaction = (1 << 6), //!< Supported in a transaction
};
+/*!
+ * \internal
+ * \enum cib__op_type
+ * \brief Types of CIB operations
+ */
+enum cib__op_type {
+ cib__op_abs_delete,
+ cib__op_apply_patch,
+ cib__op_bump,
+ cib__op_commit_transact,
+ cib__op_create,
+ cib__op_delete,
+ cib__op_erase,
+ cib__op_is_primary,
+ cib__op_modify,
+ cib__op_noop,
+ cib__op_ping,
+ cib__op_primary,
+ cib__op_query,
+ cib__op_replace,
+ cib__op_secondary,
+ cib__op_shutdown,
+ cib__op_sync_all,
+ cib__op_sync_one,
+ cib__op_upgrade,
+};
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);
+typedef int (*cib__op_fn_t)(const char *, int, const char *, xmlNode *,
+ xmlNode *, xmlNode *, xmlNode **, xmlNode **);
+
+typedef struct cib__operation_s {
+ const char *name;
+ enum cib__op_type type;
+ uint32_t flags; //!< Group of <tt>enum cib__op_attr</tt> flags
+} cib__operation_t;
+
typedef struct cib_notify_client_s {
const char *event;
const char *obj_id; /* implement one day */
@@ -124,24 +162,66 @@ struct timer_rec_s {
(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 *op, const char *host,
- const char *section, xmlNode * data, int call_options,
- const char *user_name);
+/*!
+ * \internal
+ * \brief Check whether a given CIB client's update should trigger a refresh
+ *
+ * Here, "refresh" means that Pacemaker daemons write out their current state.
+ *
+ * If a Pacemaker daemon or one of certain Pacemaker CLI tools modifies the CIB,
+ * we can assume that the CIB hasn't diverged from the true cluster state. A
+ * "safe" CLI tool requests that all relevant daemons update their state before
+ * the tool requests any CIB modifications directly.
+ *
+ * In contrast, other "unsafe" tools (for example, \c cibadmin and external
+ * tools) may request arbitrary CIB changes.
+ *
+ * A Pacemaker daemon can write out its current state to the CIB when it's
+ * notified of an update from an unsafe client, to ensure the CIB still contains
+ * the daemon's correct state.
+ *
+ * \param[in] name CIB client name
+ *
+ * \return \c true if the CIB client should trigger a refresh, or \c false
+ * otherwise
+ */
+static inline bool
+cib__client_triggers_refresh(const char *name)
+{
+ return !crm_is_daemon_name(name)
+ && !pcmk__str_any_of(name,
+ "attrd_updater",
+ "crm_attribute",
+ "crm_node",
+ "crm_resource",
+ "crm_ticket",
+ NULL);
+}
+
+int cib__get_notify_patchset(const xmlNode *msg, const xmlNode **patchset);
+
+bool cib__element_in_patchset(const xmlNode *patchset, const char *element);
+
+int cib_perform_op(const char *op, int call_options, cib__op_fn_t fn,
+ bool is_query, const char *section, xmlNode *req,
+ xmlNode *input, bool manage_counters, bool *config_changed,
+ xmlNode **current_cib, xmlNode **result_cib, xmlNode **diff,
+ xmlNode **output);
+
+int cib__create_op(cib_t *cib, const char *op, const char *host,
+ const char *section, xmlNode *data, int call_options,
+ const char *user_name, const char *client_name,
+ xmlNode **op_msg);
+
+int cib__extend_transaction(cib_t *cib, xmlNode *request);
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__get_operation(const char *op, const cib__operation_t **operation);
+
int cib_process_query(const char *op, int options, const char *section, xmlNode * req,
xmlNode * input, xmlNode * existing_cib, xmlNode ** result_cib,
xmlNode ** answer);