This source file includes following definitions.
- cib_connect
- fencing_connect
- pacemakerd_event_cb
- pacemakerd_status
- pcmk__output_cluster_status
- pcmk_status
- pcmk__status
- pcmk__output_simple_status
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdbool.h>
13 #include <stddef.h>
14 #include <stdint.h>
15
16 #include <crm/cib/internal.h>
17 #include <crm/common/output.h>
18 #include <crm/common/results.h>
19 #include <crm/fencing/internal.h>
20 #include <crm/stonith-ng.h>
21 #include <pacemaker.h>
22 #include <pacemaker-internal.h>
23
24 static int
25 cib_connect(pcmk__output_t *out, cib_t *cib, xmlNode **current_cib)
26 {
27 int rc = pcmk_rc_ok;
28
29 CRM_CHECK(cib != NULL, return EINVAL);
30
31 if (cib->state == cib_connected_query ||
32 cib->state == cib_connected_command) {
33 return rc;
34 }
35
36 crm_trace("Connecting to the CIB");
37
38 rc = cib->cmds->signon(cib, crm_system_name, cib_query);
39 rc = pcmk_legacy2rc(rc);
40
41 if (rc != pcmk_rc_ok) {
42 out->err(out, "Could not connect to the CIB: %s",
43 pcmk_rc_str(rc));
44 return rc;
45 }
46
47 rc = cib->cmds->query(cib, NULL, current_cib,
48 cib_scope_local | cib_sync_call);
49 rc = pcmk_legacy2rc(rc);
50
51 return rc;
52 }
53
54 static stonith_t *
55 fencing_connect(void)
56 {
57 stonith_t *st = stonith_api_new();
58 int rc = pcmk_rc_ok;
59
60 if (st == NULL) {
61 return NULL;
62 }
63
64 rc = st->cmds->connect(st, crm_system_name, NULL);
65 if (rc == pcmk_rc_ok) {
66 return st;
67 } else {
68 stonith_api_delete(st);
69 return NULL;
70 }
71 }
72
73 static void
74 pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
75 enum pcmk_ipc_event event_type, crm_exit_t status,
76 void *event_data, void *user_data)
77 {
78 pcmk_pacemakerd_api_reply_t *reply = event_data;
79 enum pcmk_pacemakerd_state *state =
80 (enum pcmk_pacemakerd_state *) user_data;
81
82
83 *state = pcmk_pacemakerd_state_invalid;
84
85 if (event_type != pcmk_ipc_event_reply || status != CRM_EX_OK) {
86 return;
87 }
88
89 if (reply->reply_type == pcmk_pacemakerd_reply_ping &&
90 reply->data.ping.last_good != (time_t) 0 &&
91 reply->data.ping.status == pcmk_rc_ok) {
92 *state = reply->data.ping.state;
93 }
94 }
95
96 static int
97 pacemakerd_status(pcmk__output_t *out)
98 {
99 int rc = pcmk_rc_ok;
100 pcmk_ipc_api_t *pacemakerd_api = NULL;
101 enum pcmk_pacemakerd_state state = pcmk_pacemakerd_state_invalid;
102
103 rc = pcmk_new_ipc_api(&pacemakerd_api, pcmk_ipc_pacemakerd);
104 if (pacemakerd_api == NULL) {
105 out->err(out, "Could not connect to pacemakerd: %s",
106 pcmk_rc_str(rc));
107 return rc;
108 }
109
110 pcmk_register_ipc_callback(pacemakerd_api, pacemakerd_event_cb, (void *) &state);
111
112 rc = pcmk_connect_ipc(pacemakerd_api, pcmk_ipc_dispatch_sync);
113 if (rc == EREMOTEIO) {
114 return pcmk_rc_ok;
115 } else if (rc != pcmk_rc_ok) {
116 out->err(out, "Could not connect to pacemakerd: %s",
117 pcmk_rc_str(rc));
118 pcmk_free_ipc_api(pacemakerd_api);
119 return rc;
120 }
121
122 rc = pcmk_pacemakerd_api_ping(pacemakerd_api, crm_system_name);
123
124 if (rc != pcmk_rc_ok) {
125
126 } else if (state == pcmk_pacemakerd_state_running) {
127 rc = pcmk_rc_ok;
128 } else if (state == pcmk_pacemakerd_state_shutting_down) {
129 rc = ENOTCONN;
130 } else {
131 rc = EAGAIN;
132 }
133
134 pcmk_free_ipc_api(pacemakerd_api);
135 return rc;
136 }
137
138 int
139 pcmk__output_cluster_status(pcmk__output_t *out, stonith_t *st, cib_t *cib,
140 xmlNode *current_cib, enum pcmk__fence_history fence_history,
141 uint32_t show, uint32_t show_opts, char *only_node,
142 char *only_rsc, char *neg_location_prefix, bool simple_output)
143 {
144 xmlNode *cib_copy = copy_xml(current_cib);
145 stonith_history_t *stonith_history = NULL;
146 int history_rc = 0;
147 pe_working_set_t *data_set = NULL;
148 GList *unames = NULL;
149 GList *resources = NULL;
150
151 int rc = pcmk_rc_ok;
152
153 if (cli_config_update(&cib_copy, NULL, FALSE) == FALSE) {
154 cib__clean_up_connection(&cib);
155 rc = pcmk_rc_schema_validation;
156 out->err(out, "Upgrade failed: %s", pcmk_rc_str(rc));
157 return rc;
158 }
159
160
161 if (fence_history != pcmk__fence_history_none) {
162 history_rc = pcmk__get_fencing_history(st, &stonith_history, fence_history);
163 }
164
165 data_set = pe_new_working_set();
166 CRM_ASSERT(data_set != NULL);
167 pe__set_working_set_flags(data_set, pe_flag_no_compat);
168
169 data_set->input = cib_copy;
170 data_set->priv = out;
171 cluster_status(data_set);
172
173
174
175
176 if (pcmk_is_set(show, pcmk_section_bans) || pcmk_is_set(show, pcmk_section_tickets)) {
177 pcmk__unpack_constraints(data_set);
178 }
179
180 unames = pe__build_node_name_list(data_set, only_node);
181 resources = pe__build_rsc_list(data_set, only_rsc);
182
183
184 if (data_set->dc_node == NULL) {
185 show |= pcmk_section_dc;
186 }
187
188 if (simple_output) {
189 rc = pcmk__output_simple_status(out, data_set);
190 } else {
191 out->message(out, "cluster-status", data_set, pcmk_rc2exitc(history_rc),
192 stonith_history, fence_history, show, show_opts,
193 neg_location_prefix, unames, resources);
194 }
195
196 g_list_free_full(unames, free);
197 g_list_free_full(resources, free);
198
199 stonith_history_free(stonith_history);
200 stonith_history = NULL;
201 pe_reset_working_set(data_set);
202 return rc;
203 }
204
205 int
206 pcmk_status(xmlNodePtr *xml)
207 {
208 cib_t *cib = NULL;
209 pcmk__output_t *out = NULL;
210 int rc = pcmk_rc_ok;
211
212 uint32_t show_opts = pcmk_show_pending | pcmk_show_inactive_rscs | pcmk_show_timing;
213
214 cib = cib_new();
215
216 if (cib == NULL) {
217 return pcmk_rc_cib_corrupt;
218 }
219
220 rc = pcmk__out_prologue(&out, xml);
221 if (rc != pcmk_rc_ok) {
222 cib_delete(cib);
223 return rc;
224 }
225
226 pcmk__register_lib_messages(out);
227 pe__register_messages(out);
228 stonith__register_messages(out);
229
230 rc = pcmk__status(out, cib, pcmk__fence_history_full, pcmk_section_all,
231 show_opts, NULL, NULL, NULL, false);
232 pcmk__out_epilogue(out, xml, rc);
233
234 cib_delete(cib);
235 return rc;
236 }
237
238 int
239 pcmk__status(pcmk__output_t *out, cib_t *cib, enum pcmk__fence_history fence_history,
240 uint32_t show, uint32_t show_opts, char *only_node, char *only_rsc,
241 char *neg_location_prefix, bool simple_output)
242 {
243 xmlNode *current_cib = NULL;
244 int rc = pcmk_rc_ok;
245 stonith_t *st = NULL;
246
247 if (cib == NULL) {
248 return ENOTCONN;
249 }
250
251 if (cib->variant == cib_native) {
252 if (cib->state == cib_connected_query || cib->state == cib_connected_command) {
253 rc = pcmk_rc_ok;
254 } else {
255 rc = pacemakerd_status(out);
256 }
257 }
258
259 if (rc != pcmk_rc_ok) {
260 return rc;
261 }
262
263 if (fence_history != pcmk__fence_history_none && cib->variant == cib_native) {
264 st = fencing_connect();
265
266 if (st == NULL) {
267 return ENOTCONN;
268 }
269 }
270
271 rc = cib_connect(out, cib, ¤t_cib);
272 if (rc != pcmk_rc_ok) {
273 goto done;
274 }
275
276 rc = pcmk__output_cluster_status(out, st, cib, current_cib, fence_history, show, show_opts,
277 only_node, only_rsc, neg_location_prefix, simple_output);
278
279 done:
280 if (st != NULL) {
281 if (st->state != stonith_disconnected) {
282 st->cmds->remove_notification(st, NULL);
283 st->cmds->disconnect(st);
284 }
285
286 stonith_api_delete(st);
287 }
288
289 return rc;
290 }
291
292
293
294
295 int
296 pcmk__output_simple_status(pcmk__output_t *out, pe_working_set_t *data_set)
297 {
298 int nodes_online = 0;
299 int nodes_standby = 0;
300 int nodes_maintenance = 0;
301 char *offline_nodes = NULL;
302 size_t offline_nodes_len = 0;
303 bool no_dc = false;
304 bool offline = false;
305 bool has_warnings = false;
306
307 if (data_set->dc_node == NULL) {
308 has_warnings = true;
309 no_dc = true;
310 }
311
312 for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
313 pe_node_t *node = (pe_node_t *) iter->data;
314
315 if (node->details->standby && node->details->online) {
316 nodes_standby++;
317 } else if (node->details->maintenance && node->details->online) {
318 nodes_maintenance++;
319 } else if (node->details->online) {
320 nodes_online++;
321 } else {
322 char *s = crm_strdup_printf("offline node: %s", node->details->uname);
323
324 pcmk__add_word(&offline_nodes, &offline_nodes_len, s);
325 free(s);
326 has_warnings = true;
327 offline = true;
328 }
329 }
330
331 if (has_warnings) {
332 out->info(out, "CLUSTER WARN: %s%s%s",
333 no_dc ? "No DC" : "",
334 no_dc && offline ? ", " : "",
335 (offline? offline_nodes : ""));
336 free(offline_nodes);
337 } else {
338 char *nodes_standby_s = NULL;
339 char *nodes_maint_s = NULL;
340
341 if (nodes_standby > 0) {
342 nodes_standby_s = crm_strdup_printf(", %d standby node%s", nodes_standby,
343 pcmk__plural_s(nodes_standby));
344 }
345
346 if (nodes_maintenance > 0) {
347 nodes_maint_s = crm_strdup_printf(", %d maintenance node%s",
348 nodes_maintenance,
349 pcmk__plural_s(nodes_maintenance));
350 }
351
352 out->info(out, "CLUSTER OK: %d node%s online%s%s, "
353 "%d resource instance%s configured",
354 nodes_online, pcmk__plural_s(nodes_online),
355 nodes_standby_s != NULL ? nodes_standby_s : "",
356 nodes_maint_s != NULL ? nodes_maint_s : "",
357 data_set->ninstances, pcmk__plural_s(data_set->ninstances));
358
359 free(nodes_standby_s);
360 free(nodes_maint_s);
361 }
362
363 if (has_warnings) {
364 return pcmk_rc_error;
365 } else {
366 return pcmk_rc_ok;
367 }
368
369 }