pacemaker  2.1.7-0f7f88312f
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/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 {
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 {
40  return NULL;
41  }
42 }
43 
71 int
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;
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) {
91  free_xml(cib_copy);
93  out->err(out, "Upgrade failed: %s", pcmk_rc_str(rc));
94  return rc;
95  }
96 
97  /* get the stonith-history if there is evidence we need it */
98  if (fence_history != pcmk__fence_history_none) {
99  history_rc = pcmk__get_fencing_history(stonith, &stonith_history,
100  fence_history);
101  }
102 
104  CRM_ASSERT(scheduler != NULL);
106 
107  scheduler->input = cib_copy;
108  scheduler->priv = out;
110 
111  if ((cib->variant == cib_native) && pcmk_is_set(show, pcmk_section_times)) {
112  if (pcmk__our_nodename == NULL) {
113  // Currently used only in the times section
114  pcmk__query_node_name(out, 0, &pcmk__our_nodename, 0);
115  }
117  }
118 
119  /* Unpack constraints if any section will need them
120  * (tickets may be referenced in constraints but not granted yet,
121  * and bans need negative location constraints) */
122  if (pcmk_is_set(show, pcmk_section_bans)
123  || pcmk_is_set(show, pcmk_section_tickets)) {
125  }
126 
127  unames = pe__build_node_name_list(scheduler, only_node);
128  resources = pe__build_rsc_list(scheduler, only_rsc);
129 
130  /* Always print DC if NULL. */
131  if (scheduler->dc_node == NULL) {
132  show |= pcmk_section_dc;
133  }
134 
135  if (simple_output) {
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;
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
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 
179 
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 
223 int
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;
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) {
253  /* Fencer and CIB may still be available while shutting down or
254  * running on a Pacemaker Remote node
255  */
256  break;
257  default:
258  // Fencer and CIB are definitely unavailable
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, &current_cib);
270  if (rc != pcmk_rc_ok) {
271  if (pcmkd_state != pcmk_pacemakerd_state_invalid) {
272  // Invalid at this point means we didn't query the pcmkd state
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 
304 int
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 : "",
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  /* coverity[leaked_storage] False positive */
381 }
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:224
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:605
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
Definition: cib_utils.c:1022
int(* message)(pcmk__output_t *out, const char *message_id,...)
pcmk__fence_history
Control how much of the fencing history is output.
Definition: pcmki_fence.h:18
crm_exit_t pcmk_rc2exitc(int rc)
Map a function return code to the most similar exit code.
Definition: results.c:702
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)
#define pe__set_working_set_flags(scheduler, flags_to_set)
Definition: internal.h:52
High Level API.
char * crm_system_name
Definition: utils.c:51
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
GList * pe__build_rsc_list(pcmk_scheduler_t *scheduler, const char *s)
Definition: utils.c:834
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:501
Implementation of pcmk_scheduler_t.
Definition: scheduler.h:172
gboolean cluster_status(pcmk_scheduler_t *scheduler)
Definition: status.c:71
void cib_delete(cib_t *cib)
Free all memory used by CIB connection.
Definition: cib_client.c:778
stonith_t * stonith_api_new(void)
Definition: st_client.c:1828
int ninstances
Total number of resource instances.
Definition: scheduler.h:224
GList * nodes
Nodes in cluster.
Definition: scheduler.h:195
xmlNode * copy_xml(xmlNode *src_node)
Definition: xml.c:789
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:72
stonith_t * st
Definition: pcmk_fence.c:28
void pcmk__unpack_constraints(pcmk_scheduler_t *scheduler)
#define pcmk_section_all
Definition: output.h:49
int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml)
Definition: output.c:236
void * priv
For Pacemaker use only.
Definition: scheduler.h:229
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:99
struct pe_node_shared_s * details
Basic node information.
Definition: nodes.h:134
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:2403
int pcmk__output_simple_status(pcmk__output_t *out, const pcmk_scheduler_t *scheduler)
Definition: pcmk_status.c:305
gboolean standby
Whether in standby mode.
Definition: nodes.h:73
GList * pe__build_node_name_list(pcmk_scheduler_t *scheduler, const char *s)
Definition: utils.c:801
void pe__register_messages(pcmk__output_t *out)
Definition: pe_output.c:3162
void free_xml(xmlNode *child)
Definition: xml.c:783
int(* connect)(stonith_t *st, const char *name, int *stonith_fd)
Connect to the local fencer.
Definition: stonith-ng.h:169
Implementation of pcmk_node_t.
Definition: nodes.h:130
xmlNode * input
CIB XML.
Definition: scheduler.h:175
int cib__clean_up_connection(cib_t **cib)
Definition: cib_utils.c:1076
pcmk_scheduler_t * pe_new_working_set(void)
Create a new object to hold scheduler data.
Definition: status.c:34
Function and executable result codes.
pcmk_pacemakerd_state
void pe_free_working_set(pcmk_scheduler_t *scheduler)
Free scheduler data.
Definition: status.c:50
const char * localhost
Definition: scheduler.h:216
void stonith_api_delete(stonith_t *st)
Definition: st_client.c:1720
pcmk_scheduler_t * scheduler
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
void stonith_history_free(stonith_history_t *history)
Definition: st_client.c:759
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:612
enum cib_variant variant
Definition: cib_types.h:332
#define pcmk__plural_s(i)
gboolean maintenance
Whether in maintenance mode.
Definition: nodes.h:81
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:154
gboolean cli_config_update(xmlNode **xml, int *best_version, gboolean to_logs)
Definition: schemas.c:1134
pcmk_node_t * dc_node
Node object for DC.
Definition: scheduler.h:178
gboolean online
Whether online.
Definition: nodes.h:72