Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3687184
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/crm/admin/crmadmin.c b/crm/admin/crmadmin.c
index f46a015295..f31afdeff1 100644
--- a/crm/admin/crmadmin.c
+++ b/crm/admin/crmadmin.c
@@ -1,738 +1,728 @@
-/* $Id: crmadmin.c,v 1.67 2006/04/20 10:55:22 andrew Exp $ */
+/* $Id: crmadmin.c,v 1.68 2006/04/26 13:32:52 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <portability.h>
#include <sys/param.h>
#include <crm/crm.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <heartbeat.h>
#include <hb_api.h>
#include <clplumbing/uids.h>
#include <clplumbing/Gmain_timeout.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/common/ctrl.h>
#include <crm/common/ipc.h>
#include <crm/pengine/pengine.h>
#include <crm/pengine/pe_utils.h>
#include <crm/cib.h>
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif
#include <crm/dmalloc_wrapper.h>
int message_timer_id = -1;
int message_timeout_ms = 30*1000;
GMainLoop *mainloop = NULL;
IPC_Channel *crmd_channel = NULL;
char *admin_uuid = NULL;
void usage(const char *cmd, int exit_status);
ll_cluster_t *do_init(void);
int do_work(ll_cluster_t * hb_cluster);
void crmd_ipc_connection_destroy(gpointer user_data);
gboolean admin_msg_callback(IPC_Channel * source_data, void *private_data);
char *pluralSection(const char *a_section);
crm_data_t *handleCibMod(void);
int do_find_node_list(crm_data_t *xml_node);
gboolean admin_message_timeout(gpointer data);
gboolean is_node_online(crm_data_t *node_state);
enum debug {
debug_none,
debug_dec,
debug_inc
};
gboolean BE_VERBOSE = FALSE;
int expected_responses = 1;
gboolean BASH_EXPORT = FALSE;
gboolean DO_HEALTH = FALSE;
gboolean DO_RESET = FALSE;
gboolean DO_RESOURCE = FALSE;
gboolean DO_ELECT_DC = FALSE;
gboolean DO_WHOIS_DC = FALSE;
gboolean DO_NODE_LIST = FALSE;
gboolean BE_SILENT = FALSE;
gboolean DO_RESOURCE_LIST = FALSE;
enum debug DO_DEBUG = debug_none;
const char *crmd_operation = NULL;
crm_data_t *msg_options = NULL;
const char *standby_on_off = "on";
const char *admin_verbose = XML_BOOLEAN_FALSE;
char *id = NULL;
char *this_msg_reference = NULL;
char *disconnect = NULL;
char *dest_node = NULL;
char *rsc_name = NULL;
char *crm_option = NULL;
int operation_status = 0;
const char *sys_to = NULL;
const char *crm_system_name = NULL;
#define OPTARGS "V?K:S:HE:Dd:i:RNqt:B"
int
main(int argc, char **argv)
{
int argerr = 0;
int flag;
ll_cluster_t *hb_cluster = NULL;
#ifdef HAVE_GETOPT_H
int option_index = 0;
static struct option long_options[] = {
/* Top-level Options */
{"verbose", 0, 0, 'V'},
{"help", 0, 0, '?'},
{"quiet", 0, 0, 'q'},
{"reference", 1, 0, 0},
{XML_ATTR_TIMEOUT, 1, 0, 't'},
{"bash-export", 0, 0, 'B'},
/* daemon options */
{"kill", 1, 0, 'K'}, /* stop a node */
{"die", 0, 0, 0}, /* kill a node, no respawn */
{"debug_inc", 1, 0, 'i'},
{"debug_dec", 1, 0, 'd'},
{"status", 1, 0, 'S'},
{"standby", 1, 0, 's'},
{"active", 1, 0, 'a'},
{"health", 0, 0, 'H'},
{"election", 0, 0, 'E'},
{"dc_lookup", 0, 0, 'D'},
{"nodes", 0, 0, 'N'},
{"option", 1, 0, 'o'},
{0, 0, 0, 0}
};
#endif
crm_system_name = basename(argv[0]);
crm_log_init(crm_system_name);
if(argc < 2) {
usage(crm_system_name, LSB_EXIT_EINVAL);
}
while (1) {
#ifdef HAVE_GETOPT_H
flag = getopt_long(argc, argv, OPTARGS,
long_options, &option_index);
#else
flag = getopt(argc, argv, OPTARGS);
#endif
if (flag == -1)
break;
switch(flag) {
#ifdef HAVE_GETOPT_H
case 0:
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
if (strcmp("reference",
long_options[option_index].name) == 0) {
this_msg_reference =
crm_strdup(optarg);
} else if (strcmp("die",
long_options[option_index].name) == 0) {
DO_RESET = TRUE;
crmd_operation = CRM_OP_DIE;
} else {
printf( "?? Long option (--%s) is not yet properly supported ??\n",
long_options[option_index].name);
++argerr;
}
break;
#endif
/* a sample test for multiple instance
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
*/
case 'V':
BE_VERBOSE = TRUE;
admin_verbose = XML_BOOLEAN_TRUE;
cl_log_enable_stderr(TRUE);
alter_debug(DEBUG_INC);
break;
case 't':
message_timeout_ms = atoi(optarg);
if(message_timeout_ms < 1) {
message_timeout_ms = 30*1000;
}
break;
case '?':
usage(crm_system_name, LSB_EXIT_OK);
break;
case 'D':
DO_WHOIS_DC = TRUE;
break;
case 'B':
BASH_EXPORT = TRUE;
break;
case 'K':
DO_RESET = TRUE;
crm_debug_2("Option %c => %s", flag, optarg);
dest_node = crm_strdup(optarg);
crmd_operation = CRM_OP_LOCAL_SHUTDOWN;
break;
case 'q':
BE_SILENT = TRUE;
break;
case 'i':
DO_DEBUG = debug_inc;
crm_debug_2("Option %c => %s", flag, optarg);
dest_node = crm_strdup(optarg);
break;
case 'd':
DO_DEBUG = debug_dec;
crm_debug_2("Option %c => %s", flag, optarg);
dest_node = crm_strdup(optarg);
break;
case 'S':
DO_HEALTH = TRUE;
crm_debug_2("Option %c => %s", flag, optarg);
dest_node = crm_strdup(optarg);
break;
case 'E':
DO_ELECT_DC = TRUE;
break;
case 'N':
DO_NODE_LIST = TRUE;
break;
case 'H':
DO_HEALTH = TRUE;
break;
default:
printf("Argument code 0%o (%c) is not (?yet?) supported\n", flag, flag);
++argerr;
break;
}
}
if (optind < argc) {
printf("non-option ARGV-elements: ");
while (optind < argc)
printf("%s ", argv[optind++]);
printf("\n");
}
if (optind > argc) {
++argerr;
}
if (argerr) {
usage(crm_system_name, LSB_EXIT_GENERIC);
}
hb_cluster = do_init();
if (hb_cluster != NULL) {
int res = do_work(hb_cluster);
if (res >= 0) {
/* wait for the reply by creating a mainloop and running it until
* the callbacks are invoked...
*/
mainloop = g_main_new(FALSE);
expected_responses++;
if(res == 0) {
crm_debug_2("no reply expected,"
" wait for the hello message only");
} else {
crm_debug_2("Waiting for reply from the local CRM");
}
message_timer_id = Gmain_timeout_add(
message_timeout_ms, admin_message_timeout, NULL);
g_main_run(mainloop);
return_to_orig_privs();
} else {
crm_err("No message to send");
operation_status = -1;
}
} else {
crm_warn("Init failed, could not perform requested operations");
operation_status = -2;
}
crm_debug_2("%s exiting normally", crm_system_name);
return operation_status;
}
int
do_work(ll_cluster_t * hb_cluster)
{
int ret = 1;
/* construct the request */
crm_data_t *msg_data = NULL;
gboolean all_is_good = TRUE;
msg_options = create_xml_node(NULL, XML_TAG_OPTIONS);
crm_xml_add(msg_options, XML_ATTR_VERBOSE, admin_verbose);
crm_xml_add(msg_options, XML_ATTR_TIMEOUT, "0");
if (DO_HEALTH == TRUE) {
crm_debug_2("Querying the system");
sys_to = CRM_SYSTEM_DC;
if (dest_node != NULL) {
sys_to = CRM_SYSTEM_CRMD;
crmd_operation = CRM_OP_PING;
if (BE_VERBOSE) {
expected_responses = -1;/* wait until timeout instead */
}
crm_xml_add(msg_options, XML_ATTR_TIMEOUT, "0");
} else {
crm_info("Cluster-wide health not available yet");
all_is_good = FALSE;
}
} else if(DO_ELECT_DC) {
/* tell the local node to initiate an election */
sys_to = CRM_SYSTEM_CRMD;
crmd_operation = CRM_OP_VOTE;
crm_xml_add(msg_options, XML_ATTR_TIMEOUT, "0");
dest_node = NULL;
ret = 0; /* no return message */
} else if(DO_WHOIS_DC) {
sys_to = CRM_SYSTEM_DC;
crmd_operation = CRM_OP_PING;
crm_xml_add(msg_options, XML_ATTR_TIMEOUT, "0");
dest_node = NULL;
} else if(DO_NODE_LIST) {
cib_t * the_cib = cib_new();
crm_data_t *output = NULL;
enum cib_errors rc = the_cib->cmds->signon(
the_cib, crm_system_name, cib_command_synchronous);
if(rc != cib_ok) {
return -1;
}
output = get_cib_copy(the_cib);
do_find_node_list(output);
free_xml(output);
the_cib->cmds->signoff(the_cib);
exit(rc);
} else if(DO_RESET) {
/* tell dest_node to initiate the shutdown proceedure
*
* if dest_node is NULL, the request will be sent to the
* local node
*/
sys_to = CRM_SYSTEM_CRMD;
crm_xml_add(msg_options, XML_ATTR_TIMEOUT, "0");
ret = 0; /* no return message */
} else if(DO_DEBUG == debug_inc) {
/* tell dest_node to increase its debug level
*
* if dest_node is NULL, the request will be sent to the
* local node
*/
sys_to = CRM_SYSTEM_CRMD;
crmd_operation = CRM_OP_DEBUG_UP;
ret = 0; /* no return message */
} else if(DO_DEBUG == debug_dec) {
/* tell dest_node to increase its debug level
*
* if dest_node is NULL, the request will be sent to the
* local node
*/
sys_to = CRM_SYSTEM_CRMD;
crmd_operation = CRM_OP_DEBUG_DOWN;
ret = 0; /* no return message */
} else {
crm_err("Unknown options");
all_is_good = FALSE;
}
if(all_is_good == FALSE) {
crm_err("Creation of request failed. No message to send");
return -1;
}
/* send it */
if (crmd_channel == NULL) {
crm_err("The IPC connection is not valid, cannot send anything");
return -1;
}
if(sys_to == NULL) {
if (dest_node != NULL)
sys_to = CRM_SYSTEM_CRMD;
else
sys_to = CRM_SYSTEM_DC;
}
{
HA_Message *cmd = create_request(
crmd_operation, msg_data, dest_node, sys_to,
crm_system_name, admin_uuid);
if(this_msg_reference != NULL) {
ha_msg_mod(cmd, XML_ATTR_REFERENCE, this_msg_reference);
}
send_ipc_message(crmd_channel, cmd);
}
return ret;
}
void
crmd_ipc_connection_destroy(gpointer user_data)
{
crm_info("Connection to CRMd was terminated");
exit(1);
}
ll_cluster_t *
do_init(void)
{
int facility;
GCHSource *src = NULL;
ll_cluster_t *hb_cluster = NULL;
/* change the logging facility to the one used by heartbeat daemon */
hb_cluster = ll_cluster_new("heartbeat");
crm_debug_2("Switching to Heartbeat logger");
if (( facility =
hb_cluster->llc_ops->get_logfacility(hb_cluster)) > 0) {
cl_log_set_facility(facility);
}
crm_malloc0(admin_uuid, sizeof(char) * 11);
if(admin_uuid != NULL) {
snprintf(admin_uuid, 10, "%d", getpid());
admin_uuid[10] = '\0';
}
src = init_client_ipc_comms(
CRM_SYSTEM_CRMD, admin_msg_callback, NULL, &crmd_channel);
if(DO_RESOURCE || DO_RESOURCE_LIST || DO_NODE_LIST) {
return hb_cluster;
} else if(crmd_channel != NULL) {
send_hello_message(
crmd_channel, admin_uuid, crm_system_name,"0", "1");
set_IPC_Channel_dnotify(src, crmd_ipc_connection_destroy);
return hb_cluster;
}
return NULL;
}
gboolean
admin_msg_callback(IPC_Channel * server, void *private_data)
{
int lpc = 0;
IPC_Message *msg = NULL;
ha_msg_input_t *new_input = NULL;
gboolean hack_return_good = TRUE;
static int received_responses = 0;
char *filename = NULL;
int filename_len = 0;
const char *result = NULL;
Gmain_timeout_remove(message_timer_id);
while (server->ch_status != IPC_DISCONNECT
&& server->ops->is_message_pending(server) == TRUE) {
if(new_input != NULL) {
delete_ha_msg_input(new_input);
}
if (server->ops->recv(server, &msg) != IPC_OK) {
perror("Receive failure:");
return !hack_return_good;
}
if (msg == NULL) {
crm_debug_4("No message this time");
continue;
}
lpc++;
received_responses++;
new_input = new_ipc_msg_input(msg);
crm_log_message(LOG_MSG, new_input->msg);
msg->msg_done(msg);
if (new_input->xml == NULL) {
crm_info("XML in IPC message was not valid... "
"discarding.");
continue;
} else if (validate_crm_message(
new_input->msg, crm_system_name, admin_uuid,
XML_ATTR_RESPONSE) == FALSE) {
crm_debug_2("Message was not a CRM response. Discarding.");
continue;
}
result = cl_get_string(new_input->msg, XML_ATTR_RESULT);
if(result == NULL || strcmp(result, "ok") == 0) {
result = "pass";
} else {
result = "fail";
}
if(DO_HEALTH) {
const char *state = crm_element_value(
new_input->xml, "crmd_state");
printf("Status of %s@%s: %s (%s)\n",
crm_element_value(new_input->xml,XML_PING_ATTR_SYSFROM),
cl_get_string(new_input->msg, F_CRM_HOST_FROM),
state,
crm_element_value(new_input->xml,XML_PING_ATTR_STATUS));
if(BE_SILENT && state != NULL) {
fprintf(stderr, "%s\n", state);
}
} else if(DO_WHOIS_DC) {
const char *dc = cl_get_string(
new_input->msg, F_CRM_HOST_FROM);
printf("Designated Controller is: %s\n", dc);
if(BE_SILENT && dc != NULL) {
fprintf(stderr, "%s\n", dc);
}
}
if (this_msg_reference != NULL) {
/* in testing mode... */
/* 31 = "test-_.xml" + an_int_as_string + '\0' */
filename_len = 31 + strlen(this_msg_reference);
crm_malloc0(filename, sizeof(char) * filename_len);
if(filename != NULL) {
sprintf(filename, "%s-%s_%d.xml",
result, this_msg_reference,
received_responses);
filename[filename_len - 1] = '\0';
if (0 > write_xml_file(
new_input->xml, filename, FALSE)) {
crm_crit("Could not save response to"
" %s", filename);
}
}
}
}
if (server->ch_status == IPC_DISCONNECT) {
crm_debug_2("admin_msg_callback: received HUP");
return !hack_return_good;
}
if (received_responses >= expected_responses) {
crm_debug_2(
"Recieved expected number (%d) of messages from Heartbeat."
" Exiting normally.", expected_responses);
g_main_quit(mainloop);
return !hack_return_good;
}
message_timer_id = Gmain_timeout_add(
message_timeout_ms, admin_message_timeout, NULL);
return hack_return_good;
}
gboolean
admin_message_timeout(gpointer data)
{
fprintf(stderr, "No messages received in %d seconds.. aborting\n",
(int)message_timeout_ms/1000);
crm_err("No messages received in %d seconds",
(int)message_timeout_ms/1000);
g_main_quit(mainloop);
return FALSE;
}
gboolean
is_node_online(crm_data_t *node_state)
{
const char *uname = crm_element_value(node_state,XML_ATTR_UNAME);
const char *join_state = crm_element_value(node_state,XML_CIB_ATTR_JOINSTATE);
const char *exp_state = crm_element_value(node_state,XML_CIB_ATTR_EXPSTATE);
const char *crm_state = crm_element_value(node_state,XML_CIB_ATTR_CRMDSTATE);
const char *ha_state = crm_element_value(node_state,XML_CIB_ATTR_HASTATE);
const char *ccm_state = crm_element_value(node_state,XML_CIB_ATTR_INCCM);
if(safe_str_neq(join_state, CRMD_JOINSTATE_DOWN)
&& (ha_state == NULL || safe_str_eq(ha_state, ACTIVESTATUS))
&& crm_is_true(ccm_state)
&& safe_str_eq(crm_state, ONLINESTATUS)) {
crm_debug_3("Node %s is online", uname);
return TRUE;
}
crm_debug_3("Node %s: ha=%s ccm=%s join=%s exp=%s crm=%s",
uname, crm_str(ha_state), crm_str(ccm_state),
crm_str(join_state), crm_str(exp_state),
crm_str(crm_state));
crm_debug_3("Node %s is offline", uname);
return FALSE;
}
int
do_find_node_list(crm_data_t *xml_node)
{
int found = 0;
crm_data_t *nodes = get_object_root(XML_CIB_TAG_NODES, xml_node);
xml_child_iter_filter(
nodes, node, XML_CIB_TAG_NODE,
if(BASH_EXPORT) {
printf("export %s=%s\n",
crm_element_value(node, XML_ATTR_UNAME),
crm_element_value(node, XML_ATTR_ID));
} else {
printf("%s node: %s (%s)\n",
crm_element_value(node, XML_ATTR_TYPE),
crm_element_value(node, XML_ATTR_UNAME),
crm_element_value(node, XML_ATTR_ID));
}
found++;
);
if(found == 0) {
printf("NO nodes configured\n");
}
return found;
}
void
usage(const char *cmd, int exit_status)
{
FILE *stream;
stream = exit_status ? stderr : stdout;
fprintf(stream, "usage: %s [-?vs] [command] [command args]\n", cmd);
fprintf(stream, "Options\n");
fprintf(stream, "\t--%s (-%c)\t: this help message\n", "help", '?');
fprintf(stream, "\t--%s (-%c)\t: "
"turn on debug info. additional instances increase verbosity\n",
"verbose", 'V');
fprintf(stream, "\t--%s (-%c)\t: be very *very* quiet\n", "quiet", 'q');
fprintf(stream, "\t--%s (-%c)\t: Only applies to -N.\n"
"\t\tCreate Bash export entries of the form \"export uname=uuid\"\n", "bash-export", 'B');
fprintf(stream, "\nCommands\n");
fprintf(stream, "\t--%s (-%c) <node>\t: "
"increment the CRMd debug level on <node>\n", CRM_OP_DEBUG_UP,'i');
fprintf(stream, "\t--%s (-%c) <node>\t: "
"decrement the CRMd debug level on <node>\n", CRM_OP_DEBUG_DOWN,'d');
fprintf(stream, "\t--%s (-%c) <node>\t: "
"shutdown the CRMd on <node>\n", "kill", 'K');
fprintf(stream, "\t--%s (-%c) <node>\t: "
"request the status of <node>\n", "status", 'S');
#if 0
fprintf(stream, "\t--%s (-%c)\t\t: "
"request the status of all nodes\n", "health", 'H');
#endif
fprintf(stream, "\t--%s (-%c) <node>\t: "
"initiate an election from <node>\n", "election", 'E');
fprintf(stream, "\t--%s (-%c)\t: "
"request the uname of the DC\n", "dc_lookup", 'D');
fprintf(stream, "\t--%s (-%c)\t\t: "
"request the uname of all member nodes\n", "nodes", 'N');
-#if 0
- fprintf(stream, "\t--%s (-%c)\t: "
- "request the names of all resources\n", "resources", 'R');
-#endif
- fprintf(stream, "\t--%s (-%c) <rsc>\t: "
- "request the location of <rsc>\n", "whereis", 'W');
- fprintf(stream, "\t--%s (-%c) <node_uuid>\t: "
- "Tell the node to enter \"standby\" mode\n", "standby", 's');
- fprintf(stream, "\t--%s (-%c) <node_uuid>\t: "
- "Tell the node to exit \"standby\" mode\n", "active", 'a');
/* fprintf(stream, "\t--%s (-%c)\t\n", "disconnect", 'D'); */
fflush(stream);
exit(exit_status);
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Apr 21, 7:04 PM (16 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1665329
Default Alt Text
(19 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment