pacemaker 2.1.5-a3f44794f94
Scalable High-Availability cluster resource manager
pcmk_status.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2022 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU General Public License version 2
7 * or later (GPLv2+) WITHOUT ANY WARRANTY.
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>
20#include <crm/stonith-ng.h>
21#include <pacemaker.h>
22#include <pacemaker-internal.h>
23
24static int
25cib_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 ||
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,
49 rc = pcmk_legacy2rc(rc);
50
51 return rc;
52}
53
54static stonith_t *
55fencing_connect(void)
56{
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 {
69 return NULL;
70 }
71}
72
99int
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;
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) {
117 free_xml(cib_copy);
119 out->err(out, "Upgrade failed: %s", pcmk_rc_str(rc));
120 return rc;
121 }
122
123 /* get the stonith-history if there is evidence we need it */
124 if (fence_history != pcmk__fence_history_none) {
125 history_rc = pcmk__get_fencing_history(stonith, &stonith_history,
126 fence_history);
127 }
128
130 CRM_ASSERT(data_set != NULL);
132
133 data_set->input = cib_copy;
134 data_set->priv = out;
136
137 /* Unpack constraints if any section will need them
138 * (tickets may be referenced in constraints but not granted yet,
139 * and bans need negative location constraints) */
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 /* Always print DC if NULL. */
148 if (data_set->dc_node == NULL) {
149 show |= pcmk_section_dc;
150 }
151
152 if (simple_output) {
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;
166 return rc;
167}
168
169int
170pcmk_status(xmlNodePtr *xml)
171{
172 cib_t *cib = NULL;
173 pcmk__output_t *out = NULL;
174 int rc = pcmk_rc_ok;
175
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
193
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
237int
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;
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) {
263 // CIB may still be available while shutting down
264 break;
265 default:
266 return rc;
267 }
268 break;
269 case EREMOTEIO:
270 /* We'll always get EREMOTEIO if we run this on a Pacemaker
271 * Remote node. The fencer and CIB might be available.
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, &current_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
297done:
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/* This is an internal-only function that is planned to be deprecated and removed.
315 * It should only ever be called from crm_mon.
316 */
317int
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 : "",
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 /* coverity[leaked_storage] False positive */
392}
int cib__clean_up_connection(cib_t **cib)
Definition: cib_utils.c:756
void cib_delete(cib_t *cib)
Free all memory used by CIB connection.
Definition: cib_client.c:469
cib_t * cib_new(void)
Definition: cib_client.c:305
@ cib_query
Definition: cib_types.h:44
@ cib_scope_local
Definition: cib_types.h:59
@ cib_sync_call
Definition: cib_types.h:61
@ cib_native
Definition: cib_types.h:30
@ cib_connected_command
Definition: cib_types.h:37
@ cib_connected_query
Definition: cib_types.h:38
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
Definition: util.h:121
char * crm_system_name
Definition: utils.c:51
void stonith__register_messages(pcmk__output_t *out)
Definition: st_output.c:578
pcmk_pacemakerd_state
@ pcmk_pacemakerd_state_invalid
@ pcmk_pacemakerd_state_running
@ pcmk_pacemakerd_state_shutting_down
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:227
#define crm_trace(fmt, args...)
Definition: logging.h:365
pe_working_set_t * data_set
Control output from tools.
@ pcmk_show_timing
Definition: output.h:62
@ pcmk_show_pending
Definition: output.h:65
@ pcmk_show_inactive_rscs
Definition: output.h:63
#define pcmk_section_all
Definition: output.h:49
@ pcmk_section_bans
Definition: output.h:41
@ pcmk_section_tickets
Definition: output.h:40
@ pcmk_section_dc
Definition: output.h:28
int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml)
Definition: output.c:201
void pcmk__xml_output_finish(pcmk__output_t *out, xmlNodePtr *xml)
Definition: output.c:223
High Level API.
stonith_t * st
Definition: pcmk_fence.c:28
int pcmk__status(pcmk__output_t *out, cib_t *cib, enum pcmk__fence_history fence_history, uint32_t show, uint32_t show_opts, const char *only_node, const char *only_rsc, const char *neg_location_prefix, bool simple_output, guint timeout_ms)
Definition: pcmk_status.c:238
int pcmk__output_simple_status(pcmk__output_t *out, pe_working_set_t *data_set)
Definition: pcmk_status.c:318
int pcmk__output_cluster_status(pcmk__output_t *out, stonith_t *stonith, cib_t *cib, xmlNode *current_cib, enum pcmk__fence_history fence_history, uint32_t show, uint32_t show_opts, const char *only_node, const char *only_rsc, const char *neg_location_prefix, bool simple_output)
Definition: pcmk_status.c:100
int pcmk_status(xmlNodePtr *xml)
Output the current status of the cluster, formatted in the same way that crm_mon --output-as=xml woul...
Definition: pcmk_status.c:170
int pcmk__pacemakerd_status(pcmk__output_t *out, const char *ipc_name, guint message_timeout_ms, enum pcmk_pacemakerd_state *state)
int pcmk__get_fencing_history(stonith_t *st, stonith_history_t **stonith_history, enum pcmk__fence_history fence_history)
Fetch STONITH history, optionally reducing it.
Definition: pcmk_fence.c:583
pcmk__fence_history
Control how much of the fencing history is output.
Definition: pcmki_fence.h:18
@ pcmk__fence_history_none
Definition: pcmki_fence.h:19
@ pcmk__fence_history_full
Definition: pcmki_fence.h:21
void pcmk__register_lib_messages(pcmk__output_t *out)
Definition: pcmk_output.c:2195
void pcmk__unpack_constraints(pe_working_set_t *data_set)
#define pe_flag_no_compat
Definition: pe_types.h:132
GList * pe__build_rsc_list(pe_working_set_t *data_set, const char *s)
Definition: utils.c:826
GList * pe__build_node_name_list(pe_working_set_t *data_set, const char *s)
Definition: utils.c:794
void pe__register_messages(pcmk__output_t *out)
Definition: pe_output.c:3010
#define pe__set_working_set_flags(working_set, flags_to_set)
Definition: internal.h:62
#define EREMOTEIO
Definition: portability.h:135
Function and executable result codes.
#define CRM_ASSERT(expr)
Definition: results.h:42
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:476
@ pcmk_rc_ok
Definition: results.h:148
@ pcmk_rc_schema_validation
Definition: results.h:128
@ pcmk_rc_error
Definition: results.h:144
@ pcmk_rc_cib_corrupt
Definition: results.h:137
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:534
crm_exit_t pcmk_rc2exitc(int rc)
Map a function return code to the most similar exit code.
Definition: results.c:677
gboolean cluster_status(pe_working_set_t *data_set)
Definition: status.c:71
void pe_free_working_set(pe_working_set_t *data_set)
Free a working set.
Definition: status.c:50
pe_working_set_t * pe_new_working_set(void)
Create a new working set.
Definition: status.c:34
Fencing aka. STONITH.
void stonith_history_free(stonith_history_t *history)
Definition: st_client.c:755
@ stonith_disconnected
Definition: stonith-ng.h:44
void stonith_api_delete(stonith_t *st)
Definition: st_client.c:1708
stonith_t * stonith_api_new(void)
Definition: st_client.c:1816
#define pcmk__plural_s(i)
int(* signon)(cib_t *cib, const char *name, enum cib_conn_type type)
Definition: cib_types.h:73
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:92
enum cib_state state
Definition: cib_types.h:167
cib_api_operations_t * cmds
Definition: cib_types.h:179
enum cib_variant variant
Definition: cib_types.h:169
This structure contains everything that makes up a single output formatter.
int(* message)(pcmk__output_t *out, const char *message_id,...)
int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
struct pe_node_shared_s * details
Definition: pe_types.h:252
gboolean online
Definition: pe_types.h:220
gboolean standby
Definition: pe_types.h:221
gboolean maintenance
Definition: pe_types.h:229
xmlNode * input
Definition: pe_types.h:144
pe_node_t * dc_node
Definition: pe_types.h:149
GList * nodes
Definition: pe_types.h:164
int(* connect)(stonith_t *st, const char *name, int *stonith_fd)
Connect to the local fencer.
Definition: stonith-ng.h:169
int(* disconnect)(stonith_t *st)
Disconnect from the local stonith daemon.
Definition: stonith-ng.h:178
int(* remove_notification)(stonith_t *stonith, const char *event)
Unregister callbacks for fence notifications.
Definition: stonith-ng.h:409
enum stonith_state state
Definition: stonith-ng.h:550
stonith_api_operations_t * cmds
Definition: stonith-ng.h:556
gboolean cli_config_update(xmlNode **xml, int *best_version, gboolean to_logs)
Definition: schemas.c:1197
void free_xml(xmlNode *child)
Definition: xml.c:885
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:891