This source file includes following definitions.
- cfg_shutdown_callback
- pcmk_cfg_dispatch
- cfg_connection_destroy
- cluster_disconnect_cfg
- cluster_connect_cfg
- pcmkd_shutdown_corosync
- get_config_opt
- mcp_read_config
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include "pacemakerd.h"
12
13 #include <sys/utsname.h>
14 #include <sys/stat.h>
15 #include <libgen.h>
16
17 #include <sys/types.h>
18 #include <pwd.h>
19
20 #include <corosync/hdb.h>
21 #include <corosync/cfg.h>
22 #include <corosync/cpg.h>
23 #include <corosync/cmap.h>
24
25 #include <crm/cluster/internal.h>
26 #include <crm/common/ipc.h>
27 #include <crm/common/mainloop.h>
28
29 #include <crm/common/ipc_internal.h>
30
31 static corosync_cfg_handle_t cfg_handle = 0;
32
33
34
35 static void
36 cfg_shutdown_callback(corosync_cfg_handle_t h, corosync_cfg_shutdown_flags_t flags)
37 {
38 crm_info("Corosync wants to shut down: %s",
39 (flags == COROSYNC_CFG_SHUTDOWN_FLAG_IMMEDIATE) ? "immediate" :
40 (flags == COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS) ? "forced" : "optional");
41
42
43 corosync_cfg_replyto_shutdown(h, COROSYNC_CFG_SHUTDOWN_FLAG_NO);
44 }
45
46 static corosync_cfg_callbacks_t cfg_callbacks = {
47 .corosync_cfg_shutdown_callback = cfg_shutdown_callback,
48 };
49
50 static int
51 pcmk_cfg_dispatch(gpointer user_data)
52 {
53 corosync_cfg_handle_t *handle = (corosync_cfg_handle_t *) user_data;
54 cs_error_t rc = corosync_cfg_dispatch(*handle, CS_DISPATCH_ALL);
55
56 if (rc != CS_OK) {
57 return -1;
58 }
59 return 0;
60 }
61
62 static void
63 cfg_connection_destroy(gpointer user_data)
64 {
65 crm_err("Lost connection to cluster layer");
66 corosync_cfg_finalize(cfg_handle);
67 cfg_handle = 0;
68 pcmk_shutdown(SIGTERM);
69 }
70
71 gboolean
72 cluster_disconnect_cfg(void)
73 {
74 if (cfg_handle) {
75 corosync_cfg_finalize(cfg_handle);
76 cfg_handle = 0;
77 }
78
79 pcmk_shutdown(SIGTERM);
80 return TRUE;
81 }
82
83 #define cs_repeat(counter, max, code) do { \
84 code; \
85 if(rc == CS_ERR_TRY_AGAIN || rc == CS_ERR_QUEUE_FULL) { \
86 counter++; \
87 crm_debug("Retrying Corosync operation after %ds", counter); \
88 sleep(counter); \
89 } else { \
90 break; \
91 } \
92 } while(counter < max)
93
94 gboolean
95 cluster_connect_cfg(void)
96 {
97 cs_error_t rc;
98 int fd = -1, retries = 0, rv;
99 uid_t found_uid = 0;
100 gid_t found_gid = 0;
101 pid_t found_pid = 0;
102 uint32_t nodeid;
103
104 static struct mainloop_fd_callbacks cfg_fd_callbacks = {
105 .dispatch = pcmk_cfg_dispatch,
106 .destroy = cfg_connection_destroy,
107 };
108
109 cs_repeat(retries, 30, rc = corosync_cfg_initialize(&cfg_handle, &cfg_callbacks));
110
111 if (rc != CS_OK) {
112 crm_crit("Could not connect to Corosync CFG: %s " CRM_XS " rc=%d",
113 cs_strerror(rc), rc);
114 return FALSE;
115 }
116
117 rc = corosync_cfg_fd_get(cfg_handle, &fd);
118 if (rc != CS_OK) {
119 crm_crit("Could not get Corosync CFG descriptor: %s " CRM_XS " rc=%d",
120 cs_strerror(rc), rc);
121 goto bail;
122 }
123
124
125 if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
126 &found_uid, &found_gid))) {
127 crm_crit("Rejecting Corosync CFG provider because process %lld "
128 "is running as uid %lld gid %lld, not root",
129 (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
130 (long long) found_uid, (long long) found_gid);
131 goto bail;
132 } else if (rv < 0) {
133 crm_crit("Could not authenticate Corosync CFG provider: %s "
134 CRM_XS " rc=%d", strerror(-rv), -rv);
135 goto bail;
136 }
137
138 retries = 0;
139 cs_repeat(retries, 30, rc = corosync_cfg_local_get(cfg_handle, &nodeid));
140 if (rc != CS_OK) {
141 crm_crit("Could not get local node ID from Corosync: %s "
142 CRM_XS " rc=%d", cs_strerror(rc), rc);
143 goto bail;
144 }
145 crm_debug("Corosync reports local node ID is %lu", (unsigned long) nodeid);
146
147 mainloop_add_fd("corosync-cfg", G_PRIORITY_DEFAULT, fd, &cfg_handle, &cfg_fd_callbacks);
148 return TRUE;
149
150 bail:
151 corosync_cfg_finalize(cfg_handle);
152 return FALSE;
153 }
154
155 void
156 pcmkd_shutdown_corosync(void)
157 {
158 cs_error_t rc;
159
160 if (cfg_handle == 0) {
161 crm_warn("Unable to shut down Corosync: No connection");
162 return;
163 }
164 crm_info("Asking Corosync to shut down");
165 rc = corosync_cfg_try_shutdown(cfg_handle,
166 COROSYNC_CFG_SHUTDOWN_FLAG_IMMEDIATE);
167 if (rc == CS_OK) {
168 corosync_cfg_finalize(cfg_handle);
169 cfg_handle = 0;
170 } else {
171 crm_warn("Corosync shutdown failed: %s " CRM_XS " rc=%d",
172 cs_strerror(rc), rc);
173 }
174 }
175
176
177
178 static int
179 get_config_opt(uint64_t unused, cmap_handle_t object_handle, const char *key, char **value,
180 const char *fallback)
181 {
182 int rc = 0, retries = 0;
183
184 cs_repeat(retries, 5, rc = cmap_get_string(object_handle, key, value));
185 if (rc != CS_OK) {
186 crm_trace("Search for %s failed %d, defaulting to %s", key, rc, fallback);
187 if (fallback) {
188 *value = strdup(fallback);
189 } else {
190 *value = NULL;
191 }
192 }
193 crm_trace("%s: %s", key, *value);
194 return rc;
195 }
196
197 gboolean
198 mcp_read_config(void)
199 {
200 cs_error_t rc = CS_OK;
201 int retries = 0;
202 cmap_handle_t local_handle;
203 uint64_t config = 0;
204 int fd = -1;
205 uid_t found_uid = 0;
206 gid_t found_gid = 0;
207 pid_t found_pid = 0;
208 int rv;
209 enum cluster_type_e stack;
210
211
212 do {
213 rc = cmap_initialize(&local_handle);
214 if (rc != CS_OK) {
215 retries++;
216 crm_info("Could not connect to Corosync CMAP: %s (retrying in %ds) "
217 CRM_XS " rc=%d", cs_strerror(rc), retries, rc);
218 sleep(retries);
219
220 } else {
221 break;
222 }
223
224 } while (retries < 5);
225
226 if (rc != CS_OK) {
227 crm_crit("Could not connect to Corosync CMAP: %s "
228 CRM_XS " rc=%d", cs_strerror(rc), rc);
229 return FALSE;
230 }
231
232 rc = cmap_fd_get(local_handle, &fd);
233 if (rc != CS_OK) {
234 crm_crit("Could not get Corosync CMAP descriptor: %s " CRM_XS " rc=%d",
235 cs_strerror(rc), rc);
236 cmap_finalize(local_handle);
237 return FALSE;
238 }
239
240
241 if (!(rv = crm_ipc_is_authentic_process(fd, (uid_t) 0,(gid_t) 0, &found_pid,
242 &found_uid, &found_gid))) {
243 crm_crit("Rejecting Corosync CMAP provider because process %lld "
244 "is running as uid %lld gid %lld, not root",
245 (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
246 (long long) found_uid, (long long) found_gid);
247 cmap_finalize(local_handle);
248 return FALSE;
249 } else if (rv < 0) {
250 crm_crit("Could not authenticate Corosync CMAP provider: %s "
251 CRM_XS " rc=%d", strerror(-rv), -rv);
252 cmap_finalize(local_handle);
253 return FALSE;
254 }
255
256 stack = get_cluster_type();
257 if (stack != pcmk_cluster_corosync) {
258 crm_crit("Expected corosync stack but detected %s " CRM_XS " stack=%d",
259 name_for_cluster_type(stack), stack);
260 return FALSE;
261 }
262
263 crm_info("Reading configuration for %s stack",
264 name_for_cluster_type(stack));
265 pcmk__set_env_option("cluster_type", "corosync");
266 pcmk__set_env_option("quorum_type", "corosync");
267
268
269 if (pcmk__env_option("debug") == NULL) {
270 char *debug_enabled = NULL;
271
272 get_config_opt(config, local_handle, "logging.debug", &debug_enabled, "off");
273
274 if (crm_is_true(debug_enabled)) {
275 pcmk__set_env_option("debug", "1");
276 if (get_crm_log_level() < LOG_DEBUG) {
277 set_crm_log_level(LOG_DEBUG);
278 }
279
280 } else {
281 pcmk__set_env_option("debug", "0");
282 }
283
284 free(debug_enabled);
285 }
286
287 if(local_handle){
288 gid_t gid = 0;
289 if (pcmk_daemon_user(NULL, &gid) < 0) {
290 crm_warn("Could not authorize group with Corosync " CRM_XS
291 " No group found for user %s", CRM_DAEMON_USER);
292
293 } else {
294 char key[PATH_MAX];
295 snprintf(key, PATH_MAX, "uidgid.gid.%u", gid);
296 rc = cmap_set_uint8(local_handle, key, 1);
297 if (rc != CS_OK) {
298 crm_warn("Could not authorize group with Corosync: %s " CRM_XS
299 " group=%u rc=%d", ais_error2text(rc), gid, rc);
300 }
301 }
302 }
303 cmap_finalize(local_handle);
304
305 return TRUE;
306 }