pacemaker  2.1.5-b7adf64e51
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>
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,
49  rc = pcmk_legacy2rc(rc);
50 
51  return rc;
52 }
53 
54 static stonith_t *
55 fencing_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 
99 int
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) {
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 
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 
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 
237 int
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 
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 /* 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  */
317 int
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 }
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:227
int pcmk__pacemakerd_status(pcmk__output_t *out, const char *ipc_name, guint message_timeout_ms, enum pcmk_pacemakerd_state *state)
Control output from tools.
void stonith__register_messages(pcmk__output_t *out)
Definition: st_output.c:578
cib_t * cib_new(void)
Definition: cib_client.c:305
int(* message)(pcmk__output_t *out, const char *message_id,...)
GList * pe__build_rsc_list(pe_working_set_t *data_set, const char *s)
Definition: utils.c:826
pcmk__fence_history
Control how much of the fencing history is output.
Definition: pcmki_fence.h:18
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
#define pe_flag_no_compat
Definition: pe_types.h:132
crm_exit_t pcmk_rc2exitc(int rc)
Map a function return code to the most similar exit code.
Definition: results.c:677
#define EREMOTEIO
Definition: portability.h:135
High Level API.
char * crm_system_name
Definition: utils.c:51
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:476
void cib_delete(cib_t *cib)
Free all memory used by CIB connection.
Definition: cib_client.c:469
stonith_t * stonith_api_new(void)
Definition: st_client.c:1816
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
GList * nodes
Definition: pe_types.h:164
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:891
stonith_t * st
Definition: pcmk_fence.c:28
cib_api_operations_t * cmds
Definition: cib_types.h:179
enum stonith_state state
Definition: stonith-ng.h:550
int(* signon)(cib_t *cib, const char *name, enum cib_conn_type type)
Definition: cib_types.h:73
#define pcmk_section_all
Definition: output.h:49
int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml)
Definition: output.c:201
#define crm_trace(fmt, args...)
Definition: logging.h:365
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
struct pe_node_shared_s * details
Definition: pe_types.h:252
int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
void pcmk__register_lib_messages(pcmk__output_t *out)
Definition: pcmk_output.c:2195
pe_working_set_t * data_set
void pcmk__unpack_constraints(pe_working_set_t *data_set)
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:92
int(* disconnect)(stonith_t *st)
Disconnect from the local stonith daemon.
Definition: stonith-ng.h:178
int pcmk__output_simple_status(pcmk__output_t *out, pe_working_set_t *data_set)
Definition: pcmk_status.c:318
int pcmk_legacy2rc(int legacy_rc)
Definition: results.c:534
gboolean standby
Definition: pe_types.h:221
void pe__register_messages(pcmk__output_t *out)
Definition: pe_output.c:3010
void free_xml(xmlNode *child)
Definition: xml.c:885
int(* connect)(stonith_t *st, const char *name, int *stonith_fd)
Connect to the local fencer.
Definition: stonith-ng.h:169
xmlNode * input
Definition: pe_types.h:144
int cib__clean_up_connection(cib_t **cib)
Definition: cib_utils.c:756
Function and executable result codes.
pcmk_pacemakerd_state
GList * pe__build_node_name_list(pe_working_set_t *data_set, const char *s)
Definition: utils.c:794
pe_node_t * dc_node
Definition: pe_types.h:149
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
void stonith_api_delete(stonith_t *st)
Definition: st_client.c:1708
#define CRM_ASSERT(expr)
Definition: results.h:42
stonith_api_operations_t * cmds
Definition: stonith-ng.h:556
gboolean cluster_status(pe_working_set_t *data_set)
Definition: status.c:71
void stonith_history_free(stonith_history_t *history)
Definition: st_client.c:755
Fencing aka. STONITH.
This structure contains everything that makes up a single output formatter.
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
enum cib_variant variant
Definition: cib_types.h:169
#define pe__set_working_set_flags(working_set, flags_to_set)
Definition: internal.h:62
#define pcmk__plural_s(i)
gboolean maintenance
Definition: pe_types.h:229
void pcmk__xml_output_finish(pcmk__output_t *out, xmlNodePtr *xml)
Definition: output.c:223
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(* remove_notification)(stonith_t *stonith, const char *event)
Unregister callbacks for fence notifications.
Definition: stonith-ng.h:409
gboolean cli_config_update(xmlNode **xml, int *best_version, gboolean to_logs)
Definition: schemas.c:1197
enum cib_state state
Definition: cib_types.h:167
gboolean online
Definition: pe_types.h:220