summaryrefslogtreecommitdiffstats
path: root/include/crm/common/results.h
blob: 87d00d27f55bcee62f409bfa9c2fd88e7c6726a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
/*
 * Copyright 2012-2023 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_RESULTS__H
#  define PCMK__CRM_COMMON_RESULTS__H

#ifdef __cplusplus
extern "C" {
#endif

/*!
 * \file
 * \brief Function and executable result codes
 * \ingroup core
 */

// Lifted from config.h
/* The _Noreturn keyword of C11.  */
#ifndef _Noreturn
# if (defined __cplusplus \
      && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
          || (defined _MSC_VER && 1900 <= _MSC_VER)))
#  define _Noreturn [[noreturn]]
# elif ((!defined __cplusplus || defined __clang__) \
        && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0)  \
            || 4 < __GNUC__ + (7 <= __GNUC_MINOR__)))
   /* _Noreturn works as-is.  */
# elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C
#  define _Noreturn __attribute__ ((__noreturn__))
# elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0)
#  define _Noreturn __declspec (noreturn)
# else
#  define _Noreturn
# endif
#endif

#  define CRM_ASSERT(expr) do {                                              \
        if (!(expr)) {                                                       \
            crm_abort(__FILE__, __func__, __LINE__, #expr, TRUE, FALSE);     \
            abort(); /* crm_abort() doesn't always abort! */                 \
        }                                                                    \
    } while(0)

/*
 * Function return codes
 *
 * Most Pacemaker API functions return an integer return code. There are two
 * alternative interpretations. The legacy interpration is that the absolute
 * value of the return code is either a system error number or a custom
 * pcmk_err_* number. This is less than ideal because system error numbers are
 * constrained only to the positive int range, so there's the possibility that
 * system errors and custom errors could collide (which did in fact happen
 * already on one architecture). The new intepretation is that negative values
 * are from the pcmk_rc_e enum, and positive values are system error numbers.
 * Both use 0 for success.
 *
 * For system error codes, see:
 * - /usr/include/asm-generic/errno.h
 * - /usr/include/asm-generic/errno-base.h
 */

// 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
/* 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 */
#else
#  define pcmk_err_bad_nvpair           216
#  define pcmk_err_unknown_format       217
#endif

/*!
 * \enum pcmk_rc_e
 * \brief Return codes for Pacemaker API functions
 *
 * Any Pacemaker API function documented as returning a "standard Pacemaker
 * return code" will return pcmk_rc_ok (0) on success, and one of this
 * enumeration's other (negative) values or a (positive) system error number
 * otherwise. The custom codes are at -1001 and lower, so that the caller may
 * use -1 through -1000 for their own custom values if desired. While generally
 * referred to as "errors", nonzero values simply indicate a result, which might
 * or might not be an error depending on the calling context.
 */
enum pcmk_rc_e {
    /* When adding new values, use consecutively lower numbers, update the array
     * in lib/common/results.c, and test with crm_error.
     */
    pcmk_rc_compression         = -1039,
    pcmk_rc_ns_resolution       = -1038,
    pcmk_rc_no_transaction      = -1037,
    pcmk_rc_bad_xml_patch       = -1036,
    pcmk_rc_bad_input           = -1035,
    pcmk_rc_disabled            = -1034,
    pcmk_rc_duplicate_id        = -1033,
    pcmk_rc_unpack_error        = -1032,
    pcmk_rc_invalid_transition  = -1031,
    pcmk_rc_graph_error         = -1030,
    pcmk_rc_dot_error           = -1029,
    pcmk_rc_underflow           = -1028,
    pcmk_rc_no_input            = -1027,
    pcmk_rc_no_output           = -1026,
    pcmk_rc_after_range         = -1025,
    pcmk_rc_within_range        = -1024,
    pcmk_rc_before_range        = -1023,
    pcmk_rc_undetermined        = -1022,
    pcmk_rc_op_unsatisfied      = -1021,
    pcmk_rc_ipc_pid_only        = -1020,
    pcmk_rc_ipc_unresponsive    = -1019,
    pcmk_rc_ipc_unauthorized    = -1018,
    pcmk_rc_no_quorum           = -1017,
    pcmk_rc_schema_validation   = -1016,
    pcmk_rc_schema_unchanged    = -1015,
    pcmk_rc_transform_failed    = -1014,
    pcmk_rc_old_data            = -1013,
    pcmk_rc_diff_failed         = -1012,
    pcmk_rc_diff_resync         = -1011,
    pcmk_rc_cib_modified        = -1010,
    pcmk_rc_cib_backup          = -1009,
    pcmk_rc_cib_save            = -1008,
    pcmk_rc_cib_corrupt         = -1007,
    pcmk_rc_multiple            = -1006,
    pcmk_rc_node_unknown        = -1005,
    pcmk_rc_already             = -1004,
    pcmk_rc_bad_nvpair          = -1003,
    pcmk_rc_unknown_format      = -1002,
    // Developers: Use a more specific code than pcmk_rc_error whenever possible
    pcmk_rc_error               = -1001,

