diff options
Diffstat (limited to '')
79 files changed, 3624 insertions, 1577 deletions
diff --git a/include/Makefile.am b/include/Makefile.am index dfd7085..6618c7a 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2003-2019 the Pacemaker project contributors +# Copyright 2003-2023 the Pacemaker project contributors # # The version control history for this file may have further details. # @@ -7,14 +7,15 @@ # or later (GPLv2+) WITHOUT ANY WARRANTY. # -MAINTAINERCLEANFILES = Makefile.in config.h.in +MAINTAINERCLEANFILES = Makefile.in \ + config.h.in -noinst_HEADERS = config.h \ - crm_internal.h \ - doxygen.h \ - pacemaker.h \ - pacemaker-internal.h \ - portability.h \ +noinst_HEADERS = config.h \ + crm_internal.h \ + doxygen.h \ + pacemaker.h \ + pacemaker-internal.h \ + portability.h \ gettext.h pkginclude_HEADERS = crm_config.h @@ -24,16 +25,17 @@ SUBDIRS = crm pcmki GETTEXT_H ?= $(datadir)/gettext/gettext.h +.PHONY: update-gettext update-gettext: @if [ ! -e "$(GETTEXT_H)" ]; then \ echo "$(GETTEXT_H) not found"; \ else \ cp "$(GETTEXT_H)" gettext.h; \ - git diff --quiet gettext.h 2>/dev/null; \ + "$(GIT)" diff --quiet gettext.h 2>/dev/null; \ if [ $$? -eq 0 ]; then \ echo "No update needed"; \ else \ - git add gettext.h; \ + "$(GIT)" add gettext.h; \ echo 'Review changes then run:'; \ echo 'git commit -m "Low: NLS: update gettext.h from upstream"'; \ fi \ diff --git a/include/crm/Makefile.am b/include/crm/Makefile.am index 6dd52fd..95564b8 100644 --- a/include/crm/Makefile.am +++ b/include/crm/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2004-2021 the Pacemaker project contributors +# Copyright 2004-2023 the Pacemaker project contributors # # The version control history for this file may have further details. # @@ -11,12 +11,23 @@ MAINTAINERCLEANFILES = Makefile.in headerdir=$(pkgincludedir)/crm -header_HEADERS = cib.h cluster.h compatibility.h crm.h \ - lrmd.h msg_xml.h services.h stonith-ng.h \ +header_HEADERS = cib.h \ + cluster.h \ + compatibility.h \ + crm.h \ crm_compat.h \ + lrmd.h \ + lrmd_events.h \ + msg_xml.h \ msg_xml_compat.h \ - services_compat.h + services.h \ + services_compat.h \ + stonith-ng.h -noinst_HEADERS = lrmd_internal.h services_internal.h +noinst_HEADERS = $(wildcard *_internal.h) -SUBDIRS = common pengine cib fencing cluster +SUBDIRS = common \ + pengine \ + cib \ + fencing \ + cluster 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); diff --git a/include/crm/cluster.h b/include/crm/cluster.h index bceb9c2..b61fd70 100644 --- a/include/crm/cluster.h +++ b/include/crm/cluster.h @@ -78,6 +78,9 @@ typedef struct crm_peer_node_s { time_t peer_lost; char *conn_host; + + time_t when_member; // Since when node has been a cluster member + time_t when_online; // Since when peer has been online in CPG } crm_node_t; void crm_peer_init(void); @@ -133,8 +136,8 @@ enum crm_get_peer_flags { }; gboolean send_cluster_message(const crm_node_t *node, - enum crm_ais_msg_types service, xmlNode *data, - gboolean ordered); + enum crm_ais_msg_types service, + const xmlNode *data, gboolean ordered); int crm_remote_peer_cache_size(void); @@ -174,7 +177,6 @@ char *pcmk_message_common_cs(cpg_handle_t handle, uint32_t nodeid, uint32_t pid, const char *crm_peer_uuid(crm_node_t *node); const char *crm_peer_uname(const char *uuid); -void set_uuid(xmlNode *xml, const char *attr, crm_node_t *node); enum crm_status_type { crm_status_uname, diff --git a/include/crm/cluster/Makefile.am b/include/crm/cluster/Makefile.am index 96f2bd0..2500a87 100644 --- a/include/crm/cluster/Makefile.am +++ b/include/crm/cluster/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2012-2021 the Pacemaker project contributors +# Copyright 2012-2023 the Pacemaker project contributors # # The version control history for this file may have further details. # @@ -10,5 +10,6 @@ MAINTAINERCLEANFILES = Makefile.in headerdir=$(pkgincludedir)/crm/cluster -noinst_HEADERS = internal.h election_internal.h +noinst_HEADERS = internal.h \ + $(wildcard *_internal.h) header_HEADERS = compat.h diff --git a/include/crm/cluster/compat.h b/include/crm/cluster/compat.h index 9bf14ee..89a03fd 100644 --- a/include/crm/cluster/compat.h +++ b/include/crm/cluster/compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2021 the Pacemaker project contributors + * Copyright 2004-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -10,6 +10,9 @@ #ifndef PCMK__CRM_CLUSTER_COMPAT__H # define PCMK__CRM_CLUSTER_COMPAT__H +#include <libxml/tree.h> // xmlNode +#include <crm/cluster.h> // crm_node_t + #ifdef __cplusplus extern "C" { #endif @@ -30,6 +33,9 @@ int crm_terminate_member(int nodeid, const char *uname, void *unused); int crm_terminate_member_no_mainloop(int nodeid, const char *uname, int *connection); +// \deprecated Use crm_xml_add(xml, attr, crm_peer_uuid(node)) instead +void set_uuid(xmlNode *xml, const char *attr, crm_node_t *node); + #ifdef __cplusplus } #endif diff --git a/include/crm/cluster/internal.h b/include/crm/cluster/internal.h index 9bc57c6..e20ee4c 100644 --- a/include/crm/cluster/internal.h +++ b/include/crm/cluster/internal.h @@ -124,10 +124,16 @@ void pcmk__corosync_quorum_connect(gboolean (*dispatch)(unsigned long long, void (*destroy) (gpointer)); crm_node_t *pcmk__search_node_caches(unsigned int id, const char *uname, uint32_t flags); -crm_node_t *pcmk__search_cluster_node_cache(unsigned int id, const char *uname); +crm_node_t *pcmk__search_cluster_node_cache(unsigned int id, const char *uname, + const char *uuid); void pcmk__refresh_node_caches_from_cib(xmlNode *cib); crm_node_t *pcmk__search_known_node_cache(unsigned int id, const char *uname, uint32_t flags); +crm_node_t *pcmk__get_peer(unsigned int id, const char *uname, + const char *uuid); +crm_node_t *pcmk__get_peer_full(unsigned int id, const char *uname, + const char *uuid, int flags); + #endif diff --git a/include/crm/common/Makefile.am b/include/crm/common/Makefile.am index 7d417e4..83a4197 100644 --- a/include/crm/common/Makefile.am +++ b/include/crm/common/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2004-2022 the Pacemaker project contributors +# Copyright 2004-2023 the Pacemaker project contributors # # The version control history for this file may have further details. # @@ -11,45 +11,34 @@ MAINTAINERCLEANFILES = Makefile.in headerdir=$(pkgincludedir)/crm/common -header_HEADERS = acl.h \ - agents.h \ - agents_compat.h \ - cib.h \ - ipc.h \ - ipc_attrd_internal.h \ - ipc_controld.h \ - ipc_pacemakerd.h \ - ipc_schedulerd.h \ - iso8601.h \ - logging.h \ - logging_compat.h \ - mainloop.h \ - mainloop_compat.h \ - nvpair.h \ - output.h \ - results.h \ - results_compat.h \ - util.h \ - util_compat.h \ - xml.h \ - xml_compat.h +header_HEADERS = acl.h \ + actions.h \ + agents.h \ + agents_compat.h \ + cib.h \ + ipc.h \ + ipc_controld.h \ + ipc_pacemakerd.h \ + ipc_schedulerd.h \ + iso8601.h \ + logging.h \ + logging_compat.h \ + mainloop.h \ + mainloop_compat.h \ + nodes.h \ + nvpair.h \ + output.h \ + resources.h \ + results.h \ + results_compat.h \ + roles.h \ + scheduler.h \ + scheduler_types.h \ + tags.h \ + tickets.h \ + util.h \ + util_compat.h \ + xml.h \ + xml_compat.h -noinst_HEADERS = acl_internal.h \ - alerts_internal.h \ - attrd_internal.h \ - cmdline_internal.h \ - health_internal.h \ - internal.h \ - io_internal.h \ - ipc_internal.h \ - iso8601_internal.h \ - lists_internal.h \ - logging_internal.h \ - messages_internal.h \ - options_internal.h \ - output_internal.h \ - remote_internal.h \ - results_internal.h \ - strings_internal.h \ - unittest_internal.h \ - xml_internal.h +noinst_HEADERS = $(wildcard *internal.h) diff --git a/include/crm/common/action_relation_internal.h b/include/crm/common/action_relation_internal.h new file mode 100644 index 0000000..e789131 --- /dev/null +++ b/include/crm/common/action_relation_internal.h @@ -0,0 +1,132 @@ +/* + * Copyright 2023 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 PCMK__CRM_COMMON_ACTION_RELATION_INTERNAL__H +# define PCMK__CRM_COMMON_ACTION_RELATION_INTERNAL__H + +/*! + * Flags to indicate the relationship between two actions + * + * @COMPAT The values and semantics of these flags should not be changed until + * the deprecated enum pe_ordering is dropped from the public API. + */ +enum pcmk__action_relation_flags { + //! No relation (compare with equality rather than bit set) + pcmk__ar_none = 0U, + + //! Actions are ordered (optionally, if no other flags are set) + pcmk__ar_ordered = (1U << 0), + + //! Relation applies only if 'first' cannot be part of a live migration + pcmk__ar_if_first_unmigratable = (1U << 1), + + /*! + * If 'then' is required, 'first' becomes required (and becomes unmigratable + * if 'then' is); also, if 'first' is a stop of a blocked resource, 'then' + * becomes unrunnable + */ + pcmk__ar_then_implies_first = (1U << 4), + + /*! + * If 'first' is required, 'then' becomes required; if 'first' is a stop of + * a blocked resource, 'then' becomes unrunnable + */ + pcmk__ar_first_implies_then = (1U << 5), + + /*! + * If 'then' is required and for a promoted instance, 'first' becomes + * required (and becomes unmigratable if 'then' is) + */ + pcmk__ar_promoted_then_implies_first = (1U << 6), + + /*! + * 'first' is runnable only if 'then' is both runnable and migratable, + * and 'first' becomes required if 'then' is + */ + pcmk__ar_unmigratable_then_blocks = (1U << 7), + + //! 'then' is runnable (and migratable) only if 'first' is runnable + pcmk__ar_unrunnable_first_blocks = (1U << 8), + + //! If 'first' is unrunnable, 'then' becomes a real, unmigratable action + pcmk__ar_first_else_then = (1U << 9), + + //! If 'first' is required, 'then' action for instance on same node is + pcmk__ar_first_implies_same_node_then = (1U << 10), + + /*! + * Disable relation if 'first' is unrunnable and for an active resource, + * otherwise order actions and make 'then' unrunnable if 'first' is. + * + * This is used to order a bundle replica's start of its container before a + * probe of its remote connection resource, in case the connection uses the + * REMOTE_CONTAINER_HACK to replace the connection address with where the + * container is running. + */ + pcmk__ar_nested_remote_probe = (1U << 11), + + /*! + * If 'first' is for a blocked resource, make 'then' unrunnable. + * + * If 'then' is required, make 'first' required, make 'first' unmigratable + * if 'then' is unmigratable, and make 'then' unrunnable if 'first' is + * unrunnable. + * + * If 'then' is unrunnable and for the same resource as 'first', make + * 'first' required if it is runnable, and make 'first' unmigratable if + * 'then' is unmigratable. + * + * This is used for "stop then start primitive" (restarts) and + * "stop group member then stop previous member". + */ + pcmk__ar_intermediate_stop = (1U << 12), + + /*! + * The actions must be serialized if in the same transition but can be in + * either order. (In practice, we always arrange them as 'first' then + * 'then', so they end up being essentially the same as optional orderings.) + * + * @TODO Handle more intelligently -- for example, we could schedule the + * action with the fewest inputs first, so we're more likely to execute at + * least one if there is a failure during the transition. Or, we could + * prefer certain action types over others, or base it on resource priority. + */ + pcmk__ar_serialize = (1U << 14), + + //! Relation applies only if actions are on same node + pcmk__ar_if_on_same_node = (1U << 15), + + //! If 'then' is required, 'first' must be added to the transition graph + pcmk__ar_then_implies_first_graphed = (1U << 16), + + //! If 'first' is required and runnable, 'then' must be in graph + pcmk__ar_first_implies_then_graphed = (1U << 17), + + //! User-configured asymmetric ordering + pcmk__ar_asymmetric = (1U << 20), + + //! Actions are ordered if on same node (or migration target for migrate_to) + pcmk__ar_if_on_same_node_or_target = (1U << 21), + + //! 'then' action is runnable if certain number of 'first' instances are + pcmk__ar_min_runnable = (1U << 22), + + //! Ordering applies only if 'first' is required and on same node as 'then' + pcmk__ar_if_required_on_same_node = (1U << 23), + + //! Ordering applies even if 'first' runs on guest node created by 'then' + pcmk__ar_guest_allowed = (1U << 24), + + //! If 'then' action becomes required, 'first' becomes optional + pcmk__ar_then_cancels_first = (1U << 25), +}; + +typedef struct pe_action_wrapper_s pcmk__related_action_t; + +#endif // PCMK__CRM_COMMON_ACTION_RELATION_INTERNAL__H diff --git a/include/crm/common/actions.h b/include/crm/common/actions.h new file mode 100644 index 0000000..5d2784d --- /dev/null +++ b/include/crm/common/actions.h @@ -0,0 +1,467 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_ACTIONS__H +#define PCMK__CRM_COMMON_ACTIONS__H + +#include <stdbool.h> // bool +#include <strings.h> // strcasecmp() +#include <glib.h> // gboolean, guint +#include <libxml/tree.h> // xmlNode + +#include <crm/lrmd_events.h> // lrmd_event_data_t + +#include <glib.h> // GList, GHashTable +#include <libxml/tree.h> // xmlNode + +#include <crm/common/nodes.h> +#include <crm/common/resources.h> // enum rsc_start_requirement, etc. +#include <crm/common/scheduler_types.h> // pcmk_resource_t, pcmk_node_t + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief APIs related to actions + * \ingroup core + */ + +//! Default timeout (in milliseconds) for non-metadata actions +#define PCMK_DEFAULT_ACTION_TIMEOUT_MS 20000 + +// @COMPAT We don't need a separate timeout for metadata, much less a longer one +//! \deprecated Default timeout (in milliseconds) for metadata actions +#define PCMK_DEFAULT_METADATA_TIMEOUT_MS 30000 + +// Action names as strings +#define PCMK_ACTION_CANCEL "cancel" +#define PCMK_ACTION_CLEAR_FAILCOUNT "clear_failcount" +#define PCMK_ACTION_CLONE_ONE_OR_MORE "clone-one-or-more" +#define PCMK_ACTION_DELETE "delete" +#define PCMK_ACTION_DEMOTE "demote" +#define PCMK_ACTION_DEMOTED "demoted" +#define PCMK_ACTION_DO_SHUTDOWN "do_shutdown" +#define PCMK_ACTION_LIST "list" +#define PCMK_ACTION_LRM_DELETE "lrm_delete" +#define PCMK_ACTION_LOAD_STOPPED "load_stopped" +#define PCMK_ACTION_MAINTENANCE_NODES "maintenance_nodes" +#define PCMK_ACTION_META_DATA "meta-data" +#define PCMK_ACTION_MIGRATE_FROM "migrate_from" +#define PCMK_ACTION_MIGRATE_TO "migrate_to" +#define PCMK_ACTION_MONITOR "monitor" +#define PCMK_ACTION_NOTIFIED "notified" +#define PCMK_ACTION_NOTIFY "notify" +#define PCMK_ACTION_OFF "off" +#define PCMK_ACTION_ON "on" +#define PCMK_ACTION_ONE_OR_MORE "one-or-more" +#define PCMK_ACTION_PROMOTE "promote" +#define PCMK_ACTION_PROMOTED "promoted" +#define PCMK_ACTION_REBOOT "reboot" +#define PCMK_ACTION_RELOAD "reload" +#define PCMK_ACTION_RELOAD_AGENT "reload-agent" +#define PCMK_ACTION_RUNNING "running" +#define PCMK_ACTION_START "start" +#define PCMK_ACTION_STATUS "status" +#define PCMK_ACTION_STONITH "stonith" +#define PCMK_ACTION_STOP "stop" +#define PCMK_ACTION_STOPPED "stopped" +#define PCMK_ACTION_VALIDATE_ALL "validate-all" + +//! Possible actions (including some pseudo-actions) +enum action_tasks { + pcmk_action_unspecified = 0, //!< Unspecified or unknown action + pcmk_action_monitor, //!< Monitor + + // Each "completed" action must be the regular action plus 1 + + pcmk_action_stop, //!< Stop + pcmk_action_stopped, //!< Stop completed + + pcmk_action_start, //!< Start + pcmk_action_started, //!< Start completed + + pcmk_action_notify, //!< Notify + pcmk_action_notified, //!< Notify completed + + pcmk_action_promote, //!< Promote + pcmk_action_promoted, //!< Promoted + + pcmk_action_demote, //!< Demote + pcmk_action_demoted, //!< Demoted + + pcmk_action_shutdown, //!< Shut down node + pcmk_action_fence, //!< Fence node + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_action_unspecified instead + no_action = pcmk_action_unspecified, + + //! \deprecated Use pcmk_action_monitor instead + monitor_rsc = pcmk_action_monitor, + + //! \deprecated Use pcmk_action_stop instead + stop_rsc = pcmk_action_stop, + + //! \deprecated Use pcmk_action_stopped instead + stopped_rsc = pcmk_action_stopped, + + //! \deprecated Use pcmk_action_start instead + start_rsc = pcmk_action_start, + + //! \deprecated Use pcmk_action_started instead + started_rsc = pcmk_action_started, + + //! \deprecated Use pcmk_action_notify instead + action_notify = pcmk_action_notify, + + //! \deprecated Use pcmk_action_notified instead + action_notified = pcmk_action_notified, + + //! \deprecated Use pcmk_action_promote instead + action_promote = pcmk_action_promote, + + //! \deprecated Use pcmk_action_promoted instead + action_promoted = pcmk_action_promoted, + + //! \deprecated Use pcmk_action_demote instead + action_demote = pcmk_action_demote, + + //! \deprecated Use pcmk_action_demoted instead + action_demoted = pcmk_action_demoted, + + //! \deprecated Use pcmk_action_shutdown instead + shutdown_crm = pcmk_action_shutdown, + + //! \deprecated Use pcmk_action_fence instead + stonith_node = pcmk_action_fence, +#endif +}; + +//! Possible responses to a resource action failure +enum action_fail_response { + /* The order is (partially) significant here; the values from + * pcmk_on_fail_ignore through pcmk_on_fail_fence_node are in order of + * increasing severity. + * + * @COMPAT The values should be ordered and numbered per the "TODO" comments + * below, so all values are in order of severity and there is room for + * future additions, but that would break API compatibility. + * @TODO For now, we just use a function to compare the values specially, but + * at the next compatibility break, we should arrange things + * properly so we can compare with less than and greater than. + */ + + // @TODO Define as 10 + pcmk_on_fail_ignore = 0, //!< Act as if failure didn't happen + + // @TODO Define as 30 + pcmk_on_fail_restart = 1, //!< Restart resource + + // @TODO Define as 60 + pcmk_on_fail_ban = 2, //!< Ban resource from current node + + // @TODO Define as 70 + pcmk_on_fail_block = 3, //!< Treat resource as unmanaged + + // @TODO Define as 80 + pcmk_on_fail_stop = 4, //!< Stop resource and leave stopped + + // @TODO Define as 90 + pcmk_on_fail_standby_node = 5, //!< Put resource's node in standby + + // @TODO Define as 100 + pcmk_on_fail_fence_node = 6, //!< Fence resource's node + + // @COMPAT Values below here are out of desired order for API compatibility + + // @TODO Define as 50 + pcmk_on_fail_restart_container = 7, //!< Restart resource's container + + // @TODO Define as 40 + /*! + * Fence the remote node created by the resource if fencing is enabled, + * otherwise attempt to restart the resource (used internally for some + * remote connection failures). + */ + pcmk_on_fail_reset_remote = 8, + + // @TODO Define as 20 + pcmk_on_fail_demote = 9, //!< Demote if promotable, else stop + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_on_fail_ignore instead + action_fail_ignore = pcmk_on_fail_ignore, + + //! \deprecated Use pcmk_on_fail_restart instead + action_fail_recover = pcmk_on_fail_restart, + + //! \deprecated Use pcmk_on_fail_ban instead + action_fail_migrate = pcmk_on_fail_ban, + + //! \deprecated Use pcmk_on_fail_block instead + action_fail_block = pcmk_on_fail_block, + + //! \deprecated Use pcmk_on_fail_stop instead + action_fail_stop = pcmk_on_fail_stop, + + //! \deprecated Use pcmk_on_fail_standby_node instead + action_fail_standby = pcmk_on_fail_standby_node, + + //! \deprecated Use pcmk_on_fail_fence_node instead + action_fail_fence = pcmk_on_fail_fence_node, + + //! \deprecated Use pcmk_on_fail_restart_container instead + action_fail_restart_container = pcmk_on_fail_restart_container, + + //! \deprecated Use pcmk_on_fail_reset_remote instead + action_fail_reset_remote = pcmk_on_fail_reset_remote, + + //! \deprecated Use pcmk_on_fail_demote instead + action_fail_demote = pcmk_on_fail_demote, +#endif +}; + +//! Action scheduling flags +enum pe_action_flags { + //! No action flags set (compare with equality rather than bit set) + pcmk_no_action_flags = 0, + + //! Whether action does not require invoking an agent + pcmk_action_pseudo = (1 << 0), + + //! Whether action is runnable + pcmk_action_runnable = (1 << 1), + + //! Whether action should not be executed + pcmk_action_optional = (1 << 2), + + //! Whether action should be added to transition graph even if optional + pcmk_action_always_in_graph = (1 << 3), + + //! Whether operation-specific instance attributes have been unpacked yet + pcmk_action_attrs_evaluated = (1 << 4), + + //! Whether action is allowed to be part of a live migration + pcmk_action_migratable = (1 << 7), + + //! Whether action has been added to transition graph + pcmk_action_added_to_graph = (1 << 8), + + //! Whether action is a stop to abort a dangling migration + pcmk_action_migration_abort = (1 << 11), + + /*! + * Whether action is an ordering point for minimum required instances + * (used to implement ordering after clones with clone-min configured, + * and ordered sets with require-all=false) + */ + pcmk_action_min_runnable = (1 << 12), + + //! Whether action is recurring monitor that must be rescheduled if active + pcmk_action_reschedule = (1 << 13), + + //! Whether action has already been processed by a recursive procedure + pcmk_action_detect_loop = (1 << 14), + + //! Whether action's inputs have been de-duplicated yet + pcmk_action_inputs_deduplicated = (1 << 15), + + //! Whether action can be executed on DC rather than own node + pcmk_action_on_dc = (1 << 16), + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_action_pseudo instead + pe_action_pseudo = pcmk_action_pseudo, + + //! \deprecated Use pcmk_action_runnable instead + pe_action_runnable = pcmk_action_runnable, + + //! \deprecated Use pcmk_action_optional instead + pe_action_optional = pcmk_action_optional, + + //! \deprecated Use pcmk_action_always_in_graph instead + pe_action_print_always = pcmk_action_always_in_graph, + + //! \deprecated Use pcmk_action_attrs_evaluated instead + pe_action_have_node_attrs = pcmk_action_attrs_evaluated, + + //! \deprecated Do not use + pe_action_implied_by_stonith = (1 << 6), + + //! \deprecated Use pcmk_action_migratable instead + pe_action_migrate_runnable = pcmk_action_migratable, + + //! \deprecated Use pcmk_action_added_to_graph instead + pe_action_dumped = pcmk_action_added_to_graph, + + //! \deprecated Do not use + pe_action_processed = (1 << 9), + + //! \deprecated Do not use + pe_action_clear = (1 << 10), + + //! \deprecated Use pcmk_action_migration_abort instead + pe_action_dangle = pcmk_action_migration_abort, + + //! \deprecated Use pcmk_action_min_runnable instead + pe_action_requires_any = pcmk_action_min_runnable, + + //! \deprecated Use pcmk_action_reschedule instead + pe_action_reschedule = pcmk_action_reschedule, + + //! \deprecated Use pcmk_action_detect_loop instead + pe_action_tracking = pcmk_action_detect_loop, + + //! \deprecated Use pcmk_action_inputs_deduplicated instead + pe_action_dedup = pcmk_action_inputs_deduplicated, + + //! \deprecated Use pcmk_action_on_dc instead + pe_action_dc = pcmk_action_on_dc, +#endif +}; + +/* @COMPAT enum pe_link_state and enum pe_ordering are currently needed for + * struct pe_action_wrapper_s (which is public) but should be removed at an + * API compatibility break when that can be refactored and made internal + */ + +//!@{ +//! \deprecated Do not use +enum pe_link_state { + pe_link_not_dumped = 0, + pe_link_dumped = 1, +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + pe_link_dup = 2, +#endif +}; + +enum pe_ordering { + pe_order_none = 0x0, +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + pe_order_optional = 0x1, + pe_order_apply_first_non_migratable = 0x2, + pe_order_implies_first = 0x10, + pe_order_implies_then = 0x20, + pe_order_promoted_implies_first = 0x40, + pe_order_implies_first_migratable = 0x80, + pe_order_runnable_left = 0x100, + pe_order_pseudo_left = 0x200, + pe_order_implies_then_on_node = 0x400, + pe_order_probe = 0x800, + pe_order_restart = 0x1000, + pe_order_stonith_stop = 0x2000, + pe_order_serialize_only = 0x4000, + pe_order_same_node = 0x8000, + pe_order_implies_first_printed = 0x10000, + pe_order_implies_then_printed = 0x20000, + pe_order_asymmetrical = 0x100000, + pe_order_load = 0x200000, + pe_order_one_or_more = 0x400000, + pe_order_anti_colocation = 0x800000, + pe_order_preserve = 0x1000000, + pe_order_then_cancels_first = 0x2000000, + pe_order_trace = 0x4000000, + pe_order_implies_first_master = pe_order_promoted_implies_first, +#endif +}; + +// Action sequenced relative to another action +// @COMPAT This should be internal +struct pe_action_wrapper_s { + // @COMPAT This should be uint32_t + enum pe_ordering type; // Group of enum pcmk__action_relation_flags + + // @COMPAT This should be a bool + enum pe_link_state state; // Whether action has been added to graph yet + + pcmk_action_t *action; // Action to be sequenced +}; +//!@} + +//! Implementation of pcmk_action_t +struct pe_action_s { + int id; //!< Counter to identify action + + /*! + * When the controller aborts a transition graph, it sets an abort priority. + * If this priority is higher, the action will still be executed anyway. + * Pseudo-actions are always allowed, so this is irrelevant for them. + */ + int priority; + + pcmk_resource_t *rsc; //!< Resource to apply action to, if any + pcmk_node_t *node; //!< Node to execute action on, if any + xmlNode *op_entry; //!< Action XML configuration, if any + char *task; //!< Action name + char *uuid; //!< Action key + char *cancel_task; //!< If task is "cancel", the action being cancelled + char *reason; //!< Readable description of why action is needed + + //@ COMPAT Change to uint32_t at a compatibility break + enum pe_action_flags flags; //!< Group of enum pe_action_flags + + enum rsc_start_requirement needs; //!< Prerequisite for recovery + enum action_fail_response on_fail; //!< Response to failure + enum rsc_role_e fail_role; //!< Resource role if action fails + GHashTable *meta; //!< Meta-attributes relevant to action + GHashTable *extra; //!< Action-specific instance attributes + + /* Current count of runnable instance actions for "first" action in an + * ordering dependency with pcmk__ar_min_runnable set. + */ + int runnable_before; //!< For Pacemaker use only + + /*! + * Number of instance actions for "first" action in an ordering dependency + * with pcmk__ar_min_runnable set that must be runnable before this action + * can be runnable. + */ + int required_runnable_before; + + // Actions in a relation with this one (as pcmk__related_action_t *) + GList *actions_before; //!< For Pacemaker use only + GList *actions_after; //!< For Pacemaker use only + + /* This is intended to hold data that varies by the type of action, but is + * not currently used. Some of the above fields could be moved here except + * for API backward compatibility. + */ + void *action_details; //!< For Pacemaker use only +}; + +// For parsing various action-related string specifications +gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, + guint *interval_ms); +gboolean decode_transition_key(const char *key, char **uuid, int *transition_id, + int *action_id, int *target_rc); +gboolean decode_transition_magic(const char *magic, char **uuid, + int *transition_id, int *action_id, + int *op_status, int *op_rc, int *target_rc); + +// @COMPAT Either these shouldn't be in libcrmcommon or lrmd_event_data_t should +int rsc_op_expected_rc(const lrmd_event_data_t *event); +gboolean did_rsc_op_fail(lrmd_event_data_t *event, int target_rc); + +bool crm_op_needs_metadata(const char *rsc_class, const char *op); + +xmlNode *crm_create_op_xml(xmlNode *parent, const char *prefix, + const char *task, const char *interval_spec, + const char *timeout); + +bool pcmk_is_probe(const char *task, guint interval); +bool pcmk_xe_is_probe(const xmlNode *xml_op); +bool pcmk_xe_mask_probe_failure(const xmlNode *xml_op); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_ACTIONS__H diff --git a/include/crm/common/actions_internal.h b/include/crm/common/actions_internal.h new file mode 100644 index 0000000..7e794e6 --- /dev/null +++ b/include/crm/common/actions_internal.h @@ -0,0 +1,57 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_ACTIONS_INTERNAL__H +#define PCMK__CRM_COMMON_ACTIONS_INTERNAL__H + +#include <stdbool.h> // bool +#include <glib.h> // guint +#include <libxml/tree.h> // xmlNode + +#include <crm/common/actions.h> // PCMK_ACTION_MONITOR +#include <crm/common/strings_internal.h> // pcmk__str_eq() + +#ifdef __cplusplus +extern "C" { +#endif + +//! printf-style format to create operation key from resource, action, interval +#define PCMK__OP_FMT "%s_%s_%u" + +char *pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms); +char *pcmk__notify_key(const char *rsc_id, const char *notify_type, + const char *op_type); +char *pcmk__transition_key(int transition_id, int action_id, int target_rc, + const char *node); +void pcmk__filter_op_for_digest(xmlNode *param_set); +bool pcmk__is_fencing_action(const char *action); + +/*! + * \internal + * \brief Get a human-friendly action name + * + * \param[in] action_name Actual action name + * \param[in] interval_ms Action interval (in milliseconds) + * + * \return Action name suitable for display + */ +static inline const char * +pcmk__readable_action(const char *action_name, guint interval_ms) { + if ((interval_ms == 0) + && pcmk__str_eq(action_name, PCMK_ACTION_MONITOR, pcmk__str_none)) { + return "probe"; + } + return action_name; +} + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_ACTIONS_INTERNAL__H diff --git a/include/crm/common/alerts_internal.h b/include/crm/common/alerts_internal.h index ef64fab..dc67427 100644 --- a/include/crm/common/alerts_internal.h +++ b/include/crm/common/alerts_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 the Pacemaker project contributors + * Copyright 2015-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -76,7 +76,6 @@ void pcmk__add_alert_key(GHashTable *table, enum pcmk__alert_keys_e name, const char *value); void pcmk__add_alert_key_int(GHashTable *table, enum pcmk__alert_keys_e name, int value); -bool pcmk__alert_in_patchset(xmlNode *msg, bool config); static inline const char * pcmk__alert_flag2text(enum pcmk__alert_flags flag) diff --git a/include/crm/common/cib_internal.h b/include/crm/common/cib_internal.h new file mode 100644 index 0000000..c41c12e --- /dev/null +++ b/include/crm/common/cib_internal.h @@ -0,0 +1,23 @@ +/* + * Copyright 2023 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 PCMK__CRM_COMMON_CIB_INTERNAL__H +#define PCMK__CRM_COMMON_CIB_INTERNAL__H + +#ifdef __cplusplus +extern "C" { +#endif + +const char *pcmk__cib_abs_xpath_for(const char *element); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__COMMON_CIB_INTERNAL__H diff --git a/include/crm/common/clone_internal.h b/include/crm/common/clone_internal.h new file mode 100644 index 0000000..494ee74 --- /dev/null +++ b/include/crm/common/clone_internal.h @@ -0,0 +1,33 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_CLONE_INTERNAL__H +# define PCMK__CRM_COMMON_CLONE_INTERNAL__H + +#ifdef __cplusplus +extern "C" { +#endif + +// Clone resource flags (used in variant data) +enum pcmk__clone_flags { + // Whether instances should be started sequentially + pcmk__clone_ordered = (1 << 0), + + // Whether promotion scores have been added + pcmk__clone_promotion_added = (1 << 1), + + // Whether promotion constraints have been added + pcmk__clone_promotion_constrained = (1 << 2), +}; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_CLONE_INTERNAL__H diff --git a/include/crm/common/digests_internal.h b/include/crm/common/digests_internal.h new file mode 100644 index 0000000..7598de2 --- /dev/null +++ b/include/crm/common/digests_internal.h @@ -0,0 +1,33 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_DIGESTS_INTERNAL__H +# define PCMK__CRM_COMMON_DIGESTS_INTERNAL__H + +#include <libxml/tree.h> // xmlNode + +#ifdef __cplusplus +extern "C" { +#endif + +// Digest comparison results +enum pcmk__digest_result { + pcmk__digest_unknown, // No digest available for comparison + pcmk__digest_match, // Digests match + pcmk__digest_mismatch, // Any parameter changed (potentially reloadable) + pcmk__digest_restart, // Parameters that require a restart changed +}; + +bool pcmk__verify_digest(xmlNode *input, const char *expected); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_DIGESTS_INTERNAL__H diff --git a/include/crm/common/failcounts_internal.h b/include/crm/common/failcounts_internal.h new file mode 100644 index 0000000..4ad01bf --- /dev/null +++ b/include/crm/common/failcounts_internal.h @@ -0,0 +1,41 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_FAILCOUNTS_INTERNAL__H +# define PCMK__CRM_COMMON_FAILCOUNTS_INTERNAL__H + +#ifdef __cplusplus +extern "C" { +#endif + +// Options when getting resource fail counts +enum pcmk__fc_flags { + pcmk__fc_default = (1 << 0), + pcmk__fc_effective = (1 << 1), // Don't count expired failures + pcmk__fc_fillers = (1 << 2), // If container, include filler failures +}; + +/*! + * \internal + * \enum pcmk__rsc_node + * \brief Type of resource location lookup to perform + */ +enum pcmk__rsc_node { + pcmk__rsc_node_assigned = 0, //!< Where resource is assigned + pcmk__rsc_node_current = 1, //!< Where resource is running + + // @COMPAT: Use in native_location() at a compatibility break + pcmk__rsc_node_pending = 2, //!< Where resource is pending +}; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_FAILCOUNTS_INTERNAL__H diff --git a/include/crm/common/group_internal.h b/include/crm/common/group_internal.h new file mode 100644 index 0000000..9e1424d --- /dev/null +++ b/include/crm/common/group_internal.h @@ -0,0 +1,27 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_GROUP_INTERNAL__H +# define PCMK__CRM_COMMON_GROUP_INTERNAL__H + +#ifdef __cplusplus +extern "C" { +#endif + +// Group resource flags (used in variant data) +enum pcmk__group_flags { + pcmk__group_ordered = (1 << 0), // Members start sequentially + pcmk__group_colocated = (1 << 1), // Members must be on same node +}; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_GROUP_INTERNAL__H diff --git a/include/crm/common/health_internal.h b/include/crm/common/health_internal.h index 277a4c9..f98529c 100644 --- a/include/crm/common/health_internal.h +++ b/include/crm/common/health_internal.h @@ -18,7 +18,7 @@ extern "C" { * \internal * \brief Possible node health strategies * - * \note It would be nice to use this in pe_working_set_t but that will have to + * \note It would be nice to use this in pcmk_scheduler_t but that will have to * wait for an API backward compatibility break. */ enum pcmk__health_strategy { diff --git a/include/crm/common/internal.h b/include/crm/common/internal.h index bd98780..3078606 100644 --- a/include/crm/common/internal.h +++ b/include/crm/common/internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 the Pacemaker project contributors + * Copyright 2015-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -20,6 +20,8 @@ #include <crm/common/util.h> // crm_strdup_printf() #include <crm/common/logging.h> // do_crm_log_unlikely(), etc. #include <crm/common/mainloop.h> // mainloop_io_t, struct ipc_client_callbacks +#include <crm/common/actions_internal.h> +#include <crm/common/digests_internal.h> #include <crm/common/health_internal.h> #include <crm/common/io_internal.h> #include <crm/common/iso8601_internal.h> @@ -50,11 +52,6 @@ int pcmk__substitute_secrets(const char *rsc_id, GHashTable *params); #endif -/* internal digest-related utilities (from digest.c) */ - -bool pcmk__verify_digest(xmlNode *input, const char *expected); - - /* internal main loop utilities (from mainloop.c) */ int pcmk__add_mainloop_ipc(crm_ipc_t *ipc, int priority, void *userdata, @@ -164,20 +161,6 @@ int pcmk__pidfile_matches(const char *filename, pid_t expected_pid, int pcmk__lock_pidfile(const char *filename, const char *name); -/* internal functions related to resource operations (from operations.c) */ - -// printf-style format to create operation ID from resource, action, interval -#define PCMK__OP_FMT "%s_%s_%u" - -char *pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms); -char *pcmk__notify_key(const char *rsc_id, const char *notify_type, - const char *op_type); -char *pcmk__transition_key(int transition_id, int action_id, int target_rc, - const char *node); -void pcmk__filter_op_for_digest(xmlNode *param_set); -bool pcmk__is_fencing_action(const char *action); - - // bitwise arithmetic utilities /*! diff --git a/include/crm/common/ipc.h b/include/crm/common/ipc.h index 3d4ee10..397c8b1 100644 --- a/include/crm/common/ipc.h +++ b/include/crm/common/ipc.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2022 the Pacemaker project contributors + * Copyright 2004-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -170,8 +170,8 @@ void crm_ipc_close(crm_ipc_t * client); void crm_ipc_destroy(crm_ipc_t * client); void pcmk_free_ipc_event(struct iovec *event); -int crm_ipc_send(crm_ipc_t * client, xmlNode * message, enum crm_ipc_flags flags, - int32_t ms_timeout, xmlNode ** reply); +int crm_ipc_send(crm_ipc_t *client, const xmlNode *message, + enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply); int crm_ipc_get_fd(crm_ipc_t * client); bool crm_ipc_connected(crm_ipc_t * client); diff --git a/include/crm/common/ipc_internal.h b/include/crm/common/ipc_internal.h index 5099dda..b391e83 100644 --- a/include/crm/common/ipc_internal.h +++ b/include/crm/common/ipc_internal.h @@ -96,6 +96,10 @@ extern "C" { int pcmk__ipc_is_authentic_process_active(const char *name, uid_t refuid, gid_t refgid, pid_t *gotpid); +int pcmk__connect_generic_ipc(crm_ipc_t *ipc); +int pcmk__ipc_fd(crm_ipc_t *ipc, int *fd); +int pcmk__connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type, + int attempts); /* * Server-related @@ -112,6 +116,7 @@ struct pcmk__remote_s { int tcp_socket; mainloop_io_t *source; time_t uptime; + char *start_state; /* CIB-only */ char *token; @@ -245,11 +250,11 @@ int pcmk__ipc_send_ack_as(const char *function, int line, pcmk__client_t *c, #define pcmk__ipc_send_ack(c, req, flags, tag, ver, st) \ pcmk__ipc_send_ack_as(__func__, __LINE__, (c), (req), (flags), (tag), (ver), (st)) -int pcmk__ipc_prepare_iov(uint32_t request, xmlNode *message, +int pcmk__ipc_prepare_iov(uint32_t request, const xmlNode *message, uint32_t max_send_size, struct iovec **result, ssize_t *bytes); -int pcmk__ipc_send_xml(pcmk__client_t *c, uint32_t request, xmlNode *message, - uint32_t flags); +int pcmk__ipc_send_xml(pcmk__client_t *c, uint32_t request, + const xmlNode *message, uint32_t flags); int pcmk__ipc_send_iov(pcmk__client_t *c, struct iovec *iov, uint32_t flags); xmlNode *pcmk__client_data2xml(pcmk__client_t *c, void *data, uint32_t *id, uint32_t *flags); diff --git a/include/crm/common/logging.h b/include/crm/common/logging.h index 2878fba..eea4cec 100644 --- a/include/crm/common/logging.h +++ b/include/crm/common/logging.h @@ -11,6 +11,7 @@ # define PCMK__CRM_COMMON_LOGGING__H # include <stdio.h> +# include <stdint.h> // uint8_t, uint32_t # include <glib.h> # include <qb/qblog.h> # include <libxml/tree.h> @@ -120,7 +121,9 @@ unsigned int set_crm_log_level(unsigned int level); unsigned int get_crm_log_level(void); -void pcmk_log_xml_impl(uint8_t level, const char *text, const xmlNode *xml); +void pcmk_log_xml_as(const char *file, const char *function, uint32_t line, + uint32_t tags, uint8_t level, const char *text, + const xmlNode *xml); /* * Throughout the macros below, note the leading, pre-comma, space in the @@ -270,7 +273,8 @@ pcmk__clip_log_level(int level) __LINE__, 0); \ } \ if (crm_is_callsite_active(xml_cs, _level, 0)) { \ - pcmk_log_xml_impl(_level, text, xml); \ + pcmk_log_xml_as(__FILE__, __func__, __LINE__, 0, \ + _level, text, (xml)); \ } \ break; \ } \ diff --git a/include/crm/common/logging_compat.h b/include/crm/common/logging_compat.h index cfdb562..b57a802 100644 --- a/include/crm/common/logging_compat.h +++ b/include/crm/common/logging_compat.h @@ -10,6 +10,7 @@ #ifndef PCMK__CRM_COMMON_LOGGING_COMPAT__H # define PCMK__CRM_COMMON_LOGGING_COMPAT__H +#include <stdint.h> // uint8_t #include <glib.h> #include <libxml/tree.h> @@ -78,6 +79,9 @@ void log_data_element(int log_level, const char *file, const char *function, int line, const char *prefix, const xmlNode *data, int depth, int legacy_options); +//! \deprecated Do not use Pacemaker for general-purpose logging +void pcmk_log_xml_impl(uint8_t level, const char *text, const xmlNode *xml); + #ifdef __cplusplus } #endif diff --git a/include/crm/common/logging_internal.h b/include/crm/common/logging_internal.h index 479dcab..981ddf3 100644 --- a/include/crm/common/logging_internal.h +++ b/include/crm/common/logging_internal.h @@ -19,6 +19,18 @@ extern "C" { # include <crm/common/logging.h> # include <crm/common/output_internal.h> +typedef void (*pcmk__config_error_func) (void *ctx, const char *msg, ...); +typedef void (*pcmk__config_warning_func) (void *ctx, const char *msg, ...); + +extern pcmk__config_error_func pcmk__config_error_handler; +extern pcmk__config_warning_func pcmk__config_warning_handler; + +extern void *pcmk__config_error_context; +extern void *pcmk__config_warning_context; + +void pcmk__set_config_error_handler(pcmk__config_error_func error_handler, void *error_context); +void pcmk__set_config_warning_handler(pcmk__config_warning_func warning_handler, void *warning_context); + /*! * \internal * \brief Log a configuration error @@ -26,9 +38,13 @@ extern "C" { * \param[in] fmt printf(3)-style format string * \param[in] ... Arguments for format string */ -# define pcmk__config_err(fmt...) do { \ - crm_config_error = TRUE; \ - crm_err(fmt); \ +# define pcmk__config_err(fmt...) do { \ + crm_config_error = TRUE; \ + if (pcmk__config_error_handler == NULL) { \ + crm_err(fmt); \ + } else { \ + pcmk__config_error_handler(pcmk__config_error_context, fmt); \ + } \ } while (0) /*! @@ -38,9 +54,13 @@ extern "C" { * \param[in] fmt printf(3)-style format string * \param[in] ... Arguments for format string */ -# define pcmk__config_warn(fmt...) do { \ - crm_config_warning = TRUE; \ - crm_warn(fmt); \ +# define pcmk__config_warn(fmt...) do { \ + crm_config_warning = TRUE; \ + if (pcmk__config_warning_handler == NULL) { \ + crm_warn(fmt); \ + } else { \ + pcmk__config_warning_handler(pcmk__config_warning_context, fmt); \ + } \ } while (0) /*! @@ -74,6 +94,76 @@ extern "C" { /*! * \internal + * \brief Log XML changes line-by-line in a formatted fashion + * + * \param[in] level Priority at which to log the messages + * \param[in] xml XML to log + * + * \note This does nothing when \p level is \c LOG_STDOUT. + */ +#define pcmk__log_xml_changes(level, xml) do { \ + uint8_t _level = pcmk__clip_log_level(level); \ + static struct qb_log_callsite *xml_cs = NULL; \ + \ + switch (_level) { \ + case LOG_STDOUT: \ + case LOG_NEVER: \ + break; \ + default: \ + if (xml_cs == NULL) { \ + xml_cs = qb_log_callsite_get(__func__, __FILE__, \ + "xml-changes", _level, \ + __LINE__, 0); \ + } \ + if (crm_is_callsite_active(xml_cs, _level, 0)) { \ + pcmk__log_xml_changes_as(__FILE__, __func__, __LINE__, \ + 0, _level, xml); \ + } \ + break; \ + } \ + } while(0) + +/*! + * \internal + * \brief Log an XML patchset line-by-line in a formatted fashion + * + * \param[in] level Priority at which to log the messages + * \param[in] patchset XML patchset to log + * + * \note This does nothing when \p level is \c LOG_STDOUT. + */ +#define pcmk__log_xml_patchset(level, patchset) do { \ + uint8_t _level = pcmk__clip_log_level(level); \ + static struct qb_log_callsite *xml_cs = NULL; \ + \ + switch (_level) { \ + case LOG_STDOUT: \ + case LOG_NEVER: \ + break; \ + default: \ + if (xml_cs == NULL) { \ + xml_cs = qb_log_callsite_get(__func__, __FILE__, \ + "xml-patchset", _level, \ + __LINE__, 0); \ + } \ + if (crm_is_callsite_active(xml_cs, _level, 0)) { \ + pcmk__log_xml_patchset_as(__FILE__, __func__, __LINE__, \ + 0, _level, patchset); \ + } \ + break; \ + } \ + } while(0) + +void pcmk__log_xml_changes_as(const char *file, const char *function, + uint32_t line, uint32_t tags, uint8_t level, + const xmlNode *xml); + +void pcmk__log_xml_patchset_as(const char *file, const char *function, + uint32_t line, uint32_t tags, uint8_t level, + const xmlNode *patchset); + +/*! + * \internal * \brief Initialize logging for command line tools * * \param[in] name The name of the program diff --git a/include/crm/common/nodes.h b/include/crm/common/nodes.h new file mode 100644 index 0000000..fbc3758 --- /dev/null +++ b/include/crm/common/nodes.h @@ -0,0 +1,144 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_NODES__H +# define PCMK__CRM_COMMON_NODES__H + +#include <glib.h> // gboolean, GList, GHashTable + +#include <crm/common/scheduler_types.h> // pcmk_resource_t, pcmk_scheduler_t + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief Scheduler API for nodes + * \ingroup core + */ + +// Special node attributes + +#define PCMK_NODE_ATTR_TERMINATE "terminate" + + +//! Possible node types +enum node_type { + pcmk_node_variant_cluster = 1, //!< Cluster layer node + pcmk_node_variant_remote = 2, //!< Pacemaker Remote node + + node_ping = 0, //!< \deprecated Do not use +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_node_variant_cluster instead + node_member = pcmk_node_variant_cluster, + + //! \deprecated Use pcmk_node_variant_remote instead + node_remote = pcmk_node_variant_remote, +#endif +}; + +//! When to probe a resource on a node (as specified in location constraints) +enum pe_discover_e { + pcmk_probe_always = 0, //! Always probe resource on node + pcmk_probe_never = 1, //! Never probe resource on node + pcmk_probe_exclusive = 2, //! Probe only on designated nodes + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_probe_always instead + pe_discover_always = pcmk_probe_always, + + //! \deprecated Use pcmk_probe_never instead + pe_discover_never = pcmk_probe_never, + + //! \deprecated Use pcmk_probe_exclusive instead + pe_discover_exclusive = pcmk_probe_exclusive, +#endif +}; + +//! Basic node information (all node objects for the same node share this) +struct pe_node_shared_s { + const char *id; //!< Node ID at the cluster layer + const char *uname; //!< Node name in cluster + enum node_type type; //!< Node variant + + // @TODO Convert these into a flag group + gboolean online; //!< Whether online + gboolean standby; //!< Whether in standby mode + gboolean standby_onfail; //!< Whether in standby mode due to on-fail + gboolean pending; //!< Whether controller membership is pending + gboolean unclean; //!< Whether node requires fencing + gboolean unseen; //!< Whether node has never joined cluster + gboolean shutdown; //!< Whether shutting down + gboolean expected_up; //!< Whether expected join state is member + gboolean is_dc; //!< Whether node is cluster's DC + gboolean maintenance; //!< Whether in maintenance mode + gboolean rsc_discovery_enabled; //!< Whether probes are allowed on node + + /*! + * Whether this is a guest node whose guest resource must be recovered or a + * remote node that must be fenced + */ + gboolean remote_requires_reset; + + /*! + * Whether this is a Pacemaker Remote node that was fenced since it was last + * connected by the cluster + */ + gboolean remote_was_fenced; + + /*! + * Whether this is a Pacemaker Remote node previously marked in its + * node state as being in maintenance mode + */ + gboolean remote_maintenance; + + gboolean unpacked; //!< Whether node history has been unpacked + + /*! + * Number of resources active on this node (valid after CIB status section + * has been unpacked, as long as pcmk_sched_no_counts was not set) + */ + int num_resources; + + //! Remote connection resource for node, if it is a Pacemaker Remote node + pcmk_resource_t *remote_rsc; + + GList *running_rsc; //!< List of resources active on node + GList *allocated_rsc; //!< List of resources assigned to node + GHashTable *attrs; //!< Node attributes + GHashTable *utilization; //!< Node utilization attributes + GHashTable *digest_cache; //!< Cache of calculated resource digests + + /*! + * Sum of priorities of all resources active on node and on any guest nodes + * connected to this node, with +1 for promoted instances (used to compare + * nodes for priority-fencing-delay) + */ + int priority; + + pcmk_scheduler_t *data_set; //!< Cluster that node is part of +}; + +//! Implementation of pcmk_node_t +struct pe_node_s { + int weight; //!< Node score for a given resource + gboolean fixed; //!< \deprecated Do not use + int count; //!< Counter reused by assignment and promotion code + struct pe_node_shared_s *details; //!< Basic node information + + // @COMPAT This should be enum pe_discover_e + int rsc_discover_mode; //!< Probe mode (enum pe_discover_e) +}; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_NODES__H diff --git a/include/crm/common/nvpair.h b/include/crm/common/nvpair.h index aebc199..185bdc3 100644 --- a/include/crm/common/nvpair.h +++ b/include/crm/common/nvpair.h @@ -46,7 +46,6 @@ void hash2smartfield(gpointer key, gpointer value, gpointer user_data); GHashTable *xml2list(const xmlNode *parent); const char *crm_xml_add(xmlNode *node, const char *name, const char *value); -const char *crm_xml_replace(xmlNode *node, const char *name, const char *value); const char *crm_xml_add_int(xmlNode *node, const char *name, int value); const char *crm_xml_add_ll(xmlNode *node, const char *name, long long value); const char *crm_xml_add_ms(xmlNode *node, const char *name, guint ms); diff --git a/include/crm/common/options_internal.h b/include/crm/common/options_internal.h index 4157b58..5c561fd 100644 --- a/include/crm/common/options_internal.h +++ b/include/crm/common/options_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the Pacemaker project contributors + * Copyright 2006-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -26,7 +26,7 @@ _Noreturn void pcmk__cli_help(char cmd); */ const char *pcmk__env_option(const char *option); -void pcmk__set_env_option(const char *option, const char *value); +void pcmk__set_env_option(const char *option, const char *value, bool compat); bool pcmk__env_option_enabled(const char *daemon, const char *option); @@ -76,18 +76,52 @@ long pcmk__auto_watchdog_timeout(void); bool pcmk__valid_sbd_timeout(const char *value); // Constants for environment variable names +#define PCMK__ENV_AUTHKEY_LOCATION "authkey_location" #define PCMK__ENV_BLACKBOX "blackbox" +#define PCMK__ENV_CALLGRIND_ENABLED "callgrind_enabled" #define PCMK__ENV_CLUSTER_TYPE "cluster_type" #define PCMK__ENV_DEBUG "debug" +#define PCMK__ENV_DH_MAX_BITS "dh_max_bits" +#define PCMK__ENV_DH_MIN_BITS "dh_min_bits" +#define PCMK__ENV_FAIL_FAST "fail_fast" +#define PCMK__ENV_IPC_BUFFER "ipc_buffer" +#define PCMK__ENV_IPC_TYPE "ipc_type" #define PCMK__ENV_LOGFACILITY "logfacility" #define PCMK__ENV_LOGFILE "logfile" +#define PCMK__ENV_LOGFILE_MODE "logfile_mode" #define PCMK__ENV_LOGPRIORITY "logpriority" -#define PCMK__ENV_MCP "mcp" +#define PCMK__ENV_NODE_ACTION_LIMIT "node_action_limit" #define PCMK__ENV_NODE_START_STATE "node_start_state" +#define PCMK__ENV_PANIC_ACTION "panic_action" #define PCMK__ENV_PHYSICAL_HOST "physical_host" +#define PCMK__ENV_REMOTE_ADDRESS "remote_address" +#define PCMK__ENV_REMOTE_PID1 "remote_pid1" +#define PCMK__ENV_REMOTE_PORT "remote_port" +#define PCMK__ENV_RESPAWNED "respawned" +#define PCMK__ENV_SCHEMA_DIRECTORY "schema_directory" +#define PCMK__ENV_SERVICE "service" +#define PCMK__ENV_STDERR "stderr" +#define PCMK__ENV_TLS_PRIORITIES "tls_priorities" +#define PCMK__ENV_TRACE_BLACKBOX "trace_blackbox" +#define PCMK__ENV_TRACE_FILES "trace_files" +#define PCMK__ENV_TRACE_FORMATS "trace_formats" +#define PCMK__ENV_TRACE_FUNCTIONS "trace_functions" +#define PCMK__ENV_TRACE_TAGS "trace_tags" +#define PCMK__ENV_VALGRIND_ENABLED "valgrind_enabled" + +// @COMPAT Drop at 3.0.0; default is plenty +#define PCMK__ENV_CIB_TIMEOUT "cib_timeout" + +// @COMPAT Drop at 3.0.0; likely last used in 1.1.24 +#define PCMK__ENV_MCP "mcp" + +// @COMPAT Drop at 3.0.0; added unused in 1.1.9 #define PCMK__ENV_QUORUM_TYPE "quorum_type" + +/* @COMPAT Drop at 3.0.0; added to debug shutdown issues when Pacemaker is + * managed by systemd, but no longer useful. + */ #define PCMK__ENV_SHUTDOWN_DELAY "shutdown_delay" -#define PCMK__ENV_STDERR "stderr" // Constants for cluster option names #define PCMK__OPT_NODE_HEALTH_BASE "node-health-base" diff --git a/include/crm/common/output_internal.h b/include/crm/common/output_internal.h index e7b631e..274bd85 100644 --- a/include/crm/common/output_internal.h +++ b/include/crm/common/output_internal.h @@ -763,6 +763,11 @@ pcmk__output_get_log_level(const pcmk__output_t *out); void pcmk__output_set_log_level(pcmk__output_t *out, uint8_t log_level); +void pcmk__output_set_log_filter(pcmk__output_t *out, const char *file, + const char *function, uint32_t line, + uint32_t tags); + + /*! * \internal * \brief Create and return a new XML node with the given name, as a child of the diff --git a/include/crm/common/remote_internal.h b/include/crm/common/remote_internal.h index 8473668..030c7a4 100644 --- a/include/crm/common/remote_internal.h +++ b/include/crm/common/remote_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2008-2022 the Pacemaker project contributors + * Copyright 2008-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -14,7 +14,7 @@ typedef struct pcmk__remote_s pcmk__remote_t; -int pcmk__remote_send_xml(pcmk__remote_t *remote, xmlNode *msg); +int pcmk__remote_send_xml(pcmk__remote_t *remote, const xmlNode *msg); int pcmk__remote_ready(const pcmk__remote_t *remote, int timeout_ms); int pcmk__read_remote_message(pcmk__remote_t *remote, int timeout_ms); xmlNode *pcmk__remote_message_xml(pcmk__remote_t *remote); diff --git a/include/crm/common/resources.h b/include/crm/common/resources.h new file mode 100644 index 0000000..043dc1c --- /dev/null +++ b/include/crm/common/resources.h @@ -0,0 +1,502 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_RESOURCES__H +# define PCMK__CRM_COMMON_RESOURCES__H + +#include <sys/types.h> // time_t +#include <libxml/tree.h> // xmlNode +#include <glib.h> // gboolean, guint, GList, GHashTable + +#include <crm/common/roles.h> // enum rsc_role_e +#include <crm/common/scheduler_types.h> // pcmk_resource_t, etc. + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief Scheduler API for resources + * \ingroup core + */ + +//! Resource variants supported by Pacemaker +enum pe_obj_types { + // Order matters: some code compares greater or lesser than + pcmk_rsc_variant_unknown = -1, //!< Unknown resource variant + pcmk_rsc_variant_primitive = 0, //!< Primitive resource + pcmk_rsc_variant_group = 1, //!< Group resource + pcmk_rsc_variant_clone = 2, //!< Clone resource + pcmk_rsc_variant_bundle = 3, //!< Bundle resource + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_rsc_variant_unknown instead + pe_unknown = pcmk_rsc_variant_unknown, + + //! \deprecated Use pcmk_rsc_variant_primitive instead + pe_native = pcmk_rsc_variant_primitive, + + //! \deprecated Use pcmk_rsc_variant_group instead + pe_group = pcmk_rsc_variant_group, + + //! \deprecated Use pcmk_rsc_variant_clone instead + pe_clone = pcmk_rsc_variant_clone, + + //! \deprecated Use pcmk_rsc_variant_bundle instead + pe_container = pcmk_rsc_variant_bundle, +#endif +}; + +//! What resource needs before it can be recovered from a failed node +enum rsc_start_requirement { + pcmk_requires_nothing = 0, //!< Resource can be recovered immediately + pcmk_requires_quorum = 1, //!< Resource can be recovered if quorate + pcmk_requires_fencing = 2, //!< Resource can be recovered after fencing + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_requires_nothing instead + rsc_req_nothing = pcmk_requires_nothing, + + //! \deprecated Use pcmk_requires_quorum instead + rsc_req_quorum = pcmk_requires_quorum, + + //! \deprecated Use pcmk_requires_fencing instead + rsc_req_stonith = pcmk_requires_fencing, +#endif +}; + +//! How to recover a resource that is incorrectly active on multiple nodes +enum rsc_recovery_type { + pcmk_multiply_active_restart = 0, //!< Stop on all, start on desired + pcmk_multiply_active_stop = 1, //!< Stop on all and leave stopped + pcmk_multiply_active_block = 2, //!< Do nothing to resource + pcmk_multiply_active_unexpected = 3, //!< Stop unexpected instances + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_multiply_active_restart instead + recovery_stop_start = pcmk_multiply_active_restart, + + //! \deprecated Use pcmk_multiply_active_stop instead + recovery_stop_only = pcmk_multiply_active_stop, + + //! \deprecated Use pcmk_multiply_active_block instead + recovery_block = pcmk_multiply_active_block, + + //! \deprecated Use pcmk_multiply_active_unexpected instead + recovery_stop_unexpected = pcmk_multiply_active_unexpected, +#endif +}; + +//! Resource scheduling flags +enum pcmk_rsc_flags { + //! No resource flags set (compare with equality rather than bit set) + pcmk_no_rsc_flags = 0ULL, + + //! Whether resource has been removed from the configuration + pcmk_rsc_removed = (1ULL << 0), + + //! Whether resource is managed + pcmk_rsc_managed = (1ULL << 1), + + //! Whether resource is blocked from further action + pcmk_rsc_blocked = (1ULL << 2), + + //! Whether resource has been removed but has a container + pcmk_rsc_removed_filler = (1ULL << 3), + + //! Whether resource has clone notifications enabled + pcmk_rsc_notify = (1ULL << 4), + + //! Whether resource is not an anonymous clone instance + pcmk_rsc_unique = (1ULL << 5), + + //! Whether resource's class is "stonith" + pcmk_rsc_fence_device = (1ULL << 6), + + //! Whether resource can be promoted and demoted + pcmk_rsc_promotable = (1ULL << 7), + + //! Whether resource has not yet been assigned to a node + pcmk_rsc_unassigned = (1ULL << 8), + + //! Whether resource is in the process of being assigned to a node + pcmk_rsc_assigning = (1ULL << 9), + + //! Whether resource is in the process of modifying allowed node scores + pcmk_rsc_updating_nodes = (1ULL << 10), + + //! Whether resource is in the process of scheduling actions to restart + pcmk_rsc_restarting = (1ULL << 11), + + //! Whether resource must be stopped (instead of demoted) if it is failed + pcmk_rsc_stop_if_failed = (1ULL << 12), + + //! Whether a reload action has been scheduled for resource + pcmk_rsc_reload = (1ULL << 13), + + //! Whether resource is a remote connection allowed to run on a remote node + pcmk_rsc_remote_nesting_allowed = (1ULL << 14), + + //! Whether resource has "critical" meta-attribute enabled + pcmk_rsc_critical = (1ULL << 15), + + //! Whether resource is considered failed + pcmk_rsc_failed = (1ULL << 16), + + //! Flag for non-scheduler code to use to detect recursion loops + pcmk_rsc_detect_loop = (1ULL << 17), + + //! \deprecated Do not use + pcmk_rsc_runnable = (1ULL << 18), + + //! Whether resource has pending start action in history + pcmk_rsc_start_pending = (1ULL << 19), + + //! \deprecated Do not use + pcmk_rsc_starting = (1ULL << 20), + + //! \deprecated Do not use + pcmk_rsc_stopping = (1ULL << 21), + + //! Whether resource is multiply active with recovery set to stop_unexpected + pcmk_rsc_stop_unexpected = (1ULL << 22), + + //! Whether resource is allowed to live-migrate + pcmk_rsc_migratable = (1ULL << 23), + + //! Whether resource has an ignorable failure + pcmk_rsc_ignore_failure = (1ULL << 24), + + //! Whether resource is an implicit container resource for a bundle replica + pcmk_rsc_replica_container = (1ULL << 25), + + //! Whether resource, its node, or entire cluster is in maintenance mode + pcmk_rsc_maintenance = (1ULL << 26), + + //! \deprecated Do not use + pcmk_rsc_has_filler = (1ULL << 27), + + //! Whether resource can be started or promoted only on quorate nodes + pcmk_rsc_needs_quorum = (1ULL << 28), + + //! Whether resource requires fencing before recovery if on unclean node + pcmk_rsc_needs_fencing = (1ULL << 29), + + //! Whether resource can be started or promoted only on unfenced nodes + pcmk_rsc_needs_unfencing = (1ULL << 30), +}; + +//! Search options for resources (exact resource ID always matches) +enum pe_find { + //! Also match clone instance ID from resource history + pcmk_rsc_match_history = (1 << 0), + + //! Also match anonymous clone instances by base name + pcmk_rsc_match_anon_basename = (1 << 1), + + //! Match only clones and their instances, by either clone or instance ID + pcmk_rsc_match_clone_only = (1 << 2), + + //! If matching by node, compare current node instead of assigned node + pcmk_rsc_match_current_node = (1 << 3), + + //! \deprecated Do not use + pe_find_inactive = (1 << 4), + + //! Match clone instances (even unique) by base name as well as exact ID + pcmk_rsc_match_basename = (1 << 5), + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_rsc_match_history instead + pe_find_renamed = pcmk_rsc_match_history, + + //! \deprecated Use pcmk_rsc_match_anon_basename instead + pe_find_anon = pcmk_rsc_match_anon_basename, + + //! \deprecated Use pcmk_rsc_match_clone_only instead + pe_find_clone = pcmk_rsc_match_clone_only, + + //! \deprecated Use pcmk_rsc_match_current_node instead + pe_find_current = pcmk_rsc_match_current_node, + + //! \deprecated Use pcmk_rsc_match_basename instead + pe_find_any = pcmk_rsc_match_basename, +#endif +}; + +//!@{ +//! \deprecated Do not use +enum pe_restart { + pe_restart_restart, + pe_restart_ignore, +}; + +enum pe_print_options { + pe_print_log = (1 << 0), + pe_print_html = (1 << 1), + pe_print_ncurses = (1 << 2), + pe_print_printf = (1 << 3), + pe_print_dev = (1 << 4), // Ignored + pe_print_details = (1 << 5), // Ignored + pe_print_max_details = (1 << 6), // Ignored + pe_print_rsconly = (1 << 7), + pe_print_ops = (1 << 8), + pe_print_suppres_nl = (1 << 9), + pe_print_xml = (1 << 10), + pe_print_brief = (1 << 11), + pe_print_pending = (1 << 12), + pe_print_clone_details = (1 << 13), + pe_print_clone_active = (1 << 14), // Print clone instances only if active + pe_print_implicit = (1 << 15) // Print implicitly created resources +}; +//!@} + +// Resource assignment methods (implementation defined by libpacemaker) +//! This type should be considered internal to Pacemaker +typedef struct resource_alloc_functions_s pcmk_assignment_methods_t; + +//! Resource object methods +typedef struct resource_object_functions_s { + /*! + * \brief Parse variant-specific resource XML from CIB into struct members + * + * \param[in,out] rsc Partially unpacked resource + * \param[in,out] scheduler Scheduler data + * + * \return TRUE if resource was unpacked successfully, otherwise FALSE + */ + gboolean (*unpack)(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler); + + /*! + * \brief Search for a resource ID in a resource and its children + * + * \param[in] rsc Search this resource and its children + * \param[in] id Search for this resource ID + * \param[in] on_node If not NULL, limit search to resources on this node + * \param[in] flags Group of enum pe_find flags + * + * \return Resource that matches search criteria if any, otherwise NULL + */ + pcmk_resource_t *(*find_rsc)(pcmk_resource_t *rsc, const char *search, + const pcmk_node_t *node, int flags); + + /*! + * \brief Get value of a resource instance attribute + * + * \param[in,out] rsc Resource to check + * \param[in] node Node to use to evaluate rules + * \param[in] create Ignored + * \param[in] name Name of instance attribute to check + * \param[in,out] scheduler Scheduler data + * + * \return Value of requested attribute if available, otherwise NULL + * \note The caller is responsible for freeing the result using free(). + */ + char *(*parameter)(pcmk_resource_t *rsc, pcmk_node_t *node, gboolean create, + const char *name, pcmk_scheduler_t *scheduler); + + //! \deprecated Do not use + void (*print)(pcmk_resource_t *rsc, const char *pre_text, long options, + void *print_data); + + /*! + * \brief Check whether a resource is active + * + * \param[in] rsc Resource to check + * \param[in] all If \p rsc is collective, all instances must be active + * + * \return TRUE if \p rsc is active, otherwise FALSE + */ + gboolean (*active)(pcmk_resource_t *rsc, gboolean all); + + /*! + * \brief Get resource's current or assigned role + * + * \param[in] rsc Resource to check + * \param[in] current If TRUE, check current role, otherwise assigned role + * + * \return Current or assigned role of \p rsc + */ + enum rsc_role_e (*state)(const pcmk_resource_t *rsc, gboolean current); + + /*! + * \brief List nodes where a resource (or any of its children) is + * + * \param[in] rsc Resource to check + * \param[out] list List to add result to + * \param[in] current If 0, list nodes where \p rsc is assigned; + * if 1, where active; if 2, where active or pending + * + * \return If list contains only one node, that node, otherwise NULL + */ + pcmk_node_t *(*location)(const pcmk_resource_t *rsc, GList **list, + int current); + + /*! + * \brief Free all memory used by a resource + * + * \param[in,out] rsc Resource to free + */ + void (*free)(pcmk_resource_t *rsc); + + /*! + * \brief Increment cluster's instance counts for a resource + * + * Given a resource, increment its cluster's ninstances, disabled_resources, + * and blocked_resources counts for the resource and its descendants. + * + * \param[in,out] rsc Resource to count + */ + void (*count)(pcmk_resource_t *rsc); + + /*! + * \brief Check whether a given resource is in a list of resources + * + * \param[in] rsc Resource ID to check for + * \param[in] only_rsc List of resource IDs to check + * \param[in] check_parent If TRUE, check top ancestor as well + * + * \return TRUE if \p rsc, its top parent if requested, or '*' is in + * \p only_rsc, otherwise FALSE + */ + gboolean (*is_filtered)(const pcmk_resource_t *rsc, GList *only_rsc, + gboolean check_parent); + + /*! + * \brief Find a node (and optionally count all) where resource is active + * + * \param[in] rsc Resource to check + * \param[out] count_all If not NULL, set this to count of active nodes + * \param[out] count_clean If not NULL, set this to count of clean nodes + * + * \return A node where the resource is active, preferring the source node + * if the resource is involved in a partial migration, or a clean, + * online node if the resource's "requires" is "quorum" or + * "nothing", otherwise NULL. + */ + pcmk_node_t *(*active_node)(const pcmk_resource_t *rsc, + unsigned int *count_all, + unsigned int *count_clean); + + /*! + * \brief Get maximum resource instances per node + * + * \param[in] rsc Resource to check + * + * \return Maximum number of \p rsc instances that can be active on one node + */ + unsigned int (*max_per_node)(const pcmk_resource_t *rsc); +} pcmk_rsc_methods_t; + +//! Implementation of pcmk_resource_t +struct pe_resource_s { + char *id; //!< Resource ID in configuration + char *clone_name; //!< Resource instance ID in history + + //! Resource configuration (possibly expanded from template) + xmlNode *xml; + + //! Original resource configuration, if using template + xmlNode *orig_xml; + + //! Configuration of resource operations (possibly expanded from template) + xmlNode *ops_xml; + + pcmk_scheduler_t *cluster; //!< Cluster that resource is part of + pcmk_resource_t *parent; //!< Resource's parent resource, if any + enum pe_obj_types variant; //!< Resource variant + void *variant_opaque; //!< Variant-specific (and private) data + pcmk_rsc_methods_t *fns; //!< Resource object methods + pcmk_assignment_methods_t *cmds; //!< Resource assignment methods + + enum rsc_recovery_type recovery_type; //!< How to recover if failed + + enum pe_restart restart_type; //!< \deprecated Do not use + int priority; //!< Configured priority + int stickiness; //!< Extra preference for current node + int sort_index; //!< Promotion score on assigned node + int failure_timeout; //!< Failure timeout + int migration_threshold; //!< Migration threshold + guint remote_reconnect_ms; //!< Retry interval for remote connections + char *pending_task; //!< Pending action in history, if any + unsigned long long flags; //!< Group of enum pcmk_rsc_flags + + // @TODO Merge these into flags + gboolean is_remote_node; //!< Whether this is a remote connection + gboolean exclusive_discover; //!< Whether exclusive probing is enabled + + /* Pay special attention to whether you want to use rsc_cons_lhs and + * rsc_cons directly, which include only colocations explicitly involving + * this resource, or call libpacemaker's pcmk__with_this_colocations() and + * pcmk__this_with_colocations() functions, which may return relevant + * colocations involving the resource's ancestors as well. + */ + + //!@{ + //! This field should be treated as internal to Pacemaker + GList *rsc_cons_lhs; // Colocations of other resources with this one + GList *rsc_cons; // Colocations of this resource with others + GList *rsc_location; // Location constraints for resource + GList *actions; // Actions scheduled for resource + GList *rsc_tickets; // Ticket constraints for resource + //!@} + + pcmk_node_t *allocated_to; //!< Node resource is assigned to + + //! The destination node, if migrate_to completed but migrate_from has not + pcmk_node_t *partial_migration_target; + + //! The source node, if migrate_to completed but migrate_from has not + pcmk_node_t *partial_migration_source; + + //! Nodes where resource may be active + GList *running_on; + + //! Nodes where resource has been probed (key is node ID, not name) + GHashTable *known_on; + + //! Nodes where resource may run (key is node ID, not name) + GHashTable *allowed_nodes; + + enum rsc_role_e role; //!< Resource's current role + enum rsc_role_e next_role; //!< Resource's scheduled next role + + GHashTable *meta; //!< Resource's meta-attributes + GHashTable *parameters; //!< \deprecated Use pe_rsc_params() instead + GHashTable *utilization; //!< Resource's utilization attributes + + GList *children; //!< Resource's child resources, if any + + // Source nodes where stop is needed after migrate_from and migrate_to + GList *dangling_migrations; + + pcmk_resource_t *container; //!< Resource containing this one, if any + GList *fillers; //!< Resources contained by this one, if any + + // @COMPAT These should be made const at next API compatibility break + pcmk_node_t *pending_node; //!< Node on which pending_task is happening + pcmk_node_t *lock_node; //!< Resource shutdown-locked to this node + + time_t lock_time; //!< When shutdown lock started + + /*! + * Resource parameters may have node-attribute-based rules, which means the + * values can vary by node. This table has node names as keys and parameter + * name/value tables as values. Use pe_rsc_params() to get the table for a + * given node rather than use this directly. + */ + GHashTable *parameter_cache; +}; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_RESOURCES__H diff --git a/include/crm/common/results.h b/include/crm/common/results.h index 224bcbe..87d00d2 100644 --- a/include/crm/common/results.h +++ b/include/crm/common/results.h @@ -108,6 +108,9 @@ enum pcmk_rc_e { /* When adding new values, use consecutively lower numbers, update the array * in lib/common/results.c, and test with crm_error. */ + pcmk_rc_compression = -1039, + pcmk_rc_ns_resolution = -1038, + pcmk_rc_no_transaction = -1037, pcmk_rc_bad_xml_patch = -1036, pcmk_rc_bad_input = -1035, pcmk_rc_disabled = -1034, @@ -360,7 +363,6 @@ int pcmk_rc2legacy(int rc); int pcmk_legacy2rc(int legacy_rc); const char *pcmk_strerror(int rc); const char *pcmk_errorname(int rc); -const char *bz2_strerror(int rc); const char *crm_exit_name(crm_exit_t exit_code); const char *crm_exit_str(crm_exit_t exit_code); _Noreturn crm_exit_t crm_exit(crm_exit_t rc); diff --git a/include/crm/common/results_compat.h b/include/crm/common/results_compat.h index 00ac6b2..278e48e 100644 --- a/include/crm/common/results_compat.h +++ b/include/crm/common/results_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 the Pacemaker project contributors + * Copyright 2022-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -25,6 +25,9 @@ extern "C" { * release. */ +//! \deprecated Do not use +const char *bz2_strerror(int rc); + //! \deprecated Use pcmk_rc2exitc(pcmk_legacy2rc(rc)) instead crm_exit_t crm_errno2exit(int rc); diff --git a/include/crm/common/results_internal.h b/include/crm/common/results_internal.h index be62780..09907e9 100644 --- a/include/crm/common/results_internal.h +++ b/include/crm/common/results_internal.h @@ -69,6 +69,9 @@ void pcmk__reset_result(pcmk__action_result_t *result); void pcmk__copy_result(const pcmk__action_result_t *src, pcmk__action_result_t *dst); +int pcmk__gaierror2rc(int gai); +int pcmk__bzlib2rc(int bz2); + /*! * \internal * \brief Check whether a result is OK diff --git a/include/crm/common/roles.h b/include/crm/common/roles.h new file mode 100644 index 0000000..1498097 --- /dev/null +++ b/include/crm/common/roles.h @@ -0,0 +1,62 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_ROLES__H +# define PCMK__CRM_COMMON_ROLES__H + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief Scheduler API for resource roles + * \ingroup core + */ + +/*! + * Possible roles that a resource can be in + * (order matters; values can be compared with less than and greater than) + */ +enum rsc_role_e { + pcmk_role_unknown = 0, //!< Resource role is unknown + pcmk_role_stopped = 1, //!< Stopped + pcmk_role_started = 2, //!< Started + pcmk_role_unpromoted = 3, //!< Unpromoted + pcmk_role_promoted = 4, //!< Promoted + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_role_unknown instead + RSC_ROLE_UNKNOWN = pcmk_role_unknown, + + //! \deprecated Use pcmk_role_stopped instead + RSC_ROLE_STOPPED = pcmk_role_stopped, + + //! \deprecated Use pcmk_role_started instead + RSC_ROLE_STARTED = pcmk_role_started, + + //! \deprecated Use pcmk_role_unpromoted instead + RSC_ROLE_UNPROMOTED = pcmk_role_unpromoted, + + //! \deprecated Use pcmk_role_unpromoted instead + RSC_ROLE_SLAVE = pcmk_role_unpromoted, + + //! \deprecated Use pcmk_role_promoted instead + RSC_ROLE_PROMOTED = pcmk_role_promoted, + + //! \deprecated Use pcmk_role_promoted instead + RSC_ROLE_MASTER = pcmk_role_promoted, +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_ROLES__H diff --git a/include/crm/common/roles_internal.h b/include/crm/common/roles_internal.h new file mode 100644 index 0000000..e304f13 --- /dev/null +++ b/include/crm/common/roles_internal.h @@ -0,0 +1,30 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_ROLES_INTERNAL__H +# define PCMK__CRM_COMMON_ROLES_INTERNAL__H + +#ifdef __cplusplus +extern "C" { +#endif + +// String equivalents of enum rsc_role_e +#define PCMK__ROLE_UNKNOWN "Unknown" +#define PCMK__ROLE_STOPPED "Stopped" +#define PCMK__ROLE_STARTED "Started" +#define PCMK__ROLE_UNPROMOTED "Unpromoted" +#define PCMK__ROLE_PROMOTED "Promoted" +#define PCMK__ROLE_UNPROMOTED_LEGACY "Slave" +#define PCMK__ROLE_PROMOTED_LEGACY "Master" + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_ROLES_INTERNAL__H diff --git a/include/crm/common/scheduler.h b/include/crm/common/scheduler.h new file mode 100644 index 0000000..96f9a62 --- /dev/null +++ b/include/crm/common/scheduler.h @@ -0,0 +1,238 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_SCHEDULER__H +# define PCMK__CRM_COMMON_SCHEDULER__H + +#include <sys/types.h> // time_t +#include <libxml/tree.h> // xmlNode +#include <glib.h> // guint, GList, GHashTable + +#include <crm/common/iso8601.h> // crm_time_t + +#include <crm/common/actions.h> +#include <crm/common/nodes.h> +#include <crm/common/resources.h> +#include <crm/common/roles.h> +#include <crm/common/scheduler_types.h> +#include <crm/common/tags.h> +#include <crm/common/tickets.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief Scheduler API + * \ingroup core + */ + +//! Possible responses to loss of quorum +enum pe_quorum_policy { + pcmk_no_quorum_freeze, //<! Do not recover resources from outside partition + pcmk_no_quorum_stop, //<! Stop all resources in partition + pcmk_no_quorum_ignore, //<! Act as if partition still holds quorum + pcmk_no_quorum_fence, //<! Fence all nodes in partition + pcmk_no_quorum_demote, //<! Demote promotable resources and stop all others + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + //! \deprecated Use pcmk_no_quorum_freeze instead + no_quorum_freeze = pcmk_no_quorum_freeze, + + //! \deprecated Use pcmk_no_quorum_stop instead + no_quorum_stop = pcmk_no_quorum_stop, + + //! \deprecated Use pcmk_no_quorum_ignore instead + no_quorum_ignore = pcmk_no_quorum_ignore, + + //! \deprecated Use pcmk_no_quorum_fence instead + no_quorum_suicide = pcmk_no_quorum_fence, + + //! \deprecated Use pcmk_no_quorum_demote instead + no_quorum_demote = pcmk_no_quorum_demote, +#endif +}; + +//! Scheduling options and conditions +enum pcmk_scheduler_flags { + //! No scheduler flags set (compare with equality rather than bit set) + pcmk_sched_none = 0ULL, + + // These flags are dynamically determined conditions + + //! Whether partition has quorum (via have-quorum property) + pcmk_sched_quorate = (1ULL << 0), + + //! Whether cluster is symmetric (via symmetric-cluster property) + pcmk_sched_symmetric_cluster = (1ULL << 1), + + //! Whether cluster is in maintenance mode (via maintenance-mode property) + pcmk_sched_in_maintenance = (1ULL << 3), + + //! Whether fencing is enabled (via stonith-enabled property) + pcmk_sched_fencing_enabled = (1ULL << 4), + + //! Whether cluster has a fencing resource (via CIB resources) + pcmk_sched_have_fencing = (1ULL << 5), + + //! Whether any resource provides or requires unfencing (via CIB resources) + pcmk_sched_enable_unfencing = (1ULL << 6), + + //! Whether concurrent fencing is allowed (via concurrent-fencing property) + pcmk_sched_concurrent_fencing = (1ULL << 7), + + /*! + * Whether resources removed from the configuration should be stopped (via + * stop-orphan-resources property) + */ + pcmk_sched_stop_removed_resources = (1ULL << 8), + + /*! + * Whether recurring actions removed from the configuration should be + * cancelled (via stop-orphan-actions property) + */ + pcmk_sched_cancel_removed_actions = (1ULL << 9), + + //! Whether to stop all resources (via stop-all-resources property) + pcmk_sched_stop_all = (1ULL << 10), + + /*! + * Whether start failure should be treated as if migration-threshold is 1 + * (via start-failure-is-fatal property) + */ + pcmk_sched_start_failure_fatal = (1ULL << 12), + + //! \deprecated Do not use + pcmk_sched_remove_after_stop = (1ULL << 13), + + //! Whether unseen nodes should be fenced (via startup-fencing property) + pcmk_sched_startup_fencing = (1ULL << 14), + + /*! + * Whether resources should be left stopped when their node shuts down + * cleanly (via shutdown-lock property) + */ + pcmk_sched_shutdown_lock = (1ULL << 15), + + /*! + * Whether resources' current state should be probed (when unknown) before + * scheduling any other actions (via the enable-startup-probes property) + */ + pcmk_sched_probe_resources = (1ULL << 16), + + //! Whether the CIB status section has been parsed yet + pcmk_sched_have_status = (1ULL << 17), + + //! Whether the cluster includes any Pacemaker Remote nodes (via CIB) + pcmk_sched_have_remote_nodes = (1ULL << 18), + + // The remaining flags are scheduling options that must be set explicitly + + /*! + * Whether to skip unpacking the CIB status section and stop the scheduling + * sequence after applying node-specific location criteria (skipping + * assignment, ordering, actions, etc.). + */ + pcmk_sched_location_only = (1ULL << 20), + + //! Whether sensitive resource attributes have been masked + pcmk_sched_sanitized = (1ULL << 21), + + //! Skip counting of total, disabled, and blocked resource instances + pcmk_sched_no_counts = (1ULL << 23), + + /*! + * Skip deprecated code kept solely for backward API compatibility + * (internal code should always set this) + */ + pcmk_sched_no_compat = (1ULL << 24), + + //! Whether node scores should be output instead of logged + pcmk_sched_output_scores = (1ULL << 25), + + //! Whether to show node and resource utilization (in log or output) + pcmk_sched_show_utilization = (1ULL << 26), + + /*! + * Whether to stop the scheduling sequence after unpacking the CIB, + * calculating cluster status, and applying node health (skipping + * applying node-specific location criteria, assignment, etc.) + */ + pcmk_sched_validate_only = (1ULL << 27), +}; + +//! Implementation of pcmk_scheduler_t +struct pe_working_set_s { + // Be careful about when each piece of information is available and final + + xmlNode *input; //!< CIB XML + crm_time_t *now; //!< Current time for evaluation purposes + char *dc_uuid; //!< Node ID of designated controller + pcmk_node_t *dc_node; //!< Node object for DC + const char *stonith_action; //!< Default fencing action + const char *placement_strategy; //!< Value of placement-strategy property + + // @COMPAT Change to uint64_t at a compatibility break + unsigned long long flags; //!< Group of enum pcmk_scheduler_flags + + int stonith_timeout; //!< Value of stonith-timeout property + enum pe_quorum_policy no_quorum_policy; //!< Response to loss of quorum + GHashTable *config_hash; //!< Cluster properties + + //!< Ticket constraints unpacked from ticket state + GHashTable *tickets; + + //! Actions for which there can be only one (such as "fence node X") + GHashTable *singletons; + + GList *nodes; //!< Nodes in cluster + GList *resources; //!< Resources in cluster + GList *placement_constraints; //!< Location constraints + GList *ordering_constraints; //!< Ordering constraints + GList *colocation_constraints; //!< Colocation constraints + + //!< Ticket constraints unpacked by libpacemaker + GList *ticket_constraints; + + GList *actions; //!< Scheduled actions + xmlNode *failed; //!< History entries of failed actions + xmlNode *op_defaults; //!< Configured operation defaults + xmlNode *rsc_defaults; //!< Configured resource defaults + int num_synapse; //!< Number of transition graph synapses + int max_valid_nodes; //!< \deprecated Do not use + int order_id; //!< ID to use for next created ordering + int action_id; //!< ID to use for next created action + xmlNode *graph; //!< Transition graph + GHashTable *template_rsc_sets; //!< Mappings of template ID to resource ID + + // @COMPAT Replace this with a fencer variable (only place it's used) + const char *localhost; //!< \deprecated Do not use + + GHashTable *tags; //!< Configuration tags (ID -> pcmk_tag_t *) + int blocked_resources; //!< Number of blocked resources in cluster + int disabled_resources; //!< Number of disabled resources in cluster + GList *param_check; //!< History entries that need to be checked + GList *stop_needed; //!< Containers that need stop actions + time_t recheck_by; //!< Hint to controller when to reschedule + int ninstances; //!< Total number of resource instances + guint shutdown_lock; //!< How long to lock resources (seconds) + int priority_fencing_delay; //!< Priority fencing delay + + // pcmk__output_t * + void *priv; //!< For Pacemaker use only + + guint node_pending_timeout; //!< Pending join times out after this (ms) +}; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_SCHEDULER__H diff --git a/include/crm/common/scheduler_internal.h b/include/crm/common/scheduler_internal.h new file mode 100644 index 0000000..1f1da9f --- /dev/null +++ b/include/crm/common/scheduler_internal.h @@ -0,0 +1,67 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_SCHEDULER_INTERNAL__H +# define PCMK__CRM_COMMON_SCHEDULER_INTERNAL__H + +#include <crm/common/action_relation_internal.h> +#include <crm/common/clone_internal.h> +#include <crm/common/digests_internal.h> +#include <crm/common/failcounts_internal.h> +#include <crm/common/group_internal.h> +#include <crm/common/roles_internal.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Some warnings are too noisy when logged every time a give function is called + * (for example, using a deprecated feature). As an alternative, we allow + * warnings to be logged once per scheduler sequence (transition). Each of those + * warnings needs a flag defined here. + */ +enum pcmk__sched_warnings { + pcmk__wo_blind = (1 << 0), + pcmk__wo_restart_type = (1 << 1), + pcmk__wo_role_after = (1 << 2), + pcmk__wo_poweroff = (1 << 3), + pcmk__wo_require_all = (1 << 4), + pcmk__wo_order_score = (1 << 5), + pcmk__wo_neg_threshold = (1 << 6), + pcmk__wo_remove_after = (1 << 7), + pcmk__wo_ping_node = (1 << 8), + pcmk__wo_order_inst = (1 << 9), + pcmk__wo_coloc_inst = (1 << 10), + pcmk__wo_group_order = (1 << 11), + pcmk__wo_group_coloc = (1 << 12), + pcmk__wo_upstart = (1 << 13), + pcmk__wo_nagios = (1 << 14), + pcmk__wo_set_ordering = (1 << 15), +}; + +enum pcmk__check_parameters { + /* Clear fail count if parameters changed for un-expired start or monitor + * last_failure. + */ + pcmk__check_last_failure, + + /* Clear fail count if parameters changed for start, monitor, promote, or + * migrate_from actions for active resources. + */ + pcmk__check_active, +}; + +// Group of enum pcmk__sched_warnings flags for warnings we want to log once +extern uint32_t pcmk__warnings; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_SCHEDULER_INTERNAL__H diff --git a/include/crm/common/scheduler_types.h b/include/crm/common/scheduler_types.h new file mode 100644 index 0000000..5c4a193 --- /dev/null +++ b/include/crm/common/scheduler_types.h @@ -0,0 +1,39 @@ +/* + * Copyright 2023 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 PCMK__CRM_COMMON_SCHEDULER_TYPES__H +# define PCMK__CRM_COMMON_SCHEDULER_TYPES__H + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief Type aliases needed to define scheduler objects + * \ingroup core + */ + +//! Node object (including information that may vary depending on resource) +typedef struct pe_node_s pcmk_node_t; + +//! Resource object +typedef struct pe_resource_s pcmk_resource_t; + +//! Action object +typedef struct pe_action_s pcmk_action_t; + +//! Scheduler object +typedef struct pe_working_set_s pcmk_scheduler_t; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_SCHEDULER_TYPES__H diff --git a/include/crm/common/tags.h b/include/crm/common/tags.h new file mode 100644 index 0000000..3f4861d --- /dev/null +++ b/include/crm/common/tags.h @@ -0,0 +1,35 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_TAGS__H +# define PCMK__CRM_COMMON_TAGS__H + +#include <glib.h> // GList + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief Scheduler API for configuration tags + * \ingroup core + */ + +//! Configuration tag object +typedef struct pe_tag_s { + char *id; //!< XML ID of tag + GList *refs; //!< XML IDs of objects that reference the tag +} pcmk_tag_t; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_TAGS__H diff --git a/include/crm/common/tickets.h b/include/crm/common/tickets.h new file mode 100644 index 0000000..40079e9 --- /dev/null +++ b/include/crm/common/tickets.h @@ -0,0 +1,39 @@ +/* + * Copyright 2004-2023 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 PCMK__CRM_COMMON_TICKETS__H +# define PCMK__CRM_COMMON_TICKETS__H + +#include <sys/types.h> // time_t +#include <glib.h> // gboolean, GHashTable + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief Scheduler API for tickets + * \ingroup core + */ + +//! Ticket constraint object +typedef struct pe_ticket_s { + char *id; //!< XML ID of ticket constraint or state + gboolean granted; //!< Whether cluster has been granted the ticket + time_t last_granted; //!< When cluster was last granted the ticket + gboolean standby; //!< Whether ticket is temporarily suspended + GHashTable *state; //!< XML attributes from ticket state +} pcmk_ticket_t; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_TICKETS__H diff --git a/include/crm/common/unittest_internal.h b/include/crm/common/unittest_internal.h index b8f78cf..1fc8501 100644 --- a/include/crm/common/unittest_internal.h +++ b/include/crm/common/unittest_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 the Pacemaker project contributors + * Copyright 2022-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -65,6 +65,44 @@ } \ } while (0); +/*! + * \internal + * \brief Assert that a statement exits with the expected exit status. + * + * \param[in] stmt Statement to execute; can be an expression. + * \param[in] rc The expected exit status. + * + * This functions just like \c pcmk__assert_asserts, except that it tests for + * an expected exit status. Abnormal termination or incorrect exit status is + * treated as a failure of the test. + * + * In the event that stmt does not exit at all, the special code \c CRM_EX_NONE + * will be returned. It is expected that this code is not used anywhere, thus + * always causing an error. + */ +#define pcmk__assert_exits(rc, stmt) \ + do { \ + pid_t p = fork(); \ + if (p == 0) { \ + struct rlimit cores = { 0, 0 }; \ + setrlimit(RLIMIT_CORE, &cores); \ + stmt; \ + _exit(CRM_EX_NONE); \ + } else if (p > 0) { \ + int wstatus = 0; \ + if (waitpid(p, &wstatus, 0) == -1) { \ + fail_msg("waitpid failed"); \ + } \ + if (!WIFEXITED(wstatus)) { \ + fail_msg("statement terminated abnormally"); \ + } else if (WEXITSTATUS(wstatus) != rc) { \ + fail_msg("statement exited with %d, not expected %d", WEXITSTATUS(wstatus), rc); \ + } \ + } else { \ + fail_msg("unable to fork for assert test"); \ + } \ + } while (0); + /* Generate the main function of most unit test files. Typically, group_setup * and group_teardown will be NULL. The rest of the arguments are a list of * calls to cmocka_unit_test or cmocka_unit_test_setup_teardown to run the diff --git a/include/crm/common/util.h b/include/crm/common/util.h index 8acdff9..c75a55e 100644 --- a/include/crm/common/util.h +++ b/include/crm/common/util.h @@ -18,10 +18,8 @@ # include <signal.h> # include <glib.h> -# include <libxml/tree.h> - -# include <crm/lrmd.h> # include <crm/common/acl.h> +# include <crm/common/actions.h> # include <crm/common/agents.h> # include <crm/common/results.h> @@ -59,26 +57,6 @@ char *crm_strdup_printf(char const *format, ...) G_GNUC_PRINTF(1, 2); guint crm_parse_interval_spec(const char *input); -/* public operation functions (from operations.c) */ -gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, - guint *interval_ms); -gboolean decode_transition_key(const char *key, char **uuid, int *transition_id, - int *action_id, int *target_rc); -gboolean decode_transition_magic(const char *magic, char **uuid, - int *transition_id, int *action_id, - int *op_status, int *op_rc, int *target_rc); -int rsc_op_expected_rc(const lrmd_event_data_t *event); -gboolean did_rsc_op_fail(lrmd_event_data_t *event, int target_rc); -bool crm_op_needs_metadata(const char *rsc_class, const char *op); -xmlNode *crm_create_op_xml(xmlNode *parent, const char *prefix, - const char *task, const char *interval_spec, - const char *timeout); -#define CRM_DEFAULT_OP_TIMEOUT_S "20s" - -bool pcmk_is_probe(const char *task, guint interval); -bool pcmk_xe_is_probe(const xmlNode *xml_op); -bool pcmk_xe_mask_probe_failure(const xmlNode *xml_op); - int compare_version(const char *version1, const char *version2); /* coverity[+kill] */ diff --git a/include/crm/common/util_compat.h b/include/crm/common/util_compat.h index 9e02e12..7a60208 100644 --- a/include/crm/common/util_compat.h +++ b/include/crm/common/util_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2021 the Pacemaker project contributors + * Copyright 2004-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -11,6 +11,7 @@ # define PCMK__CRM_COMMON_UTIL_COMPAT__H # include <glib.h> +# include <libxml/tree.h> # include <crm/common/util.h> #ifdef __cplusplus @@ -29,6 +30,9 @@ extern "C" { //! \deprecated Use crm_parse_interval_spec() instead #define crm_get_interval crm_parse_interval_spec +//! \deprecated Do not use +#define CRM_DEFAULT_OP_TIMEOUT_S "20s" + //! \deprecated Use !pcmk_is_set() or !pcmk_all_flags_set() instead static inline gboolean is_not_set(long long word, long long bit) @@ -69,6 +73,9 @@ int pcmk_scan_nvpair(const char *input, char **name, char **value); char *pcmk_format_nvpair(const char *name, const char *value, const char *units); +//! \deprecated Use \c crm_xml_add() or \c xml_remove_prop() instead +const char *crm_xml_replace(xmlNode *node, const char *name, const char *value); + //! \deprecated Use a standard printf()-style function instead char *pcmk_format_named_time(const char *name, time_t epoch_time); diff --git a/include/crm/common/xml.h b/include/crm/common/xml.h index 682b31c..ac839d3 100644 --- a/include/crm/common/xml.h +++ b/include/crm/common/xml.h @@ -52,8 +52,6 @@ typedef const xmlChar *pcmkXmlStr; gboolean add_message_xml(xmlNode * msg, const char *field, xmlNode * xml); xmlNode *get_message_xml(const xmlNode *msg, const char *field); -xmlDoc *getDocPtr(xmlNode * node); - /* * \brief xmlCopyPropList ACLs-sensitive replacement expading i++ notation * @@ -132,12 +130,13 @@ xmlNode *stdin2xml(void); xmlNode *string2xml(const char *input); -int write_xml_fd(xmlNode * xml_node, const char *filename, int fd, gboolean compress); -int write_xml_file(xmlNode * xml_node, const char *filename, gboolean compress); +int write_xml_fd(const xmlNode *xml, const char *filename, int fd, + gboolean compress); +int write_xml_file(const xmlNode *xml, const char *filename, gboolean compress); -char *dump_xml_formatted(xmlNode * msg); -char *dump_xml_formatted_with_text(xmlNode * msg); -char *dump_xml_unformatted(xmlNode * msg); +char *dump_xml_formatted(const xmlNode *xml); +char *dump_xml_formatted_with_text(const xmlNode *xml); +char *dump_xml_unformatted(const xmlNode *xml); /* * Diff related Functions @@ -170,25 +169,17 @@ xmlNode *get_xpath_object(const char *xpath, xmlNode * xml_obj, int error_level) xmlNode *get_xpath_object_relative(const char *xpath, xmlNode * xml_obj, int error_level); static inline const char * -crm_element_name(const xmlNode *xml) -{ - return xml? (const char *)(xml->name) : NULL; -} - -static inline const char * crm_map_element_name(const xmlNode *xml) { - const char *name = crm_element_name(xml); - - if (strcmp(name, "master") == 0) { + if (xml == NULL) { + return NULL; + } else if (strcmp((const char *) xml->name, "master") == 0) { return "clone"; } else { - return name; + return (const char *) xml->name; } } -gboolean xml_has_children(const xmlNode * root); - char *calculate_on_disk_digest(xmlNode * local_cib); char *calculate_operation_digest(xmlNode * local_cib, const char *version); char *calculate_xml_versioned_digest(xmlNode * input, gboolean sort, gboolean do_filter, @@ -196,7 +187,7 @@ char *calculate_xml_versioned_digest(xmlNode * input, gboolean sort, gboolean do /* schema-related functions (from schemas.c) */ gboolean validate_xml(xmlNode * xml_blob, const char *validation, gboolean to_logs); -gboolean validate_xml_verbose(xmlNode * xml_blob); +gboolean validate_xml_verbose(const xmlNode *xml_blob); /*! * \brief Update CIB XML to most recent schema version @@ -258,7 +249,7 @@ xmlNode *first_named_child(const xmlNode *parent, const char *name); xmlNode *crm_next_same_xml(const xmlNode *sibling); xmlNode *sorted_xml(xmlNode * input, xmlNode * parent, gboolean recursive); -xmlXPathObjectPtr xpath_search(xmlNode * xml_top, const char *path); +xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path); void crm_foreach_xpath_result(xmlNode *xml, const char *xpath, void (*helper)(xmlNode*, void*), void *user_data); xmlNode *expand_idref(xmlNode * input, xmlNode * top); @@ -289,7 +280,8 @@ int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version); void patchset_process_digest(xmlNode *patch, xmlNode *source, xmlNode *target, bool with_digest); -void save_xml_to_file(xmlNode * xml, const char *desc, const char *filename); +void save_xml_to_file(const xmlNode *xml, const char *desc, + const char *filename); char * crm_xml_escape(const char *text); void crm_xml_sanitize_id(char *id); diff --git a/include/crm/common/xml_compat.h b/include/crm/common/xml_compat.h index bb49b68..85e39ff 100644 --- a/include/crm/common/xml_compat.h +++ b/include/crm/common/xml_compat.h @@ -31,6 +31,9 @@ extern "C" { #define XML_PARANOIA_CHECKS 0 //! \deprecated This function will be removed in a future release +xmlDoc *getDocPtr(xmlNode *node); + +//! \deprecated This function will be removed in a future release int add_node_nocopy(xmlNode * parent, const char *name, xmlNode * child); //! \deprecated This function will be removed in a future release @@ -51,13 +54,23 @@ gboolean apply_xml_diff(xmlNode *old_xml, xmlNode *diff, xmlNode **new_xml); //! \deprecated Do not use (will be removed in a future release) void crm_destroy_xml(gpointer data); -//! \deprecated Use crm_xml_add() with "true" or "false" instead +//! \deprecated Check children member directly +gboolean xml_has_children(const xmlNode *root); + +//! \deprecated Use crm_xml_add() with "true" or "false" instead static inline const char * crm_xml_add_boolean(xmlNode *node, const char *name, gboolean value) { return crm_xml_add(node, name, (value? "true" : "false")); } +//! \deprecated Use name member directly +static inline const char * +crm_element_name(const xmlNode *xml) +{ + return (xml == NULL)? NULL : (const char *) xml->name; +} + #ifdef __cplusplus } #endif diff --git a/include/crm/common/xml_internal.h b/include/crm/common/xml_internal.h index 43b3b8c..ddb4384 100644 --- a/include/crm/common/xml_internal.h +++ b/include/crm/common/xml_internal.h @@ -21,6 +21,7 @@ # include <crm/crm.h> /* transitively imports qblog.h */ # include <crm/common/output_internal.h> +# include <libxml/relaxng.h> /*! * \brief Base for directing lib{xml2,xslt} log into standard libqb backend @@ -135,9 +136,6 @@ enum pcmk__xml_fmt_options { //! Include indentation and newlines pcmk__xml_fmt_pretty = (1 << 1), - //! Include full XML subtree (with any text), using libxml serialization - pcmk__xml_fmt_full = (1 << 2), - //! Include the opening tag of an XML element, and include XML comments pcmk__xml_fmt_open = (1 << 3), @@ -147,7 +145,6 @@ enum pcmk__xml_fmt_options { //! Include the closing tag of an XML element pcmk__xml_fmt_close = (1 << 5), - // @COMPAT Remove when log_data_element() is removed //! Include XML text nodes pcmk__xml_fmt_text = (1 << 6), @@ -190,6 +187,16 @@ int pcmk__xml_show_changes(pcmk__output_t *out, const xmlNode *xml); #define PCMK__XP_REMOTE_NODE_STATUS \ "//" XML_TAG_CIB "//" XML_CIB_TAG_STATUS "//" XML_CIB_TAG_STATE \ "[@" XML_NODE_IS_REMOTE "='true']" +/*! + * \internal + * \brief Serialize XML (using libxml) into provided descriptor + * + * \param[in] fd File descriptor to (piece-wise) write to + * \param[in] cur XML subtree to proceed + * + * \return a standard Pacemaker return code + */ +int pcmk__xml2fd(int fd, xmlNode *cur); enum pcmk__xml_artefact_ns { pcmk__xml_artefact_ns_legacy_rng = 1, @@ -235,6 +242,22 @@ char *pcmk__xml_artefact_path(enum pcmk__xml_artefact_ns ns, /*! * \internal + * \brief Check whether an XML element is of a particular type + * + * \param[in] xml XML element to compare + * \param[in] name XML element name to compare + * + * \return \c true if \p xml is of type \p name, otherwise \c false + */ +static inline bool +pcmk__xe_is(const xmlNode *xml, const char *name) +{ + return (xml != NULL) && (xml->name != NULL) && (name != NULL) + && (strcmp((const char *) xml->name, name) == 0); +} + +/*! + * \internal * \brief Return first non-text child node of an XML node * * \param[in] parent XML node to check @@ -411,4 +434,15 @@ pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int (*handler)(xmlNode *xml, void *userdata), void *userdata); +static inline const char * +pcmk__xml_attr_value(const xmlAttr *attr) +{ + return ((attr == NULL) || (attr->children == NULL))? NULL + : (const char *) attr->children->content; +} + +gboolean pcmk__validate_xml(xmlNode *xml_blob, const char *validation, + xmlRelaxNGValidityErrorFunc error_handler, + void *error_handler_context); + #endif // PCMK__XML_INTERNAL__H diff --git a/include/crm/compatibility.h b/include/crm/compatibility.h index 1281a3c..f8502cc 100644 --- a/include/crm/compatibility.h +++ b/include/crm/compatibility.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2021 the Pacemaker project contributors + * Copyright 2004-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -196,41 +196,41 @@ extern "C" { /* Clone terminology definitions */ // These can no longer be used in a switch together -#define pe_master pe_clone +#define pe_master pcmk_rsc_variant_clone static inline enum pe_obj_types get_resource_type(const char *name) { if (safe_str_eq(name, XML_CIB_TAG_RESOURCE)) { - return pe_native; + return pcmk_rsc_variant_primitive; } else if (safe_str_eq(name, XML_CIB_TAG_GROUP)) { - return pe_group; + return pcmk_rsc_variant_group; } else if (safe_str_eq(name, XML_CIB_TAG_INCARNATION) || safe_str_eq(name, PCMK_XE_PROMOTABLE_LEGACY)) { - return pe_clone; + return pcmk_rsc_variant_clone; } else if (safe_str_eq(name, XML_CIB_TAG_CONTAINER)) { - return pe_container; + return pcmk_rsc_variant_bundle; } - return pe_unknown; + return pcmk_rsc_variant_unknown; } static inline const char * get_resource_typename(enum pe_obj_types type) { switch (type) { - case pe_native: + case pcmk_rsc_variant_primitive: return XML_CIB_TAG_RESOURCE; - case pe_group: + case pcmk_rsc_variant_group: return XML_CIB_TAG_GROUP; - case pe_clone: + case pcmk_rsc_variant_clone: return XML_CIB_TAG_INCARNATION; - case pe_container: + case pcmk_rsc_variant_bundle: return XML_CIB_TAG_CONTAINER; - case pe_unknown: + case pcmk_rsc_variant_unknown: return "unknown"; } return "<unknown>"; diff --git a/include/crm/crm.h b/include/crm/crm.h index e824825..aecfcc8 100644 --- a/include/crm/crm.h +++ b/include/crm/crm.h @@ -65,8 +65,9 @@ extern "C" { * XML v2 patchsets are created by default * >=3.0.13: Fail counts include operation name and interval * >=3.2.0: DC supports PCMK_EXEC_INVALID and PCMK_EXEC_NOT_CONNECTED + * >=3.19.0: DC supports PCMK__CIB_REQUEST_COMMIT_TRANSACT */ -# define CRM_FEATURE_SET "3.17.4" +# define CRM_FEATURE_SET "3.19.0" /* Pacemaker's CPG protocols use fixed-width binary fields for the sender and * recipient of a CPG message. This imposes an arbitrary limit on cluster node @@ -79,8 +80,6 @@ extern "C" { extern char *crm_system_name; -/* *INDENT-OFF* */ - // How we represent "infinite" scores # define CRM_SCORE_INFINITY 1000000 # define CRM_INFINITY_S "INFINITY" @@ -110,6 +109,7 @@ extern char *crm_system_name; # define CRM_SYSTEM_MCP "pacemakerd" // Names of internally generated node attributes +// @TODO Replace these with PCMK_NODE_ATTR_* # define CRM_ATTR_UNAME "#uname" # define CRM_ATTR_ID "#id" # define CRM_ATTR_KIND "#kind" @@ -140,22 +140,19 @@ extern char *crm_system_name; # define CRM_OP_QUIT "quit" # define CRM_OP_LOCAL_SHUTDOWN "start_shutdown" # define CRM_OP_SHUTDOWN_REQ "req_shutdown" -# define CRM_OP_SHUTDOWN "do_shutdown" -# define CRM_OP_FENCE "stonith" +# define CRM_OP_SHUTDOWN PCMK_ACTION_DO_SHUTDOWN # define CRM_OP_REGISTER "register" # define CRM_OP_IPC_FWD "ipc_fwd" # define CRM_OP_INVOKE_LRM "lrm_invoke" # define CRM_OP_LRM_REFRESH "lrm_refresh" //!< Deprecated since 1.1.10 -# define CRM_OP_LRM_DELETE "lrm_delete" +# define CRM_OP_LRM_DELETE PCMK_ACTION_LRM_DELETE # define CRM_OP_LRM_FAIL "lrm_fail" # define CRM_OP_PROBED "probe_complete" # define CRM_OP_REPROBE "probe_again" -# define CRM_OP_CLEAR_FAILCOUNT "clear_failcount" +# define CRM_OP_CLEAR_FAILCOUNT PCMK_ACTION_CLEAR_FAILCOUNT # define CRM_OP_REMOTE_STATE "remote_state" -# define CRM_OP_RELAXED_SET "one-or-more" -# define CRM_OP_RELAXED_CLONE "clone-one-or-more" # define CRM_OP_RM_NODE_CACHE "rm_node_cache" -# define CRM_OP_MAINTENANCE_NODES "maintenance_nodes" +# define CRM_OP_MAINTENANCE_NODES PCMK_ACTION_MAINTENANCE_NODES /* Possible cluster membership states */ # define CRMD_JOINSTATE_DOWN "down" @@ -163,70 +160,11 @@ extern char *crm_system_name; # define CRMD_JOINSTATE_MEMBER "member" # define CRMD_JOINSTATE_NACK "banned" -# define CRMD_ACTION_DELETE "delete" -# define CRMD_ACTION_CANCEL "cancel" - -# define CRMD_ACTION_RELOAD "reload" -# define CRMD_ACTION_RELOAD_AGENT "reload-agent" -# define CRMD_ACTION_MIGRATE "migrate_to" -# define CRMD_ACTION_MIGRATED "migrate_from" - -# define CRMD_ACTION_START "start" -# define CRMD_ACTION_STARTED "running" - -# define CRMD_ACTION_STOP "stop" -# define CRMD_ACTION_STOPPED "stopped" - -# define CRMD_ACTION_PROMOTE "promote" -# define CRMD_ACTION_PROMOTED "promoted" -# define CRMD_ACTION_DEMOTE "demote" -# define CRMD_ACTION_DEMOTED "demoted" - -# define CRMD_ACTION_NOTIFY "notify" -# define CRMD_ACTION_NOTIFIED "notified" - -# define CRMD_ACTION_STATUS "monitor" -# define CRMD_ACTION_METADATA "meta-data" -# define CRMD_METADATA_CALL_TIMEOUT 30000 - -/* short names */ -# define RSC_DELETE CRMD_ACTION_DELETE -# define RSC_CANCEL CRMD_ACTION_CANCEL - -# define RSC_MIGRATE CRMD_ACTION_MIGRATE -# define RSC_MIGRATED CRMD_ACTION_MIGRATED - -# define RSC_START CRMD_ACTION_START -# define RSC_STARTED CRMD_ACTION_STARTED - -# define RSC_STOP CRMD_ACTION_STOP -# define RSC_STOPPED CRMD_ACTION_STOPPED - -# define RSC_PROMOTE CRMD_ACTION_PROMOTE -# define RSC_PROMOTED CRMD_ACTION_PROMOTED -# define RSC_DEMOTE CRMD_ACTION_DEMOTE -# define RSC_DEMOTED CRMD_ACTION_DEMOTED - -# define RSC_NOTIFY CRMD_ACTION_NOTIFY -# define RSC_NOTIFIED CRMD_ACTION_NOTIFIED - -# define RSC_STATUS CRMD_ACTION_STATUS -# define RSC_METADATA CRMD_ACTION_METADATA -/* *INDENT-ON* */ - +# include <crm/common/actions.h> # include <crm/common/cib.h> # include <crm/common/logging.h> # include <crm/common/util.h> -static inline const char * -crm_action_str(const char *task, guint interval_ms) { - if ((task != NULL) && (interval_ms == 0) - && (strcasecmp(task, RSC_STATUS) == 0)) { - return "probe"; - } - return task; -} - #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #include <crm/crm_compat.h> #endif diff --git a/include/crm/crm_compat.h b/include/crm/crm_compat.h index 2c0a3dd..bfe1098 100644 --- a/include/crm/crm_compat.h +++ b/include/crm/crm_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2022 the Pacemaker project contributors + * Copyright 2004-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -10,8 +10,11 @@ #ifndef PCMK__CRM_CRM_COMPAT__H # define PCMK__CRM_CRM_COMPAT__H +#include <strings.h> #include <glib.h> +#include <crm/common/actions.h> + #ifdef __cplusplus extern "C" { #endif @@ -31,12 +34,126 @@ extern "C" { //! \deprecated This defined constant will be removed in a future release #define MAX_IPC_DELAY 120 +//! \deprecated Use PCMK_ACTION_STONITH instead +#define CRM_OP_FENCE PCMK_ACTION_STONITH + //! \deprecated This defined constant will be removed in a future release #define CRM_OP_LRM_QUERY "lrm_query" +//! \deprecated Use PCMK_ACTION_CLONE_ONE_OR_MORE instead +#define CRM_OP_RELAXED_CLONE PCMK_ACTION_CLONE_ONE_OR_MORE + +//! \deprecated Use PCMK_ACTION_ONE_OR_MORE instead +#define CRM_OP_RELAXED_SET PCMK_ACTION_ONE_OR_MORE + //! \deprecated This defined constant will be removed in a future release #define CRM_ATTR_RA_VERSION "#ra-version" +//! \deprecated Use PCMK_ACTION_CANCEL instead +#define CRMD_ACTION_CANCEL PCMK_ACTION_CANCEL + +//! \deprecated Use PCMK_ACTION_DELETE instead +#define CRMD_ACTION_DELETE PCMK_ACTION_DELETE + +//! \deprecated Use PCMK_ACTION_DEMOTE instead +#define CRMD_ACTION_DEMOTE PCMK_ACTION_DEMOTE + +//! \deprecated Use PCMK_ACTION_DEMOTED instead +#define CRMD_ACTION_DEMOTED PCMK_ACTION_DEMOTED + +//! \deprecated Use PCMK_ACTION_META_DATA instead +#define CRMD_ACTION_METADATA PCMK_ACTION_META_DATA + +//! \deprecated Use PCMK_ACTION_MIGRATE_TO instead +#define CRMD_ACTION_MIGRATE PCMK_ACTION_MIGRATE_TO + +//! \deprecated Use PCMK_ACTION_MIGRATE_FROM instead +#define CRMD_ACTION_MIGRATED PCMK_ACTION_MIGRATE_FROM + +//! \deprecated Use PCMK_ACTION_NOTIFIED instead +#define CRMD_ACTION_NOTIFIED PCMK_ACTION_NOTIFIED + +//! \deprecated Use PCMK_ACTION_NOTIFY instead +#define CRMD_ACTION_NOTIFY PCMK_ACTION_NOTIFY + +//! \deprecated Use PCMK_ACTION_PROMOTE instead +#define CRMD_ACTION_PROMOTE PCMK_ACTION_PROMOTE + +//! \deprecated Use PCMK_ACTION_PROMOTED instead +#define CRMD_ACTION_PROMOTED PCMK_ACTION_PROMOTED + +//! \deprecated Use PCMK_ACTION_RELOAD instead +#define CRMD_ACTION_RELOAD PCMK_ACTION_RELOAD + +//! \deprecated Use PCMK_ACTION_RELOAD_AGENT instead +#define CRMD_ACTION_RELOAD_AGENT PCMK_ACTION_RELOAD_AGENT + +//! \deprecated Use PCMK_ACTION_START instead +#define CRMD_ACTION_START PCMK_ACTION_START + +//! \deprecated Use PCMK_ACTION_RUNNING instead +#define CRMD_ACTION_STARTED PCMK_ACTION_RUNNING + +//! \deprecated Use PCMK_ACTION_MONITOR instead +#define CRMD_ACTION_STATUS PCMK_ACTION_MONITOR + +//! \deprecated Use PCMK_ACTION_STOP instead +#define CRMD_ACTION_STOP PCMK_ACTION_STOP + +//! \deprecated Use PCMK_ACTION_STOPPED instead +#define CRMD_ACTION_STOPPED PCMK_ACTION_STOPPED + +//! \deprecated Do not use +#define CRMD_METADATA_CALL_TIMEOUT PCMK_DEFAULT_METADATA_TIMEOUT_MS + +//! \deprecated Use PCMK_ACTION_CANCEL instead +#define RSC_CANCEL PCMK_ACTION_CANCEL + +//! \deprecated Use PCMK_ACTION_DELETE instead +#define RSC_DELETE PCMK_ACTION_DELETE + +//! \deprecated Use PCMK_ACTION_DEMOTE instead +#define RSC_DEMOTE PCMK_ACTION_DEMOTE + +//! \deprecated Use PCMK_ACTION_DEMOTED instead +#define RSC_DEMOTED PCMK_ACTION_DEMOTED + +//! \deprecated Use PCMK_ACTION_META_DATA instead +#define RSC_METADATA PCMK_ACTION_META_DATA + +//! \deprecated Use PCMK_ACTION_MIGRATE_TO instead +#define RSC_MIGRATE PCMK_ACTION_MIGRATE_TO + +//! \deprecated Use PCMK_ACTION_MIGRATE_FROM instead +#define RSC_MIGRATED PCMK_ACTION_MIGRATE_FROM + +//! \deprecated Use PCMK_ACTION_NOTIFIED instead +#define RSC_NOTIFIED PCMK_ACTION_NOTIFIED + +//! \deprecated Use PCMK_ACTION_NOTIFY instead +#define RSC_NOTIFY PCMK_ACTION_NOTIFY + +//! \deprecated Use PCMK_ACTION_PROMOTE instead +#define RSC_PROMOTE PCMK_ACTION_PROMOTE + +//! \deprecated Use PCMK_ACTION_PROMOTED instead +#define RSC_PROMOTED PCMK_ACTION_PROMOTED + +//! \deprecated Use PCMK_ACTION_START instead +#define RSC_START PCMK_ACTION_START + +//! \deprecated Use PCMK_ACTION_RUNNING instead +#define RSC_STARTED PCMK_ACTION_RUNNING + +//! \deprecated Use PCMK_ACTION_MONITOR instead +#define RSC_STATUS PCMK_ACTION_MONITOR + +//! \deprecated Use PCMK_ACTION_STOP instead +#define RSC_STOP PCMK_ACTION_STOP + +//! \deprecated Use PCMK_ACTION_STOPPED instead +#define RSC_STOPPED PCMK_ACTION_STOPPED + //!@{ //! \deprecated This macro will be removed in a future release @@ -54,6 +171,16 @@ extern "C" { //! \deprecated Use GList * instead typedef GList *GListPtr; +//! \deprecated Do not use +static inline const char * +crm_action_str(const char *task, guint interval_ms) { + if ((task != NULL) && (interval_ms == 0) + && (strcasecmp(task, PCMK_ACTION_MONITOR) == 0)) { + return "probe"; + } + return task; +} + #ifdef __cplusplus } #endif diff --git a/include/crm/lrmd.h b/include/crm/lrmd.h index dfc2f25..0c5a40b 100644 --- a/include/crm/lrmd.h +++ b/include/crm/lrmd.h @@ -13,6 +13,7 @@ #include <stdbool.h> // bool #include <glib.h> // guint, GList #include <crm_config.h> +#include <crm/lrmd_events.h> #include <crm/services.h> #ifdef __cplusplus @@ -203,74 +204,6 @@ enum lrmd_call_options { lrmd_opt_notify_changes_only = (1 << 2), }; -enum lrmd_callback_event { - lrmd_event_register, - lrmd_event_unregister, - lrmd_event_exec_complete, - lrmd_event_disconnect, - lrmd_event_connect, - lrmd_event_poke, - lrmd_event_new_client, -}; - -typedef struct lrmd_event_data_s { - /*! Type of event, register, unregister, call_completed... */ - enum lrmd_callback_event type; - - /*! The resource this event occurred on. */ - const char *rsc_id; - /*! The action performed, start, stop, monitor... */ - const char *op_type; - /*! The user data passed by caller of exec() API function */ - const char *user_data; - - /*! The client api call id associated with this event */ - int call_id; - /*! The operation's timeout period in ms. */ - int timeout; - /*! The operation's recurring interval in ms. */ - guint interval_ms; - /*! The operation's start delay value in ms. */ - int start_delay; - /*! This operation that just completed is on a deleted rsc. */ - int rsc_deleted; - - /*! The executed ra return code mapped to OCF */ - enum ocf_exitcode rc; - /*! The executor status returned for exec_complete events */ - int op_status; - /*! stdout from resource agent operation */ - const char *output; - /*! Timestamp of when op ran */ - unsigned int t_run; - /*! Timestamp of last rc change */ - unsigned int t_rcchange; - /*! Time in length op took to execute */ - unsigned int exec_time; - /*! Time in length spent in queue */ - unsigned int queue_time; - - /*! int connection result. Used for connection and poke events */ - int connection_rc; - - /* This is a GHashTable containing the - * parameters given to the operation */ - void *params; - - /*! client node name associated with this connection - * (used to match actions to the proper client when there are multiple) - */ - const char *remote_nodename; - - /*! exit failure reason string from resource agent operation */ - const char *exit_reason; -} lrmd_event_data_t; - -lrmd_event_data_t *lrmd_new_event(const char *rsc_id, const char *task, - guint interval_ms); -lrmd_event_data_t *lrmd_copy_event(lrmd_event_data_t * event); -void lrmd_free_event(lrmd_event_data_t * event); - typedef struct lrmd_rsc_info_s { char *id; char *type; diff --git a/include/crm/lrmd_events.h b/include/crm/lrmd_events.h new file mode 100644 index 0000000..3a1c500 --- /dev/null +++ b/include/crm/lrmd_events.h @@ -0,0 +1,108 @@ +/* + * Copyright 2012-2023 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 PCMK__CRM_LRMD_EVENTS__H +# define PCMK__CRM_LRMD_EVENTS__H + +#include <glib.h> // guint +#include <crm/common/results.h> // enum ocf_exitcode + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file + * \brief Resource agent executor events + * \ingroup lrmd + */ + +enum lrmd_callback_event { + lrmd_event_register, + lrmd_event_unregister, + lrmd_event_exec_complete, + lrmd_event_disconnect, + lrmd_event_connect, + lrmd_event_poke, + lrmd_event_new_client, +}; + +typedef struct lrmd_event_data_s { + /*! Type of event, register, unregister, call_completed... */ + enum lrmd_callback_event type; + + /*! The resource this event occurred on. */ + const char *rsc_id; + /*! The action performed, start, stop, monitor... */ + const char *op_type; + /*! The user data passed by caller of exec() API function */ + const char *user_data; + + /*! The client api call id associated with this event */ + int call_id; + + /*! The operation's timeout period in ms. */ + int timeout; + + /*! The operation's recurring interval in ms. */ + guint interval_ms; + + /*! The operation's start delay value in ms. */ + int start_delay; + + /*! This operation that just completed is on a deleted rsc. */ + int rsc_deleted; + + /*! The executed ra return code mapped to OCF */ + enum ocf_exitcode rc; + + /*! The executor status returned for exec_complete events */ + int op_status; + + /*! stdout from resource agent operation */ + const char *output; + + /*! Timestamp of when op ran */ + unsigned int t_run; + + /*! Timestamp of last rc change */ + unsigned int t_rcchange; + + /*! Time in length op took to execute */ + unsigned int exec_time; + + /*! Time in length spent in queue */ + unsigned int queue_time; + + /*! int connection result. Used for connection and poke events */ + int connection_rc; + + /* This is a GHashTable containing the + * parameters given to the operation */ + void *params; + + /*! client node name associated with this connection + * (used to match actions to the proper client when there are multiple) + */ + const char *remote_nodename; + + /*! exit failure reason string from resource agent operation */ + const char *exit_reason; +} lrmd_event_data_t; + +lrmd_event_data_t *lrmd_new_event(const char *rsc_id, const char *task, + guint interval_ms); +lrmd_event_data_t *lrmd_copy_event(lrmd_event_data_t *event); +void lrmd_free_event(lrmd_event_data_t *event); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_LRMD_EVENTS__H diff --git a/include/crm/lrmd_internal.h b/include/crm/lrmd_internal.h index 5810554..d1cd25d 100644 --- a/include/crm/lrmd_internal.h +++ b/include/crm/lrmd_internal.h @@ -47,6 +47,7 @@ void lrmd__set_result(lrmd_event_data_t *event, enum ocf_exitcode rc, void lrmd__reset_result(lrmd_event_data_t *event); time_t lrmd__uptime(lrmd_t *lrmd); +const char *lrmd__node_start_state(lrmd_t *lrmd); /* Shared functions for IPC proxy back end */ diff --git a/include/crm/msg_xml.h b/include/crm/msg_xml.h index 2e50adb..c616182 100644 --- a/include/crm/msg_xml.h +++ b/include/crm/msg_xml.h @@ -48,6 +48,8 @@ extern "C" { * XML attributes */ +#define PCMK_XA_FORMAT "format" + /* These have been deprecated as CIB <clone> element attributes (aliases for * "promoted-max" and "promoted-node-max") since 2.0.0. */ @@ -59,7 +61,14 @@ extern "C" { * Meta attributes */ +#define PCMK_META_CLONE_MAX "clone-max" +#define PCMK_META_CLONE_MIN "clone-min" +#define PCMK_META_CLONE_NODE_MAX "clone-node-max" #define PCMK_META_ENABLED "enabled" +#define PCMK_META_FAILURE_TIMEOUT "failure-timeout" +#define PCMK_META_MIGRATION_THRESHOLD "migration-threshold" +#define PCMK_META_PROMOTED_MAX "promoted-max" +#define PCMK_META_PROMOTED_NODE_MAX "promoted-node-max" /* @@ -149,7 +158,6 @@ extern "C" { # define XML_ATTR_IDREF "id-ref" # define XML_ATTR_ID_LONG "long-id" # define XML_ATTR_TYPE "type" -# define XML_ATTR_VERBOSE "verbose" # define XML_ATTR_OP "op" # define XML_ATTR_DC_UUID "dc-uuid" # define XML_ATTR_UPDATE_ORIG "update-origin" @@ -183,8 +191,6 @@ extern "C" { # define XML_PING_ATTR_PACEMAKERDSTATE_SHUTDOWNCOMPLETE "shutdown_complete" # define XML_PING_ATTR_PACEMAKERDSTATE_REMOTE "remote" -# define XML_TAG_FRAGMENT "cib_fragment" - # define XML_FAIL_TAG_CIB "failed_update" # define XML_FAILCIB_ATTR_ID "id" @@ -198,7 +204,6 @@ extern "C" { # define XML_CIB_TAG_STATUS "status" # define XML_CIB_TAG_RESOURCES "resources" # define XML_CIB_TAG_NODES "nodes" -# define XML_CIB_TAG_DOMAINS "domains" # define XML_CIB_TAG_CONSTRAINTS "constraints" # define XML_CIB_TAG_CRMCONFIG "crm_config" # define XML_CIB_TAG_OPCONFIG "op_defaults" @@ -239,19 +244,12 @@ extern "C" { # define XML_RSC_ATTR_ORDERED "ordered" # define XML_RSC_ATTR_INTERLEAVE "interleave" # define XML_RSC_ATTR_INCARNATION "clone" -# define XML_RSC_ATTR_INCARNATION_MAX "clone-max" -# define XML_RSC_ATTR_INCARNATION_MIN "clone-min" -# define XML_RSC_ATTR_INCARNATION_NODEMAX "clone-node-max" # define XML_RSC_ATTR_PROMOTABLE "promotable" -# define XML_RSC_ATTR_PROMOTED_MAX "promoted-max" -# define XML_RSC_ATTR_PROMOTED_NODEMAX "promoted-node-max" # define XML_RSC_ATTR_MANAGED "is-managed" # define XML_RSC_ATTR_TARGET_ROLE "target-role" # define XML_RSC_ATTR_UNIQUE "globally-unique" # define XML_RSC_ATTR_NOTIFY "notify" # define XML_RSC_ATTR_STICKINESS "resource-stickiness" -# define XML_RSC_ATTR_FAIL_STICKINESS "migration-threshold" -# define XML_RSC_ATTR_FAIL_TIMEOUT "failure-timeout" # define XML_RSC_ATTR_MULTIPLE "multiple-active" # define XML_RSC_ATTR_REQUIRES "requires" # define XML_RSC_ATTR_CONTAINER "container" @@ -285,15 +283,8 @@ extern "C" { //! \deprecated Do not use (will be removed in a future release) # define XML_CIB_ATTR_REPLACE "replace" -# define XML_CIB_ATTR_SOURCE "source" - # define XML_CIB_ATTR_PRIORITY "priority" -# define XML_CIB_ATTR_SOURCE "source" -# define XML_NODE_JOIN_STATE "join" -# define XML_NODE_EXPECTED "expected" -# define XML_NODE_IN_CLUSTER "in_ccm" -# define XML_NODE_IS_PEER "crmd" # define XML_NODE_IS_REMOTE "remote_node" # define XML_NODE_IS_FENCED "node_fenced" # define XML_NODE_IS_MAINTENANCE "node_in_maintenance" @@ -333,7 +324,6 @@ extern "C" { # define XML_LRM_ATTR_EXIT_REASON "exit-reason" # define XML_RSC_OP_LAST_CHANGE "last-rc-change" -# define XML_RSC_OP_LAST_RUN "last-run" // deprecated since 2.0.3 # define XML_RSC_OP_T_EXEC "exec-time" # define XML_RSC_OP_T_QUEUE "queue-time" @@ -413,6 +403,7 @@ extern "C" { # define XML_CONFIG_ATTR_SHUTDOWN_LOCK "shutdown-lock" # define XML_CONFIG_ATTR_SHUTDOWN_LOCK_LIMIT "shutdown-lock-limit" # define XML_CONFIG_ATTR_PRIORITY_FENCING_DELAY "priority-fencing-delay" +# define XML_CONFIG_ATTR_NODE_PENDING_TIMEOUT "node-pending-timeout" # define XML_ALERT_ATTR_PATH "path" # define XML_ALERT_ATTR_TIMEOUT "timeout" @@ -428,7 +419,10 @@ extern "C" { # define XML_ATTR_TE_TARGET_RC "op_target_rc" # define XML_TAG_TRANSIENT_NODEATTRS "transient_attributes" +//! \deprecated Do not use (will be removed in a future release) # define XML_TAG_DIFF_ADDED "diff-added" + +//! \deprecated Do not use (will be removed in a future release) # define XML_TAG_DIFF_REMOVED "diff-removed" # define XML_ACL_TAG_USER "acl_target" @@ -478,7 +472,6 @@ extern "C" { # define XML_DIFF_POSITION "position" # define ID(x) crm_element_value(x, XML_ATTR_ID) -# define TYPE(x) crm_element_name(x) #ifdef __cplusplus } diff --git a/include/crm/msg_xml_compat.h b/include/crm/msg_xml_compat.h index aad98e8..612eebf 100644 --- a/include/crm/msg_xml_compat.h +++ b/include/crm/msg_xml_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2022 the Pacemaker project contributors + * Copyright 2004-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -25,6 +25,21 @@ extern "C" { * release. */ +//! \deprecated Use PCMK_META_CLONE_MAX instead +#define XML_RSC_ATTR_INCARNATION_MAX PCMK_META_CLONE_MAX + +//! \deprecated Use PCMK_META_CLONE_MIN instead +#define XML_RSC_ATTR_INCARNATION_MIN PCMK_META_CLONE_MIN + +//! \deprecated Use PCMK_META_CLONE_NODE_MAX instead +#define XML_RSC_ATTR_INCARNATION_NODEMAX PCMK_META_CLONE_NODE_MAX + +//! \deprecated Use PCMK_META_PROMOTED_MAX instead +#define XML_RSC_ATTR_PROMOTED_MAX PCMK_META_PROMOTED_MAX + +//! \deprecated Use PCMK_META_PROMOTED_NODE_MAX instead +#define XML_RSC_ATTR_PROMOTED_NODEMAX PCMK_META_PROMOTED_NODE_MAX + //! \deprecated Use PCMK_STONITH_PROVIDES instead #define XML_RSC_ATTR_PROVIDES PCMK_STONITH_PROVIDES @@ -40,6 +55,12 @@ extern "C" { //! \deprecated Use PCMK_XA_PROMOTED_NODE_MAX_LEGACY instead #define PCMK_XE_PROMOTED_NODE_MAX_LEGACY PCMK_XA_PROMOTED_NODE_MAX_LEGACY +//! \deprecated Use PCMK_META_MIGRATION_THRESHOLD instead +#define XML_RSC_ATTR_FAIL_STICKINESS PCMK_META_MIGRATION_THRESHOLD + +//! \deprecated Use PCMK_META_FAILURE_TIMEOUT instead +#define XML_RSC_ATTR_FAIL_TIMEOUT PCMK_META_FAILURE_TIMEOUT + //! \deprecated Use PCMK_XA_PROMOTED_NODE_MAX_LEGACY instead #define XML_RSC_ATTR_MASTER_NODEMAX PCMK_XA_PROMOTED_NODE_MAX_LEGACY @@ -47,6 +68,9 @@ extern "C" { #define XML_ATTR_RA_VERSION "ra-version" //! \deprecated Do not use (will be removed in a future release) +#define XML_TAG_FRAGMENT "cib_fragment" + +//! \deprecated Do not use (will be removed in a future release) #define XML_TAG_RSC_VER_ATTRS "rsc_versioned_attrs" //! \deprecated Do not use (will be removed in a future release) @@ -58,6 +82,33 @@ extern "C" { //! \deprecated Use \p XML_ATTR_ID instead #define XML_ATTR_UUID "id" +//! \deprecated Do not use (will be removed in a future release) +#define XML_ATTR_VERBOSE "verbose" + +//! \deprecated Do not use (will be removed in a future release) +#define XML_CIB_TAG_DOMAINS "domains" + +//! \deprecated Do not use (will be removed in a future release) +#define XML_CIB_ATTR_SOURCE "source" + +//! \deprecated Do not use +#define XML_NODE_EXPECTED "expected" + +//! \deprecated Do not use +#define XML_NODE_IN_CLUSTER "in_ccm" + +//! \deprecated Do not use +#define XML_NODE_IS_PEER "crmd" + +//! \deprecated Do not use +#define XML_NODE_JOIN_STATE "join" + +//! \deprecated Do not use (will be removed in a future release) +#define XML_RSC_OP_LAST_RUN "last-run" + +//! \deprecated Use name member directly +#define TYPE(x) (((x) == NULL)? NULL : (const char *) ((x)->name)) + #ifdef __cplusplus } #endif diff --git a/include/crm/pengine/Makefile.am b/include/crm/pengine/Makefile.am index fac6031..3560d24 100644 --- a/include/crm/pengine/Makefile.am +++ b/include/crm/pengine/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2006-2021 the Pacemaker project contributors +# Copyright 2006-2023 the Pacemaker project contributors # # The version control history for this file may have further details. # @@ -10,8 +10,13 @@ MAINTAINERCLEANFILES = Makefile.in headerdir=$(pkgincludedir)/crm/pengine -noinst_HEADERS = internal.h remote_internal.h rules_internal.h -header_HEADERS = common.h complex.h pe_types.h rules.h status.h \ +noinst_HEADERS = internal.h \ + $(wildcard *_internal.h) +header_HEADERS = common.h \ + complex.h \ + pe_types.h \ + rules.h \ + status.h \ common_compat.h \ pe_types_compat.h \ rules_compat.h diff --git a/include/crm/pengine/common.h b/include/crm/pengine/common.h index 9fe05bd..2feac8a 100644 --- a/include/crm/pengine/common.h +++ b/include/crm/pengine/common.h @@ -13,6 +13,7 @@ # include <glib.h> # include <regex.h> # include <crm/common/iso8601.h> +# include <crm/common/scheduler.h> #ifdef __cplusplus extern "C" { @@ -21,120 +22,6 @@ extern "C" { extern gboolean was_processing_error; extern gboolean was_processing_warning; -/* The order is (partially) significant here; the values from action_fail_ignore - * through action_fail_fence are in order of increasing severity. - * - * @COMPAT The values should be ordered and numbered per the "TODO" comments - * below, so all values are in order of severity and there is room for - * future additions, but that would break API compatibility. - * @TODO For now, we just use a function to compare the values specially, but - * at the next compatibility break, we should arrange things properly. - */ -enum action_fail_response { - action_fail_ignore, // @TODO = 10 - // @TODO action_fail_demote = 20, - action_fail_recover, // @TODO = 30 - // @TODO action_fail_reset_remote = 40, - // @TODO action_fail_restart_container = 50, - action_fail_migrate, // @TODO = 60 - action_fail_block, // @TODO = 70 - action_fail_stop, // @TODO = 80 - action_fail_standby, // @TODO = 90 - action_fail_fence, // @TODO = 100 - - // @COMPAT Values below here are out of order for API compatibility - - action_fail_restart_container, - - /* This is reserved for internal use for remote node connection resources. - * Fence the remote node if stonith is enabled, otherwise attempt to recover - * the connection resource. This allows us to specify types of connection - * resource failures that should result in fencing the remote node - * (for example, recurring monitor failures). - */ - action_fail_reset_remote, - - action_fail_demote, -}; - -/* the "done" action must be the "pre" action +1 */ -enum action_tasks { - no_action, - monitor_rsc, - stop_rsc, - stopped_rsc, - start_rsc, - started_rsc, - action_notify, - action_notified, - action_promote, - action_promoted, - action_demote, - action_demoted, - shutdown_crm, - stonith_node -}; - -enum rsc_recovery_type { - recovery_stop_start, - recovery_stop_only, - recovery_block, - recovery_stop_unexpected, -}; - -enum rsc_start_requirement { - rsc_req_nothing, /* Allowed by custom_action() */ - rsc_req_quorum, /* Enforced by custom_action() */ - rsc_req_stonith /* Enforced by native_start_constraints() */ -}; - -//! Possible roles that a resource can be in -enum rsc_role_e { - RSC_ROLE_UNKNOWN = 0, - RSC_ROLE_STOPPED = 1, - RSC_ROLE_STARTED = 2, - RSC_ROLE_UNPROMOTED = 3, - RSC_ROLE_PROMOTED = 4, - -#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) - //! \deprecated Use RSC_ROLE_UNPROMOTED instead - RSC_ROLE_SLAVE = RSC_ROLE_UNPROMOTED, - - //! \deprecated Use RSC_ROLE_PROMOTED instead - RSC_ROLE_MASTER = RSC_ROLE_PROMOTED, -#endif -}; - -# define RSC_ROLE_MAX (RSC_ROLE_PROMOTED + 1) - -# define RSC_ROLE_UNKNOWN_S "Unknown" -# define RSC_ROLE_STOPPED_S "Stopped" -# define RSC_ROLE_STARTED_S "Started" -# define RSC_ROLE_UNPROMOTED_S "Unpromoted" -# define RSC_ROLE_PROMOTED_S "Promoted" -# define RSC_ROLE_UNPROMOTED_LEGACY_S "Slave" -# define RSC_ROLE_PROMOTED_LEGACY_S "Master" - -//! Deprecated -enum pe_print_options { - pe_print_log = (1 << 0), - pe_print_html = (1 << 1), - pe_print_ncurses = (1 << 2), - pe_print_printf = (1 << 3), - pe_print_dev = (1 << 4), //! Ignored - pe_print_details = (1 << 5), //! Ignored - pe_print_max_details = (1 << 6), //! Ignored - pe_print_rsconly = (1 << 7), - pe_print_ops = (1 << 8), - pe_print_suppres_nl = (1 << 9), - pe_print_xml = (1 << 10), - pe_print_brief = (1 << 11), - pe_print_pending = (1 << 12), - pe_print_clone_details = (1 << 13), - pe_print_clone_active = (1 << 14), // Print clone instances only if active - pe_print_implicit = (1 << 15) // Print implicitly created resources -}; - const char *task2text(enum action_tasks task); enum action_tasks text2task(const char *task); enum rsc_role_e text2role(const char *role); @@ -154,13 +41,13 @@ static inline const char * recovery2text(enum rsc_recovery_type type) { switch (type) { - case recovery_stop_only: + case pcmk_multiply_active_stop: return "shutting it down"; - case recovery_stop_start: + case pcmk_multiply_active_restart: return "attempting recovery"; - case recovery_block: + case pcmk_multiply_active_block: return "waiting for an administrator"; - case recovery_stop_unexpected: + case pcmk_multiply_active_unexpected: return "stopping unexpected instances"; } return "Unknown"; diff --git a/include/crm/pengine/common_compat.h b/include/crm/pengine/common_compat.h index 773bb3d..4330ccf 100644 --- a/include/crm/pengine/common_compat.h +++ b/include/crm/pengine/common_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2021 the Pacemaker project contributors + * Copyright 2004-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -10,6 +10,8 @@ #ifndef PCMK__CRM_PENGINE_COMMON_COMPAT__H # define PCMK__CRM_PENGINE_COMMON_COMPAT__H +#include <crm/common/scheduler.h> + #ifdef __cplusplus extern "C" { #endif @@ -23,12 +25,35 @@ extern "C" { * release. */ -//! \deprecated Use RSC_ROLE_UNPROMOTED_LEGACY_S instead -# define RSC_ROLE_SLAVE_S RSC_ROLE_UNPROMOTED_LEGACY_S +//! \deprecated Use (pcmk_role_promoted + 1) instead +#define RSC_ROLE_MAX (pcmk_role_promoted + 1) + +//! \deprecated Use role2text(pcmk_role_unknown) instead +#define RSC_ROLE_UNKNOWN_S role2text(pcmk_role_unknown) + +//! \deprecated Use role2text(pcmk_role_stopped) instead +#define RSC_ROLE_STOPPED_S role2text(pcmk_role_stopped) + +//! \deprecated Use role2text(pcmk_role_started) instead +#define RSC_ROLE_STARTED_S role2text(pcmk_role_started) + +//! \deprecated Use role2text(pcmk_role_unpromoted) instead +#define RSC_ROLE_UNPROMOTED_S role2text(pcmk_role_unpromoted) + +//! \deprecated Use role2text(pcmk_role_promoted) instead +#define RSC_ROLE_PROMOTED_S role2text(pcmk_role_promoted) + +//! \deprecated Do not use +#define RSC_ROLE_UNPROMOTED_LEGACY_S "Slave" + +//! \deprecated Do not use +#define RSC_ROLE_SLAVE_S RSC_ROLE_UNPROMOTED_LEGACY_S -//! \deprecated Use RSC_ROLE_PROMOTED_LEGACY_S instead -# define RSC_ROLE_MASTER_S RSC_ROLE_PROMOTED_LEGACY_S +//! \deprecated Do not use +#define RSC_ROLE_PROMOTED_LEGACY_S "Master" +//! \deprecated Do not use +#define RSC_ROLE_MASTER_S RSC_ROLE_PROMOTED_LEGACY_S #ifdef __cplusplus } diff --git a/include/crm/pengine/complex.h b/include/crm/pengine/complex.h index 929e4da..9b6ad1b 100644 --- a/include/crm/pengine/complex.h +++ b/include/crm/pengine/complex.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2022 the Pacemaker project contributors + * Copyright 2004-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -12,23 +12,23 @@ #include <glib.h> // gboolean, GHashTable #include <libxml/tree.h> // xmlNode -#include <crm/pengine/pe_types.h> // pe_node_t, pe_resource_t, etc. +#include <crm/pengine/pe_types.h> // pcmk_node_t, pcmk_resource_t, etc. #ifdef __cplusplus extern "C" { #endif -extern resource_object_functions_t resource_class_functions[]; +extern pcmk_rsc_methods_t resource_class_functions[]; -GHashTable *pe_rsc_params(pe_resource_t *rsc, const pe_node_t *node, - pe_working_set_t *data_set); -void get_meta_attributes(GHashTable * meta_hash, pe_resource_t *rsc, - pe_node_t *node, pe_working_set_t *data_set); -void get_rsc_attributes(GHashTable *meta_hash, const pe_resource_t *rsc, - const pe_node_t *node, pe_working_set_t *data_set); +GHashTable *pe_rsc_params(pcmk_resource_t *rsc, const pcmk_node_t *node, + pcmk_scheduler_t *scheduler); +void get_meta_attributes(GHashTable * meta_hash, pcmk_resource_t *rsc, + pcmk_node_t *node, pcmk_scheduler_t *scheduler); +void get_rsc_attributes(GHashTable *meta_hash, const pcmk_resource_t *rsc, + const pcmk_node_t *node, pcmk_scheduler_t *scheduler); -gboolean is_parent(pe_resource_t *child, pe_resource_t *rsc); -pe_resource_t *uber_parent(pe_resource_t *rsc); +gboolean is_parent(pcmk_resource_t *child, pcmk_resource_t *rsc); +pcmk_resource_t *uber_parent(pcmk_resource_t *rsc); #ifdef __cplusplus } diff --git a/include/crm/pengine/internal.h b/include/crm/pengine/internal.h index 1b5f6f1..9c8068f 100644 --- a/include/crm/pengine/internal.h +++ b/include/crm/pengine/internal.h @@ -10,6 +10,7 @@ #ifndef PE_INTERNAL__H # define PE_INTERNAL__H +# include <stdbool.h> # include <stdint.h> # include <string.h> # include <crm/msg_xml.h> @@ -18,31 +19,17 @@ # include <crm/common/internal.h> # include <crm/common/options_internal.h> # include <crm/common/output_internal.h> +# include <crm/common/scheduler_internal.h> -const char *pe__resource_description(const pe_resource_t *rsc, uint32_t show_opts); +const char *pe__resource_description(const pcmk_resource_t *rsc, + uint32_t show_opts); -enum pe__clone_flags { - // Whether instances should be started sequentially - pe__clone_ordered = (1 << 0), +bool pe__clone_is_ordered(const pcmk_resource_t *clone); +int pe__set_clone_flag(pcmk_resource_t *clone, enum pcmk__clone_flags flag); +bool pe__clone_flag_is_set(const pcmk_resource_t *clone, uint32_t flags); - // Whether promotion scores have been added - pe__clone_promotion_added = (1 << 1), - - // Whether promotion constraints have been added - pe__clone_promotion_constrained = (1 << 2), -}; - -bool pe__clone_is_ordered(const pe_resource_t *clone); -int pe__set_clone_flag(pe_resource_t *clone, enum pe__clone_flags flag); - - -enum pe__group_flags { - pe__group_ordered = (1 << 0), // Members start sequentially - pe__group_colocated = (1 << 1), // Members must be on same node -}; - -bool pe__group_flag_is_set(const pe_resource_t *group, uint32_t flags); -pe_resource_t *pe__last_group_member(const pe_resource_t *group); +bool pe__group_flag_is_set(const pcmk_resource_t *group, uint32_t flags); +pcmk_resource_t *pe__last_group_member(const pcmk_resource_t *group); # define pe_rsc_info(rsc, fmt, args...) crm_log_tag(LOG_INFO, rsc ? rsc->id : "<NULL>", fmt, ##args) @@ -62,16 +49,16 @@ pe_resource_t *pe__last_group_member(const pe_resource_t *group); # define pe_proc_err(fmt...) { was_processing_error = TRUE; crm_err(fmt); } # define pe_proc_warn(fmt...) { was_processing_warning = TRUE; crm_warn(fmt); } -#define pe__set_working_set_flags(working_set, flags_to_set) do { \ - (working_set)->flags = pcmk__set_flags_as(__func__, __LINE__, \ - LOG_TRACE, "Working set", crm_system_name, \ - (working_set)->flags, (flags_to_set), #flags_to_set); \ +#define pe__set_working_set_flags(scheduler, flags_to_set) do { \ + (scheduler)->flags = pcmk__set_flags_as(__func__, __LINE__, \ + LOG_TRACE, "Scheduler", crm_system_name, \ + (scheduler)->flags, (flags_to_set), #flags_to_set); \ } while (0) -#define pe__clear_working_set_flags(working_set, flags_to_clear) do { \ - (working_set)->flags = pcmk__clear_flags_as(__func__, __LINE__, \ - LOG_TRACE, "Working set", crm_system_name, \ - (working_set)->flags, (flags_to_clear), #flags_to_clear); \ +#define pe__clear_working_set_flags(scheduler, flags_to_clear) do { \ + (scheduler)->flags = pcmk__clear_flags_as(__func__, __LINE__, \ + LOG_TRACE, "Scheduler", crm_system_name, \ + (scheduler)->flags, (flags_to_clear), #flags_to_clear); \ } while (0) #define pe__set_resource_flags(resource, flags_to_set) do { \ @@ -152,144 +139,127 @@ pe_resource_t *pe__last_group_member(const pe_resource_t *group); #flags_to_clear); \ } while (0) -// Some warnings we don't want to print every transition - -enum pe_warn_once_e { - pe_wo_blind = (1 << 0), - pe_wo_restart_type = (1 << 1), - pe_wo_role_after = (1 << 2), - pe_wo_poweroff = (1 << 3), - pe_wo_require_all = (1 << 4), - pe_wo_order_score = (1 << 5), - pe_wo_neg_threshold = (1 << 6), - pe_wo_remove_after = (1 << 7), - pe_wo_ping_node = (1 << 8), - pe_wo_order_inst = (1 << 9), - pe_wo_coloc_inst = (1 << 10), - pe_wo_group_order = (1 << 11), - pe_wo_group_coloc = (1 << 12), - pe_wo_upstart = (1 << 13), - pe_wo_nagios = (1 << 14), -}; - -extern uint32_t pe_wo; - #define pe_warn_once(pe_wo_bit, fmt...) do { \ - if (!pcmk_is_set(pe_wo, pe_wo_bit)) { \ - if (pe_wo_bit == pe_wo_blind) { \ + if (!pcmk_is_set(pcmk__warnings, pe_wo_bit)) { \ + if (pe_wo_bit == pcmk__wo_blind) { \ crm_warn(fmt); \ } else { \ pe_warn(fmt); \ } \ - pe_wo = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ - "Warn-once", "logging", pe_wo, \ - (pe_wo_bit), #pe_wo_bit); \ - } \ + pcmk__warnings = pcmk__set_flags_as(__func__, __LINE__, \ + LOG_TRACE, \ + "Warn-once", "logging", \ + pcmk__warnings, \ + (pe_wo_bit), #pe_wo_bit); \ + } \ } while (0); typedef struct pe__location_constraint_s { char *id; // Constraint XML ID - pe_resource_t *rsc_lh; // Resource being located + pcmk_resource_t *rsc_lh; // Resource being located enum rsc_role_e role_filter; // Role to locate enum pe_discover_e discover_mode; // Resource discovery - GList *node_list_rh; // List of pe_node_t* + GList *node_list_rh; // List of pcmk_node_t* } pe__location_t; typedef struct pe__order_constraint_s { int id; - uint32_t flags; // Group of enum pe_ordering flags + uint32_t flags; // Group of enum pcmk__action_relation_flags void *lh_opaque; - pe_resource_t *lh_rsc; - pe_action_t *lh_action; + pcmk_resource_t *lh_rsc; + pcmk_action_t *lh_action; char *lh_action_task; void *rh_opaque; - pe_resource_t *rh_rsc; - pe_action_t *rh_action; + pcmk_resource_t *rh_rsc; + pcmk_action_t *rh_action; char *rh_action_task; } pe__ordering_t; -const pe_resource_t *pe__const_top_resource(const pe_resource_t *rsc, - bool include_bundle); +const pcmk_resource_t *pe__const_top_resource(const pcmk_resource_t *rsc, + bool include_bundle); -int pe__clone_max(const pe_resource_t *clone); -int pe__clone_node_max(const pe_resource_t *clone); -int pe__clone_promoted_max(const pe_resource_t *clone); -int pe__clone_promoted_node_max(const pe_resource_t *clone); -void pe__create_clone_notifications(pe_resource_t *clone); -void pe__free_clone_notification_data(pe_resource_t *clone); -void pe__create_clone_notif_pseudo_ops(pe_resource_t *clone, - pe_action_t *start, pe_action_t *started, - pe_action_t *stop, pe_action_t *stopped); +int pe__clone_max(const pcmk_resource_t *clone); +int pe__clone_node_max(const pcmk_resource_t *clone); +int pe__clone_promoted_max(const pcmk_resource_t *clone); +int pe__clone_promoted_node_max(const pcmk_resource_t *clone); +void pe__create_clone_notifications(pcmk_resource_t *clone); +void pe__free_clone_notification_data(pcmk_resource_t *clone); +void pe__create_clone_notif_pseudo_ops(pcmk_resource_t *clone, + pcmk_action_t *start, + pcmk_action_t *started, + pcmk_action_t *stop, + pcmk_action_t *stopped); +pcmk_action_t *pe__new_rsc_pseudo_action(pcmk_resource_t *rsc, const char *task, + bool optional, bool runnable); -pe_action_t *pe__new_rsc_pseudo_action(pe_resource_t *rsc, const char *task, - bool optional, bool runnable); +void pe__create_promotable_pseudo_ops(pcmk_resource_t *clone, + bool any_promoting, bool any_demoting); -void pe__create_promotable_pseudo_ops(pe_resource_t *clone, bool any_promoting, - bool any_demoting); - -bool pe_can_fence(const pe_working_set_t *data_set, const pe_node_t *node); +bool pe_can_fence(const pcmk_scheduler_t *scheduler, const pcmk_node_t *node); void add_hash_param(GHashTable * hash, const char *name, const char *value); -char *native_parameter(pe_resource_t * rsc, pe_node_t * node, gboolean create, const char *name, - pe_working_set_t * data_set); -pe_node_t *native_location(const pe_resource_t *rsc, GList **list, int current); +char *native_parameter(pcmk_resource_t *rsc, pcmk_node_t *node, gboolean create, + const char *name, pcmk_scheduler_t *scheduler); +pcmk_node_t *native_location(const pcmk_resource_t *rsc, GList **list, + int current); void pe_metadata(pcmk__output_t *out); void verify_pe_options(GHashTable * options); -void native_add_running(pe_resource_t * rsc, pe_node_t * node, pe_working_set_t * data_set, gboolean failed); +void native_add_running(pcmk_resource_t *rsc, pcmk_node_t *node, + pcmk_scheduler_t *scheduler, gboolean failed); -gboolean native_unpack(pe_resource_t * rsc, pe_working_set_t * data_set); -gboolean group_unpack(pe_resource_t * rsc, pe_working_set_t * data_set); -gboolean clone_unpack(pe_resource_t * rsc, pe_working_set_t * data_set); -gboolean pe__unpack_bundle(pe_resource_t *rsc, pe_working_set_t *data_set); +gboolean native_unpack(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler); +gboolean group_unpack(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler); +gboolean clone_unpack(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler); +gboolean pe__unpack_bundle(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler); -pe_resource_t *native_find_rsc(pe_resource_t *rsc, const char *id, const pe_node_t *node, - int flags); +pcmk_resource_t *native_find_rsc(pcmk_resource_t *rsc, const char *id, + const pcmk_node_t *node, int flags); -gboolean native_active(pe_resource_t * rsc, gboolean all); -gboolean group_active(pe_resource_t * rsc, gboolean all); -gboolean clone_active(pe_resource_t * rsc, gboolean all); -gboolean pe__bundle_active(pe_resource_t *rsc, gboolean all); +gboolean native_active(pcmk_resource_t *rsc, gboolean all); +gboolean group_active(pcmk_resource_t *rsc, gboolean all); +gboolean clone_active(pcmk_resource_t *rsc, gboolean all); +gboolean pe__bundle_active(pcmk_resource_t *rsc, gboolean all); //! \deprecated This function will be removed in a future release -void native_print(pe_resource_t *rsc, const char *pre_text, long options, +void native_print(pcmk_resource_t *rsc, const char *pre_text, long options, void *print_data); //! \deprecated This function will be removed in a future release -void group_print(pe_resource_t *rsc, const char *pre_text, long options, +void group_print(pcmk_resource_t *rsc, const char *pre_text, long options, void *print_data); //! \deprecated This function will be removed in a future release -void clone_print(pe_resource_t *rsc, const char *pre_text, long options, +void clone_print(pcmk_resource_t *rsc, const char *pre_text, long options, void *print_data); //! \deprecated This function will be removed in a future release -void pe__print_bundle(pe_resource_t *rsc, const char *pre_text, long options, +void pe__print_bundle(pcmk_resource_t *rsc, const char *pre_text, long options, void *print_data); -gchar *pcmk__native_output_string(const pe_resource_t *rsc, const char *name, - const pe_node_t *node, uint32_t show_opts, +gchar *pcmk__native_output_string(const pcmk_resource_t *rsc, const char *name, + const pcmk_node_t *node, uint32_t show_opts, const char *target_role, bool show_nodes); int pe__name_and_nvpairs_xml(pcmk__output_t *out, bool is_list, const char *tag_name , size_t pairs_count, ...); -char *pe__node_display_name(pe_node_t *node, bool print_detail); +char *pe__node_display_name(pcmk_node_t *node, bool print_detail); // Clone notifications (pe_notif.c) -void pe__order_notifs_after_fencing(const pe_action_t *action, - pe_resource_t *rsc, - pe_action_t *stonith_op); +void pe__order_notifs_after_fencing(const pcmk_action_t *action, + pcmk_resource_t *rsc, + pcmk_action_t *stonith_op); static inline const char * -pe__rsc_bool_str(const pe_resource_t *rsc, uint64_t rsc_flag) +pe__rsc_bool_str(const pcmk_resource_t *rsc, uint64_t rsc_flag) { return pcmk__btoa(pcmk_is_set(rsc->flags, rsc_flag)); } @@ -308,167 +278,156 @@ int pe__resource_xml(pcmk__output_t *out, va_list args); int pe__resource_html(pcmk__output_t *out, va_list args); int pe__resource_text(pcmk__output_t *out, va_list args); -void native_free(pe_resource_t * rsc); -void group_free(pe_resource_t * rsc); -void clone_free(pe_resource_t * rsc); -void pe__free_bundle(pe_resource_t *rsc); - -enum rsc_role_e native_resource_state(const pe_resource_t * rsc, gboolean current); -enum rsc_role_e group_resource_state(const pe_resource_t * rsc, gboolean current); -enum rsc_role_e clone_resource_state(const pe_resource_t * rsc, gboolean current); -enum rsc_role_e pe__bundle_resource_state(const pe_resource_t *rsc, +void native_free(pcmk_resource_t *rsc); +void group_free(pcmk_resource_t *rsc); +void clone_free(pcmk_resource_t *rsc); +void pe__free_bundle(pcmk_resource_t *rsc); + +enum rsc_role_e native_resource_state(const pcmk_resource_t *rsc, + gboolean current); +enum rsc_role_e group_resource_state(const pcmk_resource_t *rsc, + gboolean current); +enum rsc_role_e clone_resource_state(const pcmk_resource_t *rsc, + gboolean current); +enum rsc_role_e pe__bundle_resource_state(const pcmk_resource_t *rsc, gboolean current); -void pe__count_common(pe_resource_t *rsc); -void pe__count_bundle(pe_resource_t *rsc); +void pe__count_common(pcmk_resource_t *rsc); +void pe__count_bundle(pcmk_resource_t *rsc); -void common_free(pe_resource_t * rsc); +void common_free(pcmk_resource_t *rsc); -pe_node_t *pe__copy_node(const pe_node_t *this_node); -extern time_t get_effective_time(pe_working_set_t * data_set); +pcmk_node_t *pe__copy_node(const pcmk_node_t *this_node); +time_t get_effective_time(pcmk_scheduler_t *scheduler); /* Failure handling utilities (from failcounts.c) */ -// bit flags for fail count handling options -enum pe_fc_flags_e { - pe_fc_default = (1 << 0), - pe_fc_effective = (1 << 1), // don't count expired failures - pe_fc_fillers = (1 << 2), // if container, include filler failures in count -}; - -int pe_get_failcount(const pe_node_t *node, pe_resource_t *rsc, +int pe_get_failcount(const pcmk_node_t *node, pcmk_resource_t *rsc, time_t *last_failure, uint32_t flags, const xmlNode *xml_op); -pe_action_t *pe__clear_failcount(pe_resource_t *rsc, const pe_node_t *node, - const char *reason, - pe_working_set_t *data_set); +pcmk_action_t *pe__clear_failcount(pcmk_resource_t *rsc, + const pcmk_node_t *node, const char *reason, + pcmk_scheduler_t *scheduler); /* Functions for finding/counting a resource's active nodes */ -bool pe__count_active_node(const pe_resource_t *rsc, pe_node_t *node, - pe_node_t **active, unsigned int *count_all, +bool pe__count_active_node(const pcmk_resource_t *rsc, pcmk_node_t *node, + pcmk_node_t **active, unsigned int *count_all, unsigned int *count_clean); -pe_node_t *pe__find_active_requires(const pe_resource_t *rsc, +pcmk_node_t *pe__find_active_requires(const pcmk_resource_t *rsc, unsigned int *count); -static inline pe_node_t * -pe__current_node(const pe_resource_t *rsc) +static inline pcmk_node_t * +pe__current_node(const pcmk_resource_t *rsc) { return (rsc == NULL)? NULL : rsc->fns->active_node(rsc, NULL, NULL); } /* Binary like operators for lists of nodes */ -extern void node_list_exclude(GHashTable * list, GList *list2, gboolean merge_scores); - GHashTable *pe__node_list2table(const GList *list); -static inline gpointer -pe_hash_table_lookup(GHashTable * hash, gconstpointer key) -{ - if (hash) { - return g_hash_table_lookup(hash, key); - } - return NULL; -} - -extern pe_action_t *get_pseudo_op(const char *name, pe_working_set_t * data_set); -extern gboolean order_actions(pe_action_t * lh_action, pe_action_t * rh_action, enum pe_ordering order); - -void pe__show_node_weights_as(const char *file, const char *function, - int line, bool to_log, const pe_resource_t *rsc, - const char *comment, GHashTable *nodes, - pe_working_set_t *data_set); - -#define pe__show_node_weights(level, rsc, text, nodes, data_set) \ - pe__show_node_weights_as(__FILE__, __func__, __LINE__, \ - (level), (rsc), (text), (nodes), (data_set)) - -xmlNode *find_rsc_op_entry(const pe_resource_t *rsc, const char *key); - -pe_action_t *custom_action(pe_resource_t *rsc, char *key, const char *task, - const pe_node_t *on_node, gboolean optional, - gboolean foo, pe_working_set_t *data_set); - -# define delete_key(rsc) pcmk__op_key(rsc->id, CRMD_ACTION_DELETE, 0) +pcmk_action_t *get_pseudo_op(const char *name, pcmk_scheduler_t *scheduler); +gboolean order_actions(pcmk_action_t *lh_action, pcmk_action_t *rh_action, + uint32_t flags); + +void pe__show_node_scores_as(const char *file, const char *function, + int line, bool to_log, const pcmk_resource_t *rsc, + const char *comment, GHashTable *nodes, + pcmk_scheduler_t *scheduler); + +#define pe__show_node_scores(level, rsc, text, nodes, scheduler) \ + pe__show_node_scores_as(__FILE__, __func__, __LINE__, \ + (level), (rsc), (text), (nodes), (scheduler)) + +GHashTable *pcmk__unpack_action_meta(pcmk_resource_t *rsc, + const pcmk_node_t *node, + const char *action_name, guint interval_ms, + const xmlNode *action_config); +GHashTable *pcmk__unpack_action_rsc_params(const xmlNode *action_xml, + GHashTable *node_attrs, + pcmk_scheduler_t *data_set); +xmlNode *pcmk__find_action_config(const pcmk_resource_t *rsc, + const char *action_name, guint interval_ms, + bool include_disabled); + +enum rsc_start_requirement pcmk__action_requires(const pcmk_resource_t *rsc, + const char *action_name); + +enum action_fail_response pcmk__parse_on_fail(const pcmk_resource_t *rsc, + const char *action_name, + guint interval_ms, + const char *value); + +enum rsc_role_e pcmk__role_after_failure(const pcmk_resource_t *rsc, + const char *action_name, + enum action_fail_response on_fail, + GHashTable *meta); + +pcmk_action_t *custom_action(pcmk_resource_t *rsc, char *key, const char *task, + const pcmk_node_t *on_node, gboolean optional, + pcmk_scheduler_t *scheduler); + +# define delete_key(rsc) pcmk__op_key(rsc->id, PCMK_ACTION_DELETE, 0) # define delete_action(rsc, node, optional) custom_action( \ - rsc, delete_key(rsc), CRMD_ACTION_DELETE, node, \ - optional, TRUE, rsc->cluster); - -# define stopped_key(rsc) pcmk__op_key(rsc->id, CRMD_ACTION_STOPPED, 0) -# define stopped_action(rsc, node, optional) custom_action( \ - rsc, stopped_key(rsc), CRMD_ACTION_STOPPED, node, \ - optional, TRUE, rsc->cluster); + rsc, delete_key(rsc), PCMK_ACTION_DELETE, node, \ + optional, rsc->cluster); -# define stop_key(rsc) pcmk__op_key(rsc->id, CRMD_ACTION_STOP, 0) +# define stop_key(rsc) pcmk__op_key(rsc->id, PCMK_ACTION_STOP, 0) # define stop_action(rsc, node, optional) custom_action( \ - rsc, stop_key(rsc), CRMD_ACTION_STOP, node, \ - optional, TRUE, rsc->cluster); + rsc, stop_key(rsc), PCMK_ACTION_STOP, node, \ + optional, rsc->cluster); -# define reload_key(rsc) pcmk__op_key(rsc->id, CRMD_ACTION_RELOAD_AGENT, 0) -# define start_key(rsc) pcmk__op_key(rsc->id, CRMD_ACTION_START, 0) +# define reload_key(rsc) pcmk__op_key(rsc->id, PCMK_ACTION_RELOAD_AGENT, 0) +# define start_key(rsc) pcmk__op_key(rsc->id, PCMK_ACTION_START, 0) # define start_action(rsc, node, optional) custom_action( \ - rsc, start_key(rsc), CRMD_ACTION_START, node, \ - optional, TRUE, rsc->cluster) + rsc, start_key(rsc), PCMK_ACTION_START, node, \ + optional, rsc->cluster) -# define started_key(rsc) pcmk__op_key(rsc->id, CRMD_ACTION_STARTED, 0) -# define started_action(rsc, node, optional) custom_action( \ - rsc, started_key(rsc), CRMD_ACTION_STARTED, node, \ - optional, TRUE, rsc->cluster) - -# define promote_key(rsc) pcmk__op_key(rsc->id, CRMD_ACTION_PROMOTE, 0) +# define promote_key(rsc) pcmk__op_key(rsc->id, PCMK_ACTION_PROMOTE, 0) # define promote_action(rsc, node, optional) custom_action( \ - rsc, promote_key(rsc), CRMD_ACTION_PROMOTE, node, \ - optional, TRUE, rsc->cluster) - -# define promoted_key(rsc) pcmk__op_key(rsc->id, CRMD_ACTION_PROMOTED, 0) -# define promoted_action(rsc, node, optional) custom_action( \ - rsc, promoted_key(rsc), CRMD_ACTION_PROMOTED, node, \ - optional, TRUE, rsc->cluster) + rsc, promote_key(rsc), PCMK_ACTION_PROMOTE, node, \ + optional, rsc->cluster) -# define demote_key(rsc) pcmk__op_key(rsc->id, CRMD_ACTION_DEMOTE, 0) +# define demote_key(rsc) pcmk__op_key(rsc->id, PCMK_ACTION_DEMOTE, 0) # define demote_action(rsc, node, optional) custom_action( \ - rsc, demote_key(rsc), CRMD_ACTION_DEMOTE, node, \ - optional, TRUE, rsc->cluster) + rsc, demote_key(rsc), PCMK_ACTION_DEMOTE, node, \ + optional, rsc->cluster) -# define demoted_key(rsc) pcmk__op_key(rsc->id, CRMD_ACTION_DEMOTED, 0) -# define demoted_action(rsc, node, optional) custom_action( \ - rsc, demoted_key(rsc), CRMD_ACTION_DEMOTED, node, \ - optional, TRUE, rsc->cluster) +extern int pe_get_configured_timeout(pcmk_resource_t *rsc, const char *action, + pcmk_scheduler_t *scheduler); -extern int pe_get_configured_timeout(pe_resource_t *rsc, const char *action, - pe_working_set_t *data_set); +pcmk_action_t *find_first_action(const GList *input, const char *uuid, + const char *task, const pcmk_node_t *on_node); -pe_action_t *find_first_action(const GList *input, const char *uuid, - const char *task, const pe_node_t *on_node); +enum action_tasks get_complex_task(const pcmk_resource_t *rsc, + const char *name); -enum action_tasks get_complex_task(const pe_resource_t *rsc, const char *name); - -extern GList *find_actions(GList *input, const char *key, const pe_node_t *on_node); +GList *find_actions(GList *input, const char *key, const pcmk_node_t *on_node); GList *find_actions_exact(GList *input, const char *key, - const pe_node_t *on_node); -GList *pe__resource_actions(const pe_resource_t *rsc, const pe_node_t *node, + const pcmk_node_t *on_node); +GList *pe__resource_actions(const pcmk_resource_t *rsc, const pcmk_node_t *node, const char *task, bool require_node); -extern void pe_free_action(pe_action_t * action); +extern void pe_free_action(pcmk_action_t *action); -void resource_location(pe_resource_t *rsc, const pe_node_t *node, int score, - const char *tag, pe_working_set_t *data_set); +void resource_location(pcmk_resource_t *rsc, const pcmk_node_t *node, int score, + const char *tag, pcmk_scheduler_t *scheduler); extern int pe__is_newer_op(const xmlNode *xml_a, const xmlNode *xml_b, bool same_node_default); extern gint sort_op_by_callid(gconstpointer a, gconstpointer b); -gboolean get_target_role(const pe_resource_t *rsc, enum rsc_role_e *role); -void pe__set_next_role(pe_resource_t *rsc, enum rsc_role_e role, +gboolean get_target_role(const pcmk_resource_t *rsc, enum rsc_role_e *role); +void pe__set_next_role(pcmk_resource_t *rsc, enum rsc_role_e role, const char *why); -pe_resource_t *find_clone_instance(const pe_resource_t *rsc, - const char *sub_id); +pcmk_resource_t *find_clone_instance(const pcmk_resource_t *rsc, + const char *sub_id); extern void destroy_ticket(gpointer data); -extern pe_ticket_t *ticket_new(const char *ticket_id, pe_working_set_t * data_set); +pcmk_ticket_t *ticket_new(const char *ticket_id, pcmk_scheduler_t *scheduler); // Resources for manipulating resource names const char *pe_base_name_end(const char *id); @@ -476,7 +435,7 @@ char *clone_strip(const char *last_rsc_id); char *clone_zero(const char *last_rsc_id); static inline bool -pe_base_name_eq(const pe_resource_t *rsc, const char *id) +pe_base_name_eq(const pcmk_resource_t *rsc, const char *id) { if (id && rsc && rsc->id) { // Number of characters in rsc->id before any clone suffix @@ -490,22 +449,10 @@ pe_base_name_eq(const pe_resource_t *rsc, const char *id) int pe__target_rc_from_xml(const xmlNode *xml_op); gint pe__cmp_node_name(gconstpointer a, gconstpointer b); -bool is_set_recursive(const pe_resource_t *rsc, long long flag, bool any); - -enum rsc_digest_cmp_val { - /*! Digests are the same */ - RSC_DIGEST_MATCH = 0, - /*! Params that require a restart changed */ - RSC_DIGEST_RESTART, - /*! Some parameter changed. */ - RSC_DIGEST_ALL, - /*! rsc op didn't have a digest associated with it, so - * it is unknown if parameters changed or not. */ - RSC_DIGEST_UNKNOWN, -}; +bool is_set_recursive(const pcmk_resource_t *rsc, long long flag, bool any); typedef struct op_digest_cache_s { - enum rsc_digest_cmp_val rc; + enum pcmk__digest_result rc; xmlNode *params_all; xmlNode *params_secure; xmlNode *params_restart; @@ -514,35 +461,37 @@ typedef struct op_digest_cache_s { char *digest_restart_calc; } op_digest_cache_t; -op_digest_cache_t *pe__calculate_digests(pe_resource_t *rsc, const char *task, +op_digest_cache_t *pe__calculate_digests(pcmk_resource_t *rsc, const char *task, guint *interval_ms, - const pe_node_t *node, + const pcmk_node_t *node, const xmlNode *xml_op, GHashTable *overrides, bool calc_secure, - pe_working_set_t *data_set); + pcmk_scheduler_t *scheduler); void pe__free_digests(gpointer ptr); -op_digest_cache_t *rsc_action_digest_cmp(pe_resource_t *rsc, +op_digest_cache_t *rsc_action_digest_cmp(pcmk_resource_t *rsc, const xmlNode *xml_op, - pe_node_t *node, - pe_working_set_t *data_set); - -pe_action_t *pe_fence_op(pe_node_t *node, const char *op, bool optional, - const char *reason, bool priority_delay, - pe_working_set_t *data_set); -void trigger_unfencing(pe_resource_t *rsc, pe_node_t *node, - const char *reason, pe_action_t *dependency, - pe_working_set_t *data_set); - -char *pe__action2reason(const pe_action_t *action, enum pe_action_flags flag); -void pe_action_set_reason(pe_action_t *action, const char *reason, bool overwrite); -void pe__add_action_expected_result(pe_action_t *action, int expected_result); - -void pe__set_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags); -void pe__clear_resource_flags_recursive(pe_resource_t *rsc, uint64_t flags); -void pe__clear_resource_flags_on_all(pe_working_set_t *data_set, uint64_t flag); + pcmk_node_t *node, + pcmk_scheduler_t *scheduler); + +pcmk_action_t *pe_fence_op(pcmk_node_t *node, const char *op, bool optional, + const char *reason, bool priority_delay, + pcmk_scheduler_t *scheduler); +void trigger_unfencing(pcmk_resource_t *rsc, pcmk_node_t *node, + const char *reason, pcmk_action_t *dependency, + pcmk_scheduler_t *scheduler); + +char *pe__action2reason(const pcmk_action_t *action, enum pe_action_flags flag); +void pe_action_set_reason(pcmk_action_t *action, const char *reason, + bool overwrite); +void pe__add_action_expected_result(pcmk_action_t *action, int expected_result); + +void pe__set_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags); +void pe__clear_resource_flags_recursive(pcmk_resource_t *rsc, uint64_t flags); +void pe__clear_resource_flags_on_all(pcmk_scheduler_t *scheduler, + uint64_t flag); gboolean add_tag_ref(GHashTable * tags, const char * tag_name, const char * obj_ref); @@ -550,49 +499,75 @@ gboolean add_tag_ref(GHashTable * tags, const char * tag_name, const char * obj void print_rscs_brief(GList *rsc_list, const char * pre_text, long options, void * print_data, gboolean print_all); int pe__rscs_brief_output(pcmk__output_t *out, GList *rsc_list, unsigned int options); -void pe_fence_node(pe_working_set_t * data_set, pe_node_t * node, const char *reason, bool priority_delay); +void pe_fence_node(pcmk_scheduler_t *scheduler, pcmk_node_t *node, + const char *reason, bool priority_delay); -pe_node_t *pe_create_node(const char *id, const char *uname, const char *type, - const char *score, pe_working_set_t * data_set); +pcmk_node_t *pe_create_node(const char *id, const char *uname, const char *type, + const char *score, pcmk_scheduler_t *scheduler); //! \deprecated This function will be removed in a future release -void common_print(pe_resource_t *rsc, const char *pre_text, const char *name, - const pe_node_t *node, long options, void *print_data); -int pe__common_output_text(pcmk__output_t *out, const pe_resource_t *rsc, - const char *name, const pe_node_t *node, +void common_print(pcmk_resource_t *rsc, const char *pre_text, const char *name, + const pcmk_node_t *node, long options, void *print_data); +int pe__common_output_text(pcmk__output_t *out, const pcmk_resource_t *rsc, + const char *name, const pcmk_node_t *node, unsigned int options); -int pe__common_output_html(pcmk__output_t *out, const pe_resource_t *rsc, - const char *name, const pe_node_t *node, +int pe__common_output_html(pcmk__output_t *out, const pcmk_resource_t *rsc, + const char *name, const pcmk_node_t *node, unsigned int options); -GList *pe__bundle_containers(const pe_resource_t *bundle); - -int pe__bundle_max(const pe_resource_t *rsc); -int pe__bundle_max_per_node(const pe_resource_t *rsc); - -pe_resource_t *pe__find_bundle_replica(const pe_resource_t *bundle, - const pe_node_t *node); -bool pe__bundle_needs_remote_name(pe_resource_t *rsc); -const char *pe__add_bundle_remote_name(pe_resource_t *rsc, - pe_working_set_t *data_set, +//! A single instance of a bundle +typedef struct { + int offset; //!< 0-origin index of this instance in bundle + char *ipaddr; //!< IP address associated with this instance + pcmk_node_t *node; //!< Node created for this instance + pcmk_resource_t *ip; //!< IP address resource for ipaddr + pcmk_resource_t *child; //!< Instance of bundled resource + pcmk_resource_t *container; //!< Container associated with this instance + pcmk_resource_t *remote; //!< Pacemaker Remote connection into container +} pe__bundle_replica_t; + +GList *pe__bundle_containers(const pcmk_resource_t *bundle); + +int pe__bundle_max(const pcmk_resource_t *rsc); +bool pe__node_is_bundle_instance(const pcmk_resource_t *bundle, + const pcmk_node_t *node); +pcmk_resource_t *pe__bundled_resource(const pcmk_resource_t *rsc); +const pcmk_resource_t *pe__get_rsc_in_container(const pcmk_resource_t *instance); +pcmk_resource_t *pe__first_container(const pcmk_resource_t *bundle); +void pe__foreach_bundle_replica(pcmk_resource_t *bundle, + bool (*fn)(pe__bundle_replica_t *, void *), + void *user_data); +void pe__foreach_const_bundle_replica(const pcmk_resource_t *bundle, + bool (*fn)(const pe__bundle_replica_t *, + void *), + void *user_data); +pcmk_resource_t *pe__find_bundle_replica(const pcmk_resource_t *bundle, + const pcmk_node_t *node); +bool pe__bundle_needs_remote_name(pcmk_resource_t *rsc); +const char *pe__add_bundle_remote_name(pcmk_resource_t *rsc, + pcmk_scheduler_t *scheduler, xmlNode *xml, const char *field); -const char *pe_node_attribute_calculated(const pe_node_t *node, - const char *name, - const pe_resource_t *rsc); -const char *pe_node_attribute_raw(const pe_node_t *node, const char *name); -bool pe__is_universal_clone(const pe_resource_t *rsc, - const pe_working_set_t *data_set); -void pe__add_param_check(const xmlNode *rsc_op, pe_resource_t *rsc, - pe_node_t *node, enum pe_check_parameters, - pe_working_set_t *data_set); -void pe__foreach_param_check(pe_working_set_t *data_set, - void (*cb)(pe_resource_t*, pe_node_t*, + +const char *pe__node_attribute_calculated(const pcmk_node_t *node, + const char *name, + const pcmk_resource_t *rsc, + enum pcmk__rsc_node node_type, + bool force_host); +const char *pe_node_attribute_raw(const pcmk_node_t *node, const char *name); +bool pe__is_universal_clone(const pcmk_resource_t *rsc, + const pcmk_scheduler_t *scheduler); +void pe__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc, + pcmk_node_t *node, enum pcmk__check_parameters, + pcmk_scheduler_t *scheduler); +void pe__foreach_param_check(pcmk_scheduler_t *scheduler, + void (*cb)(pcmk_resource_t*, pcmk_node_t*, const xmlNode*, - enum pe_check_parameters)); -void pe__free_param_checks(pe_working_set_t *data_set); + enum pcmk__check_parameters)); +void pe__free_param_checks(pcmk_scheduler_t *scheduler); -bool pe__shutdown_requested(const pe_node_t *node); -void pe__update_recheck_time(time_t recheck, pe_working_set_t *data_set); +bool pe__shutdown_requested(const pcmk_node_t *node); +void pe__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler, + const char *reason); /*! * \internal @@ -605,53 +580,55 @@ void pe__register_messages(pcmk__output_t *out); void pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name, const pe_rule_eval_data_t *rule_data, GHashTable *hash, const char *always_first, - gboolean overwrite, pe_working_set_t *data_set); - -bool pe__resource_is_disabled(const pe_resource_t *rsc); -pe_action_t *pe__clear_resource_history(pe_resource_t *rsc, - const pe_node_t *node, - pe_working_set_t *data_set); - -GList *pe__rscs_with_tag(pe_working_set_t *data_set, const char *tag_name); -GList *pe__unames_with_tag(pe_working_set_t *data_set, const char *tag_name); -bool pe__rsc_has_tag(pe_working_set_t *data_set, const char *rsc, const char *tag); -bool pe__uname_has_tag(pe_working_set_t *data_set, const char *node, const char *tag); - -bool pe__rsc_running_on_only(const pe_resource_t *rsc, const pe_node_t *node); -bool pe__rsc_running_on_any(pe_resource_t *rsc, GList *node_list); + gboolean overwrite, + pcmk_scheduler_t *scheduler); + +bool pe__resource_is_disabled(const pcmk_resource_t *rsc); +void pe__clear_resource_history(pcmk_resource_t *rsc, const pcmk_node_t *node); + +GList *pe__rscs_with_tag(pcmk_scheduler_t *scheduler, const char *tag_name); +GList *pe__unames_with_tag(pcmk_scheduler_t *scheduler, const char *tag_name); +bool pe__rsc_has_tag(pcmk_scheduler_t *scheduler, const char *rsc, + const char *tag); +bool pe__uname_has_tag(pcmk_scheduler_t *scheduler, const char *node, + const char *tag); + +bool pe__rsc_running_on_only(const pcmk_resource_t *rsc, + const pcmk_node_t *node); +bool pe__rsc_running_on_any(pcmk_resource_t *rsc, GList *node_list); GList *pe__filter_rsc_list(GList *rscs, GList *filter); -GList * pe__build_node_name_list(pe_working_set_t *data_set, const char *s); -GList * pe__build_rsc_list(pe_working_set_t *data_set, const char *s); +GList * pe__build_node_name_list(pcmk_scheduler_t *scheduler, const char *s); +GList * pe__build_rsc_list(pcmk_scheduler_t *scheduler, const char *s); -bool pcmk__rsc_filtered_by_node(pe_resource_t *rsc, GList *only_node); +bool pcmk__rsc_filtered_by_node(pcmk_resource_t *rsc, GList *only_node); -gboolean pe__bundle_is_filtered(const pe_resource_t *rsc, GList *only_rsc, +gboolean pe__bundle_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent); -gboolean pe__clone_is_filtered(const pe_resource_t *rsc, GList *only_rsc, +gboolean pe__clone_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent); -gboolean pe__group_is_filtered(const pe_resource_t *rsc, GList *only_rsc, +gboolean pe__group_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent); -gboolean pe__native_is_filtered(const pe_resource_t *rsc, GList *only_rsc, +gboolean pe__native_is_filtered(const pcmk_resource_t *rsc, GList *only_rsc, gboolean check_parent); -xmlNode *pe__failed_probe_for_rsc(const pe_resource_t *rsc, const char *name); +xmlNode *pe__failed_probe_for_rsc(const pcmk_resource_t *rsc, const char *name); -const char *pe__clone_child_id(const pe_resource_t *rsc); +const char *pe__clone_child_id(const pcmk_resource_t *rsc); -int pe__sum_node_health_scores(const pe_node_t *node, int base_health); -int pe__node_health(pe_node_t *node); +int pe__sum_node_health_scores(const pcmk_node_t *node, int base_health); +int pe__node_health(pcmk_node_t *node); static inline enum pcmk__health_strategy -pe__health_strategy(pe_working_set_t *data_set) +pe__health_strategy(pcmk_scheduler_t *scheduler) { - return pcmk__parse_health_strategy(pe_pref(data_set->config_hash, + return pcmk__parse_health_strategy(pe_pref(scheduler->config_hash, PCMK__OPT_NODE_HEALTH_STRATEGY)); } static inline int -pe__health_score(const char *option, pe_working_set_t *data_set) +pe__health_score(const char *option, pcmk_scheduler_t *scheduler) { - return char2score(pe_pref(data_set->config_hash, option)); + return char2score(pe_pref(scheduler->config_hash, option)); } /*! @@ -665,7 +642,7 @@ pe__health_score(const char *option, pe_working_set_t *data_set) * if node has neither a name nor ID. */ static inline const char * -pe__node_name(const pe_node_t *node) +pe__node_name(const pcmk_node_t *node) { if (node == NULL) { return "unspecified node"; @@ -691,7 +668,7 @@ pe__node_name(const pe_node_t *node) * \return true if \p node1 and \p node2 refer to the same node */ static inline bool -pe__same_node(const pe_node_t *node1, const pe_node_t *node2) +pe__same_node(const pcmk_node_t *node1, const pcmk_node_t *node2) { return (node1 != NULL) && (node2 != NULL) && (node1->details == node2->details); diff --git a/include/crm/pengine/pe_types.h b/include/crm/pengine/pe_types.h index cc626c8..24355f8 100644 --- a/include/crm/pengine/pe_types.h +++ b/include/crm/pengine/pe_types.h @@ -16,6 +16,7 @@ # include <libxml/tree.h> // xmlNode # include <glib.h> // gboolean, guint, GList, GHashTable # include <crm/common/iso8601.h> +# include <crm/common/scheduler.h> # include <crm/pengine/common.h> #ifdef __cplusplus @@ -28,535 +29,6 @@ extern "C" { * \ingroup pengine */ -typedef struct pe_node_s pe_node_t; -typedef struct pe_action_s pe_action_t; -typedef struct pe_resource_s pe_resource_t; -typedef struct pe_working_set_s pe_working_set_t; - -enum pe_obj_types { - pe_unknown = -1, - pe_native = 0, - pe_group = 1, - pe_clone = 2, - pe_container = 3, -}; - -typedef struct resource_object_functions_s { - gboolean (*unpack) (pe_resource_t*, pe_working_set_t*); - pe_resource_t *(*find_rsc) (pe_resource_t *parent, const char *search, - const pe_node_t *node, int flags); - /* parameter result must be free'd */ - char *(*parameter) (pe_resource_t*, pe_node_t*, gboolean, const char*, - pe_working_set_t*); - //! \deprecated will be removed in a future release - void (*print) (pe_resource_t*, const char*, long, void*); - gboolean (*active) (pe_resource_t*, gboolean); - enum rsc_role_e (*state) (const pe_resource_t*, gboolean); - pe_node_t *(*location) (const pe_resource_t*, GList**, int); - void (*free) (pe_resource_t*); - void (*count) (pe_resource_t*); - gboolean (*is_filtered) (const pe_resource_t*, GList *, gboolean); - - /*! - * \brief - * \internal Find a node (and optionally count all) where resource is active - * - * \param[in] rsc Resource to check - * \param[out] count_all If not NULL, set this to count of active nodes - * \param[out] count_clean If not NULL, set this to count of clean nodes - * - * \return A node where the resource is active, preferring the source node - * if the resource is involved in a partial migration or a clean, - * online node if the resource's "requires" is "quorum" or - * "nothing", or NULL if the resource is inactive. - */ - pe_node_t *(*active_node)(const pe_resource_t *rsc, unsigned int *count_all, - unsigned int *count_clean); -} resource_object_functions_t; - -typedef struct resource_alloc_functions_s resource_alloc_functions_t; - -enum pe_quorum_policy { - no_quorum_freeze, - no_quorum_stop, - no_quorum_ignore, - no_quorum_suicide, - no_quorum_demote -}; - -enum node_type { - node_ping, //! \deprecated Do not use - node_member, - node_remote -}; - -//! \deprecated will be removed in a future release -enum pe_restart { - pe_restart_restart, //! \deprecated will be removed in a future release - pe_restart_ignore //! \deprecated will be removed in a future release -}; - -//! Determine behavior of pe_find_resource_with_flags() -enum pe_find { - pe_find_renamed = 0x001, //!< match resource ID or LRM history ID - pe_find_anon = 0x002, //!< match base name of anonymous clone instances - pe_find_clone = 0x004, //!< match only clone instances - pe_find_current = 0x008, //!< match resource active on specified node - pe_find_inactive = 0x010, //!< match resource not running anywhere - pe_find_any = 0x020, //!< match base name of any clone instance -}; - -// @TODO Make these an enum - -# define pe_flag_have_quorum 0x00000001ULL -# define pe_flag_symmetric_cluster 0x00000002ULL -# define pe_flag_maintenance_mode 0x00000008ULL - -# define pe_flag_stonith_enabled 0x00000010ULL -# define pe_flag_have_stonith_resource 0x00000020ULL -# define pe_flag_enable_unfencing 0x00000040ULL -# define pe_flag_concurrent_fencing 0x00000080ULL - -# define pe_flag_stop_rsc_orphans 0x00000100ULL -# define pe_flag_stop_action_orphans 0x00000200ULL -# define pe_flag_stop_everything 0x00000400ULL - -# define pe_flag_start_failure_fatal 0x00001000ULL - -//! \deprecated -# define pe_flag_remove_after_stop 0x00002000ULL - -# define pe_flag_startup_fencing 0x00004000ULL -# define pe_flag_shutdown_lock 0x00008000ULL - -# define pe_flag_startup_probes 0x00010000ULL -# define pe_flag_have_status 0x00020000ULL -# define pe_flag_have_remote_nodes 0x00040000ULL - -# define pe_flag_quick_location 0x00100000ULL -# define pe_flag_sanitized 0x00200000ULL - -//! \deprecated -# define pe_flag_stdout 0x00400000ULL - -//! Don't count total, disabled and blocked resource instances -# define pe_flag_no_counts 0x00800000ULL - -/*! Skip deprecated code that is kept solely for backward API compatibility. - * (Internal code should always set this.) - */ -# define pe_flag_no_compat 0x01000000ULL - -# define pe_flag_show_scores 0x02000000ULL -# define pe_flag_show_utilization 0x04000000ULL - -/*! - * When scheduling, only unpack the CIB (including constraints), calculate - * as much cluster status as possible, and apply node health. - */ -# define pe_flag_check_config 0x08000000ULL - -struct pe_working_set_s { - xmlNode *input; - crm_time_t *now; - - /* options extracted from the input */ - char *dc_uuid; - pe_node_t *dc_node; - const char *stonith_action; - const char *placement_strategy; - - unsigned long long flags; - - int stonith_timeout; - enum pe_quorum_policy no_quorum_policy; - - GHashTable *config_hash; - GHashTable *tickets; - - // Actions for which there can be only one (e.g. fence nodeX) - GHashTable *singletons; - - GList *nodes; - GList *resources; - GList *placement_constraints; - GList *ordering_constraints; - GList *colocation_constraints; - GList *ticket_constraints; - - GList *actions; - xmlNode *failed; - xmlNode *op_defaults; - xmlNode *rsc_defaults; - - /* stats */ - int num_synapse; - int max_valid_nodes; //! Deprecated (will be removed in a future release) - int order_id; - int action_id; - - /* final output */ - xmlNode *graph; - - GHashTable *template_rsc_sets; - const char *localhost; - GHashTable *tags; - - int blocked_resources; - int disabled_resources; - - GList *param_check; // History entries that need to be checked - GList *stop_needed; // Containers that need stop actions - time_t recheck_by; // Hint to controller to re-run scheduler by this time - int ninstances; // Total number of resource instances - guint shutdown_lock;// How long (seconds) to lock resources to shutdown node - int priority_fencing_delay; // Priority fencing delay - - void *priv; -}; - -enum pe_check_parameters { - /* Clear fail count if parameters changed for un-expired start or monitor - * last_failure. - */ - pe_check_last_failure, - - /* Clear fail count if parameters changed for start, monitor, promote, or - * migrate_from actions for active resources. - */ - pe_check_active, -}; - -struct pe_node_shared_s { - const char *id; - const char *uname; - enum node_type type; - - /* @TODO convert these flags into a bitfield */ - gboolean online; - gboolean standby; - gboolean standby_onfail; - gboolean pending; - gboolean unclean; - gboolean unseen; - gboolean shutdown; - gboolean expected_up; - gboolean is_dc; - gboolean maintenance; - gboolean rsc_discovery_enabled; - gboolean remote_requires_reset; - gboolean remote_was_fenced; - gboolean remote_maintenance; /* what the remote-rsc is thinking */ - gboolean unpacked; - - int num_resources; - pe_resource_t *remote_rsc; - GList *running_rsc; /* pe_resource_t* */ - GList *allocated_rsc; /* pe_resource_t* */ - - GHashTable *attrs; /* char* => char* */ - GHashTable *utilization; - GHashTable *digest_cache; //!< cache of calculated resource digests - int priority; // calculated based on the priority of resources running on the node - pe_working_set_t *data_set; //!< Cluster that this node is part of -}; - -struct pe_node_s { - int weight; - gboolean fixed; //!< \deprecated Will be removed in a future release - int count; - struct pe_node_shared_s *details; - int rsc_discover_mode; -}; - -# define pe_rsc_orphan 0x00000001ULL -# define pe_rsc_managed 0x00000002ULL -# define pe_rsc_block 0x00000004ULL -# define pe_rsc_orphan_container_filler 0x00000008ULL - -# define pe_rsc_notify 0x00000010ULL -# define pe_rsc_unique 0x00000020ULL -# define pe_rsc_fence_device 0x00000040ULL -# define pe_rsc_promotable 0x00000080ULL - -# define pe_rsc_provisional 0x00000100ULL -# define pe_rsc_allocating 0x00000200ULL -# define pe_rsc_merging 0x00000400ULL -# define pe_rsc_restarting 0x00000800ULL - -# define pe_rsc_stop 0x00001000ULL -# define pe_rsc_reload 0x00002000ULL -# define pe_rsc_allow_remote_remotes 0x00004000ULL -# define pe_rsc_critical 0x00008000ULL - -# define pe_rsc_failed 0x00010000ULL -# define pe_rsc_detect_loop 0x00020000ULL -# define pe_rsc_runnable 0x00040000ULL -# define pe_rsc_start_pending 0x00080000ULL - -//!< \deprecated Do not use -# define pe_rsc_starting 0x00100000ULL - -//!< \deprecated Do not use -# define pe_rsc_stopping 0x00200000ULL - -# define pe_rsc_stop_unexpected 0x00400000ULL -# define pe_rsc_allow_migrate 0x00800000ULL - -# define pe_rsc_failure_ignored 0x01000000ULL -# define pe_rsc_replica_container 0x02000000ULL -# define pe_rsc_maintenance 0x04000000ULL -# define pe_rsc_is_container 0x08000000ULL - -# define pe_rsc_needs_quorum 0x10000000ULL -# define pe_rsc_needs_fencing 0x20000000ULL -# define pe_rsc_needs_unfencing 0x40000000ULL - -/* *INDENT-OFF* */ -enum pe_action_flags { - pe_action_pseudo = 0x00001, - pe_action_runnable = 0x00002, - pe_action_optional = 0x00004, - pe_action_print_always = 0x00008, - - pe_action_have_node_attrs = 0x00010, - pe_action_implied_by_stonith = 0x00040, - pe_action_migrate_runnable = 0x00080, - - pe_action_dumped = 0x00100, - pe_action_processed = 0x00200, -#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) - pe_action_clear = 0x00400, //! \deprecated Unused -#endif - pe_action_dangle = 0x00800, - - /* This action requires one or more of its dependencies to be runnable. - * We use this to clear the runnable flag before checking dependencies. - */ - pe_action_requires_any = 0x01000, - - pe_action_reschedule = 0x02000, - pe_action_tracking = 0x04000, - pe_action_dedup = 0x08000, //! Internal state tracking when creating graph - - pe_action_dc = 0x10000, //! Action may run on DC instead of target -}; -/* *INDENT-ON* */ - -struct pe_resource_s { - char *id; - char *clone_name; - xmlNode *xml; - xmlNode *orig_xml; - xmlNode *ops_xml; - - pe_working_set_t *cluster; - pe_resource_t *parent; - - enum pe_obj_types variant; - void *variant_opaque; - resource_object_functions_t *fns; - resource_alloc_functions_t *cmds; - - enum rsc_recovery_type recovery_type; - - enum pe_restart restart_type; //!< \deprecated will be removed in future release - - int priority; - int stickiness; - int sort_index; - int failure_timeout; - int migration_threshold; - guint remote_reconnect_ms; - char *pending_task; - - unsigned long long flags; - - // @TODO merge these into flags - gboolean is_remote_node; - gboolean exclusive_discover; - - /* Pay special attention to whether you want to use rsc_cons_lhs and - * rsc_cons directly, which include only colocations explicitly involving - * this resource, or call libpacemaker's pcmk__with_this_colocations() and - * pcmk__this_with_colocations() functions, which may return relevant - * colocations involving the resource's ancestors as well. - */ - - //!@{ - //! This field should be treated as internal to Pacemaker - GList *rsc_cons_lhs; // List of pcmk__colocation_t* - GList *rsc_cons; // List of pcmk__colocation_t* - GList *rsc_location; // List of pe__location_t* - GList *actions; // List of pe_action_t* - GList *rsc_tickets; // List of rsc_ticket* - //!@} - - pe_node_t *allocated_to; - pe_node_t *partial_migration_target; - pe_node_t *partial_migration_source; - GList *running_on; /* pe_node_t* */ - GHashTable *known_on; /* pe_node_t* */ - GHashTable *allowed_nodes; /* pe_node_t* */ - - enum rsc_role_e role; - enum rsc_role_e next_role; - - GHashTable *meta; - GHashTable *parameters; //! \deprecated Use pe_rsc_params() instead - GHashTable *utilization; - - GList *children; /* pe_resource_t* */ - GList *dangling_migrations; /* pe_node_t* */ - - pe_resource_t *container; - GList *fillers; - - // @COMPAT These should be made const at next API compatibility break - pe_node_t *pending_node; // Node on which pending_task is happening - pe_node_t *lock_node; // Resource is shutdown-locked to this node - - time_t lock_time; // When shutdown lock started - - /* Resource parameters may have node-attribute-based rules, which means the - * values can vary by node. This table is a cache of parameter name/value - * tables for each node (as needed). Use pe_rsc_params() to get the table - * for a given node. - */ - GHashTable *parameter_cache; // Key = node name, value = parameters table -}; - -struct pe_action_s { - int id; - int priority; - - pe_resource_t *rsc; - pe_node_t *node; - xmlNode *op_entry; - - char *task; - char *uuid; - char *cancel_task; - char *reason; - - enum pe_action_flags flags; - enum rsc_start_requirement needs; - enum action_fail_response on_fail; - enum rsc_role_e fail_role; - - GHashTable *meta; - GHashTable *extra; - - /* - * These two varables are associated with the constraint logic - * that involves first having one or more actions runnable before - * then allowing this action to execute. - * - * These varables are used with features such as 'clone-min' which - * requires at minimum X number of cloned instances to be running - * before an order dependency can run. Another option that uses - * this is 'require-all=false' in ordering constrants. This option - * says "only require one instance of a resource to start before - * allowing dependencies to start" -- basically, require-all=false is - * the same as clone-min=1. - */ - - /* current number of known runnable actions in the before list. */ - int runnable_before; - /* the number of "before" runnable actions required for this action - * to be considered runnable */ - int required_runnable_before; - - GList *actions_before; /* pe_action_wrapper_t* */ - GList *actions_after; /* pe_action_wrapper_t* */ - - /* Some of the above fields could be moved to the details, - * except for API backward compatibility. - */ - void *action_details; // varies by type of action -}; - -typedef struct pe_ticket_s { - char *id; - gboolean granted; - time_t last_granted; - gboolean standby; - GHashTable *state; -} pe_ticket_t; - -typedef struct pe_tag_s { - char *id; - GList *refs; -} pe_tag_t; - -//! Internal tracking for transition graph creation -enum pe_link_state { - pe_link_not_dumped, //! Internal tracking for transition graph creation - pe_link_dumped, //! Internal tracking for transition graph creation - pe_link_dup, //! \deprecated No longer used by Pacemaker -}; - -enum pe_discover_e { - pe_discover_always = 0, - pe_discover_never, - pe_discover_exclusive, -}; - -/* *INDENT-OFF* */ -enum pe_ordering { - pe_order_none = 0x0, /* deleted */ - pe_order_optional = 0x1, /* pure ordering, nothing implied */ - pe_order_apply_first_non_migratable = 0x2, /* Only apply this constraint's ordering if first is not migratable. */ - - pe_order_implies_first = 0x10, /* If 'then' is required, ensure 'first' is too */ - pe_order_implies_then = 0x20, /* If 'first' is required, ensure 'then' is too */ - pe_order_promoted_implies_first = 0x40, /* If 'then' is required and then's rsc is promoted, ensure 'first' becomes required too */ - - /* first requires then to be both runnable and migrate runnable. */ - pe_order_implies_first_migratable = 0x80, - - pe_order_runnable_left = 0x100, /* 'then' requires 'first' to be runnable */ - - pe_order_pseudo_left = 0x200, /* 'then' can only be pseudo if 'first' is runnable */ - pe_order_implies_then_on_node = 0x400, /* If 'first' is required on 'nodeX', - * ensure instances of 'then' on 'nodeX' are too. - * Only really useful if 'then' is a clone and 'first' is not - */ - pe_order_probe = 0x800, /* If 'first->rsc' is - * - running but about to stop, ignore the constraint - * - otherwise, behave as runnable_left - */ - - pe_order_restart = 0x1000, /* 'then' is runnable if 'first' is optional or runnable */ - pe_order_stonith_stop = 0x2000, //<! \deprecated Will be removed in future release - pe_order_serialize_only = 0x4000, /* serialize */ - pe_order_same_node = 0x8000, /* applies only if 'first' and 'then' are on same node */ - - pe_order_implies_first_printed = 0x10000, /* Like ..implies_first but only ensures 'first' is printed, not mandatory */ - pe_order_implies_then_printed = 0x20000, /* Like ..implies_then but only ensures 'then' is printed, not mandatory */ - - pe_order_asymmetrical = 0x100000, /* Indicates asymmetrical one way ordering constraint. */ - pe_order_load = 0x200000, /* Only relevant if... */ - pe_order_one_or_more = 0x400000, /* 'then' is runnable only if one or more of its dependencies are too */ - pe_order_anti_colocation = 0x800000, - - pe_order_preserve = 0x1000000, /* Hack for breaking user ordering constraints with container resources */ - pe_order_then_cancels_first = 0x2000000, // if 'then' becomes required, 'first' becomes optional - pe_order_trace = 0x4000000, /* test marker */ - -#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) - // \deprecated Use pe_order_promoted_implies_first instead - pe_order_implies_first_master = pe_order_promoted_implies_first, -#endif -}; -/* *INDENT-ON* */ - -typedef struct pe_action_wrapper_s { - enum pe_ordering type; - enum pe_link_state state; - pe_action_t *action; -} pe_action_wrapper_t; - #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #include <crm/pengine/pe_types_compat.h> #endif diff --git a/include/crm/pengine/pe_types_compat.h b/include/crm/pengine/pe_types_compat.h index 6f174c4..1becd12 100644 --- a/include/crm/pengine/pe_types_compat.h +++ b/include/crm/pengine/pe_types_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2022 the Pacemaker project contributors + * Copyright 2004-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -10,7 +10,7 @@ #ifndef PCMK__CRM_PENGINE_PE_TYPES_COMPAT__H # define PCMK__CRM_PENGINE_PE_TYPES_COMPAT__H -#include <crm/pengine/pe_types.h> +#include <crm/common/scheduler.h> #ifdef __cplusplus extern "C" { @@ -25,6 +25,174 @@ extern "C" { * release. */ +//! \deprecated Use pcmk_rsc_removed instead +#define pe_rsc_orphan pcmk_rsc_removed + +//! \deprecated Use pcmk_rsc_managed instead +#define pe_rsc_managed pcmk_rsc_managed + +//! \deprecated Use pcmk_rsc_blocked instead +#define pe_rsc_block pcmk_rsc_blocked + +//! \deprecated Use pcmk_rsc_removed_filler instead +#define pe_rsc_orphan_container_filler pcmk_rsc_removed_filler + +//! \deprecated Use pcmk_rsc_notify instead +#define pe_rsc_notify pcmk_rsc_notify + +//! \deprecated Use pcmk_rsc_unique instead +#define pe_rsc_unique pcmk_rsc_unique + +//! \deprecated Use pcmk_rsc_fence_device instead +#define pe_rsc_fence_device pcmk_rsc_fence_device + +//! \deprecated Use pcmk_rsc_promotable instead +#define pe_rsc_promotable pcmk_rsc_promotable + +//! \deprecated Use pcmk_rsc_unassigned instead +#define pe_rsc_provisional pcmk_rsc_unassigned + +//! \deprecated Use pcmk_rsc_assigning instead +#define pe_rsc_allocating pcmk_rsc_assigning + +//! \deprecated Use pcmk_rsc_updating_nodes instead +#define pe_rsc_merging pcmk_rsc_updating_nodes + +//! \deprecated Use pcmk_rsc_restarting instead +#define pe_rsc_restarting pcmk_rsc_restarting + +//! \deprecated Use pcmk_rsc_stop_if_failed instead +#define pe_rsc_stop pcmk_rsc_stop_if_failed + +//! \deprecated Use pcmk_rsc_reload instead +#define pe_rsc_reload pcmk_rsc_reload + +//! \deprecated Use pcmk_rsc_remote_nesting_allowed instead +#define pe_rsc_allow_remote_remotes pcmk_rsc_remote_nesting_allowed + +//! \deprecated Use pcmk_rsc_critical instead +#define pe_rsc_critical pcmk_rsc_critical + +//! \deprecated Use pcmk_rsc_failed instead +#define pe_rsc_failed pcmk_rsc_failed + +//! \deprecated Use pcmk_rsc_detect_loop instead +#define pe_rsc_detect_loop pcmk_rsc_detect_loop + +//! \deprecated Do not use +#define pe_rsc_runnable pcmk_rsc_runnable + +//! \deprecated Use pcmk_rsc_start_pending instead +#define pe_rsc_start_pending pcmk_rsc_start_pending + +//!< \deprecated Do not use +#define pe_rsc_starting pcmk_rsc_starting + +//!< \deprecated Do not use +#define pe_rsc_stopping pcmk_rsc_stopping + +//! \deprecated Use pcmk_rsc_stop_unexpected instead +#define pe_rsc_stop_unexpected pcmk_rsc_stop_unexpected + +//! \deprecated Use pcmk_rsc_migratable instead +#define pe_rsc_allow_migrate pcmk_rsc_migratable + +//! \deprecated Use pcmk_rsc_ignore_failure instead +#define pe_rsc_failure_ignored pcmk_rsc_ignore_failure + +//! \deprecated Use pcmk_rsc_replica_container instead +#define pe_rsc_replica_container pcmk_rsc_replica_container + +//! \deprecated Use pcmk_rsc_maintenance instead +#define pe_rsc_maintenance pcmk_rsc_maintenance + +//! \deprecated Do not use +#define pe_rsc_is_container pcmk_rsc_has_filler + +//! \deprecated Use pcmk_rsc_needs_quorum instead +#define pe_rsc_needs_quorum pcmk_rsc_needs_quorum + +//! \deprecated Use pcmk_rsc_needs_fencing instead +#define pe_rsc_needs_fencing pcmk_rsc_needs_fencing + +//! \deprecated Use pcmk_rsc_needs_unfencing instead +#define pe_rsc_needs_unfencing pcmk_rsc_needs_unfencing + +//! \deprecated Use pcmk_sched_quorate instead +#define pe_flag_have_quorum pcmk_sched_quorate + +//! \deprecated Use pcmk_sched_symmetric_cluster instead +#define pe_flag_symmetric_cluster pcmk_sched_symmetric_cluster + +//! \deprecated Use pcmk_sched_in_maintenance instead +#define pe_flag_maintenance_mode pcmk_sched_in_maintenance + +//! \deprecated Use pcmk_sched_fencing_enabled instead +#define pe_flag_stonith_enabled pcmk_sched_fencing_enabled + +//! \deprecated Use pcmk_sched_have_fencing instead +#define pe_flag_have_stonith_resource pcmk_sched_have_fencing + +//! \deprecated Use pcmk_sched_enable_unfencing instead +#define pe_flag_enable_unfencing pcmk_sched_enable_unfencing + +//! \deprecated Use pcmk_sched_concurrent_fencing instead +#define pe_flag_concurrent_fencing pcmk_sched_concurrent_fencing + +//! \deprecated Use pcmk_sched_stop_removed_resources instead +#define pe_flag_stop_rsc_orphans pcmk_sched_stop_removed_resources + +//! \deprecated Use pcmk_sched_cancel_removed_actions instead +#define pe_flag_stop_action_orphans pcmk_sched_cancel_removed_actions + +//! \deprecated Use pcmk_sched_stop_all instead +#define pe_flag_stop_everything pcmk_sched_stop_all + +//! \deprecated Use pcmk_sched_start_failure_fatal instead +#define pe_flag_start_failure_fatal pcmk_sched_start_failure_fatal + +//! \deprecated Do not use +#define pe_flag_remove_after_stop pcmk_sched_remove_after_stop + +//! \deprecated Use pcmk_sched_startup_fencing instead +#define pe_flag_startup_fencing pcmk_sched_startup_fencing + +//! \deprecated Use pcmk_sched_shutdown_lock instead +#define pe_flag_shutdown_lock pcmk_sched_shutdown_lock + +//! \deprecated Use pcmk_sched_probe_resources instead +#define pe_flag_startup_probes pcmk_sched_probe_resources + +//! \deprecated Use pcmk_sched_have_status instead +#define pe_flag_have_status pcmk_sched_have_status + +//! \deprecated Use pcmk_sched_have_remote_nodes instead +#define pe_flag_have_remote_nodes pcmk_sched_have_remote_nodes + +//! \deprecated Use pcmk_sched_location_only instead +#define pe_flag_quick_location pcmk_sched_location_only + +//! \deprecated Use pcmk_sched_sanitized instead +#define pe_flag_sanitized pcmk_sched_sanitized + +//! \deprecated Do not use +#define pe_flag_stdout (1ULL << 22) + +//! \deprecated Use pcmk_sched_no_counts instead +#define pe_flag_no_counts pcmk_sched_no_counts + +//! \deprecated Use pcmk_sched_no_compat instead +#define pe_flag_no_compat pcmk_sched_no_compat + +//! \deprecated Use pcmk_sched_output_scores instead +#define pe_flag_show_scores pcmk_sched_output_scores + +//! \deprecated Use pcmk_sched_show_utilization instead +#define pe_flag_show_utilization pcmk_sched_show_utilization + +//! \deprecated Use pcmk_sched_validate_only instead +#define pe_flag_check_config pcmk_sched_validate_only + //!@{ //! \deprecated Do not use (unused by Pacemaker) enum pe_graph_flags { @@ -35,27 +203,62 @@ enum pe_graph_flags { }; //!@} -//!< \deprecated Use pe_action_t instead +//!@{ +//! \deprecated Do not use +enum pe_check_parameters { + pe_check_last_failure, + pe_check_active, +}; +//!@} + +//! \deprecated Use pcmk_action_t instead typedef struct pe_action_s action_t; -//!< \deprecated Use pe_action_wrapper_t instead +//! \deprecated Use pcmk_action_t instead +typedef struct pe_action_s pe_action_t; + +//! \deprecated Do not use typedef struct pe_action_wrapper_s action_wrapper_t; -//!< \deprecated Use pe_node_t instead +//! \deprecated Do not use +typedef struct pe_action_wrapper_s pe_action_wrapper_t; + +//! \deprecated Use pcmk_node_t instead typedef struct pe_node_s node_t; -//!< \deprecated Use enum pe_quorum_policy instead +//! \deprecated Use pcmk_node_t instead +typedef struct pe_node_s pe_node_t; + +//! \deprecated Use enum pe_quorum_policy instead typedef enum pe_quorum_policy no_quorum_policy_t; -//!< \deprecated use pe_resource_t instead +//! \deprecated use pcmk_resource_t instead typedef struct pe_resource_s resource_t; -//!< \deprecated Use pe_tag_t instead +//! \deprecated use pcmk_resource_t instead +typedef struct pe_resource_s pe_resource_t; + +//! \deprecated Use pcmk_tag_t instead typedef struct pe_tag_s tag_t; -//!< \deprecated Use pe_ticket_t instead +//! \deprecated Use pcmk_tag_t instead +typedef struct pe_tag_s pe_tag_t; + +//! \deprecated Use pcmk_ticket_t instead typedef struct pe_ticket_s ticket_t; +//! \deprecated Use pcmk_ticket_t instead +typedef struct pe_ticket_s pe_ticket_t; + +//! \deprecated Use pcmk_scheduler_t instead +typedef struct pe_working_set_s pe_working_set_t; + +//! \deprecated This type should be treated as internal to Pacemaker +typedef struct resource_alloc_functions_s resource_alloc_functions_t; + +//! \deprecated Use pcmk_rsc_methods_t instead +typedef struct resource_object_functions_s resource_object_functions_t; + #ifdef __cplusplus } #endif diff --git a/include/crm/pengine/remote_internal.h b/include/crm/pengine/remote_internal.h index 46d58fc..0e7c044 100644 --- a/include/crm/pengine/remote_internal.h +++ b/include/crm/pengine/remote_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the Pacemaker project contributors + * Copyright 2013-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -19,16 +19,17 @@ extern "C" { #include <crm/pengine/status.h> bool xml_contains_remote_node(xmlNode *xml); -bool pe__is_remote_node(const pe_node_t *node); -bool pe__is_guest_node(const pe_node_t *node); -bool pe__is_guest_or_remote_node(const pe_node_t *node); -bool pe__is_bundle_node(const pe_node_t *node); -bool pe__resource_is_remote_conn(const pe_resource_t *rsc, - const pe_working_set_t *data_set); -pe_resource_t *pe__resource_contains_guest_node(const pe_working_set_t *data_set, - const pe_resource_t *rsc); -void pe_foreach_guest_node(const pe_working_set_t *data_set, const pe_node_t *host, - void (*helper)(const pe_node_t*, void*), void *user_data); +bool pe__is_remote_node(const pcmk_node_t *node); +bool pe__is_guest_node(const pcmk_node_t *node); +bool pe__is_guest_or_remote_node(const pcmk_node_t *node); +bool pe__is_bundle_node(const pcmk_node_t *node); +bool pe__resource_is_remote_conn(const pcmk_resource_t *rsc); +pcmk_resource_t *pe__resource_contains_guest_node(const pcmk_scheduler_t *scheduler, + const pcmk_resource_t *rsc); +void pe_foreach_guest_node(const pcmk_scheduler_t *scheduler, + const pcmk_node_t *host, + void (*helper)(const pcmk_node_t*, void*), + void *user_data); xmlNode *pe_create_remote_xml(xmlNode *parent, const char *uname, const char *container_id, const char *migrateable, const char *is_managed, const char *start_timeout, diff --git a/include/crm/pengine/status.h b/include/crm/pengine/status.h index 145a166..9c85425 100644 --- a/include/crm/pengine/status.h +++ b/include/crm/pengine/status.h @@ -15,7 +15,7 @@ # include <crm/common/util.h> // pcmk_is_set() # include <crm/common/iso8601.h> # include <crm/pengine/common.h> -# include <crm/pengine/pe_types.h> // pe_node_t, pe_resource_t, etc. +# include <crm/pengine/pe_types.h> // pcmk_node_t, pcmk_resource_t, etc. # include <crm/pengine/complex.h> #ifdef __cplusplus @@ -28,24 +28,25 @@ extern "C" { * \ingroup pengine */ -const char *rsc_printable_id(const pe_resource_t *rsc); -gboolean cluster_status(pe_working_set_t * data_set); -pe_working_set_t *pe_new_working_set(void); -void pe_free_working_set(pe_working_set_t *data_set); -void set_working_set_defaults(pe_working_set_t * data_set); -void cleanup_calculations(pe_working_set_t * data_set); -void pe_reset_working_set(pe_working_set_t *data_set); -pe_resource_t *pe_find_resource(GList *rsc_list, const char *id_rh); -pe_resource_t *pe_find_resource_with_flags(GList *rsc_list, const char *id, enum pe_find flags); -pe_node_t *pe_find_node(const GList *node_list, const char *node_name); -pe_node_t *pe_find_node_id(const GList *node_list, const char *id); -pe_node_t *pe_find_node_any(const GList *node_list, const char *id, +const char *rsc_printable_id(const pcmk_resource_t *rsc); +gboolean cluster_status(pcmk_scheduler_t *scheduler); +pcmk_scheduler_t *pe_new_working_set(void); +void pe_free_working_set(pcmk_scheduler_t *scheduler); +void set_working_set_defaults(pcmk_scheduler_t *scheduler); +void cleanup_calculations(pcmk_scheduler_t *scheduler); +void pe_reset_working_set(pcmk_scheduler_t *scheduler); +pcmk_resource_t *pe_find_resource(GList *rsc_list, const char *id_rh); +pcmk_resource_t *pe_find_resource_with_flags(GList *rsc_list, const char *id, + enum pe_find flags); +pcmk_node_t *pe_find_node(const GList *node_list, const char *node_name); +pcmk_node_t *pe_find_node_id(const GList *node_list, const char *id); +pcmk_node_t *pe_find_node_any(const GList *node_list, const char *id, const char *node_name); GList *find_operations(const char *rsc, const char *node, gboolean active_filter, - pe_working_set_t * data_set); + pcmk_scheduler_t *scheduler); void calculate_active_ops(const GList *sorted_op_list, int *start_index, int *stop_index); -int pe_bundle_replicas(const pe_resource_t *rsc); +int pe_bundle_replicas(const pcmk_resource_t *rsc); /*! * \brief Check whether a resource is any clone type @@ -55,9 +56,9 @@ int pe_bundle_replicas(const pe_resource_t *rsc); * \return true if resource is clone, false otherwise */ static inline bool -pe_rsc_is_clone(const pe_resource_t *rsc) +pe_rsc_is_clone(const pcmk_resource_t *rsc) { - return rsc && (rsc->variant == pe_clone); + return (rsc != NULL) && (rsc->variant == pcmk_rsc_variant_clone); } /*! @@ -68,9 +69,9 @@ pe_rsc_is_clone(const pe_resource_t *rsc) * \return true if resource is unique clone, false otherwise */ static inline bool -pe_rsc_is_unique_clone(const pe_resource_t *rsc) +pe_rsc_is_unique_clone(const pcmk_resource_t *rsc) { - return pe_rsc_is_clone(rsc) && pcmk_is_set(rsc->flags, pe_rsc_unique); + return pe_rsc_is_clone(rsc) && pcmk_is_set(rsc->flags, pcmk_rsc_unique); } /*! @@ -81,9 +82,9 @@ pe_rsc_is_unique_clone(const pe_resource_t *rsc) * \return true if resource is anonymous clone, false otherwise */ static inline bool -pe_rsc_is_anon_clone(const pe_resource_t *rsc) +pe_rsc_is_anon_clone(const pcmk_resource_t *rsc) { - return pe_rsc_is_clone(rsc) && !pcmk_is_set(rsc->flags, pe_rsc_unique); + return pe_rsc_is_clone(rsc) && !pcmk_is_set(rsc->flags, pcmk_rsc_unique); } /*! @@ -94,7 +95,7 @@ pe_rsc_is_anon_clone(const pe_resource_t *rsc) * \return true if resource is part of a bundle, false otherwise */ static inline bool -pe_rsc_is_bundled(const pe_resource_t *rsc) +pe_rsc_is_bundled(const pcmk_resource_t *rsc) { if (rsc == NULL) { return false; @@ -102,7 +103,7 @@ pe_rsc_is_bundled(const pe_resource_t *rsc) while (rsc->parent != NULL) { rsc = rsc->parent; } - return rsc->variant == pe_container; + return rsc->variant == pcmk_rsc_variant_bundle; } #ifdef __cplusplus diff --git a/include/crm/services_compat.h b/include/crm/services_compat.h index 97310f4..456d351 100644 --- a/include/crm/services_compat.h +++ b/include/crm/services_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 the Pacemaker project contributors + * Copyright 2010-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -10,7 +10,7 @@ #ifndef PCMK__CRM_SERVICES_COMPAT__H # define PCMK__CRM_SERVICES_COMPAT__H - +#include <crm/common/actions.h> #include <crm/common/results.h> #include <crm/services.h> #include <glib.h> @@ -68,7 +68,8 @@ static inline enum ocf_exitcode services_get_ocf_exitcode(const char *action, int lsb_exitcode) { /* For non-status actions, LSB and OCF share error code meaning <= 7 */ - if (action && strcmp(action, "status") && strcmp(action, "monitor")) { + if ((action != NULL) && (strcmp(action, PCMK_ACTION_STATUS) != 0) + && (strcmp(action, PCMK_ACTION_MONITOR) != 0)) { if ((lsb_exitcode < 0) || (lsb_exitcode > PCMK_LSB_NOT_RUNNING)) { return PCMK_OCF_UNKNOWN_ERROR; } diff --git a/include/crm_internal.h b/include/crm_internal.h index 5f6531f..71a0f7e 100644 --- a/include/crm_internal.h +++ b/include/crm_internal.h @@ -81,9 +81,14 @@ #define PCMK__XA_CONFIG_ERRORS "config-errors" #define PCMK__XA_CONFIG_WARNINGS "config-warnings" #define PCMK__XA_CONFIRM "confirm" +#define PCMK__XA_CRMD "crmd" +#define PCMK__XA_EXPECTED "expected" #define PCMK__XA_GRAPH_ERRORS "graph-errors" #define PCMK__XA_GRAPH_WARNINGS "graph-warnings" +#define PCMK__XA_IN_CCM "in_ccm" +#define PCMK__XA_JOIN "join" #define PCMK__XA_MODE "mode" +#define PCMK__XA_NODE_START_STATE "node_start_state" #define PCMK__XA_TASK "task" #define PCMK__XA_UPTIME "uptime" #define PCMK__XA_CONN_HOST "connection_host" diff --git a/include/pacemaker-internal.h b/include/pacemaker-internal.h index 8610d1e..9e6ff21 100644 --- a/include/pacemaker-internal.h +++ b/include/pacemaker-internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 the Pacemaker project contributors + * Copyright 2019-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -11,14 +11,13 @@ # define PACEMAKER_INTERNAL__H # include <pcmki/pcmki_acl.h> +# include <pcmki/pcmki_agents.h> # include <pcmki/pcmki_cluster_queries.h> # include <pcmki/pcmki_fence.h> # include <pcmki/pcmki_output.h> # include <pcmki/pcmki_resource.h> # include <pcmki/pcmki_result_code.h> # include <pcmki/pcmki_rule.h> -# include <pcmki/pcmki_sched_allocate.h> -# include <pcmki/pcmki_sched_utils.h> # include <pcmki/pcmki_scheduler.h> # include <pcmki/pcmki_simulate.h> # include <pcmki/pcmki_status.h> diff --git a/include/pacemaker.h b/include/pacemaker.h index f5c375a..ffa99ff 100644 --- a/include/pacemaker.h +++ b/include/pacemaker.h @@ -12,8 +12,8 @@ # include <glib.h> # include <libxml/tree.h> +# include <crm/common/scheduler.h> # include <crm/cib/cib_types.h> -# include <crm/pengine/pe_types.h> # include <crm/stonith-ng.h> @@ -202,13 +202,13 @@ int pcmk_pacemakerd_status(xmlNodePtr *xml, const char *ipc_name, * \param[in,out] rsc Resource to calculate digests for * \param[in] node Node whose operation history should be used * \param[in] overrides Hash table of configuration parameters to override - * \param[in] data_set Cluster working set (with status) + * \param[in] scheduler Scheduler data (with status) * * \return Standard Pacemaker return code */ -int pcmk_resource_digests(xmlNodePtr *xml, pe_resource_t *rsc, - const pe_node_t *node, GHashTable *overrides, - pe_working_set_t *data_set); +int pcmk_resource_digests(xmlNodePtr *xml, pcmk_resource_t *rsc, + const pcmk_node_t *node, GHashTable *overrides, + pcmk_scheduler_t *scheduler); /*! * \brief Simulate a cluster's response to events @@ -219,7 +219,7 @@ int pcmk_resource_digests(xmlNodePtr *xml, pe_resource_t *rsc, * simulation. Output can be modified with various flags. * * \param[in,out] xml The destination for the result, as an XML tree - * \param[in,out] data_set Working set for the cluster + * \param[in,out] scheduler Scheduler data * \param[in] injections A structure containing cluster events * (node up/down, tickets, injected operations) * \param[in] flags A bitfield of :pcmk_sim_flags to modify @@ -238,7 +238,7 @@ int pcmk_resource_digests(xmlNodePtr *xml, pe_resource_t *rsc, * * \return Standard Pacemaker return code */ -int pcmk_simulate(xmlNodePtr *xml, pe_working_set_t *data_set, +int pcmk_simulate(xmlNodePtr *xml, pcmk_scheduler_t *scheduler, const pcmk_injections_t *injections, unsigned int flags, unsigned int section_opts, const char *use_date, const char *input_file, const char *graph_file, @@ -337,6 +337,45 @@ int pcmk_show_result_code(xmlNodePtr *xml, int code, enum pcmk_result_type type, int pcmk_list_result_codes(xmlNodePtr *xml, enum pcmk_result_type type, uint32_t flags); +/*! + * \brief List available providers for the given OCF agent + * + * \param[in,out] xml The destination for the result, as an XML tree + * \param[in] agent_spec Resource agent name + * + * \return Standard Pacemaker return code + */ +int pcmk_list_alternatives(xmlNodePtr *xml, const char *agent_spec); + +/*! + * \brief List all agents available for the named standard and/or provider + * + * \param[in,out] xml The destination for the result, as an XML tree + * \param[in] agent_spec STD[:PROV] + * + * \return Standard Pacemaker return code + */ +int pcmk_list_agents(xmlNodePtr *xml, char *agent_spec); + +/*! + * \brief List all available OCF providers for the given agent + * + * \param[in,out] xml The destination for the result, as an XML tree + * \param[in] agent_spec Resource agent name + * + * \return Standard Pacemaker return code + */ +int pcmk_list_providers(xmlNodePtr *xml, const char *agent_spec); + +/*! + * \brief List all available resource agent standards + * + * \param[in,out] xml The destination for the result, as an XML tree + * + * \return Standard Pacemaker return code + */ +int pcmk_list_standards(xmlNodePtr *xml); + #ifdef BUILD_PUBLIC_LIBPACEMAKER /*! diff --git a/include/pcmki/Makefile.am b/include/pcmki/Makefile.am index b379fdb..b9475af 100644 --- a/include/pcmki/Makefile.am +++ b/include/pcmki/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2019-2022 the Pacemaker project contributors +# Copyright 2019-2023 the Pacemaker project contributors # # The version control history for this file may have further details. # @@ -9,18 +9,6 @@ MAINTAINERCLEANFILES = Makefile.in -noinst_HEADERS = pcmki_acl.h \ - pcmki_cluster_queries.h \ - pcmki_fence.h \ - pcmki_output.h \ - pcmki_resource.h \ - pcmki_result_code.h \ - pcmki_rule.h \ - pcmki_sched_allocate.h \ - pcmki_sched_utils.h \ - pcmki_scheduler.h \ - pcmki_simulate.h \ - pcmki_status.h \ - pcmki_transition.h +noinst_HEADERS = $(wildcard *.h) .PHONY: $(ARCHIVE_VERSION) diff --git a/include/pcmki/pcmki_agents.h b/include/pcmki/pcmki_agents.h new file mode 100644 index 0000000..eefe3e5 --- /dev/null +++ b/include/pcmki/pcmki_agents.h @@ -0,0 +1,19 @@ +/* + * Copyright 2023 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 PCMK__PCMKI_PCMKI_AGENTS__H +#define PCMK__PCMKI_PCMKI_AGENTS__H + +#include <crm/common/output_internal.h> + +int pcmk__list_alternatives(pcmk__output_t *out, const char *agent_spec); +int pcmk__list_agents(pcmk__output_t *out, char *agent_spec); +int pcmk__list_providers(pcmk__output_t *out, const char *agent_spec); +int pcmk__list_standards(pcmk__output_t *out); + +#endif /* PCMK__PCMKI_PCMKI_AGENTS__H */ diff --git a/include/pcmki/pcmki_cluster_queries.h b/include/pcmki/pcmki_cluster_queries.h index 776aa27..3fa4c23 100644 --- a/include/pcmki/pcmki_cluster_queries.h +++ b/include/pcmki/pcmki_cluster_queries.h @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 the Pacemaker project contributors + * Copyright 2020-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -10,7 +10,8 @@ #ifndef PCMK__PCMKI_PCMKI_CLUSTER_QUERIES__H # define PCMK__PCMKI_PCMKI_CLUSTER_QUERIES__H -#include <glib.h> // gboolean, GMainLoop, etc. +#include <stdbool.h> +#include <stdint.h> #include <crm/crm.h> #include <crm/common/output_internal.h> @@ -19,7 +20,7 @@ // CIB queries int pcmk__list_nodes(pcmk__output_t *out, const char *node_types, - gboolean bash_export); + bool bash_export); // Controller queries int pcmk__controller_status(pcmk__output_t *out, const char *node_name, diff --git a/include/pcmki/pcmki_resource.h b/include/pcmki/pcmki_resource.h index dc8ac69..442bb1f 100644 --- a/include/pcmki/pcmki_resource.h +++ b/include/pcmki/pcmki_resource.h @@ -1,5 +1,5 @@ /* - * Copyright 2021-2022 the Pacemaker project contributors + * Copyright 2021-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -11,10 +11,10 @@ #include <glib.h> +#include <crm/common/scheduler.h> #include <crm/common/output_internal.h> -#include <crm/pengine/pe_types.h> -int pcmk__resource_digests(pcmk__output_t *out, pe_resource_t *rsc, - const pe_node_t *node, GHashTable *overrides); +int pcmk__resource_digests(pcmk__output_t *out, pcmk_resource_t *rsc, + const pcmk_node_t *node, GHashTable *overrides); #endif /* PCMK__PCMKI_PCMKI_RESOURCE__H */ diff --git a/include/pcmki/pcmki_sched_allocate.h b/include/pcmki/pcmki_sched_allocate.h deleted file mode 100644 index 32044ea..0000000 --- a/include/pcmki/pcmki_sched_allocate.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2004-2023 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 PCMK__PCMKI_PCMKI_SCHED_ALLOCATE__H -# define PCMK__PCMKI_PCMKI_SCHED_ALLOCATE__H - -# include <glib.h> -# include <crm/common/xml.h> -# include <crm/pengine/status.h> -# include <crm/pengine/complex.h> -# include <crm/common/xml_internal.h> -# include <crm/pengine/internal.h> -# include <crm/common/xml.h> -# include <pcmki/pcmki_scheduler.h> - -pe_node_t *pcmk__bundle_allocate(pe_resource_t *rsc, const pe_node_t *prefer); -void pcmk__bundle_create_actions(pe_resource_t *rsc); -bool pcmk__bundle_create_probe(pe_resource_t *rsc, pe_node_t *node); -void pcmk__bundle_internal_constraints(pe_resource_t *rsc); -void pcmk__bundle_rsc_location(pe_resource_t *rsc, pe__location_t *constraint); -enum pe_action_flags pcmk__bundle_action_flags(pe_action_t *action, - const pe_node_t *node); -void pcmk__bundle_expand(pe_resource_t *rsc); -void pcmk__bundle_add_utilization(const pe_resource_t *rsc, - const pe_resource_t *orig_rsc, - GList *all_rscs, GHashTable *utilization); -void pcmk__bundle_shutdown_lock(pe_resource_t *rsc); - -void clone_create_actions(pe_resource_t *rsc); -void clone_internal_constraints(pe_resource_t *rsc); -void clone_rsc_location(pe_resource_t *rsc, pe__location_t *constraint); -enum pe_action_flags clone_action_flags(pe_action_t *action, - const pe_node_t *node); -void clone_expand(pe_resource_t *rsc); -bool clone_create_probe(pe_resource_t *rsc, pe_node_t *node); -void clone_append_meta(const pe_resource_t *rsc, xmlNode *xml); -void pcmk__clone_add_utilization(const pe_resource_t *rsc, - const pe_resource_t *orig_rsc, - GList *all_rscs, GHashTable *utilization); -void pcmk__clone_shutdown_lock(pe_resource_t *rsc); - -void pcmk__log_transition_summary(const char *filename); - -#endif diff --git a/include/pcmki/pcmki_sched_utils.h b/include/pcmki/pcmki_sched_utils.h deleted file mode 100644 index 3e6d52f..0000000 --- a/include/pcmki/pcmki_sched_utils.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2004-2023 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 PCMK__PCMKI_PCMKI_SCHED_UTILS__H -# define PCMK__PCMKI_PCMKI_SCHED_UTILS__H - -#include <stdbool.h> // bool -#include <glib.h> // GList, GHashTable, gboolean, guint -#include <crm/lrmd.h> // lrmd_event_data_t -#include <crm/cib.h> // cib_t -#include <crm/pengine/pe_types.h> -#include <crm/common/xml_internal.h> -#include <crm/pengine/internal.h> -#include <pcmki/pcmki_scheduler.h> -#include <pcmki/pcmki_transition.h> -#include <pacemaker.h> - -/* Constraint helper functions */ -GList *pcmk__copy_node_list(const GList *list, bool reset); - -int copies_per_node(pe_resource_t * rsc); - -xmlNode *pcmk__create_history_xml(xmlNode *parent, lrmd_event_data_t *event, - const char *caller_version, int target_rc, - const char *node, const char *origin); - -#endif diff --git a/include/pcmki/pcmki_scheduler.h b/include/pcmki/pcmki_scheduler.h index dde50a5..9adb9a9 100644 --- a/include/pcmki/pcmki_scheduler.h +++ b/include/pcmki/pcmki_scheduler.h @@ -8,36 +8,37 @@ */ #ifndef PCMK__PCMKI_PCMKI_SCHEDULER__H -# define PCMK__PCMKI_PCMKI_SCHEDULER__H +#define PCMK__PCMKI_PCMKI_SCHEDULER__H -# include <glib.h> -# include <crm/crm.h> -# include <crm/common/iso8601.h> -# include <crm/pengine/rules.h> -# include <crm/pengine/common.h> -# include <crm/pengine/status.h> +#include <glib.h> // GList +#include <stdbool.h> // bool +#include <libxml/tree.h> // xmlNode -# include <crm/pengine/complex.h> +#include <crm/lrmd_events.h> // lrmd_event_data_t +#include <crm/pengine/status.h> // pcmk_resource_t, pcmk_scheduler_t typedef struct { const char *id; const char *node_attribute; - pe_resource_t *dependent; // The resource being colocated - pe_resource_t *primary; // The resource the dependent is colocated with + pcmk_resource_t *dependent; // The resource being colocated + pcmk_resource_t *primary; // The resource the dependent is colocated with int dependent_role; // Colocation applies only if dependent has this role int primary_role; // Colocation applies only if primary has this role int score; - bool influence; // Whether dependent influences active primary placement + uint32_t flags; // Group of enum pcmk__coloc_flags } pcmk__colocation_t; -void pcmk__unpack_constraints(pe_working_set_t *data_set); +void pcmk__unpack_constraints(pcmk_scheduler_t *scheduler); void pcmk__schedule_actions(xmlNode *cib, unsigned long long flags, - pe_working_set_t *data_set); + pcmk_scheduler_t *scheduler); -GList *pcmk__with_this_colocations(const pe_resource_t *rsc); -GList *pcmk__this_with_colocations(const pe_resource_t *rsc); +GList *pcmk__copy_node_list(const GList *list, bool reset); + +xmlNode *pcmk__create_history_xml(xmlNode *parent, lrmd_event_data_t *event, + const char *caller_version, int target_rc, + const char *node, const char *origin); #endif diff --git a/include/pcmki/pcmki_simulate.h b/include/pcmki/pcmki_simulate.h index 0b09903..ab73411 100644 --- a/include/pcmki/pcmki_simulate.h +++ b/include/pcmki/pcmki_simulate.h @@ -1,5 +1,5 @@ /* - * Copyright 2021-2022 the Pacemaker project contributors + * Copyright 2021-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -11,7 +11,7 @@ # define PCMK__PCMKI_PCMKI_SIMULATE__H #include <crm/common/output_internal.h> -#include <crm/pengine/pe_types.h> +#include <crm/common/scheduler.h> #include <pcmki/pcmki_transition.h> #include <crm/cib.h> // cib_t #include <pacemaker.h> @@ -24,28 +24,28 @@ * CIB file in a given directory, printing the profiling timings for * each. * - * \note \p data_set->priv must have been set to a valid \p pcmk__output_t + * \note \p scheduler->priv must have been set to a valid \p pcmk__output_t * object before this function is called. * - * \param[in] dir A directory full of CIB files to be profiled - * \param[in] repeat Number of times to run on each input file - * \param[in,out] data_set Working set for the cluster - * \param[in] use_date The date to set the cluster's time to (may be NULL) + * \param[in] dir A directory full of CIB files to be profiled + * \param[in] repeat Number of times to run on each input file + * \param[in,out] scheduler Scheduler data + * \param[in] use_date The date to set the cluster's time to (may be NULL) */ -void pcmk__profile_dir(const char *dir, long long repeat, pe_working_set_t *data_set, - const char *use_date); +void pcmk__profile_dir(const char *dir, long long repeat, + pcmk_scheduler_t *scheduler, const char *use_date); /*! * \internal * \brief Simulate executing a transition * - * \param[in,out] data_set Cluster working set + * \param[in,out] scheduler Scheduler data * \param[in,out] cib CIB object for scheduler input * \param[in] op_fail_list List of actions to simulate as failing * * \return Transition status after simulated execution */ -enum pcmk__graph_status pcmk__simulate_transition(pe_working_set_t *data_set, +enum pcmk__graph_status pcmk__simulate_transition(pcmk_scheduler_t *scheduler, cib_t *cib, const GList *op_fail_list); @@ -58,7 +58,7 @@ enum pcmk__graph_status pcmk__simulate_transition(pe_working_set_t *data_set, * optionally writes out a variety of artifacts to show the results of the * simulation. Output can be modified with various flags. * - * \param[in,out] data_set Working set for the cluster + * \param[in,out] scheduler Scheduler data * \param[in,out] out The output functions structure * \param[in] injections A structure containing cluster events * (node up/down, tickets, injected operations) @@ -80,7 +80,7 @@ enum pcmk__graph_status pcmk__simulate_transition(pe_working_set_t *data_set, * * \return Standard Pacemaker return code */ -int pcmk__simulate(pe_working_set_t *data_set, pcmk__output_t *out, +int pcmk__simulate(pcmk_scheduler_t *scheduler, pcmk__output_t *out, const pcmk_injections_t *injections, unsigned int flags, uint32_t section_opts, const char *use_date, const char *input_file, const char *graph_file, diff --git a/include/pcmki/pcmki_status.h b/include/pcmki/pcmki_status.h index 6b48069..01139bb 100644 --- a/include/pcmki/pcmki_status.h +++ b/include/pcmki/pcmki_status.h @@ -13,7 +13,7 @@ #include <stdint.h> #include <crm/cib/cib_types.h> -#include <crm/pengine/pe_types.h> +#include <crm/common/scheduler.h> #include <crm/common/ipc_pacemakerd.h> #include <crm/common/output_internal.h> #include <pcmki/pcmki_fence.h> @@ -26,8 +26,8 @@ extern "C" { * \internal * \brief Print one-line status suitable for use with monitoring software * - * \param[in,out] out Output object - * \param[in] data_set Cluster working set + * \param[in,out] out Output object + * \param[in] scheduler Scheduler data * * \return Standard Pacemaker return code * @@ -39,7 +39,7 @@ extern "C" { * callers should be added. */ int pcmk__output_simple_status(pcmk__output_t *out, - const pe_working_set_t *data_set); + const pcmk_scheduler_t *scheduler); int pcmk__output_cluster_status(pcmk__output_t *out, stonith_t *stonith, cib_t *cib, xmlNode *current_cib, diff --git a/include/pcmki/pcmki_transition.h b/include/pcmki/pcmki_transition.h index 5dc3101..93237ed 100644 --- a/include/pcmki/pcmki_transition.h +++ b/include/pcmki/pcmki_transition.h @@ -14,6 +14,7 @@ # include <crm/crm.h> # include <crm/msg_xml.h> # include <crm/common/xml.h> +# include <crm/lrmd_events.h> // lrmd_event_data_t #ifdef __cplusplus extern "C" { @@ -164,6 +165,7 @@ void pcmk__free_graph(pcmk__graph_t *graph); const char *pcmk__graph_status2text(enum pcmk__graph_status state); void pcmk__log_graph(unsigned int log_level, pcmk__graph_t *graph); void pcmk__log_graph_action(int log_level, pcmk__graph_action_t *action); +void pcmk__log_transition_summary(const char *filename); lrmd_event_data_t *pcmk__event_from_graph_action(const xmlNode *resource, const pcmk__graph_action_t *action, int status, int rc, diff --git a/include/portability.h b/include/portability.h index 932642d..368f887 100644 --- a/include/portability.h +++ b/include/portability.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2021 the Pacemaker project contributors + * Copyright 2001-2023 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -27,45 +27,6 @@ # endif # endif -/* Prototypes for libreplace functions */ - -# ifndef HAVE_DAEMON - /* We supply a replacement function, but need a prototype */ -int daemon(int nochdir, int noclose); -# endif - -# ifndef HAVE_SETENV - /* We supply a replacement function, but need a prototype */ -int setenv(const char *name, const char *value, int why); -# endif - -# ifndef HAVE_STRERROR - /* We supply a replacement function, but need a prototype */ -char *strerror(int errnum); -# endif - -# ifndef HAVE_STRCHRNUL - /* We supply a replacement function, but need a prototype */ -char *strchrnul(const char *s, int c_in); -# endif - -# ifndef HAVE_ALPHASORT -# include <dirent.h> -int alphasort(const void *dirent1, const void *dirent2); -# endif - -# ifndef HAVE_STRNLEN -size_t strnlen(const char *s, size_t maxlen); -# else -# define USE_GNU -# endif - -# ifndef HAVE_STRNDUP -char *strndup(const char *str, size_t len); -# else -# define USE_GNU -# endif - # if HAVE_DBUS # ifndef HAVE_DBUSBASICVALUE # include <stdint.h> |