Skip to content

Commit

Permalink
Refactor: Implement crm_mon's one shot mode with a library function.
Browse files Browse the repository at this point in the history
First, add minimal static versions of cib_connect, fencing_connect, and
pacemakerd_status.  These functions do only as much as is necessary to
make a single request and display it.  In particular, there's nothing
about event callbacks and main loops beyond what is absolutely
necessary.  These versions are taken from what's already being done in
crm_mon, but cannot replace what's happening there.

Second, add a pcmk__output_cluster_status function.  This takes a bunch
of arguments and basically does what mon_refresh_display in crm_mon
does.

Third, add a pcmk__status function.  This basically does what the
existing one_shot function does - connect to the CIB and fencing if
required, call a function to do the display, and close connections
afterwards.

Having done this, one_shot can then just be turned into a wrapper around
pcmk__status that calls it, deals with error codes, and calls crm_mon's
clean_up function afterwards.
  • Loading branch information
clumens committed Feb 17, 2022
1 parent ffef7f5 commit 3f342e3
Show file tree
Hide file tree
Showing 3 changed files with 255 additions and 12 deletions.
15 changes: 15 additions & 0 deletions include/pcmki/pcmki_status.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@
#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" {
Expand All @@ -33,6 +38,16 @@ extern "C" {
*/
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, 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,
char *neg_location_prefix, bool simple_output);

#ifdef __cplusplus
}
#endif
Expand Down
234 changes: 234 additions & 0 deletions lib/pacemaker/pcmk_status.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

#include <crm_internal.h>

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include <crm/cib/internal.h>
#include <crm/common/output.h>
Expand All @@ -18,6 +20,238 @@
#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, cib_t *cib)
{
int rc = pcmk_rc_ok;
pcmk_ipc_api_t *pacemakerd_api = NULL;
enum pcmk_pacemakerd_state state = pcmk_pacemakerd_state_invalid;

if (cib != NULL &&
(cib->state == cib_connected_query ||
cib->state == cib_connected_command)) {
return rc;
}

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;
}

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, 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);
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);
}

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);

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_reset_working_set(data_set);
return rc;
}

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,
char *neg_location_prefix, bool simple_output)
{
xmlNode *current_cib = NULL;
int rc = pcmk_rc_ok;
stonith_t *st = NULL;

if (cib->variant == cib_native) {
rc = pacemakerd_status(out, cib);
}

if (rc != pcmk_rc_ok) {
return rc;
}

if (fence_history != pcmk__fence_history_none && cib->variant == cib_native) {
st = fencing_connect();

if (st == NULL) {
return ENOTCONN;
}
}

rc = cib_connect(out, cib, &current_cib);
if (rc != pcmk_rc_ok) {
cib__clean_up_connection(&cib);

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);

done:
if (st != NULL) {
if (st->state != stonith_disconnected) {
st->cmds->remove_notification(st, NULL);
st->cmds->disconnect(st);
}

stonith_api_delete(st);
}

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.
*/
Expand Down
18 changes: 6 additions & 12 deletions tools/crm_mon.c
Original file line number Diff line number Diff line change
Expand Up @@ -1366,22 +1366,16 @@ handle_connection_failures(int rc)
static void
one_shot(void)
{
int rc;
int rc = pcmk__status(out, cib, fence_history, show, show_opts,
options.only_node, options.only_rsc,
options.neg_location_prefix,
output_format == mon_output_monitor);

rc = pacemakerd_status();

if (rc == pcmk_rc_ok) {
fencing_connect();
rc = cib_connect(FALSE);
}

if (rc == pcmk_rc_ok) {
mon_refresh_display(NULL);
} else {
if (rc != pcmk_rc_ok) {
handle_connection_failures(rc);
}

clean_up(CRM_EX_OK);
clean_up(pcmk_rc2exitc(rc));
}

static void
Expand Down

0 comments on commit 3f342e3

Please sign in to comment.