1 /*
2 * Copyright 2004-2025 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10 #ifndef PCMK__CRM_COMMON_SCHEDULER_INTERNAL__H
11 #define PCMK__CRM_COMMON_SCHEDULER_INTERNAL__H
12
13 #include <crm/common/action_relation_internal.h>
14 #include <crm/common/actions_internal.h>
15 #include <crm/common/attrs_internal.h>
16 #include <crm/common/bundles_internal.h>
17 #include <crm/common/clone_internal.h>
18 #include <crm/common/digest_internal.h>
19 #include <crm/common/failcounts_internal.h>
20 #include <crm/common/group_internal.h>
21 #include <crm/common/history_internal.h>
22 #include <crm/common/location_internal.h>
23 #include <crm/common/nodes_internal.h>
24 #include <crm/common/primitive_internal.h>
25 #include <crm/common/remote_internal.h>
26 #include <crm/common/resources_internal.h>
27 #include <crm/common/roles_internal.h>
28 #include <crm/common/rules_internal.h>
29 #include <crm/common/tickets_internal.h>
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 enum pcmk__check_parameters {
36 /* Clear fail count if parameters changed for un-expired start or monitor
37 * last_failure.
38 */
39 pcmk__check_last_failure,
40
41 /* Clear fail count if parameters changed for start, monitor, promote, or
42 * migrate_from actions for active resources.
43 */
44 pcmk__check_active,
45 };
46
47 // Scheduling options and conditions
48 enum pcmk__scheduler_flags {
49 // No scheduler flags set (compare with equality rather than bit set)
50 pcmk__sched_none = 0ULL,
51
52 /* These flags are dynamically determined conditions */
53
54 // Whether partition has quorum (via \c PCMK_XA_HAVE_QUORUM attribute)
55 //! \deprecated Call pcmk_has_quorum() to check quorum instead
56 pcmk__sched_quorate = (1ULL << 0),
57
58 // Whether cluster is symmetric (via symmetric-cluster property)
59 pcmk__sched_symmetric_cluster = (1ULL << 1),
60
61 // Whether scheduling encountered a non-configuration error
62 pcmk__sched_processing_error = (1ULL << 2),
63
64 // Whether cluster is in maintenance mode (via maintenance-mode property)
65 pcmk__sched_in_maintenance = (1ULL << 3),
66
67 // Whether fencing is enabled (via stonith-enabled property)
68 pcmk__sched_fencing_enabled = (1ULL << 4),
69
70 // Whether cluster has a fencing resource (via CIB resources)
71 /*! \deprecated To indicate the cluster has a fencing resource, add either a
72 * fencing resource configuration or the have-watchdog cluster option to the
73 * input CIB
74 */
75 pcmk__sched_have_fencing = (1ULL << 5),
76
77 // Whether any resource provides or requires unfencing (via CIB resources)
78 pcmk__sched_enable_unfencing = (1ULL << 6),
79
80 // Whether concurrent fencing is allowed (via concurrent-fencing property)
81 pcmk__sched_concurrent_fencing = (1ULL << 7),
82
83 /*
84 * Whether resources removed from the configuration should be stopped (via
85 * stop-orphan-resources property)
86 */
87 pcmk__sched_stop_removed_resources = (1ULL << 8),
88
89 /*
90 * Whether recurring actions removed from the configuration should be
91 * cancelled (via stop-orphan-actions property)
92 */
93 pcmk__sched_cancel_removed_actions = (1ULL << 9),
94
95 // Whether to stop all resources (via stop-all-resources property)
96 pcmk__sched_stop_all = (1ULL << 10),
97
98 // Whether scheduler processing encountered a warning
99 pcmk__sched_processing_warning = (1ULL << 11),
100
101 /*
102 * Whether start failure should be treated as if
103 * \c PCMK_META_MIGRATION_THRESHOLD is 1 (via
104 * \c PCMK_OPT_START_FAILURE_IS_FATAL property)
105 */
106 pcmk__sched_start_failure_fatal = (1ULL << 12),
107
108 // Whether unseen nodes should be fenced (via startup-fencing property)
109 pcmk__sched_startup_fencing = (1ULL << 14),
110
111 /*
112 * Whether resources should be left stopped when their node shuts down
113 * cleanly (via shutdown-lock property)
114 */
115 pcmk__sched_shutdown_lock = (1ULL << 15),
116
117 /*
118 * Whether resources' current state should be probed (when unknown) before
119 * scheduling any other actions (via the enable-startup-probes property)
120 */
121 pcmk__sched_probe_resources = (1ULL << 16),
122
123 // Whether the CIB status section has been parsed yet
124 pcmk__sched_have_status = (1ULL << 17),
125
126 // Whether the cluster includes any Pacemaker Remote nodes (via CIB)
127 pcmk__sched_have_remote_nodes = (1ULL << 18),
128
129
130 /* The remaining flags are scheduling options that must be set explicitly */
131
132 /*
133 * Whether to skip unpacking the CIB status section and stop the scheduling
134 * sequence after applying node-specific location criteria (skipping
135 * assignment, ordering, actions, etc.).
136 */
137 pcmk__sched_location_only = (1ULL << 20),
138
139 // Whether sensitive resource attributes have been masked
140 pcmk__sched_sanitized = (1ULL << 21),
141
142 // Skip counting of total, disabled, and blocked resource instances
143 pcmk__sched_no_counts = (1ULL << 23),
144
145 // Whether node scores should be output instead of logged
146 pcmk__sched_output_scores = (1ULL << 25),
147
148 // Whether to show node and resource utilization (in log or output)
149 pcmk__sched_show_utilization = (1ULL << 26),
150
151 /*
152 * Whether to stop the scheduling sequence after unpacking the CIB,
153 * calculating cluster status, and applying node health (skipping
154 * applying node-specific location criteria, assignment, etc.)
155 */
156 pcmk__sched_validate_only = (1ULL << 27),
157
158 /* Can Pacemaker Remote nodes be fenced even from a node that doesn't
159 * have quorum?
160 */
161 pcmk__sched_fence_remote_no_quorum = (1ULL << 28),
162 };
163
164 // Implementation of pcmk__scheduler_private_t
165 struct pcmk__scheduler_private {
166 // Be careful about when each piece of information is available and final
167
168 char *local_node_name; // Name of node running scheduler (if known)
169 crm_time_t *now; // Time to use when evaluating rules
170 pcmk__output_t *out; // Output object for displaying messages
171 GHashTable *options; // Cluster options
172 const char *fence_action; // Default fencing action
173 guint fence_timeout_ms; // Default fencing action timeout (in ms)
174 guint priority_fencing_ms; // Priority-based fencing delay (in ms)
175 guint shutdown_lock_ms; // How long to lock resources (in ms)
176 guint node_pending_ms; // Pending join times out after this (in ms)
177
178 // @TODO convert to enum
179 const char *placement_strategy; // Value of placement-strategy property
180
181 xmlNode *rsc_defaults; // Configured resource defaults
182 xmlNode *op_defaults; // Configured operation defaults
183 GList *resources; // Resources in cluster
184 GHashTable *templates; // Key = template ID, value = resource list
185 GHashTable *tags; // Key = tag ID, value = element list
186 GList *actions; // All scheduled actions
187 GHashTable *singletons; // Scheduled non-resource actions
188 int next_action_id; // Counter used as ID for actions
189 xmlNode *failed; // History entries of failed actions
190 GList *param_check; // History entries that need to be checked
191 GList *stop_needed; // Containers that need stop actions
192 GList *location_constraints; // Location constraints
193 GList *colocation_constraints; // Colocation constraints
194 GList *ordering_constraints; // Ordering constraints
195 GHashTable *ticket_constraints; // Key = ticket ID, value = pcmk__ticket_t
196 int next_ordering_id; // Counter used as ID for orderings
197 int ninstances; // Total number of resource instances
198 int blocked_resources; // Number of blocked resources in cluster
199 int disabled_resources; // Number of disabled resources in cluster
200 time_t recheck_by; // Hint to controller when to reschedule
201 xmlNode *graph; // Transition graph
202 int synapse_count; // Number of transition graph synapses
203 };
204
205 // Group of enum pcmk__warnings flags for warnings we want to log once
206 extern uint32_t pcmk__warnings;
207
208 /*!
209 * \internal
210 * \brief Log a resource-tagged message at info severity
211 *
212 * \param[in] rsc Tag message with this resource's ID
213 * \param[in] fmt... printf(3)-style format and arguments
214 */
215 #define pcmk__rsc_info(rsc, fmt, args...) \
216 crm_log_tag(LOG_INFO, ((rsc) == NULL)? "<NULL>" : (rsc)->id, (fmt), ##args)
217
218 /*!
219 * \internal
220 * \brief Log a resource-tagged message at debug severity
221 *
222 * \param[in] rsc Tag message with this resource's ID
223 * \param[in] fmt... printf(3)-style format and arguments
224 */
225 #define pcmk__rsc_debug(rsc, fmt, args...) \
226 crm_log_tag(LOG_DEBUG, ((rsc) == NULL)? "<NULL>" : (rsc)->id, (fmt), ##args)
227
228 /*!
229 * \internal
230 * \brief Log a resource-tagged message at trace severity
231 *
232 * \param[in] rsc Tag message with this resource's ID
233 * \param[in] fmt... printf(3)-style format and arguments
234 */
235 #define pcmk__rsc_trace(rsc, fmt, args...) \
236 crm_log_tag(LOG_TRACE, ((rsc) == NULL)? "<NULL>" : (rsc)->id, (fmt), ##args)
237
238 /*!
239 * \internal
240 * \brief Log an error and remember that current scheduler input has errors
241 *
242 * \param[in,out] scheduler Scheduler data
243 * \param[in] fmt... printf(3)-style format and arguments
244 */
245 #define pcmk__sched_err(scheduler, fmt...) do { \
246 pcmk__set_scheduler_flags((scheduler), \
247 pcmk__sched_processing_error); \
248 crm_err(fmt); \
249 } while (0)
250
251 /*!
252 * \internal
253 * \brief Log a warning and remember that current scheduler input has warnings
254 *
255 * \param[in,out] scheduler Scheduler data
256 * \param[in] fmt... printf(3)-style format and arguments
257 */
258 #define pcmk__sched_warn(scheduler, fmt...) do { \
259 pcmk__set_scheduler_flags((scheduler), \
260 pcmk__sched_processing_warning); \
261 crm_warn(fmt); \
262 } while (0)
263
264 /*!
265 * \internal
266 * \brief Set scheduler flags
267 *
268 * \param[in,out] scheduler Scheduler data
269 * \param[in] flags_to_set Group of enum pcmk__scheduler_flags to set
270 */
271 #define pcmk__set_scheduler_flags(scheduler, flags_to_set) do { \
272 (scheduler)->flags = pcmk__set_flags_as(__func__, __LINE__, \
273 LOG_TRACE, "Scheduler", crm_system_name, \
274 (scheduler)->flags, (flags_to_set), #flags_to_set); \
275 } while (0)
276
277 /*!
278 * \internal
279 * \brief Clear scheduler flags
280 *
281 * \param[in,out] scheduler Scheduler data
282 * \param[in] flags_to_clear Group of enum pcmk__scheduler_flags to clear
283 */
284 #define pcmk__clear_scheduler_flags(scheduler, flags_to_clear) do { \
285 (scheduler)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
286 LOG_TRACE, "Scheduler", crm_system_name, \
287 (scheduler)->flags, (flags_to_clear), #flags_to_clear); \
288 } while (0)
289
290 void pcmk__set_scheduler_defaults(pcmk_scheduler_t *scheduler);
291 time_t pcmk__scheduler_epoch_time(pcmk_scheduler_t *scheduler);
292 void pcmk__update_recheck_time(time_t recheck, pcmk_scheduler_t *scheduler,
293 const char *reason);
294
295 void pcmk__add_param_check(const xmlNode *rsc_op, pcmk_resource_t *rsc,
296 pcmk_node_t *node, enum pcmk__check_parameters);
297 void pcmk__foreach_param_check(pcmk_scheduler_t *scheduler,
298 void (*cb)(pcmk_resource_t*, pcmk_node_t*,
299 const xmlNode*,
300 enum pcmk__check_parameters));
301 void pcmk__free_param_checks(pcmk_scheduler_t *scheduler);
302
303 #ifdef __cplusplus
304 }
305 #endif
306
307 #endif // PCMK__CRM_COMMON_SCHEDULER_INTERNAL__H