root/lib/pacemaker/pcmk_trans_utils.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pseudo_action_dummy
  2. set_default_graph_functions
  3. set_graph_functions
  4. transition_status
  5. actiontype2text
  6. find_action
  7. synapse_state_str
  8. synapse_pending_inputs
  9. log_unresolved_inputs
  10. log_synapse_action
  11. print_synapse
  12. print_action
  13. print_graph
  14. abort2text
  15. update_abort_priority

   1 /*
   2  * Copyright 2004-2021 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 #include <crm_internal.h>
  11 
  12 #include <crm/crm.h>
  13 #include <crm/msg_xml.h>
  14 #include <crm/common/xml.h>
  15 #include <pacemaker-internal.h>
  16 
  17 extern crm_graph_functions_t *graph_fns;
  18 
  19 static gboolean
  20 pseudo_action_dummy(crm_graph_t * graph, crm_action_t * action)
     /* [previous][next][first][last][top][bottom][index][help] */
  21 {
  22     static int fail = -1;
  23 
  24     if (fail < 0) {
  25         long long fail_ll;
  26 
  27         if ((pcmk__scan_ll(getenv("PE_fail"), &fail_ll, 0LL) == pcmk_rc_ok)
  28             && (fail_ll > 0LL) && (fail_ll <= INT_MAX)) {
  29             fail = (int) fail_ll;
  30         } else {
  31             fail = 0;
  32         }
  33     }
  34 
  35     crm_trace("Dummy event handler: action %d executed", action->id);
  36     if (action->id == fail) {
  37         crm_err("Dummy event handler: pretending action %d failed", action->id);
  38         action->failed = TRUE;
  39         graph->abort_priority = INFINITY;
  40     }
  41     action->confirmed = TRUE;
  42     update_graph(graph, action);
  43     return TRUE;
  44 }
  45 
  46 crm_graph_functions_t default_fns = {
  47     pseudo_action_dummy,
  48     pseudo_action_dummy,
  49     pseudo_action_dummy,
  50     pseudo_action_dummy
  51 };
  52 
  53 void
  54 set_default_graph_functions(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  55 {
  56     graph_fns = &default_fns;
  57 }
  58 
  59 void
  60 set_graph_functions(crm_graph_functions_t * fns)
     /* [previous][next][first][last][top][bottom][index][help] */
  61 {
  62     crm_info("Setting custom graph functions");
  63     graph_fns = fns;
  64 
  65     CRM_ASSERT(graph_fns != NULL);
  66     CRM_ASSERT(graph_fns->rsc != NULL);
  67     CRM_ASSERT(graph_fns->crmd != NULL);
  68     CRM_ASSERT(graph_fns->pseudo != NULL);
  69     CRM_ASSERT(graph_fns->stonith != NULL);
  70 }
  71 
  72 const char *
  73 transition_status(enum transition_status state)
     /* [previous][next][first][last][top][bottom][index][help] */
  74 {
  75     switch (state) {
  76         case transition_active:
  77             return "active";
  78         case transition_pending:
  79             return "pending";
  80         case transition_complete:
  81             return "complete";
  82         case transition_stopped:
  83             return "stopped";
  84         case transition_terminated:
  85             return "terminated";
  86         case transition_action_failed:
  87             return "failed (action)";
  88         case transition_failed:
  89             return "failed";
  90     }
  91     return "unknown";
  92 }
  93 
  94 const char *
  95 actiontype2text(action_type_e type)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97     switch (type) {
  98         case action_type_pseudo:
  99             return "pseudo";
 100         case action_type_rsc:
 101             return "resource";
 102         case action_type_crm:
 103             return "cluster";
 104     }
 105     return "invalid";
 106 }
 107 
 108 static crm_action_t *
 109 find_action(crm_graph_t * graph, int id)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111     GList *sIter = NULL;
 112 
 113     if (graph == NULL) {
 114         return NULL;
 115     }
 116 
 117     for (sIter = graph->synapses; sIter != NULL; sIter = sIter->next) {
 118         GList *aIter = NULL;
 119         synapse_t *synapse = (synapse_t *) sIter->data;
 120 
 121         for (aIter = synapse->actions; aIter != NULL; aIter = aIter->next) {
 122             crm_action_t *action = (crm_action_t *) aIter->data;
 123 
 124             if (action->id == id) {
 125                 return action;
 126             }
 127         }
 128     }
 129     return NULL;
 130 }
 131 
 132 static const char *
 133 synapse_state_str(synapse_t *synapse)
     /* [previous][next][first][last][top][bottom][index][help] */
 134 {
 135     if (synapse->failed) {
 136         return "Failed";
 137 
 138     } else if (synapse->confirmed) {
 139         return "Completed";
 140 
 141     } else if (synapse->executed) {
 142         return "In-flight";
 143 
 144     } else if (synapse->ready) {
 145         return "Ready";
 146     }
 147     return "Pending";
 148 }
 149 
 150 // List action IDs of inputs in graph that haven't completed successfully
 151 static char *
 152 synapse_pending_inputs(crm_graph_t *graph, synapse_t *synapse)
     /* [previous][next][first][last][top][bottom][index][help] */
 153 {
 154     char *pending = NULL;
 155     size_t pending_len = 0;
 156 
 157     for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
 158         crm_action_t *input = (crm_action_t *) lpc->data;
 159 
 160         if (input->failed) {
 161             pcmk__add_word(&pending, &pending_len, ID(input->xml));
 162 
 163         } else if (input->confirmed) {
 164             // Confirmed successful inputs are not pending
 165 
 166         } else if (find_action(graph, input->id) != NULL) {
 167             // In-flight or pending
 168             pcmk__add_word(&pending, &pending_len, ID(input->xml));
 169         }
 170     }
 171     if (pending == NULL) {
 172         pending = strdup("none");
 173     }
 174     return pending;
 175 }
 176 
 177 // Log synapse inputs that aren't in graph
 178 static void
 179 log_unresolved_inputs(unsigned int log_level, crm_graph_t *graph,
     /* [previous][next][first][last][top][bottom][index][help] */
 180                       synapse_t *synapse)
 181 {
 182     for (GList *lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
 183         crm_action_t *input = (crm_action_t *) lpc->data;
 184         const char *key = crm_element_value(input->xml, XML_LRM_ATTR_TASK_KEY);
 185         const char *host = crm_element_value(input->xml, XML_LRM_ATTR_TARGET);
 186 
 187         if (find_action(graph, input->id) == NULL) {
 188             do_crm_log(log_level,
 189                        " * [Input %2d]: Unresolved dependency %s op %s%s%s",
 190                        input->id, actiontype2text(input->type), key,
 191                        (host? " on " : ""), (host? host : ""));
 192         }
 193     }
 194 }
 195 
 196 static void
 197 log_synapse_action(unsigned int log_level, synapse_t *synapse,
     /* [previous][next][first][last][top][bottom][index][help] */
 198                    crm_action_t *action, const char *pending_inputs)
 199 {
 200     const char *key = crm_element_value(action->xml, XML_LRM_ATTR_TASK_KEY);
 201     const char *host = crm_element_value(action->xml, XML_LRM_ATTR_TARGET);
 202     char *desc = crm_strdup_printf("%s %s op %s",
 203                                    synapse_state_str(synapse),
 204                                    actiontype2text(action->type), key);
 205 
 206     do_crm_log(log_level,
 207                "[Action %4d]: %-50s%s%s (priority: %d, waiting: %s)",
 208                action->id, desc, (host? " on " : ""), (host? host : ""),
 209                synapse->priority, pending_inputs);
 210     free(desc);
 211 }
 212 
 213 static void
 214 print_synapse(unsigned int log_level, crm_graph_t * graph, synapse_t * synapse)
     /* [previous][next][first][last][top][bottom][index][help] */
 215 {
 216     char *pending = NULL;
 217 
 218     if (!synapse->executed) {
 219         pending = synapse_pending_inputs(graph, synapse);
 220     }
 221     for (GList *lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
 222         log_synapse_action(log_level, synapse, (crm_action_t *) lpc->data,
 223                            pending);
 224     }
 225     free(pending);
 226     if (!synapse->executed) {
 227         log_unresolved_inputs(log_level, graph, synapse);
 228     }
 229 }
 230 
 231 void
 232 print_action(int log_level, const char *prefix, crm_action_t * action)
     /* [previous][next][first][last][top][bottom][index][help] */
 233 {
 234     print_synapse(log_level, NULL, action->synapse);
 235 }
 236 
 237 void
 238 print_graph(unsigned int log_level, crm_graph_t * graph)
     /* [previous][next][first][last][top][bottom][index][help] */
 239 {
 240     GList *lpc = NULL;
 241 
 242     if (graph == NULL || graph->num_actions == 0) {
 243         if (log_level == LOG_TRACE) {
 244             crm_debug("Empty transition graph");
 245         }
 246         return;
 247     }
 248 
 249     do_crm_log(log_level, "Graph %d with %d actions:"
 250                " batch-limit=%d jobs, network-delay=%ums",
 251                graph->id, graph->num_actions,
 252                graph->batch_limit, graph->network_delay);
 253 
 254     for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
 255         synapse_t *synapse = (synapse_t *) lpc->data;
 256 
 257         print_synapse(log_level, graph, synapse);
 258     }
 259 }
 260 
 261 static const char *
 262 abort2text(enum transition_action abort_action)
     /* [previous][next][first][last][top][bottom][index][help] */
 263 {
 264     switch (abort_action) {
 265         case tg_done:
 266             return "done";
 267         case tg_stop:
 268             return "stop";
 269         case tg_restart:
 270             return "restart";
 271         case tg_shutdown:
 272             return "shutdown";
 273     }
 274     return "unknown";
 275 }
 276 
 277 bool
 278 update_abort_priority(crm_graph_t * graph, int priority,
     /* [previous][next][first][last][top][bottom][index][help] */
 279                       enum transition_action action, const char *abort_reason)
 280 {
 281     bool change = FALSE;
 282 
 283     if (graph == NULL) {
 284         return change;
 285     }
 286 
 287     if (graph->abort_priority < priority) {
 288         crm_debug("Abort priority upgraded from %d to %d", graph->abort_priority, priority);
 289         graph->abort_priority = priority;
 290         if (graph->abort_reason != NULL) {
 291             crm_debug("'%s' abort superseded by %s", graph->abort_reason, abort_reason);
 292         }
 293         graph->abort_reason = abort_reason;
 294         change = TRUE;
 295     }
 296 
 297     if (graph->completion_action < action) {
 298         crm_debug("Abort action %s superseded by %s: %s",
 299                   abort2text(graph->completion_action), abort2text(action), abort_reason);
 300         graph->completion_action = action;
 301         change = TRUE;
 302     }
 303 
 304     return change;
 305 }

/* [previous][next][first][last][top][bottom][index][help] */