This source file includes following definitions.
- attrd_cib_destroy_cb
- attrd_erase_cb
- attrd_erase_attrs
- attrd_cib_connect
- attrd_cib_init
- ipc_already_running
- build_arg_context
- main
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <sys/param.h>
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <unistd.h>
17
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <fcntl.h>
21
22 #include <crm/crm.h>
23 #include <crm/cib/internal.h>
24 #include <crm/msg_xml.h>
25 #include <crm/pengine/rules.h>
26 #include <crm/common/cmdline_internal.h>
27 #include <crm/common/iso8601.h>
28 #include <crm/common/ipc.h>
29 #include <crm/common/ipc_internal.h>
30 #include <crm/common/output_internal.h>
31 #include <crm/common/xml.h>
32 #include <crm/cluster/internal.h>
33
34 #include <crm/common/attrd_internal.h>
35 #include "pacemaker-attrd.h"
36
37 #define SUMMARY "daemon for managing Pacemaker node attributes"
38
39 static pcmk__output_t *out = NULL;
40
41 static pcmk__supported_format_t formats[] = {
42 PCMK__SUPPORTED_FORMAT_NONE,
43 PCMK__SUPPORTED_FORMAT_TEXT,
44 PCMK__SUPPORTED_FORMAT_XML,
45 { NULL, NULL, NULL }
46 };
47
48 lrmd_t *the_lrmd = NULL;
49 crm_cluster_t *attrd_cluster = NULL;
50 crm_trigger_t *attrd_config_read = NULL;
51 crm_exit_t attrd_exit_status = CRM_EX_OK;
52
53 static void
54 attrd_cib_destroy_cb(gpointer user_data)
55 {
56 cib_t *conn = user_data;
57
58 conn->cmds->signoff(conn);
59
60 if (attrd_shutting_down()) {
61 crm_info("Connection disconnection complete");
62
63 } else {
64
65 crm_crit("Lost connection to the CIB manager, shutting down");
66 attrd_exit_status = CRM_EX_DISCONNECT;
67 attrd_shutdown(0);
68 }
69
70 return;
71 }
72
73 static void
74 attrd_erase_cb(xmlNode *msg, int call_id, int rc, xmlNode *output,
75 void *user_data)
76 {
77 do_crm_log_unlikely((rc? LOG_NOTICE : LOG_DEBUG),
78 "Cleared transient attributes: %s "
79 CRM_XS " xpath=%s rc=%d",
80 pcmk_strerror(rc), (char *) user_data, rc);
81 }
82
83 #define XPATH_TRANSIENT "//node_state[@uname='%s']/" XML_TAG_TRANSIENT_NODEATTRS
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 static void
100 attrd_erase_attrs(void)
101 {
102 int call_id;
103 char *xpath = crm_strdup_printf(XPATH_TRANSIENT, attrd_cluster->uname);
104
105 crm_info("Clearing transient attributes from CIB " CRM_XS " xpath=%s",
106 xpath);
107
108 call_id = the_cib->cmds->remove(the_cib, xpath, NULL,
109 cib_quorum_override | cib_xpath);
110 the_cib->cmds->register_callback_full(the_cib, call_id, 120, FALSE, xpath,
111 "attrd_erase_cb", attrd_erase_cb,
112 free);
113 }
114
115 static int
116 attrd_cib_connect(int max_retry)
117 {
118 static int attempts = 0;
119
120 int rc = -ENOTCONN;
121
122 the_cib = cib_new();
123 if (the_cib == NULL) {
124 return -ENOTCONN;
125 }
126
127 do {
128 if(attempts > 0) {
129 sleep(attempts);
130 }
131
132 attempts++;
133 crm_debug("Connection attempt %d to the CIB manager", attempts);
134 rc = the_cib->cmds->signon(the_cib, T_ATTRD, cib_command);
135
136 } while(rc != pcmk_ok && attempts < max_retry);
137
138 if (rc != pcmk_ok) {
139 crm_err("Connection to the CIB manager failed: %s " CRM_XS " rc=%d",
140 pcmk_strerror(rc), rc);
141 goto cleanup;
142 }
143
144 crm_debug("Connected to the CIB manager after %d attempts", attempts);
145
146 rc = the_cib->cmds->set_connection_dnotify(the_cib, attrd_cib_destroy_cb);
147 if (rc != pcmk_ok) {
148 crm_err("Could not set disconnection callback");
149 goto cleanup;
150 }
151
152 rc = the_cib->cmds->add_notify_callback(the_cib, T_CIB_REPLACE_NOTIFY, attrd_cib_replaced_cb);
153 if(rc != pcmk_ok) {
154 crm_err("Could not set CIB notification callback");
155 goto cleanup;
156 }
157
158 rc = the_cib->cmds->add_notify_callback(the_cib, T_CIB_DIFF_NOTIFY, attrd_cib_updated_cb);
159 if (rc != pcmk_ok) {
160 crm_err("Could not set CIB notification callback (update)");
161 goto cleanup;
162 }
163
164 return pcmk_ok;
165
166 cleanup:
167 cib__clean_up_connection(&the_cib);
168 return -ENOTCONN;
169 }
170
171
172
173
174
175 static void
176 attrd_cib_init(void)
177 {
178
179 attrd_erase_attrs();
180
181
182 attrd_config_read = mainloop_add_trigger(G_PRIORITY_HIGH, attrd_read_options, NULL);
183
184
185 mainloop_set_trigger(attrd_config_read);
186 }
187
188 static bool
189 ipc_already_running(void)
190 {
191 pcmk_ipc_api_t *old_instance = NULL;
192 int rc = pcmk_rc_ok;
193
194 rc = pcmk_new_ipc_api(&old_instance, pcmk_ipc_attrd);
195 if (rc != pcmk_rc_ok) {
196 return false;
197 }
198
199 rc = pcmk_connect_ipc(old_instance, pcmk_ipc_dispatch_sync);
200 if (rc != pcmk_rc_ok) {
201 pcmk_free_ipc_api(old_instance);
202 return false;
203 }
204
205 pcmk_disconnect_ipc(old_instance);
206 pcmk_free_ipc_api(old_instance);
207 return true;
208 }
209
210 static GOptionContext *
211 build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
212 return pcmk__build_arg_context(args, "text (default), xml", group, NULL);
213 }
214
215 int
216 main(int argc, char **argv)
217 {
218 int rc = pcmk_rc_ok;
219
220 GError *error = NULL;
221 bool initialized = false;
222
223 GOptionGroup *output_group = NULL;
224 pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
225 gchar **processed_args = pcmk__cmdline_preproc(argv, NULL);
226 GOptionContext *context = build_arg_context(args, &output_group);
227
228 attrd_init_mainloop();
229 crm_log_preinit(NULL, argc, argv);
230 mainloop_add_signal(SIGTERM, attrd_shutdown);
231
232 pcmk__register_formats(output_group, formats);
233 if (!g_option_context_parse_strv(context, &processed_args, &error)) {
234 attrd_exit_status = CRM_EX_USAGE;
235 goto done;
236 }
237
238 rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
239 if ((rc != pcmk_rc_ok) || (out == NULL)) {
240 attrd_exit_status = CRM_EX_ERROR;
241 g_set_error(&error, PCMK__EXITC_ERROR, attrd_exit_status,
242 "Error creating output format %s: %s",
243 args->output_ty, pcmk_rc_str(rc));
244 goto done;
245 }
246
247 if (args->version) {
248 out->version(out, false);
249 goto done;
250 }
251
252 initialized = true;
253
254 crm_log_init(T_ATTRD, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
255 crm_notice("Starting Pacemaker node attribute manager");
256
257 if (ipc_already_running()) {
258 crm_err("pacemaker-attrd is already active, aborting startup");
259 crm_exit(CRM_EX_OK);
260 }
261
262 attributes = pcmk__strkey_table(NULL, attrd_free_attribute);
263
264
265
266
267
268 if (attrd_cib_connect(30) != pcmk_ok) {
269 attrd_exit_status = CRM_EX_FATAL;
270 goto done;
271 }
272 crm_info("CIB connection active");
273
274 if (attrd_cluster_connect() != pcmk_ok) {
275 attrd_exit_status = CRM_EX_FATAL;
276 goto done;
277 }
278 crm_info("Cluster connection active");
279
280
281 attrd_election_init();
282 attrd_cib_init();
283
284
285
286
287
288
289 attrd_broadcast_protocol();
290
291 attrd_init_ipc();
292 crm_notice("Pacemaker node attribute manager successfully started and accepting connections");
293 attrd_run_mainloop();
294
295 done:
296 if (initialized) {
297 crm_info("Shutting down attribute manager");
298
299 attrd_election_fini();
300 attrd_ipc_fini();
301 attrd_lrmd_disconnect();
302 attrd_cib_disconnect();
303 g_hash_table_destroy(attributes);
304 }
305
306 g_strfreev(processed_args);
307 pcmk__free_arg_context(context);
308
309 pcmk__output_and_clear_error(error, out);
310
311 if (out != NULL) {
312 out->finish(out, attrd_exit_status, true, NULL);
313 pcmk__output_free(out);
314 }
315 crm_exit(attrd_exit_status);
316 }