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