This source file includes following definitions.
- cib_connect
- fencing_connect
- 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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 int
100 pcmk__output_cluster_status(pcmk__output_t *out, stonith_t *stonith, cib_t *cib,
101 xmlNode *current_cib, enum pcmk__fence_history fence_history,
102 uint32_t show, uint32_t show_opts,
103 const char *only_node, const char *only_rsc,
104 const char *neg_location_prefix, bool simple_output)
105 {
106 xmlNode *cib_copy = copy_xml(current_cib);
107 stonith_history_t *stonith_history = NULL;
108 int history_rc = 0;
109 pe_working_set_t *data_set = NULL;
110 GList *unames = NULL;
111 GList *resources = NULL;
112
113 int rc = pcmk_rc_ok;
114
115 if (cli_config_update(&cib_copy, NULL, FALSE) == FALSE) {
116 cib__clean_up_connection(&cib);
117 free_xml(cib_copy);
118 rc = pcmk_rc_schema_validation;
119 out->err(out, "Upgrade failed: %s", pcmk_rc_str(rc));
120 return rc;
121 }
122
123
124 if (fence_history != pcmk__fence_history_none) {
125 history_rc = pcmk__get_fencing_history(stonith, &stonith_history,
126 fence_history);
127 }
128
129 data_set = pe_new_working_set();
130 CRM_ASSERT(data_set != NULL);
131 pe__set_working_set_flags(data_set, pe_flag_no_compat);
132
133 data_set->input = cib_copy;
134 data_set->priv = out;
135 cluster_status(data_set);
136
137
138
139
140 if (pcmk_is_set(show, pcmk_section_bans) || pcmk_is_set(show, pcmk_section_tickets)) {
141 pcmk__unpack_constraints(data_set);
142 }
143
144 unames = pe__build_node_name_list(data_set, only_node);
145 resources = pe__build_rsc_list(data_set, only_rsc);
146
147
148 if (data_set->dc_node == NULL) {
149 show |= pcmk_section_dc;
150 }
151
152 if (simple_output) {
153 rc = pcmk__output_simple_status(out, data_set);
154 } else {
155 out->message(out, "cluster-status", data_set, pcmk_rc2exitc(history_rc),
156 stonith_history, fence_history, show, show_opts,
157 neg_location_prefix, unames, resources);
158 }
159
160 g_list_free_full(unames, free);
161 g_list_free_full(resources, free);
162
163 stonith_history_free(stonith_history);
164 stonith_history = NULL;
165 pe_free_working_set(data_set);
166 return rc;
167 }
168
169 int
170 pcmk_status(xmlNodePtr *xml)
171 {
172 cib_t *cib = NULL;
173 pcmk__output_t *out = NULL;
174 int rc = pcmk_rc_ok;
175
176 uint32_t show_opts = pcmk_show_pending | pcmk_show_inactive_rscs | pcmk_show_timing;
177
178 cib = cib_new();
179
180 if (cib == NULL) {
181 return pcmk_rc_cib_corrupt;
182 }
183
184 rc = pcmk__xml_output_new(&out, xml);
185 if (rc != pcmk_rc_ok) {
186 cib_delete(cib);
187 return rc;
188 }
189
190 pcmk__register_lib_messages(out);
191 pe__register_messages(out);
192 stonith__register_messages(out);
193
194 rc = pcmk__status(out, cib, pcmk__fence_history_full, pcmk_section_all,
195 show_opts, NULL, NULL, NULL, false, 0);
196 pcmk__xml_output_finish(out, xml);
197
198 cib_delete(cib);
199 return rc;
200 }
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237 int
238 pcmk__status(pcmk__output_t *out, cib_t *cib,
239 enum pcmk__fence_history fence_history, uint32_t show,
240 uint32_t show_opts, const char *only_node, const char *only_rsc,
241 const char *neg_location_prefix, bool simple_output,
242 guint timeout_ms)
243 {
244 xmlNode *current_cib = NULL;
245 int rc = pcmk_rc_ok;
246 stonith_t *stonith = NULL;
247 enum pcmk_pacemakerd_state state = pcmk_pacemakerd_state_invalid;
248
249 if (cib == NULL) {
250 return ENOTCONN;
251 }
252
253 if ((cib->variant == cib_native)
254 && (cib->state != cib_connected_query)
255 && (cib->state != cib_connected_command)) {
256
257 rc = pcmk__pacemakerd_status(out, crm_system_name, timeout_ms, &state);
258 switch (rc) {
259 case pcmk_rc_ok:
260 switch (state) {
261 case pcmk_pacemakerd_state_running:
262 case pcmk_pacemakerd_state_shutting_down:
263
264 break;
265 default:
266 return rc;
267 }
268 break;
269 case EREMOTEIO:
270
271
272
273 rc = pcmk_rc_ok;
274 break;
275 default:
276 return rc;
277 }
278 }
279
280 if (fence_history != pcmk__fence_history_none && cib->variant == cib_native) {
281 stonith = fencing_connect();
282 }
283
284 rc = cib_connect(out, cib, ¤t_cib);
285 if (rc != pcmk_rc_ok) {
286 goto done;
287 }
288
289 rc = pcmk__output_cluster_status(out, stonith, cib, current_cib,
290 fence_history, show, show_opts, only_node,
291 only_rsc, neg_location_prefix,
292 simple_output);
293 if (rc != pcmk_rc_ok) {
294 out->err(out, "Error outputting status info from the fencer or CIB");
295 }
296
297 done:
298 if (stonith != NULL) {
299 if (stonith->state != stonith_disconnected) {
300 stonith->cmds->remove_notification(stonith, NULL);
301 stonith->cmds->disconnect(stonith);
302 }
303
304 stonith_api_delete(stonith);
305 }
306
307 if (current_cib != NULL) {
308 free_xml(current_cib);
309 }
310
311 return pcmk_rc_ok;
312 }
313
314
315
316
317 int
318 pcmk__output_simple_status(pcmk__output_t *out, pe_working_set_t *data_set)
319 {
320 int nodes_online = 0;
321 int nodes_standby = 0;
322 int nodes_maintenance = 0;
323 GString *offline_nodes = NULL;
324 bool no_dc = false;
325 bool offline = false;
326 bool has_warnings = false;
327
328 if (data_set->dc_node == NULL) {
329 has_warnings = true;
330 no_dc = true;
331 }
332
333 for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
334 pe_node_t *node = (pe_node_t *) iter->data;
335
336 if (node->details->standby && node->details->online) {
337 nodes_standby++;
338 } else if (node->details->maintenance && node->details->online) {
339 nodes_maintenance++;
340 } else if (node->details->online) {
341 nodes_online++;
342 } else {
343 pcmk__add_word(&offline_nodes, 1024, "offline node:");
344 pcmk__add_word(&offline_nodes, 0, pe__node_name(node));
345 has_warnings = true;
346 offline = true;
347 }
348 }
349
350 if (has_warnings) {
351 out->info(out, "CLUSTER WARN: %s%s%s",
352 no_dc ? "No DC" : "",
353 no_dc && offline ? ", " : "",
354 (offline? (const char *) offline_nodes->str : ""));
355
356 if (offline_nodes != NULL) {
357 g_string_free(offline_nodes, TRUE);
358 }
359
360 } else {
361 char *nodes_standby_s = NULL;
362 char *nodes_maint_s = NULL;
363
364 if (nodes_standby > 0) {
365 nodes_standby_s = crm_strdup_printf(", %d standby node%s", nodes_standby,
366 pcmk__plural_s(nodes_standby));
367 }
368
369 if (nodes_maintenance > 0) {
370 nodes_maint_s = crm_strdup_printf(", %d maintenance node%s",
371 nodes_maintenance,
372 pcmk__plural_s(nodes_maintenance));
373 }
374
375 out->info(out, "CLUSTER OK: %d node%s online%s%s, "
376 "%d resource instance%s configured",
377 nodes_online, pcmk__plural_s(nodes_online),
378 nodes_standby_s != NULL ? nodes_standby_s : "",
379 nodes_maint_s != NULL ? nodes_maint_s : "",
380 data_set->ninstances, pcmk__plural_s(data_set->ninstances));
381
382 free(nodes_standby_s);
383 free(nodes_maint_s);
384 }
385
386 if (has_warnings) {
387 return pcmk_rc_error;
388 } else {
389 return pcmk_rc_ok;
390 }
391
392 }