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