Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/include/pcmki/pcmki_status.h b/include/pcmki/pcmki_status.h
index 6c4a7fbab3..2bbd099a7b 100644
--- a/include/pcmki/pcmki_status.h
+++ b/include/pcmki/pcmki_status.h
@@ -1,55 +1,59 @@
/*
* Copyright 2022 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#ifndef PCMK__PCMKI_PCMKI_STATUS__H
#define PCMK__PCMKI_PCMKI_STATUS__H
#include <stdbool.h>
#include <stdint.h>
#include <crm/cib/cib_types.h>
#include <crm/pengine/pe_types.h>
#include <crm/common/output_internal.h>
#include <pcmki/pcmki_fence.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* \internal
* \brief Print one-line status suitable for use with monitoring software
*
* \param[in] data_set Working set of CIB state
*
* \return Standard Pacemaker return code
*
* \note This function's output (and the return code when the program exits)
* should conform to https://www.monitoring-plugins.org/doc/guidelines.html
*
* \note This function is planned to be deprecated and then removed in the
* future. It should only be called from crm_mon, and no additional
* callers should be added.
*/
int pcmk__output_simple_status(pcmk__output_t *out, pe_working_set_t *data_set);
-int pcmk__output_cluster_status(pcmk__output_t *out, stonith_t *st, cib_t *cib,
- xmlNode *current_cib, enum pcmk__fence_history fence_history,
- uint32_t show, uint32_t show_opts, char *only_node,
- char *only_rsc, const char *neg_location_prefix,
+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);
-int pcmk__status(pcmk__output_t *out, cib_t *cib, enum pcmk__fence_history fence_history,
- uint32_t show, uint32_t show_opts, char *only_node, char *only_rsc,
- const char *neg_location_prefix, bool simple_output);
+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);
#ifdef __cplusplus
}
#endif
#endif
diff --git a/lib/pacemaker/pcmk_status.c b/lib/pacemaker/pcmk_status.c
index 80215d368e..6a795432ab 100644
--- a/lib/pacemaker/pcmk_status.c
+++ b/lib/pacemaker/pcmk_status.c
@@ -1,375 +1,434 @@
/*
* Copyright 2004-2022 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU General Public License version 2
* or later (GPLv2+) WITHOUT ANY WARRANTY.
*/
#include <crm_internal.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <crm/cib/internal.h>
#include <crm/common/output.h>
#include <crm/common/results.h>
#include <crm/fencing/internal.h>
#include <crm/stonith-ng.h>
#include <pacemaker.h>
#include <pacemaker-internal.h>
static int
cib_connect(pcmk__output_t *out, cib_t *cib, xmlNode **current_cib)
{
int rc = pcmk_rc_ok;
CRM_CHECK(cib != NULL, return EINVAL);
if (cib->state == cib_connected_query ||
cib->state == cib_connected_command) {
return rc;
}
crm_trace("Connecting to the CIB");
rc = cib->cmds->signon(cib, crm_system_name, cib_query);
rc = pcmk_legacy2rc(rc);
if (rc != pcmk_rc_ok) {
out->err(out, "Could not connect to the CIB: %s",
pcmk_rc_str(rc));
return rc;
}
rc = cib->cmds->query(cib, NULL, current_cib,
cib_scope_local | cib_sync_call);
rc = pcmk_legacy2rc(rc);
return rc;
}
static stonith_t *
fencing_connect(void)
{
stonith_t *st = stonith_api_new();
int rc = pcmk_rc_ok;
if (st == NULL) {
return NULL;
}
rc = st->cmds->connect(st, crm_system_name, NULL);
if (rc == pcmk_rc_ok) {
return st;
} else {
stonith_api_delete(st);
return NULL;
}
}
static void
pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
enum pcmk_ipc_event event_type, crm_exit_t status,
void *event_data, void *user_data)
{
pcmk_pacemakerd_api_reply_t *reply = event_data;
enum pcmk_pacemakerd_state *state =
(enum pcmk_pacemakerd_state *) user_data;
/* we are just interested in the latest reply */
*state = pcmk_pacemakerd_state_invalid;
if (event_type != pcmk_ipc_event_reply || status != CRM_EX_OK) {
return;
}
if (reply->reply_type == pcmk_pacemakerd_reply_ping &&
reply->data.ping.last_good != (time_t) 0 &&
reply->data.ping.status == pcmk_rc_ok) {
*state = reply->data.ping.state;
}
}
static int
pacemakerd_status(pcmk__output_t *out)
{
int rc = pcmk_rc_ok;
pcmk_ipc_api_t *pacemakerd_api = NULL;
enum pcmk_pacemakerd_state state = pcmk_pacemakerd_state_invalid;
rc = pcmk_new_ipc_api(&pacemakerd_api, pcmk_ipc_pacemakerd);
if (pacemakerd_api == NULL) {
out->err(out, "Could not connect to pacemakerd: %s",
pcmk_rc_str(rc));
return rc;
}
pcmk_register_ipc_callback(pacemakerd_api, pacemakerd_event_cb, (void *) &state);
rc = pcmk_connect_ipc(pacemakerd_api, pcmk_ipc_dispatch_sync);
if (rc == EREMOTEIO) {
return pcmk_rc_ok;
} else if (rc != pcmk_rc_ok) {
out->err(out, "Could not connect to pacemakerd: %s",
pcmk_rc_str(rc));
pcmk_free_ipc_api(pacemakerd_api);
return rc;
}
rc = pcmk_pacemakerd_api_ping(pacemakerd_api, crm_system_name);
if (rc != pcmk_rc_ok) {
/* Got some error from pcmk_pacemakerd_api_ping, so return it. */
} else if (state == pcmk_pacemakerd_state_running) {
rc = pcmk_rc_ok;
} else if (state == pcmk_pacemakerd_state_shutting_down) {
rc = ENOTCONN;
} else {
rc = EAGAIN;
}
pcmk_free_ipc_api(pacemakerd_api);
return rc;
}
+/*!
+ * \internal
+ * \brief Output the cluster status given a fencer and CIB connection
+ *
+ * \param[in,out] out Output object
+ * \param[in,out] stonith Fencer connection
+ * \param[in,out] cib CIB connection
+ * \param[in] current_cib Current CIB XML
+ * \param[in] fence_history How much of the fencing history to output
+ * \param[in] show Group of \p pcmk_section_e flags
+ * \param[in] show_opts Group of \p pcmk_show_opt_e flags
+ * \param[in] only_node If a node name or tag, include only the
+ * matching node(s) (if any) in the output.
+ * If \p "*" or \p NULL, include all nodes
+ * in the output.
+ * \param[in] only_rsc If a resource ID or tag, include only the
+ * matching resource(s) (if any) in the
+ * output. If \p "*" or \p NULL, include all
+ * resources in the output.
+ * \param[in] neg_location_prefix Prefix denoting a ban in a constraint ID
+ * \param[in] simple_output Whether to use a simple output format.
+ * Note: This is for use by \p crm_mon only
+ * and is planned to be deprecated.
+ *
+ * \return Standard Pacemaker return code
+ */
int
-pcmk__output_cluster_status(pcmk__output_t *out, stonith_t *st, cib_t *cib,
+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, char *only_node,
- char *only_rsc, const char *neg_location_prefix, bool simple_output)
+ uint32_t show, uint32_t show_opts,
+ const char *only_node, const char *only_rsc,
+ const char *neg_location_prefix, bool simple_output)
{
xmlNode *cib_copy = copy_xml(current_cib);
stonith_history_t *stonith_history = NULL;
int history_rc = 0;
pe_working_set_t *data_set = NULL;
GList *unames = NULL;
GList *resources = NULL;
int rc = pcmk_rc_ok;
if (cli_config_update(&cib_copy, NULL, FALSE) == FALSE) {
cib__clean_up_connection(&cib);
free_xml(cib_copy);
rc = pcmk_rc_schema_validation;
out->err(out, "Upgrade failed: %s", pcmk_rc_str(rc));
return rc;
}
/* get the stonith-history if there is evidence we need it */
if (fence_history != pcmk__fence_history_none) {
- history_rc = pcmk__get_fencing_history(st, &stonith_history, fence_history);
+ history_rc = pcmk__get_fencing_history(stonith, &stonith_history,
+ fence_history);
}
data_set = pe_new_working_set();
CRM_ASSERT(data_set != NULL);
pe__set_working_set_flags(data_set, pe_flag_no_compat);
data_set->input = cib_copy;
data_set->priv = out;
cluster_status(data_set);
/* Unpack constraints if any section will need them
* (tickets may be referenced in constraints but not granted yet,
* and bans need negative location constraints) */
if (pcmk_is_set(show, pcmk_section_bans) || pcmk_is_set(show, pcmk_section_tickets)) {
pcmk__unpack_constraints(data_set);
}
unames = pe__build_node_name_list(data_set, only_node);
resources = pe__build_rsc_list(data_set, only_rsc);
/* Always print DC if NULL. */
if (data_set->dc_node == NULL) {
show |= pcmk_section_dc;
}
if (simple_output) {
rc = pcmk__output_simple_status(out, data_set);
} else {
out->message(out, "cluster-status", data_set, pcmk_rc2exitc(history_rc),
stonith_history, fence_history, show, show_opts,
neg_location_prefix, unames, resources);
}
g_list_free_full(unames, free);
g_list_free_full(resources, free);
stonith_history_free(stonith_history);
stonith_history = NULL;
pe_free_working_set(data_set);
return rc;
}
int
pcmk_status(xmlNodePtr *xml)
{
cib_t *cib = NULL;
pcmk__output_t *out = NULL;
int rc = pcmk_rc_ok;
uint32_t show_opts = pcmk_show_pending | pcmk_show_inactive_rscs | pcmk_show_timing;
cib = cib_new();
if (cib == NULL) {
return pcmk_rc_cib_corrupt;
}
rc = pcmk__xml_output_new(&out, xml);
if (rc != pcmk_rc_ok) {
cib_delete(cib);
return rc;
}
pcmk__register_lib_messages(out);
pe__register_messages(out);
stonith__register_messages(out);
rc = pcmk__status(out, cib, pcmk__fence_history_full, pcmk_section_all,
show_opts, NULL, NULL, NULL, false);
pcmk__xml_output_finish(out, xml);
cib_delete(cib);
return rc;
}
+/*!
+ * \internal
+ * \brief Query and output the cluster status
+ *
+ * The operation is considered a success if we're able to get the \p pacemakerd
+ * state. If possible, we'll also try to connect to the fencer and CIB and
+ * output their respective status information.
+ *
+ * \param[in,out] out Output object
+ * \param[in,out] cib CIB connection
+ * \param[in] fence_history How much of the fencing history to output
+ * \param[in] show Group of \p pcmk_section_e flags
+ * \param[in] show_opts Group of \p pcmk_show_opt_e flags
+ * \param[in] only_node If a node name or tag, include only the
+ * matching node(s) (if any) in the output.
+ * If \p "*" or \p NULL, include all nodes
+ * in the output.
+ * \param[in] only_rsc If a resource ID or tag, include only the
+ * matching resource(s) (if any) in the
+ * output. If \p "*" or \p NULL, include all
+ * resources in the output.
+ * \param[in] neg_location_prefix Prefix denoting a ban in a constraint ID
+ * \param[in] simple_output Whether to use a simple output format.
+ * Note: This is for use by \p crm_mon only
+ * and is planned to be deprecated.
+ *
+ * \return Standard Pacemaker return code
+ */
int
-pcmk__status(pcmk__output_t *out, cib_t *cib, enum pcmk__fence_history fence_history,
- uint32_t show, uint32_t show_opts, char *only_node, char *only_rsc,
+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)
{
xmlNode *current_cib = NULL;
int rc = pcmk_rc_ok;
- stonith_t *st = NULL;
+ stonith_t *stonith = NULL;
if (cib == NULL) {
return ENOTCONN;
}
if (cib->variant == cib_native) {
if (cib->state == cib_connected_query || cib->state == cib_connected_command) {
rc = pcmk_rc_ok;
} else {
rc = pacemakerd_status(out);
}
}
if (rc != pcmk_rc_ok) {
return rc;
}
if (fence_history != pcmk__fence_history_none && cib->variant == cib_native) {
- st = fencing_connect();
+ stonith = fencing_connect();
- if (st == NULL) {
+ if (stonith == NULL) {
return ENOTCONN;
}
}
rc = cib_connect(out, cib, &current_cib);
if (rc != pcmk_rc_ok) {
goto done;
}
- rc = pcmk__output_cluster_status(out, st, cib, current_cib, fence_history, show, show_opts,
- only_node, only_rsc, neg_location_prefix, simple_output);
+ rc = pcmk__output_cluster_status(out, stonith, cib, current_cib,
+ fence_history, show, show_opts, only_node,
+ only_rsc, neg_location_prefix,
+ simple_output);
done:
- if (st != NULL) {
- if (st->state != stonith_disconnected) {
- st->cmds->remove_notification(st, NULL);
- st->cmds->disconnect(st);
+ if (stonith != NULL) {
+ if (stonith->state != stonith_disconnected) {
+ stonith->cmds->remove_notification(stonith, NULL);
+ stonith->cmds->disconnect(stonith);
}
- stonith_api_delete(st);
+ stonith_api_delete(stonith);
}
if (current_cib != NULL) {
free_xml(current_cib);
}
return rc;
}
/* This is an internal-only function that is planned to be deprecated and removed.
* It should only ever be called from crm_mon.
*/
int
pcmk__output_simple_status(pcmk__output_t *out, pe_working_set_t *data_set)
{
int nodes_online = 0;
int nodes_standby = 0;
int nodes_maintenance = 0;
GString *offline_nodes = NULL;
bool no_dc = false;
bool offline = false;
bool has_warnings = false;
if (data_set->dc_node == NULL) {
has_warnings = true;
no_dc = true;
}
for (GList *iter = data_set->nodes; iter != NULL; iter = iter->next) {
pe_node_t *node = (pe_node_t *) iter->data;
if (node->details->standby && node->details->online) {
nodes_standby++;
} else if (node->details->maintenance && node->details->online) {
nodes_maintenance++;
} else if (node->details->online) {
nodes_online++;
} else {
pcmk__add_word(&offline_nodes, 1024, "offline node:");
pcmk__add_word(&offline_nodes, 0, pe__node_name(node));
has_warnings = true;
offline = true;
}
}
if (has_warnings) {
out->info(out, "CLUSTER WARN: %s%s%s",
no_dc ? "No DC" : "",
no_dc && offline ? ", " : "",
(offline? (const char *) offline_nodes->str : ""));
if (offline_nodes != NULL) {
g_string_free(offline_nodes, TRUE);
}
} else {
char *nodes_standby_s = NULL;
char *nodes_maint_s = NULL;
if (nodes_standby > 0) {
nodes_standby_s = crm_strdup_printf(", %d standby node%s", nodes_standby,
pcmk__plural_s(nodes_standby));
}
if (nodes_maintenance > 0) {
nodes_maint_s = crm_strdup_printf(", %d maintenance node%s",
nodes_maintenance,
pcmk__plural_s(nodes_maintenance));
}
out->info(out, "CLUSTER OK: %d node%s online%s%s, "
"%d resource instance%s configured",
nodes_online, pcmk__plural_s(nodes_online),
nodes_standby_s != NULL ? nodes_standby_s : "",
nodes_maint_s != NULL ? nodes_maint_s : "",
data_set->ninstances, pcmk__plural_s(data_set->ninstances));
free(nodes_standby_s);
free(nodes_maint_s);
}
if (has_warnings) {
return pcmk_rc_error;
} else {
return pcmk_rc_ok;
}
/* coverity[leaked_storage] False positive */
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Sep 5, 9:20 AM (9 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2308631
Default Alt Text
(18 KB)

Event Timeline