diff options
Diffstat (limited to 'include/crm/cib')
-rw-r--r-- | include/crm/cib/cib_types.h | 139 | ||||
-rw-r--r-- | include/crm/cib/internal.h | 124 |
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); |