File: actions_internal.h

package info (click to toggle)
pacemaker 3.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 68,576 kB
  • sloc: xml: 160,564; ansic: 143,744; python: 5,670; sh: 2,969; makefile: 2,426
file content (302 lines) | stat: -rw-r--r-- 11,871 bytes parent folder | download
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
/*
 * 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_ACTIONS_INTERNAL__H
#define PCMK__CRM_COMMON_ACTIONS_INTERNAL__H

#include <stdbool.h>                        // bool
#include <stdint.h>                         // uint32_t, UINT32_C()
#include <glib.h>                           // guint, GList, GHashTable
#include <libxml/tree.h>                    // xmlNode

#include <crm/common/actions.h>             // PCMK_ACTION_MONITOR
#include <crm/common/roles.h>               // enum rsc_role_e
#include <crm/common/scheduler_types.h>     // pcmk_resource_t, pcmk_node_t
#include <crm/common/strings_internal.h>    // pcmk__str_eq()

#include <crm/common/strings_internal.h>    // pcmk__str_any_of()

#ifdef __cplusplus
extern "C" {
#endif

//! 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 pcmk__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 pcmk__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 pcmk__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 pcmk__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)

// Possible actions (including some pseudo-actions)
enum pcmk__action_type {
    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_start,             // Start
    pcmk__action_started,           // Start completed

    pcmk__action_notify,            // Notify
    pcmk__action_notified,          // Notify completed

    pcmk__action_promote,           // Promote
    pcmk__action_promoted,          // Promoted

    pcmk__action_demote,            // Demote
    pcmk__action_demoted,           // Demoted

    pcmk__action_shutdown,          // Shut down node
    pcmk__action_fence,             // Fence node
};

// Action scheduling flags
enum pcmk__action_flags {
    // No action flags set (compare with equality rather than bit set)
    pcmk__no_action_flags               = 0,

    // Whether action does not require invoking an agent
    pcmk__action_pseudo                 = (UINT32_C(1) << 0),

    // Whether action is runnable
    pcmk__action_runnable               = (UINT32_C(1) << 1),

    // Whether action should not be executed
    pcmk__action_optional               = (UINT32_C(1) << 2),

    // Whether action should be added to transition graph even if optional
    pcmk__action_always_in_graph        = (UINT32_C(1) << 3),

    // Whether operation-specific instance attributes have been unpacked yet
    pcmk__action_attrs_evaluated        = (UINT32_C(1) << 4),

    // Whether action is allowed to be part of a live migration
    pcmk__action_migratable             = (UINT32_C(1) << 7),

    // Whether action has been added to transition graph
    pcmk__action_added_to_graph         = (UINT32_C(1) << 8),

    // Whether action is a stop to abort a dangling migration
    pcmk__action_migration_abort        = (UINT32_C(1) << 11),

    // Whether action is recurring monitor that must be rescheduled if active
    pcmk__action_reschedule             = (UINT32_C(1) << 13),

    // Whether action has already been processed by a recursive procedure
    pcmk__action_detect_loop            = (UINT32_C(1) << 14),

    // Whether action's inputs have been de-duplicated yet
    pcmk__action_inputs_deduplicated    = (UINT32_C(1) << 15),

    // Whether action can be executed on DC rather than own node
    pcmk__action_on_dc                  = (UINT32_C(1) << 16),
};

/* Possible responses to a resource action failure
 *
 * The order is significant; the values are in order of increasing severity so
 * that they can be compared with less than and greater than.
 */
enum pcmk__on_fail {
    pcmk__on_fail_ignore,               // Act as if failure didn't happen
    pcmk__on_fail_demote,               // Demote if promotable, else stop
    pcmk__on_fail_restart,              // Restart resource

    /* 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).
     */
    pcmk__on_fail_reset_remote,

    pcmk__on_fail_restart_container,    // Restart resource's container
    pcmk__on_fail_ban,                  // Ban resource from current node
    pcmk__on_fail_block,                // Treat resource as unmanaged
    pcmk__on_fail_stop,                 // Stop resource and leave stopped
    pcmk__on_fail_standby_node,         // Put resource's node in standby
    pcmk__on_fail_fence_node,           // Fence resource's node
};

// What resource needs before it can be recovered from a failed node
enum pcmk__requires {
    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
};

// Implementation of pcmk_action_t
struct pcmk__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;      // Copy of 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
    uint32_t flags;         // Group of enum pcmk__action_flags
    enum pcmk__requires needs;          // Prerequisite for recovery
    enum pcmk__on_fail 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
    pcmk_scheduler_t *scheduler;        // Scheduler data this action is part of

    /* Current count of runnable instance actions for "first" action in an
     * ordering dependency with pcmk__ar_min_runnable set.
     */
    int runnable_before;

    /*
     * 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.
     */
    int required_runnable_before;

    // Actions in a relation with this one (as pcmk__related_action_t *)
    GList *actions_before;
    GList *actions_after;
};

void pcmk__free_action(gpointer user_data);
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);
char *pcmk__transition_key(int transition_id, int action_id, int target_rc,
                           const char *node);
void pcmk__filter_op_for_digest(xmlNode *param_set);
bool pcmk__is_fencing_action(const char *action);
enum pcmk__action_type pcmk__parse_action(const char *action_name);
const char *pcmk__action_text(enum pcmk__action_type action);
const char *pcmk__on_fail_text(enum pcmk__on_fail on_fail);


/*!
 * \internal
 * \brief Get a human-friendly action name
 *
 * \param[in] action_name  Actual action name
 * \param[in] interval_ms  Action interval (in milliseconds)
 *
 * \return Action name suitable for display
 */
static inline const char *
pcmk__readable_action(const char *action_name, guint interval_ms) {
    if ((interval_ms == 0)
        && pcmk__str_eq(action_name, PCMK_ACTION_MONITOR, pcmk__str_none)) {
        return "probe";
    }
    return action_name;
}

/*!
 * \internal
 * \brief Check whether an action raises a resource's role
 *
 * \param[in] action  Action to check
 *
 * \return \c true if \p action is "start", "promote", or "migrate_from"
 */
static inline bool
pcmk__is_up_action(const char *action)
{
    return pcmk__str_any_of(action, PCMK_ACTION_START, PCMK_ACTION_PROMOTE,
                            PCMK_ACTION_MIGRATE_FROM, NULL);
}

/*!
 * \internal
 * \brief Check whether an action lowers a resource's role
 *
 * \param[in] action  Action to check
 *
 * \return \c true if \p action is "stop", "demote", or "migrate_to"
 */
static inline bool
pcmk__is_down_action(const char *action)
{
    return pcmk__str_any_of(action, PCMK_ACTION_STOP, PCMK_ACTION_DEMOTE,
                            PCMK_ACTION_MIGRATE_TO, NULL);
}

#ifdef __cplusplus
}
#endif

#endif // PCMK__CRM_COMMON_ACTIONS_INTERNAL__H