pacemaker  1.1.14-70404b0
Scalable High-Availability cluster resource manager
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", NULL, "0", &check_number, "", NULL },
93  { "is-managed-default", "is_managed_default", "boolean", NULL, "true", &check_boolean,
94  "Should the cluster start/stop resources as required", NULL },
95  { "maintenance-mode", NULL, "boolean", NULL, "false", &check_boolean,
96  "Should the cluster monitor resources and start/stop them as required", NULL },
97  { "start-failure-is-fatal", NULL, "boolean", NULL, "true", &check_boolean, "Always treat start failures as fatal",
98  "This was the old default. However when set to FALSE, the cluster will instead use the resource's failcount and value for resource-failure-stickiness" },
99  { "enable-startup-probes", NULL, "boolean", NULL, "true", &check_boolean,
100  "Should the cluster check for active resources during startup", NULL },
101 
102  /* Stonith Options */
103  { "stonith-enabled", "stonith_enabled", "boolean", NULL, "true", &check_boolean,
104  "Failed nodes are STONITH'd", NULL },
105  { "stonith-action", "stonith_action", "enum", "reboot, poweroff, off", "reboot", &check_stonith_action,
106  "Action to send to STONITH device", NULL },
107  { "stonith-timeout", NULL, "time", NULL, "60s", &check_timer,
108  "How long to wait for the STONITH action (reboot,on,off) to complete", NULL },
109  { XML_ATTR_HAVE_WATCHDOG, NULL, "boolean", NULL, "false", &check_boolean,
110  "Enable watchdog integration", "Set automatically by the cluster if SBD is detected. User configured values are ignored." },
111  { "startup-fencing", "startup_fencing", "boolean", NULL, "true", &check_boolean,
112  "STONITH unseen nodes", "Advanced Use Only! Not using the default is very unsafe!" },
113 
114  /* Timeouts etc */
115  { "cluster-delay", "transition_idle_timeout", "time", NULL, "60s", &check_time,
116  "Round trip delay over the network (excluding action execution)",
117  "The \"correct\" value will depend on the speed and load of your network and cluster nodes." },
118  { "batch-limit", NULL, "integer", NULL, "0", &check_number,
119  "The number of jobs that the TE is allowed to execute in parallel",
120  "The \"correct\" value will depend on the speed and load of your network and cluster nodes." },
121  { "migration-limit", NULL, "integer", NULL, "-1", &check_number,
122  "The number of migration jobs that the TE is allowed to execute in parallel on a node"},
123  { "default-action-timeout", "default_action_timeout", "time", NULL, "20s", &check_time,
124  "How long to wait for actions to complete", NULL },
125 
126  /* Orphans and stopping */
127  { "stop-all-resources", NULL, "boolean", NULL, "false", &check_boolean,
128  "Should the cluster stop all active resources (except those needed for fencing)", NULL },
129  { "stop-orphan-resources", "stop_orphan_resources", "boolean", NULL, "true", &check_boolean,
130  "Should deleted resources be stopped", NULL },
131  { "stop-orphan-actions", "stop_orphan_actions", "boolean", NULL, "true", &check_boolean,
132  "Should deleted actions be cancelled", NULL },
133  { "remove-after-stop", "remove_after_stop", "boolean", NULL, "false", &check_boolean,
134  "Remove resources from the LRM after they are stopped",
135  "Always set this to false. Other values are, at best, poorly tested and potentially dangerous." },
136 /* { "", "", , "0", "", NULL }, */
137 
138  /* Storing inputs */
139  { "pe-error-series-max", NULL, "integer", NULL, "-1", &check_number,
140  "The number of PE inputs resulting in ERRORs to save", "Zero to disable, -1 to store unlimited." },
141  { "pe-warn-series-max", NULL, "integer", NULL, "5000", &check_number,
142  "The number of PE inputs resulting in WARNINGs to save", "Zero to disable, -1 to store unlimited." },
143  { "pe-input-series-max", NULL, "integer", NULL, "4000", &check_number,
144  "The number of other PE inputs to save", "Zero to disable, -1 to store unlimited." },
145 
146  /* Node health */
147  { "node-health-strategy", NULL, "enum", "none, migrate-on-red, only-green, progressive, custom", "none", &check_health,
148  "The strategy combining node attributes to determine overall node health.",
149  "Requires external entities to create node attributes (named with the prefix '#health') with values: 'red', 'yellow' or 'green'."},
150  { "node-health-green", NULL, "integer", NULL, "0", &check_number,
151  "The score 'green' translates to in rsc_location constraints",
152  "Only used when node-health-strategy is set to custom or progressive." },
153  { "node-health-yellow", NULL, "integer", NULL, "0", &check_number,
154  "The score 'yellow' translates to in rsc_location constraints",
155  "Only used when node-health-strategy is set to custom or progressive." },
156  { "node-health-red", NULL, "integer", NULL, "-INFINITY", &check_number,
157  "The score 'red' translates to in rsc_location constraints",
158  "Only used when node-health-strategy is set to custom or progressive." },
159 
160  /*Placement Strategy*/
161  { "placement-strategy", NULL, "enum", "default, utilization, minimal, balanced", "default", &check_placement_strategy,
162  "The strategy to determine resource placement", NULL},
163 };
164 /* *INDENT-ON* */
165 
166 void
168 {
169  config_metadata("Policy Engine", "1.0",
170  "Policy Engine Options",
171  "This is a fake resource that details the options that can be configured for the Policy Engine.",
172  pe_opts, DIMOF(pe_opts));
173 }
174 
175 void
176 verify_pe_options(GHashTable * options)
177 {
178  verify_all_options(options, pe_opts, DIMOF(pe_opts));
179 }
180 
181 const char *
182 pe_pref(GHashTable * options, const char *name)
183 {
184  return get_cluster_pref(options, pe_opts, DIMOF(pe_opts), name);
185 }
186 
187 const char *
189 {
190  const char *result = "<unknown>";
191 
192  switch (fail) {
193  case action_fail_ignore:
194  result = "ignore";
195  break;
196  case action_fail_block:
197  result = "block";
198  break;
199  case action_fail_recover:
200  result = "recover";
201  break;
202  case action_fail_migrate:
203  result = "migrate";
204  break;
205  case action_fail_stop:
206  result = "stop";
207  break;
208  case action_fail_fence:
209  result = "fence";
210  break;
211  case action_fail_standby:
212  result = "standby";
213  break;
215  result = "restart-container";
216  break;
218  result = "reset-remote";
219  break;
220  }
221  return result;
222 }
223 
224 enum action_tasks
225 text2task(const char *task)
226 {
227  if (safe_str_eq(task, CRMD_ACTION_STOP)) {
228  return stop_rsc;
229  } else if (safe_str_eq(task, CRMD_ACTION_STOPPED)) {
230  return stopped_rsc;
231  } else if (safe_str_eq(task, CRMD_ACTION_START)) {
232  return start_rsc;
233  } else if (safe_str_eq(task, CRMD_ACTION_STARTED)) {
234  return started_rsc;
235  } else if (safe_str_eq(task, CRM_OP_SHUTDOWN)) {
236  return shutdown_crm;
237  } else if (safe_str_eq(task, CRM_OP_FENCE)) {
238  return stonith_node;
239  } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
240  return monitor_rsc;
241  } else if (safe_str_eq(task, CRMD_ACTION_NOTIFY)) {
242  return action_notify;
243  } else if (safe_str_eq(task, CRMD_ACTION_NOTIFIED)) {
244  return action_notified;
245  } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) {
246  return action_promote;
247  } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) {
248  return action_demote;
249  } else if (safe_str_eq(task, CRMD_ACTION_PROMOTED)) {
250  return action_promoted;
251  } else if (safe_str_eq(task, CRMD_ACTION_DEMOTED)) {
252  return action_demoted;
253  }
254 #if SUPPORT_TRACING
255  if (safe_str_eq(task, CRMD_ACTION_CANCEL)) {
256  return no_action;
257  } else if (safe_str_eq(task, CRMD_ACTION_DELETE)) {
258  return no_action;
259  } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
260  return no_action;
261  } else if (safe_str_eq(task, CRM_OP_PROBED)) {
262  return no_action;
263  } else if (safe_str_eq(task, CRM_OP_LRM_REFRESH)) {
264  return no_action;
265  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE)) {
266  return no_action;
267  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) {
268  return no_action;
269  } else if (safe_str_eq(task, "fail")) {
270  return no_action;
271  } else if (safe_str_eq(task, "stonith_up")) {
272  return no_action;
273  } else if (safe_str_eq(task, "stonith_complete")) {
274  return no_action;
275  } else if (safe_str_eq(task, "all_stopped")) {
276  return no_action;
277  }
278  crm_trace("Unsupported action: %s", task);
279 #endif
280 
281  return no_action;
282 }
283 
284 const char *
286 {
287  const char *result = "<unknown>";
288 
289  switch (task) {
290  case no_action:
291  result = "no_action";
292  break;
293  case stop_rsc:
294  result = CRMD_ACTION_STOP;
295  break;
296  case stopped_rsc:
297  result = CRMD_ACTION_STOPPED;
298  break;
299  case start_rsc:
300  result = CRMD_ACTION_START;
301  break;
302  case started_rsc:
303  result = CRMD_ACTION_STARTED;
304  break;
305  case shutdown_crm:
306  result = CRM_OP_SHUTDOWN;
307  break;
308  case stonith_node:
309  result = CRM_OP_FENCE;
310  break;
311  case monitor_rsc:
312  result = CRMD_ACTION_STATUS;
313  break;
314  case action_notify:
315  result = CRMD_ACTION_NOTIFY;
316  break;
317  case action_notified:
318  result = CRMD_ACTION_NOTIFIED;
319  break;
320  case action_promote:
321  result = CRMD_ACTION_PROMOTE;
322  break;
323  case action_promoted:
324  result = CRMD_ACTION_PROMOTED;
325  break;
326  case action_demote:
327  result = CRMD_ACTION_DEMOTE;
328  break;
329  case action_demoted:
330  result = CRMD_ACTION_DEMOTED;
331  break;
332  }
333 
334  return result;
335 }
336 
337 const char *
339 {
340  switch (role) {
341  case RSC_ROLE_UNKNOWN:
342  return RSC_ROLE_UNKNOWN_S;
343  case RSC_ROLE_STOPPED:
344  return RSC_ROLE_STOPPED_S;
345  case RSC_ROLE_STARTED:
346  return RSC_ROLE_STARTED_S;
347  case RSC_ROLE_SLAVE:
348  return RSC_ROLE_SLAVE_S;
349  case RSC_ROLE_MASTER:
350  return RSC_ROLE_MASTER_S;
351  }
353  CRM_CHECK(role < RSC_ROLE_MAX, return RSC_ROLE_UNKNOWN_S);
354  return RSC_ROLE_UNKNOWN_S;
355 }
356 
357 enum rsc_role_e
358 text2role(const char *role)
359 {
360  CRM_ASSERT(role != NULL);
361  if (safe_str_eq(role, RSC_ROLE_STOPPED_S)) {
362  return RSC_ROLE_STOPPED;
363  } else if (safe_str_eq(role, RSC_ROLE_STARTED_S)) {
364  return RSC_ROLE_STARTED;
365  } else if (safe_str_eq(role, RSC_ROLE_SLAVE_S)) {
366  return RSC_ROLE_SLAVE;
367  } else if (safe_str_eq(role, RSC_ROLE_MASTER_S)) {
368  return RSC_ROLE_MASTER;
369  } else if (safe_str_eq(role, RSC_ROLE_UNKNOWN_S)) {
370  return RSC_ROLE_UNKNOWN;
371  }
372  crm_err("Unknown role: %s", role);
373  return RSC_ROLE_UNKNOWN;
374 }
375 
376 int
377 merge_weights(int w1, int w2)
378 {
379  int result = w1 + w2;
380 
381  if (w1 <= -INFINITY || w2 <= -INFINITY) {
382  if (w1 >= INFINITY || w2 >= INFINITY) {
383  crm_trace("-INFINITY + INFINITY == -INFINITY");
384  }
385  return -INFINITY;
386 
387  } else if (w1 >= INFINITY || w2 >= INFINITY) {
388  return INFINITY;
389  }
390 
391  /* detect wrap-around */
392  if (result > 0) {
393  if (w1 <= 0 && w2 < 0) {
394  result = -INFINITY;
395  }
396 
397  } else if (w1 > 0 && w2 > 0) {
398  result = INFINITY;
399  }
400 
401  /* detect +/- INFINITY */
402  if (result >= INFINITY) {
403  result = INFINITY;
404 
405  } else if (result <= -INFINITY) {
406  result = -INFINITY;
407  }
408 
409  crm_trace("%d + %d = %d", w1, w2, result);
410  return result;
411 }
412 
413 void
414 add_hash_param(GHashTable * hash, const char *name, const char *value)
415 {
416  CRM_CHECK(hash != NULL, return);
417 
418  crm_trace("adding: name=%s value=%s", crm_str(name), crm_str(value));
419  if (name == NULL || value == NULL) {
420  return;
421 
422  } else if (safe_str_eq(value, "#default")) {
423  return;
424 
425  } else if (g_hash_table_lookup(hash, name) == NULL) {
426  g_hash_table_insert(hash, strdup(name), strdup(value));
427  }
428 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:164
void add_hash_param(GHashTable *hash, const char *name, const char *value)
Definition: common.c:414
A dumping ground.
#define CRMD_ACTION_MIGRATED
Definition: crm.h:148
#define INFINITY
Definition: crm.h:77
int merge_weights(int w1, int w2)
Definition: common.c:377
#define CRM_OP_FENCE
Definition: crm.h:114
void pe_metadata(void)
Definition: common.c:167
#define RSC_ROLE_STARTED_S
Definition: common.h:93
#define CRMD_ACTION_NOTIFY
Definition: crm.h:161
#define CRMD_ACTION_PROMOTE
Definition: crm.h:156
const char * task2text(enum action_tasks task)
Definition: common.c:285
gboolean check_number(const char *value)
Definition: utils.c:144
action_fail_response
Definition: common.h:29
gboolean was_processing_error
Definition: common.c:28
gboolean was_processing_warning
Definition: common.c:29
#define CRMD_ACTION_START
Definition: crm.h:150
enum rsc_role_e text2role(const char *role)
Definition: common.c:358
#define CRM_OP_LRM_REFRESH
Definition: crm.h:127
#define CRMD_ACTION_DEMOTED
Definition: crm.h:159
#define CRMD_ACTION_STOP
Definition: crm.h:153
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:355
#define CRMD_ACTION_DEMOTE
Definition: crm.h:158
const char * role2text(enum rsc_role_e role)
Definition: common.c:338
Utility functions.
gboolean check_quorum(const char *value)
Definition: utils.c:165
#define crm_trace(fmt, args...)
Definition: logging.h:254
Wrappers for and extensions to libxml2.
gboolean check_time(const char *value)
Definition: utils.c:115
#define RSC_ROLE_MASTER_S
Definition: common.h:95
#define CRMD_ACTION_PROMOTED
Definition: crm.h:157
gboolean check_boolean(const char *value)
Definition: utils.c:133
void verify_pe_options(GHashTable *options)
Definition: common.c:176
#define CRM_OP_SHUTDOWN
Definition: crm.h:113
const char * pe_pref(GHashTable *options, const char *name)
Definition: common.c:182
#define CRMD_ACTION_STOPPED
Definition: crm.h:154
#define crm_err(fmt, args...)
Definition: logging.h:248
#define XML_ATTR_HAVE_WATCHDOG
Definition: msg_xml.h:89
#define RSC_ROLE_SLAVE_S
Definition: common.h:94
#define DIMOF(a)
Definition: crm.h:41
#define CRMD_ACTION_MIGRATE
Definition: crm.h:147
#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:390
rsc_role_e
Definition: common.h:81
#define CRM_OP_PROBED
Definition: crm.h:131
enum action_tasks text2task(const char *task)
Definition: common.c:225
#define RSC_ROLE_UNKNOWN_S
Definition: common.h:91
#define RSC_ROLE_MAX
Definition: common.h:89
gboolean check_timer(const char *value)
Definition: utils.c:124
#define CRMD_ACTION_NOTIFIED
Definition: crm.h:162
#define safe_str_eq(a, b)
Definition: util.h:74
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:335
const char * fail2text(enum action_fail_response fail)
Definition: common.c:188
#define CRMD_ACTION_STARTED
Definition: crm.h:151
#define CRMD_ACTION_CANCEL
Definition: crm.h:145
action_tasks
Definition: common.h:52
#define CRMD_ACTION_DELETE
Definition: crm.h:144
#define CRMD_ACTION_STATUS
Definition: crm.h:164