1 /*
2 * Copyright 2012-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 #ifndef PCMK__CRM_COMMON_RESULTS__H
10 #define PCMK__CRM_COMMON_RESULTS__H
11
12 #include <glib.h> // gboolean
13
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17
18 /*!
19 * \file
20 * \brief Function and executable result codes
21 * \ingroup core
22 */
23
24 // Lifted from config.h
25 /* The _Noreturn keyword of C11. */
26 #ifndef _Noreturn
27 # if (defined __cplusplus \
28 && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
29 || (defined _MSC_VER && 1900 <= _MSC_VER)))
30 # define _Noreturn [[noreturn]]
31 # elif ((!defined __cplusplus || defined __clang__) \
32 && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
33 || 4 < __GNUC__ + (7 <= __GNUC_MINOR__)))
34 /* _Noreturn works as-is. */
35 # elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C
36 # define _Noreturn __attribute__ ((__noreturn__))
37 # elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0)
38 # define _Noreturn __declspec (noreturn)
39 # else
40 # define _Noreturn
41 # endif
42 #endif
43
44 /*
45 * Function return codes
46 *
47 * Most Pacemaker API functions return an integer return code. There are two
48 * alternative interpretations. The legacy interpration is that the absolute
49 * value of the return code is either a system error number or a custom
50 * pcmk_err_* number. This is less than ideal because system error numbers are
51 * constrained only to the positive int range, so there's the possibility that
52 * system errors and custom errors could collide (which did in fact happen
53 * already on one architecture). The new intepretation is that negative values
54 * are from the pcmk_rc_e enum, and positive values are system error numbers.
55 * Both use 0 for success.
56 *
57 * For system error codes, see:
58 * - /usr/include/asm-generic/errno.h
59 * - /usr/include/asm-generic/errno-base.h
60 */
61
62 // Legacy custom return codes for Pacemaker API functions (deprecated)
63
64 // NOTE: sbd (as of at least 1.5.2) uses this
65 #define pcmk_ok 0
66
67 #define PCMK_ERROR_OFFSET 190 /* Replacements on non-linux systems, see include/portability.h */
68 #define PCMK_CUSTOM_OFFSET 200 /* Purely custom codes */
69 #define pcmk_err_generic 201
70 #define pcmk_err_no_quorum 202
71 #define pcmk_err_schema_validation 203
72 #define pcmk_err_transform_failed 204
73 #define pcmk_err_old_data 205
74
75 // NOTE: sbd (as of at least 1.5.2) uses this
76 #define pcmk_err_diff_failed 206
77
78 // NOTE: sbd (as of at least 1.5.2) uses this
79 #define pcmk_err_diff_resync 207
80
81 #define pcmk_err_cib_modified 208
82 #define pcmk_err_cib_backup 209
83 #define pcmk_err_cib_save 210
84 #define pcmk_err_schema_unchanged 211
85 #define pcmk_err_cib_corrupt 212
86 #define pcmk_err_multiple 213
87 #define pcmk_err_node_unknown 214
88 #define pcmk_err_already 215
89 /* On HPPA 215 is ENOSYM (Unknown error 215), which hopefully never happens. */
90 #ifdef __hppa__
91 #define pcmk_err_bad_nvpair 250 /* 216 is ENOTSOCK */
92 #define pcmk_err_unknown_format 252 /* 217 is EDESTADDRREQ */
93 #else
94 #define pcmk_err_bad_nvpair 216
95 #define pcmk_err_unknown_format 217
96 #endif
97
98 /*!
99 * \enum pcmk_rc_e
100 * \brief Return codes for Pacemaker API functions
101 *
102 * Any Pacemaker API function documented as returning a "standard Pacemaker
103 * return code" will return pcmk_rc_ok (0) on success, and one of this
104 * enumeration's other (negative) values or a (positive) system error number
105 * otherwise. The custom codes are at -1001 and lower, so that the caller may
106 * use -1 through -1000 for their own custom values if desired. While generally
107 * referred to as "errors", nonzero values simply indicate a result, which might
108 * or might not be an error depending on the calling context.
109 */
110 enum pcmk_rc_e {
111 /* When adding new values, use consecutively lower numbers, update the array
112 * in lib/common/results.c, and test with crm_error.
113 */
114 pcmk_rc_compression = -1039,
115 pcmk_rc_ns_resolution = -1038,
116 pcmk_rc_no_transaction = -1037,
117 pcmk_rc_bad_xml_patch = -1036,
118 pcmk_rc_bad_input = -1035,
119 pcmk_rc_disabled = -1034,
120 pcmk_rc_duplicate_id = -1033,
121 pcmk_rc_unpack_error = -1032,
122 pcmk_rc_invalid_transition = -1031,
123 pcmk_rc_graph_error = -1030,
124 pcmk_rc_dot_error = -1029,
125 pcmk_rc_underflow = -1028,
126 pcmk_rc_no_input = -1027,
127 pcmk_rc_no_output = -1026,
128 pcmk_rc_after_range = -1025,
129 pcmk_rc_within_range = -1024,
130 pcmk_rc_before_range = -1023,
131 pcmk_rc_undetermined = -1022,
132 pcmk_rc_op_unsatisfied = -1021,
133 pcmk_rc_ipc_pid_only = -1020,
134 pcmk_rc_ipc_unresponsive = -1019,
135 pcmk_rc_ipc_unauthorized = -1018,
136 pcmk_rc_no_quorum = -1017,
137 pcmk_rc_schema_validation = -1016,
138 pcmk_rc_schema_unchanged = -1015,
139 pcmk_rc_transform_failed = -1014,
140 pcmk_rc_old_data = -1013,
141 pcmk_rc_diff_failed = -1012,
142 pcmk_rc_diff_resync = -1011,
143 pcmk_rc_cib_modified = -1010,
144 pcmk_rc_cib_backup = -1009,
145 pcmk_rc_cib_save = -1008,
146 pcmk_rc_cib_corrupt = -1007,
147 pcmk_rc_multiple = -1006,
148 pcmk_rc_node_unknown = -1005,
149 pcmk_rc_already = -1004,
150 pcmk_rc_bad_nvpair = -1003,
151 pcmk_rc_unknown_format = -1002,
152 // Developers: Use a more specific code than pcmk_rc_error whenever possible
153 pcmk_rc_error = -1001,
154
155 // Values -1 through -1000 reserved for caller use
156
157 // NOTE: sbd (as of at least 1.5.2) uses this
158 pcmk_rc_ok = 0
159
160 // Positive values reserved for system error numbers
161 };
162
163
164 /*!
165 * \enum ocf_exitcode
166 * \brief Exit status codes for resource agents
167 *
168 * The OCF Resource Agent API standard enumerates the possible exit status codes
169 * that agents should return. Besides being used with OCF agents, these values
170 * are also used by the executor as a universal status for all agent standards;
171 * actual results are mapped to these before returning them to clients.
172 */
173 enum ocf_exitcode {
174 PCMK_OCF_OK = 0, //!< Success
175
176 // NOTE: booth (as of at least 1.1) uses this value
177 PCMK_OCF_UNKNOWN_ERROR = 1, //!< Unspecified error
178
179 PCMK_OCF_INVALID_PARAM = 2, //!< Parameter invalid (in local context)
180 PCMK_OCF_UNIMPLEMENT_FEATURE = 3, //!< Requested action not implemented
181 PCMK_OCF_INSUFFICIENT_PRIV = 4, //!< Insufficient privileges
182 PCMK_OCF_NOT_INSTALLED = 5, //!< Dependencies not available locally
183 PCMK_OCF_NOT_CONFIGURED = 6, //!< Parameter invalid (inherently)
184
185 // NOTE: booth (as of at least 1.1) uses this value
186 PCMK_OCF_NOT_RUNNING = 7, //!< Service safely stopped
187
188 PCMK_OCF_RUNNING_PROMOTED = 8, //!< Service active and promoted
189 PCMK_OCF_FAILED_PROMOTED = 9, //!< Service failed and possibly in promoted role
190 PCMK_OCF_DEGRADED = 190, //!< Service active but more likely to fail soon
191 PCMK_OCF_DEGRADED_PROMOTED = 191, //!< Service promoted but more likely to fail soon
192
193 /* These two are Pacemaker extensions, not in the OCF standard. The
194 * controller records PCMK_OCF_UNKNOWN for pending actions.
195 * PCMK_OCF_CONNECTION_DIED is used only with older DCs that don't support
196 * PCMK_EXEC_NOT_CONNECTED.
197 */
198 PCMK_OCF_CONNECTION_DIED = 189, //!< \deprecated See PCMK_EXEC_NOT_CONNECTED
199 PCMK_OCF_UNKNOWN = 193, //!< Action is pending
200
201 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
202 // Former Pacemaker extensions
203 PCMK_OCF_EXEC_ERROR = 192, //!< \deprecated (Unused)
204 PCMK_OCF_SIGNAL = 194, //!< \deprecated (Unused)
205 PCMK_OCF_NOT_SUPPORTED = 195, //!< \deprecated (Unused)
206 PCMK_OCF_PENDING = 196, //!< \deprecated (Unused)
207 PCMK_OCF_CANCELLED = 197, //!< \deprecated (Unused)
208 PCMK_OCF_TIMEOUT = 198, //!< \deprecated (Unused)
209 PCMK_OCF_OTHER_ERROR = 199, //!< \deprecated (Unused)
210
211 //! \deprecated Use PCMK_OCF_RUNNING_PROMOTED instead
212 PCMK_OCF_RUNNING_MASTER = PCMK_OCF_RUNNING_PROMOTED,
213
214 //! \deprecated Use PCMK_OCF_FAILED_PROMOTED instead
215 PCMK_OCF_FAILED_MASTER = PCMK_OCF_FAILED_PROMOTED,
216
217 //! \deprecated Use PCMK_OCF_DEGRADED_PROMOTED instead
218 PCMK_OCF_DEGRADED_MASTER = PCMK_OCF_DEGRADED_PROMOTED,
219 #endif
220 };
221
222 // NOTE: sbd (as of at least 1.5.2) uses this
223 /*!
224 * \enum crm_exit_e
225 * \brief Exit status codes for tools and daemons
226 *
227 * We want well-specified (i.e. OS-invariant) exit status codes for our daemons
228 * and applications so they can be relied on by callers. (Function return codes
229 * and errno's do not make good exit statuses.)
230 *
231 * The only hard rule is that exit statuses must be between 0 and 255; all else
232 * is convention. Universally, 0 is success, and 1 is generic error (excluding
233 * OSes we don't support -- for example, OpenVMS considers 1 success!).
234 *
235 * For init scripts, the LSB gives meaning to 0-7, and sets aside 150-199 for
236 * application use. OCF adds 8-9 and 190-191.
237 *
238 * sysexits.h was an attempt to give additional meanings, but never really
239 * caught on. It uses 0 and 64-78.
240 *
241 * Bash reserves 2 ("incorrect builtin usage") and 126-255 (126 is "command
242 * found but not executable", 127 is "command not found", 128 + n is
243 * "interrupted by signal n").
244 *
245 * tldp.org recommends 64-113 for application use.
246 *
247 * We try to overlap with the above conventions when practical.
248 */
249 typedef enum crm_exit_e {
250 // Common convention
251 CRM_EX_OK = 0, //!< Success
252 CRM_EX_ERROR = 1, //!< Unspecified error
253
254 // LSB + OCF
255 CRM_EX_INVALID_PARAM = 2, //!< Parameter invalid (in local context)
256 CRM_EX_UNIMPLEMENT_FEATURE = 3, //!< Requested action not implemented
257 CRM_EX_INSUFFICIENT_PRIV = 4, //!< Insufficient privileges
258 CRM_EX_NOT_INSTALLED = 5, //!< Dependencies not available locally
259 CRM_EX_NOT_CONFIGURED = 6, //!< Parameter invalid (inherently)
260 CRM_EX_NOT_RUNNING = 7, //!< Service safely stopped
261 CRM_EX_PROMOTED = 8, //!< Service active and promoted
262 CRM_EX_FAILED_PROMOTED = 9, //!< Service failed and possibly promoted
263
264 // sysexits.h
265 CRM_EX_USAGE = 64, //!< Command line usage error
266 CRM_EX_DATAERR = 65, //!< User-supplied data incorrect
267 CRM_EX_NOINPUT = 66, //!< Input file not available
268 CRM_EX_NOUSER = 67, //!< User does not exist
269 CRM_EX_NOHOST = 68, //!< Host unknown
270 CRM_EX_UNAVAILABLE = 69, //!< Needed service unavailable
271 CRM_EX_SOFTWARE = 70, //!< Internal software bug
272 CRM_EX_OSERR = 71, //!< External (OS/environmental) problem
273 CRM_EX_OSFILE = 72, //!< System file not usable
274 CRM_EX_CANTCREAT = 73, //!< File couldn't be created
275 CRM_EX_IOERR = 74, //!< File I/O error
276 CRM_EX_TEMPFAIL = 75, //!< Try again
277 CRM_EX_PROTOCOL = 76, //!< Protocol violated
278 CRM_EX_NOPERM = 77, //!< Non-file permission issue
279 CRM_EX_CONFIG = 78, //!< Misconfiguration
280
281 // Custom
282 CRM_EX_FATAL = 100, //!< Do not respawn
283 CRM_EX_PANIC = 101, //!< Panic the local host
284 CRM_EX_DISCONNECT = 102, //!< Lost connection to something
285 CRM_EX_OLD = 103, //!< Update older than existing config
286 CRM_EX_DIGEST = 104, //!< Digest comparison failed
287 CRM_EX_NOSUCH = 105, //!< Requested item does not exist
288 CRM_EX_QUORUM = 106, //!< Local partition does not have quorum
289 CRM_EX_UNSAFE = 107, //!< Requires --force or new conditions
290 CRM_EX_EXISTS = 108, //!< Requested item already exists
291 CRM_EX_MULTIPLE = 109, //!< Requested item has multiple matches
292 CRM_EX_EXPIRED = 110, //!< Requested item has expired
293 CRM_EX_NOT_YET_IN_EFFECT = 111, //!< Requested item is not in effect
294 CRM_EX_INDETERMINATE = 112, //!< Could not determine status
295 CRM_EX_UNSATISFIED = 113, //!< Requested item does not satisfy constraints
296
297 // Other
298 CRM_EX_TIMEOUT = 124, //!< Convention from timeout(1)
299
300 /* Anything above 128 overlaps with some shells' use of these values for
301 * "interrupted by signal N", and so may be unreliable when detected by
302 * shell scripts.
303 */
304
305 // OCF Resource Agent API 1.1
306 CRM_EX_DEGRADED = 190, //!< Service active but more likely to fail soon
307 CRM_EX_DEGRADED_PROMOTED = 191, //!< Service promoted but more likely to fail soon
308
309 /* Custom
310 *
311 * This can be used to initialize exit status variables or to indicate that
312 * a command is pending (which is what the controller uses it for).
313 */
314 CRM_EX_NONE = 193, //!< No exit status available
315
316 CRM_EX_MAX = 255, //!< Ensure crm_exit_t can hold this
317 } crm_exit_t;
318
319 /*!
320 * \enum pcmk_exec_status
321 * \brief Execution status
322 *
323 * These codes are used to specify the result of the attempt to execute an
324 * agent, rather than the agent's result itself.
325 */
326 enum pcmk_exec_status {
327 PCMK_EXEC_UNKNOWN = -2, //!< Used only to initialize variables
328 PCMK_EXEC_PENDING = -1, //!< Action is in progress
329 PCMK_EXEC_DONE, //!< Action completed, result is known
330 PCMK_EXEC_CANCELLED, //!< Action was cancelled
331 PCMK_EXEC_TIMEOUT, //!< Action did not complete in time
332 PCMK_EXEC_NOT_SUPPORTED, //!< Agent does not implement requested action
333 PCMK_EXEC_ERROR, //!< Execution failed, may be retried
334 PCMK_EXEC_ERROR_HARD, //!< Execution failed, do not retry on node
335 PCMK_EXEC_ERROR_FATAL, //!< Execution failed, do not retry anywhere
336 PCMK_EXEC_NOT_INSTALLED, //!< Agent or dependency not available locally
337 PCMK_EXEC_NOT_CONNECTED, //!< No connection to executor
338 PCMK_EXEC_INVALID, //!< Action cannot be attempted (e.g. shutdown)
339 PCMK_EXEC_NO_FENCE_DEVICE, //!< No fence device is configured for target
340 PCMK_EXEC_NO_SECRETS, //!< Necessary CIB secrets are unavailable
341
342 // Add new values above here then update this one below
343 PCMK_EXEC_MAX = PCMK_EXEC_NO_SECRETS, //!< Maximum value for this enum
344 };
345
346 /*!
347 * \enum pcmk_result_type
348 * \brief Types of Pacemaker result codes
349 *
350 * A particular integer can have different meanings within different Pacemaker
351 * result code families. It may be interpretable within zero, one, or multiple
352 * families.
353 *
354 * These values are useful for specifying how an integer result code should be
355 * interpreted in situations involving a generic integer value. For example, a
356 * function that can process multiple types of result codes might accept an
357 * arbitrary integer argument along with a \p pcmk_result_type argument that
358 * specifies how to interpret the integer.
359 */
360 enum pcmk_result_type {
361 pcmk_result_legacy = 0, //!< Legacy API function return code
362 pcmk_result_rc = 1, //!< Standard Pacemaker return code
363 pcmk_result_exitcode = 2, //!< Exit status code
364 pcmk_result_exec_status = 3, //!< Execution status
365 };
366
367 int pcmk_result_get_strings(int code, enum pcmk_result_type type,
368 const char **name, const char **desc);
369 const char *pcmk_rc_name(int rc);
370
371 // NOTE: sbd (as of at least 1.5.2) uses this
372 const char *pcmk_rc_str(int rc);
373
374 crm_exit_t pcmk_rc2exitc(int rc);
375 enum ocf_exitcode pcmk_rc2ocf(int rc);
376 int pcmk_rc2legacy(int rc);
377 int pcmk_legacy2rc(int legacy_rc);
378
379 // NOTE: sbd (as of at least 1.5.2) uses this
380 const char *pcmk_strerror(int rc);
381
382 const char *pcmk_errorname(int rc);
383 const char *crm_exit_name(crm_exit_t exit_code);
384
385 // NOTE: sbd (as of at least 1.5.2) uses this
386 const char *crm_exit_str(crm_exit_t exit_code);
387
388 _Noreturn crm_exit_t crm_exit(crm_exit_t rc);
389
390 /* coverity[+kill] */
391 void crm_abort(const char *file, const char *function, int line,
392 const char *condition, gboolean do_core, gboolean do_fork);
393
394 static inline const char *
395 pcmk_exec_status_str(enum pcmk_exec_status status)
/* ![[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)
*/
396 {
397 switch (status) {
398 case PCMK_EXEC_PENDING: return "pending";
399 case PCMK_EXEC_DONE: return "complete";
400 case PCMK_EXEC_CANCELLED: return "Cancelled";
401 case PCMK_EXEC_TIMEOUT: return "Timed Out";
402 case PCMK_EXEC_NOT_SUPPORTED: return "NOT SUPPORTED";
403 case PCMK_EXEC_ERROR: return "Error";
404 case PCMK_EXEC_ERROR_HARD: return "Hard error";
405 case PCMK_EXEC_ERROR_FATAL: return "Fatal error";
406 case PCMK_EXEC_NOT_INSTALLED: return "Not installed";
407 case PCMK_EXEC_NOT_CONNECTED: return "Internal communication failure";
408 case PCMK_EXEC_INVALID: return "Cannot execute now";
409 case PCMK_EXEC_NO_FENCE_DEVICE: return "No fence device";
410 case PCMK_EXEC_NO_SECRETS: return "CIB secrets unavailable";
411 default: return "UNKNOWN!";
412 }
413 }
414
415 #ifdef __cplusplus
416 }
417 #endif
418
419 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
420 #include <crm/common/results_compat.h>
421 #endif
422
423 #endif