root/lib/pengine/pe_health.c

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

DEFINITIONS

This source file includes following definitions.
  1. pe__unpack_node_health_scores
  2. add_node_health_value
  3. pe__sum_node_health_scores
  4. pe__node_health

   1 /*
   2  * Copyright 2004-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 #include <crm_internal.h>
  11 
  12 #include <crm/pengine/status.h>
  13 #include <crm/pengine/internal.h>
  14 #include "pe_status_private.h"
  15 
  16 /*!
  17  * \internal
  18  * \brief Set the node health values to use for \c PCMK_VALUE_RED,
  19  *        \c PCMK_VALUE_YELLOW, and \c PCMK_VALUE_GREEN
  20  *
  21  * \param[in,out] scheduler  Scheduler data
  22  */
  23 void
  24 pe__unpack_node_health_scores(pcmk_scheduler_t *scheduler)
     /* [previous][next][first][last][top][bottom][index][help] */
  25 {
  26     switch (pe__health_strategy(scheduler)) {
  27         case pcmk__health_strategy_none:
  28             pcmk__score_red = 0;
  29             pcmk__score_yellow = 0;
  30             pcmk__score_green = 0;
  31             break;
  32 
  33         case pcmk__health_strategy_no_red:
  34             pcmk__score_red = -PCMK_SCORE_INFINITY;
  35             pcmk__score_yellow = 0;
  36             pcmk__score_green = 0;
  37             break;
  38 
  39         case pcmk__health_strategy_only_green:
  40             pcmk__score_red = -PCMK_SCORE_INFINITY;
  41             pcmk__score_yellow = -PCMK_SCORE_INFINITY;
  42             pcmk__score_green = 0;
  43             break;
  44 
  45         default: // progressive or custom
  46             pcmk__score_red = pcmk__health_score(PCMK_OPT_NODE_HEALTH_RED,
  47                                                  scheduler);
  48             pcmk__score_green = pcmk__health_score(PCMK_OPT_NODE_HEALTH_GREEN,
  49                                                    scheduler);
  50             pcmk__score_yellow = pcmk__health_score(PCMK_OPT_NODE_HEALTH_YELLOW,
  51                                                     scheduler);
  52             break;
  53     }
  54 
  55     if ((pcmk__score_red != 0) || (pcmk__score_yellow != 0)
  56         || (pcmk__score_green != 0)) {
  57         crm_debug("Values of node health scores: "
  58                   PCMK_VALUE_RED "=%d "
  59                   PCMK_VALUE_YELLOW "=%d "
  60                   PCMK_VALUE_GREEN "=%d",
  61                   pcmk__score_red, pcmk__score_yellow, pcmk__score_green);
  62     }
  63 }
  64 
  65 struct health_sum {
  66     const pcmk_node_t *node; // Node that health score is being summed for
  67     int sum;                 // Sum of health scores checked so far
  68 };
  69 
  70 /*!
  71  * \internal
  72  * \brief Add node attribute value to an integer, if it is a health attribute
  73  *
  74  * \param[in]     key        Name of node attribute
  75  * \param[in]     value      String value of node attribute
  76  * \param[in,out] user_data  Address of integer to which \p value should be
  77  *                           added if \p key is a node health attribute
  78  */
  79 static void
  80 add_node_health_value(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82     if (pcmk__starts_with((const char *) key, "#health")) {
  83         struct health_sum *health_sum = user_data;
  84         int score = 0;
  85         int rc = pcmk_parse_score((const char *) value, &score, 0);
  86 
  87         if (rc != pcmk_rc_ok) {
  88             crm_warn("Ignoring %s for %s because '%s' is not a valid value: %s",
  89                      (const char *) key, pcmk__node_name(health_sum->node),
  90                      (const char *) value, pcmk_rc_str(rc));
  91             return;
  92         }
  93 
  94         health_sum->sum = pcmk__add_scores(score, health_sum->sum);
  95         crm_trace("Combined '%s' into node health score (now %s)",
  96                   (const char *) value, pcmk_readable_score(health_sum->sum));
  97     }
  98 }
  99 
 100 /*!
 101  * \internal
 102  * \brief Sum a node's health attribute scores
 103  *
 104  * \param[in] node         Node whose health attributes should be added
 105  * \param[in] base_health  Add this number to the total
 106  *
 107  * \return Sum of all health attribute scores of \p node plus \p base_health
 108  */
 109 int
 110 pe__sum_node_health_scores(const pcmk_node_t *node, int base_health)
     /* [previous][next][first][last][top][bottom][index][help] */
 111 {
 112     struct health_sum health_sum = { node, base_health, };
 113 
 114     pcmk__assert(node != NULL);
 115     g_hash_table_foreach(node->details->attrs, add_node_health_value,
 116                          &health_sum);
 117     return health_sum.sum;
 118 }
 119 
 120 /*!
 121  * \internal
 122  * \brief Check the general health status for a node
 123  *
 124  * \param[in,out] node  Node to check
 125  *
 126  * \return  A negative value if any health attribute for \p node is red,
 127  *          otherwise 0 if any attribute is yellow, otherwise a positive value.
 128  */
 129 int
 130 pe__node_health(pcmk_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132     GHashTableIter iter;
 133     const char *name = NULL;
 134     const char *value = NULL;
 135     enum pcmk__health_strategy strategy;
 136     int score = 0;
 137     int rc = 1;
 138 
 139     pcmk__assert(node != NULL);
 140 
 141     strategy = pe__health_strategy(node->details->data_set);
 142     if (strategy == pcmk__health_strategy_none) {
 143         return rc;
 144     }
 145 
 146     g_hash_table_iter_init(&iter, node->details->attrs);
 147     while (g_hash_table_iter_next(&iter, (gpointer *) &name,
 148                                   (gpointer *) &value)) {
 149         if (pcmk__starts_with(name, "#health")) {
 150             int parse_rc = pcmk_rc_ok;
 151 
 152             /* It's possible that pcmk__score_red equals pcmk__score_yellow,
 153              * or pcmk__score_yellow equals pcmk__score_green, so check the
 154              * textual value first to be able to distinguish those.
 155              */
 156             if (pcmk__str_eq(value, PCMK_VALUE_RED, pcmk__str_casei)) {
 157                 return -1;
 158             } else if (pcmk__str_eq(value, PCMK_VALUE_YELLOW,
 159                                     pcmk__str_casei)) {
 160                 rc = 0;
 161                 continue;
 162             }
 163 
 164             parse_rc = pcmk_parse_score(value, &score, 0);
 165             if (parse_rc != pcmk_rc_ok) {
 166                 crm_warn("Treating %s for %s as 0 "
 167                          "because '%s' is not a valid value: %s",
 168                          name, pcmk__node_name(node), value,
 169                          pcmk_rc_str(parse_rc));
 170             }
 171 
 172             // The value is an integer, so compare numerically
 173             if (score <= pcmk__score_red) {
 174                 return -1;
 175             } else if ((score <= pcmk__score_yellow)
 176                        && (pcmk__score_yellow != pcmk__score_green)) {
 177                 rc = 0;
 178             }
 179         }
 180     }
 181     return rc;
 182 }

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