1 /*
2 * Copyright 2004-2024 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_ACTIONS_INTERNAL__H
11 #define PCMK__CRM_COMMON_ACTIONS_INTERNAL__H
12
13 #include <stdbool.h> // bool
14 #include <stdint.h> // uint32_t, UINT32_C()
15 #include <glib.h> // guint, GList, GHashTable
16 #include <libxml/tree.h> // xmlNode
17
18 #include <crm/common/actions.h> // PCMK_ACTION_MONITOR
19 #include <crm/common/roles.h> // enum rsc_role_e
20 #include <crm/common/scheduler_types.h> // pcmk_resource_t, pcmk_node_t
21 #include <crm/common/strings_internal.h> // pcmk__str_eq()
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 //! printf-style format to create operation key from resource, action, interval
28 #define PCMK__OP_FMT "%s_%s_%u"
29
30 /*!
31 * \internal
32 * \brief Set action flags for an action
33 *
34 * \param[in,out] action Action to set flags for
35 * \param[in] flags_to_set Group of enum pcmk__action_flags to set
36 */
37 #define pcmk__set_action_flags(action, flags_to_set) do { \
38 (action)->flags = pcmk__set_flags_as(__func__, __LINE__, \
39 LOG_TRACE, \
40 "Action", (action)->uuid, \
41 (action)->flags, \
42 (flags_to_set), \
43 #flags_to_set); \
44 } while (0)
45
46 /*!
47 * \internal
48 * \brief Clear action flags for an action
49 *
50 * \param[in,out] action Action to clear flags for
51 * \param[in] flags_to_clear Group of enum pcmk__action_flags to clear
52 */
53 #define pcmk__clear_action_flags(action, flags_to_clear) do { \
54 (action)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
55 LOG_TRACE, \
56 "Action", (action)->uuid, \
57 (action)->flags, \
58 (flags_to_clear), \
59 #flags_to_clear); \
60 } while (0)
61
62 /*!
63 * \internal
64 * \brief Set action flags for a flag group
65 *
66 * \param[in,out] action_flags Flag group to set flags for
67 * \param[in] action_name Name of action being modified (for logging)
68 * \param[in] to_set Group of enum pcmk__action_flags to set
69 */
70 #define pcmk__set_raw_action_flags(action_flags, action_name, to_set) do { \
71 action_flags = pcmk__set_flags_as(__func__, __LINE__, \
72 LOG_TRACE, "Action", action_name, \
73 (action_flags), \
74 (to_set), #to_set); \
75 } while (0)
76
77 /*!
78 * \internal
79 * \brief Clear action flags for a flag group
80 *
81 * \param[in,out] action_flags Flag group to clear flags for
82 * \param[in] action_name Name of action being modified (for logging)
83 * \param[in] to_clear Group of enum pcmk__action_flags to clear
84 */
85 #define pcmk__clear_raw_action_flags(action_flags, action_name, to_clear) \
86 do { \
87 action_flags = pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, \
88 "Action", action_name, \
89 (action_flags), \
90 (to_clear), #to_clear); \
91 } while (0)
92
93 // Possible actions (including some pseudo-actions)
94 enum pcmk__action_type {
95 pcmk__action_unspecified = 0, // Unspecified or unknown action
96 pcmk__action_monitor, // Monitor
97
98 // Each "completed" action must be the regular action plus 1
99
100 pcmk__action_stop, // Stop
101 pcmk__action_stopped, // Stop completed
102
103 pcmk__action_start, // Start
104 pcmk__action_started, // Start completed
105
106 pcmk__action_notify, // Notify
107 pcmk__action_notified, // Notify completed
108
109 pcmk__action_promote, // Promote
110 pcmk__action_promoted, // Promoted
111
112 pcmk__action_demote, // Demote
113 pcmk__action_demoted, // Demoted
114
115 pcmk__action_shutdown, // Shut down node
116 pcmk__action_fence, // Fence node
117 };
118
119 // Action scheduling flags
120 enum pcmk__action_flags {
121 // No action flags set (compare with equality rather than bit set)
122 pcmk__no_action_flags = 0,
123
124 // Whether action does not require invoking an agent
125 pcmk__action_pseudo = (UINT32_C(1) << 0),
126
127 // Whether action is runnable
128 pcmk__action_runnable = (UINT32_C(1) << 1),
129
130 // Whether action should not be executed
131 pcmk__action_optional = (UINT32_C(1) << 2),
132
133 // Whether action should be added to transition graph even if optional
134 pcmk__action_always_in_graph = (UINT32_C(1) << 3),
135
136 // Whether operation-specific instance attributes have been unpacked yet
137 pcmk__action_attrs_evaluated = (UINT32_C(1) << 4),
138
139 // Whether action is allowed to be part of a live migration
140 pcmk__action_migratable = (UINT32_C(1) << 7),
141
142 // Whether action has been added to transition graph
143 pcmk__action_added_to_graph = (UINT32_C(1) << 8),
144
145 // Whether action is a stop to abort a dangling migration
146 pcmk__action_migration_abort = (UINT32_C(1) << 11),
147
148 // Whether action is recurring monitor that must be rescheduled if active
149 pcmk__action_reschedule = (UINT32_C(1) << 13),
150
151 // Whether action has already been processed by a recursive procedure
152 pcmk__action_detect_loop = (UINT32_C(1) << 14),
153
154 // Whether action's inputs have been de-duplicated yet
155 pcmk__action_inputs_deduplicated = (UINT32_C(1) << 15),
156
157 // Whether action can be executed on DC rather than own node
158 pcmk__action_on_dc = (UINT32_C(1) << 16),
159 };
160
161 /* Possible responses to a resource action failure
162 *
163 * The order is significant; the values are in order of increasing severity so
164 * that they can be compared with less than and greater than.
165 */
166 enum pcmk__on_fail {
167 pcmk__on_fail_ignore, // Act as if failure didn't happen
168 pcmk__on_fail_demote, // Demote if promotable, else stop
169 pcmk__on_fail_restart, // Restart resource
170
171 /* Fence the remote node created by the resource if fencing is enabled,
172 * otherwise attempt to restart the resource (used internally for some
173 * remote connection failures).
174 */
175 pcmk__on_fail_reset_remote,
176
177 pcmk__on_fail_restart_container, // Restart resource's container
178 pcmk__on_fail_ban, // Ban resource from current node
179 pcmk__on_fail_block, // Treat resource as unmanaged
180 pcmk__on_fail_stop, // Stop resource and leave stopped
181 pcmk__on_fail_standby_node, // Put resource's node in standby
182 pcmk__on_fail_fence_node, // Fence resource's node
183 };
184
185 // What resource needs before it can be recovered from a failed node
186 enum pcmk__requires {
187 pcmk__requires_nothing = 0, // Resource can be recovered immediately
188 pcmk__requires_quorum = 1, // Resource can be recovered if quorate
189 pcmk__requires_fencing = 2, // Resource can be recovered after fencing
190 };
191
192 // Implementation of pcmk_action_t
193 struct pcmk__action {
194 int id; // Counter to identify action
195
196 /*
197 * When the controller aborts a transition graph, it sets an abort priority.
198 * If this priority is higher, the action will still be executed anyway.
199 * Pseudo-actions are always allowed, so this is irrelevant for them.
200 */
201 int priority;
202
203 pcmk_resource_t *rsc; // Resource to apply action to, if any
204 pcmk_node_t *node; // Copy of node to execute action on, if any
205 xmlNode *op_entry; // Action XML configuration, if any
206 char *task; // Action name
207 char *uuid; // Action key
208 char *cancel_task; // If task is "cancel", the action being cancelled
209 char *reason; // Readable description of why action is needed
210 uint32_t flags; // Group of enum pcmk__action_flags
211 enum pcmk__requires needs; // Prerequisite for recovery
212 enum pcmk__on_fail on_fail; // Response to failure
213 enum rsc_role_e fail_role; // Resource role if action fails
214 GHashTable *meta; // Meta-attributes relevant to action
215 GHashTable *extra; // Action-specific instance attributes
216 pcmk_scheduler_t *scheduler; // Scheduler data this action is part of
217
218 /* Current count of runnable instance actions for "first" action in an
219 * ordering dependency with pcmk__ar_min_runnable set.
220 */
221 int runnable_before;
222
223 /*
224 * Number of instance actions for "first" action in an ordering dependency
225 * with pcmk__ar_min_runnable set that must be runnable before this action
226 * can be runnable.
227 */
228 int required_runnable_before;
229
230 // Actions in a relation with this one (as pcmk__related_action_t *)
231 GList *actions_before;
232 GList *actions_after;
233 };
234
235 char *pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms);
236 char *pcmk__notify_key(const char *rsc_id, const char *notify_type,
237 const char *op_type);
238 char *pcmk__transition_key(int transition_id, int action_id, int target_rc,
239 const char *node);
240 void pcmk__filter_op_for_digest(xmlNode *param_set);
241 bool pcmk__is_fencing_action(const char *action);
242 enum pcmk__action_type pcmk__parse_action(const char *action_name);
243 const char *pcmk__action_text(enum pcmk__action_type action);
244 const char *pcmk__on_fail_text(enum pcmk__on_fail on_fail);
245
246
247 /*!
248 * \internal
249 * \brief Get a human-friendly action name
250 *
251 * \param[in] action_name Actual action name
252 * \param[in] interval_ms Action interval (in milliseconds)
253 *
254 * \return Action name suitable for display
255 */
256 static inline const char *
257 pcmk__readable_action(const char *action_name, guint interval_ms) {
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
258 if ((interval_ms == 0)
259 && pcmk__str_eq(action_name, PCMK_ACTION_MONITOR, pcmk__str_none)) {
260 return "probe";
261 }
262 return action_name;
263 }
264
265 #ifdef __cplusplus
266 }
267 #endif
268
269 #endif // PCMK__CRM_COMMON_ACTIONS_INTERNAL__H