This source file includes following definitions.
- cfg_shutdown_callback
- pcmk_cfg_dispatch
- cfg_connection_destroy
- cluster_disconnect_cfg
- cluster_connect_cfg
- get_config_opt
- config_find_init
- config_find_next
- get_config_opt
- mcp_read_config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <crm_internal.h>
19 #include <pacemaker.h>
20
21 #include <sys/utsname.h>
22 #include <sys/stat.h>
23 #include <libgen.h>
24
25 #include <sys/types.h>
26 #include <pwd.h>
27
28 #include <corosync/hdb.h>
29 #include <corosync/cfg.h>
30 #include <corosync/cpg.h>
31 #if HAVE_CONFDB
32 # include <corosync/confdb.h>
33 #endif
34
35 #include <crm/cluster/internal.h>
36 #include <crm/common/mainloop.h>
37
38 #if SUPPORT_CMAN
39 # include <libcman.h>
40 #endif
41
42 #if HAVE_CMAP
43 # include <corosync/cmap.h>
44 #endif
45
46 enum cluster_type_e stack = pcmk_cluster_unknown;
47 static corosync_cfg_handle_t cfg_handle;
48
49
50
51 static void
52 cfg_shutdown_callback(corosync_cfg_handle_t h, corosync_cfg_shutdown_flags_t flags)
53 {
54 crm_info("Corosync wants to shut down: %s",
55 (flags == COROSYNC_CFG_SHUTDOWN_FLAG_IMMEDIATE) ? "immediate" :
56 (flags == COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS) ? "forced" : "optional");
57
58
59 corosync_cfg_replyto_shutdown(h, COROSYNC_CFG_SHUTDOWN_FLAG_NO);
60 }
61
62 static corosync_cfg_callbacks_t cfg_callbacks = {
63 .corosync_cfg_shutdown_callback = cfg_shutdown_callback,
64 };
65
66 static int
67 pcmk_cfg_dispatch(gpointer user_data)
68 {
69 corosync_cfg_handle_t *handle = (corosync_cfg_handle_t *) user_data;
70 cs_error_t rc = corosync_cfg_dispatch(*handle, CS_DISPATCH_ALL);
71
72 if (rc != CS_OK) {
73 return -1;
74 }
75 return 0;
76 }
77
78 static void
79 cfg_connection_destroy(gpointer user_data)
80 {
81 crm_err("Connection destroyed");
82 cfg_handle = 0;
83
84 pcmk_shutdown(SIGTERM);
85 }
86
87 gboolean
88 cluster_disconnect_cfg(void)
89 {
90 if (cfg_handle) {
91 corosync_cfg_finalize(cfg_handle);
92 cfg_handle = 0;
93 }
94
95 pcmk_shutdown(SIGTERM);
96 return TRUE;
97 }
98
99 #define cs_repeat(counter, max, code) do { \
100 code; \
101 if(rc == CS_ERR_TRY_AGAIN || rc == CS_ERR_QUEUE_FULL) { \
102 counter++; \
103 crm_debug("Retrying operation after %ds", counter); \
104 sleep(counter); \
105 } else { \
106 break; \
107 } \
108 } while(counter < max)
109
110 gboolean
111 cluster_connect_cfg(uint32_t * nodeid)
112 {
113 cs_error_t rc;
114 int fd = 0, retries = 0;
115
116 static struct mainloop_fd_callbacks cfg_fd_callbacks = {
117 .dispatch = pcmk_cfg_dispatch,
118 .destroy = cfg_connection_destroy,
119 };
120
121 cs_repeat(retries, 30, rc = corosync_cfg_initialize(&cfg_handle, &cfg_callbacks));
122
123 if (rc != CS_OK) {
124 crm_err("corosync cfg init error %d", rc);
125 return FALSE;
126 }
127
128 rc = corosync_cfg_fd_get(cfg_handle, &fd);
129 if (rc != CS_OK) {
130 crm_err("corosync cfg fd_get error %d", rc);
131 goto bail;
132 }
133
134 retries = 0;
135 cs_repeat(retries, 30, rc = corosync_cfg_local_get(cfg_handle, nodeid));
136
137 if (rc != CS_OK) {
138 crm_err("corosync cfg local_get error %d", rc);
139 goto bail;
140 }
141
142 crm_debug("Our nodeid: %d", *nodeid);
143 mainloop_add_fd("corosync-cfg", G_PRIORITY_DEFAULT, fd, &cfg_handle, &cfg_fd_callbacks);
144
145 return TRUE;
146
147 bail:
148 corosync_cfg_finalize(cfg_handle);
149 return FALSE;
150 }
151
152
153 #if HAVE_CONFDB
154 static int
155 get_config_opt(confdb_handle_t config,
156 hdb_handle_t object_handle, const char *key, char **value, const char *fallback)
157 {
158 size_t len = 0;
159 char *env_key = NULL;
160 const char *env_value = NULL;
161 char buffer[256];
162
163 if (*value) {
164 free(*value);
165 *value = NULL;
166 }
167
168 if (object_handle > 0) {
169 if (CS_OK == confdb_key_get(config, object_handle, key, strlen(key), &buffer, &len)) {
170 *value = strdup(buffer);
171 }
172 }
173
174 if (*value) {
175 crm_info("Found '%s' for option: %s", *value, key);
176 return 0;
177 }
178
179 env_key = crm_concat("HA", key, '_');
180 env_value = getenv(env_key);
181 free(env_key);
182
183 if (*value) {
184 crm_info("Found '%s' in ENV for option: %s", *value, key);
185 *value = strdup(env_value);
186 return 0;
187 }
188
189 if (fallback) {
190 crm_info("Defaulting to '%s' for option: %s", fallback, key);
191 *value = strdup(fallback);
192
193 } else {
194 crm_info("No default for option: %s", key);
195 }
196
197 return -1;
198 }
199
200 static confdb_handle_t
201 config_find_init(confdb_handle_t config)
202 {
203 cs_error_t rc = CS_OK;
204 confdb_handle_t local_handle = OBJECT_PARENT_HANDLE;
205
206 rc = confdb_object_find_start(config, local_handle);
207 if (rc == CS_OK) {
208 return local_handle;
209 } else {
210 crm_err("Couldn't create search context: %d", rc);
211 }
212 return 0;
213 }
214
215 static hdb_handle_t
216 config_find_next(confdb_handle_t config, const char *name, confdb_handle_t top_handle)
217 {
218 cs_error_t rc = CS_OK;
219 hdb_handle_t local_handle = 0;
220
221 if (top_handle == 0) {
222 crm_err("Couldn't search for %s: no valid context", name);
223 return 0;
224 }
225
226 crm_trace("Searching for %s in " HDB_X_FORMAT, name, top_handle);
227 rc = confdb_object_find(config, top_handle, name, strlen(name), &local_handle);
228 if (rc != CS_OK) {
229 crm_info("No additional configuration supplied for: %s", name);
230 local_handle = 0;
231 } else {
232 crm_info("Processing additional %s options...", name);
233 }
234 return local_handle;
235 }
236 #else
237 static int
238 get_config_opt(uint64_t unused, cmap_handle_t object_handle, const char *key, char **value,
239 const char *fallback)
240 {
241 int rc = 0, retries = 0;
242
243 cs_repeat(retries, 5, rc = cmap_get_string(object_handle, key, value));
244 if (rc != CS_OK) {
245 crm_trace("Search for %s failed %d, defaulting to %s", key, rc, fallback);
246 if (fallback) {
247 *value = strdup(fallback);
248 } else {
249 *value = NULL;
250 }
251 }
252 crm_trace("%s: %s", key, *value);
253 return rc;
254 }
255
256 #endif
257
258 #if HAVE_CONFDB
259 # define KEY_PREFIX ""
260 #elif HAVE_CMAP
261 # define KEY_PREFIX "logging."
262 #endif
263
264 gboolean
265 mcp_read_config(void)
266 {
267 int rc = CS_OK;
268 int retries = 0;
269
270 const char *const_value = NULL;
271
272 #if HAVE_CONFDB
273 char *value = NULL;
274 confdb_handle_t config = 0;
275 confdb_handle_t top_handle = 0;
276 hdb_handle_t local_handle;
277 static confdb_callbacks_t callbacks = { };
278
279 do {
280 rc = confdb_initialize(&config, &callbacks);
281 if (rc != CS_OK) {
282 retries++;
283 printf("confdb connection setup failed: %s. Retrying in %ds\n", ais_error2text(rc), retries);
284 crm_info("confdb connection setup failed: %s. Retrying in %ds", ais_error2text(rc), retries);
285 sleep(retries);
286
287 } else {
288 break;
289 }
290
291 } while (retries < 5);
292 #elif HAVE_CMAP
293 cmap_handle_t local_handle;
294 uint64_t config = 0;
295
296
297 do {
298 rc = cmap_initialize(&local_handle);
299 if (rc != CS_OK) {
300 retries++;
301 printf("cmap connection setup failed: %s. Retrying in %ds\n", cs_strerror(rc), retries);
302 crm_info("cmap connection setup failed: %s. Retrying in %ds", cs_strerror(rc), retries);
303 sleep(retries);
304
305 } else {
306 break;
307 }
308
309 } while (retries < 5);
310 #endif
311
312 if (rc != CS_OK) {
313 printf("Could not connect to Cluster Configuration Database API, error %d\n", rc);
314 crm_warn("Could not connect to Cluster Configuration Database API, error %d", rc);
315 return FALSE;
316 }
317
318 stack = get_cluster_type();
319 crm_info("Reading configure for stack: %s", name_for_cluster_type(stack));
320
321
322 if (stack == pcmk_cluster_corosync) {
323 set_daemon_option("cluster_type", "corosync");
324 set_daemon_option("quorum_type", "corosync");
325
326 #if HAVE_CONFDB
327 } else if (stack == pcmk_cluster_cman) {
328 set_daemon_option("cluster_type", "cman");
329 set_daemon_option("quorum_type", "cman");
330 enable_crmd_as_root(TRUE);
331
332 } else if (stack == pcmk_cluster_classic_ais) {
333 set_daemon_option("cluster_type", "openais");
334 set_daemon_option("quorum_type", "pcmk");
335
336
337 top_handle = config_find_init(config);
338 local_handle = config_find_next(config, "service", top_handle);
339
340 while (local_handle) {
341 get_config_opt(config, local_handle, "name", &value, NULL);
342 if (safe_str_eq("pacemaker", value)) {
343 get_config_opt(config, local_handle, "ver", &value, "0");
344 if (safe_str_eq(value, "1")) {
345 get_config_opt(config, local_handle, "use_logd", &value, "no");
346 set_daemon_option("use_logd", value);
347 set_daemon_option("LOGD", value);
348
349 get_config_opt(config, local_handle, "use_mgmtd", &value, "no");
350 enable_mgmtd(crm_is_true(value));
351
352 } else {
353 crm_err("We can only start Pacemaker from init if using version 1"
354 " of the Pacemaker plugin for Corosync. Terminating.");
355 crm_exit(DAEMON_RESPAWN_STOP);
356 }
357 break;
358 }
359 local_handle = config_find_next(config, "service", top_handle);
360 }
361 free(value);
362
363 #endif
364 } else {
365 crm_err("Unsupported stack type: %s", name_for_cluster_type(stack));
366 return FALSE;
367 }
368
369 #if HAVE_CONFDB
370 top_handle = config_find_init(config);
371 local_handle = config_find_next(config, "logging", top_handle);
372 #endif
373
374
375 if (daemon_option("debug")) {
376
377
378 } else {
379
380 char *debug_enabled = NULL;
381
382 get_config_opt(config, local_handle, KEY_PREFIX "debug", &debug_enabled, "off");
383
384 if (crm_is_true(debug_enabled)) {
385 set_daemon_option("debug", "1");
386 if (get_crm_log_level() < LOG_DEBUG) {
387 set_crm_log_level(LOG_DEBUG);
388 }
389
390 } else {
391 set_daemon_option("debug", "0");
392 }
393
394 free(debug_enabled);
395 }
396
397
398
399
400
401
402
403
404 const_value = daemon_option("debugfile");
405 if (daemon_option("logfile")) {
406
407
408 } else if(const_value) {
409
410 set_daemon_option("logfile", const_value);
411 crm_add_logfile(const_value);
412
413 } else {
414
415 char *logfile = NULL;
416 char *logfile_enabled = NULL;
417
418 get_config_opt(config, local_handle, KEY_PREFIX "to_logfile", &logfile_enabled, "on");
419 get_config_opt(config, local_handle, KEY_PREFIX "logfile", &logfile, "/var/log/pacemaker.log");
420
421 if (crm_is_true(logfile_enabled) == FALSE) {
422 crm_trace("File logging disabled in corosync");
423
424 } else if (crm_add_logfile(logfile)) {
425 set_daemon_option("logfile", logfile);
426
427 } else {
428 crm_err("Couldn't create logfile: %s", logfile);
429 set_daemon_option("logfile", "none");
430 }
431
432 free(logfile);
433 free(logfile_enabled);
434 }
435
436 if (daemon_option("logfacility")) {
437
438
439 } else {
440
441 char *syslog_enabled = NULL;
442 char *syslog_facility = NULL;
443
444 get_config_opt(config, local_handle, KEY_PREFIX "to_syslog", &syslog_enabled, "on");
445 get_config_opt(config, local_handle, KEY_PREFIX "syslog_facility", &syslog_facility, "daemon");
446
447 if (crm_is_true(syslog_enabled) == FALSE) {
448 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
449 set_daemon_option("logfacility", "none");
450
451 } else {
452 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(syslog_facility));
453 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
454 set_daemon_option("logfacility", syslog_facility);
455 }
456
457 free(syslog_enabled);
458 free(syslog_facility);
459 }
460
461 const_value = daemon_option("logfacility");
462 if (const_value) {
463
464 setenv("HA_LOGFACILITY", const_value, 1);
465 }
466
467 #if HAVE_CONFDB
468 confdb_finalize(config);
469 #elif HAVE_CMAP
470 if(local_handle){
471 gid_t gid = 0;
472 if (crm_user_lookup(CRM_DAEMON_USER, NULL, &gid) < 0) {
473 crm_warn("Could not authorize group with corosync " CRM_XS
474 " No group found for user %s", CRM_DAEMON_USER);
475
476 } else {
477 char key[PATH_MAX];
478 snprintf(key, PATH_MAX, "uidgid.gid.%u", gid);
479 rc = cmap_set_uint8(local_handle, key, 1);
480 if (rc != CS_OK) {
481 crm_warn("Could not authorize group with corosync "CRM_XS
482 " group=%u rc=%d (%s)", gid, rc, ais_error2text(rc));
483 }
484 }
485 }
486 cmap_finalize(local_handle);
487 #endif
488
489 return TRUE;
490 }