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