summaryrefslogtreecommitdiffstats
path: root/include/crm/common
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 13:39:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 13:39:29 +0000
commitb41961d74fe7ff2d4d4abaca92454e87c561e49f (patch)
treeb34e3826a7b649dafdbd05081140c990c96d736d /include/crm/common
parentReleasing progress-linux version 2.1.7-1~progress7.99u1. (diff)
downloadpacemaker-b41961d74fe7ff2d4d4abaca92454e87c561e49f.tar.xz
pacemaker-b41961d74fe7ff2d4d4abaca92454e87c561e49f.zip
Merging upstream version 2.1.8~rc1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--include/crm/common/Makefile.am12
-rw-r--r--include/crm/common/acl.h8
-rw-r--r--include/crm/common/acl_internal.h7
-rw-r--r--include/crm/common/action_relation_internal.h51
-rw-r--r--include/crm/common/actions.h237
-rw-r--r--include/crm/common/actions_internal.h71
-rw-r--r--include/crm/common/agents.h4
-rw-r--r--include/crm/common/agents_compat.h4
-rw-r--r--include/crm/common/alerts_internal.h6
-rw-r--r--include/crm/common/attrs_internal.h (renamed from include/crm/common/attrd_internal.h)15
-rw-r--r--include/crm/common/bundles_internal.h89
-rw-r--r--include/crm/common/cib.h4
-rw-r--r--include/crm/common/cib_internal.h4
-rw-r--r--include/crm/common/clone_internal.h52
-rw-r--r--include/crm/common/digests_internal.h15
-rw-r--r--include/crm/common/failcounts_internal.h4
-rw-r--r--include/crm/common/group_internal.h24
-rw-r--r--include/crm/common/history_internal.h52
-rw-r--r--include/crm/common/internal.h72
-rw-r--r--include/crm/common/io_internal.h4
-rw-r--r--include/crm/common/ipc.h28
-rw-r--r--include/crm/common/ipc_attrd_internal.h11
-rw-r--r--include/crm/common/ipc_controld.h4
-rw-r--r--include/crm/common/ipc_internal.h18
-rw-r--r--include/crm/common/ipc_pacemakerd.h18
-rw-r--r--include/crm/common/ipc_schedulerd.h4
-rw-r--r--include/crm/common/iso8601.h30
-rw-r--r--include/crm/common/iso8601_internal.h4
-rw-r--r--include/crm/common/location_internal.h36
-rw-r--r--include/crm/common/logging.h125
-rw-r--r--include/crm/common/logging_compat.h6
-rw-r--r--include/crm/common/logging_internal.h96
-rw-r--r--include/crm/common/mainloop.h30
-rw-r--r--include/crm/common/mainloop_compat.h8
-rw-r--r--include/crm/common/messages_internal.h3
-rw-r--r--include/crm/common/nodes.h198
-rw-r--r--include/crm/common/nodes_internal.h27
-rw-r--r--include/crm/common/nvpair.h23
-rw-r--r--include/crm/common/nvpair_internal.h63
-rw-r--r--include/crm/common/options.h231
-rw-r--r--include/crm/common/options_internal.h204
-rw-r--r--include/crm/common/output.h4
-rw-r--r--include/crm/common/output_internal.h107
-rw-r--r--include/crm/common/primitive_internal.h39
-rw-r--r--include/crm/common/remote_internal.h65
-rw-r--r--include/crm/common/resources.h268
-rw-r--r--include/crm/common/resources_internal.h25
-rw-r--r--include/crm/common/results.h76
-rw-r--r--include/crm/common/results_compat.h4
-rw-r--r--include/crm/common/results_internal.h23
-rw-r--r--include/crm/common/roles.h14
-rw-r--r--include/crm/common/roles_internal.h48
-rw-r--r--include/crm/common/rules.h112
-rw-r--r--include/crm/common/rules_internal.h38
-rw-r--r--include/crm/common/scheduler.h207
-rw-r--r--include/crm/common/scheduler_internal.h118
-rw-r--r--include/crm/common/scheduler_types.h4
-rw-r--r--include/crm/common/schemas.h32
-rw-r--r--include/crm/common/schemas_internal.h37
-rw-r--r--include/crm/common/scores.h33
-rw-r--r--include/crm/common/scores_compat.h37
-rw-r--r--include/crm/common/scores_internal.h15
-rw-r--r--include/crm/common/strings_internal.h22
-rw-r--r--include/crm/common/tags.h14
-rw-r--r--include/crm/common/tickets.h20
-rw-r--r--include/crm/common/unittest_internal.h85
-rw-r--r--include/crm/common/util.h56
-rw-r--r--include/crm/common/util_compat.h29
-rw-r--r--include/crm/common/xml.h224
-rw-r--r--include/crm/common/xml_compat.h127
-rw-r--r--include/crm/common/xml_internal.h234
-rw-r--r--include/crm/common/xml_io.h48
-rw-r--r--include/crm/common/xml_io_compat.h58
-rw-r--r--include/crm/common/xml_io_internal.h34
-rw-r--r--include/crm/common/xml_names.h458
-rw-r--r--include/crm/common/xml_names_internal.h353
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>"&quot;"</tt>) or character references (for
+ * example, <tt>"&#13;"</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 "&#x0A;" 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