pacemaker  1.1.16-94ff4df
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-base", NULL, "integer", NULL, "0", &check_number,
153  "The base score assigned to a node",
154  "Only used when node-health-strategy is set to progressive." },
155  { "node-health-green", NULL, "integer", NULL, "0", &check_number,
156  "The score 'green' translates to in rsc_location constraints",
157  "Only used when node-health-strategy is set to custom or progressive." },
158  { "node-health-yellow", NULL, "integer", NULL, "0", &check_number,
159  "The score 'yellow' translates to in rsc_location constraints",
160  "Only used when node-health-strategy is set to custom or progressive." },
161  { "node-health-red", NULL, "integer", NULL, "-INFINITY", &check_number,
162  "The score 'red' translates to in rsc_location constraints",
163  "Only used when node-health-strategy is set to custom or progressive." },
164 
165  /*Placement Strategy*/
166  { "placement-strategy", NULL, "enum", "default, utilization, minimal, balanced", "default", &check_placement_strategy,
167  "The strategy to determine resource placement", NULL},
168 };
169 /* *INDENT-ON* */
170 
171 void
173 {
174  config_metadata("Policy Engine", "1.0",
175  "Policy Engine Options",
176  "This is a fake resource that details the options that can be configured for the Policy Engine.",
177  pe_opts, DIMOF(pe_opts));
178 }
179 
180 void
181 verify_pe_options(GHashTable * options)
182 {
183  verify_all_options(options, pe_opts, DIMOF(pe_opts));
184 }
185 
186 const char *
187 pe_pref(GHashTable * options, const char *name)
188 {
189  return get_cluster_pref(options, pe_opts, DIMOF(pe_opts), name);
190 }
191 
192 const char *
194 {
195  const char *result = "<unknown>";
196 
197  switch (fail) {
198  case action_fail_ignore:
199  result = "ignore";
200  break;
201  case action_fail_block:
202  result = "block";
203  break;
204  case action_fail_recover:
205  result = "recover";
206  break;
207  case action_fail_migrate:
208  result = "migrate";
209  break;
210  case action_fail_stop:
211  result = "stop";
212  break;
213  case action_fail_fence:
214  result = "fence";
215  break;
216  case action_fail_standby:
217  result = "standby";
218  break;
220  result = "restart-container";
221  break;
223  result = "reset-remote";
224  break;
225  }
226  return result;
227 }
228 
229 enum action_tasks
230 text2task(const char *task)
231 {
232  if (safe_str_eq(task, CRMD_ACTION_STOP)) {
233  return stop_rsc;
234  } else if (safe_str_eq(task, CRMD_ACTION_STOPPED)) {
235  return stopped_rsc;
236  } else if (safe_str_eq(task, CRMD_ACTION_START)) {
237  return start_rsc;
238  } else if (safe_str_eq(task, CRMD_ACTION_STARTED)) {
239  return started_rsc;
240  } else if (safe_str_eq(task, CRM_OP_SHUTDOWN)) {
241  return shutdown_crm;
242  } else if (safe_str_eq(task, CRM_OP_FENCE)) {
243  return stonith_node;
244  } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
245  return monitor_rsc;
246  } else if (safe_str_eq(task, CRMD_ACTION_NOTIFY)) {
247  return action_notify;
248  } else if (safe_str_eq(task, CRMD_ACTION_NOTIFIED)) {
249  return action_notified;
250  } else if (safe_str_eq(task, CRMD_ACTION_PROMOTE)) {
251  return action_promote;
252  } else if (safe_str_eq(task, CRMD_ACTION_DEMOTE)) {
253  return action_demote;
254  } else if (safe_str_eq(task, CRMD_ACTION_PROMOTED)) {
255  return action_promoted;
256  } else if (safe_str_eq(task, CRMD_ACTION_DEMOTED)) {
257  return action_demoted;
258  }
259 #if SUPPORT_TRACING
260  if (safe_str_eq(task, CRMD_ACTION_CANCEL)) {
261  return no_action;
262  } else if (safe_str_eq(task, CRMD_ACTION_DELETE)) {
263  return no_action;
264  } else if (safe_str_eq(task, CRMD_ACTION_STATUS)) {
265  return no_action;
266  } else if (safe_str_eq(task, CRM_OP_PROBED)) {
267  return no_action;
268  } else if (safe_str_eq(task, CRM_OP_LRM_REFRESH)) {
269  return no_action;
270  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATE)) {
271  return no_action;
272  } else if (safe_str_eq(task, CRMD_ACTION_MIGRATED)) {
273  return no_action;
274  } else if (safe_str_eq(task, "fail")) {
275  return no_action;
276  } else if (safe_str_eq(task, "stonith_up")) {
277  return no_action;
278  } else if (safe_str_eq(task, "stonith_complete")) {
279  return no_action;
280  } else if (safe_str_eq(task, "all_stopped")) {
281  return no_action;
282  }
283  crm_trace("Unsupported action: %s", task);
284 #endif
285 
286  return no_action;
287 }
288 
289 const char *
291 {
292  const char *result = "<unknown>";
293 
294  switch (task) {
295  case no_action:
296  result = "no_action";
297  break;
298  case stop_rsc:
299  result = CRMD_ACTION_STOP;
300  break;
301  case stopped_rsc:
302  result = CRMD_ACTION_STOPPED;
303  break;
304  case start_rsc:
305  result = CRMD_ACTION_START;
306  break;
307  case started_rsc:
308  result = CRMD_ACTION_STARTED;
309  break;
310  case shutdown_crm:
311  result = CRM_OP_SHUTDOWN;
312  break;
313  case stonith_node:
314  result = CRM_OP_FENCE;
315  break;
316  case monitor_rsc:
317  result = CRMD_ACTION_STATUS;
318  break;
319  case action_notify:
320  result = CRMD_ACTION_NOTIFY;
321  break;
322  case action_notified:
323  result = CRMD_ACTION_NOTIFIED;
324  break;
325  case action_promote:
326  result = CRMD_ACTION_PROMOTE;
327  break;
328  case action_promoted:
329  result = CRMD_ACTION_PROMOTED;
330  break;
331  case action_demote:
332  result = CRMD_ACTION_DEMOTE;
333  break;
334  case action_demoted:
335  result = CRMD_ACTION_DEMOTED;
336  break;
337  }
338 
339  return result;
340 }
341 
342 const char *
344 {
345  switch (role) {
346  case RSC_ROLE_UNKNOWN:
347  return RSC_ROLE_UNKNOWN_S;
348  case RSC_ROLE_STOPPED:
349  return RSC_ROLE_STOPPED_S;
350  case RSC_ROLE_STARTED:
351  return RSC_ROLE_STARTED_S;
352  case RSC_ROLE_SLAVE:
353  return RSC_ROLE_SLAVE_S;
354  case RSC_ROLE_MASTER:
355  return RSC_ROLE_MASTER_S;
356  }
358  CRM_CHECK(role < RSC_ROLE_MAX, return RSC_ROLE_UNKNOWN_S);
359  return RSC_ROLE_UNKNOWN_S;
360 }
361 
362 enum rsc_role_e
363 text2role(const char *role)
364 {
365  CRM_ASSERT(role != NULL);
366  if (safe_str_eq(role, RSC_ROLE_STOPPED_S)) {
367  return RSC_ROLE_STOPPED;
368  } else if (safe_str_eq(role, RSC_ROLE_STARTED_S)) {
369  return RSC_ROLE_STARTED;
370  } else if (safe_str_eq(role, RSC_ROLE_SLAVE_S)) {
371  return RSC_ROLE_SLAVE;
372  } else if (safe_str_eq(role, RSC_ROLE_MASTER_S)) {
373  return RSC_ROLE_MASTER;
374  } else if (safe_str_eq(role, RSC_ROLE_UNKNOWN_S)) {
375  return RSC_ROLE_UNKNOWN;
376  }
377  crm_err("Unknown role: %s", role);
378  return RSC_ROLE_UNKNOWN;
379 }
380 
381 int
382 merge_weights(int w1, int w2)
383 {
384  int result = w1 + w2;
385 
386  if (w1 <= -INFINITY || w2 <= -INFINITY) {
387  if (w1 >= INFINITY || w2 >= INFINITY) {
388  crm_trace("-INFINITY + INFINITY == -INFINITY");
389  }
390  return -INFINITY;
391 
392  } else if (w1 >= INFINITY || w2 >= INFINITY) {
393  return INFINITY;
394  }
395 
396  /* detect wrap-around */
397  if (result > 0) {
398  if (w1 <= 0 && w2 < 0) {
399  result = -INFINITY;
400  }
401 
402  } else if (w1 > 0 && w2 > 0) {
403  result = INFINITY;
404  }
405 
406  /* detect +/- INFINITY */
407  if (result >= INFINITY) {
408  result = INFINITY;
409 
410  } else if (result <= -INFINITY) {
411  result = -INFINITY;
412  }
413 
414  crm_trace("%d + %d = %d", w1, w2, result);
415  return result;
416 }
417 
418 void
419 add_hash_param(GHashTable * hash, const char *name, const char *value)
420 {
421  CRM_CHECK(hash != NULL, return);
422 
423  crm_trace("adding: name=%s value=%s", crm_str(name), crm_str(value));
424  if (name == NULL || value == NULL) {
425  return;
426 
427  } else if (safe_str_eq(value, "#default")) {
428  return;
429 
430  } else if (g_hash_table_lookup(hash, name) == NULL) {
431  g_hash_table_insert(hash, strdup(name), strdup(value));
432  }
433 }
#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:419
A dumping ground.
#define CRMD_ACTION_MIGRATED
Definition: crm.h:156
#define INFINITY
Definition: crm.h:83
int merge_weights(int w1, int w2)
Definition: common.c:382
#define CRM_OP_FENCE
Definition: crm.h:120
void pe_metadata(void)
Definition: common.c:172
#define RSC_ROLE_STARTED_S
Definition: common.h:93
#define CRMD_ACTION_NOTIFY
Definition: crm.h:169
#define CRMD_ACTION_PROMOTE
Definition: crm.h:164
const char * task2text(enum action_tasks task)
Definition: common.c:290
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:158
enum rsc_role_e text2role(const char *role)
Definition: common.c:363
#define CRM_OP_LRM_REFRESH
Definition: crm.h:133
#define CRMD_ACTION_DEMOTED
Definition: crm.h:167
#define CRMD_ACTION_STOP
Definition: crm.h:161
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:166
const char * role2text(enum rsc_role_e role)
Definition: common.c:343
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:165
gboolean check_boolean(const char *value)
Definition: utils.c:133
void verify_pe_options(GHashTable *options)
Definition: common.c:181
#define CRM_OP_SHUTDOWN
Definition: crm.h:119
const char * pe_pref(GHashTable *options, const char *name)
Definition: common.c:187
#define CRMD_ACTION_STOPPED
Definition: crm.h:162
#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:39
#define CRMD_ACTION_MIGRATE
Definition: crm.h:155
#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:137
enum action_tasks text2task(const char *task)
Definition: common.c:230
#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:170
#define safe_str_eq(a, b)
Definition: util.h:63
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:193
#define CRMD_ACTION_STARTED
Definition: crm.h:159
#define CRMD_ACTION_CANCEL
Definition: crm.h:152
action_tasks
Definition: common.h:52
#define CRMD_ACTION_DELETE
Definition: crm.h:151
#define CRMD_ACTION_STATUS
Definition: crm.h:172