This source file includes following definitions.
- cfg_shutdown_callback
- pcmk_cfg_dispatch
- close_cfg
- cluster_reconnect_cb
- cfg_connection_destroy
- cluster_disconnect_cfg
- cluster_connect_cfg
- pcmkd_shutdown_corosync
- pcmkd_corosync_connected
- get_config_opt
- pacemakerd_read_config
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include "pacemakerd.h"
12 #include "pcmkd_corosync.h"
13
14 #include <sys/utsname.h>
15 #include <sys/stat.h>
16 #include <libgen.h>
17
18 #include <sys/types.h>
19 #include <pwd.h>
20
21 #include <corosync/hdb.h>
22 #include <corosync/cfg.h>
23 #include <corosync/cpg.h>
24 #include <corosync/cmap.h>
25
26 #include <crm/cluster/internal.h>
27 #include <crm/common/ipc.h>
28 #include <crm/common/mainloop.h>
29
30 #include <crm/common/ipc_internal.h>
31
32 static corosync_cfg_handle_t cfg_handle = 0;
33 static mainloop_timer_t *reconnect_timer = NULL;
34
35
36
37 static void
38 cfg_shutdown_callback(corosync_cfg_handle_t h, corosync_cfg_shutdown_flags_t flags)
39 {
40 crm_info("Corosync wants to shut down: %s",
41 (flags == COROSYNC_CFG_SHUTDOWN_FLAG_IMMEDIATE) ? "immediate" :
42 (flags == COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS) ? "forced" : "optional");
43
44
45 corosync_cfg_replyto_shutdown(h, COROSYNC_CFG_SHUTDOWN_FLAG_NO);
46 }
47
48 static corosync_cfg_callbacks_t cfg_callbacks = {
49 .corosync_cfg_shutdown_callback = cfg_shutdown_callback,
50 };
51
52 static int
53 pcmk_cfg_dispatch(gpointer user_data)
54 {
55 corosync_cfg_handle_t *handle = (corosync_cfg_handle_t *) user_data;
56 cs_error_t rc = corosync_cfg_dispatch(*handle, CS_DISPATCH_ALL);
57
58 if (rc != CS_OK) {
59 return -1;
60 }
61 return 0;
62 }
63
64 static void
65 close_cfg(void)
66 {
67 if (cfg_handle != 0) {
68 #ifdef HAVE_COROSYNC_CFG_TRACKSTART
69
70
71
72
73 #endif
74 corosync_cfg_finalize(cfg_handle);
75 cfg_handle = 0;
76 }
77 }
78
79 static gboolean
80 cluster_reconnect_cb(gpointer data)
81 {
82 if (cluster_connect_cfg()) {
83 mainloop_timer_del(reconnect_timer);
84 reconnect_timer = NULL;
85 crm_notice("Cluster reconnect succeeded");
86 pacemakerd_read_config();
87 restart_cluster_subdaemons();
88 return G_SOURCE_REMOVE;
89 } else {
90 crm_info("Cluster reconnect failed "
91 "(connection will be reattempted once per second)");
92 }
93
94
95
96
97 return G_SOURCE_CONTINUE;
98 }
99
100
101 static void
102 cfg_connection_destroy(gpointer user_data)
103 {
104 crm_warn("Lost connection to cluster layer "
105 "(connection will be reattempted once per second)");
106 corosync_cfg_finalize(cfg_handle);
107 cfg_handle = 0;
108 reconnect_timer = mainloop_timer_add("corosync reconnect", 1000, TRUE, cluster_reconnect_cb, NULL);
109 mainloop_timer_start(reconnect_timer);
110 }
111
112 void
113 cluster_disconnect_cfg(void)
114 {
115 close_cfg();
116 if (reconnect_timer != NULL) {
117
118
119
120 mainloop_timer_del(reconnect_timer);
121 reconnect_timer = NULL;
122 }
123 }
124
125 #define cs_repeat(counter, max, code) do { \
126 code; \
127 if(rc == CS_ERR_TRY_AGAIN || rc == CS_ERR_QUEUE_FULL) { \
128 counter++; \
129 crm_debug("Retrying Corosync operation after %ds", counter); \
130 sleep(counter); \
131 } else { \
132 break; \
133 } \
134 } while(counter < max)
135
136 gboolean
137 cluster_connect_cfg(void)
138 {
139 cs_error_t rc;
140 int fd = -1, retries = 0, rv;
141 uid_t found_uid = 0;
142 gid_t found_gid = 0;
143 pid_t found_pid = 0;
144 uint32_t nodeid;
145
146 static struct mainloop_fd_callbacks cfg_fd_callbacks = {
147 .dispatch = pcmk_cfg_dispatch,
148 .destroy = cfg_connection_destroy,
149 };
150
151 cs_repeat(retries, 30, rc = corosync_cfg_initialize(&cfg_handle, &cfg_callbacks));
152
153 if (rc != CS_OK) {
154 crm_crit("Could not connect to Corosync CFG: %s " CRM_XS " rc=%d",
155 cs_strerror(rc), rc);
156 return FALSE;
157 }
158
159 rc = corosync_cfg_fd_get(cfg_handle, &fd);
160 if (rc != CS_OK) {
161 crm_crit("Could not get Corosync CFG descriptor: %s " CRM_XS " rc=%d",
162 cs_strerror(rc), rc);
163 goto bail;
164 }
165
166
167 if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
168 &found_uid, &found_gid))) {
169 crm_crit("Rejecting Corosync CFG provider because process %lld "
170 "is running as uid %lld gid %lld, not root",
171 (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
172 (long long) found_uid, (long long) found_gid);
173 goto bail;
174 } else if (rv < 0) {
175 crm_crit("Could not authenticate Corosync CFG provider: %s "
176 CRM_XS " rc=%d", strerror(-rv), -rv);
177 goto bail;
178 }
179
180 retries = 0;
181 cs_repeat(retries, 30, rc = corosync_cfg_local_get(cfg_handle, &nodeid));
182 if (rc != CS_OK) {
183 crm_crit("Could not get local node ID from Corosync: %s "
184 CRM_XS " rc=%d", cs_strerror(rc), rc);
185 goto bail;
186 }
187 crm_debug("Corosync reports local node ID is %lu", (unsigned long) nodeid);
188
189 #ifdef HAVE_COROSYNC_CFG_TRACKSTART
190 retries = 0;
191 cs_repeat(retries, 30, rc = corosync_cfg_trackstart(cfg_handle, 0));
192 if (rc != CS_OK) {
193 crm_crit("Could not enable Corosync CFG shutdown tracker: %s " CRM_XS " rc=%d",
194 cs_strerror(rc), rc);
195 goto bail;
196 }
197 #endif
198
199 mainloop_add_fd("corosync-cfg", G_PRIORITY_DEFAULT, fd, &cfg_handle, &cfg_fd_callbacks);
200 return TRUE;
201
202 bail:
203 corosync_cfg_finalize(cfg_handle);
204 return FALSE;
205 }
206
207 void
208 pcmkd_shutdown_corosync(void)
209 {
210 cs_error_t rc;
211
212 if (cfg_handle == 0) {
213 crm_warn("Unable to shut down Corosync: No connection");
214 return;
215 }
216 crm_info("Asking Corosync to shut down");
217 rc = corosync_cfg_try_shutdown(cfg_handle,
218 COROSYNC_CFG_SHUTDOWN_FLAG_IMMEDIATE);
219 if (rc == CS_OK) {
220 close_cfg();
221 } else {
222 crm_warn("Corosync shutdown failed: %s " CRM_XS " rc=%d",
223 cs_strerror(rc), rc);
224 }
225 }
226
227 bool
228 pcmkd_corosync_connected(void)
229 {
230 cpg_handle_t local_handle = 0;
231 cpg_model_v1_data_t cpg_model_info = {CPG_MODEL_V1, NULL, NULL, NULL, 0};
232 int fd = -1;
233
234 if (cpg_model_initialize(&local_handle, CPG_MODEL_V1, (cpg_model_data_t *) &cpg_model_info, NULL) != CS_OK) {
235 return false;
236 }
237
238 if (cpg_fd_get(local_handle, &fd) != CS_OK) {
239 return false;
240 }
241
242 cpg_finalize(local_handle);
243
244 return true;
245 }
246
247
248 static int
249 get_config_opt(uint64_t unused, cmap_handle_t object_handle, const char *key, char **value,
250 const char *fallback)
251 {
252 int rc = 0, retries = 0;
253
254 cs_repeat(retries, 5, rc = cmap_get_string(object_handle, key, value));
255 if (rc != CS_OK) {
256 crm_trace("Search for %s failed %d, defaulting to %s", key, rc, fallback);
257 pcmk__str_update(value, fallback);
258 }
259 crm_trace("%s: %s", key, *value);
260 return rc;
261 }
262
263 gboolean
264 pacemakerd_read_config(void)
265 {
266 cs_error_t rc = CS_OK;
267 int retries = 0;
268 cmap_handle_t local_handle;
269 uint64_t config = 0;
270 int fd = -1;
271 uid_t found_uid = 0;
272 gid_t found_gid = 0;
273 pid_t found_pid = 0;
274 int rv;
275 enum pcmk_cluster_layer cluster_layer = pcmk_cluster_layer_unknown;
276 const char *cluster_layer_s = NULL;
277
278
279 do {
280 rc = pcmk__init_cmap(&local_handle);
281 if (rc != CS_OK) {
282 retries++;
283 crm_info("Could not connect to Corosync CMAP: %s (retrying in %ds) "
284 CRM_XS " rc=%d", cs_strerror(rc), retries, rc);
285 sleep(retries);
286
287 } else {
288 break;
289 }
290
291 } while (retries < 5);
292
293 if (rc != CS_OK) {
294 crm_crit("Could not connect to Corosync CMAP: %s "
295 CRM_XS " rc=%d", cs_strerror(rc), rc);
296 return FALSE;
297 }
298
299 rc = cmap_fd_get(local_handle, &fd);
300 if (rc != CS_OK) {
301 crm_crit("Could not get Corosync CMAP descriptor: %s " CRM_XS " rc=%d",
302 cs_strerror(rc), rc);
303 cmap_finalize(local_handle);
304 return FALSE;
305 }
306
307
308 if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
309 &found_uid, &found_gid))) {
310 crm_crit("Rejecting Corosync CMAP provider because process %lld "
311 "is running as uid %lld gid %lld, not root",
312 (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
313 (long long) found_uid, (long long) found_gid);
314 cmap_finalize(local_handle);
315 return FALSE;
316 } else if (rv < 0) {
317 crm_crit("Could not authenticate Corosync CMAP provider: %s "
318 CRM_XS " rc=%d", strerror(-rv), -rv);
319 cmap_finalize(local_handle);
320 return FALSE;
321 }
322
323 cluster_layer = pcmk_get_cluster_layer();
324 cluster_layer_s = pcmk_cluster_layer_text(cluster_layer);
325
326 if (cluster_layer != pcmk_cluster_layer_corosync) {
327 crm_crit("Expected Corosync cluster layer but detected %s "
328 CRM_XS " cluster_layer=%d",
329 cluster_layer_s, cluster_layer);
330 return FALSE;
331 }
332
333 crm_info("Reading configuration for %s cluster layer", cluster_layer_s);
334 pcmk__set_env_option(PCMK__ENV_CLUSTER_TYPE, PCMK_VALUE_COROSYNC, true);
335
336
337 pcmk__set_env_option(PCMK__ENV_QUORUM_TYPE, PCMK_VALUE_COROSYNC, true);
338
339
340 if (pcmk__env_option(PCMK__ENV_DEBUG) == NULL) {
341 char *debug_enabled = NULL;
342
343 get_config_opt(config, local_handle, "logging.debug", &debug_enabled, "off");
344
345 if (crm_is_true(debug_enabled)) {
346 pcmk__set_env_option(PCMK__ENV_DEBUG, "1", true);
347 if (get_crm_log_level() < LOG_DEBUG) {
348 set_crm_log_level(LOG_DEBUG);
349 }
350
351 } else {
352 pcmk__set_env_option(PCMK__ENV_DEBUG, "0", true);
353 }
354
355 free(debug_enabled);
356 }
357
358 if(local_handle){
359 gid_t gid = 0;
360 if (pcmk_daemon_user(NULL, &gid) < 0) {
361 crm_warn("Could not authorize group with Corosync " CRM_XS
362 " No group found for user %s", CRM_DAEMON_USER);
363
364 } else {
365 char key[PATH_MAX];
366 snprintf(key, PATH_MAX, "uidgid.gid.%u", gid);
367 rc = cmap_set_uint8(local_handle, key, 1);
368 if (rc != CS_OK) {
369 crm_warn("Could not authorize group with Corosync: %s " CRM_XS
370 " group=%u rc=%d", pcmk__cs_err_str(rc), gid, rc);
371 }
372 }
373 }
374 cmap_finalize(local_handle);
375
376 return TRUE;
377 }