    // Values -1 through -1000 reserved for caller use

    pcmk_rc_ok                  =     0

    // Positive values reserved for system error numbers
};


/*!
 * \enum ocf_exitcode
 * \brief Exit status codes for resource agents
 *
 * The OCF Resource Agent API standard enumerates the possible exit status codes
 * that agents should return. Besides being used with OCF agents, these values
 * are also used by the executor as a universal status for all agent standards;
 * actual results are mapped to these before returning them to clients.
 */
enum ocf_exitcode {
    PCMK_OCF_OK                   = 0,   //!< Success
    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)
    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
    PCMK_OCF_DEGRADED_PROMOTED    = 191, //!< Service promoted but more likely to fail soon

    /* These two are Pacemaker extensions, not in the OCF standard. The
     * controller records PCMK_OCF_UNKNOWN for pending actions.
     * PCMK_OCF_CONNECTION_DIED is used only with older DCs that don't support
     * PCMK_EXEC_NOT_CONNECTED.
     */
    PCMK_OCF_CONNECTION_DIED      = 189, //!< \deprecated See PCMK_EXEC_NOT_CONNECTED
    PCMK_OCF_UNKNOWN              = 193, //!< Action is pending

#if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
    // Former Pacemaker extensions
    PCMK_OCF_EXEC_ERROR           = 192, //!< \deprecated (Unused)
    PCMK_OCF_SIGNAL               = 194, //!< \deprecated (Unused)
    PCMK_OCF_NOT_SUPPORTED        = 195, //!< \deprecated (Unused)
    PCMK_OCF_PENDING              = 196, //!< \deprecated (Unused)
    PCMK_OCF_CANCELLED            = 197, //!< \deprecated (Unused)
    PCMK_OCF_TIMEOUT              = 198, //!< \deprecated (Unused)
    PCMK_OCF_OTHER_ERROR          = 199, //!< \deprecated (Unused)

    //! \deprecated Use PCMK_OCF_RUNNING_PROMOTED instead
    PCMK_OCF_RUNNING_MASTER     = PCMK_OCF_RUNNING_PROMOTED,

    //! \deprecated Use PCMK_OCF_FAILED_PROMOTED instead
    PCMK_OCF_FAILED_MASTER      = PCMK_OCF_FAILED_PROMOTED,

    //! \deprecated Use PCMK_OCF_DEGRADED_PROMOTED instead
    PCMK_OCF_DEGRADED_MASTER    = PCMK_OCF_DEGRADED_PROMOTED,
#endif
};

/*!
 * \enum crm_exit_e
 * \brief Exit status codes for tools and daemons
 *
 * We want well-specified (i.e. OS-invariant) exit status codes for our daemons
 * and applications so they can be relied on by callers. (Function return codes
 * and errno's do not make good exit statuses.)
 *
 * The only hard rule is that exit statuses must be between 0 and 255; all else
 * is convention. Universally, 0 is success, and 1 is generic error (excluding
 * OSes we don't support -- for example, OpenVMS considers 1 success!).
 *
 * For init scripts, the LSB gives meaning to 0-7, and sets aside 150-199 for
 * application use. OCF adds 8-9 and 190-191.
 *
 * sysexits.h was an attempt to give additional meanings, but never really
 * caught on. It uses 0 and 64-78.
 *
 * Bash reserves 2 ("incorrect builtin usage") and 126-255 (126 is "command
 * found but not executable", 127 is "command not found", 128 + n is
 * "interrupted by signal n").
 *
 * tldp.org recommends 64-113 for application use.
 *
 * We try to overlap with the above conventions when practical.
 */
