Skip to content

Commit a7b4483

Browse files
committed
Feature: tools: Add -P to crmadmin to ping via pacemakerd-api
1 parent 97036e4 commit a7b4483

File tree

1 file changed

+150
-10
lines changed

1 file changed

+150
-10
lines changed

tools/crmadmin.c

Lines changed: 150 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
#include <crm/cib.h>
2121
#include <crm/msg_xml.h>
2222
#include <crm/common/xml.h>
23+
#include <crm/common/iso8601.h>
2324
#include <crm/common/ipc_controld.h>
25+
#include <crm/common/ipc_pacemakerd.h>
2426
#include <crm/common/mainloop.h>
2527

2628
#define DEFAULT_MESSAGE_TIMEOUT_MS 30000
@@ -31,6 +33,8 @@ static GMainLoop *mainloop = NULL;
3133

3234
bool do_work(pcmk_ipc_api_t *api);
3335
void do_find_node_list(xmlNode *xml_node);
36+
static char *ipc_name = NULL;
37+
3438
gboolean admin_message_timeout(gpointer data);
3539

3640
static enum {
@@ -40,6 +44,7 @@ static enum {
4044
cmd_elect_dc,
4145
cmd_whois_dc,
4246
cmd_list_nodes,
47+
cmd_pacemakerd_health,
4348
} command = cmd_none;
4449

4550
static gboolean BE_VERBOSE = FALSE;
@@ -81,6 +86,15 @@ static pcmk__cli_option_t long_options[] = {
8186
"can be useful for debugging\n",
8287
pcmk__option_default
8388
},
89+
{
90+
"pacemakerd", no_argument, NULL, 'P',
91+
"Display the status of local pacemakerd.", pcmk__option_default
92+
},
93+
{
94+
"-spacer-", no_argument, NULL, '-',
95+
"\n\tResult is the state of the sub-daemons watched by pacemakerd.\n",
96+
pcmk__option_default
97+
},
8498
{
8599
"dc_lookup", no_argument, NULL, 'D',
86100
"Display the uname of the node co-ordinating the cluster.",
@@ -122,16 +136,20 @@ static pcmk__cli_option_t long_options[] = {
122136
{
123137
"bash-export", no_argument, NULL, 'B',
124138
"Display nodes as shell commands of the form 'export uname=uuid' "
125-
"(valid with -N/--nodes)'\n",
139+
"(valid with -N/--nodes)",
126140
pcmk__option_default
127141
},
142+
{
143+
"ipc-name", required_argument, NULL, 'i',
144+
"Name to use for ipc instead of 'crmadmin'.", pcmk__option_default
145+
},
128146
{
129147
"-spacer-", no_argument, NULL, '-',
130-
"Notes:", pcmk__option_default
148+
"\nNotes:", pcmk__option_default
131149
},
132150
{
133151
"-spacer-", no_argument, NULL, '-',
134-
"The -K and -E commands do not work and may be removed in a future "
152+
"\nThe -K and -E commands do not work and may be removed in a future "
135153
"version.",
136154
pcmk__option_default
137155
},
@@ -223,6 +241,88 @@ controller_event_cb(pcmk_ipc_api_t *controld_api,
223241
quit_main_loop(exit_code);
224242
}
225243

244+
static void
245+
pacemakerd_event_cb(pcmk_ipc_api_t *pacemakerd_api,
246+
enum pcmk_ipc_event event_type, crm_exit_t status,
247+
void *event_data, void *user_data)
248+
{
249+
pcmk_pacemakerd_api_reply_t *reply = event_data;
250+
251+
switch (event_type) {
252+
case pcmk_ipc_event_disconnect:
253+
if (exit_code == CRM_EX_DISCONNECT) { // Unexpected
254+
fprintf(stderr, "error: Lost connection to pacemakerd\n");
255+
}
256+
goto done;
257+
break;
258+
259+
case pcmk_ipc_event_reply:
260+
break;
261+
262+
default:
263+
return;
264+
}
265+
266+
if (message_timer_id != 0) {
267+
g_source_remove(message_timer_id);
268+
message_timer_id = 0;
269+
}
270+
271+
if (status != CRM_EX_OK) {
272+
fprintf(stderr, "error: Bad reply from pacemakerd: %s",
273+
crm_exit_str(status));
274+
exit_code = status;
275+
goto done;
276+
}
277+
278+
if (reply->reply_type != pcmk_pacemakerd_reply_ping) {
279+
fprintf(stderr, "error: Unknown reply type %d from pacemakerd\n",
280+
reply->reply_type);
281+
goto done;
282+
}
283+
284+
// Parse desired information from reply
285+
switch (command) {
286+
case cmd_pacemakerd_health:
287+
{
288+
crm_time_t *crm_when = crm_time_new(NULL);
289+
char *pinged_buf = NULL;
290+
291+
crm_time_set_timet(crm_when, &reply->data.ping.last_good);
292+
pinged_buf = crm_time_as_string(crm_when,
293+
crm_time_log_date | crm_time_log_timeofday |
294+
crm_time_log_with_timezone);
295+
296+
printf("Status of %s: '%s' %s %s\n",
297+
reply->data.ping.sys_from,
298+
(reply->data.ping.status == pcmk_rc_ok)?
299+
pcmk_pacemakerd_api_pacemakerd_state_enum2text(
300+
reply->data.ping.state):"query failed",
301+
(reply->data.ping.status == pcmk_rc_ok)?"last updated":"",
302+
(reply->data.ping.status == pcmk_rc_ok)?pinged_buf:"");
303+
if (BE_SILENT &&
304+
(reply->data.ping.state != pcmk_pacemakerd_state_invalid)) {
305+
fprintf(stderr, "%s\n",
306+
(reply->data.ping.status == pcmk_rc_ok)?
307+
pcmk_pacemakerd_api_pacemakerd_state_enum2text(
308+
reply->data.ping.state):
309+
"query failed");
310+
}
311+
exit_code = CRM_EX_OK;
312+
free(pinged_buf);
313+
}
314+
break;
315+
316+
default: // Not really possible here
317+
exit_code = CRM_EX_SOFTWARE;
318+
break;
319+
}
320+
321+
done:
322+
pcmk_disconnect_ipc(pacemakerd_api);
323+
quit_main_loop(exit_code);
324+
}
325+
226326
// \return Standard Pacemaker return code
227327
static int
228328
list_nodes()
@@ -257,7 +357,9 @@ main(int argc, char **argv)
257357
int flag;
258358
int rc;
259359
pcmk_ipc_api_t *controld_api = NULL;
360+
pcmk_ipc_api_t *pacemakerd_api = NULL;
260361
bool need_controld_api = true;
362+
bool need_pacemakerd_api = false;
261363

262364
crm_log_cli_init("crmadmin");
263365
pcmk__set_cli_options(NULL, "<command> [options]", long_options,
@@ -282,7 +384,9 @@ main(int argc, char **argv)
282384
message_timeout_ms = DEFAULT_MESSAGE_TIMEOUT_MS;
283385
}
284386
break;
285-
387+
case 'i':
388+
ipc_name = strdup(optarg);
389+
break;
286390
case '$':
287391
case '?':
288392
pcmk__cli_help(flag, CRM_EX_OK);
@@ -304,6 +408,11 @@ main(int argc, char **argv)
304408
case 'q':
305409
BE_SILENT = TRUE;
306410
break;
411+
case 'P':
412+
command = cmd_pacemakerd_health;
413+
need_pacemakerd_api = true;
414+
need_controld_api = false;
415+
break;
307416
case 'S':
308417
command = cmd_health;
309418
crm_trace("Option %c => %s", flag, optarg);
@@ -369,7 +478,26 @@ main(int argc, char **argv)
369478
}
370479
}
371480

372-
if (do_work(controld_api)) {
481+
// Connect to pacemakerd if needed
482+
if (need_pacemakerd_api) {
483+
rc = pcmk_new_ipc_api(&pacemakerd_api, pcmk_ipc_pacemakerd);
484+
if (pacemakerd_api == NULL) {
485+
fprintf(stderr, "error: Could not connect to pacemakerd: %s\n",
486+
pcmk_rc_str(rc));
487+
exit_code = pcmk_rc2exitc(rc);
488+
goto done;
489+
}
490+
pcmk_register_ipc_callback(pacemakerd_api, pacemakerd_event_cb, NULL);
491+
rc = pcmk_connect_ipc(pacemakerd_api, pcmk_ipc_dispatch_main);
492+
if (rc != pcmk_rc_ok) {
493+
fprintf(stderr, "error: Could not connect to pacemakerd: %s\n",
494+
pcmk_rc_str(rc));
495+
exit_code = pcmk_rc2exitc(rc);
496+
goto done;
497+
}
498+
}
499+
500+
if (do_work(controld_api?controld_api:pacemakerd_api)) {
373501
// A reply is needed from controller, so run main loop to get it
374502
exit_code = CRM_EX_DISCONNECT; // For unexpected disconnects
375503
mainloop = g_main_loop_new(NULL, FALSE);
@@ -379,12 +507,19 @@ main(int argc, char **argv)
379507
}
380508

381509
done:
510+
382511
if (controld_api != NULL) {
383512
pcmk_ipc_api_t *capi = controld_api;
384-
385513
controld_api = NULL; // Ensure we can't free this twice
386514
pcmk_free_ipc_api(capi);
387515
}
516+
517+
if (pacemakerd_api != NULL) {
518+
pcmk_ipc_api_t *capi = pacemakerd_api;
519+
pacemakerd_api = NULL; // Ensure we can't free this twice
520+
pcmk_free_ipc_api(capi);
521+
}
522+
388523
if (mainloop != NULL) {
389524
g_main_loop_unref(mainloop);
390525
mainloop = NULL;
@@ -394,30 +529,35 @@ main(int argc, char **argv)
394529

395530
// \return True if reply from controller is needed
396531
bool
397-
do_work(pcmk_ipc_api_t *controld_api)
532+
do_work(pcmk_ipc_api_t *api)
398533
{
399534
bool need_reply = false;
400535
int rc = pcmk_rc_ok;
401536

402537
switch (command) {
403538
case cmd_shutdown:
404-
rc = pcmk_controld_api_shutdown(controld_api, dest_node);
539+
rc = pcmk_controld_api_shutdown(api, dest_node);
405540
break;
406541

407542
case cmd_health: // dest_node != NULL
408543
case cmd_whois_dc: // dest_node == NULL
409-
rc = pcmk_controld_api_ping(controld_api, dest_node);
544+
rc = pcmk_controld_api_ping(api, dest_node);
410545
need_reply = true;
411546
break;
412547

413548
case cmd_elect_dc:
414-
rc = pcmk_controld_api_start_election(controld_api);
549+
rc = pcmk_controld_api_start_election(api);
415550
break;
416551

417552
case cmd_list_nodes:
418553
rc = list_nodes();
419554
break;
420555

556+
case cmd_pacemakerd_health:
557+
rc = pcmk_pacemakerd_api_ping(api, ipc_name);
558+
need_reply = true;
559+
break;
560+
421561
case cmd_none: // not actually possible here
422562
break;
423563
}

0 commit comments

Comments
 (0)