root/daemons/controld/controld_te_utils.c

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

DEFINITIONS

This source file includes following definitions.
  1. stop_te_timer
  2. te_graph_trigger
  3. trigger_graph_processing
  4. abort_timer_popped
  5. abort_after_delay
  6. abort_transition_graph

   1 /*
   2  * Copyright 2004-2020 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 General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 #include <crm/crm.h>
  12 #include <crm/msg_xml.h>
  13 #include <crm/common/xml.h>
  14 
  15 #include <pacemaker-controld.h>
  16 
  17 gboolean
  18 stop_te_timer(crm_action_timer_t * timer)
     /* [previous][next][first][last][top][bottom][index][help] */
  19 {
  20     if (timer == NULL) {
  21         return FALSE;
  22     }
  23     if (timer->source_id != 0) {
  24         crm_trace("Stopping action timer");
  25         g_source_remove(timer->source_id);
  26         timer->source_id = 0;
  27     } else {
  28         crm_trace("Action timer was already stopped");
  29         return FALSE;
  30     }
  31     return TRUE;
  32 }
  33 
  34 gboolean
  35 te_graph_trigger(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  36 {
  37     enum transition_status graph_rc = -1;
  38 
  39     if (transition_graph == NULL) {
  40         crm_debug("Nothing to do");
  41         return TRUE;
  42     }
  43 
  44     crm_trace("Invoking graph %d in state %s", transition_graph->id, fsa_state2string(fsa_state));
  45 
  46     switch (fsa_state) {
  47         case S_STARTING:
  48         case S_PENDING:
  49         case S_NOT_DC:
  50         case S_HALT:
  51         case S_ILLEGAL:
  52         case S_STOPPING:
  53         case S_TERMINATE:
  54             return TRUE;
  55         default:
  56             break;
  57     }
  58 
  59     if (transition_graph->complete == FALSE) {
  60         int limit = transition_graph->batch_limit;
  61 
  62         transition_graph->batch_limit = throttle_get_total_job_limit(limit);
  63         graph_rc = run_graph(transition_graph);
  64         transition_graph->batch_limit = limit; /* Restore the configured value */
  65 
  66         /* significant overhead... */
  67         /* print_graph(LOG_TRACE, transition_graph); */
  68 
  69         if (graph_rc == transition_active) {
  70             crm_trace("Transition not yet complete");
  71             return TRUE;
  72 
  73         } else if (graph_rc == transition_pending) {
  74             crm_trace("Transition not yet complete - no actions fired");
  75             return TRUE;
  76         }
  77 
  78         if (graph_rc != transition_complete) {
  79             crm_warn("Transition failed: %s", transition_status(graph_rc));
  80             print_graph(LOG_NOTICE, transition_graph);
  81         }
  82     }
  83 
  84     crm_debug("Transition %d is now complete", transition_graph->id);
  85     transition_graph->complete = TRUE;
  86     notify_crmd(transition_graph);
  87 
  88     return TRUE;
  89 }
  90 
  91 void
  92 trigger_graph_processing(const char *fn, int line)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94     crm_trace("%s:%d - Triggered graph processing", fn, line);
  95     mainloop_set_trigger(transition_trigger);
  96 }
  97 
  98 static struct abort_timer_s {
  99     bool aborted;
 100     guint id;
 101     int priority;
 102     enum transition_action action;
 103     const char *text;
 104 } abort_timer = { 0, };
 105 
 106 static gboolean
 107 abort_timer_popped(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109     if (AM_I_DC && (abort_timer.aborted == FALSE)) {
 110         abort_transition(abort_timer.priority, abort_timer.action,
 111                          abort_timer.text, NULL);
 112     }
 113     abort_timer.id = 0;
 114     return FALSE; // do not immediately reschedule timer
 115 }
 116 
 117 /*!
 118  * \internal
 119  * \brief Abort transition after delay, if not already aborted in that time
 120  *
 121  * \param[in] abort_text  Must be literal string
 122  */
 123 void
 124 abort_after_delay(int abort_priority, enum transition_action abort_action,
     /* [previous][next][first][last][top][bottom][index][help] */
 125                   const char *abort_text, guint delay_ms)
 126 {
 127     if (abort_timer.id) {
 128         // Timer already in progress, stop and reschedule
 129         g_source_remove(abort_timer.id);
 130     }
 131     abort_timer.aborted = FALSE;
 132     abort_timer.priority = abort_priority;
 133     abort_timer.action = abort_action;
 134     abort_timer.text = abort_text;
 135     abort_timer.id = g_timeout_add(delay_ms, abort_timer_popped, NULL);
 136 }
 137 
 138 void
 139 abort_transition_graph(int abort_priority, enum transition_action abort_action,
     /* [previous][next][first][last][top][bottom][index][help] */
 140                        const char *abort_text, xmlNode * reason, const char *fn, int line)
 141 {
 142     int add[] = { 0, 0, 0 };
 143     int del[] = { 0, 0, 0 };
 144     int level = LOG_INFO;
 145     xmlNode *diff = NULL;
 146     xmlNode *change = NULL;
 147 
 148     CRM_CHECK(transition_graph != NULL, return);
 149 
 150     switch (fsa_state) {
 151         case S_STARTING:
 152         case S_PENDING:
 153         case S_NOT_DC:
 154         case S_HALT:
 155         case S_ILLEGAL:
 156         case S_STOPPING:
 157         case S_TERMINATE:
 158             crm_info("Abort %s suppressed: state=%s (complete=%d)",
 159                      abort_text, fsa_state2string(fsa_state), transition_graph->complete);
 160             return;
 161         default:
 162             break;
 163     }
 164 
 165     abort_timer.aborted = TRUE;
 166     controld_expect_sched_reply(NULL);
 167 
 168     if (transition_graph->complete == FALSE) {
 169         if(update_abort_priority(transition_graph, abort_priority, abort_action, abort_text)) {
 170             level = LOG_NOTICE;
 171         }
 172     }
 173 
 174     if(reason) {
 175         xmlNode *search = NULL;
 176 
 177         for(search = reason; search; search = search->parent) {
 178             if (pcmk__str_eq(XML_TAG_DIFF, TYPE(search), pcmk__str_casei)) {
 179                 diff = search;
 180                 break;
 181             }
 182         }
 183 
 184         if(diff) {
 185             xml_patch_versions(diff, add, del);
 186             for(search = reason; search; search = search->parent) {
 187                 if (pcmk__str_eq(XML_DIFF_CHANGE, TYPE(search), pcmk__str_casei)) {
 188                     change = search;
 189                     break;
 190                 }
 191             }
 192         }
 193     }
 194 
 195     if(reason == NULL) {
 196         do_crm_log(level, "Transition %d aborted: %s "CRM_XS" source=%s:%d complete=%s",
 197                    transition_graph->id, abort_text, fn, line,
 198                    pcmk__btoa(transition_graph->complete));
 199 
 200     } else if(change == NULL) {
 201         char *local_path = xml_get_path(reason);
 202 
 203         do_crm_log(level, "Transition %d aborted by %s.%s: %s "
 204                    CRM_XS " cib=%d.%d.%d source=%s:%d path=%s complete=%s",
 205                    transition_graph->id, TYPE(reason), ID(reason), abort_text,
 206                    add[0], add[1], add[2], fn, line, local_path,
 207                    pcmk__btoa(transition_graph->complete));
 208         free(local_path);
 209 
 210     } else {
 211         const char *kind = NULL;
 212         const char *op = crm_element_value(change, XML_DIFF_OP);
 213         const char *path = crm_element_value(change, XML_DIFF_PATH);
 214 
 215         if(change == reason) {
 216             if(strcmp(op, "create") == 0) {
 217                 reason = reason->children;
 218 
 219             } else if(strcmp(op, "modify") == 0) {
 220                 reason = first_named_child(reason, XML_DIFF_RESULT);
 221                 if(reason) {
 222                     reason = reason->children;
 223                 }
 224             }
 225         }
 226 
 227         kind = TYPE(reason);
 228         if(strcmp(op, "delete") == 0) {
 229             const char *shortpath = strrchr(path, '/');
 230 
 231             do_crm_log(level, "Transition %d aborted by deletion of %s: %s "
 232                        CRM_XS " cib=%d.%d.%d source=%s:%d path=%s complete=%s",
 233                        transition_graph->id,
 234                        (shortpath? (shortpath + 1) : path), abort_text,
 235                        add[0], add[1], add[2], fn, line, path,
 236                        pcmk__btoa(transition_graph->complete));
 237 
 238         } else if (pcmk__str_eq(XML_CIB_TAG_NVPAIR, kind, pcmk__str_casei)) { 
 239             do_crm_log(level, "Transition %d aborted by %s doing %s %s=%s: %s "
 240                        CRM_XS " cib=%d.%d.%d source=%s:%d path=%s complete=%s",
 241                        transition_graph->id,
 242                        crm_element_value(reason, XML_ATTR_ID), op,
 243                        crm_element_value(reason, XML_NVPAIR_ATTR_NAME),
 244                        crm_element_value(reason, XML_NVPAIR_ATTR_VALUE),
 245                        abort_text, add[0], add[1], add[2], fn, line, path,
 246                        pcmk__btoa(transition_graph->complete));
 247 
 248         } else if (pcmk__str_eq(XML_LRM_TAG_RSC_OP, kind, pcmk__str_casei)) {
 249             const char *magic = crm_element_value(reason, XML_ATTR_TRANSITION_MAGIC);
 250 
 251             do_crm_log(level, "Transition %d aborted by operation %s '%s' on %s: %s "
 252                        CRM_XS " magic=%s cib=%d.%d.%d source=%s:%d complete=%s",
 253                        transition_graph->id,
 254                        crm_element_value(reason, XML_LRM_ATTR_TASK_KEY), op,
 255                        crm_element_value(reason, XML_LRM_ATTR_TARGET), abort_text,
 256                        magic, add[0], add[1], add[2], fn, line,
 257                        pcmk__btoa(transition_graph->complete));
 258 
 259         } else if (pcmk__strcase_any_of(kind, XML_CIB_TAG_STATE, XML_CIB_TAG_NODE, NULL)) {
 260             const char *uname = crm_peer_uname(ID(reason));
 261 
 262             do_crm_log(level, "Transition %d aborted by %s '%s' on %s: %s "
 263                        CRM_XS " cib=%d.%d.%d source=%s:%d complete=%s",
 264                        transition_graph->id,
 265                        kind, op, (uname? uname : ID(reason)), abort_text,
 266                        add[0], add[1], add[2], fn, line,
 267                        pcmk__btoa(transition_graph->complete));
 268 
 269         } else {
 270             const char *id = ID(reason);
 271 
 272             do_crm_log(level, "Transition %d aborted by %s.%s '%s': %s "
 273                        CRM_XS " cib=%d.%d.%d source=%s:%d path=%s complete=%s",
 274                        transition_graph->id,
 275                        TYPE(reason), (id? id : ""), (op? op : "change"),
 276                        abort_text, add[0], add[1], add[2], fn, line, path,
 277                        pcmk__btoa(transition_graph->complete));
 278         }
 279     }
 280 
 281     if (transition_graph->complete) {
 282         if (transition_timer->period_ms > 0) {
 283             controld_stop_timer(transition_timer);
 284             controld_start_timer(transition_timer);
 285         } else {
 286             register_fsa_input(C_FSA_INTERNAL, I_PE_CALC, NULL);
 287         }
 288         return;
 289     }
 290 
 291     mainloop_set_trigger(transition_trigger);
 292 }

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