pacemaker  2.1.9-49aab99839
Scalable High-Availability cluster resource manager
pe_health.c
Go to the documentation of this file.
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 
23 void
25 {
26  switch (pe__health_strategy(scheduler)) {
28  pcmk__score_red = 0;
31  break;
32 
37  break;
38 
43  break;
44 
45  default: // progressive or custom
47  scheduler);
49  scheduler);
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",
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 
79 static void
80 add_node_health_value(gpointer key, gpointer value, gpointer user_data)
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 
109 int
110 pe__sum_node_health_scores(const pcmk_node_t *node, int base_health)
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 
129 int
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)
177  rc = 0;
178  }
179  }
180  }
181  return rc;
182 }
GHashTable * attrs
Definition: nodes.h:143
#define PCMK_VALUE_GREEN
Definition: options.h:157
#define PCMK_OPT_NODE_HEALTH_GREEN
Definition: options.h:49
int pcmk__health_score(const char *option, const pcmk_scheduler_t *scheduler)
Definition: health.c:82
const char * name
Definition: cib.c:26
const char * pcmk_readable_score(int score)
Return a displayable static string for a score value.
Definition: scores.c:137
#define PCMK_OPT_NODE_HEALTH_RED
Definition: options.h:50
int pe__node_health(pcmk_node_t *node)
Definition: pe_health.c:130
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:503
pcmk_scheduler_t * data_set
Definition: nodes.h:154
#define crm_warn(fmt, args...)
Definition: logging.h:394
#define PCMK_VALUE_RED
Definition: options.h:197
#define crm_debug(fmt, args...)
Definition: logging.h:402
#define crm_trace(fmt, args...)
Definition: logging.h:404
struct pe_node_shared_s * details
Definition: nodes.h:168
int pcmk__add_scores(int score1, int score2)
Definition: scores.c:167
#define PCMK_OPT_NODE_HEALTH_YELLOW
Definition: options.h:52
#define pcmk__assert(expr)
int pcmk__score_green
Definition: scores.c:22
Cluster status and scheduling.
int pcmk__score_red
Definition: scores.c:21
void pe__unpack_node_health_scores(pcmk_scheduler_t *scheduler)
Definition: pe_health.c:24
pcmk_scheduler_t * scheduler
int pcmk__score_yellow
Definition: scores.c:23
pcmk__health_strategy
int pcmk_parse_score(const char *score_s, int *score, int default_score)
Parse an integer score from a string.
Definition: scores.c:39
bool pcmk__starts_with(const char *str, const char *prefix)
Check whether a string starts with a certain sequence.
Definition: strings.c:568
#define PCMK_VALUE_YELLOW
Definition: options.h:221
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
Definition: scores.h:24
int pe__sum_node_health_scores(const pcmk_node_t *node, int base_health)
Definition: pe_health.c:110