1 /* 2 * Copyright 2023-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_ACTION_RELATION_INTERNAL__H 11 #define PCMK__CRM_COMMON_ACTION_RELATION_INTERNAL__H 12 13 #include <stdint.h> // uint32_t 14 #include <crm/common/scheduler_types.h> // pcmk_resource_t, pcmk_action_t 15 16 /*! 17 * Flags to indicate the relationship between two actions 18 * 19 * @COMPAT The values and semantics of these flags should not be changed until 20 * the deprecated enum pe_ordering is dropped from the public API. 21 */ 22 enum pcmk__action_relation_flags { 23 //! No relation (compare with equality rather than bit set) 24 pcmk__ar_none = 0U, 25 26 //! Actions are ordered (optionally, if no other flags are set) 27 pcmk__ar_ordered = (1U << 0), 28 29 //! Relation applies only if 'first' cannot be part of a live migration 30 pcmk__ar_if_first_unmigratable = (1U << 1), 31 32 /*! 33 * If 'then' is required, 'first' becomes required (and becomes unmigratable 34 * if 'then' is); also, if 'first' is a stop of a blocked resource, 'then' 35 * becomes unrunnable 36 */ 37 pcmk__ar_then_implies_first = (1U << 4), 38 39 /*! 40 * If 'first' is required, 'then' becomes required; if 'first' is a stop of 41 * a blocked resource, 'then' becomes unrunnable 42 */ 43 pcmk__ar_first_implies_then = (1U << 5), 44 45 /*! 46 * If 'then' is required and for a promoted instance, 'first' becomes 47 * required (and becomes unmigratable if 'then' is) 48 */ 49 pcmk__ar_promoted_then_implies_first = (1U << 6), 50 51 /*! 52 * 'first' is runnable only if 'then' is both runnable and migratable, 53 * and 'first' becomes required if 'then' is 54 */ 55 pcmk__ar_unmigratable_then_blocks = (1U << 7), 56 57 //! 'then' is runnable (and migratable) only if 'first' is runnable 58 pcmk__ar_unrunnable_first_blocks = (1U << 8), 59 60 //! If 'first' is unrunnable, 'then' becomes a real, unmigratable action 61 pcmk__ar_first_else_then = (1U << 9), 62 63 //! If 'first' is required, 'then' action for instance on same node is 64 pcmk__ar_first_implies_same_node_then = (1U << 10), 65 66 /*! 67 * Disable relation if 'first' is unrunnable and for an active resource, 68 * otherwise order actions and make 'then' unrunnable if 'first' is. 69 * 70 * This is used to order a bundle replica's start of its container before a 71 * probe of its remote connection resource, in case the connection uses the 72 * REMOTE_CONTAINER_HACK to replace the connection address with where the 73 * container is running. 74 */ 75 pcmk__ar_nested_remote_probe = (1U << 11), 76 77 /*! 78 * If 'first' is for a blocked resource, make 'then' unrunnable. 79 * 80 * If 'then' is required, make 'first' required, make 'first' unmigratable 81 * if 'then' is unmigratable, and make 'then' unrunnable if 'first' is 82 * unrunnable. 83 * 84 * If 'then' is unrunnable and for the same resource as 'first', make 85 * 'first' required if it is runnable, and make 'first' unmigratable if 86 * 'then' is unmigratable. 87 * 88 * This is used for "stop then start primitive" (restarts) and 89 * "stop group member then stop previous member". 90 */ 91 pcmk__ar_intermediate_stop = (1U << 12), 92 93 /*! 94 * The actions must be serialized if in the same transition but can be in 95 * either order. (In practice, we always arrange them as 'first' then 96 * 'then', so they end up being essentially the same as optional orderings.) 97 * 98 * @TODO Handle more intelligently -- for example, we could schedule the 99 * action with the fewest inputs first, so we're more likely to execute at 100 * least one if there is a failure during the transition. Or, we could 101 * prefer certain action types over others, or base it on resource priority. 102 */ 103 pcmk__ar_serialize = (1U << 14), 104 105 //! Relation applies only if actions are on same node 106 pcmk__ar_if_on_same_node = (1U << 15), 107 108 //! If 'then' is required, 'first' must be added to the transition graph 109 pcmk__ar_then_implies_first_graphed = (1U << 16), 110 111 //! If 'first' is required and runnable, 'then' must be in graph 112 pcmk__ar_first_implies_then_graphed = (1U << 17), 113 114 //! User-configured asymmetric ordering 115 pcmk__ar_asymmetric = (1U << 20), 116 117 //! Actions are ordered if on same node (or migration target for migrate_to) 118 pcmk__ar_if_on_same_node_or_target = (1U << 21), 119 120 //! 'then' action is runnable if certain number of 'first' instances are 121 pcmk__ar_min_runnable = (1U << 22), 122 123 //! Ordering applies only if 'first' is required and on same node as 'then' 124 pcmk__ar_if_required_on_same_node = (1U << 23), 125 126 //! Ordering applies even if 'first' runs on guest node created by 'then' 127 pcmk__ar_guest_allowed = (1U << 24), 128 129 //! If 'then' action becomes required, 'first' becomes optional 130 pcmk__ar_then_cancels_first = (1U << 25), 131 }; 132 133 /* Action relation object 134 * 135 * The most common type of relation is an ordering, in which case action1 etc. 136 * refers to the "first" action, and action2 etc. refers to the "then" action. 137 */ 138 typedef struct { 139 int id; // Counter to identify relation 140 uint32_t flags; // Group of enum pcmk__action_relation_flags 141 pcmk_resource_t *rsc1; // Resource for first action, if any 142 pcmk_action_t *action1; // First action in relation 143 char *task1; // Action name or key for first action 144 pcmk_resource_t *rsc2; // Resource for second action, if any 145 pcmk_action_t *action2; // Second action in relation 146 char *task2; // Action name or key for second action 147 } pcmk__action_relation_t; 148 149 typedef struct pe_action_wrapper_s pcmk__related_action_t; 150 151 /*! 152 * \internal 153 * \brief Set action relation flags 154 * 155 * \param[in,out] ar_flags Flag group to modify 156 * \param[in] flags_to_set enum pcmk__action_relation_flags to set 157 */ 158 #define pcmk__set_relation_flags(ar_flags, flags_to_set) do { \ 159 ar_flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, \ 160 "Action relation", "constraint", \ 161 ar_flags, (flags_to_set), \ 162 #flags_to_set); \ 163 } while (0) 164 165 /*! 166 * \internal 167 * \brief Clear action relation flags 168 * 169 * \param[in,out] ar_flags Flag group to modify 170 * \param[in] flags_to_clear enum pcmk__action_relation_flags to clear 171 */ 172 #define pcmk__clear_relation_flags(ar_flags, flags_to_clear) do { \ 173 ar_flags = pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, \ 174 "Action relation", "constraint", \ 175 ar_flags, (flags_to_clear), \ 176 #flags_to_clear); \ 177 } while (0) 178 179 #endif // PCMK__CRM_COMMON_ACTION_RELATION_INTERNAL__H