pacemaker  2.0.2-debe490
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
common.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2018 Andrew Beekhof <andrew@beekhof.net>
3  *
4  * This source code is licensed under the GNU Lesser General Public License
5  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
6  */
7 
8 #include <crm_internal.h>
9 #include <crm/crm.h>
10 #include <crm/msg_xml.h>
11 #include <crm/common/xml.h>
12 #include <crm/common/util.h>
13 
14 #include <glib.h>
15 
16 #include <crm/pengine/internal.h>
17 
18 gboolean was_processing_error = FALSE;
19 gboolean was_processing_warning = FALSE;
20 
21 static gboolean
22 check_health(const char *value)
23 {
24  if (safe_str_eq(value, "none")) {
25  return TRUE;
26 
27  } else if (safe_str_eq(value, "custom")) {
28  return TRUE;
29 
30  } else if (safe_str_eq(value, "only-green")) {
31  return TRUE;
32 
33  } else if (safe_str_eq(value, "progressive")) {
34  return TRUE;
35 
36  } else if (safe_str_eq(value, "migrate-on-red")) {
37  return TRUE;
38  }
39  return FALSE;
40 }
41 
42 static gboolean
43 check_stonith_action(const char *value)
44 {
45  if (safe_str_eq(value, "reboot")) {
46  return TRUE;
47 
48  } else if (safe_str_eq(value, "poweroff")) {
49  return TRUE;
50 
51  } else if (safe_str_eq(value, "off")) {
52  return TRUE;
53  }
54  return FALSE;
55 }
56 
57 static gboolean
58 check_placement_strategy(const char *value)
59 {
60  if (safe_str_eq(value, "default")) {
61  return TRUE;
62 
63  } else if (safe_str_eq(value, "utilization")) {
64  return TRUE;
65 
66  } else if (safe_str_eq(value, "minimal")) {
67  return TRUE;
68 
69  } else if (safe_str_eq(value, "balanced")) {
70  return TRUE;
71  }
72  return FALSE;
73 }
74 
75 /* *INDENT-OFF* */
76 static pe_cluster_option pe_opts[] = {
77  /* name, old-name, validate, default, description */
78  { "no-quorum-policy", NULL, "enum", "stop, freeze, ignore, suicide", "stop", &check_quorum,
79  "What to do when the cluster does not have quorum", NULL },
80  { "symmetric-cluster", NULL, "boolean", NULL, "true", &check_boolean,
81  "All resources can run anywhere by default", NULL },
82  { "maintenance-mode", NULL, "boolean", NULL, "false", &check_boolean,
83  "Should the cluster monitor resources and start/stop them as required", NULL },
84  { "start-failure-is-fatal", NULL, "boolean", NULL, "true", &check_boolean, "Always treat start failures as fatal",
85  "When set to TRUE, the cluster will immediately ban a resource from a node if it fails to start there. When FALSE, the cluster will instead check the resource's fail count against its migration-threshold." },
86  { "enable-startup-probes", NULL, "boolean", NULL, "true", &check_boolean,
87  "Should the cluster check for active resources during startup", NULL },
88 
89  /* Stonith Options */
90  { "stonith-enabled", NULL, "boolean", NULL, "true", &check_boolean,
91  "Failed nodes are STONITH'd", NULL },
92  { "stonith-action", NULL, "enum", "reboot, off, poweroff", "reboot", &check_stonith_action,
93  "Action to send to STONITH device ('poweroff' is a deprecated alias for 'off')", NULL },
94  { "stonith-timeout", NULL, "time", NULL, "60s", &check_timer,
95  "How long to wait for the STONITH action (reboot,on,off) to complete", NULL },
96  { XML_ATTR_HAVE_WATCHDOG, NULL, "boolean", NULL, "false", &check_boolean,
97  "Enable watchdog integration", "Set automatically by the cluster if SBD is detected. User configured values are ignored." },
98  { "concurrent-fencing", NULL, "boolean", NULL, "false", &check_boolean,
99  "Allow performing fencing operations in parallel", NULL },
100  { "startup-fencing", NULL, "boolean", NULL, "true", &check_boolean,
101  "STONITH unseen nodes", "Advanced Use Only! Not using the default is very unsafe!" },
102 
103  /* Timeouts etc */
104  { "cluster-delay", NULL, "time", NULL, "60s", &check_time,
105  "Round trip delay over the network (excluding action execution)",
106  "The \"correct\" value will depend on the speed and load of your network and cluster nodes." },
107  { "batch-limit", NULL, "integer", NULL, "0", &check_number,
108  "The number of jobs that the TE is allowed to execute in parallel",
109  "The \"correct\" value will depend on the speed and load of your network and cluster nodes." },
110  { "migration-limit", NULL, "integer", NULL, "-1", &check_number,
111  "The number of migration jobs that the TE is allowed to execute in parallel on a node"},
112 
113  /* Orphans and stopping */
114  { "stop-all-resources", NULL, "boolean", NULL, "false", &check_boolean,
115  "Should the cluster stop all active resources (except those needed for fencing)", NULL },
116  { "stop-orphan-resources", NULL, "boolean", NULL, "true", &check_boolean,
117  "Should deleted resources be stopped", NULL },
118  { "stop-orphan-actions", NULL, "boolean", NULL, "true", &check_boolean,
119  "Should deleted actions be cancelled", NULL },
120  { "remove-after-stop", NULL, "boolean", NULL, "false", &check_boolean,
121  "Remove resources from the executor after they are stopped",
122  "Always set this to false. Other values are, at best, poorly tested and potentially dangerous." },
123 /* { "", "", , "0", "", NULL }, */
124 
125  /* Storing inputs */
126  {
127  "pe-error-series-max", NULL, "integer", NULL, "-1", &check_number,
128  "The number of scheduler inputs resulting in ERRORs to save",
129  "Zero to disable, -1 to store unlimited"
130  },
131  {
132  "pe-warn-series-max", NULL, "integer", NULL, "5000", &check_number,
133  "The number of scheduler inputs resulting in WARNINGs to save",
134  "Zero to disable, -1 to store unlimited"
135  },
136  {
137  "pe-input-series-max", NULL, "integer", NULL, "4000", &check_number,
138  "The number of other scheduler inputs to save",
139  "Zero to disable, -1 to store unlimited"
140  },
141 
142  /* Node health */
143  { "node-health-strategy", NULL, "enum", "none, migrate-on-red, only-green, progressive, custom", "none", &check_health,
144  "The strategy combining node attributes to determine overall node health.",
145  "Requires external entities to create node attributes (named with the prefix '#health') with values: 'red', 'yellow' or 'green'."},
146  { "node-health-base", NULL, "integer", NULL, "0", &check_number,
147  "The base score assigned to a node",
148  "Only used when node-health-strategy is set to progressive." },
149  { "node-health-green", NULL, "integer", NULL, "0", &check_number,
150  "The score 'green' translates to in rsc_location constraints",
151  "Only used when node-health-strategy is set to custom or progressive." },
152  { "node-health-yellow", NULL, "integer", NULL, "0", &check_number,
153  "The score 'yellow' translates to in rsc_location constraints",
154  "Only used when node-health-strategy is set to custom or progressive." },
155  { "node-health-red", NULL, "integer", NULL, "-INFINITY", &check_number,
156  "The score 'red' translates to in rsc_location constraints",
157  "Only used when node-health-strategy is set to custom or progressive." },
158 
159  /*Placement Strategy*/
160  { "placement-strategy", NULL, "enum", "default, utilization, minimal, balanced", "default", &check_placement_strategy,
161  "The strategy to determine resource placement", NULL},
162 };
163 /* *INDENT-ON* */
164 
165 void
167 {
168  config_metadata("pacemaker-schedulerd", "1.0", "scheduler properties",
169  "Cluster properties used by Pacemaker's scheduler,"
170  " formerly known as pengine",
171  pe_opts, DIMOF(pe_opts));
172 }
173 
174 void
175 verify_pe_options(GHashTable * options)
176 {
177  verify_all_options(options, pe_opts, DIMOF(pe_opts));
178 }
179 
180 const char *
181 pe_pref(GHashTable * options, const char *name)
182 {
183  return get_cluster_pref(options, pe_opts, DIMOF(pe_opts), name);
184 }
185 
186 const char *
188 {
189  const char *result = "<unknown>";
190 
191  switch (fail) {
192  case action_fail_ignore:
193  result = "ignore";
194  break;
195  case action_fail_block:
196  result = "block";
197  break;
198  case action_fail_recover:
199  result = "recover";
200  break;
201  case action_fail_migrate:
202  result = "migrate";
203  break;
204  case action_fail_stop:
205  result = "stop";
206  break;
207  case action_fail_fence:
208  result = "fence";
209  break;
210  case action_fail_standby:
211  result = "standby";
212  break;
214  result = "restart-container";
215  break;
217  result = "reset-remote";
218  break;
219  }
220  return result;
221 }
222 
223 enum action_tasks
224 text2task(const char *task)
225 {
226  if (safe_str_eq(task, CRMD_ACTION_STOP)) {
227  return stop_rsc;
228  } else if (safe_str_eq(task, CRMD_ACTION_STOPPED)) {
229  return stopped_rsc;
230  } else if (safe_str_eq(task, CRMD_ACTION_START)) {
231  return start_rsc;
232  } else if (safe_str_eq(task, CRMD_ACTION_STARTED)) {
233  return started_rsc;
234  } else if (safe_str_eq(task, CRM_OP_SHUTDOWN)) {
235  return shutdown_crm;
236  } else if (safe_str_eq(task, CRM_OP_FENCE)) {
237  return stonith_node;
238  } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
239  return monitor_rsc;
240  } else if (safe_str_eq(task, CRMD_ACTION_NOTIFY)) {
241  return action_notify;
242  } else if (safe_str_eq(task, CRMD_ACTION_NOTIFIED)) {
243  return action_notified;
244  } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) {
245  return action_promote;
246  } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) {
247  return action_demote;
248  } else if (safe_str_eq(task, CRMD_ACTION_PROMOTED)) {
249  return action_promoted;
250  } else if (safe_str_eq(task, CRMD_ACTION_DEMOTED)) {
251  return action_demoted;
252  }
253 #if SUPPORT_TRACING
254  if (safe_str_eq(task, CRMD_ACTION_CANCEL)) {
255  return no_action;
256  } else if (safe_str_eq(task, CRMD_ACTION_DELETE)) {
257  return no_action;
258  } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
259  return no_action;
260  } else if (safe_str_eq(task, CRM_OP_PROBED)) {
261  return no_action;
262  } else if (safe_str_eq(task, CRM_OP_LRM_REFRESH)) {
263  return no_action;
264  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE)) {
265  return no_action;
266  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) {
267  return no_action;
268  }
269  crm_trace("Unsupported action: %s", task);
270 #endif
271 
272  return no_action;
273 }
274 
275 const char *
277 {
278  const char *result = "<unknown>";
279 
280  switch (task) {
281  case no_action:
282  result = "no_action";
283  break;
284  case stop_rsc:
285  result = CRMD_ACTION_STOP;
286  break;
287  case stopped_rsc:
288  result = CRMD_ACTION_STOPPED;
289  break;
290  case start_rsc:
291  result = CRMD_ACTION_START;
292  break;
293  case started_rsc:
294  result = CRMD_ACTION_STARTED;
295  break;
296  case shutdown_crm:
297  result = CRM_OP_SHUTDOWN;
298  break;
299  case stonith_node:
300  result = CRM_OP_FENCE;
301  break;
302  case monitor_rsc:
303  result = CRMD_ACTION_STATUS;
304  break;
305  case action_notify:
306  result = CRMD_ACTION_NOTIFY;
307  break;
308  case action_notified:
309  result = CRMD_ACTION_NOTIFIED;
310  break;
311  case action_promote:
312  result = CRMD_ACTION_PROMOTE;
313  break;
314  case action_promoted:
315  result = CRMD_ACTION_PROMOTED;
316  break;
317  case action_demote:
318  result = CRMD_ACTION_DEMOTE;
319  break;
320  case action_demoted:
321  result = CRMD_ACTION_DEMOTED;
322  break;
323  }
324 
325  return result;
326 }
327 
328 const char *
330 {
331  switch (role) {
332  case RSC_ROLE_UNKNOWN:
333  return RSC_ROLE_UNKNOWN_S;
334  case RSC_ROLE_STOPPED:
335  return RSC_ROLE_STOPPED_S;
336  case RSC_ROLE_STARTED:
337  return RSC_ROLE_STARTED_S;
338  case RSC_ROLE_SLAVE:
339  return RSC_ROLE_SLAVE_S;
340  case RSC_ROLE_MASTER:
341  return RSC_ROLE_MASTER_S;
342  }
344  CRM_CHECK(role < RSC_ROLE_MAX, return RSC_ROLE_UNKNOWN_S);
345  // coverity[dead_error_line]
346  return RSC_ROLE_UNKNOWN_S;
347 }
348 
349 enum rsc_role_e
350 text2role(const char *role)
351 {
352  CRM_ASSERT(role != NULL);
353  if (safe_str_eq(role, RSC_ROLE_STOPPED_S)) {
354  return RSC_ROLE_STOPPED;
355  } else if (safe_str_eq(role, RSC_ROLE_STARTED_S)) {
356  return RSC_ROLE_STARTED;
357  } else if (safe_str_eq(role, RSC_ROLE_SLAVE_S)) {
358  return RSC_ROLE_SLAVE;
359  } else if (safe_str_eq(role, RSC_ROLE_MASTER_S)) {
360  return RSC_ROLE_MASTER;
361  } else if (safe_str_eq(role, RSC_ROLE_UNKNOWN_S)) {
362  return RSC_ROLE_UNKNOWN;
363  }
364  crm_err("Unknown role: %s", role);
365  return RSC_ROLE_UNKNOWN;
366 }
367 
368 int
369 merge_weights(int w1, int w2)
370 {
371  int result = w1 + w2;
372 
373  if (w1 <= -INFINITY || w2 <= -INFINITY) {
374  if (w1 >= INFINITY || w2 >= INFINITY) {
375  crm_trace("-INFINITY + INFINITY == -INFINITY");
376  }
377  return -INFINITY;
378 
379  } else if (w1 >= INFINITY || w2 >= INFINITY) {
380  return INFINITY;
381  }
382 
383  /* detect wrap-around */
384  if (result > 0) {
385  if (w1 <= 0 && w2 < 0) {
386  result = -INFINITY;
387  }
388 
389  } else if (w1 > 0 && w2 > 0) {
390  result = INFINITY;
391  }
392 
393  /* detect +/- INFINITY */
394  if (result >= INFINITY) {
395  result = INFINITY;
396 
397  } else if (result <= -INFINITY) {
398  result = -INFINITY;
399  }
400 
401  crm_trace("%d + %d = %d", w1, w2, result);
402  return result;
403 }
404 
405 void
406 add_hash_param(GHashTable * hash, const char *name, const char *value)
407 {
408  CRM_CHECK(hash != NULL, return);
409 
410  crm_trace("adding: name=%s value=%s", crm_str(name), crm_str(value));
411  if (name == NULL || value == NULL) {
412  return;
413 
414  } else if (safe_str_eq(value, "#default")) {
415  return;
416 
417  } else if (g_hash_table_lookup(hash, name) == NULL) {
418  g_hash_table_insert(hash, strdup(name), strdup(value));
419  }
420 }
421 
422 const char *
423 pe_node_attribute_calculated(const pe_node_t *node, const char *name,
424  const resource_t *rsc)
425 {
426  const char *source;
427 
428  if(node == NULL) {
429  return NULL;
430 
431  } else if(rsc == NULL) {
432  return g_hash_table_lookup(node->details->attrs, name);
433  }
434 
435  source = g_hash_table_lookup(rsc->meta, XML_RSC_ATTR_TARGET);
436  if(source == NULL || safe_str_eq("host", source) == FALSE) {
437  return g_hash_table_lookup(node->details->attrs, name);
438  }
439 
440  /* Use attributes set for the containers location
441  * instead of for the container itself
442  *
443  * Useful when the container is using the host's local
444  * storage
445  */
446 
447  CRM_ASSERT(node->details->remote_rsc);
449 
450  if(node->details->remote_rsc->container->running_on) {
452  pe_rsc_trace(rsc, "%s: Looking for %s on the container host %s", rsc->id, name, host->details->uname);
453  return g_hash_table_lookup(host->details->attrs, name);
454  }
455 
456  pe_rsc_trace(rsc, "%s: Not looking for %s on the container host: %s is inactive",
457  rsc->id, name, node->details->remote_rsc->container->id);
458  return NULL;
459 }
460 
461 const char *
462 pe_node_attribute_raw(pe_node_t *node, const char *name)
463 {
464  if(node == NULL) {
465  return NULL;
466  }
467  return g_hash_table_lookup(node->details->attrs, name);
468 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:156
void verify_pe_options(GHashTable *options)
Definition: common.c:175
const char * task2text(enum action_tasks task)
Definition: common.c:276
A dumping ground.
#define CRMD_ACTION_MIGRATED
Definition: crm.h:147
GHashTable * attrs
Definition: pe_types.h:204
#define INFINITY
Definition: crm.h:73
#define CRM_OP_FENCE
Definition: crm.h:119
void pe_metadata(void)
Definition: common.c:166
pe_resource_t * container
Definition: pe_types.h:343
#define RSC_ROLE_STARTED_S
Definition: common.h:98
pe_resource_t * remote_rsc
Definition: pe_types.h:200
#define CRMD_ACTION_NOTIFY
Definition: crm.h:160
GHashTable * meta
Definition: pe_types.h:336
#define CRMD_ACTION_PROMOTE
Definition: crm.h:155
AIS_Host host
Definition: internal.h:86
enum action_tasks text2task(const char *task)
Definition: common.c:224
const char * pe_pref(GHashTable *options, const char *name)
Definition: common.c:181
gboolean check_number(const char *value)
Definition: utils.c:102
#define XML_RSC_ATTR_TARGET
Definition: msg_xml.h:182
action_fail_response
Definition: common.h:36
#define CRMD_ACTION_START
Definition: crm.h:149
#define CRM_OP_LRM_REFRESH
Definition: crm.h:123
const char * role2text(enum rsc_role_e role)
Definition: common.c:329
#define CRMD_ACTION_DEMOTED
Definition: crm.h:158
#define CRMD_ACTION_STOP
Definition: crm.h:152
void config_metadata(const char *name, const char *version, const char *desc_short, const char *desc_long, pe_cluster_option *option_list, int len)
Definition: utils.c:344
#define CRMD_ACTION_DEMOTE
Definition: crm.h:157
Utility functions.
gboolean check_quorum(const char *value)
Definition: utils.c:132
#define crm_trace(fmt, args...)
Definition: logging.h:246
struct pe_node_shared_s * details
Definition: pe_types.h:213
GListPtr running_on
Definition: pe_types.h:329
const char * uname
Definition: pe_types.h:179
Wrappers for and extensions to libxml2.
const char * pe_node_attribute_raw(pe_node_t *node, const char *name)
Definition: common.c:462
gboolean check_time(const char *value)
Definition: utils.c:73
#define RSC_ROLE_MASTER_S
Definition: common.h:100
#define CRMD_ACTION_PROMOTED
Definition: crm.h:156
gboolean check_boolean(const char *value)
Definition: utils.c:91
enum rsc_role_e text2role(const char *role)
Definition: common.c:350
#define CRM_OP_SHUTDOWN
Definition: crm.h:118
#define CRMD_ACTION_STOPPED
Definition: crm.h:153
const char * fail2text(enum action_fail_response fail)
Definition: common.c:187
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:406
#define crm_err(fmt, args...)
Definition: logging.h:240
#define CRM_ASSERT(expr)
Definition: results.h:42
#define XML_ATTR_HAVE_WATCHDOG
Definition: msg_xml.h:86
#define RSC_ROLE_SLAVE_S
Definition: common.h:99
#define DIMOF(a)
Definition: crm.h:35
int merge_weights(int w1, int w2)
Definition: common.c:369
#define CRMD_ACTION_MIGRATE
Definition: crm.h:146
#define RSC_ROLE_STOPPED_S
Definition: common.h:97
#define crm_str(x)
Definition: logging.h:266
void verify_all_options(GHashTable *options, pe_cluster_option *option_list, int len)
Definition: utils.c:379
rsc_role_e
Definition: common.h:86
#define CRM_OP_PROBED
Definition: crm.h:127
#define RSC_ROLE_UNKNOWN_S
Definition: common.h:96
#define RSC_ROLE_MAX
Definition: common.h:94
gboolean check_timer(const char *value)
Definition: utils.c:82
#define CRMD_ACTION_NOTIFIED
Definition: crm.h:161
#define pe_rsc_trace(rsc, fmt, args...)
Definition: internal.h:18
gboolean was_processing_error
Definition: common.c:18
#define safe_str_eq(a, b)
Definition: util.h:59
const char * get_cluster_pref(GHashTable *options, pe_cluster_option *option_list, int len, const char *name)
Definition: utils.c:325
gboolean was_processing_warning
Definition: common.c:19
#define CRMD_ACTION_STARTED
Definition: crm.h:150
#define CRMD_ACTION_CANCEL
Definition: crm.h:143
action_tasks
Definition: common.h:57
#define CRMD_ACTION_DELETE
Definition: crm.h:142
char * id
Definition: pe_types.h:284
#define CRMD_ACTION_STATUS
Definition: crm.h:163
const char * pe_node_attribute_calculated(const pe_node_t *node, const char *name, const resource_t *rsc)
Definition: common.c:423