typedef enum crm_exit_e {
    // Common convention
    CRM_EX_OK                   =   0, //!< Success
    CRM_EX_ERROR                =   1, //!< Unspecified error

    // LSB + OCF
    CRM_EX_INVALID_PARAM        =   2, //!< Parameter invalid (in local context)
    CRM_EX_UNIMPLEMENT_FEATURE  =   3, //!< Requested action not implemented
    CRM_EX_INSUFFICIENT_PRIV    =   4, //!< Insufficient privileges
    CRM_EX_NOT_INSTALLED        =   5, //!< Dependencies not available locally
    CRM_EX_NOT_CONFIGURED       =   6, //!< Parameter invalid (inherently)
    CRM_EX_NOT_RUNNING          =   7, //!< Service safely stopped
    CRM_EX_PROMOTED             =   8, //!< Service active and promoted
    CRM_EX_FAILED_PROMOTED      =   9, //!< Service failed and possibly promoted

    // sysexits.h
    CRM_EX_USAGE                =  64, //!< Command line usage error
    CRM_EX_DATAERR              =  65, //!< User-supplied data incorrect
    CRM_EX_NOINPUT              =  66, //!< Input file not available
    CRM_EX_NOUSER               =  67, //!< User does not exist
    CRM_EX_NOHOST               =  68, //!< Host unknown
    CRM_EX_UNAVAILABLE          =  69, //!< Needed service unavailable
    CRM_EX_SOFTWARE             =  70, //!< Internal software bug
    CRM_EX_OSERR                =  71, //!< External (OS/environmental) problem
    CRM_EX_OSFILE               =  72, //!< System file not usable
    CRM_EX_CANTCREAT            =  73, //!< File couldn't be created
    CRM_EX_IOERR                =  74, //!< File I/O error
    CRM_EX_TEMPFAIL             =  75, //!< Try again
    CRM_EX_PROTOCOL             =  76, //!< Protocol violated
    CRM_EX_NOPERM               =  77, //!< Non-file permission issue
    CRM_EX_CONFIG               =  78, //!< Misconfiguration

    // Custom
    CRM_EX_FATAL                = 100, //!< Do not respawn
    CRM_EX_PANIC                = 101, //!< Panic the local host
    CRM_EX_DISCONNECT           = 102, //!< Lost connection to something
    CRM_EX_OLD                  = 103, //!< Update older than existing config
    CRM_EX_DIGEST               = 104, //!< Digest comparison failed
    CRM_EX_NOSUCH               = 105, //!< Requested item does not exist
    CRM_EX_QUORUM               = 106, //!< Local partition does not have quorum
    CRM_EX_UNSAFE               = 107, //!< Requires --force or new conditions
    CRM_EX_EXISTS               = 108, //!< Requested item already exists
    CRM_EX_MULTIPLE             = 109, //!< Requested item has multiple matches
    CRM_EX_EXPIRED              = 110, //!< Requested item has expired
    CRM_EX_NOT_YET_IN_EFFECT    = 111, //!< Requested item is not in effect
    CRM_EX_INDETERMINATE        = 112, //!< Could not determine status
    CRM_EX_UNSATISFIED          = 113, //!< Requested item does not satisfy constraints

    // Other
    CRM_EX_TIMEOUT              = 124, //!< Convention from timeout(1)

    /* Anything above 128 overlaps with some shells' use of these values for
     * "interrupted by signal N", and so may be unreliable when detected by
     * shell scripts.
     */

    // OCF Resource Agent API 1.1
    CRM_EX_DEGRADED             = 190, //!< Service active but more likely to fail soon
    CRM_EX_DEGRADED_PROMOTED    = 191, //!< Service promoted but more likely to fail soon

    /* Custom
     *
     * This can be used to initialize exit status variables or to indicate that
     * a command is pending (which is what the controller uses it for).
     */
    CRM_EX_NONE                 = 193, //!< No exit status available

    CRM_EX_MAX                  = 255, //!< Ensure crm_exit_t can hold this
} crm_exit_t;

