diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 13:39:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 13:39:28 +0000 |
commit | 924f5ea83e48277e014ebf0d19a27187cb93e2f7 (patch) | |
tree | 75920a275bba045f6d108204562c218a9a26ea15 /include/crm/common | |
parent | Adding upstream version 2.1.7. (diff) | |
download | pacemaker-924f5ea83e48277e014ebf0d19a27187cb93e2f7.tar.xz pacemaker-924f5ea83e48277e014ebf0d19a27187cb93e2f7.zip |
Adding upstream version 2.1.8~rc1.upstream/2.1.8_rc1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/crm/common')
76 files changed, 3902 insertions, 1068 deletions
diff --git a/include/crm/common/Makefile.am b/include/crm/common/Makefile.am index 83a4197..4d2055f 100644 --- a/include/crm/common/Makefile.am +++ b/include/crm/common/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2004-2023 the Pacemaker project contributors +# Copyright 2004-2024 the Pacemaker project contributors # # The version control history for this file may have further details. # @@ -27,18 +27,26 @@ header_HEADERS = acl.h \ mainloop_compat.h \ nodes.h \ nvpair.h \ + options.h \ output.h \ resources.h \ results.h \ results_compat.h \ roles.h \ + rules.h \ scheduler.h \ scheduler_types.h \ + schemas.h \ + scores.h \ + scores_compat.h \ tags.h \ tickets.h \ util.h \ util_compat.h \ xml.h \ - xml_compat.h + xml_compat.h \ + xml_io.h \ + xml_io_compat.h \ + xml_names.h noinst_HEADERS = $(wildcard *internal.h) diff --git a/include/crm/common/acl.h b/include/crm/common/acl.h index 655ad55..f8f4b68 100644 --- a/include/crm/common/acl.h +++ b/include/crm/common/acl.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2022 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,10 +8,10 @@ */ #ifndef PCMK__CRM_COMMON_ACL__H -# define PCMK__CRM_COMMON_ACL__H +#define PCMK__CRM_COMMON_ACL__H -# include <libxml/tree.h> // xmlNode -# include <stdbool.h> +#include <libxml/tree.h> // xmlNode +#include <stdbool.h> #ifdef __cplusplus extern "C" { diff --git a/include/crm/common/acl_internal.h b/include/crm/common/acl_internal.h index ca67d68..8512407 100644 --- a/include/crm/common/acl_internal.h +++ b/include/crm/common/acl_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 the Pacemaker project contributors + * Copyright 2015-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -10,7 +10,10 @@ #ifndef CRM_COMMON_ACL_INTERNAL__H #define CRM_COMMON_ACL_INTERNAL__H -#include <string.h> // strcmp() +#include <string.h> // strcmp() +#include <libxml/tree.h> // xmlNode + +#include <crm/common/xml_internal.h> // enum xml_private_flags /* internal ACL-related utilities */ diff --git a/include/crm/common/action_relation_internal.h b/include/crm/common/action_relation_internal.h index e789131..1401f9d 100644 --- a/include/crm/common/action_relation_internal.h +++ b/include/crm/common/action_relation_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 the Pacemaker project contributors + * Copyright 2023-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,10 @@ */ #ifndef PCMK__CRM_COMMON_ACTION_RELATION_INTERNAL__H -# define PCMK__CRM_COMMON_ACTION_RELATION_INTERNAL__H +#define PCMK__CRM_COMMON_ACTION_RELATION_INTERNAL__H + +#include <stdint.h> // uint32_t +#include <crm/common/scheduler_types.h> // pcmk_resource_t, pcmk_action_t /*! * Flags to indicate the relationship between two actions @@ -127,6 +130,50 @@ enum pcmk__action_relation_flags { pcmk__ar_then_cancels_first = (1U << 25), }; +/* Action relation object + * + * The most common type of relation is an ordering, in which case action1 etc. + * refers to the "first" action, and action2 etc. refers to the "then" action. + */ +typedef struct { + int id; // Counter to identify relation + uint32_t flags; // Group of enum pcmk__action_relation_flags + pcmk_resource_t *rsc1; // Resource for first action, if any + pcmk_action_t *action1; // First action in relation + char *task1; // Action name or key for first action + pcmk_resource_t *rsc2; // Resource for second action, if any + pcmk_action_t *action2; // Second action in relation + char *task2; // Action name or key for second action +} pcmk__action_relation_t; + typedef struct pe_action_wrapper_s pcmk__related_action_t; +/*! + * \internal + * \brief Set action relation flags + * + * \param[in,out] ar_flags Flag group to modify + * \param[in] flags_to_set enum pcmk__action_relation_flags to set + */ +#define pcmk__set_relation_flags(ar_flags, flags_to_set) do { \ + ar_flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ + "Action relation", "constraint", \ + ar_flags, (flags_to_set), \ + #flags_to_set); \ + } while (0) + +/*! + * \internal + * \brief Clear action relation flags + * + * \param[in,out] ar_flags Flag group to modify + * \param[in] flags_to_clear enum pcmk__action_relation_flags to clear + */ +#define pcmk__clear_relation_flags(ar_flags, flags_to_clear) do { \ + ar_flags = pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, \ + "Action relation", "constraint", \ + ar_flags, (flags_to_clear), \ + #flags_to_clear); \ + } while (0) + #endif // PCMK__CRM_COMMON_ACTION_RELATION_INTERNAL__H diff --git a/include/crm/common/actions.h b/include/crm/common/actions.h index 5d2784d..899aa8b 100644 --- a/include/crm/common/actions.h +++ b/include/crm/common/actions.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -54,6 +54,7 @@ extern "C" { #define PCMK_ACTION_LOAD_STOPPED "load_stopped" #define PCMK_ACTION_MAINTENANCE_NODES "maintenance_nodes" #define PCMK_ACTION_META_DATA "meta-data" +#define PCMK_ACTION_METADATA "metadata" #define PCMK_ACTION_MIGRATE_FROM "migrate_from" #define PCMK_ACTION_MIGRATE_TO "migrate_to" #define PCMK_ACTION_MONITOR "monitor" @@ -75,77 +76,57 @@ extern "C" { #define PCMK_ACTION_STOPPED "stopped" #define PCMK_ACTION_VALIDATE_ALL "validate-all" -//! Possible actions (including some pseudo-actions) +// Possible actions (including some pseudo-actions) +// @COMPAT Make this internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) enum action_tasks { - pcmk_action_unspecified = 0, //!< Unspecified or unknown action - pcmk_action_monitor, //!< Monitor + 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_stop, // Stop + pcmk_action_stopped, // Stop completed - pcmk_action_start, //!< Start - pcmk_action_started, //!< Start completed + pcmk_action_start, // Start + pcmk_action_started, // Start completed - pcmk_action_notify, //!< Notify - pcmk_action_notified, //!< Notify completed + pcmk_action_notify, // Notify + pcmk_action_notified, // Notify completed - pcmk_action_promote, //!< Promote - pcmk_action_promoted, //!< Promoted + pcmk_action_promote, // Promote + pcmk_action_promoted, // Promoted - pcmk_action_demote, //!< Demote - pcmk_action_demoted, //!< Demoted + pcmk_action_demote, // Demote + pcmk_action_demoted, // Demoted - pcmk_action_shutdown, //!< Shut down node - pcmk_action_fence, //!< Fence node + 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 +// Possible responses to a resource action failure +// @COMPAT Make this internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) 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 @@ -160,33 +141,33 @@ enum action_fail_response { */ // @TODO Define as 10 - pcmk_on_fail_ignore = 0, //!< Act as if failure didn't happen + pcmk_on_fail_ignore = 0, // Act as if failure didn't happen // @TODO Define as 30 - pcmk_on_fail_restart = 1, //!< Restart resource + pcmk_on_fail_restart = 1, // Restart resource // @TODO Define as 60 - pcmk_on_fail_ban = 2, //!< Ban resource from current node + pcmk_on_fail_ban = 2, // Ban resource from current node // @TODO Define as 70 - pcmk_on_fail_block = 3, //!< Treat resource as unmanaged + pcmk_on_fail_block = 3, // Treat resource as unmanaged // @TODO Define as 80 - pcmk_on_fail_stop = 4, //!< Stop resource and leave stopped + 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 + 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 + 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 + 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). @@ -194,139 +175,95 @@ enum action_fail_response { pcmk_on_fail_reset_remote = 8, // @TODO Define as 20 - pcmk_on_fail_demote = 9, //!< Demote if promotable, else stop + 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 +// Action scheduling flags +// @COMPAT Make this internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) enum pe_action_flags { - //! No action flags set (compare with equality rather than bit set) + // No action flags set (compare with equality rather than bit set) pcmk_no_action_flags = 0, - //! Whether action does not require invoking an agent + // Whether action does not require invoking an agent pcmk_action_pseudo = (1 << 0), - //! Whether action is runnable + // Whether action is runnable pcmk_action_runnable = (1 << 1), - //! Whether action should not be executed + // Whether action should not be executed pcmk_action_optional = (1 << 2), - //! Whether action should be added to transition graph even if optional + // 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 + // 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 + // Whether action is allowed to be part of a live migration pcmk_action_migratable = (1 << 7), - //! Whether action has been added to transition graph + // 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 + // 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) + * (used to implement ordering after clones with \c PCMK_META_CLONE_MIN + * configured, and ordered sets with \c PCMK_XA_REQUIRE_ALL set to + * \c PCMK_VALUE_FALSE). */ pcmk_action_min_runnable = (1 << 12), - //! Whether action is recurring monitor that must be rescheduled if active + // 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 + // 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 + // 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 + // 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 @@ -386,40 +323,43 @@ struct pe_action_wrapper_s { }; //!@} -//! Implementation of pcmk_action_t +// Implementation of pcmk_action_t +// @COMPAT Make this internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) struct pe_action_s { - int id; //!< Counter to identify action + 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 + 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 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 + 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 + 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. @@ -427,15 +367,28 @@ struct pe_action_s { 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 + GList *actions_before; + GList *actions_after; /* 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 + void *action_details; }; +//!@} + +// @COMPAT Make this internal when we can break API backward compatibility +//! \deprecated Do not use (public access will be removed in a future release) +const char *pcmk_action_text(enum action_tasks action); + +// @COMPAT Make this internal when we can break API backward compatibility +//! \deprecated Do not use (public access will be removed in a future release) +enum action_tasks pcmk_parse_action(const char *action_name); + +// @COMPAT Make this internal when we can break API backward compatibility +//! \deprecated Do not use (public access will be removed in a future release) +const char *pcmk_on_fail_text(enum action_fail_response on_fail); // For parsing various action-related string specifications gboolean parse_op_key(const char *key, char **rsc_id, char **op_type, diff --git a/include/crm/common/actions_internal.h b/include/crm/common/actions_internal.h index 7e794e6..4a148f0 100644 --- a/include/crm/common/actions_internal.h +++ b/include/crm/common/actions_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -21,9 +21,78 @@ extern "C" { #endif +// Action names as strings + +// @COMPAT Deprecated since 2.0.0 +#define PCMK__ACTION_POWEROFF "poweroff" + + //! printf-style format to create operation key from resource, action, interval #define PCMK__OP_FMT "%s_%s_%u" +/*! + * \internal + * \brief Set action flags for an action + * + * \param[in,out] action Action to set flags for + * \param[in] flags_to_set Group of enum pe_action_flags to set + */ +#define pcmk__set_action_flags(action, flags_to_set) do { \ + (action)->flags = pcmk__set_flags_as(__func__, __LINE__, \ + LOG_TRACE, \ + "Action", (action)->uuid, \ + (action)->flags, \ + (flags_to_set), \ + #flags_to_set); \ + } while (0) + +/*! + * \internal + * \brief Clear action flags for an action + * + * \param[in,out] action Action to clear flags for + * \param[in] flags_to_clear Group of enum pe_action_flags to clear + */ +#define pcmk__clear_action_flags(action, flags_to_clear) do { \ + (action)->flags = pcmk__clear_flags_as(__func__, __LINE__, \ + LOG_TRACE, \ + "Action", (action)->uuid, \ + (action)->flags, \ + (flags_to_clear), \ + #flags_to_clear); \ + } while (0) + +/*! + * \internal + * \brief Set action flags for a flag group + * + * \param[in,out] action_flags Flag group to set flags for + * \param[in] action_name Name of action being modified (for logging) + * \param[in] to_set Group of enum pe_action_flags to set + */ +#define pcmk__set_raw_action_flags(action_flags, action_name, to_set) do { \ + action_flags = pcmk__set_flags_as(__func__, __LINE__, \ + LOG_TRACE, "Action", action_name, \ + (action_flags), \ + (to_set), #to_set); \ + } while (0) + +/*! + * \internal + * \brief Clear action flags for a flag group + * + * \param[in,out] action_flags Flag group to clear flags for + * \param[in] action_name Name of action being modified (for logging) + * \param[in] to_clear Group of enum pe_action_flags to clear + */ +#define pcmk__clear_raw_action_flags(action_flags, action_name, to_clear) \ + do { \ + action_flags = pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, \ + "Action", action_name, \ + (action_flags), \ + (to_clear), #to_clear); \ + } while (0) + 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); diff --git a/include/crm/common/agents.h b/include/crm/common/agents.h index 5a67a87..7d7733f 100644 --- a/include/crm/common/agents.h +++ b/include/crm/common/agents.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 the Pacemaker project contributors + * Copyright 2017-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_AGENTS__H -# define PCMK__CRM_COMMON_AGENTS__H +#define PCMK__CRM_COMMON_AGENTS__H #ifdef __cplusplus extern "C" { diff --git a/include/crm/common/agents_compat.h b/include/crm/common/agents_compat.h index 05a80f1..1c819a8 100644 --- a/include/crm/common/agents_compat.h +++ b/include/crm/common/agents_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 the Pacemaker project contributors + * Copyright 2017-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_AGENTS_COMPAT__H -# define PCMK__CRM_COMMON_AGENTS_COMPAT__H +#define PCMK__CRM_COMMON_AGENTS_COMPAT__H #ifdef __cplusplus extern "C" { diff --git a/include/crm/common/alerts_internal.h b/include/crm/common/alerts_internal.h index dc67427..3a591e5 100644 --- a/include/crm/common/alerts_internal.h +++ b/include/crm/common/alerts_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 the Pacemaker project contributors + * Copyright 2015-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -14,10 +14,10 @@ #include <stdbool.h> /* Default-Timeout to use before killing a alerts script (in milliseconds) */ -# define PCMK__ALERT_DEFAULT_TIMEOUT_MS (30000) +#define PCMK__ALERT_DEFAULT_TIMEOUT_MS (30000) /* Default-Format-String used to pass timestamps to the alerts scripts */ -# define PCMK__ALERT_DEFAULT_TSTAMP_FORMAT "%H:%M:%S.%06N" +#define PCMK__ALERT_DEFAULT_TSTAMP_FORMAT "%H:%M:%S.%06N" enum pcmk__alert_flags { pcmk__alert_none = 0, diff --git a/include/crm/common/attrd_internal.h b/include/crm/common/attrs_internal.h index 9d0b730..4c16675 100644 --- a/include/crm/common/attrd_internal.h +++ b/include/crm/common/attrs_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -7,8 +7,13 @@ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ -#ifndef PCMK__ATTRD_INTERNAL__H -# define PCMK__ATTRD_INTERNAL__H +#ifndef PCMK__CRM_COMMON_ATTRS_INTERNAL__H +#define PCMK__CRM_COMMON_ATTRS_INTERNAL__H + +#include <crm/crm.h> // crm_system_name +#include <crm/common/logging.h> // LOG_TRACE +#include <crm/common/scheduler_types.h> // pcmk_node_t +#include <crm/common/failcounts_internal.h> // enum pcmk__rsc_node #ifdef __cplusplus extern "C" { @@ -42,9 +47,11 @@ enum pcmk__node_attr_opts { } while (0) const char *pcmk__node_attr_target(const char *name); +const char *pcmk__node_attr(const pcmk_node_t *node, const char *name, + const char *target, enum pcmk__rsc_node node_type); #ifdef __cplusplus } #endif -#endif +#endif // PCMK__CRM_COMMON_ATTRS_INTERNAL__H diff --git a/include/crm/common/bundles_internal.h b/include/crm/common/bundles_internal.h new file mode 100644 index 0000000..62fdb74 --- /dev/null +++ b/include/crm/common/bundles_internal.h @@ -0,0 +1,89 @@ +/* + * Copyright 2017-2024 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_BUNDLES_INTERNAL__H +#define PCMK__CRM_COMMON_BUNDLES_INTERNAL__H + +#include <stdbool.h> // bool, false + +#include <crm/common/remote_internal.h> // pcmk__is_guest_or_bundle_node() +#include <crm/common/resources.h> // pcmk_rsc_variant_bundle +#include <crm/common/scheduler_types.h> // pcmk_resource_t, pcmk_node_t + +#ifdef __cplusplus +extern "C" { +#endif + +//! 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 +} pcmk__bundle_replica_t; + +/*! + * \internal + * \brief Check whether a resource is a bundle resource + * + * \param[in] rsc Resource to check + * + * \return true if \p rsc is a bundle, otherwise false + * \note This does not return true if \p rsc is part of a bundle + * (see pcmk__is_bundled()). + */ +static inline bool +pcmk__is_bundle(const pcmk_resource_t *rsc) +{ + return (rsc != NULL) && (rsc->variant == pcmk_rsc_variant_bundle); +} + +/*! + * \internal + * \brief Check whether a resource is part of a bundle + * + * \param[in] rsc Resource to check + * + * \return true if \p rsc is part of a bundle, otherwise false + */ +static inline bool +pcmk__is_bundled(const pcmk_resource_t *rsc) +{ + if (rsc == NULL) { + return false; + } + while (rsc->parent != NULL) { + rsc = rsc->parent; + } + return rsc->variant == pcmk_rsc_variant_bundle; +} + +/*! + * \internal + * \brief Check whether a node is a bundle node + * + * \param[in] node Node to check + * + * \return true if \p node is a bundle node, otherwise false + */ +static inline bool +pcmk__is_bundle_node(const pcmk_node_t *node) +{ + return pcmk__is_guest_or_bundle_node(node) + && pcmk__is_bundled(node->details->remote_rsc); +} + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_BUNDLES_INTERNAL__H diff --git a/include/crm/common/cib.h b/include/crm/common/cib.h index e1c4471..a30a22c 100644 --- a/include/crm/common/cib.h +++ b/include/crm/common/cib.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 the Pacemaker project contributors + * Copyright 2021-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_CIB__H -# define PCMK__CRM_COMMON_CIB__H +#define PCMK__CRM_COMMON_CIB__H #ifdef __cplusplus extern "C" { diff --git a/include/crm/common/cib_internal.h b/include/crm/common/cib_internal.h index c41c12e..fa65e58 100644 --- a/include/crm/common/cib_internal.h +++ b/include/crm/common/cib_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 the Pacemaker project contributors + * Copyright 2023-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -16,6 +16,8 @@ extern "C" { const char *pcmk__cib_abs_xpath_for(const char *element); +int pcmk__check_feature_set(const char *cib_version); + #ifdef __cplusplus } #endif diff --git a/include/crm/common/clone_internal.h b/include/crm/common/clone_internal.h index 494ee74..db001a0 100644 --- a/include/crm/common/clone_internal.h +++ b/include/crm/common/clone_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,11 @@ */ #ifndef PCMK__CRM_COMMON_CLONE_INTERNAL__H -# define PCMK__CRM_COMMON_CLONE_INTERNAL__H +#define PCMK__CRM_COMMON_CLONE_INTERNAL__H + +#include <stdbool.h> // bool +#include <crm/common/scheduler_types.h> // pcmk_resource_t +#include <crm/common/resources.h> // pcmk_rsc_variant_clone #ifdef __cplusplus extern "C" { @@ -26,6 +30,50 @@ enum pcmk__clone_flags { pcmk__clone_promotion_constrained = (1 << 2), }; +/*! + * \internal + * \brief Check whether a resource is a clone resource + * + * \param[in] rsc Resource to check + * + * \return true if \p rsc is a clone, otherwise false + * + * \note This does not return true if \p rsc has a clone ancestor. + */ +static inline bool +pcmk__is_clone(const pcmk_resource_t *rsc) +{ + return (rsc != NULL) && (rsc->variant == pcmk_rsc_variant_clone); +} + +/*! + * \internal + * \brief Check whether a resource is a globally unique clone + * + * \param[in] rsc Resource to check + * + * \return true if \p rsc is a unique clone, otherwise false + */ +static inline bool +pcmk__is_unique_clone(const pcmk_resource_t *rsc) +{ + return pcmk__is_clone(rsc) && pcmk_is_set(rsc->flags, pcmk_rsc_unique); +} + +/*! + * \internal + * \brief Check whether a resource is an anonymous clone + * + * \param[in] rsc Resource to check + * + * \return true if \p rsc is an anonymous clone, otherwise false + */ +static inline bool +pcmk__is_anonymous_clone(const pcmk_resource_t *rsc) +{ + return pcmk__is_clone(rsc) && !pcmk_is_set(rsc->flags, pcmk_rsc_unique); +} + #ifdef __cplusplus } #endif diff --git a/include/crm/common/digests_internal.h b/include/crm/common/digests_internal.h index 7598de2..1b17cd6 100644 --- a/include/crm/common/digests_internal.h +++ b/include/crm/common/digests_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_DIGESTS_INTERNAL__H -# define PCMK__CRM_COMMON_DIGESTS_INTERNAL__H +#define PCMK__CRM_COMMON_DIGESTS_INTERNAL__H #include <libxml/tree.h> // xmlNode @@ -24,6 +24,17 @@ enum pcmk__digest_result { pcmk__digest_restart, // Parameters that require a restart changed }; +// Information needed to compare operation digests +typedef struct { + enum pcmk__digest_result rc; // Result of digest comparison + xmlNode *params_all; // All operation parameters + xmlNode *params_secure; // Parameters marked private + xmlNode *params_restart; // Parameters marked not reloadable + char *digest_all_calc; // Digest of params_all + char *digest_secure_calc; // Digest of params_secure + char *digest_restart_calc; // Digest of params_restart +} pcmk__op_digest_t; + bool pcmk__verify_digest(xmlNode *input, const char *expected); #ifdef __cplusplus diff --git a/include/crm/common/failcounts_internal.h b/include/crm/common/failcounts_internal.h index 4ad01bf..776f949 100644 --- a/include/crm/common/failcounts_internal.h +++ b/include/crm/common/failcounts_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_FAILCOUNTS_INTERNAL__H -# define PCMK__CRM_COMMON_FAILCOUNTS_INTERNAL__H +#define PCMK__CRM_COMMON_FAILCOUNTS_INTERNAL__H #ifdef __cplusplus extern "C" { diff --git a/include/crm/common/group_internal.h b/include/crm/common/group_internal.h index 9e1424d..4a02e29 100644 --- a/include/crm/common/group_internal.h +++ b/include/crm/common/group_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,11 @@ */ #ifndef PCMK__CRM_COMMON_GROUP_INTERNAL__H -# define PCMK__CRM_COMMON_GROUP_INTERNAL__H +#define PCMK__CRM_COMMON_GROUP_INTERNAL__H + +#include <stdbool.h> // bool +#include <crm/common/scheduler_types.h> // pcmk_resource_t +#include <crm/common/resources.h> // pcmk_rsc_variant_group #ifdef __cplusplus extern "C" { @@ -20,6 +24,22 @@ enum pcmk__group_flags { pcmk__group_colocated = (1 << 1), // Members must be on same node }; +/*! + * \internal + * \brief Check whether a resource is a group resource + * + * \param[in] rsc Resource to check + * + * \return true if \p rsc is a group, otherwise false + * + * \note This does not return true if \p rsc is a clone of a group. + */ +static inline bool +pcmk__is_group(const pcmk_resource_t *rsc) +{ + return (rsc != NULL) && (rsc->variant == pcmk_rsc_variant_group); +} + #ifdef __cplusplus } #endif diff --git a/include/crm/common/history_internal.h b/include/crm/common/history_internal.h new file mode 100644 index 0000000..c74ef29 --- /dev/null +++ b/include/crm/common/history_internal.h @@ -0,0 +1,52 @@ +/* + * Copyright 2004-2024 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_HISTORY_INTERNAL__H +#define PCMK__CRM_COMMON_HISTORY_INTERNAL__H + +#include <stdio.h> // NULL +#include <libxml/tree.h> // xmlNode + +#include <crm/common/xml.h> // crm_element_value() +#include <crm/common/internal.h> // pcmk__str_empty() +#include <crm/common/xml_names_internal.h> // PCMK__XA_OPERATION_KEY + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \internal + * \brief Get the operation key from an action history entry + * + * \param[in] xml Action history entry + * + * \return Entry's operation key + */ +static inline const char * +pcmk__xe_history_key(const xmlNode *xml) +{ + if (xml == NULL) { + return NULL; + } else { + /* @COMPAT Pacemaker <= 1.1.5 did not add the key, and used the ID + * instead. Checking for that allows us to process old saved CIBs, + * including some regression tests. + */ + const char *key = crm_element_value(xml, PCMK__XA_OPERATION_KEY); + + return pcmk__str_empty(key)? pcmk__xe_id(xml) : key; + } +} + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_HISTORY_INTERNAL__H diff --git a/include/crm/common/internal.h b/include/crm/common/internal.h index 3078606..878ec4c 100644 --- a/include/crm/common/internal.h +++ b/include/crm/common/internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 the Pacemaker project contributors + * Copyright 2015-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -27,6 +27,8 @@ #include <crm/common/iso8601_internal.h> #include <crm/common/results_internal.h> #include <crm/common/messages_internal.h> +#include <crm/common/nvpair_internal.h> +#include <crm/common/scores_internal.h> #include <crm/common/strings_internal.h> #include <crm/common/acl_internal.h> @@ -98,7 +100,7 @@ pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value); * \param[in] name XML attribute to get * * \return True if the given \p name is an attribute on \p node and has - * the value "true", False in all other cases + * the value \c PCMK_VALUE_TRUE, False in all other cases */ bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name); @@ -129,12 +131,6 @@ unsigned int pcmk__procfs_num_cores(void); int pcmk__procfs_pid2path(pid_t pid, char path[], size_t path_size); bool pcmk__procfs_has_pids(void); -/* internal XML schema functions (from xml.c) */ - -void crm_schema_init(void); -void crm_schema_cleanup(void); - - /* internal functions related to process IDs (from pid.c) */ /*! @@ -231,6 +227,22 @@ pcmk__clear_flags_as(const char *function, int line, uint8_t log_level, return result; } +/*! + * \internal + * \brief Get readable string for whether specified flags are set + * + * \param[in] flag_group Group of flags to check + * \param[in] flags Which flags in \p flag_group should be checked + * + * \return "true" if all \p flags are set in \p flag_group, otherwise "false" + */ +static inline const char * +pcmk__flag_text(uint64_t flag_group, uint64_t flags) +{ + return pcmk__btoa(pcmk_all_flags_set(flag_group, flags)); +} + + // miscellaneous utilities (from utils.c) void pcmk__daemonize(const char *name, const char *pidfile); @@ -244,6 +256,49 @@ extern int pcmk__score_yellow; /*! * \internal + * \brief Allocate new zero-initialized memory, asserting on failure + * + * \param[in] file File where \p function is located + * \param[in] function Calling function + * \param[in] line Line within \p file + * \param[in] nmemb Number of elements to allocate memory for + * \param[in] size Size of each element + * + * \return Newly allocated memory of of size <tt>nmemb * size</tt> (guaranteed + * not to be \c NULL) + * + * \note The caller is responsible for freeing the return value using \c free(). + */ +static inline void * +pcmk__assert_alloc_as(const char *file, const char *function, uint32_t line, + size_t nmemb, size_t size) +{ + void *ptr = calloc(nmemb, size); + + if (ptr == NULL) { + crm_abort(file, function, line, "Out of memory", FALSE, TRUE); + crm_exit(CRM_EX_OSERR); + } + return ptr; +} + +/*! + * \internal + * \brief Allocate new zero-initialized memory, asserting on failure + * + * \param[in] nmemb Number of elements to allocate memory for + * \param[in] size Size of each element + * + * \return Newly allocated memory of of size <tt>nmemb * size</tt> (guaranteed + * not to be \c NULL) + * + * \note The caller is responsible for freeing the return value using \c free(). + */ +#define pcmk__assert_alloc(nmemb, size) \ + pcmk__assert_alloc_as(__FILE__, __func__, __LINE__, nmemb, size) + +/*! + * \internal * \brief Resize a dynamically allocated memory block * * \param[in] ptr Memory block to resize (or NULL to allocate new memory) @@ -270,7 +325,6 @@ pcmk__realloc(void *ptr, size_t size) return new_ptr; } - static inline char * pcmk__getpid_s(void) { diff --git a/include/crm/common/io_internal.h b/include/crm/common/io_internal.h index a8e1f28..6b6ef33 100644 --- a/include/crm/common/io_internal.h +++ b/include/crm/common/io_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 the Pacemaker project contributors + * Copyright 2022-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_IO_INTERNAL__H -# define PCMK__CRM_COMMON_IO_INTERNAL__H +#define PCMK__CRM_COMMON_IO_INTERNAL__H #include <fcntl.h> // open() #include <stdbool.h> // bool diff --git a/include/crm/common/ipc.h b/include/crm/common/ipc.h index 397c8b1..7a58725 100644 --- a/include/crm/common/ipc.h +++ b/include/crm/common/ipc.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_IPC__H -# define PCMK__CRM_COMMON_IPC__H +#define PCMK__CRM_COMMON_IPC__H #include <sys/uio.h> @@ -34,16 +34,24 @@ extern "C" { * compatibility. */ +// @COMPAT Make internal when we can break API backward compatibility +//! \deprecated Do not use #define create_reply(request, xml_response_data) \ create_reply_adv(request, xml_response_data, __func__) +// @COMPAT Make internal when we can break API backward compatibility +//! \deprecated Do not use xmlNode *create_reply_adv(const xmlNode *request, xmlNode *xml_response_data, const char *origin); +// @COMPAT Make internal when we can break API backward compatibility +//! \deprecated Do not use #define create_request(task, xml_data, host_to, sys_to, sys_from, uuid_from) \ create_request_adv(task, xml_data, host_to, sys_to, sys_from, uuid_from, \ __func__) +// @COMPAT Make internal when we can break API backward compatibility +//! \deprecated Do not use xmlNode *create_request_adv(const char *task, xmlNode *xml_data, const char *host_to, const char *sys_to, const char *sys_from, const char *uuid_from, @@ -76,11 +84,17 @@ enum pcmk_ipc_server { pcmk_ipc_schedulerd, //!< Scheduler }; +// NOTE: sbd (as of at least 1.5.2) uses this enum //! Possible event types that an IPC event callback can be called for enum pcmk_ipc_event { pcmk_ipc_event_connect, //!< Result of asynchronous connection attempt + + // NOTE: sbd (as of at least 1.5.2) uses this value pcmk_ipc_event_disconnect, //!< Termination of IPC connection + + // NOTE: sbd (as of at least 1.5.2) uses this value pcmk_ipc_event_reply, //!< Daemon's reply to client IPC request + pcmk_ipc_event_notify, //!< Notification from daemon }; @@ -91,6 +105,7 @@ enum pcmk_ipc_dispatch { pcmk_ipc_dispatch_sync, //!< Sending a command will wait for any reply }; +// NOTE: sbd (as of at least 1.5.2) uses this //! Client connection to Pacemaker IPC typedef struct pcmk_ipc_api_s pcmk_ipc_api_t; @@ -113,10 +128,13 @@ typedef void (*pcmk_ipc_callback_t)(pcmk_ipc_api_t *api, crm_exit_t status, void *event_data, void *user_data); +// NOTE: sbd (as of at least 1.5.2) uses this int pcmk_new_ipc_api(pcmk_ipc_api_t **api, enum pcmk_ipc_server server); +// NOTE: sbd (as of at least 1.5.2) uses this void pcmk_free_ipc_api(pcmk_ipc_api_t *api); +// NOTE: sbd (as of at least 1.5.2) uses this int pcmk_connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type); void pcmk_disconnect_ipc(pcmk_ipc_api_t *api); @@ -125,6 +143,7 @@ int pcmk_poll_ipc(const pcmk_ipc_api_t *api, int timeout_ms); void pcmk_dispatch_ipc(pcmk_ipc_api_t *api); +// NOTE: sbd (as of at least 1.5.2) uses this void pcmk_register_ipc_callback(pcmk_ipc_api_t *api, pcmk_ipc_callback_t cb, void *user_data); @@ -220,9 +239,8 @@ unsigned int crm_ipc_default_buffer_size(void); int crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid, pid_t *gotpid, uid_t *gotuid, gid_t *gotgid); -/* This is controller-specific but is declared in this header for C API - * backward compatibility. - */ +// @COMPAT Make internal when we can break API backward compatibility +//! \deprecated Do not use xmlNode *create_hello_message(const char *uuid, const char *client_name, const char *major_version, const char *minor_version); diff --git a/include/crm/common/ipc_attrd_internal.h b/include/crm/common/ipc_attrd_internal.h index b1b7584..de88e40 100644 --- a/include/crm/common/ipc_attrd_internal.h +++ b/include/crm/common/ipc_attrd_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 the Pacemaker project contributors + * Copyright 2022-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_IPC_ATTRD_INTERNAL__H -# define PCMK__CRM_COMMON_IPC_ATTRD_INTERNAL__H +#define PCMK__CRM_COMMON_IPC_ATTRD_INTERNAL__H #include <glib.h> // GList #include <crm/common/ipc.h> // pcmk_ipc_api_t @@ -89,10 +89,11 @@ int pcmk__attrd_api_delete(pcmk_ipc_api_t *api, const char *node, const char *na /*! * \internal - * \brief Purge a node from pacemaker-attrd + * \brief Request removal of a node's transient attributes * * \param[in,out] api pacemaker-attrd IPC object - * \param[in] node Node to remove + * \param[in] node Node whose attributes should be purged + * \param[in] reap If true, also request removal from node caches * * \note If \p api is NULL, a new temporary connection will be created * just for this operation and destroyed afterwards. If \p api is @@ -102,7 +103,7 @@ int pcmk__attrd_api_delete(pcmk_ipc_api_t *api, const char *node, const char *na * * \return Standard Pacemaker return code */ -int pcmk__attrd_api_purge(pcmk_ipc_api_t *api, const char *node); +int pcmk__attrd_api_purge(pcmk_ipc_api_t *api, const char *node, bool reap); /*! * \internal diff --git a/include/crm/common/ipc_controld.h b/include/crm/common/ipc_controld.h index 6deba48..cb4baac 100644 --- a/include/crm/common/ipc_controld.h +++ b/include/crm/common/ipc_controld.h @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 the Pacemaker project contributors + * Copyright 2020-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_IPC_CONTROLD__H -# define PCMK__CRM_COMMON_IPC_CONTROLD__H +#define PCMK__CRM_COMMON_IPC_CONTROLD__H #include <stdbool.h> // bool diff --git a/include/crm/common/ipc_internal.h b/include/crm/common/ipc_internal.h index b391e83..8a66126 100644 --- a/include/crm/common/ipc_internal.h +++ b/include/crm/common/ipc_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 the Pacemaker project contributors + * Copyright 2013-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -20,7 +20,7 @@ extern "C" { #include <sys/types.h> // uid_t, gid_t, pid_t, size_t #ifdef HAVE_GNUTLS_GNUTLS_H -# include <gnutls/gnutls.h> // gnutls_session_t +#include <gnutls/gnutls.h> // gnutls_session_t #endif #include <glib.h> // guint, gpointer, GQueue, ... @@ -122,9 +122,9 @@ struct pcmk__remote_s { char *token; /* TLS only */ -# ifdef HAVE_GNUTLS_GNUTLS_H +#ifdef HAVE_GNUTLS_GNUTLS_H gnutls_session_t *tls_session; -# endif +#endif }; enum pcmk__client_flags { @@ -138,10 +138,10 @@ enum pcmk__client_flags { //! Client uses TCP connection pcmk__client_tcp = (UINT64_C(1) << 33), -# ifdef HAVE_GNUTLS_GNUTLS_H +#ifdef HAVE_GNUTLS_GNUTLS_H //! Client uses TCP with TLS pcmk__client_tls = (UINT64_C(1) << 34), -# endif +#endif // The rest are client attributes @@ -157,14 +157,14 @@ enum pcmk__client_flags { /*! * \brief Client IPC connection accepted * - * Used only for remote CIB connections via \c remote-tls-port. + * Used only for remote CIB connections via \c PCMK_XA_REMOTE_TLS_PORT. */ pcmk__client_authenticated = (UINT64_C(1) << 43), -# ifdef HAVE_GNUTLS_GNUTLS_H +#ifdef HAVE_GNUTLS_GNUTLS_H //! Client TLS handshake is complete pcmk__client_tls_handshake_complete = (UINT64_C(1) << 44), -# endif +#endif }; #define PCMK__CLIENT_TYPE(client) ((client)->flags & UINT64_C(0xff00000000)) diff --git a/include/crm/common/ipc_pacemakerd.h b/include/crm/common/ipc_pacemakerd.h index 340f9a6..39d50ea 100644 --- a/include/crm/common/ipc_pacemakerd.h +++ b/include/crm/common/ipc_pacemakerd.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 the Pacemaker project contributors + * Copyright 2020-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_IPC_PACEMAKERD__H -# define PCMK__CRM_COMMON_IPC_PACEMAKERD__H +#define PCMK__CRM_COMMON_IPC_PACEMAKERD__H #include <sys/types.h> // time_t #include <crm/common/ipc.h> // pcmk_ipc_api_t @@ -24,14 +24,22 @@ extern "C" { * \ingroup core */ +// NOTE: sbd (as of at least 1.5.2) uses this enum enum pcmk_pacemakerd_state { pcmk_pacemakerd_state_invalid = -1, pcmk_pacemakerd_state_init = 0, pcmk_pacemakerd_state_starting_daemons, pcmk_pacemakerd_state_wait_for_ping, + + // NOTE: sbd (as of at least 1.5.2) uses this value pcmk_pacemakerd_state_running, + + // NOTE: sbd (as of at least 1.5.2) uses this value pcmk_pacemakerd_state_shutting_down, + + // NOTE: sbd (as of at least 1.5.2) uses this value pcmk_pacemakerd_state_shutdown_complete, + pcmk_pacemakerd_state_remote, pcmk_pacemakerd_state_max = pcmk_pacemakerd_state_remote, }; @@ -39,10 +47,14 @@ enum pcmk_pacemakerd_state { //! Possible types of pacemakerd replies enum pcmk_pacemakerd_api_reply { pcmk_pacemakerd_reply_unknown, + + // NOTE: sbd (as of at least 1.5.2) uses this value pcmk_pacemakerd_reply_ping, + pcmk_pacemakerd_reply_shutdown, }; +// NOTE: sbd (as of at least 1.5.2) uses this type and some of its members /*! * Pacemakerd reply passed to event callback */ @@ -64,7 +76,9 @@ typedef struct { } data; } pcmk_pacemakerd_api_reply_t; +// NOTE: sbd (as of at least 1.5.2) uses this int pcmk_pacemakerd_api_ping(pcmk_ipc_api_t *api, const char *ipc_name); + int pcmk_pacemakerd_api_shutdown(pcmk_ipc_api_t *api, const char *ipc_name); enum pcmk_pacemakerd_state diff --git a/include/crm/common/ipc_schedulerd.h b/include/crm/common/ipc_schedulerd.h index 303ec59..096e2d8 100644 --- a/include/crm/common/ipc_schedulerd.h +++ b/include/crm/common/ipc_schedulerd.h @@ -1,5 +1,5 @@ /* - * Copyright 2021-2022 the Pacemaker project contributors + * Copyright 2021-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_IPC_SCHEDULERD__H -# define PCMK__CRM_COMMON_IPC_SCHEDULERD__H +#define PCMK__CRM_COMMON_IPC_SCHEDULERD__H #include <crm/common/ipc.h> // pcmk_ipc_api_t diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index 78f530b..4c6adda 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2020 the Pacemaker project contributors + * Copyright 2005-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,12 +8,12 @@ */ #ifndef PCMK__CRM_COMMON_ISO8601__H -# define PCMK__CRM_COMMON_ISO8601__H +#define PCMK__CRM_COMMON_ISO8601__H -# include <time.h> -# include <ctype.h> -# include <stdint.h> // uint32_t -# include <stdbool.h> // bool +#include <time.h> +#include <ctype.h> +#include <stdint.h> // uint32_t +#include <stdbool.h> // bool #ifdef __cplusplus extern "C" { @@ -64,16 +64,16 @@ void crm_time_log_alias(int log_level, const char *file, const char *function, int line, const char *prefix, const crm_time_t *date_time, int flags); -# define crm_time_log_date 0x001 -# define crm_time_log_timeofday 0x002 -# define crm_time_log_with_timezone 0x004 -# define crm_time_log_duration 0x008 +#define crm_time_log_date 0x001 +#define crm_time_log_timeofday 0x002 +#define crm_time_log_with_timezone 0x004 +#define crm_time_log_duration 0x008 -# define crm_time_ordinal 0x010 -# define crm_time_weeks 0x020 -# define crm_time_seconds 0x100 -# define crm_time_epoch 0x200 -# define crm_time_usecs 0x400 +#define crm_time_ordinal 0x010 +#define crm_time_weeks 0x020 +#define crm_time_seconds 0x100 +#define crm_time_epoch 0x200 +#define crm_time_usecs 0x400 crm_time_t *crm_time_parse_duration(const char *duration_str); crm_time_t *crm_time_calculate_duration(const crm_time_t *dt, diff --git a/include/crm/common/iso8601_internal.h b/include/crm/common/iso8601_internal.h index f924d8a..3093a32 100644 --- a/include/crm/common/iso8601_internal.h +++ b/include/crm/common/iso8601_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 the Pacemaker project contributors + * Copyright 2015-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__ISO8601_INTERNAL__H -# define PCMK__ISO8601_INTERNAL__H +#define PCMK__ISO8601_INTERNAL__H #include <time.h> #include <sys/time.h> diff --git a/include/crm/common/location_internal.h b/include/crm/common/location_internal.h new file mode 100644 index 0000000..a00691e --- /dev/null +++ b/include/crm/common/location_internal.h @@ -0,0 +1,36 @@ +/* + * Copyright 2004-2024 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_LOCATION_INTERNAL__H +#define PCMK__CRM_COMMON_LOCATION_INTERNAL__H + +#include <glib.h> // GList + +#include <crm/common/nodes.h> // enum pe_discover_e +#include <crm/common/resources.h> // enum rsc_role_e +#include <crm/common/scheduler_types.h> // pcmk_resource_t + +#ifdef __cplusplus +extern "C" { +#endif + +//! Location constraint object +typedef struct { + char *id; // XML ID of location constraint + pcmk_resource_t *rsc; // Resource with location preference + enum rsc_role_e role_filter; // Limit to instances with this role + enum pe_discover_e discover_mode; // How to probe resource on node + GList *nodes; // Affected nodes, with preference score +} pcmk__location_t; + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_LOCATION_INTERNAL__H diff --git a/include/crm/common/logging.h b/include/crm/common/logging.h index eea4cec..abc2fe8 100644 --- a/include/crm/common/logging.h +++ b/include/crm/common/logging.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,13 +8,13 @@ */ #ifndef PCMK__CRM_COMMON_LOGGING__H -# define PCMK__CRM_COMMON_LOGGING__H +#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> +#include <stdio.h> +#include <stdint.h> // uint8_t, uint32_t +#include <glib.h> +#include <qb/qblog.h> +#include <libxml/tree.h> #ifdef __cplusplus extern "C" { @@ -34,26 +34,26 @@ extern "C" { */ // Define something even less desired than debug -# ifndef LOG_TRACE -# define LOG_TRACE (LOG_DEBUG+1) -# endif +#ifndef LOG_TRACE +#define LOG_TRACE (LOG_DEBUG+1) +#endif // Print message to stdout instead of logging it -# ifndef LOG_STDOUT -# define LOG_STDOUT 254 -# endif +#ifndef LOG_STDOUT +#define LOG_STDOUT 254 +#endif // Don't send message anywhere -# ifndef LOG_NEVER -# define LOG_NEVER 255 -# endif +#ifndef LOG_NEVER +#define LOG_NEVER 255 +#endif /* "Extended information" logging support */ #ifdef QB_XS -# define CRM_XS QB_XS -# define crm_extended_logging(t, e) qb_log_ctl((t), QB_LOG_CONF_EXTENDED, (e)) +#define CRM_XS QB_XS +#define crm_extended_logging(t, e) qb_log_ctl((t), QB_LOG_CONF_EXTENDED, (e)) #else -# define CRM_XS "|" +#define CRM_XS "|" /* A caller might want to check the return value, so we can't define this as a * no-op, and we can't simply define it to be 0 because gcc will then complain @@ -66,7 +66,12 @@ crm_extended_logging(int t, int e) } #endif +// @COMPAT Make internal when we can break API backward compatibility +//! \deprecated Do not use extern unsigned int crm_log_level; + +// @COMPAT Make internal when we can break API backward compatibility +//! \deprecated Do not use extern unsigned int crm_trace_nonlog; /*! \deprecated Pacemaker library functions set this when a configuration @@ -116,6 +121,7 @@ void crm_enable_stderr(int enable); gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags); +// NOTE: sbd (as of at least 1.5.2) uses this /* returns the old value */ unsigned int set_crm_log_level(unsigned int level); @@ -131,10 +137,10 @@ void pcmk_log_xml_as(const char *file, const char *function, uint32_t line, * https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html#Variadic-Macros */ #if defined(__clang__) -# define CRM_TRACE_INIT_DATA(name) -# else -# include <assert.h> // required by QB_LOG_INIT_DATA() macro -# define CRM_TRACE_INIT_DATA(name) QB_LOG_INIT_DATA(name) +#define CRM_TRACE_INIT_DATA(name) +#else +#include <assert.h> // required by QB_LOG_INIT_DATA() macro +#define CRM_TRACE_INIT_DATA(name) QB_LOG_INIT_DATA(name) #endif /*! @@ -172,7 +178,7 @@ pcmk__clip_log_level(int level) * \param[in] fmt printf-style format string literal for message * \param[in] args Any arguments needed by format string */ -# define do_crm_log(level, fmt, args...) do { \ +#define do_crm_log(level, fmt, args...) do { \ uint8_t _level = pcmk__clip_log_level(level); \ \ switch (_level) { \ @@ -197,7 +203,7 @@ pcmk__clip_log_level(int level) * * \note This does nothing when level is \p LOG_STDOUT. */ -# define do_crm_log_unlikely(level, fmt, args...) do { \ +#define do_crm_log_unlikely(level, fmt, args...) do { \ uint8_t _level = pcmk__clip_log_level(level); \ \ switch (_level) { \ @@ -219,7 +225,7 @@ pcmk__clip_log_level(int level) } \ } while (0) -# define CRM_LOG_ASSERT(expr) do { \ +#define CRM_LOG_ASSERT(expr) do { \ if (!(expr)) { \ static struct qb_log_callsite *core_cs = NULL; \ if(core_cs == NULL) { \ @@ -232,10 +238,11 @@ pcmk__clip_log_level(int level) } \ } while(0) +// NOTE: sbd (as of at least 1.5.2) uses this /* 'failure_action' MUST NOT be 'continue' as it will apply to the * macro's do-while loop */ -# define CRM_CHECK(expr, failure_action) do { \ +#define CRM_CHECK(expr, failure_action) do { \ if (!(expr)) { \ static struct qb_log_callsite *core_cs = NULL; \ if (core_cs == NULL) { \ @@ -243,10 +250,10 @@ pcmk__clip_log_level(int level) "check-assert", \ LOG_TRACE, __LINE__, 0); \ } \ - crm_abort(__FILE__, __func__, __LINE__, #expr, \ - (core_cs? core_cs->targets: FALSE), TRUE); \ - failure_action; \ - } \ + crm_abort(__FILE__, __func__, __LINE__, #expr, \ + (core_cs? core_cs->targets: FALSE), TRUE); \ + failure_action; \ + } \ } while(0) /*! @@ -258,7 +265,7 @@ pcmk__clip_log_level(int level) * * \note This does nothing when \p level is \p LOG_STDOUT. */ -# define do_crm_log_xml(level, text, xml) do { \ +#define do_crm_log_xml(level, text, xml) do { \ uint8_t _level = pcmk__clip_log_level(level); \ static struct qb_log_callsite *xml_cs = NULL; \ \ @@ -290,7 +297,7 @@ pcmk__clip_log_level(int level) * \param[in] fmt printf-style format string literal for message * \param[in] args Any arguments needed by format string */ -# define do_crm_log_alias(level, file, function, line, fmt, args...) do { \ +#define do_crm_log_alias(level, file, function, line, fmt, args...) do { \ uint8_t _level = pcmk__clip_log_level(level); \ \ switch (_level) { \ @@ -306,6 +313,7 @@ pcmk__clip_log_level(int level) } \ } while (0) +// NOTE: sbd (as of at least 1.5.2) uses this /*! * \brief Send a system error message to both the log and stderr * @@ -320,7 +328,7 @@ pcmk__clip_log_level(int level) * onto the end of fmt, that information will become extended information * if CRM_XS is used inside fmt and will not show up in syslog. */ -# define crm_perror(level, fmt, args...) do { \ +#define crm_perror(level, fmt, args...) do { \ uint8_t _level = pcmk__clip_log_level(level); \ \ switch (_level) { \ @@ -351,7 +359,7 @@ pcmk__clip_log_level(int level) * * \note This does nothing when level is LOG_STDOUT. */ -# define crm_log_tag(level, tag, fmt, args...) do { \ +#define crm_log_tag(level, tag, fmt, args...) do { \ uint8_t _level = pcmk__clip_log_level(level); \ \ switch (_level) { \ @@ -376,25 +384,34 @@ pcmk__clip_log_level(int level) } \ } while (0) -# define crm_emerg(fmt, args...) qb_log(LOG_EMERG, fmt , ##args) -# define crm_crit(fmt, args...) qb_logt(LOG_CRIT, 0, fmt , ##args) -# define crm_err(fmt, args...) qb_logt(LOG_ERR, 0, fmt , ##args) -# define crm_warn(fmt, args...) qb_logt(LOG_WARNING, 0, fmt , ##args) -# define crm_notice(fmt, args...) qb_logt(LOG_NOTICE, 0, fmt , ##args) -# define crm_info(fmt, args...) qb_logt(LOG_INFO, 0, fmt , ##args) - -# define crm_debug(fmt, args...) do_crm_log_unlikely(LOG_DEBUG, fmt , ##args) -# define crm_trace(fmt, args...) do_crm_log_unlikely(LOG_TRACE, fmt , ##args) - -# define crm_log_xml_crit(xml, text) do_crm_log_xml(LOG_CRIT, text, xml) -# define crm_log_xml_err(xml, text) do_crm_log_xml(LOG_ERR, text, xml) -# define crm_log_xml_warn(xml, text) do_crm_log_xml(LOG_WARNING, text, xml) -# define crm_log_xml_notice(xml, text) do_crm_log_xml(LOG_NOTICE, text, xml) -# define crm_log_xml_info(xml, text) do_crm_log_xml(LOG_INFO, text, xml) -# define crm_log_xml_debug(xml, text) do_crm_log_xml(LOG_DEBUG, text, xml) -# define crm_log_xml_trace(xml, text) do_crm_log_xml(LOG_TRACE, text, xml) - -# define crm_log_xml_explicit(xml, text) do { \ +#define crm_emerg(fmt, args...) qb_log(LOG_EMERG, fmt , ##args) +#define crm_crit(fmt, args...) qb_logt(LOG_CRIT, 0, fmt , ##args) + +// NOTE: sbd (as of at least 1.5.2) uses this +#define crm_err(fmt, args...) qb_logt(LOG_ERR, 0, fmt , ##args) + +// NOTE: sbd (as of at least 1.5.2) uses this +#define crm_warn(fmt, args...) qb_logt(LOG_WARNING, 0, fmt , ##args) + +// NOTE: sbd (as of at least 1.5.2) uses this +#define crm_notice(fmt, args...) qb_logt(LOG_NOTICE, 0, fmt , ##args) + +#define crm_info(fmt, args...) qb_logt(LOG_INFO, 0, fmt , ##args) + // +// NOTE: sbd (as of at least 1.5.2) uses this +#define crm_debug(fmt, args...) do_crm_log_unlikely(LOG_DEBUG, fmt , ##args) + +#define crm_trace(fmt, args...) do_crm_log_unlikely(LOG_TRACE, fmt , ##args) + +#define crm_log_xml_crit(xml, text) do_crm_log_xml(LOG_CRIT, text, xml) +#define crm_log_xml_err(xml, text) do_crm_log_xml(LOG_ERR, text, xml) +#define crm_log_xml_warn(xml, text) do_crm_log_xml(LOG_WARNING, text, xml) +#define crm_log_xml_notice(xml, text) do_crm_log_xml(LOG_NOTICE, text, xml) +#define crm_log_xml_info(xml, text) do_crm_log_xml(LOG_INFO, text, xml) +#define crm_log_xml_debug(xml, text) do_crm_log_xml(LOG_DEBUG, text, xml) +#define crm_log_xml_trace(xml, text) do_crm_log_xml(LOG_TRACE, text, xml) + +#define crm_log_xml_explicit(xml, text) do { \ static struct qb_log_callsite *digest_cs = NULL; \ digest_cs = qb_log_callsite_get( \ __func__, __FILE__, text, LOG_TRACE, __LINE__, \ diff --git a/include/crm/common/logging_compat.h b/include/crm/common/logging_compat.h index b57a802..f6dec36 100644 --- a/include/crm/common/logging_compat.h +++ b/include/crm/common/logging_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_LOGGING_COMPAT__H -# define PCMK__CRM_COMMON_LOGGING_COMPAT__H +#define PCMK__CRM_COMMON_LOGGING_COMPAT__H #include <stdint.h> // uint8_t #include <glib.h> @@ -55,7 +55,7 @@ enum xml_log_options { * \note This is a macro, and \p level may be evaluated more than once. * This does nothing when level is LOG_STDOUT. */ -# define do_crm_log_always(level, fmt, args...) do { \ +#define do_crm_log_always(level, fmt, args...) do { \ switch (level) { \ case LOG_STDOUT: case LOG_NEVER: \ break; \ diff --git a/include/crm/common/logging_internal.h b/include/crm/common/logging_internal.h index 981ddf3..3bfd504 100644 --- a/include/crm/common/logging_internal.h +++ b/include/crm/common/logging_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 the Pacemaker project contributors + * Copyright 2015-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -12,12 +12,70 @@ extern "C" { #endif #ifndef PCMK__LOGGING_INTERNAL_H -# define PCMK__LOGGING_INTERNAL_H +#define PCMK__LOGGING_INTERNAL_H -# include <glib.h> +#include <glib.h> -# include <crm/common/logging.h> -# include <crm/common/output_internal.h> +#include <crm/common/logging.h> +#include <crm/common/output_internal.h> + +/* Some warnings are too noisy when logged every time a given function is called + * (for example, using a deprecated feature). As an alternative, we allow + * warnings to be logged once per invocation of the calling program. Each of + * those warnings needs a flag defined here. + */ +enum pcmk__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), + pcmk__wo_rdisc_enabled = (1 << 16), + pcmk__wo_rkt = (1 << 17), + pcmk__wo_location_rules = (1 << 18), + pcmk__wo_op_attr_expr = (1 << 19), + pcmk__wo_instance_defaults = (1 << 20), + pcmk__wo_multiple_rules = (1 << 21), + pcmk__wo_master_element = (1 << 22), + pcmk__wo_clone_master_max = (1 << 23), + pcmk__wo_clone_master_node_max = (1 << 24), + pcmk__wo_bundle_master = (1 << 25), + pcmk__wo_master_role = (1 << 26), + pcmk__wo_slave_role = (1 << 27), +}; + +/*! + * \internal + * \brief Log a warning once per invocation of calling program + * + * \param[in] wo_flag enum pcmk__warnings value for this warning + * \param[in] fmt... printf(3)-style format and arguments + */ +#define pcmk__warn_once(wo_flag, fmt...) do { \ + if (!pcmk_is_set(pcmk__warnings, wo_flag)) { \ + if (wo_flag == pcmk__wo_blind) { \ + crm_warn(fmt); \ + } else { \ + pcmk__config_warn(fmt); \ + } \ + pcmk__warnings = pcmk__set_flags_as(__func__, __LINE__, \ + LOG_TRACE, \ + "Warn-once", "logging", \ + pcmk__warnings, \ + (wo_flag), #wo_flag); \ + } \ + } while (0) typedef void (*pcmk__config_error_func) (void *ctx, const char *msg, ...); typedef void (*pcmk__config_warning_func) (void *ctx, const char *msg, ...); @@ -33,12 +91,11 @@ void pcmk__set_config_warning_handler(pcmk__config_warning_func warning_handler, /*! * \internal - * \brief Log a configuration error + * \brief Log an error and make crm_verify return failure status * - * \param[in] fmt printf(3)-style format string - * \param[in] ... Arguments for format string + * \param[in] fmt... printf(3)-style format string and arguments */ -# define pcmk__config_err(fmt...) do { \ +#define pcmk__config_err(fmt...) do { \ crm_config_error = TRUE; \ if (pcmk__config_error_handler == NULL) { \ crm_err(fmt); \ @@ -49,18 +106,17 @@ void pcmk__set_config_warning_handler(pcmk__config_warning_func warning_handler, /*! * \internal - * \brief Log a configuration warning + * \brief Log a warning and make crm_verify return failure status * - * \param[in] fmt printf(3)-style format string - * \param[in] ... Arguments for format string + * \param[in] fmt... printf(3)-style format string and arguments */ -# 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); \ - } \ +#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) /*! @@ -76,7 +132,7 @@ void pcmk__set_config_warning_handler(pcmk__config_warning_func warning_handler, * \note Neither \p if_action nor \p else_action can contain a \p break or * \p continue statement. */ -# define pcmk__if_tracing(if_action, else_action) do { \ +#define pcmk__if_tracing(if_action, else_action) do { \ static struct qb_log_callsite *trace_cs = NULL; \ \ if (trace_cs == NULL) { \ diff --git a/include/crm/common/mainloop.h b/include/crm/common/mainloop.h index a55bcdf..522a945 100644 --- a/include/crm/common/mainloop.h +++ b/include/crm/common/mainloop.h @@ -1,5 +1,5 @@ /* - * Copyright 2009-2022 the Pacemaker project contributors + * Copyright 2009-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,11 +8,11 @@ */ #ifndef PCMK__CRM_COMMON_MAINLOOP__H -# define PCMK__CRM_COMMON_MAINLOOP__H +#define PCMK__CRM_COMMON_MAINLOOP__H -# include <signal.h> // sighandler_t -# include <glib.h> -# include <stdbool.h> +#include <signal.h> // sighandler_t +#include <glib.h> +#include <stdbool.h> #ifdef __cplusplus extern "C" { @@ -29,47 +29,57 @@ enum mainloop_child_flags { mainloop_leave_pid_group = 0x01, }; +// NOTE: sbd (as of at least 1.5.2) uses this typedef struct trigger_s crm_trigger_t; + typedef struct mainloop_io_s mainloop_io_t; typedef struct mainloop_child_s mainloop_child_t; + +// NOTE: sbd (as of at least 1.5.2) uses this typedef struct mainloop_timer_s mainloop_timer_t; void mainloop_cleanup(void); +// NOTE: sbd (as of at least 1.5.2) uses this crm_trigger_t *mainloop_add_trigger(int priority, int (*dispatch) (gpointer user_data), gpointer userdata); +// NOTE: sbd (as of at least 1.5.2) uses this void mainloop_set_trigger(crm_trigger_t * source); void mainloop_trigger_complete(crm_trigger_t * trig); gboolean mainloop_destroy_trigger(crm_trigger_t * source); -# ifndef HAVE_SIGHANDLER_T +#ifndef HAVE_SIGHANDLER_T typedef void (*sighandler_t)(int); -# endif +#endif sighandler_t crm_signal_handler(int sig, sighandler_t dispatch); +// NOTE: sbd (as of at least 1.5.2) uses this gboolean mainloop_add_signal(int sig, void (*dispatch) (int sig)); gboolean mainloop_destroy_signal(int sig); bool mainloop_timer_running(mainloop_timer_t *t); +// NOTE: sbd (as of at least 1.5.2) uses this void mainloop_timer_start(mainloop_timer_t *t); +// NOTE: sbd (as of at least 1.5.2) uses this void mainloop_timer_stop(mainloop_timer_t *t); guint mainloop_timer_set_period(mainloop_timer_t *t, guint period_ms); +// NOTE: sbd (as of at least 1.5.2) uses this mainloop_timer_t *mainloop_timer_add(const char *name, guint period_ms, bool repeat, GSourceFunc cb, void *userdata); void mainloop_timer_del(mainloop_timer_t *t); -# include <crm/common/ipc.h> -# include <qb/qbipcs.h> +#include <crm/common/ipc.h> +#include <qb/qbipcs.h> struct ipc_client_callbacks { /*! @@ -179,7 +189,7 @@ void pcmk_quit_main_loop(GMainLoop *mloop, unsigned int n); void pcmk_drain_main_loop(GMainLoop *mloop, guint timer_ms, bool (*check)(guint)); -# define G_PRIORITY_MEDIUM (G_PRIORITY_HIGH/2) +#define G_PRIORITY_MEDIUM (G_PRIORITY_HIGH/2) #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) #include <crm/common/mainloop_compat.h> diff --git a/include/crm/common/mainloop_compat.h b/include/crm/common/mainloop_compat.h index 5eb445a..4c8e479 100644 --- a/include/crm/common/mainloop_compat.h +++ b/include/crm/common/mainloop_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2009-2021 the Pacemaker project contributors + * Copyright 2009-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,10 +8,10 @@ */ #ifndef PCMK__CRM_COMMON_MAINLOOP_COMPAT__H -# define PCMK__CRM_COMMON_MAINLOOP_COMPAT__H +#define PCMK__CRM_COMMON_MAINLOOP_COMPAT__H -# include <glib.h> -# include <stdbool.h> +#include <glib.h> +#include <stdbool.h> #ifdef __cplusplus extern "C" { diff --git a/include/crm/common/messages_internal.h b/include/crm/common/messages_internal.h index 0d1908f..79db784 100644 --- a/include/crm/common/messages_internal.h +++ b/include/crm/common/messages_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 the Pacemaker project contributors + * Copyright 2018-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -14,6 +14,7 @@ #include <libxml/tree.h> // xmlNode #include <crm/common/ipc_internal.h> // pcmk__client_t #include <crm/common/results_internal.h> // pcmk__action_result_t +#include <crm/common/xml_internal.h> // pcmk__xml_copy() enum pcmk__request_flags { pcmk__request_none = UINT32_C(0), diff --git a/include/crm/common/nodes.h b/include/crm/common/nodes.h index fbc3758..5f6f25f 100644 --- a/include/crm/common/nodes.h +++ b/include/crm/common/nodes.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,8 +8,9 @@ */ #ifndef PCMK__CRM_COMMON_NODES__H -# define PCMK__CRM_COMMON_NODES__H +#define PCMK__CRM_COMMON_NODES__H +#include <stdbool.h> // bool #include <glib.h> // gboolean, GList, GHashTable #include <crm/common/scheduler_types.h> // pcmk_resource_t, pcmk_scheduler_t @@ -26,116 +27,201 @@ extern "C" { // Special node attributes -#define PCMK_NODE_ATTR_TERMINATE "terminate" +#define PCMK_NODE_ATTR_MAINTENANCE "maintenance" +#define PCMK_NODE_ATTR_STANDBY "standby" +#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 +// @COMPAT Make this internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) +enum node_type { // Possible node types + pcmk_node_variant_cluster = 1, // Cluster layer node + pcmk_node_variant_remote = 2, // Pacemaker Remote node - node_ping = 0, //!< \deprecated Do not use + node_ping = 0, // deprecated #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) +// When to probe a resource on a node (as specified in location constraints) +// @COMPAT Make this internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) 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 + 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) +// Basic node information (all node objects for the same node share this) +// @COMPAT Make this internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) 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 + 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 - - /*! + + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated Call pcmk_node_is_online() instead + gboolean online; // Whether online + + gboolean standby; // Whether in standby mode + gboolean standby_onfail; // Whether in standby mode due to on-fail + + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated Call pcmk_node_is_pending() instead + gboolean pending; // Whether controller membership is pending + + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated Call !pcmk_node_is_clean() instead + gboolean unclean; // Whether node requires fencing + + gboolean unseen; // Whether node has never joined cluster + + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated Call pcmk_node_is_shutting_down() instead + gboolean shutdown; // Whether shutting down + + gboolean expected_up; // Whether expected join state is member + gboolean is_dc; // Whether node is cluster's DC + + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated Call pcmk_node_is_in_maintenance() instead + 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 + 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 + // 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 + // NOTE: sbd (as of at least 1.5.2) uses this + // \deprecated Call pcmk_foreach_active_resource() instead + 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) + * nodes for PCMK_OPT_PRIORITY_FENCING_DELAY) */ int priority; - pcmk_scheduler_t *data_set; //!< Cluster that node is part of + pcmk_scheduler_t *data_set; // Cluster that node is part of }; +//!@} -//! Implementation of pcmk_node_t +// Implementation of pcmk_node_t +// @COMPAT Make contents internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) 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 + int weight; // Node score for a given resource + gboolean fixed; // \deprecated Do not use + int count; // Counter reused by assignment and promotion code + + // NOTE: sbd (as of at least 1.5.2) uses this + 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) + int rsc_discover_mode; // Probe mode (enum pe_discover_e) }; +//!@} + +bool pcmk_node_is_online(const pcmk_node_t *node); +bool pcmk_node_is_pending(const pcmk_node_t *node); +bool pcmk_node_is_clean(const pcmk_node_t *node); +bool pcmk_node_is_shutting_down(const pcmk_node_t *node); +bool pcmk_node_is_in_maintenance(const pcmk_node_t *node); + +bool pcmk_foreach_active_resource(pcmk_node_t *node, + bool (*fn)(pcmk_resource_t *, void *), + void *user_data); +/*! + * \internal + * \brief Return a string suitable for logging as a node name + * + * \param[in] node Node to return a node name string for + * + * \return Node name if available, otherwise node ID if available, + * otherwise "unspecified node" if node is NULL or "unidentified node" + * if node has neither a name nor ID. + */ +static inline const char * +pcmk__node_name(const pcmk_node_t *node) +{ + if (node == NULL) { + return "unspecified node"; + + } else if (node->details->uname != NULL) { + return node->details->uname; + + } else if (node->details->id != NULL) { + return node->details->id; + + } else { + return "unidentified node"; + } +} + +/*! + * \internal + * \brief Check whether two node objects refer to the same node + * + * \param[in] node1 First node object to compare + * \param[in] node2 Second node object to compare + * + * \return true if \p node1 and \p node2 refer to the same node + */ +static inline bool +pcmk__same_node(const pcmk_node_t *node1, const pcmk_node_t *node2) +{ + return (node1 != NULL) && (node2 != NULL) + && (node1->details == node2->details); +} #ifdef __cplusplus } diff --git a/include/crm/common/nodes_internal.h b/include/crm/common/nodes_internal.h new file mode 100644 index 0000000..8f49566 --- /dev/null +++ b/include/crm/common/nodes_internal.h @@ -0,0 +1,27 @@ +/* + * Copyright 2024 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__NODES_INTERNAL__H +#define PCMK__NODES_INTERNAL__H + +/* + * Special node attributes + */ + +#define PCMK__NODE_ATTR_SHUTDOWN "shutdown" + +/* @COMPAT Deprecated since 2.1.8. Use a location constraint with + * PCMK_XA_RSC_PATTERN=".*" and PCMK_XA_RESOURCE_DISCOVERY="never" instead of + * PCMK__NODE_ATTR_RESOURCE_DISCOVERY_ENABLED="false". + */ +#define PCMK__NODE_ATTR_RESOURCE_DISCOVERY_ENABLED "resource-discovery-enabled" + +pcmk_node_t *pcmk__find_node_in_list(const GList *nodes, const char *node_name); + +#endif // PCMK__NODES_INTERNAL__H diff --git a/include/crm/common/nvpair.h b/include/crm/common/nvpair.h index 185bdc3..b68ba70 100644 --- a/include/crm/common/nvpair.h +++ b/include/crm/common/nvpair.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2022 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,17 +8,17 @@ */ #ifndef PCMK__CRM_COMMON_NVPAIR__H -# define PCMK__CRM_COMMON_NVPAIR__H +#define PCMK__CRM_COMMON_NVPAIR__H -# include <sys/time.h> // struct timeval -# include <glib.h> // gpointer, gboolean, guint -# include <libxml/tree.h> // xmlNode -# include <crm/crm.h> +#include <sys/time.h> // struct timeval +#include <glib.h> // gpointer, gboolean, guint, GHashTable +#include <libxml/tree.h> // xmlNode +#include <crm/crm.h> -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif /** * \file @@ -62,6 +62,9 @@ int crm_element_value_timeval(const xmlNode *data, const char *name_sec, const char *name_usec, struct timeval *dest); char *crm_element_value_copy(const xmlNode *data, const char *name); +char *crm_meta_name(const char *field); +const char *crm_meta_value(GHashTable *hash, const char *field); + /*! * \brief Copy an element from one XML object to another * @@ -80,8 +83,8 @@ crm_copy_xml_element(const xmlNode *obj1, xmlNode *obj2, const char *element) return value; } -# ifdef __cplusplus +#ifdef __cplusplus } -# endif +#endif #endif // PCMK__CRM_COMMON_NVPAIR__H diff --git a/include/crm/common/nvpair_internal.h b/include/crm/common/nvpair_internal.h new file mode 100644 index 0000000..b771dfb --- /dev/null +++ b/include/crm/common/nvpair_internal.h @@ -0,0 +1,63 @@ +/* + * Copyright 2004-2024 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_NVPAIR_INTERNAL__H +#define PCMK__CRM_COMMON_NVPAIR_INTERNAL__H + +#include <glib.h> // gboolean +#include <libxml/tree.h> // xmlNode + +#include <crm/common/rules.h> // pcmk_rule_input_t +#include <crm/common/iso8601.h> // crm_time_t +#include <crm/common/strings_internal.h> // pcmk__str_eq(), etc. + +#ifdef __cplusplus +extern "C" { +#endif + +// Data needed to sort XML blocks of name/value pairs +typedef struct unpack_data_s { + GHashTable *values; // Where to put name/value pairs + const char *first_id; // Block with this XML ID should sort first + pcmk_rule_input_t rule_input; // Data used to evaluate rules + + // Whether each block's values should overwrite any existing ones + bool overwrite; + + // If not NULL, this will be set to when rule evaluations will change next + crm_time_t *next_change; +} pcmk__nvpair_unpack_t; + +/*! + * \internal + * \brief Insert a meta-attribute into a hash table + * + * \param[in] obj Resource (pe_resource_t) or action (pe_action_t) to add to + * \param[in] name Meta-attribute name + * \param[in] value Value to add + */ +#define pcmk__insert_meta(obj, name, value) do { \ + if (pcmk__str_eq((value), "#default", pcmk__str_casei)) { \ + /* @COMPAT Deprecated since 2.1.8 */ \ + pcmk__config_warn("Support for setting meta-attributes " \ + "(such as %s) to the explicit value " \ + "'#default' is deprecated and will be " \ + "removed in a future release", (name)); \ + } else if ((value) != NULL) { \ + pcmk__insert_dup((obj)->meta, (name), (value)); \ + } \ + } while (0) + +int pcmk__xe_get_datetime(const xmlNode *xml, const char *attr, crm_time_t **t); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_NVPAIR_INTERNAL__H diff --git a/include/crm/common/options.h b/include/crm/common/options.h new file mode 100644 index 0000000..64cbf5e --- /dev/null +++ b/include/crm/common/options.h @@ -0,0 +1,231 @@ +/* + * Copyright 2024 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_OPTIONS__H +#define PCMK__CRM_COMMON_OPTIONS__H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file + * \brief API related to options + * \ingroup core + */ + +/* + * Cluster options + */ + +#define PCMK_OPT_BATCH_LIMIT "batch-limit" +#define PCMK_OPT_CLUSTER_DELAY "cluster-delay" +#define PCMK_OPT_CLUSTER_INFRASTRUCTURE "cluster-infrastructure" +#define PCMK_OPT_CLUSTER_IPC_LIMIT "cluster-ipc-limit" +#define PCMK_OPT_CLUSTER_NAME "cluster-name" +#define PCMK_OPT_CLUSTER_RECHECK_INTERVAL "cluster-recheck-interval" +#define PCMK_OPT_CONCURRENT_FENCING "concurrent-fencing" +#define PCMK_OPT_DC_DEADTIME "dc-deadtime" +#define PCMK_OPT_DC_VERSION "dc-version" +#define PCMK_OPT_ELECTION_TIMEOUT "election-timeout" +#define PCMK_OPT_ENABLE_ACL "enable-acl" +#define PCMK_OPT_ENABLE_STARTUP_PROBES "enable-startup-probes" +#define PCMK_OPT_FENCE_REACTION "fence-reaction" +#define PCMK_OPT_HAVE_WATCHDOG "have-watchdog" +#define PCMK_OPT_JOIN_FINALIZATION_TIMEOUT "join-finalization-timeout" +#define PCMK_OPT_JOIN_INTEGRATION_TIMEOUT "join-integration-timeout" +#define PCMK_OPT_LOAD_THRESHOLD "load-threshold" +#define PCMK_OPT_MAINTENANCE_MODE "maintenance-mode" +#define PCMK_OPT_MIGRATION_LIMIT "migration-limit" +#define PCMK_OPT_NO_QUORUM_POLICY "no-quorum-policy" +#define PCMK_OPT_NODE_ACTION_LIMIT "node-action-limit" +#define PCMK_OPT_NODE_HEALTH_BASE "node-health-base" +#define PCMK_OPT_NODE_HEALTH_GREEN "node-health-green" +#define PCMK_OPT_NODE_HEALTH_RED "node-health-red" +#define PCMK_OPT_NODE_HEALTH_STRATEGY "node-health-strategy" +#define PCMK_OPT_NODE_HEALTH_YELLOW "node-health-yellow" +#define PCMK_OPT_NODE_PENDING_TIMEOUT "node-pending-timeout" +#define PCMK_OPT_PE_ERROR_SERIES_MAX "pe-error-series-max" +#define PCMK_OPT_PE_INPUT_SERIES_MAX "pe-input-series-max" +#define PCMK_OPT_PE_WARN_SERIES_MAX "pe-warn-series-max" +#define PCMK_OPT_PLACEMENT_STRATEGY "placement-strategy" +#define PCMK_OPT_PRIORITY_FENCING_DELAY "priority-fencing-delay" +#define PCMK_OPT_SHUTDOWN_ESCALATION "shutdown-escalation" +#define PCMK_OPT_SHUTDOWN_LOCK "shutdown-lock" +#define PCMK_OPT_SHUTDOWN_LOCK_LIMIT "shutdown-lock-limit" +#define PCMK_OPT_START_FAILURE_IS_FATAL "start-failure-is-fatal" +#define PCMK_OPT_STARTUP_FENCING "startup-fencing" +#define PCMK_OPT_STONITH_ACTION "stonith-action" +#define PCMK_OPT_STONITH_ENABLED "stonith-enabled" +#define PCMK_OPT_STONITH_MAX_ATTEMPTS "stonith-max-attempts" +#define PCMK_OPT_STONITH_TIMEOUT "stonith-timeout" +#define PCMK_OPT_STONITH_WATCHDOG_TIMEOUT "stonith-watchdog-timeout" +#define PCMK_OPT_STOP_ALL_RESOURCES "stop-all-resources" +#define PCMK_OPT_STOP_ORPHAN_ACTIONS "stop-orphan-actions" +#define PCMK_OPT_STOP_ORPHAN_RESOURCES "stop-orphan-resources" +#define PCMK_OPT_SYMMETRIC_CLUSTER "symmetric-cluster" +#define PCMK_OPT_TRANSITION_DELAY "transition-delay" + + +/* + * Meta-attributes + */ + +#define PCMK_META_ALLOW_MIGRATE "allow-migrate" +#define PCMK_META_ALLOW_UNHEALTHY_NODES "allow-unhealthy-nodes" +#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_CONTAINER_ATTRIBUTE_TARGET "container-attribute-target" +#define PCMK_META_CRITICAL "critical" +#define PCMK_META_ENABLED "enabled" +#define PCMK_META_FAILURE_TIMEOUT "failure-timeout" +#define PCMK_META_GLOBALLY_UNIQUE "globally-unique" +#define PCMK_META_INTERLEAVE "interleave" +#define PCMK_META_INTERVAL "interval" +#define PCMK_META_IS_MANAGED "is-managed" +#define PCMK_META_INTERVAL_ORIGIN "interval-origin" +#define PCMK_META_MAINTENANCE "maintenance" +#define PCMK_META_MIGRATION_THRESHOLD "migration-threshold" +#define PCMK_META_MULTIPLE_ACTIVE "multiple-active" +#define PCMK_META_NOTIFY "notify" +#define PCMK_META_ON_FAIL "on-fail" +#define PCMK_META_ORDERED "ordered" +#define PCMK_META_PRIORITY "priority" +#define PCMK_META_PROMOTABLE "promotable" +#define PCMK_META_PROMOTED_MAX "promoted-max" +#define PCMK_META_PROMOTED_NODE_MAX "promoted-node-max" +#define PCMK_META_RECORD_PENDING "record-pending" +#define PCMK_META_REMOTE_ADDR "remote-addr" +#define PCMK_META_REMOTE_ALLOW_MIGRATE "remote-allow-migrate" +#define PCMK_META_REMOTE_CONNECT_TIMEOUT "remote-connect-timeout" +#define PCMK_META_REMOTE_NODE "remote-node" +#define PCMK_META_REMOTE_PORT "remote-port" +#define PCMK_META_REQUIRES "requires" +#define PCMK_META_RESOURCE_STICKINESS "resource-stickiness" +#define PCMK_META_START_DELAY "start-delay" +#define PCMK_META_TARGET_ROLE "target-role" +#define PCMK_META_TIMEOUT "timeout" +#define PCMK_META_TIMESTAMP_FORMAT "timestamp-format" + + +/* + * Remote resource instance attributes + */ + +#define PCMK_REMOTE_RA_ADDR "addr" +#define PCMK_REMOTE_RA_PORT "port" +#define PCMK_REMOTE_RA_RECONNECT_INTERVAL "reconnect_interval" +#define PCMK_REMOTE_RA_SERVER "server" + + +/* + * Enumerated values + */ + +#define PCMK_VALUE_ALWAYS "always" +#define PCMK_VALUE_AND "and" +#define PCMK_VALUE_BALANCED "balanced" +#define PCMK_VALUE_BLOCK "block" +#define PCMK_VALUE_BOOLEAN "boolean" +#define PCMK_VALUE_CIB_BOOTSTRAP_OPTIONS "cib-bootstrap-options" +#define PCMK_VALUE_COROSYNC "corosync" +#define PCMK_VALUE_CREATE "create" +#define PCMK_VALUE_CUSTOM "custom" +#define PCMK_VALUE_DATE_SPEC "date_spec" +#define PCMK_VALUE_DEFAULT "default" +#define PCMK_VALUE_DEFINED "defined" +#define PCMK_VALUE_DELETE "delete" +#define PCMK_VALUE_DEMOTE "demote" +#define PCMK_VALUE_DENY "deny" +#define PCMK_VALUE_DURATION "duration" +#define PCMK_VALUE_DYNAMIC_LIST "dynamic-list" +#define PCMK_VALUE_EQ "eq" +#define PCMK_VALUE_EXCLUSIVE "exclusive" +#define PCMK_VALUE_FAILED "failed" +#define PCMK_VALUE_FALSE "false" +#define PCMK_VALUE_FENCE "fence" +#define PCMK_VALUE_FENCING "fencing" +#define PCMK_VALUE_FREEZE "freeze" +#define PCMK_VALUE_GRANTED "granted" +#define PCMK_VALUE_GREEN "green" +#define PCMK_VALUE_GT "gt" +#define PCMK_VALUE_GTE "gte" +#define PCMK_VALUE_HOST "host" +#define PCMK_VALUE_IGNORE "ignore" +#define PCMK_VALUE_IN_RANGE "in_range" +#define PCMK_VALUE_INFINITY "INFINITY" +#define PCMK_VALUE_INTEGER "integer" +#define PCMK_VALUE_LITERAL "literal" +#define PCMK_VALUE_LT "lt" +#define PCMK_VALUE_LTE "lte" +#define PCMK_VALUE_MANDATORY "Mandatory" +#define PCMK_VALUE_MEMBER "member" +#define PCMK_VALUE_META "meta" +#define PCMK_VALUE_MIGRATE_ON_RED "migrate-on-red" +#define PCMK_VALUE_MINIMAL "minimal" +#define PCMK_VALUE_MINUS_INFINITY "-" PCMK_VALUE_INFINITY +#define PCMK_VALUE_MODIFY "modify" +#define PCMK_VALUE_MOVE "move" +#define PCMK_VALUE_NE "ne" +#define PCMK_VALUE_NEVER "never" +#define PCMK_VALUE_NONE "none" +#define PCMK_VALUE_NONNEGATIVE_INTEGER "nonnegative_integer" +#define PCMK_VALUE_NOT_DEFINED "not_defined" +#define PCMK_VALUE_NOTHING "nothing" +#define PCMK_VALUE_NUMBER "number" +#define PCMK_VALUE_OFFLINE "offline" +#define PCMK_VALUE_ONLINE "online" +#define PCMK_VALUE_ONLY_GREEN "only-green" +#define PCMK_VALUE_OPTIONAL "Optional" +#define PCMK_VALUE_OR "or" +#define PCMK_VALUE_PANIC "panic" +#define PCMK_VALUE_PARAM "param" +#define PCMK_VALUE_PENDING "pending" +#define PCMK_VALUE_PERCENTAGE "percentage" +#define PCMK_VALUE_PLUS_INFINITY "+" PCMK_VALUE_INFINITY +#define PCMK_VALUE_PORT "port" +#define PCMK_VALUE_PROGRESSIVE "progressive" +#define PCMK_VALUE_QUORUM "quorum" +#define PCMK_VALUE_READ "read" +#define PCMK_VALUE_RED "red" +#define PCMK_VALUE_REMOTE "remote" +#define PCMK_VALUE_RESTART "restart" +#define PCMK_VALUE_RESTART_CONTAINER "restart-container" +#define PCMK_VALUE_REVOKED "revoked" +#define PCMK_VALUE_SCORE "score" +#define PCMK_VALUE_SELECT "select" +#define PCMK_VALUE_SERIALIZE "Serialize" +#define PCMK_VALUE_STANDBY "standby" +#define PCMK_VALUE_STATIC_LIST "static-list" +#define PCMK_VALUE_STATUS "status" +#define PCMK_VALUE_STRING "string" +#define PCMK_VALUE_STOP "stop" +#define PCMK_VALUE_STOP_ONLY "stop_only" +#define PCMK_VALUE_STOP_START "stop_start" +#define PCMK_VALUE_STOP_UNEXPECTED "stop_unexpected" +#define PCMK_VALUE_SUCCESS "success" +#define PCMK_VALUE_TIMEOUT "timeout" +#define PCMK_VALUE_TRUE "true" +#define PCMK_VALUE_UNFENCING "unfencing" +#define PCMK_VALUE_UNKNOWN "unknown" +#define PCMK_VALUE_UTILIZATION "utilization" +#define PCMK_VALUE_VERSION "version" +#define PCMK_VALUE_WRITE "write" +#define PCMK_VALUE_YELLOW "yellow" + +// @COMPAT This will become a deprecated alias for PCMK_VALUE_FENCE (see T279) +#define PCMK_VALUE_FENCE_LEGACY "suicide" + + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_OPTIONS__H diff --git a/include/crm/common/options_internal.h b/include/crm/common/options_internal.h index 5c561fd..92506a0 100644 --- a/include/crm/common/options_internal.h +++ b/include/crm/common/options_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the Pacemaker project contributors + * Copyright 2006-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,15 +8,17 @@ */ #ifndef PCMK__OPTIONS_INTERNAL__H -# define PCMK__OPTIONS_INTERNAL__H +#define PCMK__OPTIONS_INTERNAL__H -# ifndef PCMK__CONFIG_H -# define PCMK__CONFIG_H -# include <config.h> // _Noreturn -# endif +#ifndef PCMK__CONFIG_H +#define PCMK__CONFIG_H +#include <config.h> // _Noreturn +#endif -# include <glib.h> // GHashTable -# include <stdbool.h> // bool +#include <glib.h> // GHashTable +#include <stdbool.h> // bool + +#include <crm/common/util.h> // pcmk_parse_interval_spec() _Noreturn void pcmk__cli_help(char cmd); @@ -34,6 +36,42 @@ bool pcmk__env_option_enabled(const char *daemon, const char *option); * Cluster option handling */ +/*! + * \internal + * \enum pcmk__opt_flags + * \brief Option flags + */ +enum pcmk__opt_flags { + pcmk__opt_none = 0U, //!< No additional information + + /*! + * \brief In CIB manager metadata + * + * \deprecated This flag will be removed with CIB manager metadata + */ + pcmk__opt_based = (1U << 0), + + /*! + * \brief In controller metadata + * + * \deprecated This flag will be removed with controller metadata + */ + pcmk__opt_controld = (1U << 1), + + /*! + * \brief In scheduler metadata + * + * \deprecated This flag will be removed with scheduler metadata + */ + pcmk__opt_schedulerd = (1U << 2), + + pcmk__opt_advanced = (1U << 3), //!< Advanced use only + pcmk__opt_generated = (1U << 4), //!< Generated by Pacemaker + pcmk__opt_deprecated = (1U << 5), //!< Option is deprecated + pcmk__opt_fencing = (1U << 6), //!< Common fencing resource parameter + pcmk__opt_primitive = (1U << 7), //!< Primitive resource meta-attribute +}; + typedef struct pcmk__cluster_option_s { const char *name; const char *alt_name; @@ -43,37 +81,44 @@ typedef struct pcmk__cluster_option_s { bool (*is_valid)(const char *); + uint32_t flags; //!< Group of <tt>enum pcmk__opt_flags</tt> + const char *description_short; const char *description_long; } pcmk__cluster_option_t; -const char *pcmk__cluster_option(GHashTable *options, - const pcmk__cluster_option_t *option_list, - int len, const char *name); +const char *pcmk__cluster_option(GHashTable *options, const char *name); -gchar *pcmk__format_option_metadata(const char *name, const char *desc_short, - const char *desc_long, - pcmk__cluster_option_t *option_list, - int len); +int pcmk__output_cluster_options(pcmk__output_t *out, const char *name, + const char *desc_short, const char *desc_long, + uint32_t filter, bool all); +int pcmk__output_fencing_params(pcmk__output_t *out, const char *name, + const char *desc_short, const char *desc_long, + bool all); +int pcmk__output_primitive_meta(pcmk__output_t *out, const char *name, + const char *desc_short, const char *desc_long, + bool all); -void pcmk__validate_cluster_options(GHashTable *options, - pcmk__cluster_option_t *option_list, - int len); +int pcmk__daemon_metadata(pcmk__output_t *out, const char *name, + const char *short_desc, const char *long_desc, + enum pcmk__opt_flags filter); + +void pcmk__validate_cluster_options(GHashTable *options); bool pcmk__valid_interval_spec(const char *value); bool pcmk__valid_boolean(const char *value); -bool pcmk__valid_number(const char *value); -bool pcmk__valid_positive_number(const char *value); -bool pcmk__valid_quorum(const char *value); -bool pcmk__valid_script(const char *value); +bool pcmk__valid_int(const char *value); +bool pcmk__valid_positive_int(const char *value); +bool pcmk__valid_no_quorum_policy(const char *value); bool pcmk__valid_percentage(const char *value); +bool pcmk__valid_placement_strategy(const char *value); // from watchdog.c -long pcmk__get_sbd_timeout(void); +long pcmk__get_sbd_watchdog_timeout(void); bool pcmk__get_sbd_sync_resource_startup(void); -long pcmk__auto_watchdog_timeout(void); -bool pcmk__valid_sbd_timeout(const char *value); +long pcmk__auto_stonith_watchdog_timeout(void); +bool pcmk__valid_stonith_watchdog_timeout(const char *value); // Constants for environment variable names #define PCMK__ENV_AUTHKEY_LOCATION "authkey_location" @@ -93,8 +138,8 @@ bool pcmk__valid_sbd_timeout(const char *value); #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_SCHEMA_DIRECTORY "remote_schema_directory" #define PCMK__ENV_REMOTE_PID1 "remote_pid1" #define PCMK__ENV_REMOTE_PORT "remote_port" #define PCMK__ENV_RESPAWNED "respawned" @@ -123,30 +168,97 @@ bool pcmk__valid_sbd_timeout(const char *value); */ #define PCMK__ENV_SHUTDOWN_DELAY "shutdown_delay" -// Constants for cluster option names -#define PCMK__OPT_NODE_HEALTH_BASE "node-health-base" -#define PCMK__OPT_NODE_HEALTH_GREEN "node-health-green" -#define PCMK__OPT_NODE_HEALTH_RED "node-health-red" -#define PCMK__OPT_NODE_HEALTH_STRATEGY "node-health-strategy" -#define PCMK__OPT_NODE_HEALTH_YELLOW "node-health-yellow" +// @COMPAT Deprecated since 2.1.0 +#define PCMK__OPT_REMOVE_AFTER_STOP "remove-after-stop" // Constants for meta-attribute names -#define PCMK__META_ALLOW_UNHEALTHY_NODES "allow-unhealthy-nodes" +#define PCMK__META_CLONE "clone" +#define PCMK__META_CONTAINER "container" +#define PCMK__META_DIGESTS_ALL "digests-all" +#define PCMK__META_DIGESTS_SECURE "digests-secure" +#define PCMK__META_INTERNAL_RSC "internal_rsc" +#define PCMK__META_MIGRATE_SOURCE "migrate_source" +#define PCMK__META_MIGRATE_TARGET "migrate_target" +#define PCMK__META_ON_NODE "on_node" +#define PCMK__META_ON_NODE_UUID "on_node_uuid" +#define PCMK__META_OP_NO_WAIT "op_no_wait" +#define PCMK__META_OP_TARGET_RC "op_target_rc" +#define PCMK__META_PHYSICAL_HOST "physical-host" +#define PCMK__META_STONITH_ACTION "stonith_action" -// Constants for enumerated values for various options +/* @TODO Plug these in. Currently, they're never set. These are op attrs for use + * with https://projects.clusterlabs.org/T382. + */ +#define PCMK__META_CLEAR_FAILURE_OP "clear_failure_op" +#define PCMK__META_CLEAR_FAILURE_INTERVAL "clear_failure_interval" + +// @COMPAT Deprecated meta-attribute since 2.1.0 +#define PCMK__META_CAN_FAIL "can_fail" + +// @COMPAT Deprecated alias for PCMK__META_PROMOTED_MAX since 2.0.0 +#define PCMK__META_PROMOTED_MAX_LEGACY "master-max" + +// @COMPAT Deprecated alias for PCMK__META_PROMOTED_NODE_MAX since 2.0.0 +#define PCMK__META_PROMOTED_NODE_MAX_LEGACY "master-node-max" + +// @COMPAT Deprecated meta-attribute since 2.0.0 +#define PCMK__META_RESTART_TYPE "restart-type" + +// @COMPAT Deprecated meta-attribute since 2.0.0 +#define PCMK__META_ROLE_AFTER_FAILURE "role_after_failure" + +// Constants for enumerated values +#define PCMK__VALUE_ATTRD "attrd" +#define PCMK__VALUE_BOLD "bold" +#define PCMK__VALUE_BROADCAST "broadcast" +#define PCMK__VALUE_CIB "cib" +#define PCMK__VALUE_CIB_DIFF_NOTIFY "cib_diff_notify" +#define PCMK__VALUE_CIB_NOTIFY "cib_notify" +#define PCMK__VALUE_CIB_POST_NOTIFY "cib_post_notify" +#define PCMK__VALUE_CIB_PRE_NOTIFY "cib_pre_notify" +#define PCMK__VALUE_CIB_UPDATE_CONFIRMATION "cib_update_confirmation" #define PCMK__VALUE_CLUSTER "cluster" -#define PCMK__VALUE_CUSTOM "custom" -#define PCMK__VALUE_FENCING "fencing" -#define PCMK__VALUE_GREEN "green" +#define PCMK__VALUE_CRMD "crmd" +#define PCMK__VALUE_EN "en" +#define PCMK__VALUE_EPOCH "epoch" +#define PCMK__VALUE_HEALTH_RED "health_red" +#define PCMK__VALUE_HEALTH_YELLOW "health_yellow" +#define PCMK__VALUE_INIT "init" #define PCMK__VALUE_LOCAL "local" -#define PCMK__VALUE_MIGRATE_ON_RED "migrate-on-red" -#define PCMK__VALUE_NONE "none" -#define PCMK__VALUE_NOTHING "nothing" -#define PCMK__VALUE_ONLY_GREEN "only-green" -#define PCMK__VALUE_PROGRESSIVE "progressive" -#define PCMK__VALUE_QUORUM "quorum" -#define PCMK__VALUE_RED "red" -#define PCMK__VALUE_UNFENCING "unfencing" -#define PCMK__VALUE_YELLOW "yellow" +#define PCMK__VALUE_LRMD "lrmd" +#define PCMK__VALUE_MAINT "maint" +#define PCMK__VALUE_OUTPUT "output" +#define PCMK__VALUE_PASSWORD "password" +#define PCMK__VALUE_PING "ping" +#define PCMK__VALUE_PRIMITIVE "primitive" +#define PCMK__VALUE_REFRESH "refresh" +#define PCMK__VALUE_REQUEST "request" +#define PCMK__VALUE_RESPONSE "response" +#define PCMK__VALUE_RSC_FAILED "rsc-failed" +#define PCMK__VALUE_RSC_FAILURE_IGNORED "rsc-failure-ignored" +#define PCMK__VALUE_RSC_MANAGED "rsc-managed" +#define PCMK__VALUE_RSC_MULTIPLE "rsc-multiple" +#define PCMK__VALUE_RSC_OK "rsc-ok" +#define PCMK__VALUE_RUNNING "running" +#define PCMK__VALUE_SHUTDOWN_COMPLETE "shutdown_complete" +#define PCMK__VALUE_SHUTTING_DOWN "shutting_down" +#define PCMK__VALUE_ST_ASYNC_TIMEOUT_VALUE "st-async-timeout-value" +#define PCMK__VALUE_ST_NOTIFY "st_notify" +#define PCMK__VALUE_ST_NOTIFY_DISCONNECT "st_notify_disconnect" +#define PCMK__VALUE_ST_NOTIFY_FENCE "st_notify_fence" +#define PCMK__VALUE_ST_NOTIFY_HISTORY "st_notify_history" +#define PCMK__VALUE_ST_NOTIFY_HISTORY_SYNCED "st_notify_history_synced" +#define PCMK__VALUE_STARTING_DAEMONS "starting_daemons" +#define PCMK__VALUE_STONITH_NG "stonith-ng" +#define PCMK__VALUE_WAIT_FOR_PING "wait_for_ping" +#define PCMK__VALUE_WARNING "warning" + +/* @COMPAT Deprecated since 2.1.7 (used with PCMK__XA_ORDERING attribute of + * resource sets) + */ +#define PCMK__VALUE_GROUP "group" + +// @COMPAT Drop when daemon metadata commands are dropped +#define PCMK__VALUE_TIME "time" #endif // PCMK__OPTIONS_INTERNAL__H diff --git a/include/crm/common/output.h b/include/crm/common/output.h index 112ebcb..acb0a0e 100644 --- a/include/crm/common/output.h +++ b/include/crm/common/output.h @@ -1,5 +1,5 @@ /* - * Copyright 2021-2023 the Pacemaker project contributors + * Copyright 2021-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_OUTPUT__H -# define PCMK__CRM_COMMON_OUTPUT__H +#define PCMK__CRM_COMMON_OUTPUT__H #ifdef __cplusplus extern "C" { diff --git a/include/crm/common/output_internal.h b/include/crm/common/output_internal.h index 274bd85..79efef9 100644 --- a/include/crm/common/output_internal.h +++ b/include/crm/common/output_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 the Pacemaker project contributors + * Copyright 2019-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,16 +8,16 @@ */ #ifndef PCMK__OUTPUT_INTERNAL__H -# define PCMK__OUTPUT_INTERNAL__H +#define PCMK__OUTPUT_INTERNAL__H -# include <stdbool.h> -# include <stdint.h> -# include <stdio.h> -# include <libxml/tree.h> -# include <libxml/HTMLtree.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <libxml/tree.h> +#include <libxml/HTMLtree.h> -# include <glib.h> -# include <crm/common/results.h> +#include <glib.h> +#include <crm/common/results.h> #ifdef __cplusplus extern "C" { @@ -29,9 +29,9 @@ extern "C" { */ #if defined(PCMK__WITH_ATTRIBUTE_OUTPUT_ARGS) -# define PCMK__OUTPUT_ARGS(ARGS...) __attribute__((output_args(ARGS))) +#define PCMK__OUTPUT_ARGS(ARGS...) __attribute__((output_args(ARGS))) #else -# define PCMK__OUTPUT_ARGS(ARGS...) +#define PCMK__OUTPUT_ARGS(ARGS...) #endif typedef struct pcmk__output_s pcmk__output_t; @@ -143,10 +143,7 @@ typedef struct pcmk__supported_format_s { */ extern GOptionEntry pcmk__html_output_entries[]; -extern GOptionEntry pcmk__log_output_entries[]; -extern GOptionEntry pcmk__none_output_entries[]; extern GOptionEntry pcmk__text_output_entries[]; -extern GOptionEntry pcmk__xml_output_entries[]; pcmk__output_t *pcmk__mk_html_output(char **argv); pcmk__output_t *pcmk__mk_log_output(char **argv); @@ -155,11 +152,10 @@ pcmk__output_t *pcmk__mk_text_output(char **argv); pcmk__output_t *pcmk__mk_xml_output(char **argv); #define PCMK__SUPPORTED_FORMAT_HTML { "html", pcmk__mk_html_output, pcmk__html_output_entries } -#define PCMK__SUPPORTED_FORMAT_LOG { "log", pcmk__mk_log_output, pcmk__log_output_entries } -#define PCMK__SUPPORTED_FORMAT_NONE { PCMK__VALUE_NONE, pcmk__mk_none_output, \ - pcmk__none_output_entries } +#define PCMK__SUPPORTED_FORMAT_LOG { "log", pcmk__mk_log_output, NULL } +#define PCMK__SUPPORTED_FORMAT_NONE { PCMK_VALUE_NONE, pcmk__mk_none_output, NULL } #define PCMK__SUPPORTED_FORMAT_TEXT { "text", pcmk__mk_text_output, pcmk__text_output_entries } -#define PCMK__SUPPORTED_FORMAT_XML { "xml", pcmk__mk_xml_output, pcmk__xml_output_entries } +#define PCMK__SUPPORTED_FORMAT_XML { "xml", pcmk__mk_xml_output, NULL } /*! * \brief This structure contains everything that makes up a single output @@ -658,6 +654,8 @@ pcmk__register_messages(pcmk__output_t *out, /* Functions that are useful for implementing custom message formatters */ +void pcmk__output_text_set_fancy(pcmk__output_t *out, bool enabled); + /*! * \internal * \brief A printf-like function. @@ -737,29 +735,9 @@ pcmk__formatted_vprintf(pcmk__output_t *out, const char *format, va_list args) G void pcmk__text_prompt(const char *prompt, bool echo, char **dest); -/*! - * \internal - * \brief Get the log level used by the formatted output logger - * - * \param[in] out Output object - * - * \return Log level used by \p out - */ uint8_t pcmk__output_get_log_level(const pcmk__output_t *out); -/*! - * \internal - * \brief Set the log level used by the formatted output logger. - * - * \param[in,out] out The output functions structure. - * \param[in] log_level The log level constant (LOG_INFO, LOG_ERR, etc.) - * to use. - * - * \note By default, LOG_INFO is used. - * \note Almost all formatted output messages will respect this setting. - * However, out->err will always log at LOG_ERR. - */ void pcmk__output_set_log_level(pcmk__output_t *out, uint8_t log_level); @@ -887,16 +865,23 @@ xmlNodePtr pcmk__output_create_html_node(pcmk__output_t *out, const char *element_name, const char *id, const char *class_name, const char *text); +xmlNode *pcmk__html_create(xmlNode *parent, const char *name, const char *id, + const char *class); + /*! * \internal * \brief Add an HTML tag to the <head> section. * * The arguments after name are a NULL-terminated list of keys and values, * all of which will be added as attributes to the given tag. For instance, - * the following code would generate the tag "<meta http-equiv='refresh' content='19'>": + * the following code would generate the tag + * "<meta http-equiv='refresh' content='19'>": * * \code - * pcmk__html_add_header("meta", "http-equiv", "refresh", "content", "19", NULL); + * pcmk__html_add_header(PCMK__XE_META, + * PCMK__XA_HTTP_EQUIV, PCMK__VALUE_REFRESH, + * PCMK__XA_CONTENT, "19", + * NULL); * \endcode * * \param[in] name The HTML tag for the new node. @@ -918,12 +903,52 @@ G_GNUC_NULL_TERMINATED; void pcmk__output_and_clear_error(GError **error, pcmk__output_t *out); int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml); -void pcmk__xml_output_finish(pcmk__output_t *out, xmlNodePtr *xml); +void pcmk__xml_output_finish(pcmk__output_t *out, crm_exit_t exit_status, xmlNodePtr *xml); int pcmk__log_output_new(pcmk__output_t **out); int pcmk__text_output_new(pcmk__output_t **out, const char *filename); /*! * \internal + * \brief Check whether older style XML output is enabled + * + * The legacy flag should be used sparingly. Its meaning depends on the context + * in which it's used. + * + * \param[in] out Output object + * + * \return \c true if the \c legacy_xml flag is enabled for \p out, or \c false + * otherwise + */ +// @COMPAT This can be removed when `crm_mon -X` and daemon metadata are removed +bool pcmk__output_get_legacy_xml(pcmk__output_t *out); + +/*! + * \internal + * \brief Enable older style XML output + * + * The legacy flag should be used sparingly. Its meaning depends on the context + * in which it's used. + * + * \param[in,out] out Output object + */ +// @COMPAT This can be removed when `crm_mon -X` and daemon metadata are removed +void pcmk__output_set_legacy_xml(pcmk__output_t *out); + +/*! + * \internal + * \brief Enable using the <list> element for lists + * + * \note This function is only used in limited places and should not be + * used anywhere new. We are trying to discourage and ultimately remove + * uses of this style of list. + * + * @COMPAT This can be removed when the stonith_admin and crm_resource + * schemas can be changed + */ +void pcmk__output_enable_list_element(pcmk__output_t *out); + +/*! + * \internal * \brief Select an updated return code for an operation on a \p pcmk__output_t * * This function helps to keep an up-to-date record of the most relevant return diff --git a/include/crm/common/primitive_internal.h b/include/crm/common/primitive_internal.h new file mode 100644 index 0000000..394495e --- /dev/null +++ b/include/crm/common/primitive_internal.h @@ -0,0 +1,39 @@ +/* + * Copyright 2024 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_PRIMITIVE_INTERNAL__H +#define PCMK__CRM_COMMON_PRIMITIVE_INTERNAL__H + +#include <stdbool.h> // bool +#include <crm/common/scheduler_types.h> // pcmk_resource_t +#include <crm/common/resources.h> // pcmk_rsc_variant_primitive + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \internal + * \brief Check whether a resource is a primitive resource + * + * \param[in] rsc Resource to check + * + * \return true if \p rsc is a primitive, otherwise false + */ +static inline bool +pcmk__is_primitive(const pcmk_resource_t *rsc) +{ + return (rsc != NULL) && (rsc->variant == pcmk_rsc_variant_primitive); +} + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_PRIMITIVE_INTERNAL__H diff --git a/include/crm/common/remote_internal.h b/include/crm/common/remote_internal.h index 030c7a4..d55f25f 100644 --- a/include/crm/common/remote_internal.h +++ b/include/crm/common/remote_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 the Pacemaker project contributors + * Copyright 2008-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -7,8 +7,13 @@ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ -#ifndef PCMK__REMOTE_INTERNAL__H -# define PCMK__REMOTE_INTERNAL__H +#ifndef PCMK__CRM_COMMON_REMOTE_INTERNAL__H +#define PCMK__CRM_COMMON_REMOTE_INTERNAL__H + +#include <stdbool.h> // bool + +#include <crm/common/nodes.h> // pcmk_node_variant_remote +#include <crm/common/scheduler_types.h> // pcmk_node_t // internal functions from remote.c @@ -24,8 +29,54 @@ int pcmk__connect_remote(const char *host, int port, int timeout_ms, int pcmk__accept_remote_connection(int ssock, int *csock); void pcmk__sockaddr2str(const void *sa, char *s); -# ifdef HAVE_GNUTLS_GNUTLS_H -# include <gnutls/gnutls.h> +/*! + * \internal + * \brief Check whether a node is a Pacemaker Remote node of any kind + * + * \param[in] node Node to check + * + * \return true if \p node is a remote, guest, or bundle node, otherwise false + */ +static inline bool +pcmk__is_pacemaker_remote_node(const pcmk_node_t *node) +{ + return (node != NULL) && (node->details->type == pcmk_node_variant_remote); +} + +/*! + * \internal + * \brief Check whether a node is a remote node + * + * \param[in] node Node to check + * + * \return true if \p node is a remote node, otherwise false + */ +static inline bool +pcmk__is_remote_node(const pcmk_node_t *node) +{ + return pcmk__is_pacemaker_remote_node(node) + && ((node->details->remote_rsc == NULL) + || (node->details->remote_rsc->container == NULL)); +} + +/*! + * \internal + * \brief Check whether a node is a guest or bundle node + * + * \param[in] node Node to check + * + * \return true if \p node is a guest or bundle node, otherwise false + */ +static inline bool +pcmk__is_guest_or_bundle_node(const pcmk_node_t *node) +{ + return pcmk__is_pacemaker_remote_node(node) + && (node->details->remote_rsc != NULL) + && (node->details->remote_rsc->container != NULL); +} + +#ifdef HAVE_GNUTLS_GNUTLS_H +#include <gnutls/gnutls.h> gnutls_session_t *pcmk__new_tls_session(int csock, unsigned int conn_type, gnutls_credentials_type_t cred_type, @@ -44,5 +95,5 @@ int pcmk__read_handshake_data(const pcmk__client_t *client); */ int pcmk__tls_client_handshake(pcmk__remote_t *remote, int timeout_ms); -# endif // HAVE_GNUTLS_GNUTLS_H -#endif // PCMK__REMOTE_INTERNAL__H +#endif // HAVE_GNUTLS_GNUTLS_H +#endif // PCMK__CRM_COMMON_REMOTE_INTERNAL__H diff --git a/include/crm/common/resources.h b/include/crm/common/resources.h index 043dc1c..9b38e68 100644 --- a/include/crm/common/resources.h +++ b/include/crm/common/resources.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,8 +8,9 @@ */ #ifndef PCMK__CRM_COMMON_RESOURCES__H -# define PCMK__CRM_COMMON_RESOURCES__H +#define PCMK__CRM_COMMON_RESOURCES__H +#include <stdbool.h> // bool #include <sys/types.h> // time_t #include <libxml/tree.h> // xmlNode #include <glib.h> // gboolean, guint, GList, GHashTable @@ -27,171 +28,156 @@ extern "C" { * \ingroup core */ -//! Resource variants supported by Pacemaker +// Resource variants supported by Pacemaker +//!@{ +//! \deprecated Do not use 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 + 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 +// 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 + 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 +// 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 + 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 +// Resource scheduling flags enum pcmk_rsc_flags { - //! No resource flags set (compare with equality rather than bit set) + // No resource flags set (compare with equality rather than bit set) pcmk_no_rsc_flags = 0ULL, - //! Whether resource has been removed from the configuration + // Whether resource has been removed from the configuration pcmk_rsc_removed = (1ULL << 0), - //! Whether resource is managed + // Whether resource is managed pcmk_rsc_managed = (1ULL << 1), - //! Whether resource is blocked from further action + // Whether resource is blocked from further action pcmk_rsc_blocked = (1ULL << 2), - //! Whether resource has been removed but has a container + // Whether resource has been removed but has a container pcmk_rsc_removed_filler = (1ULL << 3), - //! Whether resource has clone notifications enabled + // Whether resource has clone notifications enabled pcmk_rsc_notify = (1ULL << 4), - //! Whether resource is not an anonymous clone instance + // Whether resource is not an anonymous clone instance pcmk_rsc_unique = (1ULL << 5), - //! Whether resource's class is "stonith" + // Whether resource's class is "stonith" pcmk_rsc_fence_device = (1ULL << 6), - //! Whether resource can be promoted and demoted + // Whether resource can be promoted and demoted pcmk_rsc_promotable = (1ULL << 7), - //! Whether resource has not yet been assigned to a node + // 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 + // 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 + // 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 + // 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 + // 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 + // 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 + // 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 + // Whether resource has \c PCMK_META_CRITICAL meta-attribute enabled pcmk_rsc_critical = (1ULL << 15), - //! Whether resource is considered failed + // Whether resource is considered failed pcmk_rsc_failed = (1ULL << 16), - //! Flag for non-scheduler code to use to detect recursion loops + // Flag for non-scheduler code to use to detect recursion loops pcmk_rsc_detect_loop = (1ULL << 17), - //! \deprecated Do not use + // \deprecated Do not use pcmk_rsc_runnable = (1ULL << 18), - //! Whether resource has pending start action in history + // Whether resource has pending start action in history pcmk_rsc_start_pending = (1ULL << 19), - //! \deprecated Do not use + // \deprecated Do not use pcmk_rsc_starting = (1ULL << 20), - //! \deprecated Do not use + // \deprecated Do not use pcmk_rsc_stopping = (1ULL << 21), - //! Whether resource is multiply active with recovery set to stop_unexpected + /* + * Whether resource is multiply active with recovery set to + * \c PCMK_VALUE_STOP_UNEXPECTED + */ pcmk_rsc_stop_unexpected = (1ULL << 22), - //! Whether resource is allowed to live-migrate + // Whether resource is allowed to live-migrate pcmk_rsc_migratable = (1ULL << 23), - //! Whether resource has an ignorable failure + // Whether resource has an ignorable failure pcmk_rsc_ignore_failure = (1ULL << 24), - //! Whether resource is an implicit container resource for a bundle replica + // 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 + // Whether resource, its node, or entire cluster is in maintenance mode pcmk_rsc_maintenance = (1ULL << 26), - //! \deprecated Do not use + // \deprecated Do not use pcmk_rsc_has_filler = (1ULL << 27), - //! Whether resource can be started or promoted only on quorate nodes + // 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 + // 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 + // 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 { @@ -259,12 +245,15 @@ enum pe_print_options { //!@} // Resource assignment methods (implementation defined by libpacemaker) -//! This type should be considered internal to Pacemaker +//! \deprecated Do not use (public access will be removed in a future release) typedef struct resource_alloc_functions_s pcmk_assignment_methods_t; -//! Resource object methods +// Resource object methods +// @COMPAT Make this internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) typedef struct resource_object_functions_s { - /*! + /* * \brief Parse variant-specific resource XML from CIB into struct members * * \param[in,out] rsc Partially unpacked resource @@ -274,7 +263,7 @@ typedef struct resource_object_functions_s { */ 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 @@ -287,7 +276,7 @@ typedef struct resource_object_functions_s { 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 @@ -302,11 +291,11 @@ typedef struct resource_object_functions_s { char *(*parameter)(pcmk_resource_t *rsc, pcmk_node_t *node, gboolean create, const char *name, pcmk_scheduler_t *scheduler); - //! \deprecated Do not use + // \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 @@ -316,7 +305,7 @@ typedef struct resource_object_functions_s { */ gboolean (*active)(pcmk_resource_t *rsc, gboolean all); - /*! + /* * \brief Get resource's current or assigned role * * \param[in] rsc Resource to check @@ -326,7 +315,7 @@ typedef struct resource_object_functions_s { */ 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 @@ -339,14 +328,14 @@ typedef struct resource_object_functions_s { 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, @@ -356,7 +345,7 @@ typedef struct resource_object_functions_s { */ 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 @@ -369,7 +358,7 @@ typedef struct resource_object_functions_s { 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 @@ -378,14 +367,14 @@ typedef struct resource_object_functions_s { * * \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. + * online node if the resource's \c PCMK_META_REQUIRES is + * \c PCMK_VALUE_QUORUM or \c PCMK_VALUE_NOTHING, otherwise \c 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 @@ -394,43 +383,53 @@ typedef struct resource_object_functions_s { */ unsigned int (*max_per_node)(const pcmk_resource_t *rsc); } pcmk_rsc_methods_t; +//!@} -//! Implementation of pcmk_resource_t +// Implementation of pcmk_resource_t +// @COMPAT Make this internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) struct pe_resource_s { - char *id; //!< Resource ID in configuration - char *clone_name; //!< Resource instance ID in history + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated Call pcmk_resource_id() instead + char *id; // Resource ID in configuration - //! Resource configuration (possibly expanded from template) + char *clone_name; // Resource instance ID in history + + // Resource configuration (possibly expanded from template) xmlNode *xml; - //! Original resource configuration, if using template + // Original resource configuration, if using template xmlNode *orig_xml; - //! Configuration of resource operations (possibly expanded from template) + // 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 + 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 + + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated Call pcmk_resource_is_managed() instead + 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 + 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 @@ -439,54 +438,51 @@ struct pe_resource_s { * 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 + pcmk_node_t *allocated_to; // Node resource is assigned to - //! The destination node, if migrate_to completed but migrate_from has not + // 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 + // The source node, if migrate_to completed but migrate_from has not pcmk_node_t *partial_migration_source; - //! Nodes where resource may be active + // Nodes where resource may be active GList *running_on; - //! Nodes where resource has been probed (key is node ID, not name) + // 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) + // 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 + 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 + 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 + 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 + 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 + 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 + 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 @@ -494,6 +490,10 @@ struct pe_resource_s { */ GHashTable *parameter_cache; }; +//!@} + +const char *pcmk_resource_id(const pcmk_resource_t *rsc); +bool pcmk_resource_is_managed(const pcmk_resource_t *rsc); #ifdef __cplusplus } diff --git a/include/crm/common/resources_internal.h b/include/crm/common/resources_internal.h new file mode 100644 index 0000000..42e88af --- /dev/null +++ b/include/crm/common/resources_internal.h @@ -0,0 +1,25 @@ +/* + * Copyright 2024 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_INTERNAL__H +#define PCMK__CRM_COMMON_RESOURCES_INTERNAL__H + +#include <crm/common/resources.h> // enum rsc_recovery_type + +#ifdef __cplusplus +extern "C" { +#endif + +const char *pcmk__multiply_active_text(enum rsc_recovery_type recovery); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_RESOURCES_INTERNAL__H diff --git a/include/crm/common/results.h b/include/crm/common/results.h index 87d00d2..a2d35dd 100644 --- a/include/crm/common/results.h +++ b/include/crm/common/results.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the Pacemaker project contributors + * Copyright 2012-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -7,7 +7,7 @@ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #ifndef PCMK__CRM_COMMON_RESULTS__H -# define PCMK__CRM_COMMON_RESULTS__H +#define PCMK__CRM_COMMON_RESULTS__H #ifdef __cplusplus extern "C" { @@ -39,10 +39,9 @@ extern "C" { # endif #endif -# define CRM_ASSERT(expr) do { \ +#define CRM_ASSERT(expr) do { \ if (!(expr)) { \ crm_abort(__FILE__, __func__, __LINE__, #expr, TRUE, FALSE); \ - abort(); /* crm_abort() doesn't always abort! */ \ } \ } while(0) @@ -65,31 +64,39 @@ extern "C" { */ // Legacy custom return codes for Pacemaker API functions (deprecated) -# define pcmk_ok 0 -# define PCMK_ERROR_OFFSET 190 /* Replacements on non-linux systems, see include/portability.h */ -# define PCMK_CUSTOM_OFFSET 200 /* Purely custom codes */ -# define pcmk_err_generic 201 -# define pcmk_err_no_quorum 202 -# define pcmk_err_schema_validation 203 -# define pcmk_err_transform_failed 204 -# define pcmk_err_old_data 205 -# define pcmk_err_diff_failed 206 -# define pcmk_err_diff_resync 207 -# define pcmk_err_cib_modified 208 -# define pcmk_err_cib_backup 209 -# define pcmk_err_cib_save 210 -# define pcmk_err_schema_unchanged 211 -# define pcmk_err_cib_corrupt 212 -# define pcmk_err_multiple 213 -# define pcmk_err_node_unknown 214 -# define pcmk_err_already 215 + +// NOTE: sbd (as of at least 1.5.2) uses this +#define pcmk_ok 0 + +#define PCMK_ERROR_OFFSET 190 /* Replacements on non-linux systems, see include/portability.h */ +#define PCMK_CUSTOM_OFFSET 200 /* Purely custom codes */ +#define pcmk_err_generic 201 +#define pcmk_err_no_quorum 202 +#define pcmk_err_schema_validation 203 +#define pcmk_err_transform_failed 204 +#define pcmk_err_old_data 205 + +// NOTE: sbd (as of at least 1.5.2) uses this +#define pcmk_err_diff_failed 206 + +// NOTE: sbd (as of at least 1.5.2) uses this +#define pcmk_err_diff_resync 207 + +#define pcmk_err_cib_modified 208 +#define pcmk_err_cib_backup 209 +#define pcmk_err_cib_save 210 +#define pcmk_err_schema_unchanged 211 +#define pcmk_err_cib_corrupt 212 +#define pcmk_err_multiple 213 +#define pcmk_err_node_unknown 214 +#define pcmk_err_already 215 /* On HPPA 215 is ENOSYM (Unknown error 215), which hopefully never happens. */ #ifdef __hppa__ -# define pcmk_err_bad_nvpair 250 /* 216 is ENOTSOCK */ -# define pcmk_err_unknown_format 252 /* 217 is EDESTADDRREQ */ +#define pcmk_err_bad_nvpair 250 /* 216 is ENOTSOCK */ +#define pcmk_err_unknown_format 252 /* 217 is EDESTADDRREQ */ #else -# define pcmk_err_bad_nvpair 216 -# define pcmk_err_unknown_format 217 +#define pcmk_err_bad_nvpair 216 +#define pcmk_err_unknown_format 217 #endif /*! @@ -151,6 +158,7 @@ enum pcmk_rc_e { // Values -1 through -1000 reserved for caller use + // NOTE: sbd (as of at least 1.5.2) uses this pcmk_rc_ok = 0 // Positive values reserved for system error numbers @@ -168,13 +176,19 @@ enum pcmk_rc_e { */ enum ocf_exitcode { PCMK_OCF_OK = 0, //!< Success + + // NOTE: booth (as of at least 1.1) uses this value PCMK_OCF_UNKNOWN_ERROR = 1, //!< Unspecified error + PCMK_OCF_INVALID_PARAM = 2, //!< Parameter invalid (in local context) PCMK_OCF_UNIMPLEMENT_FEATURE = 3, //!< Requested action not implemented PCMK_OCF_INSUFFICIENT_PRIV = 4, //!< Insufficient privileges PCMK_OCF_NOT_INSTALLED = 5, //!< Dependencies not available locally PCMK_OCF_NOT_CONFIGURED = 6, //!< Parameter invalid (inherently) + + // NOTE: booth (as of at least 1.1) uses this value PCMK_OCF_NOT_RUNNING = 7, //!< Service safely stopped + PCMK_OCF_RUNNING_PROMOTED = 8, //!< Service active and promoted PCMK_OCF_FAILED_PROMOTED = 9, //!< Service failed and possibly in promoted role PCMK_OCF_DEGRADED = 190, //!< Service active but more likely to fail soon @@ -209,6 +223,7 @@ enum ocf_exitcode { #endif }; +// NOTE: sbd (as of at least 1.5.2) uses this /*! * \enum crm_exit_e * \brief Exit status codes for tools and daemons @@ -356,15 +371,24 @@ enum pcmk_result_type { int pcmk_result_get_strings(int code, enum pcmk_result_type type, const char **name, const char **desc); const char *pcmk_rc_name(int rc); + +// NOTE: sbd (as of at least 1.5.2) uses this const char *pcmk_rc_str(int rc); + crm_exit_t pcmk_rc2exitc(int rc); enum ocf_exitcode pcmk_rc2ocf(int rc); int pcmk_rc2legacy(int rc); int pcmk_legacy2rc(int legacy_rc); + +// NOTE: sbd (as of at least 1.5.2) uses this const char *pcmk_strerror(int rc); + const char *pcmk_errorname(int rc); const char *crm_exit_name(crm_exit_t exit_code); + +// NOTE: sbd (as of at least 1.5.2) uses this const char *crm_exit_str(crm_exit_t exit_code); + _Noreturn crm_exit_t crm_exit(crm_exit_t rc); static inline const char * diff --git a/include/crm/common/results_compat.h b/include/crm/common/results_compat.h index 278e48e..31fc8f2 100644 --- a/include/crm/common/results_compat.h +++ b/include/crm/common/results_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 the Pacemaker project contributors + * Copyright 2022-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_RESULTS_COMPAT__H -# define PCMK__CRM_COMMON_RESULTS_COMPAT__H +#define PCMK__CRM_COMMON_RESULTS_COMPAT__H #include <crm/common/results.h> diff --git a/include/crm/common/results_internal.h b/include/crm/common/results_internal.h index 09907e9..c2a3f60 100644 --- a/include/crm/common/results_internal.h +++ b/include/crm/common/results_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 the Pacemaker project contributors + * Copyright 2020-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -12,13 +12,26 @@ #include <glib.h> // GQuark -// Generic result code type +extern const size_t pcmk__n_rc; int pcmk__result_bounds(enum pcmk_result_type, int *lower, int *upper); -// Standard Pacemaker API return codes - -extern const size_t pcmk__n_rc; +/*! + * \internal + * \brief Abort without dumping core if a pointer is \c NULL + * + * This is intended to check for memory allocation failure, rather than for null + * pointers in general. + * + * \param[in] ptr Pointer to check + */ +#define pcmk__mem_assert(ptr) do { \ + if ((ptr) == NULL) { \ + crm_abort(__FILE__, __func__, __LINE__, "Out of memory", FALSE, \ + TRUE); \ + crm_exit(CRM_EX_OSERR); \ + } \ + } while (0) /* Error domains for use with g_set_error */ diff --git a/include/crm/common/roles.h b/include/crm/common/roles.h index 1498097..e315d6b 100644 --- a/include/crm/common/roles.h +++ b/include/crm/common/roles.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_ROLES__H -# define PCMK__CRM_COMMON_ROLES__H +#define PCMK__CRM_COMMON_ROLES__H #ifdef __cplusplus extern "C" { @@ -20,6 +20,13 @@ extern "C" { * \ingroup core */ +// String equivalents of enum rsc_role_e + +#define PCMK_ROLE_STOPPED "Stopped" +#define PCMK_ROLE_STARTED "Started" +#define PCMK_ROLE_UNPROMOTED "Unpromoted" +#define PCMK_ROLE_PROMOTED "Promoted" + /*! * Possible roles that a resource can be in * (order matters; values can be compared with less than and greater than) @@ -55,6 +62,9 @@ enum rsc_role_e { #endif }; +const char *pcmk_role_text(enum rsc_role_e role); +enum rsc_role_e pcmk_parse_role(const char *role); + #ifdef __cplusplus } #endif diff --git a/include/crm/common/roles_internal.h b/include/crm/common/roles_internal.h index e304f13..7df71c6 100644 --- a/include/crm/common/roles_internal.h +++ b/include/crm/common/roles_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_ROLES_INTERNAL__H -# define PCMK__CRM_COMMON_ROLES_INTERNAL__H +#define PCMK__CRM_COMMON_ROLES_INTERNAL__H #ifdef __cplusplus extern "C" { @@ -16,13 +16,49 @@ extern "C" { // 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" +/*! + * \internal + * \brief Set resource flags + * + * \param[in,out] resource Resource to set flags for + * \param[in] flags_to_set Group of enum pcmk_rsc_flags to set + */ +#define pcmk__set_rsc_flags(resource, flags_to_set) do { \ + (resource)->flags = pcmk__set_flags_as(__func__, __LINE__, \ + LOG_TRACE, "Resource", (resource)->id, (resource)->flags, \ + (flags_to_set), #flags_to_set); \ + } while (0) + +/*! + * \internal + * \brief Clear resource flags + * + * \param[in,out] resource Resource to clear flags for + * \param[in] flags_to_clear Group of enum pcmk_rsc_flags to clear + */ +#define pcmk__clear_rsc_flags(resource, flags_to_clear) do { \ + (resource)->flags = pcmk__clear_flags_as(__func__, __LINE__, \ + LOG_TRACE, "Resource", (resource)->id, (resource)->flags, \ + (flags_to_clear), #flags_to_clear); \ + } while (0) + +/*! + * \internal + * \brief Get node where resource is currently active (if any) + * + * \param[in] rsc Resource to check + * + * \return Node that \p rsc is active on, if any, otherwise NULL + */ +static inline pcmk_node_t * +pcmk__current_node(const pcmk_resource_t *rsc) +{ + return (rsc == NULL)? NULL : rsc->fns->active_node(rsc, NULL, NULL); +} + #ifdef __cplusplus } #endif diff --git a/include/crm/common/rules.h b/include/crm/common/rules.h new file mode 100644 index 0000000..ad4e94f --- /dev/null +++ b/include/crm/common/rules.h @@ -0,0 +1,112 @@ +/* + * Copyright 2004-2024 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_RULES__H +#define PCMK__CRM_COMMON_RULES__H + +#include <glib.h> // guint, GHashTable +#include <regex.h> // regmatch_t +#include <libxml/tree.h> // xmlNode +#include <crm/common/iso8601.h> // crm_time_t + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief Scheduler API for rules + * \ingroup core + */ + +/* Allowed subexpressions of a rule + * @COMPAT This should be made internal at an API compatibility break + */ +//!@{ +//! \deprecated For Pacemaker use only +enum expression_type { + pcmk__condition_unknown = 0, // Unknown or invalid condition + pcmk__condition_rule = 1, // Nested rule + pcmk__condition_attribute = 2, // Node attribute expression + pcmk__condition_location = 3, // Node location expression + pcmk__condition_datetime = 5, // Date/time expression + pcmk__condition_resource = 7, // Resource agent expression + pcmk__condition_operation = 8, // Operation expression + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + not_expr = pcmk__condition_unknown, + nested_rule = pcmk__condition_rule, + attr_expr = pcmk__condition_attribute, + loc_expr = pcmk__condition_location, + role_expr = 4, + time_expr = pcmk__condition_datetime, + version_expr = 6, + rsc_expr = pcmk__condition_resource, + op_expr = pcmk__condition_operation, +#endif +}; +//!@} + +//! Data used to evaluate a rule (any NULL items are ignored) +typedef struct pcmk_rule_input { + // Used to evaluate date expressions + const crm_time_t *now; //!< Current time for rule evaluation purposes + + // Used to evaluate resource type expressions + const char *rsc_standard; //!< Resource standard that rule applies to + const char *rsc_provider; //!< Resource provider that rule applies to + const char *rsc_agent; //!< Resource agent that rule applies to + + // Used to evaluate operation type expressions + const char *op_name; //! Operation name that rule applies to + guint op_interval_ms; //! Operation interval that rule applies to + + // Remaining members are used to evaluate node attribute expressions + + /*! + * Node attributes for rule evaluation purposes + * + * \note Though not const, this is used only with g_hash_table_lookup(). + */ + GHashTable *node_attrs; + + // Remaining members are used only within location constraint rules + + /*! + * Resource parameters that can be used as the reference value source + * + * \note Though not const, this is used only with g_hash_table_lookup(). + */ + GHashTable *rsc_params; + + /*! + * Resource meta-attributes that can be used as the reference value source + * + * \note Though not const, this is used only with g_hash_table_lookup(). + */ + GHashTable *rsc_meta; + + //! Resource ID to compare against a location constraint's resource pattern + const char *rsc_id; + + //! Resource pattern submatches (as set by regexec()) for rsc_id + const regmatch_t *rsc_id_submatches; + + //! Number of entries in rsc_id_submatches + int rsc_id_nmatches; +} pcmk_rule_input_t; + +int pcmk_evaluate_rule(xmlNode *rule, const pcmk_rule_input_t *rule_input, + crm_time_t *next_change); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_RULES__H diff --git a/include/crm/common/rules_internal.h b/include/crm/common/rules_internal.h new file mode 100644 index 0000000..5fed3f7 --- /dev/null +++ b/include/crm/common/rules_internal.h @@ -0,0 +1,38 @@ +/* + * Copyright 2004-2024 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_RULES_INTERNAL__H +#define PCMK__CRM_COMMON_RULES_INTERNAL__H + +#include <regex.h> // regmatch_t +#include <libxml/tree.h> // xmlNode + +#include <crm/common/rules.h> // enum expression_type, etc. +#include <crm/common/iso8601.h> // crm_time_t + +enum pcmk__combine { + pcmk__combine_unknown, + pcmk__combine_and, + pcmk__combine_or, +}; + +enum expression_type pcmk__condition_type(const xmlNode *condition); +char *pcmk__replace_submatches(const char *string, const char *match, + const regmatch_t submatches[], int nmatches); +enum pcmk__combine pcmk__parse_combine(const char *combine); + +int pcmk__evaluate_date_expression(const xmlNode *date_expression, + const crm_time_t *now, + crm_time_t *next_change); +int pcmk__evaluate_condition(xmlNode *expr, const pcmk_rule_input_t *rule_input, + crm_time_t *next_change); +int pcmk__evaluate_rules(xmlNode *xml, const pcmk_rule_input_t *rule_input, + crm_time_t *next_change); + +#endif // PCMK__CRM_COMMON_RULES_INTERNAL__H diff --git a/include/crm/common/scheduler.h b/include/crm/common/scheduler.h index 96f9a62..f75d808 100644 --- a/include/crm/common/scheduler.h +++ b/include/crm/common/scheduler.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_SCHEDULER__H -# define PCMK__CRM_COMMON_SCHEDULER__H +#define PCMK__CRM_COMMON_SCHEDULER__H #include <sys/types.h> // time_t #include <libxml/tree.h> // xmlNode @@ -20,6 +20,7 @@ #include <crm/common/nodes.h> #include <crm/common/resources.h> #include <crm/common/roles.h> +#include <crm/common/rules.h> #include <crm/common/scheduler_types.h> #include <crm/common/tags.h> #include <crm/common/tickets.h> @@ -34,6 +35,7 @@ extern "C" { * \ingroup core */ +// NOTE: sbd (as of at least 1.5.2) uses this enum //! Possible responses to loss of quorum enum pe_quorum_policy { pcmk_no_quorum_freeze, //<! Do not recover resources from outside partition @@ -43,193 +45,250 @@ enum pe_quorum_policy { pcmk_no_quorum_demote, //<! Demote promotable resources and stop all others #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) + // NOTE: sbd (as of at least 1.5.2) uses this value //! \deprecated Use pcmk_no_quorum_freeze instead no_quorum_freeze = pcmk_no_quorum_freeze, + // NOTE: sbd (as of at least 1.5.2) uses this value //! \deprecated Use pcmk_no_quorum_stop instead no_quorum_stop = pcmk_no_quorum_stop, + // NOTE: sbd (as of at least 1.5.2) uses this value //! \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, + // NOTE: sbd (as of at least 1.5.2) uses this value //! \deprecated Use pcmk_no_quorum_demote instead no_quorum_demote = pcmk_no_quorum_demote, #endif }; -//! Scheduling options and conditions +// Scheduling options and conditions +//!@{ +//! \deprecated Do not use enum pcmk_scheduler_flags { - //! No scheduler flags set (compare with equality rather than bit set) + // No scheduler flags set (compare with equality rather than bit set) pcmk_sched_none = 0ULL, - // These flags are dynamically determined conditions + /* These flags are dynamically determined conditions */ - //! Whether partition has quorum (via have-quorum property) + // Whether partition has quorum (via \c PCMK_XA_HAVE_QUORUM attribute) + //! \deprecated Call pcmk_has_quorum() to check quorum instead pcmk_sched_quorate = (1ULL << 0), - //! Whether cluster is symmetric (via symmetric-cluster property) + // Whether cluster is symmetric (via symmetric-cluster property) pcmk_sched_symmetric_cluster = (1ULL << 1), - //! Whether cluster is in maintenance mode (via maintenance-mode property) + // Whether cluster is in maintenance mode (via maintenance-mode property) pcmk_sched_in_maintenance = (1ULL << 3), - //! Whether fencing is enabled (via stonith-enabled property) + // Whether fencing is enabled (via stonith-enabled property) pcmk_sched_fencing_enabled = (1ULL << 4), - //! Whether cluster has a fencing resource (via CIB resources) + // Whether cluster has a fencing resource (via CIB resources) + /*! \deprecated To indicate the cluster has a fencing resource, add either a + * fencing resource configuration or the have-watchdog cluster option to the + * input CIB + */ pcmk_sched_have_fencing = (1ULL << 5), - //! Whether any resource provides or requires unfencing (via CIB resources) + // 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) + // 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) + // 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) + /* + * Whether start failure should be treated as if + * \c PCMK_META_MIGRATION_THRESHOLD is 1 (via + * \c PCMK_OPT_START_FAILURE_IS_FATAL property) */ pcmk_sched_start_failure_fatal = (1ULL << 12), - //! \deprecated Do not use + // Unused pcmk_sched_remove_after_stop = (1ULL << 13), - //! Whether unseen nodes should be fenced (via startup-fencing property) + // 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 + // 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) + // 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 - /*! + /* 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 + // Whether sensitive resource attributes have been masked pcmk_sched_sanitized = (1ULL << 21), - //! Skip counting of total, disabled, and blocked resource instances + // 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 + // 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) + // 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 +// Implementation of pcmk_scheduler_t +// @COMPAT Make contents internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) 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 + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated To set scheduler iput, use pcmk_set_scheduler_cib() instead + xmlNode *input; // CIB XML + + crm_time_t *now; // Current time for evaluation purposes + char *dc_uuid; // Node ID of designated controller + + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated Call pcmk_get_dc() instead + 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 + + // NOTE: sbd (as of at least 1.5.2) uses this // @COMPAT Change to uint64_t at a compatibility break - unsigned long long flags; //!< Group of enum pcmk_scheduler_flags + //! \deprecated Call pcmk_has_quorum() to check quorum + unsigned long long flags; // Group of enum pcmk_scheduler_flags + + int stonith_timeout; // Value of stonith-timeout property + + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated Call pcmk_get_no_quorum_policy() to get no-quorum policy + enum pe_quorum_policy no_quorum_policy; // Response to loss of quorum - 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 + GHashTable *config_hash; // Cluster properties - //!< Ticket constraints unpacked from ticket state + // Ticket constraints unpacked from ticket state GHashTable *tickets; - //! Actions for which there can be only one (such as "fence node X") + // 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 + // NOTE: sbd (as of at least 1.5.2) uses this + //! \deprecated Call pcmk_find_node() to find a node instead + GList *nodes; // Nodes in cluster - //!< Ticket constraints unpacked by libpacemaker + 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 + 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 + 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 + void *priv; // For Pacemaker use only - guint node_pending_timeout; //!< Pending join times out after this (ms) + guint node_pending_timeout; // Pending join times out after this (ms) }; +//!@} + +/* Whether the scheduler input currently being processed has warnings or errors + * + * @COMPAT When we can break API compatibility, we should make these + * internal-only. Ideally they would be converted to pcmk_scheduler_flags + * values, but everywhere they're needed doesn't currently have access to the + * scheduler data. + */ +//!@{ +//! \deprecated Do not use +extern gboolean was_processing_error; +extern gboolean was_processing_warning; +//!@} + +pcmk_node_t *pcmk_get_dc(const pcmk_scheduler_t *scheduler); +enum pe_quorum_policy pcmk_get_no_quorum_policy(const pcmk_scheduler_t + *scheduler); + +int pcmk_set_scheduler_cib(pcmk_scheduler_t *scheduler, xmlNode *cib); + +bool pcmk_has_quorum(const pcmk_scheduler_t *scheduler); +pcmk_node_t *pcmk_find_node(const pcmk_scheduler_t *scheduler, + const char *node_name); #ifdef __cplusplus } diff --git a/include/crm/common/scheduler_internal.h b/include/crm/common/scheduler_internal.h index 1f1da9f..c990795 100644 --- a/include/crm/common/scheduler_internal.h +++ b/include/crm/common/scheduler_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,43 +8,29 @@ */ #ifndef PCMK__CRM_COMMON_SCHEDULER_INTERNAL__H -# define PCMK__CRM_COMMON_SCHEDULER_INTERNAL__H +#define PCMK__CRM_COMMON_SCHEDULER_INTERNAL__H #include <crm/common/action_relation_internal.h> +#include <crm/common/actions_internal.h> +#include <crm/common/attrs_internal.h> +#include <crm/common/bundles_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/history_internal.h> +#include <crm/common/location_internal.h> +#include <crm/common/nodes_internal.h> +#include <crm/common/primitive_internal.h> +#include <crm/common/remote_internal.h> +#include <crm/common/resources_internal.h> #include <crm/common/roles_internal.h> +#include <crm/common/rules_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. @@ -57,9 +43,87 @@ enum pcmk__check_parameters { pcmk__check_active, }; -// Group of enum pcmk__sched_warnings flags for warnings we want to log once +// Group of enum pcmk__warnings flags for warnings we want to log once extern uint32_t pcmk__warnings; +/*! + * \internal + * \brief Log a resource-tagged message at info severity + * + * \param[in] rsc Tag message with this resource's ID + * \param[in] fmt... printf(3)-style format and arguments + */ +#define pcmk__rsc_info(rsc, fmt, args...) \ + crm_log_tag(LOG_INFO, ((rsc) == NULL)? "<NULL>" : (rsc)->id, (fmt), ##args) + +/*! + * \internal + * \brief Log a resource-tagged message at debug severity + * + * \param[in] rsc Tag message with this resource's ID + * \param[in] fmt... printf(3)-style format and arguments + */ +#define pcmk__rsc_debug(rsc, fmt, args...) \ + crm_log_tag(LOG_DEBUG, ((rsc) == NULL)? "<NULL>" : (rsc)->id, (fmt), ##args) + +/*! + * \internal + * \brief Log a resource-tagged message at trace severity + * + * \param[in] rsc Tag message with this resource's ID + * \param[in] fmt... printf(3)-style format and arguments + */ +#define pcmk__rsc_trace(rsc, fmt, args...) \ + crm_log_tag(LOG_TRACE, ((rsc) == NULL)? "<NULL>" : (rsc)->id, (fmt), ##args) + +/*! + * \internal + * \brief Log an error and remember that current scheduler input has errors + * + * \param[in] fmt... printf(3)-style format and arguments + */ +#define pcmk__sched_err(fmt...) do { \ + was_processing_error = TRUE; \ + crm_err(fmt); \ + } while (0) + +/*! + * \internal + * \brief Log a warning and remember that current scheduler input has warnings + * + * \param[in] fmt... printf(3)-style format and arguments + */ +#define pcmk__sched_warn(fmt...) do { \ + was_processing_warning = TRUE; \ + crm_warn(fmt); \ + } while (0) + +/*! + * \internal + * \brief Set scheduler flags + * + * \param[in,out] scheduler Scheduler data + * \param[in] flags_to_set Group of enum pcmk_scheduler_flags to set + */ +#define pcmk__set_scheduler_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) + +/*! + * \internal + * \brief Clear scheduler flags + * + * \param[in,out] scheduler Scheduler data + * \param[in] flags_to_clear Group of enum pcmk_scheduler_flags to clear + */ +#define pcmk__clear_scheduler_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) + #ifdef __cplusplus } #endif diff --git a/include/crm/common/scheduler_types.h b/include/crm/common/scheduler_types.h index 5c4a193..970d3e4 100644 --- a/include/crm/common/scheduler_types.h +++ b/include/crm/common/scheduler_types.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 the Pacemaker project contributors + * Copyright 2023-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_SCHEDULER_TYPES__H -# define PCMK__CRM_COMMON_SCHEDULER_TYPES__H +#define PCMK__CRM_COMMON_SCHEDULER_TYPES__H #ifdef __cplusplus extern "C" { diff --git a/include/crm/common/schemas.h b/include/crm/common/schemas.h new file mode 100644 index 0000000..81fdc19 --- /dev/null +++ b/include/crm/common/schemas.h @@ -0,0 +1,32 @@ +/* + * Copyright 2024 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_SCHEMAS__H +#define PCMK__CRM_COMMON_SCHEMAS__H + +#include <stdbool.h> // bool +#include <libxml/tree.h> // xmlNode + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief XML schema API + * \ingroup core + */ + +int pcmk_update_configured_schema(xmlNode **xml, bool to_logs); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_SCHEMAS__H diff --git a/include/crm/common/schemas_internal.h b/include/crm/common/schemas_internal.h new file mode 100644 index 0000000..0104016 --- /dev/null +++ b/include/crm/common/schemas_internal.h @@ -0,0 +1,37 @@ +/* + * Copyright 2006-2024 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__SCHEMAS_INTERNAL__H +#define PCMK__SCHEMAS_INTERNAL__H + +#include <glib.h> // GList, gboolean +#include <libxml/tree.h> // xmlNode, xmlRelaxNGValidityErrorFunc + +void crm_schema_init(void); +void crm_schema_cleanup(void); + +void pcmk__load_schemas_from_dir(const char *dir); +void pcmk__sort_schemas(void); +GList *pcmk__schema_files_later_than(const char *name); +void pcmk__build_schema_xml_node(xmlNode *parent, const char *name, + GList **already_included); +const char *pcmk__remote_schema_dir(void); +GList *pcmk__get_schema(const char *name); +const char *pcmk__highest_schema_name(void); +int pcmk__cmp_schemas_by_name(const char *schema1_name, + const char *schema2_name); +bool pcmk__validate_xml(xmlNode *xml_blob, const char *validation, + xmlRelaxNGValidityErrorFunc error_handler, + void *error_handler_context); +bool pcmk__configured_schema_validates(xmlNode *xml); +int pcmk__update_schema(xmlNode **xml, const char *max_schema_name, + bool transform, bool to_logs); +void pcmk__warn_if_schema_deprecated(const char *schema); + +#endif // PCMK__SCHEMAS_INTERNAL__H diff --git a/include/crm/common/scores.h b/include/crm/common/scores.h new file mode 100644 index 0000000..4b73f66 --- /dev/null +++ b/include/crm/common/scores.h @@ -0,0 +1,33 @@ +/* + * Copyright 2004-2024 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_SCORES__H +#define PCMK__CRM_COMMON_SCORES__H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file + * \brief Pacemaker APIs related to scores + * \ingroup core + */ + +//! Integer score to use to represent "infinity" +#define PCMK_SCORE_INFINITY 1000000 + +const char *pcmk_readable_score(int score); +int char2score(const char *score); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_SCORES__H diff --git a/include/crm/common/scores_compat.h b/include/crm/common/scores_compat.h new file mode 100644 index 0000000..f4515d8 --- /dev/null +++ b/include/crm/common/scores_compat.h @@ -0,0 +1,37 @@ +/* + * Copyright 2004-2024 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_SCORES_COMPAT__H +#define PCMK__CRM_COMMON_SCORES_COMPAT__H + +#include <sys/types.h> // size_t + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file + * \brief Deprecated Pacemaker score APIs + * \ingroup core + * \deprecated Do not include this header directly. The APIs in this header, and + * the header itself, will be removed in a future release. + */ + +//! \deprecated Use pcmk_readable_score() instead +char *score2char(int score); + +//! \deprecated Use pcmk_readable_score() instead +char *score2char_stack(int score, char *buf, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_SCORES_COMPAT__H diff --git a/include/crm/common/scores_internal.h b/include/crm/common/scores_internal.h new file mode 100644 index 0000000..ec9213c --- /dev/null +++ b/include/crm/common/scores_internal.h @@ -0,0 +1,15 @@ +/* + * Copyright 2022-2024 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_SCORES_INTERNAL__H +#define PCMK__CRM_COMMON_SCORES_INTERNAL__H + +int pcmk__add_scores(int score1, int score2); + +#endif // PCMK__CRM_COMMON_SCORES_INTERNAL__H diff --git a/include/crm/common/strings_internal.h b/include/crm/common/strings_internal.h index cd394d9..a34a9f8 100644 --- a/include/crm/common/strings_internal.h +++ b/include/crm/common/strings_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 the Pacemaker project contributors + * Copyright 2015-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -52,6 +52,7 @@ GHashTable *pcmk__strkey_table(GDestroyNotify key_destroy_func, GHashTable *pcmk__strikey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func); GHashTable *pcmk__str_table_dup(GHashTable *old_table); +void pcmk__insert_dup(GHashTable *table, const char *name, const char *value); /*! * \internal @@ -141,7 +142,24 @@ bool pcmk__char_in_any_str(int ch, ...) G_GNUC_NULL_TERMINATED; int pcmk__strcmp(const char *s1, const char *s2, uint32_t flags); int pcmk__numeric_strcasecmp(const char *s1, const char *s2); + +char *pcmk__str_copy_as(const char *file, const char *function, uint32_t line, + const char *str); + +/*! + * \internal + * \brief Copy a string, asserting on failure + * + * \param[in] str String to copy (can be \c NULL) + * + * \return Newly allocated copy of \p str, or \c NULL if \p str is \c NULL + * + * \note The caller is responsible for freeing the return value using \c free(). + */ +#define pcmk__str_copy(str) pcmk__str_copy_as(__FILE__, __func__, __LINE__, str) + void pcmk__str_update(char **str, const char *value); + void pcmk__g_strcat(GString *buffer, ...) G_GNUC_NULL_TERMINATED; static inline bool @@ -208,7 +226,7 @@ pcmk__ttoa(time_t epoch_time) static inline const char * pcmk__btoa(bool condition) { - return condition? "true" : "false"; + return condition? PCMK_VALUE_TRUE : PCMK_VALUE_FALSE; } #endif /* PCMK__STRINGS_INTERNAL__H */ diff --git a/include/crm/common/tags.h b/include/crm/common/tags.h index 3f4861d..4e3736f 100644 --- a/include/crm/common/tags.h +++ b/include/crm/common/tags.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_TAGS__H -# define PCMK__CRM_COMMON_TAGS__H +#define PCMK__CRM_COMMON_TAGS__H #include <glib.h> // GList @@ -22,11 +22,15 @@ extern "C" { * \ingroup core */ -//! Configuration tag object +// Configuration tag object +// @COMPAT Make internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) typedef struct pe_tag_s { - char *id; //!< XML ID of tag - GList *refs; //!< XML IDs of objects that reference the tag + char *id; // XML ID of tag + GList *refs; // XML IDs of objects that reference the tag } pcmk_tag_t; +//!@} #ifdef __cplusplus } diff --git a/include/crm/common/tickets.h b/include/crm/common/tickets.h index 40079e9..cd33420 100644 --- a/include/crm/common/tickets.h +++ b/include/crm/common/tickets.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,7 +8,7 @@ */ #ifndef PCMK__CRM_COMMON_TICKETS__H -# define PCMK__CRM_COMMON_TICKETS__H +#define PCMK__CRM_COMMON_TICKETS__H #include <sys/types.h> // time_t #include <glib.h> // gboolean, GHashTable @@ -23,14 +23,18 @@ extern "C" { * \ingroup core */ -//! Ticket constraint object +// Ticket constraint object +// @COMPAT Make internal when we can break API backward compatibility +//!@{ +//! \deprecated Do not use (public access will be removed in a future release) 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 + 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 } diff --git a/include/crm/common/unittest_internal.h b/include/crm/common/unittest_internal.h index 1fc8501..565dcc9 100644 --- a/include/crm/common/unittest_internal.h +++ b/include/crm/common/unittest_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 the Pacemaker project contributors + * Copyright 2022-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -19,11 +19,83 @@ #include <cmocka.h> +#include <crm/common/xml.h> + #ifndef CRM_COMMON_UNITTEST_INTERNAL__H #define CRM_COMMON_UNITTEST_INTERNAL__H /* internal unit testing related utilities */ +#if (PCMK__WITH_COVERAGE == 1) +/* This function isn't exposed anywhere. The following prototype was taken from + * /usr/lib/gcc/x86_64-redhat-linux/??/include/gcov.h + */ +extern void __gcov_dump(void); +#else +#define __gcov_dump() +#endif + +/*! + * \internal + * \brief Assert that the XML output from an API function is valid + * + * \param[in] xml The XML output of some public pacemaker API function + * + * Run the given XML through xmllint and attempt to validate it against the + * api-result.rng schema file. Assert if validation fails. + * + * \note PCMK_schema_directory needs to be set to the directory containing + * the built schema files before calling this function. Typically, + * this will be done in Makefile.am. + */ +void pcmk__assert_validates(xmlNode *xml); + +/*! + * \internal + * \brief Perform setup for a group of unit tests that will manipulate XML + * + * This function is suitable for being passed as the first argument to the + * \c PCMK__UNIT_TEST macro. + * + * \param[in] state The cmocka state object, currently unused by this + * function + */ +int pcmk__xml_test_setup_group(void **state); + +/*! + * \internal + * \brief Copy the given CIB file to a temporary file so it can be modified + * as part of doing unit tests, returning the full temporary file or + * \c NULL on error. + * + * This function should be called as part of the process of setting up any + * single unit test that would access and modify a CIB. That is, it should + * be called from whatever function is the second argument to + * cmocka_unit_test_setup_teardown. + * + * \param[in] in_file The filename of the input CIB file, which must + * exist in the \c $PCMK_CTS_CLI_DIR directory. This + * should only be the filename, not the complete + * path. + */ +char *pcmk__cib_test_copy_cib(const char *in_file); + +/*! + * \internal + * \brief Clean up whatever was done by a previous call to + * \c pcmk__cib_test_copy_cib. + * + * This function should be called as part of the process of tearing down + * any single unit test that accessed a CIB. That is, it should be called + * from whatever function is the third argument to + * \c cmocka_unit_test_setup_teardown. + * + * \param[in] out_path The complete path to the temporary CIB location. + * This is the return value of + * \c pcmk__cib_test_copy_cib. + */ +void pcmk__cib_test_cleanup(char *out_path); + /*! * \internal * \brief Assert that a statement aborts through CRM_ASSERT(). @@ -51,6 +123,7 @@ struct rlimit cores = { 0, 0 }; \ setrlimit(RLIMIT_CORE, &cores); \ stmt; \ + __gcov_dump(); \ _exit(0); \ } else if (p > 0) { \ int wstatus = 0; \ @@ -67,6 +140,15 @@ /*! * \internal + * \brief Assert that a statement aborts + * + * This is exactly the same as pcmk__assert_asserts (CRM_ASSERT() is implemented + * with abort()), but given a different name for clarity. + */ +#define pcmk__assert_aborts(stmt) pcmk__assert_asserts(stmt) + +/*! + * \internal * \brief Assert that a statement exits with the expected exit status. * * \param[in] stmt Statement to execute; can be an expression. @@ -87,6 +169,7 @@ struct rlimit cores = { 0, 0 }; \ setrlimit(RLIMIT_CORE, &cores); \ stmt; \ + __gcov_dump(); \ _exit(CRM_EX_NONE); \ } else if (p > 0) { \ int wstatus = 0; \ diff --git a/include/crm/common/util.h b/include/crm/common/util.h index c75a55e..2ae3f8e 100644 --- a/include/crm/common/util.h +++ b/include/crm/common/util.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,20 +8,22 @@ */ #ifndef PCMK__CRM_COMMON_UTIL__H -# define PCMK__CRM_COMMON_UTIL__H - -# include <sys/types.h> // gid_t, mode_t, size_t, time_t, uid_t -# include <stdlib.h> -# include <stdbool.h> -# include <stdint.h> // uint32_t -# include <limits.h> -# include <signal.h> -# include <glib.h> - -# include <crm/common/acl.h> -# include <crm/common/actions.h> -# include <crm/common/agents.h> -# include <crm/common/results.h> +#define PCMK__CRM_COMMON_UTIL__H + +#include <sys/types.h> // gid_t, mode_t, size_t, time_t, uid_t +#include <stdlib.h> +#include <stdbool.h> +#include <stdint.h> // uint32_t +#include <limits.h> +#include <signal.h> +#include <glib.h> + +#include <crm/common/acl.h> +#include <crm/common/actions.h> +#include <crm/common/agents.h> +#include <crm/common/results.h> +#include <crm/common/scores.h> +#include <crm/common/nvpair.h> #ifdef __cplusplus extern "C" { @@ -33,29 +35,28 @@ extern "C" { * \ingroup core */ - -# define ONLINESTATUS "online" // Status of an online client -# define OFFLINESTATUS "offline" // Status of an offline client - /* public node attribute functions (from attrd_client.c) */ char *pcmk_promotion_score_name(const char *rsc_id); /* public Pacemaker Remote functions (from remote.c) */ int crm_default_remote_port(void); -/* public score-related functions (from scores.c) */ -const char *pcmk_readable_score(int score); -int char2score(const char *score); -int pcmk__add_scores(int score1, int score2); - /* public string functions (from strings.c) */ + +// NOTE: sbd (as of at least 1.5.2) uses this gboolean crm_is_true(const char *s); + int crm_str_to_boolean(const char *s, int *ret); + +// NOTE: sbd (as of at least 1.5.2) uses this long long crm_get_msec(const char *input); + char * crm_strip_trailing_newline(char *str); + +// NOTE: sbd (as of at least 1.5.2) uses this char *crm_strdup_printf(char const *format, ...) G_GNUC_PRINTF(1, 2); -guint crm_parse_interval_spec(const char *input); +int pcmk_parse_interval_spec(const char *input, guint *result_ms); int compare_version(const char *version1, const char *version2); @@ -98,9 +99,6 @@ pcmk_all_flags_set(uint64_t flag_group, uint64_t flags_to_check) */ #define pcmk_is_set(g, f) pcmk_all_flags_set((g), (f)) -char *crm_meta_name(const char *field); -const char *crm_meta_value(GHashTable * hash, const char *field); - char *crm_md5sum(const char *buffer); char *crm_generate_uuid(void); @@ -115,8 +113,6 @@ int pcmk_daemon_user(uid_t *uid, gid_t *gid); void crm_gnutls_global_init(void); #endif -char *pcmk_hostname(void); - bool pcmk_str_is_infinity(const char *s); bool pcmk_str_is_minus_infinity(const char *s); diff --git a/include/crm/common/util_compat.h b/include/crm/common/util_compat.h index 7a60208..dad72ec 100644 --- a/include/crm/common/util_compat.h +++ b/include/crm/common/util_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,11 +8,11 @@ */ #ifndef PCMK__CRM_COMMON_UTIL_COMPAT__H -# define PCMK__CRM_COMMON_UTIL_COMPAT__H +#define PCMK__CRM_COMMON_UTIL_COMPAT__H -# include <glib.h> -# include <libxml/tree.h> -# include <crm/common/util.h> +#include <glib.h> +#include <libxml/tree.h> +#include <crm/common/util.h> #ifdef __cplusplus extern "C" { @@ -27,7 +27,7 @@ extern "C" { * release. */ -//! \deprecated Use crm_parse_interval_spec() instead +//! \deprecated Do not use #define crm_get_interval crm_parse_interval_spec //! \deprecated Do not use @@ -40,6 +40,7 @@ is_not_set(long long word, long long bit) return ((word & bit) == 0); } +// NOTE: sbd (as of at least 1.5.2) uses this //! \deprecated Use pcmk_is_set() or pcmk_all_flags_set() instead static inline gboolean is_set(long long word, long long bit) @@ -86,7 +87,7 @@ long long crm_parse_ll(const char *text, const char *default_text); int crm_parse_int(const char *text, const char *default_text); //! \deprecated Use strtoll() instead -# define crm_atoi(text, default_text) crm_parse_int(text, default_text) +#define crm_atoi(text, default_text) crm_parse_int(text, default_text) //! \deprecated Use g_str_hash() instead guint g_str_hash_traditional(gconstpointer v); @@ -158,11 +159,17 @@ crm_ttoa(time_t epoch_time) //! \deprecated Do not use Pacemaker libraries for generic I/O void crm_build_path(const char *path_c, mode_t mode); -//! \deprecated Use pcmk_readable_score() instead -char *score2char(int score); +//! \deprecated Use \c pcmk_parse_interval_spec() instead +guint crm_parse_interval_spec(const char *input); + +//! \deprecated Use \c PCMK_VALUE_ONLINE instead +#define ONLINESTATUS PCMK_VALUE_ONLINE + +//! \deprecated Use \c PCMK_VALUE_OFFLINE instead +#define OFFLINESTATUS PCMK_VALUE_OFFLINE -//! \deprecated Use pcmk_readable_score() instead -char *score2char_stack(int score, char *buf, size_t len); +//! \deprecated Use \c uname() instead +char *pcmk_hostname(void); #ifdef __cplusplus } diff --git a/include/crm/common/xml.h b/include/crm/common/xml.h index ac839d3..fd7e185 100644 --- a/include/crm/common/xml.h +++ b/include/crm/common/xml.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,22 +8,25 @@ */ #ifndef PCMK__CRM_COMMON_XML__H -# define PCMK__CRM_COMMON_XML__H +#define PCMK__CRM_COMMON_XML__H -# include <stdio.h> -# include <sys/types.h> -# include <unistd.h> +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> -# include <stdlib.h> -# include <errno.h> -# include <fcntl.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> -# include <libxml/tree.h> -# include <libxml/xpath.h> +#include <libxml/tree.h> +#include <libxml/xpath.h> -# include <crm/crm.h> -# include <crm/common/nvpair.h> +#include <crm/crm.h> +#include <crm/common/nvpair.h> +#include <crm/common/schemas.h> +#include <crm/common/xml_io.h> +#include <crm/common/xml_names.h> #ifdef __cplusplus extern "C" { @@ -35,218 +38,35 @@ extern "C" { * \ingroup core */ -/* Define compression parameters for IPC messages - * - * Compression costs a LOT, so we don't want to do it unless we're hitting - * message limits. Currently, we use 128KB as the threshold, because higher - * values don't play well with the heartbeat stack. With an earlier limit of - * 10KB, compressing 184 of 1071 messages accounted for 23% of the total CPU - * used by the cib. - */ -# define CRM_BZ2_BLOCKS 4 -# define CRM_BZ2_WORK 20 -# define CRM_BZ2_THRESHOLD 128 * 1024 - 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); - -/* - * \brief xmlCopyPropList ACLs-sensitive replacement expading i++ notation - * - * The gist is the same as with \c{xmlCopyPropList(target, src->properties)}. - * The function exits prematurely when any attribute cannot be copied for - * ACLs violation. Even without bailing out, the result can possibly be - * incosistent with expectations in that case, hence the caller shall, - * aposteriori, verify that no document-level-tracked denial was indicated - * with \c{xml_acl_denied(target)} and drop whole such intermediate object. - * - * \param[in,out] target Element to receive attributes from #src element - * \param[in] src Element carrying attributes to copy over to #target - * - * \note Original commit 1c632c506 sadly haven't stated which otherwise - * assumed behaviours of xmlCopyPropList were missing beyond otherwise - * custom extensions like said ACLs and "atomic increment" (that landed - * later on, anyway). - */ -void copy_in_properties(xmlNode *target, const xmlNode *src); - -void expand_plus_plus(xmlNode * target, const char *name, const char *value); -void fix_plus_plus_recursive(xmlNode * target); - -/* - * Create a node named "name" as a child of "parent" - * If parent is NULL, creates an unconnected node. - * - * Returns the created node - * - */ -xmlNode *create_xml_node(xmlNode * parent, const char *name); - -/* - * Create a node named "name" as a child of "parent", giving it the provided - * text content. - * If parent is NULL, creates an unconnected node. - * - * Returns the created node - * - */ -xmlNode *pcmk_create_xml_text_node(xmlNode * parent, const char *name, const char *content); - -/* - * Create a new HTML node named "element_name" as a child of "parent", giving it the - * provided text content. Optionally, apply a CSS #id and #class. - * - * Returns the created node. - */ -xmlNode *pcmk_create_html_node(xmlNode * parent, const char *element_name, const char *id, - const char *class_name, const char *text); - -/* - * - */ -void purge_diff_markers(xmlNode * a_node); - -/* - * Returns a deep copy of src_node - * - */ -xmlNode *copy_xml(xmlNode * src_node); - -/* - * Add a copy of xml_node to new_parent - */ -xmlNode *add_node_copy(xmlNode * new_parent, xmlNode * xml_node); - -/* - * XML I/O Functions - * - * Whitespace between tags is discarded. - */ -xmlNode *filename2xml(const char *filename); - -xmlNode *stdin2xml(void); - -xmlNode *string2xml(const char *input); - -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(const xmlNode *xml); -char *dump_xml_formatted_with_text(const xmlNode *xml); -char *dump_xml_unformatted(const xmlNode *xml); - -/* - * Diff related Functions - */ -xmlNode *diff_xml_object(xmlNode * left, xmlNode * right, gboolean suppress); - -xmlNode *subtract_xml_object(xmlNode * parent, xmlNode * left, xmlNode * right, - gboolean full, gboolean * changed, const char *marker); - -gboolean can_prune_leaf(xmlNode * xml_node); /* * Searching & Modifying */ -xmlNode *find_xml_node(const xmlNode *root, const char *search_path, - gboolean must_find); - -void xml_remove_prop(xmlNode * obj, const char *name); - -gboolean replace_xml_child(xmlNode * parent, xmlNode * child, xmlNode * update, - gboolean delete_only); - -gboolean update_xml_child(xmlNode * child, xmlNode * to_update); - -int find_xml_children(xmlNode ** children, xmlNode * root, - const char *tag, const char *field, const char *value, - gboolean search_matches); +// NOTE: sbd (as of at least 1.5.2) uses this 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_map_element_name(const xmlNode *xml) -{ - if (xml == NULL) { - return NULL; - } else if (strcmp((const char *) xml->name, "master") == 0) { - return "clone"; - } else { - return (const char *) xml->name; - } -} 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, const char *version); -/* schema-related functions (from schemas.c) */ -gboolean validate_xml(xmlNode * xml_blob, const char *validation, gboolean to_logs); -gboolean validate_xml_verbose(const xmlNode *xml_blob); - -/*! - * \brief Update CIB XML to most recent schema version - * - * "Update" means either actively employ XSLT-based transformation(s) - * (if intermediate product to transform valid per its declared schema version, - * transformation available, proceeded successfully with a result valid per - * expectated newer schema version), or just try to bump the marked validating - * schema until all gradually rising schema versions attested or the first - * such attempt subsequently fails to validate. Which of the two styles will - * be used depends on \p transform parameter (positive/negative, respectively). - * - * \param[in,out] xml_blob XML tree representing CIB, may be swapped with - * an "updated" one - * \param[out] best The highest configuration version (per its index - * in the global schemas table) it was possible to - * reach during the update steps while ensuring - * the validity of the result; if no validation - * success was observed against possibly multiple - * schemas, the value is less or equal the result - * of \c get_schema_version applied on the input - * \p xml_blob value (unless that function maps it - * to -1, then 0 would be used instead) - * \param[in] max When \p transform is positive, this allows to - * set upper boundary schema (per its index in the - * global schemas table) beyond which it's forbidden - * to update by the means of XSLT transformation - * \param[in] transform Whether to employ XSLT-based transformation so - * as to allow overcoming possible incompatibilities - * between major schema versions (see above) - * \param[in] to_logs If true, output notable progress info to - * internal log streams; if false, to stderr - * - * \return \c pcmk_ok if no non-recoverable error encountered (up to - * caller to evaluate if the update satisfies the requirements - * per returned \p best value), negative value carrying the reason - * otherwise - */ -int update_validation(xmlNode **xml_blob, int *best, int max, - gboolean transform, gboolean to_logs); - -int get_schema_version(const char *name); -const char *get_schema_name(int version); -const char *xml_latest_schema(void); -gboolean cli_config_update(xmlNode ** xml, int *best_version, gboolean to_logs); - +// NOTE: sbd (as of at least 1.5.2) uses this /*! * \brief Initialize the CRM XML subsystem * * This method sets global XML settings and loads pacemaker schemas into the cache. */ void crm_xml_init(void); + void crm_xml_cleanup(void); void pcmk_free_xml_subtree(xmlNode *xml); -void free_xml(xmlNode * child); -xmlNode *first_named_child(const xmlNode *parent, const char *name); -xmlNode *crm_next_same_xml(const xmlNode *sibling); +// NOTE: sbd (as of at least 1.5.2) uses this +void free_xml(xmlNode * child); xmlNode *sorted_xml(xmlNode * input, xmlNode * parent, gboolean recursive); xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path); @@ -280,10 +100,6 @@ 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(const xmlNode *xml, const char *desc, - const char *filename); - -char * crm_xml_escape(const char *text); void crm_xml_sanitize_id(char *id); void crm_xml_set_id(xmlNode *xml, const char *format, ...) G_GNUC_PRINTF(2, 3); diff --git a/include/crm/common/xml_compat.h b/include/crm/common/xml_compat.h index 85e39ff..3582838 100644 --- a/include/crm/common/xml_compat.h +++ b/include/crm/common/xml_compat.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 the Pacemaker project contributors + * Copyright 2004-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,11 +8,13 @@ */ #ifndef PCMK__CRM_COMMON_XML_COMPAT__H -# define PCMK__CRM_COMMON_XML_COMPAT__H +#define PCMK__CRM_COMMON_XML_COMPAT__H #include <glib.h> // gboolean #include <libxml/tree.h> // xmlNode -#include <crm/common/xml.h> // crm_xml_add() + +#include <crm/common/nvpair.h> // crm_xml_add() +#include <crm/common/xml_names.h> // PCMK_XE_CLONE #ifdef __cplusplus extern "C" { @@ -64,6 +66,7 @@ crm_xml_add_boolean(xmlNode *node, const char *name, gboolean value) return crm_xml_add(node, name, (value? "true" : "false")); } +// NOTE: sbd (as of at least 1.5.2) uses this //! \deprecated Use name member directly static inline const char * crm_element_name(const xmlNode *xml) @@ -71,6 +74,124 @@ crm_element_name(const xmlNode *xml) return (xml == NULL)? NULL : (const char *) xml->name; } +//! \deprecated Do not use +char *crm_xml_escape(const char *text); + +// NOTE: sbd (as of at least 1.5.2) uses this +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *copy_xml(xmlNode *src_node); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *add_node_copy(xmlNode *new_parent, xmlNode *xml_node); + +//! \deprecated Do not use +void purge_diff_markers(xmlNode *a_node); + +//! \deprecated Do not use +xmlNode *diff_xml_object(xmlNode *left, xmlNode *right, gboolean suppress); + +//! \deprecated Do not use +xmlNode *subtract_xml_object(xmlNode *parent, xmlNode *left, xmlNode *right, + gboolean full, gboolean *changed, + const char *marker); + +//! \deprecated Do not use +gboolean can_prune_leaf(xmlNode *xml_node); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *create_xml_node(xmlNode *parent, const char *name); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *pcmk_create_xml_text_node(xmlNode *parent, const char *name, + const char *content); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *pcmk_create_html_node(xmlNode *parent, const char *element_name, + const char *id, const char *class_name, + const char *text); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *first_named_child(const xmlNode *parent, const char *name); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *find_xml_node(const xmlNode *root, const char *search_path, + gboolean must_find); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *crm_next_same_xml(const xmlNode *sibling); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +void xml_remove_prop(xmlNode *obj, const char *name); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +gboolean replace_xml_child(xmlNode *parent, xmlNode *child, xmlNode *update, + gboolean delete_only); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +gboolean update_xml_child(xmlNode *child, xmlNode *to_update); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +int find_xml_children(xmlNode **children, xmlNode *root, const char *tag, + const char *field, const char *value, + gboolean search_matches); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *get_xpath_object_relative(const char *xpath, xmlNode *xml_obj, + int error_level); + +//! \deprecated Do not use +void fix_plus_plus_recursive(xmlNode *target); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +gboolean add_message_xml(xmlNode *msg, const char *field, xmlNode *xml); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *get_message_xml(const xmlNode *msg, const char *field); + +//! \deprecated Do not use +const char *xml_latest_schema(void); + +//! \deprecated Do not use +const char *get_schema_name(int version); + +//! \deprecated Do not use +int get_schema_version(const char *name); + +//! \deprecated Do not use +int update_validation(xmlNode **xml_blob, int *best, int max, + gboolean transform, gboolean to_logs); + +//! \deprecated Do not use +gboolean validate_xml(xmlNode *xml_blob, const char *validation, + gboolean to_logs); + +//! \deprecated Do not use +gboolean validate_xml_verbose(const xmlNode *xml_blob); + +// NOTE: sbd (as of at least 1.5.2) uses this +//! \deprecated Do not use +gboolean cli_config_update(xmlNode **xml, int *best_version, gboolean to_logs); + +//! \deprecated Do not use +static inline const char * +crm_map_element_name(const xmlNode *xml) +{ + if (xml == NULL) { + return NULL; + } else if (strcmp((const char *) xml->name, "master") == 0) { + // Can't use PCMK__XE_PROMOTABLE_LEGACY because it's internal + return PCMK_XE_CLONE; + } else { + return (const char *) xml->name; + } +} + +//! \deprecated Do not use +void copy_in_properties(xmlNode *target, const xmlNode *src); + +//! \deprecated Do not use +void expand_plus_plus(xmlNode * target, const char *name, const char *value); + #ifdef __cplusplus } #endif diff --git a/include/crm/common/xml_internal.h b/include/crm/common/xml_internal.h index ddb4384..6d4490f 100644 --- a/include/crm/common/xml_internal.h +++ b/include/crm/common/xml_internal.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 the Pacemaker project contributors + * Copyright 2017-2024 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -8,20 +8,23 @@ */ #ifndef PCMK__XML_INTERNAL__H -# define PCMK__XML_INTERNAL__H +#define PCMK__XML_INTERNAL__H /* * Internal-only wrappers for and extensions to libxml2 (libxslt) */ -# include <stdlib.h> -# include <stdio.h> -# include <string.h> +#include <stdlib.h> +#include <stdint.h> // uint32_t +#include <stdio.h> +#include <string.h> -# include <crm/crm.h> /* transitively imports qblog.h */ -# include <crm/common/output_internal.h> +#include <crm/crm.h> /* transitively imports qblog.h */ +#include <crm/common/output_internal.h> +#include <crm/common/xml_io_internal.h> +#include <crm/common/xml_names_internal.h> // PCMK__XE_PROMOTABLE_LEGACY -# include <libxml/relaxng.h> +#include <libxml/relaxng.h> /*! * \brief Base for directing lib{xml2,xslt} log into standard libqb backend @@ -145,6 +148,7 @@ enum pcmk__xml_fmt_options { //! Include the closing tag of an XML element pcmk__xml_fmt_close = (1 << 5), + // @COMPAT Can we start including text nodes unconditionally? //! Include XML text nodes pcmk__xml_fmt_text = (1 << 6), @@ -168,25 +172,27 @@ int pcmk__xml_show_changes(pcmk__output_t *out, const xmlNode *xml); /* XML search strings for guest, remote and pacemaker_remote nodes */ /* search string to find CIB resources entries for cluster nodes */ -#define PCMK__XP_MEMBER_NODE_CONFIG \ - "//" XML_TAG_CIB "/" XML_CIB_TAG_CONFIGURATION "/" XML_CIB_TAG_NODES \ - "/" XML_CIB_TAG_NODE "[not(@type) or @type='member']" +#define PCMK__XP_MEMBER_NODE_CONFIG \ + "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_NODES \ + "/" PCMK_XE_NODE \ + "[not(@" PCMK_XA_TYPE ") or @" PCMK_XA_TYPE "='" PCMK_VALUE_MEMBER "']" /* search string to find CIB resources entries for guest nodes */ #define PCMK__XP_GUEST_NODE_CONFIG \ - "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \ - "//" XML_TAG_META_SETS "//" XML_CIB_TAG_NVPAIR \ - "[@name='" XML_RSC_ATTR_REMOTE_NODE "']" + "//" PCMK_XE_CIB "//" PCMK_XE_CONFIGURATION "//" PCMK_XE_PRIMITIVE \ + "//" PCMK_XE_META_ATTRIBUTES "//" PCMK_XE_NVPAIR \ + "[@" PCMK_XA_NAME "='" PCMK_META_REMOTE_NODE "']" /* search string to find CIB resources entries for remote nodes */ -#define PCMK__XP_REMOTE_NODE_CONFIG \ - "//" XML_TAG_CIB "//" XML_CIB_TAG_CONFIGURATION "//" XML_CIB_TAG_RESOURCE \ - "[@type='remote'][@provider='pacemaker']" +#define PCMK__XP_REMOTE_NODE_CONFIG \ + "//" PCMK_XE_CIB "//" PCMK_XE_CONFIGURATION "//" PCMK_XE_PRIMITIVE \ + "[@" PCMK_XA_TYPE "='" PCMK_VALUE_REMOTE "']" \ + "[@" PCMK_XA_PROVIDER "='pacemaker']" /* search string to find CIB node status entries for pacemaker_remote nodes */ -#define PCMK__XP_REMOTE_NODE_STATUS \ - "//" XML_TAG_CIB "//" XML_CIB_TAG_STATUS "//" XML_CIB_TAG_STATE \ - "[@" XML_NODE_IS_REMOTE "='true']" +#define PCMK__XP_REMOTE_NODE_STATUS \ + "//" PCMK_XE_CIB "//" PCMK_XE_STATUS "//" PCMK__XE_NODE_STATE \ + "[@" PCMK_XA_REMOTE_NODE "='" PCMK_VALUE_TRUE "']" /*! * \internal * \brief Serialize XML (using libxml) into provided descriptor @@ -208,17 +214,105 @@ enum pcmk__xml_artefact_ns { void pcmk__strip_xml_text(xmlNode *xml); const char *pcmk__xe_add_last_written(xmlNode *xe); -xmlNode *pcmk__xe_match(const xmlNode *parent, const char *node_name, - const char *attr_n, const char *attr_v); +xmlNode *pcmk__xe_first_child(const xmlNode *parent, const char *node_name, + const char *attr_n, const char *attr_v); + +void pcmk__xe_remove_attr(xmlNode *element, const char *name); +bool pcmk__xe_remove_attr_cb(xmlNode *xml, void *user_data); void pcmk__xe_remove_matching_attrs(xmlNode *element, bool (*match)(xmlAttrPtr, void *), void *user_data); +int pcmk__xe_delete_match(xmlNode *xml, xmlNode *search); +int pcmk__xe_replace_match(xmlNode *xml, xmlNode *replace); +int pcmk__xe_update_match(xmlNode *xml, xmlNode *update, uint32_t flags); GString *pcmk__element_xpath(const xmlNode *xml); /*! * \internal + * \enum pcmk__xml_escape_type + * \brief Indicators of which XML characters to escape + * + * XML allows the escaping of special characters by replacing them with entity + * references (for example, <tt>"""</tt>) or character references (for + * example, <tt>" "</tt>). + * + * The special characters <tt>'&'</tt> (except as the beginning of an entity + * reference) and <tt>'<'</tt> are not allowed in their literal forms in XML + * character data. Character data is non-markup text (for example, the content + * of a text node). <tt>'>'</tt> is allowed under most circumstances; we escape + * it for safety and symmetry. + * + * For more details, see the "Character Data and Markup" section of the XML + * spec, currently section 2.4: + * https://www.w3.org/TR/xml/#dt-markup + * + * Attribute values are handled specially. + * * If an attribute value is delimited by single quotes, then single quotes + * must be escaped within the value. + * * Similarly, if an attribute value is delimited by double quotes, then double + * quotes must be escaped within the value. + * * A conformant XML processor replaces a literal whitespace character (tab, + * newline, carriage return, space) in an attribute value with a space + * (\c '#x20') character. However, a reference to a whitespace character (for + * example, \c "
" for \c '\n') does not get replaced. + * * For more details, see the "Attribute-Value Normalization" section of the + * XML spec, currently section 3.3.3. Note that the default attribute type + * is CDATA; we don't deal with NMTOKENS, etc.: + * https://www.w3.org/TR/xml/#AVNormalize + * + * Pacemaker always delimits attribute values with double quotes, so there's no + * need to escape single quotes. + * + * Newlines and tabs should be escaped in attribute values when XML is + * serialized to text, so that future parsing preserves them rather than + * normalizing them to spaces. + * + * We always escape carriage returns, so that they're not converted to spaces + * during attribute-value normalization and because displaying them as literals + * is messy. + */ +enum pcmk__xml_escape_type { + /*! + * For text nodes. + * * Escape \c '<', \c '>', and \c '&' using entity references. + * * Do not escape \c '\n' and \c '\t'. + * * Escape other non-printing characters using character references. + */ + pcmk__xml_escape_text, + + /*! + * For attribute values. + * * Escape \c '<', \c '>', \c '&', and \c '"' using entity references. + * * Escape \c '\n', \c '\t', and other non-printing characters using + * character references. + */ + pcmk__xml_escape_attr, + + /* @COMPAT Drop escaping of at least '\n' and '\t' for + * pcmk__xml_escape_attr_pretty when openstack-info, openstack-floating-ip, + * and openstack-virtual-ip resource agents no longer depend on it. + * + * At time of writing, openstack-info may set a multiline value for the + * openstack_ports node attribute. The other two agents query the value and + * require it to be on one line with no spaces. + */ + /*! + * For attribute values displayed in text output delimited by double quotes. + * * Escape \c '\n' as \c "\\n" + * * Escape \c '\r' as \c "\\r" + * * Escape \c '\t' as \c "\\t" + * * Escape \c '"' as \c "\\"" + */ + pcmk__xml_escape_attr_pretty, +}; + +bool pcmk__xml_needs_escape(const char *text, enum pcmk__xml_escape_type type); +char *pcmk__xml_escape(const char *text, enum pcmk__xml_escape_type type); + +/*! + * \internal * \brief Get the root directory to scan XML artefacts of given kind for * * \param[in] ns governs the hierarchy nesting against the inherent root dir @@ -242,6 +336,20 @@ char *pcmk__xml_artefact_path(enum pcmk__xml_artefact_ns ns, /*! * \internal + * \brief Retrieve the value of the \c PCMK_XA_ID XML attribute + * + * \param[in] xml XML element to check + * + * \return Value of the \c PCMK_XA_ID attribute (may be \c NULL) + */ +static inline const char * +pcmk__xe_id(const xmlNode *xml) +{ + return crm_element_value(xml, PCMK_XA_ID); +} + +/*! + * \internal * \brief Check whether an XML element is of a particular type * * \param[in] xml XML element to compare @@ -296,25 +404,6 @@ pcmk__xml_next(const xmlNode *child) /*! * \internal - * \brief Return first non-text child element of an XML node - * - * \param[in] parent XML node to check - * - * \return First child element of \p parent (or NULL if none) - */ -static inline xmlNode * -pcmk__xe_first_child(const xmlNode *parent) -{ - xmlNode *child = (parent? parent->children : NULL); - - while (child && (child->type != XML_ELEMENT_NODE)) { - child = child->next; - } - return child; -} - -/*! - * \internal * \brief Return next non-text sibling element of an XML element * * \param[in] child XML element to check @@ -332,6 +421,34 @@ pcmk__xe_next(const xmlNode *child) return next; } +xmlNode *pcmk__xe_create(xmlNode *parent, const char *name); +xmlNode *pcmk__xml_copy(xmlNode *parent, xmlNode *src); +xmlNode *pcmk__xe_next_same(const xmlNode *node); + +void pcmk__xe_set_content(xmlNode *node, const char *format, ...) + G_GNUC_PRINTF(2, 3); + +/*! + * \internal + * \enum pcmk__xa_flags + * \brief Flags for operations affecting XML attributes + */ +enum pcmk__xa_flags { + //! Flag has no effect + pcmk__xaf_none = 0U, + + //! Don't overwrite existing values + pcmk__xaf_no_overwrite = (1U << 0), + + /*! + * Treat values as score updates where possible (see + * \c pcmk__xe_set_score()) + */ + pcmk__xaf_score_update = (1U << 1), +}; + +int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags); + /*! * \internal * \brief Like pcmk__xe_set_props, but takes a va_list instead of @@ -383,6 +500,20 @@ pcmk__xe_first_attr(const xmlNode *xe) char * pcmk__xpath_node_id(const char *xpath, const char *node); +/*! + * \internal + * \brief Print an informational message if an xpath query returned multiple + * items with the same ID. + * + * \param[in,out] out The output object + * \param[in] search The xpath search result, most typically the result of + * calling cib->cmds->query(). + * \param[in] name The name searched for + */ +void +pcmk__warn_multiple_name_matches(pcmk__output_t *out, xmlNode *search, + const char *name); + /* internal XML-related utilities */ enum xml_private_flags { @@ -434,6 +565,9 @@ pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int (*handler)(xmlNode *xml, void *userdata), void *userdata); +bool pcmk__xml_tree_foreach(xmlNode *xml, bool (*fn)(xmlNode *, void *), + void *user_data); + static inline const char * pcmk__xml_attr_value(const xmlAttr *attr) { @@ -441,8 +575,20 @@ pcmk__xml_attr_value(const xmlAttr *attr) : (const char *) attr->children->content; } -gboolean pcmk__validate_xml(xmlNode *xml_blob, const char *validation, - xmlRelaxNGValidityErrorFunc error_handler, - void *error_handler_context); +// @COMPAT Remove when v1 patchsets are removed +xmlNode *pcmk__diff_v1_xml_object(xmlNode *left, xmlNode *right, bool suppress); + +// @COMPAT Drop when PCMK__XE_PROMOTABLE_LEGACY is removed +static inline const char * +pcmk__map_element_name(const xmlNode *xml) +{ + if (xml == NULL) { + return NULL; + } else if (pcmk__xe_is(xml, PCMK__XE_PROMOTABLE_LEGACY)) { + return PCMK_XE_CLONE; + } else { + return (const char *) xml->name; + } +} #endif // PCMK__XML_INTERNAL__H diff --git a/include/crm/common/xml_io.h b/include/crm/common/xml_io.h new file mode 100644 index 0000000..a5e454c --- /dev/null +++ b/include/crm/common/xml_io.h @@ -0,0 +1,48 @@ +/* + * Copyright 2004-2024 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_XML_IO__H +#define PCMK__CRM_COMMON_XML_IO__H + +#include <libxml/tree.h> // xmlNode + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file + * \brief Wrappers for and extensions to XML input/output functions + * \ingroup core + */ + +/* Define compression parameters for IPC messages + * + * Compression costs a LOT, so we don't want to do it unless we're hitting + * message limits. Currently, we use 128KB as the threshold, because higher + * values don't play well with the heartbeat stack. With an earlier limit of + * 10KB, compressing 184 of 1071 messages accounted for 23% of the total CPU + * used by the cib. + */ +#define CRM_BZ2_BLOCKS 4 +#define CRM_BZ2_WORK 20 +#define CRM_BZ2_THRESHOLD (128 * 1024) + +void save_xml_to_file(const xmlNode *xml, const char *desc, + const char *filename); + +#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1) +#include <crm/common/xml_io_compat.h> +#endif + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_XML_IO__H diff --git a/include/crm/common/xml_io_compat.h b/include/crm/common/xml_io_compat.h new file mode 100644 index 0000000..74e5f1d --- /dev/null +++ b/include/crm/common/xml_io_compat.h @@ -0,0 +1,58 @@ +/* + * Copyright 2004-2024 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_XML_IO_COMPAT__H +#define PCMK__CRM_COMMON_XML_IO_COMPAT__H + +#include <glib.h> // gboolean +#include <libxml/tree.h> // xmlNode + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file + * \brief Deprecated Pacemaker XML I/O API + * \ingroup core + * \deprecated Do not include this header directly. The XML APIs in this + * header, and the header itself, will be removed in a future + * release. + */ + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *filename2xml(const char *filename); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *stdin2xml(void); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +xmlNode *string2xml(const char *input); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +int write_xml_fd(const xmlNode *xml, const char *filename, int fd, + gboolean compress); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +int write_xml_file(const xmlNode *xml, const char *filename, gboolean compress); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +char *dump_xml_formatted(const xmlNode *xml); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +char *dump_xml_formatted_with_text(const xmlNode *xml); + +//! \deprecated Do not use Pacemaker for general-purpose XML manipulation +char *dump_xml_unformatted(const xmlNode *xml); + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_XML_IO_COMPAT__H diff --git a/include/crm/common/xml_io_internal.h b/include/crm/common/xml_io_internal.h new file mode 100644 index 0000000..6c2b625 --- /dev/null +++ b/include/crm/common/xml_io_internal.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017-2024 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__XML_IO_INTERNAL__H +#define PCMK__XML_IO_INTERNAL__H + +/* + * Internal-only wrappers for and extensions to libxml2 I/O + */ + +#include <stdbool.h> // bool + +#include <glib.h> // GString +#include <libxml/tree.h> // xmlNode + +xmlNode *pcmk__xml_read(const char *filename); +xmlNode *pcmk__xml_parse(const char *input); + +void pcmk__xml_string(const xmlNode *data, uint32_t options, GString *buffer, + int depth); + +int pcmk__xml2fd(int fd, xmlNode *cur); +int pcmk__xml_write_fd(const xmlNode *xml, const char *filename, int fd, + bool compress, unsigned int *nbytes); +int pcmk__xml_write_file(const xmlNode *xml, const char *filename, + bool compress, unsigned int *nbytes); + +#endif // PCMK__XML_IO_INTERNAL__H diff --git a/include/crm/common/xml_names.h b/include/crm/common/xml_names.h new file mode 100644 index 0000000..1de7fb9 --- /dev/null +++ b/include/crm/common/xml_names.h @@ -0,0 +1,458 @@ +/* + * Copyright 2004-2024 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_XML_NAMES__H +#define PCMK__CRM_COMMON_XML_NAMES__H + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \file + * \brief Defined string constants for XML element and attribute names + * \ingroup core + */ + +/* For consistency, new constants should start with "PCMK_", followed by: + * - "XE" for XML element names + * - "XA" for XML attribute names + * - "OPT" for cluster option (property) names + * - "META" for meta-attribute names + * - "VALUE" for enumerated values (such as for options or for XML attributes) + * - "NODE_ATTR" for node attribute names + * + * Old names that don't follow this policy should eventually be deprecated and + * replaced with names that do. + * + * Symbols should be public if the user may specify them somewhere (especially + * the CIB) or if they're part of a well-defined structure that a user may need + * to parse. They should be internal if they're used only internally to + * Pacemaker (such as daemon IPC/CPG message XML). + * + * Constants belong in the following locations: + * * "XE" and "XA": xml_names.h and xml_names_internal.h + * * "OPT", "META", and "VALUE": options.h and options_internal.h + * * "NODE_ATTR": nodes.h and nodes_internal.h + * + * For meta-attributes that can be specified as either XML attributes or nvpair + * names, use "META" unless using both "XA" and "META" constants adds clarity. + * An example is operation attributes, which can be specified either as + * attributes of the PCMK_XE_OP element or as nvpairs in a meta-attribute set + * beneath the PCMK_XE_OP element. + */ + +/* + * XML elements + */ + +#define PCMK_XE_ACL_GROUP "acl_group" +#define PCMK_XE_ACL_PERMISSION "acl_permission" +#define PCMK_XE_ACL_ROLE "acl_role" +#define PCMK_XE_ACL_TARGET "acl_target" +#define PCMK_XE_ACLS "acls" +#define PCMK_XE_ACTION "action" +#define PCMK_XE_ACTIONS "actions" +#define PCMK_XE_AGENT "agent" +#define PCMK_XE_AGENT_STATUS "agent-status" +#define PCMK_XE_AGENTS "agents" +#define PCMK_XE_ALERT "alert" +#define PCMK_XE_ALERTS "alerts" +#define PCMK_XE_ALLOCATIONS "allocations" +#define PCMK_XE_ALLOCATIONS_UTILIZATIONS "allocations_utilizations" +#define PCMK_XE_ATTRIBUTE "attribute" +#define PCMK_XE_BAN "ban" +#define PCMK_XE_BANS "bans" +#define PCMK_XE_BUNDLE "bundle" +#define PCMK_XE_CAPACITY "capacity" +#define PCMK_XE_CHANGE "change" +#define PCMK_XE_CHANGE_ATTR "change-attr" +#define PCMK_XE_CHANGE_LIST "change-list" +#define PCMK_XE_CHANGE_RESULT "change-result" +#define PCMK_XE_CHECK "check" +#define PCMK_XE_CIB "cib" +#define PCMK_XE_CLONE "clone" +#define PCMK_XE_CLUSTER_ACTION "cluster_action" +#define PCMK_XE_CLUSTER_INFO "cluster-info" +#define PCMK_XE_CLUSTER_OPTIONS "cluster_options" +#define PCMK_XE_CLUSTER_PROPERTY_SET "cluster_property_set" +#define PCMK_XE_CLUSTER_STATUS "cluster_status" +#define PCMK_XE_COMMAND "command" +#define PCMK_XE_CONFIGURATION "configuration" +#define PCMK_XE_CONSTRAINT "constraint" +#define PCMK_XE_CONSTRAINTS "constraints" +#define PCMK_XE_CONTENT "content" +#define PCMK_XE_CRM_CONFIG "crm_config" +#define PCMK_XE_CRM_MON "crm_mon" +#define PCMK_XE_CRM_MON_DISCONNECTED "crm-mon-disconnected" +#define PCMK_XE_CURRENT_DC "current_dc" +#define PCMK_XE_DATE_EXPRESSION "date_expression" +#define PCMK_XE_DATE_SPEC "date_spec" +#define PCMK_XE_DC "dc" +#define PCMK_XE_DEPRECATED "deprecated" +#define PCMK_XE_DIFF "diff" +#define PCMK_XE_DIGEST "digest" +#define PCMK_XE_DIGESTS "digests" +#define PCMK_XE_DOCKER "docker" +#define PCMK_XE_DURATION "duration" +#define PCMK_XE_ERROR "error" +#define PCMK_XE_ERRORS "errors" +#define PCMK_XE_EXPRESSION "expression" +#define PCMK_XE_FAILURE "failure" +#define PCMK_XE_FAILURES "failures" +#define PCMK_XE_FEATURE "feature" +#define PCMK_XE_FEATURES "features" +#define PCMK_XE_FENCE_EVENT "fence_event" +#define PCMK_XE_FENCE_HISTORY "fence_history" +#define PCMK_XE_FENCING_ACTION "fencing_action" +#define PCMK_XE_FENCING_LEVEL "fencing-level" +#define PCMK_XE_FENCING_TOPOLOGY "fencing-topology" +#define PCMK_XE_GROUP "group" +#define PCMK_XE_INJECT_ATTR "inject_attr" +#define PCMK_XE_INJECT_SPEC "inject_spec" +#define PCMK_XE_INSTANCE_ATTRIBUTES "instance_attributes" +#define PCMK_XE_INSTRUCTION "instruction" +#define PCMK_XE_ITEM "item" +#define PCMK_XE_LAST_CHANGE "last_change" +#define PCMK_XE_LAST_FENCED "last-fenced" +#define PCMK_XE_LAST_UPDATE "last_update" +#define PCMK_XE_LIST "list" +#define PCMK_XE_LONGDESC "longdesc" +#define PCMK_XE_META_ATTRIBUTES "meta_attributes" +#define PCMK_XE_METADATA "metadata" +#define PCMK_XE_MODIFICATIONS "modifications" +#define PCMK_XE_MODIFY_NODE "modify_node" +#define PCMK_XE_MODIFY_TICKET "modify_ticket" +#define PCMK_XE_NETWORK "network" +#define PCMK_XE_NODE "node" +#define PCMK_XE_NODE_ACTION "node_action" +#define PCMK_XE_NODE_ATTRIBUTES "node_attributes" +#define PCMK_XE_NODE_HISTORY "node_history" +#define PCMK_XE_NODE_INFO "node-info" +#define PCMK_XE_NODE_WEIGHT "node_weight" +#define PCMK_XE_NODES "nodes" +#define PCMK_XE_NODES_CONFIGURED "nodes_configured" +#define PCMK_XE_NVPAIR "nvpair" +#define PCMK_XE_OBJ_REF "obj_ref" +#define PCMK_XE_OP "op" +#define PCMK_XE_OP_DEFAULTS "op_defaults" +#define PCMK_XE_OP_EXPRESSION "op_expression" +#define PCMK_XE_OPERATION "operation" +#define PCMK_XE_OPERATION_HISTORY "operation_history" +#define PCMK_XE_OPERATIONS "operations" +#define PCMK_XE_OPTION "option" +#define PCMK_XE_OUTPUT "output" +#define PCMK_XE_OVERRIDE "override" +#define PCMK_XE_OVERRIDES "overrides" +#define PCMK_XE_PACEMAKER_RESULT "pacemaker-result" +#define PCMK_XE_PACEMAKERD "pacemakerd" +#define PCMK_XE_PARAMETER "parameter" +#define PCMK_XE_PARAMETERS "parameters" +#define PCMK_XE_PODMAN "podman" +#define PCMK_XE_PORT_MAPPING "port-mapping" +#define PCMK_XE_POSITION "position" +#define PCMK_XE_PRIMITIVE "primitive" +#define PCMK_XE_PROMOTION_SCORE "promotion_score" +#define PCMK_XE_PROVIDER "provider" +#define PCMK_XE_PROVIDERS "providers" +#define PCMK_XE_PSEUDO_ACTION "pseudo_action" +#define PCMK_XE_REASON "reason" +#define PCMK_XE_RECIPIENT "recipient" +#define PCMK_XE_REPLICA "replica" +#define PCMK_XE_RESOURCE "resource" +#define PCMK_XE_RESOURCE_AGENT "resource-agent" +#define PCMK_XE_RESOURCE_AGENT_ACTION "resource-agent-action" +#define PCMK_XE_RESOURCE_CONFIG "resource_config" +#define PCMK_XE_RESOURCE_HISTORY "resource_history" +#define PCMK_XE_RESOURCE_REF "resource_ref" +#define PCMK_XE_RESOURCE_SET "resource_set" +#define PCMK_XE_RESOURCES "resources" +#define PCMK_XE_RESOURCES_CONFIGURED "resources_configured" +#define PCMK_XE_RESULT_CODE "result-code" +#define PCMK_XE_REVISED_CLUSTER_STATUS "revised_cluster_status" +#define PCMK_XE_ROLE "role" +#define PCMK_XE_RSC_ACTION "rsc_action" +#define PCMK_XE_RSC_COLOCATION "rsc_colocation" +#define PCMK_XE_RSC_DEFAULTS "rsc_defaults" +#define PCMK_XE_RSC_EXPRESSION "rsc_expression" +#define PCMK_XE_RSC_LOCATION "rsc_location" +#define PCMK_XE_RSC_ORDER "rsc_order" +#define PCMK_XE_RSC_TICKET "rsc_ticket" +#define PCMK_XE_RULE "rule" +#define PCMK_XE_RULE_CHECK "rule-check" +#define PCMK_XE_SELECT "select" +#define PCMK_XE_SELECT_ATTRIBUTES "select_attributes" +#define PCMK_XE_SELECT_FENCING "select_fencing" +#define PCMK_XE_SELECT_NODES "select_nodes" +#define PCMK_XE_SELECT_RESOURCES "select_resources" +#define PCMK_XE_SHADOW "shadow" +#define PCMK_XE_SHORTDESC "shortdesc" +#define PCMK_XE_SOURCE "source" +#define PCMK_XE_SPECIAL "special" +#define PCMK_XE_STACK "stack" +#define PCMK_XE_STATUS "status" +#define PCMK_XE_STORAGE "storage" +#define PCMK_XE_STORAGE_MAPPING "storage-mapping" +#define PCMK_XE_SUMMARY "summary" +#define PCMK_XE_TAG "tag" +#define PCMK_XE_TAGS "tags" +#define PCMK_XE_TARGET "target" +#define PCMK_XE_TEMPLATE "template" +#define PCMK_XE_TICKET "ticket" +#define PCMK_XE_TICKETS "tickets" +#define PCMK_XE_TIMING "timing" +#define PCMK_XE_TIMINGS "timings" +#define PCMK_XE_TRANSITION "transition" +#define PCMK_XE_UTILIZATION "utilization" +#define PCMK_XE_UTILIZATIONS "utilizations" +#define PCMK_XE_VALIDATE "validate" +#define PCMK_XE_VERSION "version" +#define PCMK_XE_XML "xml" +#define PCMK_XE_XML_PATCHSET "xml-patchset" + + +/* + * XML attributes + */ + +#define PCMK_XA_ACTION "action" +#define PCMK_XA_ACTIVE "active" +#define PCMK_XA_ADD_HOST "add-host" +#define PCMK_XA_ADMIN_EPOCH "admin_epoch" +#define PCMK_XA_ADVANCED "advanced" +#define PCMK_XA_AGENT "agent" +#define PCMK_XA_API_VERSION "api-version" +#define PCMK_XA_ATTRIBUTE "attribute" +#define PCMK_XA_AUTHOR "author" +#define PCMK_XA_AUTOMATIC "automatic" +#define PCMK_XA_BLOCKED "blocked" +#define PCMK_XA_BOOLEAN_OP "boolean-op" +#define PCMK_XA_BUILD "build" +#define PCMK_XA_CACHED "cached" +#define PCMK_XA_CALL "call" +#define PCMK_XA_CIB_LAST_WRITTEN "cib-last-written" +#define PCMK_XA_CIB_NODE "cib_node" +#define PCMK_XA_CLASS "class" +#define PCMK_XA_CLIENT "client" +#define PCMK_XA_CODE "code" +#define PCMK_XA_COMMENT "comment" +#define PCMK_XA_COMPLETED "completed" +#define PCMK_XA_CONTROL_PORT "control-port" +#define PCMK_XA_COUNT "count" +#define PCMK_XA_CRM_DEBUG_ORIGIN "crm-debug-origin" +#define PCMK_XA_CRM_FEATURE_SET "crm_feature_set" +#define PCMK_XA_CRM_TIMESTAMP "crm-timestamp" +#define PCMK_XA_CRMD "crmd" +#define PCMK_XA_DAYS "days" +#define PCMK_XA_DC_UUID "dc-uuid" +#define PCMK_XA_DEFAULT "default" +#define PCMK_XA_DELEGATE "delegate" +#define PCMK_XA_DESCRIPTION "description" +#define PCMK_XA_DEST "dest" +#define PCMK_XA_DEVICE "device" +#define PCMK_XA_DEVICES "devices" +#define PCMK_XA_DISABLED "disabled" +#define PCMK_XA_DURATION "duration" +#define PCMK_XA_END "end" +#define PCMK_XA_EPOCH "epoch" +#define PCMK_XA_EXEC "exec" +#define PCMK_XA_EXEC_TIME "exec-time" +#define PCMK_XA_EXECUTION_CODE "execution_code" +#define PCMK_XA_EXECUTION_DATE "execution-date" +#define PCMK_XA_EXECUTION_MESSAGE "execution_message" +#define PCMK_XA_EXIT_REASON "exit-reason" +#define PCMK_XA_EXITCODE "exitcode" +#define PCMK_XA_EXITREASON "exitreason" +#define PCMK_XA_EXITSTATUS "exitstatus" +#define PCMK_XA_EXPECTED "expected" +#define PCMK_XA_EXPECTED_UP "expected_up" +#define PCMK_XA_EXPIRES "expires" +#define PCMK_XA_EXTENDED_STATUS "extended-status" +#define PCMK_XA_FAIL_COUNT "fail-count" +#define PCMK_XA_FAILED "failed" +#define PCMK_XA_FAILURE_IGNORED "failure_ignored" +#define PCMK_XA_FEATURE_SET "feature_set" +#define PCMK_XA_FEATURES "features" +#define PCMK_XA_FILE "file" +#define PCMK_XA_FIRST "first" +#define PCMK_XA_FIRST_ACTION "first-action" +#define PCMK_XA_FOR "for" +#define PCMK_XA_FORMAT "format" +#define PCMK_XA_FUNCTION "function" +#define PCMK_XA_GENERATED "generated" +#define PCMK_XA_HASH "hash" +#define PCMK_XA_HAVE_QUORUM "have-quorum" +#define PCMK_XA_HEALTH "health" +#define PCMK_XA_HOST "host" +#define PCMK_XA_HOST_INTERFACE "host-interface" +#define PCMK_XA_HOST_NETMASK "host-netmask" +#define PCMK_XA_HOURS "hours" +#define PCMK_XA_ID "id" +#define PCMK_XA_ID_AS_RESOURCE "id_as_resource" +#define PCMK_XA_ID_REF "id-ref" +#define PCMK_XA_IMAGE "image" +#define PCMK_XA_INDEX "index" +#define PCMK_XA_INFLUENCE "influence" +#define PCMK_XA_INSTANCE "instance" +#define PCMK_XA_INTERNAL_PORT "internal-port" +#define PCMK_XA_INTERVAL "interval" +#define PCMK_XA_IP_RANGE_START "ip-range-start" +#define PCMK_XA_IS_DC "is_dc" +#define PCMK_XA_KIND "kind" +#define PCMK_XA_LANG "lang" +#define PCMK_XA_LAST_FAILURE "last-failure" +#define PCMK_XA_LAST_GRANTED "last-granted" +#define PCMK_XA_LAST_RC_CHANGE "last-rc-change" +#define PCMK_XA_LAST_UPDATED "last_updated" +#define PCMK_XA_LOCKED_TO "locked_to" +#define PCMK_XA_LOCKED_TO_HYPHEN "locked-to" +#define PCMK_XA_LOSS_POLICY "loss-policy" +#define PCMK_XA_MAINTENANCE "maintenance" +#define PCMK_XA_MAINTENANCE_MODE "maintenance-mode" +#define PCMK_XA_MANAGED "managed" +#define PCMK_XA_MESSAGE "message" +#define PCMK_XA_MINUTES "minutes" +#define PCMK_XA_MIXED_VERSION "mixed_version" +#define PCMK_XA_MONTHDAYS "monthdays" +#define PCMK_XA_MONTHS "months" +#define PCMK_XA_MULTI_STATE "multi_state" +#define PCMK_XA_NAME "name" +#define PCMK_XA_NETWORK "network" +#define PCMK_XA_NEXT_ROLE "next-role" +#define PCMK_XA_NO_QUORUM_PANIC "no-quorum-panic" +#define PCMK_XA_NO_QUORUM_POLICY "no-quorum-policy" +#define PCMK_XA_NODE "node" +#define PCMK_XA_NODE_ATTRIBUTE "node-attribute" +#define PCMK_XA_NODE_NAME "node_name" +#define PCMK_XA_NODE_PATH "node_path" +#define PCMK_XA_NODEID "nodeid" +#define PCMK_XA_NODES_RUNNING_ON "nodes_running_on" +#define PCMK_XA_NUM_UPDATES "num_updates" +#define PCMK_XA_NUMBER "number" +#define PCMK_XA_NUMBER_RESOURCES "number_resources" +#define PCMK_XA_OBJECT_TYPE "object-type" +#define PCMK_XA_ON_TARGET "on_target" +#define PCMK_XA_ONLINE "online" +#define PCMK_XA_OP "op" +#define PCMK_XA_OP_KEY "op_key" +#define PCMK_XA_OPERATION "operation" +#define PCMK_XA_OPTIONS "options" +#define PCMK_XA_ORIGIN "origin" +#define PCMK_XA_ORPHAN "orphan" +#define PCMK_XA_ORPHANED "orphaned" +#define PCMK_XA_PACEMAKERD_STATE "pacemakerd-state" +#define PCMK_XA_PATH "path" +#define PCMK_XA_PENDING "pending" +#define PCMK_XA_PORT "port" +#define PCMK_XA_PRESENT "present" +#define PCMK_XA_PRIORITY_FENCING_DELAY_MS "priority-fencing-delay-ms" +#define PCMK_XA_PROGRAM "program" +#define PCMK_XA_PROMOTABLE "promotable" +#define PCMK_XA_PROMOTED_MAX "promoted-max" +#define PCMK_XA_PROMOTED_ONLY "promoted-only" +#define PCMK_XA_PROVIDER "provider" +#define PCMK_XA_QUEUE_TIME "queue-time" +#define PCMK_XA_QUEUED "queued" +#define PCMK_XA_QUORUM "quorum" +#define PCMK_XA_RANGE "range" +#define PCMK_XA_RC "rc" +#define PCMK_XA_RC_TEXT "rc_text" +#define PCMK_XA_REASON "reason" +#define PCMK_XA_REFERENCE "reference" +#define PCMK_XA_RELOADABLE "reloadable" +#define PCMK_XA_REMAIN_STOPPED "remain_stopped" +#define PCMK_XA_REMOTE_CLEAR_PORT "remote-clear-port" +#define PCMK_XA_REMOTE_NODE "remote_node" +#define PCMK_XA_REMOTE_TLS_PORT "remote-tls-port" +#define PCMK_XA_REPLICAS "replicas" +#define PCMK_XA_REPLICAS_PER_HOST "replicas-per-host" +#define PCMK_XA_REQUEST "request" +#define PCMK_XA_REQUIRE_ALL "require-all" +#define PCMK_XA_RESOURCE "resource" +#define PCMK_XA_RESOURCE_AGENT "resource_agent" +#define PCMK_XA_RESOURCE_DISCOVERY "resource-discovery" +#define PCMK_XA_RESOURCES_RUNNING "resources_running" +#define PCMK_XA_RESULT "result" +#define PCMK_XA_ROLE "role" +#define PCMK_XA_RSC "rsc" +#define PCMK_XA_RSC_PATTERN "rsc-pattern" +#define PCMK_XA_RSC_ROLE "rsc-role" +#define PCMK_XA_RULE_ID "rule-id" +#define PCMK_XA_RUN_COMMAND "run-command" +#define PCMK_XA_RUNNING "running" +#define PCMK_XA_RUNNING_ON "running_on" +#define PCMK_XA_SCOPE "scope" +#define PCMK_XA_SCORE "score" +#define PCMK_XA_SCORE_ATTRIBUTE "score-attribute" +#define PCMK_XA_SEQUENTIAL "sequential" +#define PCMK_XA_SECONDS "seconds" +#define PCMK_XA_SHUTDOWN "shutdown" +#define PCMK_XA_SOURCE "source" +#define PCMK_XA_SOURCE_DIR "source-dir" +#define PCMK_XA_SOURCE_DIR_ROOT "source-dir-root" +#define PCMK_XA_SPEC "spec" +#define PCMK_XA_STANDARD "standard" +#define PCMK_XA_STANDBY "standby" +#define PCMK_XA_STANDBY_ONFAIL "standby_onfail" +#define PCMK_XA_START "start" +#define PCMK_XA_STATE "state" +#define PCMK_XA_STATUS "status" +#define PCMK_XA_STONITH_ENABLED "stonith-enabled" +#define PCMK_XA_STONITH_TIMEOUT_MS "stonith-timeout-ms" +#define PCMK_XA_STOP_ALL_RESOURCES "stop-all-resources" +#define PCMK_XA_SYMMETRIC_CLUSTER "symmetric-cluster" +#define PCMK_XA_SYMMETRICAL "symmetrical" +#define PCMK_XA_SYS_FROM "sys_from" +#define PCMK_XA_TAG "tag" +#define PCMK_XA_TARGET "target" +#define PCMK_XA_TARGET_ATTRIBUTE "target-attribute" +#define PCMK_XA_TARGET_DIR "target-dir" +#define PCMK_XA_TARGET_PATTERN "target-pattern" +#define PCMK_XA_TARGET_ROLE "target_role" +#define PCMK_XA_TARGET_VALUE "target-value" +#define PCMK_XA_TASK "task" +#define PCMK_XA_TEMPLATE "template" +#define PCMK_XA_TICKET "ticket" +#define PCMK_XA_TIME "time" +#define PCMK_XA_THEN "then" +#define PCMK_XA_THEN_ACTION "then-action" +#define PCMK_XA_TYPE "type" +#define PCMK_XA_UNAME "uname" +#define PCMK_XA_UNCLEAN "unclean" +#define PCMK_XA_UNHEALTHY "unhealthy" +#define PCMK_XA_UNIQUE "unique" +#define PCMK_XA_UNMANAGED "unmanaged" +#define PCMK_XA_UPDATE_CLIENT "update-client" +#define PCMK_XA_UPDATE_ORIGIN "update-origin" +#define PCMK_XA_UPDATE_USER "update-user" +#define PCMK_XA_USER "user" +#define PCMK_XA_VALID "valid" +#define PCMK_XA_VALIDATE_WITH "validate-with" +#define PCMK_XA_VALUE "value" +#define PCMK_XA_VALUE_SOURCE "value-source" +#define PCMK_XA_VERSION "version" +#define PCMK_XA_WATCHDOG "watchdog" +#define PCMK_XA_WEEKDAYS "weekdays" +#define PCMK_XA_WEEKS "weeks" +#define PCMK_XA_WEEKYEARS "weekyears" +#define PCMK_XA_WEIGHT "weight" +#define PCMK_XA_WHEN "when" +#define PCMK_XA_WITH_QUORUM "with_quorum" +#define PCMK_XA_WITH_RSC "with-rsc" +#define PCMK_XA_WITH_RSC_ROLE "with-rsc-role" +#define PCMK_XA_XPATH "xpath" +#define PCMK_XA_YEARDAYS "yeardays" +#define PCMK_XA_YEARS "years" + + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_XML_NAMES__H diff --git a/include/crm/common/xml_names_internal.h b/include/crm/common/xml_names_internal.h new file mode 100644 index 0000000..a23f855 --- /dev/null +++ b/include/crm/common/xml_names_internal.h @@ -0,0 +1,353 @@ +/* + * Copyright 2004-2024 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_XML_NAMES_INTERNAL__H +#define PCMK__CRM_COMMON_XML_NAMES_INTERNAL__H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * XML element names used only by internal code + */ + +#define PCMK__XE_ACK "ack" +#define PCMK__XE_ATTRIBUTES "attributes" +#define PCMK__XE_CIB_CALLBACK "cib-callback" +#define PCMK__XE_CIB_CALLDATA "cib_calldata" +#define PCMK__XE_CIB_COMMAND "cib_command" +#define PCMK__XE_CIB_REPLY "cib-reply" +#define PCMK__XE_CIB_RESULT "cib_result" +#define PCMK__XE_CIB_TRANSACTION "cib_transaction" +#define PCMK__XE_CIB_UPDATE_RESULT "cib_update_result" +#define PCMK__XE_COPY "copy" +#define PCMK__XE_CRM_EVENT "crm_event" +#define PCMK__XE_CRM_XML "crm_xml" +#define PCMK__XE_DIV "div" +#define PCMK__XE_DOWNED "downed" +#define PCMK__XE_EXIT_NOTIFICATION "exit-notification" +#define PCMK__XE_FAILED_UPDATE "failed_update" +#define PCMK__XE_GENERATION_TUPLE "generation_tuple" +#define PCMK__XE_LRM "lrm" +#define PCMK__XE_LRM_RESOURCE "lrm_resource" +#define PCMK__XE_LRM_RESOURCES "lrm_resources" +#define PCMK__XE_LRM_RSC_OP "lrm_rsc_op" +#define PCMK__XE_LRMD_ALERT "lrmd_alert" +#define PCMK__XE_LRMD_CALLDATA "lrmd_calldata" +#define PCMK__XE_LRMD_COMMAND "lrmd_command" +#define PCMK__XE_LRMD_IPC_MSG "lrmd_ipc_msg" +#define PCMK__XE_LRMD_IPC_PROXY "lrmd_ipc_proxy" +#define PCMK__XE_LRMD_NOTIFY "lrmd_notify" +#define PCMK__XE_LRMD_REPLY "lrmd_reply" +#define PCMK__XE_LRMD_RSC "lrmd_rsc" +#define PCMK__XE_LRMD_RSC_OP "lrmd_rsc_op" +#define PCMK__XE_MAINTENANCE "maintenance" +#define PCMK__XE_META "meta" +#define PCMK__XE_NACK "nack" +#define PCMK__XE_NODE_STATE "node_state" +#define PCMK__XE_NOTIFY "notify" +#define PCMK__XE_OPTIONS "options" +#define PCMK__XE_PARAM "param" +#define PCMK__XE_PING "ping" +#define PCMK__XE_PING_RESPONSE "ping_response" +#define PCMK__XE_PSEUDO_EVENT "pseudo_event" +#define PCMK__XE_RESOURCE_SETTINGS "resource-settings" +#define PCMK__XE_RSC_OP "rsc_op" +#define PCMK__XE_SHUTDOWN "shutdown" +#define PCMK__XE_SPAN "span" +#define PCMK__XE_ST_ASYNC_TIMEOUT_VALUE "st-async-timeout-value" +#define PCMK__XE_ST_CALLDATA "st_calldata" +#define PCMK__XE_ST_DEVICE_ACTION "st_device_action" +#define PCMK__XE_ST_DEVICE_ID "st_device_id" +#define PCMK__XE_ST_HISTORY "st_history" +#define PCMK__XE_ST_NOTIFY_FENCE "st_notify_fence" +#define PCMK__XE_ST_REPLY "st-reply" +#define PCMK__XE_STONITH_COMMAND "stonith_command" +#define PCMK__XE_TICKET_STATE "ticket_state" +#define PCMK__XE_TRANSIENT_ATTRIBUTES "transient_attributes" +#define PCMK__XE_TRANSITION_GRAPH "transition_graph" +#define PCMK__XE_XPATH_QUERY "xpath-query" +#define PCMK__XE_XPATH_QUERY_PATH "xpath-query-path" + +// @COMPAT Deprecated since 1.1.12 +#define PCMK__XE_ACL_USER "acl_user" + +/* @COMPAT Deprecate somehow. It's undocumented and behaves the same as + * PCMK__XE_CIB in places where it's recognized. + */ +#define PCMK__XE_ALL "all" + +// @COMPAT Deprecated since 2.1.8 +#define PCMK__XE_CIB_GENERATION "cib_generation" + +// @COMPAT Deprecated since 2.1.8 +#define PCMK__XE_CIB_UPDATE "cib_update" + +// @COMPAT Deprecated since 1.1.12; used with legacy CIB updates +#define PCMK__XE_CIB_UPDATE_DIFF "cib_update_diff" + +// @COMPAT Deprecated since 2.1.7 +#define PCMK__XE_DIFF_ADDED "diff-added" + +// @COMPAT Deprecated since 2.1.7 +#define PCMK__XE_DIFF_REMOVED "diff-removed" + +// @COMPAT Deprecated since 2.1.8 +#define PCMK__XE_FAILED "failed" + +// @COMPAT Deprecated since 1.0.8 (commit 4cb100f) +#define PCMK__XE_LIFETIME "lifetime" + +/* @COMPAT Deprecated since 2.0.0; alias for <clone> with PCMK_META_PROMOTABLE + * set to "true" + */ +#define PCMK__XE_PROMOTABLE_LEGACY "master" + +// @COMPAT Support for rkt is deprecated since 2.1.8 +#define PCMK__XE_RKT "rkt" + +// @COMPAT Deprecated since 1.1.12 +#define PCMK__XE_ROLE_REF "role_ref" + + +/* + * XML attribute names used only by internal code + */ + +#define PCMK__XA_ATTR_CLEAR_INTERVAL "attr_clear_interval" +#define PCMK__XA_ATTR_CLEAR_OPERATION "attr_clear_operation" +#define PCMK__XA_ATTR_DAMPENING "attr_dampening" +#define PCMK__XA_ATTR_HOST "attr_host" +#define PCMK__XA_ATTR_HOST_ID "attr_host_id" +#define PCMK__XA_ATTR_IS_PRIVATE "attr_is_private" +#define PCMK__XA_ATTR_IS_REMOTE "attr_is_remote" +#define PCMK__XA_ATTR_NAME "attr_name" +#define PCMK__XA_ATTR_REGEX "attr_regex" +#define PCMK__XA_ATTR_RESOURCE "attr_resource" +#define PCMK__XA_ATTR_SECTION "attr_section" +#define PCMK__XA_ATTR_SET "attr_set" +#define PCMK__XA_ATTR_SET_TYPE "attr_set_type" +#define PCMK__XA_ATTR_SYNC_POINT "attr_sync_point" +#define PCMK__XA_ATTR_USER "attr_user" +#define PCMK__XA_ATTR_VALUE "attr_value" +#define PCMK__XA_ATTR_VERSION "attr_version" +#define PCMK__XA_ATTR_WRITER "attr_writer" +#define PCMK__XA_ATTRD_IS_FORCE_WRITE "attrd_is_force_write" +#define PCMK__XA_CALL_ID "call-id" +#define PCMK__XA_CIB_CALLID "cib_callid" +#define PCMK__XA_CIB_CALLOPT "cib_callopt" +#define PCMK__XA_CIB_CLIENTID "cib_clientid" +#define PCMK__XA_CIB_CLIENTNAME "cib_clientname" +#define PCMK__XA_CIB_DELEGATED_FROM "cib_delegated_from" +#define PCMK__XA_CIB_HOST "cib_host" +#define PCMK__XA_CIB_ISREPLYTO "cib_isreplyto" +#define PCMK__XA_CIB_NOTIFY_ACTIVATE "cib_notify_activate" +#define PCMK__XA_CIB_NOTIFY_TYPE "cib_notify_type" +#define PCMK__XA_CIB_OP "cib_op" +#define PCMK__XA_CIB_PING_ID "cib_ping_id" +#define PCMK__XA_CIB_RC "cib_rc" +#define PCMK__XA_CIB_SCHEMA_MAX "cib_schema_max" +#define PCMK__XA_CIB_SECTION "cib_section" +#define PCMK__XA_CIB_UPDATE "cib_update" +#define PCMK__XA_CIB_UPGRADE_RC "cib_upgrade_rc" +#define PCMK__XA_CIB_USER "cib_user" +#define PCMK__XA_CLIENT_NAME "client_name" +#define PCMK__XA_CLIENT_UUID "client_uuid" +#define PCMK__XA_CONFIG_ERRORS "config-errors" +#define PCMK__XA_CONFIG_WARNINGS "config-warnings" +#define PCMK__XA_CONFIRM "confirm" +#define PCMK__XA_CONNECTION_HOST "connection_host" +#define PCMK__XA_CONTENT "content" +#define PCMK__XA_CRMD_STATE "crmd_state" +#define PCMK__XA_CRM_HOST_TO "crm_host_to" +#define PCMK__XA_CRM_LIMIT_MAX "crm-limit-max" +#define PCMK__XA_CRM_LIMIT_MODE "crm-limit-mode" +#define PCMK__XA_CRM_SUBSYSTEM "crm_subsystem" +#define PCMK__XA_CRM_SYS_FROM "crm_sys_from" +#define PCMK__XA_CRM_SYS_TO "crm_sys_to" +#define PCMK__XA_CRM_TASK "crm_task" +#define PCMK__XA_CRM_TGRAPH_IN "crm-tgraph-in" +#define PCMK__XA_CRM_USER "crm_user" +#define PCMK__XA_DC_LEAVING "dc-leaving" +#define PCMK__XA_DIGEST "digest" +#define PCMK__XA_ELECTION_AGE_SEC "election-age-sec" +#define PCMK__XA_ELECTION_AGE_NANO_SEC "election-age-nano-sec" +#define PCMK__XA_ELECTION_ID "election-id" +#define PCMK__XA_ELECTION_OWNER "election-owner" +#define PCMK__XA_GRANTED "granted" +#define PCMK__XA_GRAPH_ERRORS "graph-errors" +#define PCMK__XA_GRAPH_WARNINGS "graph-warnings" +#define PCMK__XA_HIDDEN "hidden" +#define PCMK__XA_HTTP_EQUIV "http-equiv" +#define PCMK__XA_IN_CCM "in_ccm" +#define PCMK__XA_JOIN "join" +#define PCMK__XA_JOIN_ID "join_id" +#define PCMK__XA_LINE "line" +#define PCMK__XA_LONG_ID "long-id" +#define PCMK__XA_LRMD_ALERT_ID "lrmd_alert_id" +#define PCMK__XA_LRMD_ALERT_PATH "lrmd_alert_path" +#define PCMK__XA_LRMD_CALLID "lrmd_callid" +#define PCMK__XA_LRMD_CALLOPT "lrmd_callopt" +#define PCMK__XA_LRMD_CLASS "lrmd_class" +#define PCMK__XA_LRMD_CLIENTID "lrmd_clientid" +#define PCMK__XA_LRMD_CLIENTNAME "lrmd_clientname" +#define PCMK__XA_LRMD_EXEC_OP_STATUS "lrmd_exec_op_status" +#define PCMK__XA_LRMD_EXEC_RC "lrmd_exec_rc" +#define PCMK__XA_LRMD_EXEC_TIME "lrmd_exec_time" +#define PCMK__XA_LRMD_IPC_CLIENT "lrmd_ipc_client" +#define PCMK__XA_LRMD_IPC_MSG_FLAGS "lrmd_ipc_msg_flags" +#define PCMK__XA_LRMD_IPC_MSG_ID "lrmd_ipc_msg_id" +#define PCMK__XA_LRMD_IPC_OP "lrmd_ipc_op" +#define PCMK__XA_LRMD_IPC_SERVER "lrmd_ipc_server" +#define PCMK__XA_LRMD_IPC_SESSION "lrmd_ipc_session" +#define PCMK__XA_LRMD_IPC_USER "lrmd_ipc_user" +#define PCMK__XA_LRMD_IS_IPC_PROVIDER "lrmd_is_ipc_provider" +#define PCMK__XA_LRMD_OP "lrmd_op" +#define PCMK__XA_LRMD_ORIGIN "lrmd_origin" +#define PCMK__XA_LRMD_PROTOCOL_VERSION "lrmd_protocol_version" +#define PCMK__XA_LRMD_PROVIDER "lrmd_provider" +#define PCMK__XA_LRMD_QUEUE_TIME "lrmd_queue_time" +#define PCMK__XA_LRMD_RC "lrmd_rc" +#define PCMK__XA_LRMD_RCCHANGE_TIME "lrmd_rcchange_time" +#define PCMK__XA_LRMD_REMOTE_MSG_ID "lrmd_remote_msg_id" +#define PCMK__XA_LRMD_REMOTE_MSG_TYPE "lrmd_remote_msg_type" +#define PCMK__XA_LRMD_RSC_ACTION "lrmd_rsc_action" +#define PCMK__XA_LRMD_RSC_DELETED "lrmd_rsc_deleted" +#define PCMK__XA_LRMD_RSC_EXIT_REASON "lrmd_rsc_exit_reason" +#define PCMK__XA_LRMD_RSC_ID "lrmd_rsc_id" +#define PCMK__XA_LRMD_RSC_INTERVAL "lrmd_rsc_interval" +#define PCMK__XA_LRMD_RSC_OUTPUT "lrmd_rsc_output" +#define PCMK__XA_LRMD_RSC_START_DELAY "lrmd_rsc_start_delay" +#define PCMK__XA_LRMD_RSC_USERDATA_STR "lrmd_rsc_userdata_str" +#define PCMK__XA_LRMD_RUN_TIME "lrmd_run_time" +#define PCMK__XA_LRMD_TIMEOUT "lrmd_timeout" +#define PCMK__XA_LRMD_TYPE "lrmd_type" +#define PCMK__XA_LRMD_WATCHDOG "lrmd_watchdog" +#define PCMK__XA_MAJOR_VERSION "major_version" +#define PCMK__XA_MINOR_VERSION "minor_version" +#define PCMK__XA_MODE "mode" +#define PCMK__XA_MOON "moon" +#define PCMK__XA_NAMESPACE "namespace" +#define PCMK__XA_NODE_FENCED "node_fenced" +#define PCMK__XA_NODE_IN_MAINTENANCE "node_in_maintenance" +#define PCMK__XA_NODE_START_STATE "node_start_state" +#define PCMK__XA_NODE_STATE "node_state" +#define PCMK__XA_OP_DIGEST "op-digest" +#define PCMK__XA_OP_FORCE_RESTART "op-force-restart" +#define PCMK__XA_OP_RESTART_DIGEST "op-restart-digest" +#define PCMK__XA_OP_SECURE_DIGEST "op-secure-digest" +#define PCMK__XA_OP_SECURE_PARAMS "op-secure-params" +#define PCMK__XA_OP_STATUS "op-status" +#define PCMK__XA_OPERATION_KEY "operation_key" +#define PCMK__XA_ORIGINAL_CIB_OP "original_cib_op" +#define PCMK__XA_PACEMAKERD_STATE "pacemakerd_state" +#define PCMK__XA_PASSWORD "password" +#define PCMK__XA_PRIORITY "priority" +#define PCMK__XA_RC_CODE "rc-code" +#define PCMK__XA_REAP "reap" + +/* Actions to be executed on Pacemaker Remote nodes are routed through the + * controller on the cluster node hosting the remote connection. That cluster + * node is considered the router node for the action. + */ +#define PCMK__XA_ROUTER_NODE "router_node" + +#define PCMK__XA_RSC_ID "rsc-id" +#define PCMK__XA_RSC_PROVIDES "rsc_provides" +#define PCMK__XA_SCHEMA "schema" +#define PCMK__XA_SCHEMAS "schemas" +#define PCMK__XA_SET "set" +#define PCMK__XA_SRC "src" +#define PCMK__XA_ST_ACTION_DISALLOWED "st_action_disallowed" +#define PCMK__XA_ST_ACTION_TIMEOUT "st_action_timeout" +#define PCMK__XA_ST_AVAILABLE_DEVICES "st-available-devices" +#define PCMK__XA_ST_CALLID "st_callid" +#define PCMK__XA_ST_CALLOPT "st_callopt" +#define PCMK__XA_ST_CLIENTID "st_clientid" +#define PCMK__XA_ST_CLIENTNAME "st_clientname" +#define PCMK__XA_ST_CLIENTNODE "st_clientnode" +#define PCMK__XA_ST_DATE "st_date" +#define PCMK__XA_ST_DATE_NSEC "st_date_nsec" +#define PCMK__XA_ST_DELAY "st_delay" +#define PCMK__XA_ST_DELAY_BASE "st_delay_base" +#define PCMK__XA_ST_DELAY_MAX "st_delay_max" +#define PCMK__XA_ST_DELEGATE "st_delegate" +#define PCMK__XA_ST_DEVICE_ACTION "st_device_action" +#define PCMK__XA_ST_DEVICE_ID "st_device_id" +#define PCMK__XA_ST_DEVICE_SUPPORT_FLAGS "st_device_support_flags" +#define PCMK__XA_ST_DIFFERENTIAL "st_differential" +#define PCMK__XA_ST_MONITOR_VERIFIED "st_monitor_verified" +#define PCMK__XA_ST_NOTIFY_ACTIVATE "st_notify_activate" +#define PCMK__XA_ST_NOTIFY_DEACTIVATE "st_notify_deactivate" +#define PCMK__XA_ST_OP "st_op" +#define PCMK__XA_ST_OP_MERGED "st_op_merged" +#define PCMK__XA_ST_ORIGIN "st_origin" +#define PCMK__XA_ST_OUTPUT "st_output" +#define PCMK__XA_ST_RC "st_rc" +#define PCMK__XA_ST_REMOTE_OP "st_remote_op" +#define PCMK__XA_ST_REMOTE_OP_RELAY "st_remote_op_relay" +#define PCMK__XA_ST_REQUIRED "st_required" +#define PCMK__XA_ST_STATE "st_state" +#define PCMK__XA_ST_TARGET "st_target" +#define PCMK__XA_ST_TIMEOUT "st_timeout" +#define PCMK__XA_ST_TOLERANCE "st_tolerance" +#define PCMK__XA_SUBT "subt" // subtype +#define PCMK__XA_T "t" // type +#define PCMK__XA_TRANSITION_KEY "transition-key" +#define PCMK__XA_TRANSITION_MAGIC "transition-magic" +#define PCMK__XA_UPTIME "uptime" + +// @COMPAT Deprecated since 2.1.8 +#define PCMK__XA_CIB_OBJECT "cib_object" + +// @COMPAT Deprecated since 2.1.8 +#define PCMK__XA_CIB_OBJECT_TYPE "cib_object_type" + +// @COMPAT Deprecated since 1.1.12; used with legacy CIB updates +#define PCMK__XA_CIB_LOCAL_NOTIFY_ID "cib_local_notify_id" + +// @COMPAT Used only with v1 patchsets +#define PCMK__XA_CRM_DIFF_MARKER "__crm_diff_marker__" + +// @COMPAT Deprecated since 2.1.5 +#define PCMK__XA_FIRST_INSTANCE "first-instance" + +// @COMPAT Deprecated since 2.1.7 +#define PCMK__XA_ORDERING "ordering" + +// @COMPAT Deprecated alias for PCMK_XA_PROMOTED_MAX since 2.0.0 +#define PCMK__XA_PROMOTED_MAX_LEGACY "masters" + +// @COMPAT Deprecated alias for PCMK_XA_PROMOTED_ONLY since 2.0.0 +#define PCMK__XA_PROMOTED_ONLY_LEGACY "master_only" + +// @COMPAT Deprecated since 1.1.12 +#define PCMK__XA_REF "ref" + +// @COMPAT Deprecated since 2.1.6 +#define PCMK__XA_REPLACE "replace" + +// @COMPAT Deprecated alias for \c PCMK_XA_AUTOMATIC since 1.1.14 +#define PCMK__XA_REQUIRED "required" + +// @COMPAT Deprecated since 2.1.5 +#define PCMK__XA_RSC_INSTANCE "rsc-instance" + +// @COMPAT Deprecated since 2.1.5 +#define PCMK__XA_THEN_INSTANCE "then-instance" + +// @COMPAT Deprecated since 2.1.5 +#define PCMK__XA_WITH_RSC_INSTANCE "with-rsc-instance" + +#ifdef __cplusplus +} +#endif + +#endif // PCMK__CRM_COMMON_XML_NAMES_INTERNAL__H |