pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
pcmk_status.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2023 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 stonith_t *
25 fencing_connect(void)
26 {
28  int rc = pcmk_rc_ok;
29 
30  if (st == NULL) {
31  return NULL;
32  }
33 
34  rc = st->cmds->connect(st, crm_system_name, NULL);
35  if (rc == pcmk_rc_ok) {
36  return st;
37  } else {
39  return NULL;
40  }
41 }
42 
70 int
72  xmlNode *current_cib,
73  enum pcmk_pacemakerd_state pcmkd_state,
74  enum pcmk__fence_history fence_history,
75  uint32_t show, uint32_t show_opts,
76  const char *only_node, const char *only_rsc,
77  const char *neg_location_prefix, bool simple_output)
78 {
79  xmlNode *cib_copy = copy_xml(current_cib);
80  stonith_history_t *stonith_history = NULL;
81  int history_rc = 0;
82  pe_working_set_t *data_set = NULL;
83  GList *unames = NULL;
84  GList *resources = NULL;
85 
86  int rc = pcmk_rc_ok;
87 
88  if (cli_config_update(&cib_copy, NULL, FALSE) == FALSE) {
90  free_xml(cib_copy);
92  out->err(out, "Upgrade failed: %s", pcmk_rc_str(rc));
93  return rc;
94  }
95 
96  /* get the stonith-history if there is evidence we need it */
97  if (fence_history != pcmk__fence_history_none) {
98  history_rc = pcmk__get_fencing_history(stonith, &stonith_history,
99  fence_history);
100  }
101 
103  CRM_ASSERT(data_set != NULL);
105 
106  data_set->input = cib_copy;
107  data_set->priv = out;
109 
110  if ((cib->variant == cib_native) && pcmk_is_set(show, pcmk_section_times)) {
111  if (pcmk__our_nodename == NULL) {
112  // Currently used only in the times section
113  pcmk__query_node_name(out, 0, &pcmk__our_nodename, 0);
114  }
116  }
117 
118  /* Unpack constraints if any section will need them
119  * (tickets may be referenced in constraints but not granted yet,
120  * and bans need negative location constraints) */
123  }
124 
125  unames = pe__build_node_name_list(data_set, only_node);
126  resources = pe__build_rsc_list(data_set, only_rsc);
127 
128  /* Always print DC if NULL. */
129  if (data_set->dc_node == NULL) {
130  show |= pcmk_section_dc;
131  }
132 
133  if (simple_output) {
135  } else {
136  out->message(out, "cluster-status",
137  data_set, pcmkd_state, pcmk_rc2exitc(history_rc),
138  stonith_history, fence_history, show, show_opts,
139  neg_location_prefix, unames, resources);
140  }
141 
142  g_list_free_full(unames, free);
143  g_list_free_full(resources, free);
144 
145  stonith_history_free(stonith_history);
146  stonith_history = NULL;
148  return rc;
149 }
150 
151 int
152 pcmk_status(xmlNodePtr *xml)
153 {
154  cib_t *cib = NULL;
155  pcmk__output_t *out = NULL;
156  int rc = pcmk_rc_ok;
157 
159 
160  cib = cib_new();
161 
162  if (cib == NULL) {
163  return pcmk_rc_cib_corrupt;
164  }
165 
166  rc = pcmk__xml_output_new(&out, xml);
167  if (rc != pcmk_rc_ok) {
168  cib_delete(cib);
169  return rc;
170  }
171 
175 
177  show_opts, NULL, NULL, NULL, false, 0);
178  pcmk__xml_output_finish(out, xml);
179 
180  cib_delete(cib);
181  return rc;
182 }
183 
219 int
221  enum pcmk__fence_history fence_history, uint32_t show,
222  uint32_t show_opts, const char *only_node, const char *only_rsc,
223  const char *neg_location_prefix, bool simple_output,
224  unsigned int timeout_ms)
225 {
226  xmlNode *current_cib = NULL;
227  int rc = pcmk_rc_ok;
228  stonith_t *stonith = NULL;
230  time_t last_updated = 0;
231 
232  if (cib == NULL) {
233  return ENOTCONN;
234  }
235 
236  if (cib->variant == cib_native) {
237  rc = pcmk__pacemakerd_status(out, crm_system_name, timeout_ms, false,
238  &pcmkd_state);
239  if (rc != pcmk_rc_ok) {
240  return rc;
241  }
242 
243  last_updated = time(NULL);
244 
245  switch (pcmkd_state) {
249  /* Fencer and CIB may still be available while shutting down or
250  * running on a Pacemaker Remote node
251  */
252  break;
253  default:
254  // Fencer and CIB are definitely unavailable
255  out->message(out, "pacemakerd-health",
256  NULL, pcmkd_state, NULL, last_updated);
257  return rc;
258  }
259 
260  if (fence_history != pcmk__fence_history_none) {
261  stonith = fencing_connect();
262  }
263  }
264 
265  rc = cib__signon_query(out, &cib, &current_cib);
266  if (rc != pcmk_rc_ok) {
267  if (pcmkd_state != pcmk_pacemakerd_state_invalid) {
268  // Invalid at this point means we didn't query the pcmkd state
269  out->message(out, "pacemakerd-health",
270  NULL, pcmkd_state, NULL, last_updated);
271  }
272  goto done;
273  }
274 
275  rc = pcmk__output_cluster_status(out, stonith, cib, current_cib,
276  pcmkd_state, fence_history, show,
277  show_opts, only_node, only_rsc,
278  neg_location_prefix, simple_output);
279  if (rc != pcmk_rc_ok) {
280  out->err(out, "Error outputting status info from the fencer or CIB");
281  }
282 
283 done:
284  stonith_api_delete(stonith);
285  free_xml(current_cib);
286  return pcmk_rc_ok;
287 }
288 
289 /* This is an internal-only function that is planned to be deprecated and removed.
290  * It should only ever be called from crm_mon.
291  */
292 int
294  const pe_working_set_t *data_set)
295 {
296  int nodes_online = 0;
297  int nodes_standby = 0;
298  int nodes_maintenance = 0;
299  GString *offline_nodes = NULL;
300  bool no_dc = false;
301  bool offline = false;
302  bool has_warnings = false;
303 
304  if (data_set->dc_node == NULL) {
305  has_warnings = true;
306  no_dc = true;
307  }
308 
309  for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
310  pe_node_t *node = (pe_node_t *) iter->data;
311 
312  if (node->details->standby && node->details->online) {
313  nodes_standby++;
314  } else if (node->details->maintenance && node->details->online) {
315  nodes_maintenance++;
316  } else if (node->details->online) {
317  nodes_online++;
318  } else {
319  pcmk__add_word(&offline_nodes, 1024, "offline node:");
320  pcmk__add_word(&offline_nodes, 0, pe__node_name(node));
321  has_warnings = true;
322  offline = true;
323  }
324  }
325 
326  if (has_warnings) {
327  out->info(out, "CLUSTER WARN: %s%s%s",
328  no_dc ? "No DC" : "",
329  no_dc && offline ? ", " : "",
330  (offline? (const char *) offline_nodes->str : ""));
331 
332  if (offline_nodes != NULL) {
333  g_string_free(offline_nodes, TRUE);
334  }
335 
336  } else {
337  char *nodes_standby_s = NULL;
338  char *nodes_maint_s = NULL;
339 
340  if (nodes_standby > 0) {
341  nodes_standby_s = crm_strdup_printf(", %d standby node%s", nodes_standby,
342  pcmk__plural_s(nodes_standby));
343  }
344 
345  if (nodes_maintenance > 0) {
346  nodes_maint_s = crm_strdup_printf(", %d maintenance node%s",
347  nodes_maintenance,
348  pcmk__plural_s(nodes_maintenance));
349  }
350 
351  out->info(out, "CLUSTER OK: %d node%s online%s%s, "
352  "%d resource instance%s configured",
353  nodes_online, pcmk__plural_s(nodes_online),
354  nodes_standby_s != NULL ? nodes_standby_s : "",
355  nodes_maint_s != NULL ? nodes_maint_s : "",
357 
358  free(nodes_standby_s);
359  free(nodes_maint_s);
360  }
361 
362  if (has_warnings) {
363  return pcmk_rc_error;
364  } else {
365  return pcmk_rc_ok;
366  }
367  /* coverity[leaked_storage] False positive */
368 }
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, unsigned int timeout_ms)
Definition: pcmk_status.c:220
Control output from tools.
void stonith__register_messages(pcmk__output_t *out)
Definition: st_output.c:598
cib_t * cib_new(void)
Create a new CIB connection object.
Definition: cib_client.c:535
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
Definition: cib_utils.c:745
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:863
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:148
crm_exit_t pcmk_rc2exitc(int rc)
Map a function return code to the most similar exit code.
Definition: results.c:689
int pcmk__pacemakerd_status(pcmk__output_t *out, const char *ipc_name, unsigned int message_timeout_ms, bool show_output, enum pcmk_pacemakerd_state *state)
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:488
void cib_delete(cib_t *cib)
Free all memory used by CIB connection.
Definition: cib_client.c:700
stonith_t * stonith_api_new(void)
Definition: st_client.c:1817
GList * nodes
Definition: pe_types.h:180
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:819
int pcmk__output_cluster_status(pcmk__output_t *out, stonith_t *stonith, cib_t *cib, xmlNode *current_cib, enum pcmk_pacemakerd_state pcmkd_state, 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:71
stonith_t * st
Definition: pcmk_fence.c:28
#define pcmk_section_all
Definition: output.h:49
int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml)
Definition: output.c:236
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:268
int(*) 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:2329
pe_working_set_t * data_set
void pcmk__unpack_constraints(pe_working_set_t *data_set)
int pcmk__output_simple_status(pcmk__output_t *out, const pe_working_set_t *data_set)
Definition: pcmk_status.c:293
gboolean standby
Definition: pe_types.h:237
void pe__register_messages(pcmk__output_t *out)
Definition: pe_output.c:3106
void free_xml(xmlNode *child)
Definition: xml.c:813
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:160
int cib__clean_up_connection(cib_t **cib)
Definition: cib_utils.c:799
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:831
pe_node_t * dc_node
Definition: pe_types.h:165
const char * localhost
Definition: pe_types.h:202
void stonith_api_delete(stonith_t *st)
Definition: st_client.c:1709
char * pcmk__our_nodename
Node name of the local node.
Definition: logging.c:48
#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 fencing history, optionally reducing it.
Definition: pcmk_fence.c:604
enum cib_variant variant
Definition: cib_types.h:206
#define pe__set_working_set_flags(working_set, flags_to_set)
Definition: internal.h:65
#define pcmk__plural_s(i)
gboolean maintenance
Definition: pe_types.h:245
void pcmk__xml_output_finish(pcmk__output_t *out, xmlNodePtr *xml)
Definition: output.c:258
int pcmk_status(xmlNodePtr *xml)
Output cluster status formatted like crm_mon --output-as=xml
Definition: pcmk_status.c:152
gboolean cli_config_update(xmlNode **xml, int *best_version, gboolean to_logs)
Definition: schemas.c:1197
gboolean online
Definition: pe_types.h:236