/*!
 * \enum pcmk_exec_status
 * \brief Execution status
 *
 * These codes are used to specify the result of the attempt to execute an
 * agent, rather than the agent's result itself.
 */
enum pcmk_exec_status {
    PCMK_EXEC_UNKNOWN = -2,     //!< Used only to initialize variables
    PCMK_EXEC_PENDING = -1,     //!< Action is in progress
    PCMK_EXEC_DONE,             //!< Action completed, result is known
    PCMK_EXEC_CANCELLED,        //!< Action was cancelled
    PCMK_EXEC_TIMEOUT,          //!< Action did not complete in time
    PCMK_EXEC_NOT_SUPPORTED,    //!< Agent does not implement requested action
    PCMK_EXEC_ERROR,            //!< Execution failed, may be retried
    PCMK_EXEC_ERROR_HARD,       //!< Execution failed, do not retry on node
    PCMK_EXEC_ERROR_FATAL,      //!< Execution failed, do not retry anywhere
    PCMK_EXEC_NOT_INSTALLED,    //!< Agent or dependency not available locally
    PCMK_EXEC_NOT_CONNECTED,    //!< No connection to executor
    PCMK_EXEC_INVALID,          //!< Action cannot be attempted (e.g. shutdown)
    PCMK_EXEC_NO_FENCE_DEVICE,  //!< No fence device is configured for target
    PCMK_EXEC_NO_SECRETS,       //!< Necessary CIB secrets are unavailable

    // Add new values above here then update this one below
    PCMK_EXEC_MAX = PCMK_EXEC_NO_SECRETS, //!< Maximum value for this enum
};

/*!
 * \enum pcmk_result_type
 * \brief Types of Pacemaker result codes
 *
 * A particular integer can have different meanings within different Pacemaker
 * result code families. It may be interpretable within zero, one, or multiple
 * families.
 *
 * These values are useful for specifying how an integer result code should be
 * interpreted in situations involving a generic integer value. For example, a
 * function that can process multiple types of result codes might accept an
 * arbitrary integer argument along with a \p pcmk_result_type argument that
 * specifies how to interpret the integer.
 */
enum pcmk_result_type {
    pcmk_result_legacy      = 0,  //!< Legacy API function return code
    pcmk_result_rc          = 1,  //!< Standard Pacemaker return code
    pcmk_result_exitcode    = 2,  //!< Exit status code
    pcmk_result_exec_status = 3,  //!< Execution status
};

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);
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);
const char *pcmk_strerror(int rc);
const char *pcmk_errorname(int rc);
const char *crm_exit_name(crm_exit_t exit_code);
const char *crm_exit_str(crm_exit_t exit_code);
_Noreturn crm_exit_t crm_exit(crm_exit_t rc);

static inline const char *
pcmk_exec_status_str(enum pcmk_exec_status status)
{
    switch (status) {
        case PCMK_EXEC_PENDING:         return "pending";
        case PCMK_EXEC_DONE:            return "complete";
        case PCMK_EXEC_CANCELLED:       return "Cancelled";
        case PCMK_EXEC_TIMEOUT:         return "Timed Out";
        case PCMK_EXEC_NOT_SUPPORTED:   return "NOT SUPPORTED";
        case PCMK_EXEC_ERROR:           return "Error";
        case PCMK_EXEC_ERROR_HARD:      return "Hard error";
        case PCMK_EXEC_ERROR_FATAL:     return "Fatal error";
        case PCMK_EXEC_NOT_INSTALLED:   return "Not installed";
        case PCMK_EXEC_NOT_CONNECTED:   return "Internal communication failure";
        case PCMK_EXEC_INVALID:         return "Cannot execute now";
        case PCMK_EXEC_NO_FENCE_DEVICE: return "No fence device";
        case PCMK_EXEC_NO_SECRETS:      return "CIB secrets unavailable";
        default:                        return "UNKNOWN!";
    }
}

#ifdef __cplusplus
}
#endif

#endif