Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/crm/admin/adminmain.c b/crm/admin/adminmain.c
index 027e751493..dc7eaf8424 100644
--- a/crm/admin/adminmain.c
+++ b/crm/admin/adminmain.c
@@ -1,636 +1,636 @@
-/* $Id: adminmain.c,v 1.25 2004/06/01 12:25:14 andrew Exp $ */
+/* $Id: adminmain.c,v 1.26 2004/06/01 16:12:49 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 <crm/crm.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <hb_api.h>
#include <apphb.h>
#include <clplumbing/ipc.h>
#include <clplumbing/Gmain_timeout.h>
#include <clplumbing/cl_log.h>
#include <clplumbing/cl_signal.h>
#include <clplumbing/lsb_exitcodes.h>
#include <clplumbing/uids.h>
#include <clplumbing/realtime.h>
#include <clplumbing/GSource.h>
#include <clplumbing/cl_poll.h>
#include <crm/common/crmutils.h>
#include <crm/common/msgutils.h>
#include <crm/common/ipcutils.h>
#include <crm/common/xmlutils.h>
#include <crm/msg_xml.h>
#include <crm/cib.h>
#define OPTARGS "V?i:o:D:C:S:HA:U:M:I:EWRFt:m:a:d:w:c:r:p:s:"
#include <getopt.h>
#include <crm/dmalloc_wrapper.h>
GMainLoop *mainloop = NULL;
const char *crm_system_name = "crmadmin";
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);
gboolean decodeNVpair(const char *srcstring, char separator,
char **name, char **value);
gboolean admin_msg_callback(IPC_Channel * source_data, void *private_data);
char *pluralSection(const char *a_section);
xmlNodePtr handleCibMod(void);
gboolean DO_DAEMON = FALSE;
gboolean BE_VERBOSE = FALSE;
int expected_responses = 1;
gboolean DO_HEALTH = FALSE;
gboolean DO_ELECT_DC = FALSE;
gboolean DO_WHOIS_DC = FALSE;
gboolean DO_RECALC_TREE = FALSE;
gboolean DO_FLUSH_RECALC = FALSE;
const char *cib_action = NULL;
xmlNodePtr msg_options = NULL;
typedef struct str_list_s
{
int num_items;
char *value;
struct str_list_s *next;
} str_list_t;
const char *verbose = XML_BOOLEAN_FALSE;
char *id = NULL;
char *this_msg_reference = NULL;
char *obj_type = NULL;
char *clear = NULL;
char *status = NULL;
char *disconnect = NULL;
char *unload_ha = NULL;
char *migrate_from = NULL;
char *migrate_res = NULL;
char *subtype = NULL;
char *reset = NULL;
int operation_status = 0;
const char *sys_to = NULL;;
int
main(int argc, char **argv)
{
int option_index = 0;
int argerr = 0;
int flag;
ll_cluster_t *hb_cluster = NULL;
static struct option long_options[] = {
// Top-level Options
{"daemon", 0, 0, 0},
{CRM_OP_ERASE, 0, 0, 0},
{CRM_OP_QUERY, 0, 0, 0},
{CRM_OP_CREATE, 0, 0, 0},
{CRM_OP_REPLACE, 0, 0, 0},
{CRM_OP_STORE, 0, 0, 0},
{CRM_OP_UPDATE, 0, 0, 0},
{CRM_OP_DELETE, 0, 0, 0},
{"verbose", 0, 0, 'V'},
{"help", 0, 0, '?'},
{"reference", 1, 0, 0},
// common options
{XML_ATTR_ID, 1, 0, 'i'},
{"obj_type", 1, 0, 'o'},
// daemon options
{"reset", 1, 0, 'C'},
{"status", 1, 0, 'S'},
{"health", 0, 0, 'H'},
{"disconnect", 1, 0, 'A'},
{"unload_ha", 1, 0, 'U'},
{"migrate_from", 1, 0, 'M'},
{"migrate_res", 1, 0, 'I'},
{"elect_dc", 0, 0, 'E'},
{"whois_dc", 0, 0, 'W'},
{"recalc_tree", 0, 0, 'R'},
{"flush_recalc_tree", 0, 0, 'F'},
{0, 0, 0, 0}
};
cl_log_set_entity(crm_system_name);
cl_log_enable_stderr(TRUE);
cl_log_set_facility(LOG_USER);
while (1) {
flag = getopt_long(argc, argv, OPTARGS,
long_options, &option_index);
if (flag == -1)
break;
switch(flag) {
case 0:
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
if (strcmp("daemon", long_options[option_index].name) == 0)
DO_DAEMON = TRUE;
else if (strcmp(CRM_OP_ERASE,
long_options[option_index].name) == 0
|| strcmp(CRM_OP_CREATE,
long_options[option_index].name) == 0
|| strcmp(CRM_OP_UPDATE,
long_options[option_index].name) == 0
|| strcmp(CRM_OP_DELETE,
long_options[option_index].name) == 0
|| strcmp(CRM_OP_REPLACE,
long_options[option_index].name) == 0
|| strcmp(CRM_OP_STORE,
long_options[option_index].name) == 0
|| strcmp(CRM_OP_QUERY,
long_options[option_index].name) == 0){
cib_action = crm_strdup(long_options[option_index].name);
} else if (strcmp("reference",
long_options[option_index].name) == 0) {
this_msg_reference =
crm_strdup(optarg);
} else {
printf( "?? Long option (--%s) is not yet properly supported ??\n",
long_options[option_index].name);
++argerr;
}
break;
/* 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;
verbose = XML_BOOLEAN_TRUE;
break;
case '?':
usage(crm_system_name, LSB_EXIT_OK);
break;
case 'i':
CRM_DEBUG("Option %c => %s", flag, optarg);
id = crm_strdup(optarg);
break;
case 'o':
CRM_DEBUG("Option %c => %s", flag, optarg);
obj_type = crm_strdup(optarg);
break;
case 'C':
printf("Option %c is not yet supported\n", flag);
++argerr;
break;
case 'S':
DO_HEALTH = TRUE;
status = crm_strdup(optarg);
break;
case 'H':
DO_HEALTH = TRUE;
break;
case 'A':
printf("Option %c is not yet supported\n", flag);
++argerr;
break;
case 'U':
printf("Option %c is not yet supported\n", flag);
++argerr;
break;
case 'M':
printf("Option %c is not yet supported\n", flag);
++argerr;
break;
case 'I':
printf("Option %c is not yet supported\n", flag);
++argerr;
break;
case 'E':
DO_ELECT_DC = TRUE;
printf("Option %c is not yet supported\n", flag);
++argerr;
break;
case 'W':
DO_WHOIS_DC = TRUE;
printf("Option %c is not yet supported\n", flag);
++argerr;
break;
case 'R':
DO_RECALC_TREE = TRUE;
printf("Option %c is not yet supported\n", flag);
++argerr;
break;
case 'F':
DO_FLUSH_RECALC = TRUE;
printf("Option %c is not yet supported\n", flag);
++argerr;
break;
default:
printf("?? getopt returned character code 0%o ??\n", 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) {
if (do_work(hb_cluster) > 0) {
/* wait for the reply by creating a mainloop and running it until
* the callbacks are invoked...
*/
mainloop = g_main_new(FALSE);
cl_log(LOG_INFO,
"%s waiting for reply from the local CRM",
crm_system_name);
g_main_run(mainloop);
return_to_orig_privs();
} else {
cl_log(LOG_ERR, "No message to send");
operation_status = -1;
}
} else {
cl_log(LOG_ERR,
"Init failed, could not perform requested operations");
operation_status = -2;
}
cl_log(LOG_DEBUG, "%s exiting normally", crm_system_name);
return operation_status;
}
xmlNodePtr
handleCibMod(void)
{
const char *attr_name = NULL;
const char *attr_value = NULL;
xmlNodePtr fragment = NULL;
xmlNodePtr cib_object = file2xml(stdin);
if(cib_object == NULL) {
return NULL;
}
if(strcmp(cib_object->name, obj_type) != 0) {
cl_log(LOG_ERR, "Mismatching xml."
" Expected root element <%s>, got <%s>",
obj_type, cib_object->name);
return NULL;
}
attr_name = XML_ATTR_ID;
attr_value = xmlGetProp(cib_object, attr_name);
if(attr_name == NULL || strlen(attr_name) == 0) {
cl_log(LOG_ERR, "No value for %s specified.", attr_name);
return NULL;
}
- CRM_DEBUG("Object creation complete");
+ CRM_NOTE("Object creation complete");
// create the cib request
fragment = create_cib_fragment(cib_object, NULL);
set_xml_property_copy(msg_options, XML_ATTR_OP, cib_action);
return fragment;
}
int
do_work(ll_cluster_t * hb_cluster)
{
/* construct the request */
xmlNodePtr msg_data = NULL;
const char *dest_node = NULL;
gboolean all_is_good = TRUE;
char *obj_type_parent = NULL;
const char *ping_type = NULL;
msg_options = create_xml_node(NULL, XML_TAG_OPTIONS);
set_xml_property_copy(msg_options, XML_ATTR_VERBOSE, verbose);
set_xml_property_copy(msg_options, XML_ATTR_TIMEOUT, "0");
if (DO_DAEMON == TRUE && cib_action != NULL) {
if(strcmp(CRM_OP_QUERY, cib_action) == 0) {
cl_log(LOG_DEBUG, "Querying the CIB");
obj_type_parent = pluralSection(obj_type);
CRM_DEBUG("Querying the CIB for section: %s",
obj_type_parent);
set_xml_property_copy(msg_options, XML_ATTR_OP, CRM_OP_QUERY);
set_xml_property_copy(msg_options, XML_ATTR_FILTER_ID,
obj_type_parent);
dest_node = status;
CRM_DEBUG("CIB query creation %s",
msg_data == NULL ? "failed." : "passed.");
sys_to = CRM_SYSTEM_DCIB;
} else if (strcmp(CRM_OP_ERASE, cib_action) == 0) {
set_xml_property_copy(msg_options,
XML_ATTR_OP,
CRM_OP_ERASE);
dest_node = status;
- CRM_DEBUG("CIB Erase op in progress");
+ CRM_NOTE("CIB Erase op in progress");
sys_to = CRM_SYSTEM_DCIB;
} else {
cl_log(LOG_ERR, "Unknown daemon options");
all_is_good = FALSE;
}
} else if(cib_action != NULL) {
msg_data = handleCibMod();
sys_to = CRM_SYSTEM_DCIB;
if(msg_data == NULL)
all_is_good = FALSE;
} else if (DO_DAEMON == TRUE && DO_HEALTH == TRUE) {
- CRM_DEBUG("Querying the system");
+ CRM_NOTE("Querying the system");
sys_to = CRM_SYSTEM_DC;
if (status != NULL) {
sys_to = CRM_SYSTEM_CRMD;
ping_type = CRM_OP_PING;
if (BE_VERBOSE) {
ping_type = "ping_deep";
if (status != NULL)
expected_responses = 2; // 5; // CRM/DC, LRMD, CIB, PENGINE, TENGINE
else
expected_responses = -1;// wait until timeout instead
}
set_xml_property_copy(msg_options,
XML_ATTR_OP,
ping_type);
set_xml_property_copy(msg_options,
XML_ATTR_TIMEOUT,
"0");
dest_node = status;
} else {
cl_log(LOG_INFO, "Cluster-wide health not available yet");
all_is_good = FALSE;
}
} else {
cl_log(LOG_ERR, "Unknown options");
all_is_good = FALSE;
}
if(all_is_good == FALSE) {
cl_log(LOG_ERR, "Creation of request failed. No message to send");
return -1;
}
/* send it */
if (crmd_channel == NULL) {
cl_log(LOG_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;
}
send_ipc_request(crmd_channel,
msg_options,
msg_data,
dest_node, sys_to,
crm_system_name,
admin_uuid,
this_msg_reference);
return 1;
}
ll_cluster_t *
do_init(void)
{
int facility;
ll_cluster_t *hb_cluster = NULL;
/* docs say only do this once, but in their code they do it every time! */
xmlInitParser ();
/* change the logging facility to the one used by heartbeat daemon */
hb_cluster = ll_cluster_new("heartbeat");
cl_log(LOG_INFO, "Switching to Heartbeat logger");
if (( facility =
hb_cluster->llc_ops->get_logfacility(hb_cluster)) > 0) {
cl_log_set_facility(facility);
}
admin_uuid = crm_malloc(sizeof(char) * 11);
snprintf(admin_uuid, 10, "%d", getpid());
admin_uuid[10] = '\0';
crmd_channel =
init_client_ipc_comms(CRM_SYSTEM_CRMD,admin_msg_callback,NULL);
if(crmd_channel != NULL) {
send_hello_message(crmd_channel,
admin_uuid,
crm_system_name,
"0",
"1");
return hb_cluster;
}
return NULL;
}
void
usage(const char *cmd, int exit_status)
{
FILE *stream;
stream = exit_status ? stderr : stdout;
fprintf(stream, "usage: %s [-srkh]" "[-c configure file]\n", cmd);
/* fprintf(stream, "\t-d\tsets debug level\n"); */
/* fprintf(stream, "\t-s\tgets daemon status\n"); */
/* fprintf(stream, "\t-r\trestarts daemon\n"); */
/* fprintf(stream, "\t-k\tstops daemon\n"); */
/* fprintf(stream, "\t-h\thelp message\n"); */
fflush(stream);
exit(exit_status);
}
const char *ournode;
gboolean
admin_msg_callback(IPC_Channel * server, void *private_data)
{
int lpc = 0;
IPC_Message *msg = NULL;
gboolean hack_return_good = TRUE;
static int received_responses = 0;
char *filename;
int filename_len = 0;
const char *result = NULL;
xmlNodePtr options = NULL;
xmlNodePtr xml_root_node = NULL;
char *buffer = NULL;
FNIN();
while (server->ch_status != IPC_DISCONNECT
&& server->ops->is_message_pending(server) == TRUE) {
if (server->ops->recv(server, &msg) != IPC_OK) {
perror("Receive failure:");
FNRET(!hack_return_good);
}
if (msg == NULL) {
- CRM_DEBUG("No message this time");
+ CRM_NOTE("No message this time");
continue;
}
lpc++;
buffer =(char *) msg->msg_body;
CRM_DEBUG("Got xml [text=%s]", buffer);
xml_root_node =
find_xml_in_ipcmessage(msg, TRUE);
if (xml_root_node == NULL) {
cl_log(LOG_INFO,
"XML in IPC message was not valid... "
"discarding.");
continue;
} else if (validate_crm_message(xml_root_node,
crm_system_name,
admin_uuid,
"response") == FALSE) {
cl_log(LOG_INFO,
"Message was not a CRM response. Discarding.");
continue;
}
options = find_xml_node(xml_root_node,
XML_TAG_OPTIONS);
result = xmlGetProp(options, XML_ATTR_RESULT);
if(result == NULL || strcmp(result, "ok") == 0) {
result = "pass";
} else {
result = "fail";
}
received_responses++;
// do stuff
if (this_msg_reference != NULL) {
// in testing mode...
/* 31 = "test-_.xml" + an_int_as_string + '\0' */
filename_len = 31 + strlen(this_msg_reference);
filename = crm_malloc(sizeof(char) * filename_len);
sprintf(filename, "%s-%s_%d.xml",
result,
this_msg_reference,
received_responses);
filename[filename_len - 1] = '\0';
if (xmlSaveFormatFile(filename,
xml_root_node->doc, 1) < 0) {
cl_log(LOG_CRIT,
"Could not save response %s_%s_%d.xml",
this_msg_reference,
result,
received_responses);
}
}
}
if (server->ch_status == IPC_DISCONNECT) {
cl_log(LOG_INFO, "admin_msg_callback: received HUP");
FNRET(!hack_return_good);
}
if (received_responses >= expected_responses) {
cl_log(LOG_INFO,
"Recieved expected number (%d) of messages from Heartbeat."
" Exiting normally.", expected_responses);
g_main_quit(mainloop);
return !hack_return_good;
}
FNRET(hack_return_good);
}
diff --git a/crm/cib/cib.c b/crm/cib/cib.c
index 0524c52a8f..65d2cc9f5d 100644
--- a/crm/cib/cib.c
+++ b/crm/cib/cib.c
@@ -1,319 +1,315 @@
-/* $Id: cib.c,v 1.37 2004/06/01 12:25:14 andrew Exp $ */
+/* $Id: cib.c,v 1.38 2004/06/01 16:12:49 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 <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <crm/crm.h>
#include <clplumbing/cl_log.h>
#include <libxml/tree.h>
#include <crm/msg_xml.h>
#include <crm/common/xmlutils.h>
#include <crm/common/msgutils.h>
#include <crm/cib.h>
#include <cibio.h>
#include <cibmessages.h>
#include <crm/dmalloc_wrapper.h>
gboolean
startCib(const char *filename)
{
xmlNodePtr cib = readCibXmlFile(filename);
if (initializeCib(cib)) {
cl_log(LOG_INFO,
"CIB Initialization completed successfully");
} else {
// free_xml(cib);
cl_log(LOG_WARNING,
"CIB Initialization failed, "
"starting with an empty default.");
activateCibXml(createEmptyCib(), filename);
}
return TRUE;
}
xmlNodePtr
get_cib_copy()
{
return copy_xml_node_recursive(get_the_CIB());
}
/*
* The caller should never free the return value
*/
xmlNodePtr
get_object_root(const char *object_type, xmlNodePtr the_root)
{
const char *node_stack[2];
xmlNodePtr tmp_node = NULL;
FNIN();
node_stack[0] = XML_CIB_TAG_CONFIGURATION;
node_stack[1] = object_type;
if(object_type == NULL || strlen(object_type) == 0) {
FNRET(the_root);
/* get the whole cib */
} else if(strcmp(object_type, XML_CIB_TAG_STATUS) == 0) {
node_stack[0] = XML_CIB_TAG_STATUS;
node_stack[1] = NULL;
/* these live in a different place */
}
tmp_node = find_xml_node_nested(the_root, node_stack, 2);
if (tmp_node == NULL) {
cl_log(LOG_ERR,
"[cib] Section cib[%s[%s]] not present",
node_stack[0],
node_stack[1]);
}
FNRET(tmp_node);
}
xmlNodePtr
process_cib_message(xmlNodePtr message, gboolean auto_reply)
{
xmlNodePtr data;
xmlNodePtr reply;
enum cib_result result = CIBRES_OK;
xmlNodePtr fragment = find_xml_node(message, XML_TAG_FRAGMENT);
xmlNodePtr options = find_xml_node(message, XML_TAG_OPTIONS);
const char *op = get_xml_attr (message, XML_TAG_OPTIONS,
XML_ATTR_OP, TRUE);
data = cib_process_request(op, options, fragment, &result);
CRM_DEBUG("[cib] operation returned result %d", result);
if(auto_reply) {
reply = create_reply(message, data);
free_xml(data);
// TODO: put real result in here
set_xml_attr(reply, XML_TAG_OPTIONS,
XML_ATTR_RESULT, "ok", TRUE);
return reply;
}
return data;
}
xmlNodePtr
process_cib_request(const char *op,
const xmlNodePtr options,
const xmlNodePtr fragment)
{
enum cib_result result = CIBRES_OK;
return cib_process_request(op, options, fragment, &result);
}
xmlNodePtr
create_cib_fragment(xmlNodePtr update, const char *section)
{
gboolean whole_cib = FALSE;
xmlNodePtr fragment = create_xml_node(NULL, XML_TAG_FRAGMENT);
xmlNodePtr cib = NULL;
xmlNodePtr object_root = NULL;
char *auto_section = pluralSection(update?update->name:NULL);
if(update == NULL) {
cl_log(LOG_ERR, "No update to create a fragment for");
crm_free(auto_section);
return NULL;
} else if(section == NULL) {
section = auto_section;
} else if(strcmp(auto_section, section) != 0) {
cl_log(LOG_ERR,
"Values for update (tag=%s) and section (%s)"
" were not consistent", update->name, section);
crm_free(auto_section);
return NULL;
}
if(strcmp(section, "all")==0 && strcmp(update->name, XML_TAG_CIB)==0) {
whole_cib = TRUE;
}
set_xml_property_copy(fragment, XML_ATTR_SECTION, section);
if(whole_cib == FALSE) {
cib = createEmptyCib();
object_root = get_object_root(section, cib);
xmlAddChildList(object_root, xmlCopyNodeList(update));
} else {
cib = xmlCopyNodeList(update);
}
xmlAddChild(fragment, cib);
- CRM_DEBUG("Fragment created");
-
- xml_message_debug(fragment, "created fragment");
-
crm_free(auto_section);
return fragment;
}
char *
pluralSection(const char *a_section)
{
char *a_section_parent = NULL;
if (a_section == NULL) {
a_section_parent = crm_strdup("all");
} else if(strcmp(a_section, XML_TAG_CIB) == 0) {
a_section_parent = crm_strdup("all");
} else if(strcmp(a_section, XML_CIB_TAG_NODE) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_NODES);
} else if(strcmp(a_section, XML_CIB_TAG_STATE) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_STATUS);
} else if(strcmp(a_section, XML_CIB_TAG_CONSTRAINT) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_CONSTRAINTS);
} else if(strcmp(a_section, XML_CIB_TAG_RESOURCE) == 0) {
a_section_parent = crm_strdup(XML_CIB_TAG_RESOURCES);
} else {
cl_log(LOG_ERR, "Unknown section %s", a_section);
a_section_parent = crm_strdup("all");
}
CRM_DEBUG("Plural is %s", a_section_parent);
return a_section_parent;
}
const char *
cib_error2string(enum cib_result return_code)
{
const char *error_msg = NULL;
switch(return_code) {
case CIBRES_MISSING_ID:
error_msg = "The id field is missing";
break;
case CIBRES_MISSING_TYPE:
error_msg = "The type field is missing";
break;
case CIBRES_MISSING_FIELD:
error_msg = "A required field is missing";
break;
case CIBRES_OBJTYPE_MISMATCH:
error_msg = "CIBRES_OBJTYPE_MISMATCH";
break;
case CIBRES_FAILED_EXISTS:
error_msg = "The object already exists";
break;
case CIBRES_FAILED_NOTEXISTS:
error_msg = "The object does not exist";
break;
case CIBRES_CORRUPT:
error_msg = "The CIB is corrupt";
break;
case CIBRES_FAILED_NOOBJECT:
error_msg = "The update was empty";
break;
case CIBRES_FAILED_NOPARENT:
error_msg = "The parent object does not exist";
break;
case CIBRES_FAILED_NODECOPY:
error_msg = "Failed while copying update";
break;
case CIBRES_OTHER:
error_msg = "CIBRES_OTHER";
break;
case CIBRES_OK:
error_msg = "ok";
break;
case CIBRES_FAILED:
error_msg = "Failed";
break;
case CIBRES_FAILED_STALE:
error_msg = "Discarded old update";
break;
case CIBRES_FAILED_ACTIVATION:
error_msg = "Activation Failed";
break;
case CIBRES_FAILED_NOSECTION:
error_msg = "Required section was missing";
break;
case CIBRES_FAILED_NOTSUPPORTED:
error_msg = "Supplied information is not supported";
break;
}
if(error_msg == NULL) {
cl_log(LOG_ERR, "Unknown CIB Error %d", return_code);
error_msg = "<unknown error>";
}
return error_msg;
}
const char *
cib_op2string(enum cib_op operation)
{
const char *operation_msg = NULL;
switch(operation) {
case 0:
operation_msg = "none";
break;
case 1:
operation_msg = "add";
break;
case 2:
operation_msg = "modify";
break;
case 3:
operation_msg = "delete";
break;
case CIB_OP_MAX:
operation_msg = "invalid operation";
break;
}
if(operation_msg == NULL) {
cl_log(LOG_ERR, "Unknown CIB operation %d", operation);
operation_msg = "<unknown operation>";
}
return operation_msg;
}
diff --git a/crm/cib/cibio.c b/crm/cib/cibio.c
index 95c9304c8e..cd777508f3 100644
--- a/crm/cib/cibio.c
+++ b/crm/cib/cibio.c
@@ -1,434 +1,428 @@
-/* $Id: cibio.c,v 1.23 2004/06/01 12:25:14 andrew Exp $ */
+/* $Id: cibio.c,v 1.24 2004/06/01 16:12:49 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 <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <crm/crm.h>
#include <libxml/tree.h>
#include <crm/cib.h>
#include <cibio.h>
#include <crm/common/msgutils.h> // for getNow()
#include <crm/msg_xml.h>
#include <crm/common/xmlutils.h>
#include <crm/dmalloc_wrapper.h>
const char * local_resource_path[] =
{
XML_CIB_TAG_STATUS,
};
const char * resource_path[] =
{
XML_CIB_TAG_RESOURCES,
};
const char * node_path[] =
{
XML_CIB_TAG_NODES,
};
const char * constraint_path[] =
{
XML_CIB_TAG_CONSTRAINTS,
};
gboolean initialized = FALSE;
xmlNodePtr the_cib = NULL;
xmlNodePtr node_search = NULL;
xmlNodePtr resource_search = NULL;
xmlNodePtr constraint_search = NULL;
xmlNodePtr status_search = NULL;
/*
* It is the callers responsibility to free both the new CIB (output)
* and the new CIB (input)
*/
xmlNodePtr
createEmptyCib(void)
{
xmlNodePtr cib_root = NULL, config = NULL, status = NULL;
cib_root = create_xml_node(NULL, XML_TAG_CIB);
config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION);
status = create_xml_node(cib_root, XML_CIB_TAG_STATUS);
set_node_tstamp(cib_root);
set_node_tstamp(config);
set_node_tstamp(status);
set_xml_property_copy(cib_root, "version", "1");
set_xml_property_copy(cib_root, "generated", XML_BOOLEAN_TRUE);
create_xml_node(config, XML_CIB_TAG_NODES);
create_xml_node(config, XML_CIB_TAG_RESOURCES);
create_xml_node(config, XML_CIB_TAG_CONSTRAINTS);
if (verifyCibXml(cib_root)) {
FNRET(cib_root);
}
cl_log(LOG_CRIT,
"The generated CIB did not pass integrity testing!!"
" All hope is lost.");
FNRET(NULL);
}
gboolean
verifyCibXml(xmlNodePtr cib)
{
gboolean is_valid = TRUE;
xmlNodePtr tmp_node = NULL;
FNIN();
if (cib == NULL) {
cl_log(LOG_ERR, "XML Buffer was empty.");
FNRET(FALSE);
}
tmp_node = get_object_root(XML_CIB_TAG_NODES, cib);
if (tmp_node == NULL) is_valid = FALSE;
tmp_node = get_object_root(XML_CIB_TAG_RESOURCES, cib);
if (tmp_node == NULL) is_valid = FALSE;
tmp_node = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib);
if (tmp_node == NULL) is_valid = FALSE;
tmp_node = get_object_root(XML_CIB_TAG_STATUS, cib);
if (tmp_node == NULL) is_valid = FALSE;
// more integrity tests
FNRET(is_valid);
}
/*
* It is the callers responsibility to free the output of this function
*/
xmlNodePtr
readCibXml(char *buffer)
{
xmlNodePtr root = string2xml(buffer);
if (verifyCibXml(root) == FALSE) {
free_xml(root);
FNRET(createEmptyCib());
}
FNRET(root);
}
/*
* It is the callers responsibility to free the output of this function
*/
xmlNodePtr
readCibXmlFile(const char *filename)
{
int s_res = -1;
struct stat buf;
xmlNodePtr root = NULL;
FNIN();
if(filename != NULL) {
s_res = stat(filename, &buf);
}
if (s_res == 0) {
FILE *cib_file = fopen(filename, "r");
root = file2xml(cib_file);
set_xml_property_copy(root, "generated", XML_BOOLEAN_FALSE);
fclose(cib_file);
} else {
cl_log(LOG_WARNING,
"Stat of (%s) failed, file does not exist.",
CIB_FILENAME);
}
if (verifyCibXml(root) == FALSE) {
free_xml(root);
// FNRET(createEmptyCib());
root = NULL;
}
FNRET(root);
}
/*
* The caller should never free the return value
*/
xmlNodePtr
get_the_CIB(void)
{
FNIN();
FNRET(the_cib);
}
gboolean
uninitializeCib(void)
{
xmlNodePtr tmp_cib = the_cib;
FNIN();
if(tmp_cib == NULL) {
cl_log(LOG_ERR, "The CIB has already been deallocated.");
FNRET(FALSE);
}
initialized = FALSE;
the_cib = NULL;
node_search = NULL;
resource_search = NULL;
constraint_search = NULL;
status_search = NULL;
cl_log(LOG_WARNING, "Deallocating the CIB.");
free_xml(tmp_cib);
cl_log(LOG_WARNING, "The CIB has been deallocated.");
FNRET(TRUE);
}
/*
* This method will not free the old CIB pointer or the new one.
* We rely on the caller to have saved a pointer to the old CIB
* and to free the old/bad one depending on what is appropriate.
*/
gboolean
initializeCib(xmlNodePtr new_cib)
{
if (verifyCibXml(new_cib)) {
initialized = FALSE;
the_cib = new_cib;
// update search paths
/* not used yet...
node_search =
get_object_root(XML_CIB_TAG_NODES, new_cib);
resource_search =
get_object_root(XML_CIB_TAG_RESOURCES, new_cib);
constraint_search =
get_object_root(XML_CIB_TAG_CONSTRAINTS, new_cib);
status_search =
get_object_root(XML_CIB_TAG_STATUS, new_cib);
*/
initialized = TRUE;
- CRM_DEBUG("CIB initialized");
+ CRM_NOTE("CIB initialized");
FNRET(TRUE);
}
else {
cl_log(LOG_ERR, "CIB Verification failed");
}
FNRET(FALSE);
}
int
moveFile(const char *oldname,
const char *newname,
gboolean backup,
char *ext)
{
/* move 'oldname' to 'newname' by creating a hard link to it
* and then removing the original hard link
*/
int res = 0;
struct stat tmp;
int s_res = stat(newname, &tmp);
FNIN();
- cl_log(LOG_INFO, "Stat of %s (code: %d).", newname, s_res);
if (s_res >= 0)
{
if (backup == TRUE) {
char backname[1024];
static const char *back_ext = "bak";
if (ext != NULL) back_ext = (char*)ext;
snprintf(backname, sizeof(backname)-1,
"%s.%s", newname, back_ext);
moveFile(newname, backname, FALSE, NULL);
} else {
res = unlink(newname);
if (res < 0) {
perror("Could not remove the current backup of Cib");
FNRET(-1);
}
}
}
s_res = stat(oldname, &tmp);
- cl_log(LOG_INFO, "Stat of %s (code: %d).", oldname, s_res);
if (s_res >= 0) {
res = link(oldname, newname);
if (res < 0) {
perror("Could not create backup of current Cib");
FNRET(-2);
}
res = unlink(oldname);
if (res < 0) {
perror("Could not unlink the current Cib");
FNRET(-3);
}
}
FNRET(0);
}
int
activateCibBuffer(char *buffer, const char *filename)
{
int result = -1;
xmlNodePtr local_cib = NULL;
FNIN();
local_cib = readCibXml(buffer);
result = activateCibXml(local_cib, filename);
FNRET(result);
}
/*
* This method will free the old CIB pointer on success and the new one
* on failure.
*/
int
activateCibXml(xmlNodePtr new_cib, const char *filename)
{
int error_code = 0;
xmlNodePtr saved_cib = get_the_CIB();
const char *filename_bak = CIB_BACKUP; // calculate
xmlDocPtr foo;
FNIN();
if (initializeCib(new_cib) == TRUE) {
int res = moveFile(filename, filename_bak, FALSE, NULL);
if (res < 0) {
cl_log(LOG_INFO,
"Could not make backup of the current Cib "
"(code: %d)... aborting update.", res);
error_code = -1;
} else {
cl_log(LOG_INFO,
"Writing CIB out to %s",
CIB_FILENAME);
if (new_cib->doc == NULL) {
- cl_log(LOG_INFO,
- "Writing of a node tree with a NULL "
- "document will fail, creating a new "
- "back link.");
foo = xmlNewDoc("1.0");
xmlDocSetRootElement(foo, new_cib);
xmlSetTreeDoc(new_cib,foo);
}
time_t now = time(NULL);
char *now_str = asctime(localtime(&now));
set_xml_property_copy(new_cib, "last_written",now_str);
free(now_str);
/* save it.
* set arg 3 to 0 to disable line breaks,1 to enable
* res == num bytes saved
*/
res = xmlSaveFormatFile(filename,
new_cib->doc,
1);
/* for some reason, reading back after saving with
* line-breaks doesnt go real well
*/
cl_log(LOG_INFO,
"Saved %d bytes to the Cib as XML",
res);
if (res < 0) {
// assume 0 is good
if (moveFile(filename_bak,
filename,
FALSE,
NULL) < -1) {
cl_log(LOG_CRIT,
"Could not restore the "
"backup of the current Cib "
"(code: %d)... panic!",
res);
error_code = -2;
// should probably exit here
} else if (initializeCib(saved_cib) == FALSE) {
// oh we are so dead
cl_log(LOG_CRIT,
"Could not re-initialize "
"with the old CIB. "
"Everything is about to go "
"pear shaped");
error_code = -3;
} else {
cl_log(LOG_CRIT,
"Update of Cib failed "
"(code: %d)... reverted to "
"last known valid version",
res);
error_code = -4;
}
}
}
}
else
{
cl_log(LOG_INFO, "Ignoring invalid or NULL Cib");
error_code = -5;
}
// Make sure memory is cleaned up appropriately
if (error_code != 0) {
// CRM_DEBUG("Freeing new CIB %p", new_cib);
free_xml(new_cib);
} else {
// CRM_DEBUG("Freeing saved CIB %p", saved_cib);
free_xml(saved_cib);
}
FNRET(error_code);
}
diff --git a/crm/cib/cibmessages.c b/crm/cib/cibmessages.c
index 057c91a546..25afee803b 100644
--- a/crm/cib/cibmessages.c
+++ b/crm/cib/cibmessages.c
@@ -1,478 +1,477 @@
-/* $Id: cibmessages.c,v 1.36 2004/06/01 12:25:14 andrew Exp $ */
+/* $Id: cibmessages.c,v 1.37 2004/06/01 16:12:49 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 <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <crm/crm.h>
#include <clplumbing/cl_log.h>
#include <libxml/tree.h>
#include <time.h>
#include <crm/common/msgutils.h>
#include <crm/common/xmlutils.h>
#include <crm/cib.h>
#include <cibio.h>
#include <crm/msg_xml.h>
#include <clplumbing/cl_log.h>
#include <cibprimatives.h>
#include <cibmessages.h>
#include <crm/dmalloc_wrapper.h>
FILE *msg_cib_strm = NULL;
enum cib_result updateList(xmlNodePtr local_cib,
xmlNodePtr update_command,
xmlNodePtr failed,
int operation,
const char *section);
xmlNodePtr createCibFragmentAnswer(const char *section, xmlNodePtr failed);
gboolean replace_section(const char *section,
xmlNodePtr tmpCib,
xmlNodePtr command);
gboolean check_generation(xmlNodePtr newCib, xmlNodePtr oldCib);
gboolean update_results(xmlNodePtr failed,
xmlNodePtr target,
int operation,
int return_code);
xmlNodePtr
cib_process_request(const char *op,
const xmlNodePtr options,
const xmlNodePtr fragment,
enum cib_result *result)
{
const char *verbose = NULL;
const char *section = NULL;
const char *output_section = NULL;
xmlNodePtr failed = NULL;
xmlNodePtr cib_answer = NULL;
gboolean update_the_cib = FALSE;
int cib_update_op = CIB_OP_NONE;
xmlNodePtr tmpCib;
char *new_value = NULL;
char *old_value = NULL;
int int_value = -1;
FNIN();
*result = CIBRES_OK;
verbose = xmlGetProp(options, XML_ATTR_VERBOSE);
section = xmlGetProp(options, XML_ATTR_FILTER_TYPE);
failed = create_xml_node(NULL, XML_TAG_FAILED);
#ifdef MSG_LOG
if(msg_cib_strm == NULL) {
msg_cib_strm = fopen("/tmp/cib.log", "w");
}
fprintf(msg_cib_strm, "[Input %s]\t%s\n", op, dump_xml_node(fragment, FALSE));
fflush(msg_cib_strm);
#endif
cl_log(LOG_DEBUG, "[cib] Processing \"%s\" event", op);
if(op == NULL) {
*result = CIBRES_FAILED;
cl_log(LOG_ERR, "No operation specified\n");
} else if(strcmp("noop", op) == 0) {
;
} else if(strcmp(CRM_OP_QUIT, op) == 0) {
cl_log(LOG_WARNING,
"The CRMd has asked us to exit... complying");
exit(0);
} else if (strcmp(CRM_OP_PING, op) == 0) {
cib_answer =
createPingAnswerFragment(CRM_SYSTEM_CIB, "ok");
} else if (strcmp(CRM_OP_BUMP, op) == 0) {
tmpCib = get_cib_copy();
CRM_DEBUG("Handling a %s for section=%s of the cib",
CRM_OP_BUMP, section);
// modify the timestamp
set_node_tstamp(tmpCib);
old_value =
xmlGetProp(get_the_CIB(), XML_ATTR_GENERATION);
if(old_value != NULL) {
new_value = (char*)crm_malloc(128*(sizeof(char)));
int_value = atoi(old_value);
sprintf(new_value, "%d", ++int_value);
} else {
new_value = crm_strdup("0");
}
cl_log(LOG_DEBUG, "Generation %d(%s)->%s",
int_value, old_value, new_value);
set_xml_property_copy(tmpCib, XML_ATTR_GENERATION, new_value);
crm_free(new_value);
if(activateCibXml(tmpCib, CIB_FILENAME) >= 0) {
verbose = XML_BOOLEAN_TRUE;
} else {
*result = CIBRES_FAILED;
}
} else if (strcmp("query", op) == 0) {
CRM_DEBUG("Handling a query for section=%s of the cib",
section);
/* force a pick-up of the relevant section before
* returning
*/
verbose = XML_BOOLEAN_TRUE;
} else if (strcmp(CRM_OP_ERASE, op) == 0) {
xmlNodePtr new_cib = createEmptyCib();
// Preserve generation counters etc
copy_in_properties(new_cib, get_the_CIB());
if (activateCibXml(new_cib, CIB_FILENAME) < 0) {
*result = CIBRES_FAILED;
}
} else if (strcmp(CRM_OP_CREATE, op) == 0) {
update_the_cib = TRUE;
cib_update_op = CIB_OP_ADD;
} else if (strcmp(CRM_OP_UPDATE, op) == 0
|| strcmp(CRM_OP_WELCOME, op) == 0
|| strcmp(CRM_OP_SHUTDOWN_REQ, op) == 0) {
update_the_cib = TRUE;
cib_update_op = CIB_OP_MODIFY;
} else if (strcmp(CRM_OP_DELETE, op) == 0) {
update_the_cib = TRUE;
cib_update_op = CIB_OP_DELETE;
} else if (strcmp(CRM_OP_REPLACE, op) == 0) {
CRM_DEBUG("Replacing section=%s of the cib", section);
section = xmlGetProp(fragment, XML_ATTR_SECTION);
if (section == NULL
|| strlen(section) == 0
|| strcmp("all", section) == 0) {
tmpCib = copy_xml_node_recursive(
find_xml_node(fragment, XML_TAG_CIB));
} else {
tmpCib = copy_xml_node_recursive(get_the_CIB());
replace_section(section, tmpCib, fragment);
}
/*if(check_generation(cib_updates, tmpCib) == FALSE)
*result = "discarded old update";
else */
if (activateCibXml(tmpCib, CIB_FILENAME) < 0)
*result = CIBRES_FAILED;
} else {
*result = CIBRES_FAILED_NOTSUPPORTED;
cl_log(LOG_ERR, "Action [%s] is not supported by the CIB", op);
}
if (update_the_cib) {
- CRM_DEBUG("Backing up CIB");
tmpCib = copy_xml_node_recursive(get_the_CIB());
section = xmlGetProp(fragment, XML_ATTR_SECTION);
CRM_DEBUG("Updating section=%s of the cib (op=%s)",
section, op);
// should we be doing this?
// do logging
// make changes to a temp copy then activate
if(section == NULL) {
cl_log(LOG_ERR, "No section specified in %s",
XML_ATTR_FILTER_TYPE);
*result = CIBRES_FAILED_NOSECTION;
} else if(strcmp("all", section) == 0
&& cib_update_op == CIB_OP_DELETE) {
// delete
/* order is no longer important here */
updateList(tmpCib, fragment, failed, cib_update_op,
XML_CIB_TAG_STATUS);
updateList(tmpCib, fragment, failed, cib_update_op,
XML_CIB_TAG_CONSTRAINTS);
updateList(tmpCib, fragment, failed, cib_update_op,
XML_CIB_TAG_RESOURCES);
updateList(tmpCib, fragment, failed, cib_update_op,
XML_CIB_TAG_NODES);
} else if(strcmp("all", section) == 0) {
/* order is no longer important here */
updateList(tmpCib, fragment, failed, cib_update_op,
XML_CIB_TAG_NODES);
updateList(tmpCib, fragment, failed, cib_update_op,
XML_CIB_TAG_RESOURCES);
updateList(tmpCib, fragment, failed, cib_update_op,
XML_CIB_TAG_CONSTRAINTS);
updateList(tmpCib, fragment, failed, cib_update_op,
XML_CIB_TAG_STATUS);
} else {
*result = updateList(tmpCib, fragment, failed,
cib_update_op, section);
}
- CRM_DEBUG("Activating temporary CIB");
+ CRM_NOTE("Activating temporary CIB");
/* if(check_generation(cib_updates, tmpCib) == FALSE) */
/* status = "discarded old update"; */
/* else */
if (activateCibXml(tmpCib, CIB_FILENAME) < 0) {
*result = CIBRES_FAILED_ACTIVATION;
} else if (failed->children != NULL) {
*result = CIBRES_FAILED;
}
CRM_DEBUG("CIB update status: %d", *result);
}
output_section = section;
if (failed->children != NULL || *result != CIBRES_OK) {
cib_answer = createCibFragmentAnswer(NULL /*"all"*/, failed);
} else if (verbose != NULL && strcmp(XML_BOOLEAN_TRUE, verbose) == 0) {
cib_answer = createCibFragmentAnswer(output_section, failed);
}
free_xml(failed);
#ifdef MSG_LOG
fprintf(msg_cib_strm, "[Reply (%s)]\t%s\n",
op, dump_xml_node(cib_answer, FALSE));
fflush(msg_cib_strm);
#endif
FNRET(cib_answer);
}
gboolean
replace_section(const char *section, xmlNodePtr tmpCib, xmlNodePtr fragment)
{
xmlNodePtr parent = NULL,
cib_updates = NULL,
new_section = NULL,
old_section = NULL;
FNIN();
cib_updates = find_xml_node(fragment, XML_TAG_CIB);
/* find the old and new versions of the section */
new_section = get_object_root(section, cib_updates);
old_section = get_object_root(section, tmpCib);
if(old_section == NULL) {
cl_log(LOG_ERR,
"The CIB is corrupt, cannot replace missing section %s",
section);
FNRET(FALSE);
} else if(new_section == NULL) {
cl_log(LOG_ERR,
"The CIB is corrupt, cannot set section %s to nothing",
section);
FNRET(FALSE);
}
parent = old_section->parent;
/* unlink and free the old one */
unlink_xml_node(old_section);
free_xml(old_section);
/* add the new copy */
add_node_copy(parent, new_section);
FNRET(TRUE);
}
enum cib_result
updateList(xmlNodePtr local_cib, xmlNodePtr update_fragment, xmlNodePtr failed,
int operation, const char *section)
{
xmlNodePtr child = NULL;
xmlNodePtr this_section = get_object_root(section, local_cib);
xmlNodePtr cib_updates = find_xml_node(update_fragment, XML_TAG_CIB);
xmlNodePtr xml_section = get_object_root(section, cib_updates);
if (section == NULL || xml_section == NULL) {
cl_log(LOG_ERR, "Section %s not found in message."
" CIB update is corrupt, ignoring.", section);
return CIBRES_FAILED_NOSECTION;
}
if(CIB_OP_NONE > operation > CIB_OP_MAX) {
cl_log(LOG_ERR, "Invalid operation on section %s", section);
return CIBRES_FAILED;
}
set_node_tstamp(this_section);
child = xml_section->children;
while(child != NULL) {
if(operation == CIB_OP_DELETE) {
update_results(failed, child, operation,
delete_cib_object(this_section, child));
} else if(operation == CIB_OP_MODIFY) {
update_results(failed, child, operation,
update_cib_object(this_section, child,
FALSE));
} else {
update_results(failed, child, operation,
add_cib_object(this_section, child));
}
child = child->next;
}
if (failed->children != NULL)
return CIBRES_FAILED;
else
return CIBRES_OK;
}
xmlNodePtr
createCibFragmentAnswer(const char *section, xmlNodePtr failed)
{
xmlNodePtr fragment = create_xml_node(NULL, XML_TAG_FRAGMENT);
FNIN();
set_xml_property_copy(fragment, XML_ATTR_SECTION, section);
if (section == NULL
|| strlen(section) == 0
|| strcmp("all", section) == 0) {
add_node_copy(fragment, get_the_CIB());
} else {
xmlNodePtr cib = create_xml_node(fragment, XML_TAG_CIB);
add_node_copy(cib, get_object_root(section, get_the_CIB()));
copy_in_properties(cib, get_the_CIB());
}
if (failed != NULL && failed->children != NULL) {
add_node_copy(fragment, failed);
}
FNRET(fragment);
}
gboolean
check_generation(xmlNodePtr newCib, xmlNodePtr oldCib)
{
char *new_value = xmlGetProp(newCib, XML_ATTR_GENERATION);
char *old_value = xmlGetProp(oldCib, XML_ATTR_GENERATION);
int int_new_value = -1;
int int_old_value = -1;
if(old_value != NULL) int_old_value = atoi(old_value);
if(new_value != NULL) int_new_value = atoi(new_value);
if(int_new_value >= int_old_value) {
return TRUE;
} else {
cl_log(LOG_ERR, "Generation from update (%d) is older than %d",
int_new_value, int_old_value);
}
return FALSE;
}
gboolean
update_results(xmlNodePtr failed,
xmlNodePtr target,
int operation,
int return_code)
{
gboolean was_error = FALSE;
const char *error_msg = NULL;
const char *operation_msg = NULL;
xmlNodePtr xml_node;
FNIN();
if (return_code != CIBRES_OK)
{
error_msg = cib_error2string(return_code);
operation_msg = cib_op2string(operation);
xml_node = create_xml_node(failed, XML_FAIL_TAG_CIB);
was_error = TRUE;
set_xml_property_copy(xml_node,
XML_FAILCIB_ATTR_ID,
ID(target));
set_xml_property_copy(xml_node,
XML_FAILCIB_ATTR_OBJTYPE,
TYPE(target));
set_xml_property_copy(xml_node,
XML_FAILCIB_ATTR_OP,
operation_msg);
set_xml_property_copy(xml_node,
XML_FAILCIB_ATTR_REASON,
error_msg);
cl_log(LOG_DEBUG,
"Action %s failed: %s (cde=%d)",
operation_msg,
error_msg,
return_code);
}
FNRET(was_error);
}
diff --git a/crm/common/ipcutils.c b/crm/common/ipcutils.c
index 4c0b6803ed..9579f4658f 100644
--- a/crm/common/ipcutils.c
+++ b/crm/common/ipcutils.c
@@ -1,553 +1,553 @@
-/* $Id: ipcutils.c,v 1.29 2004/06/01 12:25:15 andrew Exp $ */
+/* $Id: ipcutils.c,v 1.30 2004/06/01 16:12:49 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 <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <crm/crm.h>
#include <hb_api.h>
#include <ha_msg.h>
#include <clplumbing/ipc.h>
#include <clplumbing/Gmain_timeout.h>
#include <clplumbing/cl_log.h>
#include <clplumbing/cl_signal.h>
#include <clplumbing/lsb_exitcodes.h>
#include <clplumbing/uids.h>
#include <clplumbing/realtime.h>
#include <clplumbing/GSource.h>
#include <clplumbing/cl_poll.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
//#include <time.h> // for getNow()
#include <ipcutils.h>
/*
#include <crm/common/ipcutils.h>
#include <crm/common/msgutils.h>
*/
#include <xmlutils.h>
#include <msgutils.h>
#include <crm/msg_xml.h>
#include <crm/dmalloc_wrapper.h>
FILE *msg_out_strm = NULL;
IPC_Message *create_simple_message(char *text, IPC_Channel *ch);
void
LinkStatus(const char * node, const char * lnk,
const char * status ,void * private)
{
// put something here
}
gboolean
send_xmlipc_message(IPC_Channel *ipc_client, xmlNodePtr msg)
{
int log_level = LOG_DEBUG;
char *xml_message = NULL;
IPC_Message *cib_dump = NULL;
gboolean res;
FNIN();
xml_message = dump_xml(msg);
cib_dump =
create_simple_message(xml_message, ipc_client);
res = send_ipc_message(ipc_client, cib_dump);
crm_free(xml_message);
if(res == FALSE) {
log_level = LOG_ERR;
}
cl_log(log_level,
"Sending IPC message (ref=%s) to %s@%s %s.",
xmlGetProp(msg, XML_ATTR_REFERENCE),
xmlGetProp(msg, XML_ATTR_SYSTO),
xmlGetProp(msg, XML_ATTR_HOSTTO),
res?"succeeded":"failed");
FNRET(res);
}
gboolean
send_xmlha_message(ll_cluster_t *hb_fd, xmlNodePtr root)
{
int xml_len = -1;
int send_result = -1;
char *xml_text = NULL;
const char *host_to = NULL;
const char *sys_to = NULL;
struct ha_msg *msg = NULL;
gboolean all_is_good = TRUE;
gboolean broadcast = FALSE;
int log_level = LOG_DEBUG;
xmlNodePtr opts = find_xml_node(root, XML_TAG_OPTIONS);
const char *op = xmlGetProp(opts, XML_ATTR_OP);
#ifdef MSG_LOG
char *msg_text = NULL;
#endif
FNIN();
if (root == NULL) {
cl_log(LOG_ERR, "Attempt to send NULL Message via HA failed.");
all_is_good = FALSE;
}
host_to = xmlGetProp(root, XML_ATTR_HOSTTO);
sys_to = xmlGetProp(root, XML_ATTR_SYSTO);
if (all_is_good) {
msg = ha_msg_new(4);
ha_msg_add(msg, F_TYPE, "CRM");
ha_msg_add(msg, F_COMMENT, "A CRM xml message");
xml_text = dump_xml(root);
xml_len = strlen(xml_text);
if (xml_text == NULL || xml_len <= 0) {
cl_log(LOG_ERR,
"Failed sending an invalid XML Message via HA");
all_is_good = FALSE;
xml_message_debug(root, "Bad message was");
} else {
if(ha_msg_add(msg, "xml", xml_text) == HA_FAIL) {
cl_log(LOG_ERR,
"Could not add xml to HA message");
all_is_good = FALSE;
}
}
}
if (all_is_good) {
if (sys_to == NULL || strlen(sys_to) == 0)
{
cl_log(LOG_ERR,
"You did not specify a destination sub-system"
" for this message.");
all_is_good = FALSE;
}
}
/* There are a number of messages may not need to be ordered.
* At a later point perhaps we should detect them and send them
* as unordered messages.
*/
if (all_is_good) {
if (host_to == NULL
|| strlen(host_to) == 0) {
broadcast = TRUE;
send_result =
hb_fd->llc_ops->sendclustermsg(hb_fd, msg);
}
else {
send_result = hb_fd->llc_ops->send_ordered_nodemsg(
hb_fd, msg, host_to);
}
if(send_result != HA_OK)
all_is_good = FALSE;
}
if(all_is_good == FALSE) {
log_level = LOG_ERR;
}
if(log_level == LOG_ERR
|| (safe_str_neq(op, CRM_OP_HBEAT))) {
cl_log(log_level,
"Sending %s HA message (ref=%s, len=%d) to %s@%s %s.",
broadcast?"broadcast":"directed",
xmlGetProp(root, XML_ATTR_REFERENCE), xml_len,
sys_to, host_to==NULL?"<all>":host_to,
all_is_good?"succeeded":"failed");
}
#ifdef MSG_LOG
msg_text = dump_xml(root);
if(msg_out_strm == NULL) {
msg_out_strm = fopen("/tmp/outbound.log", "w");
}
fprintf(msg_out_strm, "[%d HA (%s:%d)]\t%s\n",
all_is_good,
xmlGetProp(root, XML_ATTR_REFERENCE),
send_result,
msg_text);
fflush(msg_out_strm);
crm_free(msg_text);
if(msg != NULL) {
ha_msg_del(msg);
}
#endif
FNRET(all_is_good);
}
gboolean
send_ipc_message(IPC_Channel *ipc_client, IPC_Message *msg)
{
int lpc = 0;
gboolean all_is_good = TRUE;
FNIN();
if (msg == NULL) {
cl_log(LOG_WARNING, "cant send NULL message");
all_is_good = FALSE;
}
else if (msg->msg_len <= 0) {
cl_log(LOG_WARNING, "cant send 0 sized message");
all_is_good = FALSE;
}
else if (msg->msg_len > MAXDATASIZE) {
cl_log(LOG_WARNING, "cant send msg... too big");
all_is_good = FALSE;
}
/* CRM_DEBUG("Sending message: %s", (char*)msg->msg_body); */
CRM_DEBUG("Message is%s valid to send", all_is_good?"":" not");
if (ipc_client == NULL) {
all_is_good = FALSE;
}
CRM_DEBUG("IPC Client is%s set.", all_is_good?"":" not");
if (all_is_good) {
while(lpc++ < MAX_IPC_FAIL
&& ipc_client->ops->send(ipc_client, msg) == IPC_FAIL)
{
cl_log(LOG_WARNING, "ipc channel blocked");
cl_shortsleep();
}
}
if (lpc == MAX_IPC_FAIL) {
cl_log(LOG_ERR,
"Could not send IPC, message. Channel is dead.");
all_is_good = FALSE;
}
FNRET(all_is_good);
}
IPC_Message *
create_simple_message(char *text, IPC_Channel *ch)
{
// char str[256];
IPC_Message *ack_msg = NULL;
FNIN();
if (text == NULL) FNRET(NULL);
ack_msg = (IPC_Message *)crm_malloc(sizeof(IPC_Message));
ack_msg->msg_private = NULL;
ack_msg->msg_done = NULL;
ack_msg->msg_body = text;
ack_msg->msg_ch = ch;
ack_msg->msg_len = strlen(text)+1;
FNRET(ack_msg);
}
gboolean
default_ipc_input_dispatch(IPC_Channel *client, gpointer user_data)
{
xmlNodePtr root;
xmlNodePtr options;
IPC_Message *msg = NULL;
const char *op;
FNIN();
msg = get_ipc_message(client);
if (msg) {
root = find_xml_in_ipcmessage(msg, TRUE);
validate_crm_message(root, NULL, NULL, NULL);
options = find_xml_node(root, XML_TAG_OPTIONS);
op = xmlGetProp(options, XML_ATTR_OP);
if(op != NULL && strcmp(op, CRM_OP_QUIT) == 0) {
cl_log(LOG_WARNING,
"The CRMd has asked us to exit... complying");
exit(0);
}
} else if (client->ch_status == IPC_DISCONNECT) {
cl_log(LOG_ERR, "The server has left us: Shutting down...NOW");
exit(1); /* Server disconnects should be fatal,
* but I will do it a little more gracefully :)
*/
FNRET(FALSE); /* This conection is hosed */
}
FNRET(TRUE); /* TOBEDONE */
}
xmlNodePtr
find_xml_in_hamessage(const struct ha_msg* msg)
{
const char *xml;
xmlDocPtr doc;
xmlNodePtr root;
FNIN();
if (msg == NULL) {
cl_log(LOG_INFO,
"**** ha_crm_msg_callback called on a NULL message");
FNRET(NULL);
}
#if 0
cl_log(LOG_DEBUG, "[F_TYPE=%s]", ha_msg_value(msg, F_TYPE));
cl_log(LOG_DEBUG, "[F_ORIG=%s]", ha_msg_value(msg, F_ORIG));
cl_log(LOG_DEBUG, "[F_TO=%s]", ha_msg_value(msg, F_TO));
cl_log(LOG_DEBUG, "[F_COMMENT=%s]", ha_msg_value(msg, F_COMMENT));
cl_log(LOG_DEBUG, "[F_XML=%s]", ha_msg_value(msg, "xml"));
// cl_log(LOG_DEBUG, "[F_=%s]", ha_msg_value(ha_msg, F_));
#endif
if (strcmp("CRM", ha_msg_value(msg, F_TYPE)) != 0) {
cl_log(LOG_INFO, "Received a (%s) message by mistake.",
ha_msg_value(msg, F_TYPE));
FNRET(NULL);
}
xml = ha_msg_value(msg, "xml");
if (xml == NULL) {
cl_log(LOG_INFO, "No XML attached to this message.");
FNRET(NULL);
}
doc = xmlParseMemory(xml, strlen(xml));
if (doc == NULL) {
cl_log(LOG_INFO, "XML Buffer was not valid.");
FNRET(NULL);
}
root = xmlDocGetRootElement(doc);
if (root == NULL) {
cl_log(LOG_INFO, "Root node was NULL.");
FNRET(NULL);
}
FNRET(root);
}
xmlNodePtr
find_xml_in_ipcmessage(IPC_Message *msg, gboolean do_free)
{
char *buffer = NULL;
xmlDocPtr doc;
xmlNodePtr root;
FNIN();
if (msg == NULL) {
- CRM_DEBUG("IPC Message was empty...");
+ CRM_NOTE("IPC Message was empty...");
FNRET(NULL);
}
buffer = (char*)msg->msg_body;
doc = xmlParseMemory(buffer, strlen(buffer));
if (do_free) msg->msg_done(msg);
if (doc == NULL) {
cl_log(LOG_INFO,
"IPC Message did not contain an XML buffer...");
FNRET(NULL);
}
root = xmlDocGetRootElement(doc);
if (root == NULL) {
cl_log(LOG_INFO, "Root node was NULL.");
FNRET(NULL);
}
FNRET(root);
}
void
default_ipc_input_destroy(gpointer user_data)
{
FNIN();
FNOUT();
}
int
init_server_ipc_comms(
const char *child,
gboolean (*channel_client_connect)(IPC_Channel *newclient,
gpointer user_data),
void (*channel_input_destroy)(gpointer user_data))
{
/* the clients wait channel is the other source of events.
* This source delivers the clients connection events.
* listen to this source at a relatively lower priority.
*/
char commpath[SOCKET_LEN];
IPC_WaitConnection *wait_ch;
FNIN();
sprintf(commpath, WORKING_DIR "/%s", child);
wait_ch = wait_channel_init(commpath);
if (wait_ch == NULL) FNRET(1);
G_main_add_IPC_WaitConnection(G_PRIORITY_LOW,
wait_ch,
NULL,
FALSE,
channel_client_connect,
wait_ch, // user data passed to ??
channel_input_destroy);
cl_log(LOG_DEBUG, "Listening on: %s", commpath);
FNRET(0);
}
IPC_Channel *
init_client_ipc_comms(const char *child,
gboolean (*dispatch)(IPC_Channel* source_data
,gpointer user_data),
crmd_client_t *client_data)
{
IPC_Channel *ch;
GHashTable * attrs;
GCHSource *the_source = NULL;
void *callback_data = client_data;
static char path[] = IPC_PATH_ATTR;
char *commpath = NULL;
int local_socket_len = 2; // 2 = '/' + '\0'
FNIN();
local_socket_len += strlen(child);
local_socket_len += strlen(WORKING_DIR);
commpath = (char*)crm_malloc(sizeof(char)*local_socket_len);
sprintf(commpath, WORKING_DIR "/%s", child);
commpath[local_socket_len - 1] = '\0';
cl_log(LOG_DEBUG, "Attempting to talk on: %s", commpath);
attrs = g_hash_table_new(g_str_hash,g_str_equal);
g_hash_table_insert(attrs, path, commpath);
ch = ipc_channel_constructor(IPC_ANYTYPE, attrs);
g_hash_table_destroy(attrs);
if (ch == NULL) {
cl_log(LOG_CRIT,
"Could not access channel on: %s",
commpath);
} else if (ch->ops->initiate_connection(ch) != IPC_OK) {
cl_log(LOG_CRIT, "Could not init comms on: %s", commpath);
FNRET(NULL);
}
if(callback_data == NULL)
callback_data = ch;
ch->ops->set_recv_qlen(ch, 100);
ch->ops->set_send_qlen(ch, 100);
the_source = G_main_add_IPC_Channel(G_PRIORITY_LOW,
ch,
FALSE,
dispatch,
callback_data,
default_ipc_input_destroy);
cl_log(LOG_DEBUG, "Processing of %s complete", commpath);
FNRET(ch);
}
IPC_WaitConnection *
wait_channel_init(char daemonsocket[])
{
IPC_WaitConnection *wait_ch;
mode_t mask;
char path[] = IPC_PATH_ATTR;
GHashTable * attrs;
FNIN();
attrs = g_hash_table_new(g_str_hash,g_str_equal);
g_hash_table_insert(attrs, path, daemonsocket);
mask = umask(0);
wait_ch = ipc_wait_conn_constructor(IPC_ANYTYPE, attrs);
if (wait_ch == NULL) {
cl_perror("Can't create wait channel of type %s",
IPC_ANYTYPE);
exit(1);
}
mask = umask(mask);
g_hash_table_destroy(attrs);
FNRET(wait_ch);
}
IPC_Message *
get_ipc_message(IPC_Channel *a_channel)
{
IPC_Message *msg = NULL;
FNIN();
if(a_channel->ops->is_message_pending(a_channel) == TRUE) {
if (a_channel->ch_status == IPC_DISCONNECT) {
/* The pending message was IPC_DISCONNECT */
cl_log(LOG_INFO, "get_ipc_message: received HUP");
FNRET(msg);
}
if(a_channel->ops->recv(a_channel, &msg) != IPC_OK) {
perror("Receive failure:");
FNRET(msg);
}
cl_log(LOG_INFO, "Got message [body=%s]",
(char*)msg->msg_body);
}
FNRET(msg);
}
diff --git a/crm/common/xmlutils.c b/crm/common/xmlutils.c
index a52411961b..60aa3ad41f 100644
--- a/crm/common/xmlutils.c
+++ b/crm/common/xmlutils.c
@@ -1,838 +1,836 @@
-/* $Id: xmlutils.c,v 1.30 2004/06/01 12:25:15 andrew Exp $ */
+/* $Id: xmlutils.c,v 1.31 2004/06/01 16:12:49 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 <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <libxml/tree.h>
#include <clplumbing/ipc.h>
#include <clplumbing/cl_log.h>
#include <crm/crm.h>
#include <xmlutils.h>
#include <crm/msg_xml.h>
#include <crm/dmalloc_wrapper.h>
void dump_array(int log_level, const char *message,
const char **array, int depth);
xmlNodePtr
find_xml_node_nested(xmlNodePtr root, const char **search_path, int len)
{
int j;
xmlNodePtr child;
xmlNodePtr lastMatch;
FNIN();
if (root == NULL) {
FNRET(NULL);
}
if(search_path == NULL) {
- CRM_DEBUG("Will never find NULL :)");
+ CRM_NOTE("Will never find NULL");
FNRET(NULL);
}
#ifdef XML_TRACE
dump_array(LOG_DEBUG,
"Looking for.",
search_path, len);
#endif
child = root->children, lastMatch = NULL;
for (j=0; j < len; ++j) {
gboolean is_found = FALSE;
if (search_path[j] == NULL) {
len = j; /* a NULL also means stop searching */
break;
}
while(child != NULL) {
const char * child_name = (const char*)child->name;
#ifdef XML_TRACE
CRM_DEBUG("comparing (%s) with (%s).",
search_path[j],
child->name);
#endif
if (strcmp(child_name, search_path[j]) == 0) {
lastMatch = child;
child = lastMatch->children;
#ifdef XML_TRACE
CRM_DEBUG("found node (%s) @line (%ld).",
search_path[j],
xmlGetLineNo(child));
#endif
is_found = TRUE;
break;
}
child = child->next;
}
if (is_found == FALSE) {
#ifdef XML_TRACE
CRM_DEBUG(
"No more siblings left... %s cannot be found.",
search_path[j]);
#endif
break;
}
}
if (j == len
&& lastMatch != NULL
&& strcmp(lastMatch->name, search_path[j-1]) == 0) {
#ifdef XML_TRACE
CRM_DEBUG("returning node (%s).",
xmlGetNodePath(lastMatch));
#endif
FNRET(lastMatch);
}
dump_array(LOG_WARNING,
"Could not find the full path to the node you specified.",
search_path, len);
cl_log(LOG_WARNING,"Closest point was node (%s) starting from %s.",
xmlGetNodePath(lastMatch), root?root->name:NULL);
FNRET(NULL);
}
const char *
get_xml_attr(xmlNodePtr parent,
const char *node_name, const char *attr_name,
gboolean error)
{
if(node_name == NULL) {
// get it from the current node
return get_xml_attr_nested(parent, NULL, 0, attr_name, error);
}
return get_xml_attr_nested(parent, &node_name, 1, attr_name, error);
}
const char *
get_xml_attr_nested(xmlNodePtr parent,
const char **node_path, int length,
const char *attr_name, gboolean error)
{
const char *attr_value = NULL;
xmlNodePtr attr_parent = NULL;
if(parent == NULL) {
cl_log(LOG_ERR, "Can not find attribute %s in NULL parent",
attr_name);
return NULL;
}
if(attr_name == NULL || strlen(attr_name) == 0) {
cl_log(LOG_ERR, "Can not find attribute with no name in %s",
xmlGetNodePath(parent));
return NULL;
}
if(length == 0) {
attr_parent = parent;
} else {
attr_parent = find_xml_node_nested(parent, node_path, length);
if(attr_parent == NULL && error) {
cl_log(LOG_ERR, "No node at the path you specified.");
return NULL;
}
}
attr_value = xmlGetProp(attr_parent, attr_name);
if((attr_value == NULL || strlen(attr_value) == 0) && error) {
cl_log(LOG_ERR,
"No value present for %s at %s",
attr_name, xmlGetNodePath(attr_parent));
return NULL;
}
return attr_value;
}
xmlNodePtr
set_xml_attr(xmlNodePtr parent,
const char *node_name,
const char *attr_name,
const char *attr_value,
gboolean create)
{
if(node_name == NULL) {
// set it on the current node
return set_xml_attr_nested(parent, NULL, 0,
attr_name, attr_value, create);
}
return set_xml_attr_nested(parent, &node_name, 1,
attr_name, attr_value, create);
}
xmlNodePtr
set_xml_attr_nested(xmlNodePtr parent,
const char **node_path, int length,
const char *attr_name,
const char *attr_value,
gboolean create)
{
xmlAttrPtr result = NULL;
xmlNodePtr attr_parent = NULL;
xmlNodePtr create_parent = NULL;
xmlNodePtr tmp;
if(parent == NULL && create == FALSE) {
cl_log(LOG_ERR, "Can not set attribute in NULL parent");
return NULL;
}
if(attr_name == NULL || strlen(attr_name) == 0) {
cl_log(LOG_ERR, "Can not set attribute to %s with no name",
attr_value);
return NULL;
}
if(length == 0 && parent != NULL) {
attr_parent = parent;
} else if(length == 0 || node_path == NULL
|| *node_path == NULL || strlen(*node_path) == 0) {
cl_log(LOG_ERR,
"Can not create parent to set attribute %s=%s on",
attr_name, attr_value);
return NULL;
} else {
attr_parent = find_xml_node_nested(parent, node_path, length);
}
if(create && attr_parent == NULL) {
int j = 0;
attr_parent = parent;
for (j=0; j < length; ++j) {
if (node_path[j] == NULL) {
break;
}
tmp =
find_xml_node(attr_parent, node_path[j]);
if(tmp == NULL) {
attr_parent = create_xml_node(attr_parent,
node_path[j]);
if(j==0) {
create_parent = attr_parent;
}
} else {
attr_parent = tmp;
}
}
} else if(attr_parent == NULL) {
cl_log(LOG_ERR, "Can not find parent to set attribute on");
return NULL;
}
result = set_xml_property_copy(attr_parent, attr_name, attr_value);
if(result == NULL) {
cl_log(LOG_WARNING,
"Could not set %s=%s at %s",
attr_name, attr_value, xmlGetNodePath(attr_parent));
}
if(create_parent != NULL) {
return create_parent;
}
return parent;
}
xmlNodePtr
find_xml_node(xmlNodePtr root, const char * search_path)
{
if(root == NULL) return NULL;
return find_xml_node_nested(root, &search_path, 1);
}
xmlNodePtr
find_entity(xmlNodePtr parent,
const char *node_name,
const char *id,
gboolean siblings)
{
return find_entity_nested(parent,
node_name,
NULL,
NULL,
id,
siblings);
}
xmlNodePtr
find_entity_nested(xmlNodePtr parent,
const char *node_name,
const char *elem_filter_name,
const char *elem_filter_value,
const char *id,
gboolean siblings)
{
xmlNodePtr child;
FNIN();
#ifdef XML_TRACE
cl_log(LOG_DEBUG, "Looking for %s elem with id=%s.", node_name, id);
#endif
while(parent != NULL) {
#ifdef XML_TRACE
CRM_DEBUG("examining (%s).", xmlGetNodePath(parent));
#endif
child = parent->children;
while(child != NULL) {
#ifdef XML_TRACE
CRM_DEBUG("looking for (%s) [name].", node_name);
#endif
if (node_name != NULL
&& strcmp(child->name, node_name) != 0) {
#ifdef XML_TRACE
CRM_DEBUG(
"skipping entity (%s=%s) [node_name].",
xmlGetNodePath(child), child->name);
#endif
break;
} else if (elem_filter_name != NULL
&& elem_filter_value != NULL) {
const char* child_value = (const char*)
xmlGetProp(child, elem_filter_name);
#ifdef XML_TRACE
cl_log(LOG_DEBUG,
"comparing (%s) with (%s) [attr_value].",
child_value, elem_filter_value);
#endif
if (strcmp(child_value, elem_filter_value)) {
#ifdef XML_TRACE
CRM_DEBUG("skipping entity (%s) [attr_value].",
xmlGetNodePath(child));
#endif
break;
}
}
#ifdef XML_TRACE
cl_log(LOG_DEBUG,
"looking for entity (%s) in %s.",
id, xmlGetNodePath(child));
#endif
while(child != NULL) {
#ifdef XML_TRACE
cl_log(LOG_DEBUG,
"looking for entity (%s) in %s.",
id, xmlGetNodePath(child));
#endif
xmlChar *child_id =
xmlGetProp(child, XML_ATTR_ID);
if (child_id == NULL) {
cl_log(LOG_CRIT,
"Entity (%s) has id=NULL..."
"Cib not valid!",
xmlGetNodePath(child));
} else if (strcmp(id, child_id) == 0) {
#ifdef XML_TRACE
CRM_DEBUG("found entity (%s).", id);
#endif
FNRET(child);
}
child = child->next;
}
}
if (siblings == TRUE) {
#ifdef XML_TRACE
- CRM_DEBUG("Nothing yet... checking siblings");
+ CRM_NOTE("Nothing yet... checking siblings");
#endif
parent = parent->next;
} else
parent = NULL;
}
cl_log(LOG_INFO,
"Couldnt find anything appropriate for %s elem with id=%s.",
node_name, id);
FNRET(NULL);
}
void
copy_in_properties(xmlNodePtr target, xmlNodePtr src)
{
if(src == NULL) {
cl_log(LOG_WARNING, "No node to copy properties from");
} else if (src->properties == NULL) {
cl_log(LOG_INFO, "No properties to copy");
} else if (target == NULL) {
cl_log(LOG_WARNING, "No node to copy properties into");
} else {
#ifndef USE_BUGGY_LIBXML
xmlAttrPtr prop_iter = NULL;
FNIN();
prop_iter = src->properties;
while(prop_iter != NULL) {
const char *local_prop_name = prop_iter->name;
const char *local_prop_value =
xmlGetProp(src, local_prop_name);
set_xml_property_copy(target,
local_prop_name,
local_prop_value);
prop_iter = prop_iter->next;
}
#else
xmlCopyPropList(target, src->properties);
#endif
}
FNOUT();
}
char *
dump_xml(xmlNodePtr msg)
{
FNIN();
FNRET(dump_xml_node(msg, FALSE));
}
void
xml_message_debug(xmlNodePtr msg, const char *text)
{
char *msg_buffer;
FNIN();
if(msg == NULL) {
CRM_DEBUG("%s: %s",
text==NULL?"<null>":text,"<null>");
FNOUT();
}
msg_buffer = dump_xml_node(msg, FALSE);
CRM_DEBUG("%s: %s",
text==NULL?"<null>":text,
msg_buffer==NULL?"<null>":msg_buffer);
crm_free(msg_buffer);
FNOUT();
}
char *
dump_xml_node(xmlNodePtr msg, gboolean whole_doc)
{
int lpc = 0;
int msg_size = -1;
xmlChar *xml_message = NULL;
xmlBufferPtr xml_buffer;
FNIN();
if (msg == NULL) FNRET(NULL);
xmlInitParser();
if (whole_doc) {
if (msg->doc == NULL) {
xmlDocPtr foo = xmlNewDoc("1.0");
xmlDocSetRootElement(foo, msg);
xmlSetTreeDoc(msg,foo);
}
xmlDocDumpMemory(msg->doc, &xml_message, &msg_size);
} else {
#ifdef XML_TRACE
CRM_DEBUG("mem used by xml: %d", xmlMemUsed());
xmlMemoryDump ();
#endif
xml_buffer = xmlBufferCreate();
msg_size = xmlNodeDump(xml_buffer, msg->doc, msg, 0, 0);
xml_message =
(xmlChar*)crm_strdup(xmlBufferContent(xml_buffer));
xmlBufferFree(xml_buffer);
if (!xml_message) {
cl_log(LOG_ERR,
"memory allocation failed in dump_xml_node()");
}
}
xmlCleanupParser();
// HA wont send messages with newlines in them.
for(; xml_message != NULL && lpc < msg_size; lpc++)
if (xml_message[lpc] == '\n')
xml_message[lpc] = ' ';
FNRET((char*)xml_message);
}
xmlNodePtr
add_node_copy(xmlNodePtr new_parent, xmlNodePtr xml_node)
{
xmlNodePtr node_copy = NULL;
FNIN();
if(xml_node != NULL && new_parent != NULL) {
node_copy = copy_xml_node_recursive(xml_node);
xmlAddChild(new_parent, node_copy);
} else if(xml_node == NULL) {
cl_log(LOG_ERR, "Could not add copy of NULL node");
} else {
cl_log(LOG_ERR, "Could not add copy of node to NULL parent");
}
FNRET(node_copy);
}
xmlAttrPtr
set_xml_property_copy(xmlNodePtr node,
const xmlChar *name,
const xmlChar *value)
{
const char *parent_name = NULL;
const char *local_name = NULL;
const char *local_value = NULL;
xmlAttrPtr ret_value = NULL;
FNIN();
if(node != NULL) {
parent_name = node->name;
}
#ifdef XML_TRACE
CRM_DEBUG("[%s] Setting %s to %s", parent_name, name, value);
#endif
if (name == NULL || strlen(name) <= 0) {
ret_value = NULL;
} else if(node == NULL) {
ret_value = NULL;
} else if (value == NULL || strlen(value) <= 0) {
ret_value = NULL;
xmlUnsetProp(node, local_name);
} else {
local_value = crm_strdup(value);
local_name = crm_strdup(name);
ret_value = xmlSetProp(node, local_name, local_value);
}
FNRET(ret_value);
}
xmlNodePtr
create_xml_node(xmlNodePtr parent, const char *name)
{
const char *local_name = NULL;
const char *parent_name = NULL;
xmlNodePtr ret_value = NULL;
FNIN();
if (name == NULL || strlen(name) < 1) {
ret_value = NULL;
} else {
local_name = crm_strdup(name);
if(parent == NULL)
ret_value = xmlNewNode(NULL, local_name);
else {
parent_name = parent->name;
ret_value =
xmlNewChild(parent, NULL, local_name, NULL);
}
}
#ifdef XML_TRACE
CRM_DEBUG("Created node [%s [%s]]", parent_name, local_name);
#endif
FNRET(ret_value);
}
void
unlink_xml_node(xmlNodePtr node)
{
xmlUnlinkNode(node);
/* this helps us with frees and really should be being done by
* the library call
*/
node->doc = NULL;
}
void
free_xml(xmlNodePtr a_node)
{
FNIN();
if (a_node == NULL)
; // nothing to do
else if (a_node->doc != NULL)
xmlFreeDoc(a_node->doc);
else
{
/* make sure the node is unlinked first */
xmlUnlinkNode(a_node);
#if 0
/* set a new doc, wont delete without one? */
xmlDocPtr foo = xmlNewDoc("1.0");
xmlDocSetRootElement(foo, a_node);
xmlSetTreeDoc(a_node,foo);
xmlFreeDoc(foo);
#else
xmlFreeNode(a_node);
#endif
}
FNOUT();
}
void
set_node_tstamp(xmlNodePtr a_node)
{
char *since_epoch = (char*)crm_malloc(128*(sizeof(char)));
FNIN();
sprintf(since_epoch, "%ld", (unsigned long)time(NULL));
set_xml_property_copy(a_node, XML_ATTR_TSTAMP, since_epoch);
crm_free(since_epoch);
}
xmlNodePtr
copy_xml_node_recursive(xmlNodePtr src_node)
{
#if XML_TRACE
const char *local_name = NULL;
xmlNodePtr local_node = NULL, node_iter = NULL, local_child = NULL;
xmlAttrPtr prop_iter = NULL;
FNIN();
if(src_node != NULL && src_node->name != NULL) {
local_node = create_xml_node(NULL, src_node->name);
prop_iter = src_node->properties;
while(prop_iter != NULL) {
const char *local_prop_name = prop_iter->name;
const char *local_prop_value =
xmlGetProp(src_node, local_prop_name);
set_xml_property_copy(local_node,
local_prop_name,
local_prop_value);
prop_iter = prop_iter->next;
}
node_iter = src_node->children;
while(node_iter != NULL) {
local_child = copy_xml_node_recursive(node_iter);
if(local_child != NULL) {
xmlAddChild(local_node, local_child);
CRM_DEBUG("Copied node [%s [%s]", local_name, local_child->name);
}
node_iter = node_iter->next;
}
CRM_DEBUG("Returning [%s]", local_node->name);
FNRET(local_node);
}
- CRM_DEBUG("Returning null");
+ CRM_NOTE("Returning null");
FNRET(NULL);
#else
return xmlCopyNode(src_node, 1);
#endif
}
xmlNodePtr
string2xml(const char *input)
{
char ch = 0;
int lpc = 0, input_len = strlen(input);
gboolean more = TRUE;
gboolean inTag = FALSE;
xmlNodePtr xml_object = NULL;
const char *the_xml;
xmlDocPtr doc;
xmlBufferPtr xml_buffer = xmlBufferCreate();
for(lpc = 0; (lpc < input_len) && more; lpc++) {
ch = input[lpc];
switch(ch) {
case EOF:
case 0:
ch = 0;
more = FALSE;
xmlBufferAdd(xml_buffer, &ch, 1);
break;
case '>':
case '<':
inTag = TRUE;
if(ch == '>') inTag = FALSE;
xmlBufferAdd(xml_buffer, &ch, 1);
break;
case '\n':
case '\t':
case ' ':
ch = ' ';
if(inTag) {
xmlBufferAdd(xml_buffer, &ch, 1);
}
break;
default:
xmlBufferAdd(xml_buffer, &ch, 1);
break;
}
}
xmlInitParser();
the_xml = xmlBufferContent(xml_buffer);
doc = xmlParseMemory(the_xml, strlen(the_xml));
xmlCleanupParser();
if (doc == NULL) {
cl_log(LOG_ERR, "Malformed XML [xml=%s]", the_xml);
xmlBufferFree(xml_buffer);
return NULL;
}
xmlBufferFree(xml_buffer);
xml_object = xmlDocGetRootElement(doc);
- xml_message_debug(xml_object, "Created fragment");
-
return xml_object;
}
xmlNodePtr
file2xml(FILE *input)
{
char ch = 0;
gboolean more = TRUE;
gboolean inTag = FALSE;
xmlNodePtr xml_object = NULL;
xmlBufferPtr xml_buffer = xmlBufferCreate();
const char *the_xml;
xmlDocPtr doc;
if(input == NULL) {
cl_log(LOG_ERR, "File pointer was NULL");
return NULL;
}
while (more) {
ch = fgetc(input);
// cl_log(LOG_DEBUG, "Got [%c]", ch);
switch(ch) {
case EOF:
case 0:
ch = 0;
more = FALSE;
xmlBufferAdd(xml_buffer, &ch, 1);
break;
case '>':
case '<':
inTag = TRUE;
if(ch == '>') inTag = FALSE;
xmlBufferAdd(xml_buffer, &ch, 1);
break;
case '\n':
case '\t':
case ' ':
ch = ' ';
if(inTag) {
xmlBufferAdd(xml_buffer, &ch, 1);
}
break;
default:
xmlBufferAdd(xml_buffer, &ch, 1);
break;
}
}
xmlInitParser();
the_xml = xmlBufferContent(xml_buffer);
doc = xmlParseMemory(the_xml, strlen(the_xml));
xmlCleanupParser();
if (doc == NULL) {
cl_log(LOG_ERR, "Malformed XML [xml=%s]", the_xml);
xmlBufferFree(xml_buffer);
return NULL;
}
xmlBufferFree(xml_buffer);
xml_object = xmlDocGetRootElement(doc);
xml_message_debug(xml_object, "Created fragment");
return xml_object;
}
void
dump_array(int log_level, const char *message, const char **array, int depth)
{
int j;
if(message != NULL) {
cl_log(log_level, "%s", message);
}
cl_log(log_level, "Contents of the array:");
if(array == NULL || array[0] == NULL || depth == 0) {
cl_log(log_level, "\t<empty>");
}
for (j=0; j < depth && array[j] != NULL; j++) {
if (array[j] == NULL) break;
cl_log(log_level, "\t--> (%s).", array[j]);
}
}
diff --git a/crm/crmd/ccm.c b/crm/crmd/ccm.c
index ae2453aaf2..fa84d4f149 100644
--- a/crm/crmd/ccm.c
+++ b/crm/crmd/ccm.c
@@ -1,580 +1,577 @@
/*
* 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
*/
/* put these first so that uuid_t is defined without conflicts */
#include <portability.h>
#include <ocf/oc_event.h>
#include <ocf/oc_membership.h>
#include <crm/crm.h>
#include <crm/msg_xml.h>
#include <crm/cib.h>
#include <crmd_fsa.h>
#include <fsa_proto.h>
void oc_ev_special(const oc_ev_t *, oc_ev_class_t , int );
#include <clplumbing/GSource.h>
#include <crm/common/ipcutils.h>
#include <crm/common/xmlutils.h>
#include <crmd_messages.h>
#include <string.h>
#include <crm/dmalloc_wrapper.h>
int register_with_ccm(ll_cluster_t *hb_cluster);
void msg_ccm_join(const struct ha_msg *msg, void *foo);
void crmd_ccm_input_callback(oc_ed_t event,
void *cookie,
size_t size,
const void *data);
void ccm_event_detail(const oc_ev_membership_t *oc, oc_ed_t event);
gboolean ccm_dispatch(int fd, gpointer user_data);
gboolean ghash_node_clfree(gpointer key, gpointer value, gpointer user_data);
void ghash_update_cib_node(gpointer key, gpointer value, gpointer user_data);
#define CCM_EVENT_DETAIL 1
oc_ev_t *fsa_ev_token;
/* A_CCM_CONNECT */
enum crmd_fsa_input
do_ccm_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
int ret;
int fsa_ev_fd;
FNIN();
if(action & A_CCM_DISCONNECT){
oc_ev_unregister(fsa_ev_token);
}
if(action & A_CCM_CONNECT) {
cl_log(LOG_INFO, "Registering with CCM");
oc_ev_register(&fsa_ev_token);
cl_log(LOG_INFO, "Setting up CCM callbacks");
oc_ev_set_callback(fsa_ev_token, OC_EV_MEMB_CLASS,
crmd_ccm_input_callback,
NULL);
oc_ev_special(fsa_ev_token, OC_EV_MEMB_CLASS, 0/*don't care*/);
cl_log(LOG_INFO, "Activating CCM token");
ret = oc_ev_activate(fsa_ev_token, &fsa_ev_fd);
if (ret){
cl_log(LOG_INFO, "CCM Activation failed... unregistering");
oc_ev_unregister(fsa_ev_token);
return(I_FAIL);
}
cl_log(LOG_INFO, "CCM Activation passed... all set to go!");
//GFDSource*
G_main_add_fd(G_PRIORITY_LOW, fsa_ev_fd, FALSE, ccm_dispatch,
fsa_ev_token,
default_ipc_input_destroy);
}
if(action & ~(A_CCM_CONNECT|A_CCM_DISCONNECT)) {
cl_log(LOG_ERR, "Unexpected action %s in %s",
fsa_action2string(action), __FUNCTION__);
}
FNRET(I_NULL);
}
/* A_CCM_EVENT */
enum crmd_fsa_input
do_ccm_event(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input return_input = I_NULL;
const oc_ev_membership_t *oc = ((struct ccm_data *)data)->oc;
oc_ed_t event = *((struct ccm_data *)data)->event;
FNIN();
cl_log(LOG_INFO,"event=%s",
event==OC_EV_MS_NEW_MEMBERSHIP?"NEW MEMBERSHIP":
event==OC_EV_MS_NOT_PRIMARY?"NOT PRIMARY":
event==OC_EV_MS_PRIMARY_RESTORED?"PRIMARY RESTORED":
event==OC_EV_MS_EVICTED?"EVICTED":
"NO QUORUM MEMBERSHIP");
if(CCM_EVENT_DETAIL) {
ccm_event_detail(oc, event);
}
if (OC_EV_MS_EVICTED == event) {
/* get out... NOW! */
return_input = I_SHUTDOWN;
}
if(return_input == I_SHUTDOWN) {
; /* ignore everything, the new DC will handle it */
} else {
/* My understanding is that we will never get both
* node leaving *and* node joining callbacks at the
* same time.
*
* This logic would need to change if this is not
* the case
*/
if(oc->m_n_out !=0) {
return_input = I_NODE_LEFT;
} else if(oc->m_n_in !=0) {
/* delay the I_NODE_JOIN until they acknowledge our
* DC status and send us their CIB
*/
return_input = I_NULL;
} else {
cl_log(LOG_INFO,
"So why are we here? What CCM event happened?");
}
}
FNRET(return_input);
}
/* A_CCM_UPDATE_CACHE */
/*
* Take the opportunity to update the node status in the CIB as well
* (but only if we are the DC)
*/
enum crmd_fsa_input
do_ccm_update_cache(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input next_input = I_NULL;
int lpc, offset;
GHashTable *members = NULL;
oc_ed_t event = *((struct ccm_data *)data)->event;
const oc_ev_membership_t *oc = ((struct ccm_data *)data)->oc;
oc_node_list_t *tmp = NULL, *membership_copy = (oc_node_list_t *)
crm_malloc(sizeof(oc_node_list_t));
FNIN();
cl_log(LOG_INFO,"Updating CCM cache after a \"%s\" event.",
event==OC_EV_MS_NEW_MEMBERSHIP?"NEW MEMBERSHIP":
event==OC_EV_MS_NOT_PRIMARY?"NOT PRIMARY":
event==OC_EV_MS_PRIMARY_RESTORED?"PRIMARY RESTORED":
event==OC_EV_MS_EVICTED?"EVICTED":
"NO QUORUM MEMBERSHIP");
/*--*-- All Member Nodes --*--*/
offset = oc->m_memb_idx;
membership_copy->members_size = oc->m_n_member;
if(membership_copy->members_size > 0) {
membership_copy->members =
g_hash_table_new(g_str_hash, g_str_equal);
members = membership_copy->members;
for(lpc=0; lpc < membership_copy->members_size; lpc++) {
oc_node_t *member = (oc_node_t *)
crm_malloc(sizeof(oc_node_t));
member->node_id =
oc->m_array[offset+lpc].node_id;
member->node_born_on =
oc->m_array[offset+lpc].node_born_on;
member->node_uname =
crm_strdup(oc->m_array[offset+lpc].node_uname);
g_hash_table_insert(members, member->node_uname, member);
}
} else {
membership_copy->members = NULL;
}
/*--*-- New Member Nodes --*--*/
offset = oc->m_in_idx;
membership_copy->new_members_size = oc->m_n_in;
if(membership_copy->new_members_size > 0) {
membership_copy->new_members =
g_hash_table_new(g_str_hash, g_str_equal);
members = membership_copy->new_members;
for(lpc=0; lpc < membership_copy->new_members_size; lpc++) {
oc_node_t *member = (oc_node_t *)
crm_malloc(sizeof(oc_node_t));
member->node_id =
oc->m_array[offset+lpc].node_id;
member->node_born_on =
oc->m_array[offset+lpc].node_born_on;
member->node_uname =
crm_strdup(oc->m_array[offset+lpc].node_uname);
g_hash_table_insert(members, member->node_uname, member);
}
} else {
membership_copy->new_members = NULL;
}
/*--*-- Recently Dead Member Nodes --*--*/
offset = oc->m_out_idx;
membership_copy->dead_members_size = oc->m_n_out;
if(membership_copy->dead_members_size > 0) {
membership_copy->dead_members =
g_hash_table_new(g_str_hash, g_str_equal);
members = membership_copy->dead_members;
for(lpc=0; lpc < membership_copy->dead_members_size; lpc++) {
oc_node_t *member = (oc_node_t *)
crm_malloc(sizeof(oc_node_t));
member->node_id =
oc->m_array[offset+lpc].node_id;
member->node_born_on =
oc->m_array[offset+lpc].node_born_on;
member->node_uname =
crm_strdup(oc->m_array[offset+lpc].node_uname);
g_hash_table_insert(members, member->node_uname, member);
}
} else {
membership_copy->dead_members = NULL;
}
tmp = fsa_membership_copy;
fsa_membership_copy = membership_copy;
if(AM_I_DC) {
// should be sufficient for only the DC to do this
free_xml(do_update_cib_nodes(NULL, FALSE));
}
/* Free the old copy */
if(tmp != NULL) {
if(tmp->members != NULL)
g_hash_table_foreach_remove(
tmp->members, ghash_node_clfree, NULL);
if(tmp->new_members != NULL)
g_hash_table_foreach_remove(
tmp->new_members, ghash_node_clfree, NULL);
if(tmp->dead_members != NULL)
g_hash_table_foreach_remove(
tmp->dead_members, ghash_node_clfree, NULL);
crm_free(tmp);
}
FNRET(next_input);
}
void
ccm_event_detail(const oc_ev_membership_t *oc, oc_ed_t event)
{
int member_id = -1;
gboolean member = FALSE;
int lpc;
int node_list_size;
cl_log(LOG_INFO,"trans=%d, nodes=%d, new=%d, lost=%d n_idx=%d, "
"new_idx=%d, old_idx=%d",
oc->m_instance,
oc->m_n_member,
oc->m_n_in,
oc->m_n_out,
oc->m_memb_idx,
oc->m_in_idx,
oc->m_out_idx);
cl_log(LOG_INFO, "NODES IN THE PRIMARY MEMBERSHIP");
node_list_size = oc->m_n_member;
for(lpc=0; lpc<node_list_size; lpc++) {
cl_log(LOG_INFO,"\t%s [nodeid=%d, born=%d]",
oc->m_array[oc->m_memb_idx+lpc].node_uname,
oc->m_array[oc->m_memb_idx+lpc].node_id,
oc->m_array[oc->m_memb_idx+lpc].node_born_on);
CRM_DEBUG("%s ? %s", fsa_our_uname,
oc->m_array[oc->m_memb_idx+lpc].node_uname);
if(safe_str_eq(fsa_our_uname,
oc->m_array[oc->m_memb_idx+lpc].node_uname)) {
member = TRUE;
member_id = oc->m_array[oc->m_memb_idx+lpc].node_id;
}
}
if (member == FALSE) {
cl_log(LOG_WARNING,
"MY NODE IS NOT IN CCM THE MEMBERSHIP LIST");
} else {
cl_log(LOG_INFO, "MY NODE ID IS %d", member_id);
}
cl_log(LOG_INFO, "NEW MEMBERS");
if (oc->m_n_in==0)
cl_log(LOG_INFO, "\tNONE");
for(lpc=0; lpc<oc->m_n_in; lpc++) {
cl_log(LOG_INFO,"\t%s [nodeid=%d, born=%d]",
oc->m_array[oc->m_in_idx+lpc].node_uname,
oc->m_array[oc->m_in_idx+lpc].node_id,
oc->m_array[oc->m_in_idx+lpc].node_born_on);
}
cl_log(LOG_INFO, "MEMBERS LOST");
if (oc->m_n_out==0)
cl_log(LOG_INFO, "\tNONE");
for(lpc=0; lpc<oc->m_n_out; lpc++) {
cl_log(LOG_INFO,"\t%s [nodeid=%d, born=%d]",
oc->m_array[oc->m_out_idx+lpc].node_uname,
oc->m_array[oc->m_out_idx+lpc].node_id,
oc->m_array[oc->m_out_idx+lpc].node_born_on);
if(fsa_our_uname != NULL
&& strcmp(fsa_our_uname, oc->m_array[oc->m_memb_idx+lpc].node_uname)) {
cl_log(LOG_ERR,
"We're not part of the cluster anymore");
}
}
cl_log(LOG_INFO, "-----------------------");
}
int
register_with_ccm(ll_cluster_t *hb_cluster)
{
FNRET(0);
}
gboolean ccm_dispatch(int fd, gpointer user_data)
{
oc_ev_t *ccm_token = (oc_ev_t*)user_data;
oc_ev_handle_event(ccm_token);
return TRUE;
}
void
crmd_ccm_input_callback(oc_ed_t event,
void *cookie,
size_t size,
const void *data)
{
struct ccm_data *event_data = NULL;
FNIN();
if(data != NULL) {
event_data = (struct ccm_data *)
crm_malloc(sizeof(struct ccm_data));
event_data->event = &event;
event_data->oc = (const oc_ev_membership_t *)data;
s_crmd_fsa(C_CCM_CALLBACK, I_CCM_EVENT, (void*)event_data);
event_data->event = NULL;
event_data->oc = NULL;
crm_free(event_data);
} else {
cl_log(LOG_INFO, "CCM Callback with NULL data... "
"I dont /think/ this is bad");
}
oc_ev_callback_done(cookie);
FNOUT();
}
void
msg_ccm_join(const struct ha_msg *msg, void *foo)
{
FNIN();
cl_log(LOG_INFO, "\n###### Recieved ccm_join message...");
if (msg != NULL)
{
cl_log(LOG_INFO,
"[type=%s]",
ha_msg_value(msg, F_TYPE));
cl_log(LOG_INFO,
"[orig=%s]",
ha_msg_value(msg, F_ORIG));
cl_log(LOG_INFO,
"[to=%s]",
ha_msg_value(msg, F_TO));
cl_log(LOG_INFO,
"[status=%s]",
ha_msg_value(msg, F_STATUS));
cl_log(LOG_INFO,
"[info=%s]",
ha_msg_value(msg, F_COMMENT));
cl_log(LOG_INFO,
"[rsc_hold=%s]",
ha_msg_value(msg, F_RESOURCES));
cl_log(LOG_INFO,
"[stable=%s]",
ha_msg_value(msg, F_ISSTABLE));
cl_log(LOG_INFO,
"[rtype=%s]",
ha_msg_value(msg, F_RTYPE));
cl_log(LOG_INFO,
"[ts=%s]",
ha_msg_value(msg, F_TIME));
cl_log(LOG_INFO,
"[seq=%s]",
ha_msg_value(msg, F_SEQ));
cl_log(LOG_INFO,
"[generation=%s]",
ha_msg_value(msg, F_HBGENERATION));
// cl_log(LOG_INFO, "[=%s]", ha_msg_value(msg, F_));
}
FNOUT();
}
struct update_data_s
{
xmlNodePtr updates;
const char *state;
const char *join;
};
xmlNodePtr
do_update_cib_nodes(xmlNodePtr updates, gboolean overwrite)
{
struct update_data_s update_data;
update_data.updates = updates;
- CRM_DEBUG("Processing the \"down\" list");
update_data.state = XML_BOOLEAN_NO;
update_data.join = CRMD_JOINSTATE_DOWN;
if(fsa_membership_copy->dead_members != NULL) {
g_hash_table_foreach(fsa_membership_copy->dead_members,
ghash_update_cib_node, &update_data);
}
- CRM_DEBUG("Processing the \"in_ccm (all)\" list");
update_data.state = XML_BOOLEAN_YES;
update_data.join = NULL;
if(overwrite) {
update_data.join = CRMD_JOINSTATE_PENDING;
}
if(fsa_membership_copy->members != NULL) {
g_hash_table_foreach(fsa_membership_copy->members,
ghash_update_cib_node, &update_data);
}
/* this is most likely overkill...
*
* make *sure* that the join status of nodes entering the ccm list
* is reset
*
update_data.join = CRMD_JOINSTATE_PENDING;
- CRM_DEBUG("Processing the \"in_ccm (new)\" list");
if(fsa_membership_copy->new_members != NULL) {
g_hash_table_foreach(fsa_membership_copy->new_members,
ghash_update_cib_node, &update_data);
}
*/
if(update_data.updates != NULL) {
xmlNodePtr fragment =
create_cib_fragment(update_data.updates, NULL);
store_request(NULL, fragment,
CRM_OP_UPDATE, CRM_SYSTEM_DCIB);
free_xml(fragment);
}
return update_data.updates;
}
void
ghash_update_cib_node(gpointer key, gpointer value, gpointer user_data)
{
xmlNodePtr tmp1 = NULL;
const char *node_uname = (const char*)key;
struct update_data_s* data = (struct update_data_s*)user_data;
const char *state = data->join;
crm_debug("%s processing %s (%s)",
__FUNCTION__, node_uname, data->state);
if(state != NULL
&& safe_str_eq(fsa_our_uname, node_uname)) {
/* the DC is always a member */
state = CRMD_JOINSTATE_MEMBER;
}
tmp1 = create_node_state(node_uname, data->state, NULL, state);
if(data->updates == NULL) {
crm_debug("Creating first update");
data->updates = tmp1;
} else {
xmlAddNextSibling(data->updates, tmp1);
}
}
gboolean
ghash_node_clfree(gpointer key, gpointer value, gpointer user_data)
{
// value->node_uname is free'd as "key"
if(key != NULL) {
crm_free(key);
}
if(value != NULL) {
crm_free(value);
}
return TRUE;
}
diff --git a/crm/crmd/control.c b/crm/crmd/control.c
index 73c3021070..bec444e709 100644
--- a/crm/crmd/control.c
+++ b/crm/crmd/control.c
@@ -1,416 +1,415 @@
/*
* 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 <crm/crm.h>
#include <crmd_fsa.h>
#include <fsa_proto.h>
#include <crmd.h>
#include <crm/common/ipcutils.h>
#include <crm/common/crmutils.h>
#include <crmd_messages.h>
#include <clplumbing/Gmain_timeout.h>
#include <crm/dmalloc_wrapper.h>
#define PID_FILE WORKING_DIR"/crm.pid"
#define DAEMON_LOG LOG_DIR"/crm.log"
#define DAEMON_DEBUG LOG_DIR"/crm.debug"
gboolean crmd_ha_input_dispatch(int fd, gpointer user_data);
void crmd_ha_input_destroy(gpointer user_data);
void crm_shutdown(int nsig);
GHashTable *ipc_clients = NULL;
/* A_HA_CONNECT */
enum crmd_fsa_input
do_ha_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
gboolean registered = FALSE;
FNIN();
if(action & A_HA_DISCONNECT) {
if(fsa_cluster_conn != NULL) {
fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn);
}
}
if(action & A_HA_CONNECT) {
if(fsa_cluster_conn == NULL)
fsa_cluster_conn = ll_cluster_new("heartbeat");
// make sure we are disconnected first
fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn);
registered = register_with_ha(fsa_cluster_conn,
crm_system_name,
crmd_ha_input_dispatch,
crmd_ha_input_callback,
crmd_ha_input_destroy);
if(registered == FALSE) {
FNRET(I_FAIL);
}
}
if(action & ~(A_HA_CONNECT|A_HA_DISCONNECT)) {
cl_log(LOG_ERR, "Unexpected action %s in %s",
fsa_action2string(action), __FUNCTION__);
}
FNRET(I_NULL);
}
/* A_SHUTDOWN */
enum crmd_fsa_input
do_shutdown(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input next_input = I_NULL;
enum crmd_fsa_input tmp = I_NULL;
FNIN();
/* last attempt to shut these down */
if(is_set(fsa_input_register, R_PE_CONNECTED)) {
cl_log(LOG_WARNING,
"Last attempt to shutdown the PolicyEngine");
tmp = do_pe_control(A_PE_STOP, cause, cur_state,
current_input, data);
if(tmp != I_NULL) {
next_input = I_ERROR;
cl_log(LOG_ERR, "Failed to shutdown the PolicyEngine");
}
}
if(is_set(fsa_input_register, R_TE_CONNECTED)) {
cl_log(LOG_WARNING,
"Last attempt to shutdown the Transitioner");
tmp = do_pe_control(A_TE_STOP, cause, cur_state,
current_input, data);
if(tmp != I_NULL) {
next_input = I_ERROR;
cl_log(LOG_ERR, "Failed to shutdown the Transitioner");
}
}
/* TODO: shutdown all remaining resources? */
FNRET(next_input);
}
/* A_SHUTDOWN_REQ */
enum crmd_fsa_input
do_shutdown_req(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input next_input = I_NULL;
FNIN();
if(send_request(NULL, NULL, CRM_OP_SHUTDOWN_REQ,
NULL, CRM_SYSTEM_DC, NULL) == FALSE){
next_input = I_ERROR;
}
FNRET(next_input);
}
gboolean
crmd_ha_input_dispatch(int fd, gpointer user_data)
{
int lpc = 0;
ll_cluster_t* hb_cluster = (ll_cluster_t*)user_data;
FNIN();
while(hb_cluster->llc_ops->msgready(hb_cluster))
{
lpc++;
// invoke the callbacks but dont block
hb_cluster->llc_ops->rcvmsg(hb_cluster, 0);
}
if(lpc == 0){
// hey what happened??
cl_log(LOG_ERR, "We were called but no message was ready.\n"
"\tLikely the connection to Heartbeat failed, check the logs");
// TODO: feed this back into the FSA
FNRET(FALSE);
}
FNRET(TRUE);
}
void
crmd_ha_input_destroy(gpointer user_data)
{
cl_log(LOG_INFO, "in my hb_input_destroy");
}
/* A_EXIT_0, A_EXIT_1 */
enum crmd_fsa_input
do_exit(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
FNIN();
cl_log(LOG_ERR, "Action %s (%.16llx) not supported\n", fsa_action2string(action), action);
if(action & A_EXIT_0) {
g_main_quit(crmd_mainloop);
} else {
exit(1);
}
FNRET(I_NULL);
}
/* A_STARTUP */
enum crmd_fsa_input
do_startup(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
int facility;
int was_error = 0;
int interval = 1; // seconds between DC heartbeats
FNIN();
fsa_input_register = 0; // zero out the regester
cl_log(LOG_INFO, "Register PID");
register_pid(PID_FILE, FALSE, crm_shutdown);
cl_log_set_logfile(DAEMON_LOG);
/* if (crm_debug()) { */
cl_log_set_debugfile(DAEMON_DEBUG);
/* cl_log_enable_stderr(FALSE);
} */
ipc_clients = g_hash_table_new(&g_str_hash, &g_str_equal);
/* change the logging facility to the one used by heartbeat daemon */
fsa_cluster_conn = ll_cluster_new("heartbeat");
cl_log(LOG_INFO, "Switching to Heartbeat logger");
if ((facility =
fsa_cluster_conn->llc_ops->get_logfacility(
fsa_cluster_conn)) > 0) {
cl_log_set_facility(facility);
}
CRM_DEBUG("Facility: %d", facility);
if(was_error == 0) {
- CRM_DEBUG("Init server comms");
+ cl_log(LOG_INFO, "Init server comms");
was_error = init_server_ipc_comms(CRM_SYSTEM_CRMD,
crmd_client_connect,
default_ipc_input_destroy);
}
if (was_error == 0) {
- CRM_DEBUG("Finding our node name");
fsa_our_uname = fsa_cluster_conn->llc_ops->get_mynodeid(
fsa_cluster_conn);
if (fsa_our_uname == NULL) {
cl_log(LOG_ERR, "get_mynodeid() failed");
was_error = 1;
}
cl_log(LOG_INFO, "FSA Hostname: %s", fsa_our_uname);
}
/* set up the timers */
dc_heartbeat = (fsa_timer_t *)crm_malloc(sizeof(fsa_timer_t));
integration_timer= (fsa_timer_t *)crm_malloc(sizeof(fsa_timer_t));
election_trigger = (fsa_timer_t *)crm_malloc(sizeof(fsa_timer_t));
election_timeout = (fsa_timer_t *)crm_malloc(sizeof(fsa_timer_t));
shutdown_escalation_timmer = (fsa_timer_t *)
crm_malloc(sizeof(fsa_timer_t));
interval = interval * 1000;
election_trigger->source_id = -1;
election_trigger->period_ms = interval*4;
election_trigger->fsa_input = I_DC_TIMEOUT;
election_trigger->callback = timer_popped;
dc_heartbeat->source_id = -1;
dc_heartbeat->period_ms = interval;
dc_heartbeat->fsa_input = I_NULL;
dc_heartbeat->callback = do_dc_heartbeat;
election_timeout->source_id = -1;
election_timeout->period_ms = interval*6;
election_timeout->fsa_input = I_ELECTION_DC;
election_timeout->callback = timer_popped;
integration_timer->source_id = -1;
integration_timer->period_ms = interval*6;
integration_timer->fsa_input = I_INTEGRATION_TIMEOUT;
integration_timer->callback = timer_popped;
shutdown_escalation_timmer->source_id = -1;
shutdown_escalation_timmer->period_ms = interval*130;
shutdown_escalation_timmer->fsa_input = I_TERMINATE;
shutdown_escalation_timmer->callback = timer_popped;
/* set up the sub systems */
cib_subsystem = (struct crm_subsystem_s*)
crm_malloc(sizeof(struct crm_subsystem_s));
cib_subsystem->pid = 0;
cib_subsystem->respawn = 1;
cib_subsystem->path = crm_strdup(BIN_DIR);
cib_subsystem->name = crm_strdup(CRM_SYSTEM_CIB);
cib_subsystem->command = BIN_DIR"/cib";
cib_subsystem->flag = R_CIB_CONNECTED;
te_subsystem = (struct crm_subsystem_s*)
crm_malloc(sizeof(struct crm_subsystem_s));
te_subsystem->pid = 0;
te_subsystem->respawn = 1;
te_subsystem->path = crm_strdup(BIN_DIR);
te_subsystem->name = crm_strdup(CRM_SYSTEM_TENGINE);
te_subsystem->command = BIN_DIR"/tengine";
te_subsystem->flag = R_TE_CONNECTED;
pe_subsystem = (struct crm_subsystem_s*)
crm_malloc(sizeof(struct crm_subsystem_s));
pe_subsystem->pid = 0;
pe_subsystem->respawn = 1;
pe_subsystem->path = crm_strdup(BIN_DIR);
pe_subsystem->name = crm_strdup(CRM_SYSTEM_PENGINE);
pe_subsystem->command = BIN_DIR"/pengine";
pe_subsystem->flag = R_PE_CONNECTED;
if(was_error)
FNRET(I_FAIL);
FNRET(I_NULL);
}
/* A_STOP */
enum crmd_fsa_input
do_stop(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
FNIN();
cl_log(LOG_ERR, "Action %s (%.16llx) not supported\n",
fsa_action2string(action), action);
FNRET(I_NULL);
}
/* A_STARTED */
enum crmd_fsa_input
do_started(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
FNIN();
clear_bit_inplace(&fsa_input_register, R_STARTING);
FNRET(I_NULL);
}
/* A_RECOVER */
enum crmd_fsa_input
do_recover(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
FNIN();
cl_log(LOG_ERR, "Action %s (%.16llx) not supported\n",
fsa_action2string(action), action);
FNRET(I_SHUTDOWN);
}
void
crm_shutdown(int nsig)
{
FNIN();
CL_SIGNAL(nsig, crm_shutdown);
if (crmd_mainloop != NULL && g_main_is_running(crmd_mainloop)) {
if(is_set(fsa_input_register, R_SHUTDOWN)) {
- CRM_DEBUG("Escalating the shutdown");
+ cl_log(LOG_WARNING, "Escalating the shutdown");
s_crmd_fsa(C_SHUTDOWN, I_ERROR, NULL);
} else {
set_bit_inplace(&fsa_input_register, R_SHUTDOWN);
// cant rely on this...
startTimer(shutdown_escalation_timmer);
s_crmd_fsa(C_SHUTDOWN, I_SHUTDOWN, NULL);
}
} else {
- CRM_DEBUG("exit from shutdown");
+ cl_log(LOG_INFO, "exit from shutdown");
exit(LSB_EXIT_OK);
}
FNOUT();
}
diff --git a/crm/crmd/crmdmain.c b/crm/crmd/crmdmain.c
index e3238f2119..adddd34bb6 100644
--- a/crm/crmd/crmdmain.c
+++ b/crm/crmd/crmdmain.c
@@ -1,209 +1,209 @@
-/* $Id: crmdmain.c,v 1.16 2004/06/01 12:25:15 andrew Exp $ */
+/* $Id: crmdmain.c,v 1.17 2004/06/01 16:12:49 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 <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <hb_api.h>
#include <apphb.h>
#include <crm/crm.h>
#include <clplumbing/ipc.h>
#include <clplumbing/Gmain_timeout.h>
#include <clplumbing/cl_log.h>
#include <clplumbing/cl_signal.h>
#include <clplumbing/lsb_exitcodes.h>
#include <clplumbing/uids.h>
#include <clplumbing/realtime.h>
#include <clplumbing/GSource.h>
#include <clplumbing/cl_poll.h>
#include <libxml/tree.h>
-const char* crm_system_name = "crmd";
+const char* crm_system_name = CRM_SYSTEM_CRMD;
#include <crm/common/crmutils.h>
#include <crm/common/ipcutils.h>
#include <crmd.h>
#include <crmd_fsa.h>
#include <crm/dmalloc_wrapper.h>
#define PID_FILE WORKING_DIR"/crm.pid"
#define OPTARGS "skrh"
void usage(const char* cmd, int exit_status);
int init_start(void);
void crmd_hamsg_callback(const struct ha_msg* msg, void* private_data);
gboolean crmd_tickle_apphb(gpointer data);
GMainLoop* crmd_mainloop = NULL;
gboolean crm_debug_state = TRUE;
int
main(int argc, char ** argv)
{
int req_restart = FALSE;
int req_status = FALSE;
int req_stop = FALSE;
int argerr = 0;
int flag;
cl_log_set_entity(crm_system_name);
cl_log_enable_stderr(TRUE);
cl_log_set_facility(LOG_USER);
while ((flag = getopt(argc, argv, OPTARGS)) != EOF) {
switch(flag) {
case 's': /* Status */
req_status = TRUE;
break;
case 'k': /* Stop (kill) */
req_stop = TRUE;
break;
case 'r': /* Restart */
req_restart = TRUE;
break;
case 'h': /* Help message */
usage(crm_system_name, LSB_EXIT_OK);
break;
default:
++argerr;
break;
}
}
if (optind > argc) {
++argerr;
}
if (argerr) {
usage(crm_system_name,LSB_EXIT_GENERIC);
}
// read local config file
if (req_status){
FNRET(init_status(PID_FILE, crm_system_name));
}
if (req_stop){
FNRET(init_stop(PID_FILE));
}
if (req_restart) {
init_stop(PID_FILE);
}
FNRET(init_start());
}
int
init_start(void)
{
long pid;
enum crmd_fsa_state state;
if ((pid = get_running_pid(PID_FILE, NULL)) > 0) {
cl_log(LOG_CRIT, "already running: [pid %ld].", pid);
exit(LSB_EXIT_OK);
}
fsa_state = S_PENDING;
state = s_crmd_fsa(C_STARTUP, I_STARTUP, NULL);
if (state == S_PENDING) {
/* Create the mainloop and run it... */
crmd_mainloop = g_main_new(FALSE);
cl_log(LOG_INFO, "Starting %s", crm_system_name);
#ifdef REALTIME_SUPPORT
static int crm_realtime = 1;
if (crm_realtime == 1){
cl_enable_realtime();
}else if (crm_realtime == 0){
cl_disable_realtime();
}
cl_make_realtime(SCHED_RR, 5, 64, 64);
#endif
g_main_run(crmd_mainloop);
return_to_orig_privs();
} else {
cl_log(LOG_ERR, "Startup of CRMd failed. Current state: %s",
fsa_state2string(state));
}
if (unlink(PID_FILE) == 0) {
cl_log(LOG_INFO, "[%s] stopped", crm_system_name);
}
FNRET(state != S_PENDING);
}
void
usage(const char* cmd, int exit_status)
{
FILE* stream;
stream = exit_status ? stderr : stdout;
fprintf(stream, "usage: %s [-srkh]"
"[-c configure file]\n", cmd);
/* fprintf(stream, "\t-d\tsets debug level\n"); */
/* fprintf(stream, "\t-s\tgets daemon status\n"); */
/* fprintf(stream, "\t-r\trestarts daemon\n"); */
/* fprintf(stream, "\t-k\tstops daemon\n"); */
/* fprintf(stream, "\t-h\thelp message\n"); */
fflush(stream);
exit(exit_status);
}
gboolean
crmd_tickle_apphb(gpointer data)
{
char app_instance[APPNAME_LEN];
int rc = 0;
sprintf(app_instance, "%s_%ld", crm_system_name, (long)getpid());
rc = apphb_hb();
if (rc < 0) {
cl_perror("%s apphb_hb failure", app_instance);
exit(3);
}
return TRUE;
}
diff --git a/crm/crmd/lrm.c b/crm/crmd/lrm.c
index 40ffb2f4e3..395e05994b 100644
--- a/crm/crmd/lrm.c
+++ b/crm/crmd/lrm.c
@@ -1,627 +1,624 @@
/*
* 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 <crm/crm.h>
#include <crmd_fsa.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h> // for access
#include <clplumbing/cl_signal.h>
#include <clplumbing/realtime.h>
#include <sys/types.h> // for calls to open
#include <sys/stat.h> // for calls to open
#include <fcntl.h> // for calls to open
#include <pwd.h> // for getpwuid
#include <grp.h> // for initgroups
#include <sys/time.h> // for getrlimit
#include <sys/resource.h>// for getrlimit
#include <crm/common/crmutils.h>
#include <crm/common/ipcutils.h>
#include <crm/common/msgutils.h>
#include <crm/msg_xml.h>
#include <crm/common/xmlutils.h>
#include <crm/cib.h>
#include <crmd.h>
#include <crmd_messages.h>
#include <string.h>
#include <errno.h>
#include <crm/dmalloc_wrapper.h>
xmlNodePtr do_lrm_query(void);
GHashTable *xml2list(xmlNodePtr parent, const char **attr_path, int depth);
gboolean lrm_dispatch(int fd, gpointer user_data);
void do_update_resource(lrm_rsc_t *rsc,
int status,
int rc,
const char *op_type);
/* A_LRM_CONNECT */
enum crmd_fsa_input
do_lrm_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input failed = I_NULL;//I_FAIL;
int ret = HA_OK;
FNIN();
if(action & A_LRM_DISCONNECT) {
fsa_lrm_conn->lrm_ops->signoff(fsa_lrm_conn);
}
if(action & A_LRM_CONNECT) {
- CRM_DEBUG("LRM: connect...");
+ CRM_NOTE("LRM: connect...");
fsa_lrm_conn = ll_lrm_new(XML_CIB_TAG_LRM);
if(NULL == fsa_lrm_conn) {
return failed;
}
- CRM_DEBUG("LRM: sigon...");
+ CRM_NOTE("LRM: sigon...");
ret = fsa_lrm_conn->lrm_ops->signon(fsa_lrm_conn,
- "crmd");
+ CRM_SYSTEM_CRMD);
if(ret != HA_OK) {
cl_log(LOG_ERR, "Failed to sign on to the LRM");
return failed;
}
- CRM_DEBUG("LRM: set_lrm_callback...");
- ret = fsa_lrm_conn->lrm_ops->set_lrm_callback(fsa_lrm_conn,
- lrm_op_callback,
- lrm_monitor_callback);
+ CRM_NOTE("LRM: set_lrm_callback...");
+ ret = fsa_lrm_conn->lrm_ops->set_lrm_callback(
+ fsa_lrm_conn, lrm_op_callback, lrm_monitor_callback);
if(ret != HA_OK) {
cl_log(LOG_ERR, "Failed to set LRM callbacks");
return failed;
}
/* TODO: create a destroy handler that causes
* some recovery to happen
*/
G_main_add_fd(G_PRIORITY_LOW,
fsa_lrm_conn->lrm_ops->inputfd(fsa_lrm_conn),
FALSE,
lrm_dispatch, fsa_lrm_conn,
default_ipc_input_destroy);
}
if(action & ~(A_LRM_CONNECT|A_LRM_DISCONNECT)) {
cl_log(LOG_ERR, "Unexpected action %s in %s",
fsa_action2string(action), __FUNCTION__);
}
FNRET(I_NULL);
}
gboolean lrm_dispatch(int fd, gpointer user_data)
{
ll_lrm_t *lrm = (ll_lrm_t*)user_data;
lrm->lrm_ops->rcvmsg(lrm, FALSE);
return TRUE;
}
xmlNodePtr
do_lrm_query(void)
{
GList* lrm_list = NULL;
GList* element = NULL;
GList* op_list = NULL;
xmlNodePtr agent = NULL;
xmlNodePtr data = create_xml_node(NULL, XML_CIB_TAG_LRM);
xmlNodePtr agent_list = create_xml_node(data, "lrm_agents");
xmlNodePtr rsc_list;
char *rsc_type = NULL;
state_flag_t cur_state = 0;
const char *this_op = NULL;
GList* node = NULL;
lrm_list = fsa_lrm_conn->lrm_ops->get_ra_supported(fsa_lrm_conn);
if (NULL != lrm_list) {
GList* element = g_list_first(lrm_list);
while (NULL != element) {
rsc_type = (char*)element->data;
agent =
create_xml_node(agent_list, "lrm_agent");
set_xml_property_copy(agent, "class", rsc_type);
/* we dont have these yet */
set_xml_property_copy(agent, XML_ATTR_TYPE, NULL);
set_xml_property_copy(agent, "version", NULL);
element = g_list_next(element);
}
}
g_list_free(lrm_list);
lrm_list = fsa_lrm_conn->lrm_ops->get_all_rscs(fsa_lrm_conn);
rsc_list = create_xml_node(data, XML_LRM_TAG_RESOURCES);
if (NULL != lrm_list) {
element = g_list_first(lrm_list);
}
while (NULL != element) {
lrm_rsc_t *the_rsc = (lrm_rsc_t*)element->data;
/* const char* ra_type; */
/* GHashTable* params; */
xmlNodePtr xml_rsc = create_xml_node(rsc_list, "rsc_state");
set_xml_property_copy(xml_rsc, XML_ATTR_ID, the_rsc->id);
set_xml_property_copy(xml_rsc, "rsc_id", the_rsc->name);
set_xml_property_copy(xml_rsc, "node_id",fsa_our_uname);
- CRM_DEBUG("get_cur_state...");
-
op_list = the_rsc->ops->get_cur_state(the_rsc,
&cur_state);
CRM_DEBUG("\tcurrent state:%s\n",
cur_state==LRM_RSC_IDLE?"Idle":"Busy");
node = g_list_first(op_list);
while(NULL != node){
lrm_op_t* op = (lrm_op_t*)node->data;
this_op = op->op_type;
if(this_op == NULL
|| strcmp(this_op, "status") != 0){
const char *status_text = "<unknown>";
switch(op->status) {
case LRM_OP_DONE:
status_text = "done";
break;
case LRM_OP_CANCELLED:
status_text = "cancelled";
break;
case LRM_OP_TIMEOUT:
status_text = "timeout";
break;
case LRM_OP_NOTSUPPORTED:
status_text = "not suported";
break;
case LRM_OP_ERROR:
status_text = "error";
break;
}
set_xml_property_copy(xml_rsc,
"op_result",
status_text);
set_xml_property_copy(xml_rsc,
"rsc_op",
this_op);
// we only want the last one
break;
}
node = g_list_next(node);
}
element = g_list_next(element);
}
if (NULL != lrm_list) {
g_list_free(lrm_list);
}
return data;
}
/* A_LRM_INVOKE */
enum crmd_fsa_input
do_lrm_invoke(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input next_input = I_NULL;
xmlNodePtr fragment, tmp1;
xmlNodePtr msg;
const char *rsc_path[] =
{
"msg_data",
"rsc_op",
"resource",
"instance_attributes",
"parameters"
};
const char *operation = NULL;
rsc_id_t rid;
const char *id_from_cib = NULL;
const char *crm_op = NULL;
lrm_rsc_t *rsc = NULL;
lrm_mon_t* mon = NULL;
lrm_op_t* op = NULL;
FNIN();
if(action & A_UPDATE_NODESTATUS) {
xmlNodePtr data = NULL;
#ifndef USE_FAKE_LRM
data = do_lrm_query();
#endif
set_xml_property_copy(data, "replace", XML_CIB_TAG_LRM);
tmp1 = create_xml_node(NULL, XML_CIB_TAG_STATE);
set_xml_property_copy(tmp1, XML_ATTR_ID, fsa_our_uname);
fragment = create_cib_fragment(tmp1, NULL);
add_node_copy(tmp1, data);
/* this only happens locally. the updates are pushed out
* as part of the join process
*/
store_request(NULL, fragment, CRM_OP_UPDATE, CRM_SYSTEM_DC);
free_xml(fragment);
free_xml(tmp1);
free_xml(data);
FNRET(next_input);
}
#ifdef USE_FAKE_LRM
if(data == NULL) {
FNRET(I_ERROR);
}
msg = (xmlNodePtr)data;
operation = get_xml_attr_nested(msg, rsc_path, DIMOF(rsc_path) -3,
XML_LRM_ATTR_TASK, TRUE);
id_from_cib = get_xml_attr_nested(msg, rsc_path, DIMOF(rsc_path) -2,
XML_ATTR_ID, TRUE);
crm_op = get_xml_attr(msg, XML_TAG_OPTIONS, XML_ATTR_OP, TRUE);
if(safe_str_eq(crm_op, "rsc_op")) {
const char *op_status = NULL;
xmlNodePtr update = NULL;
xmlNodePtr state = create_xml_node(NULL, XML_CIB_TAG_STATE);
xmlNodePtr iter = create_xml_node(state, XML_CIB_TAG_LRM);
CRM_DEBUG("performing op %s...", operation);
// so we can identify where to do the update
set_xml_property_copy(state, XML_ATTR_ID, fsa_our_uname);
iter = create_xml_node(iter, XML_LRM_TAG_RESOURCES);
iter = create_xml_node(iter, "lrm_resource");
set_xml_property_copy(iter, XML_ATTR_ID, id_from_cib);
set_xml_property_copy(iter, XML_LRM_ATTR_LASTOP, operation);
long int op_code = 0;
#if 0
/* introduce a 10% chance of an action failing */
op_code = random();
#endif
if((op_code % 10) == 1) {
op_code = 1;
} else {
op_code = 0;
}
char *op_code_s = crm_itoa(op_code);
if(op_code) {
// fail
if(safe_str_eq(operation, "start")){
op_status = "stopped";
} else {
op_status = "started";
}
} else {
// pass
if(safe_str_eq(operation, "start")){
op_status = "started";
} else {
op_status = "stopped";
}
}
set_xml_property_copy(iter, XML_LRM_ATTR_OPSTATE,op_status);
set_xml_property_copy(iter, XML_LRM_ATTR_OPCODE, op_code_s);
set_xml_property_copy(iter, XML_LRM_ATTR_TARGET, fsa_our_uname);
crm_free(op_code_s);
update = create_cib_fragment(state, NULL);
send_request(NULL, update, CRM_OP_UPDATE,
fsa_our_dc, CRM_SYSTEM_DCIB, NULL);
}
FNRET(I_NULL);
#endif
cl_log(LOG_WARNING, "Action %s (%.16llx) only kind of supported\n",
fsa_action2string(action), action);
msg = (xmlNodePtr)data;
operation = get_xml_attr_nested(msg, rsc_path, DIMOF(rsc_path) -3,
XML_ATTR_OP, TRUE);
id_from_cib = get_xml_attr_nested(msg, rsc_path, DIMOF(rsc_path) -2,
XML_ATTR_ID, TRUE);
// only the first 16 chars are used by the LRM
strncpy(rid, id_from_cib, 16);
crm_op = get_xml_attr(msg, XML_TAG_OPTIONS, XML_ATTR_OP, TRUE);
rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid);
if(crm_op != NULL && strcmp(crm_op, "lrm_query") == 0) {
xmlNodePtr data, tmp1, tmp2, reply;
tmp1 = create_xml_node(NULL, XML_CIB_TAG_STATE);
set_xml_property_copy(tmp1, XML_ATTR_ID, fsa_our_uname);
data = create_cib_fragment(tmp1, NULL);
tmp2 = do_lrm_query();
add_node_copy(tmp1, tmp2);
reply = create_reply(msg, data);
relay_message(reply, TRUE);
free_xml(data);
free_xml(reply);
free_xml(tmp2);
free_xml(tmp1);
} else if(operation != NULL && strcmp(operation, "monitor") == 0) {
if(rsc == NULL) {
cl_log(LOG_ERR, "Could not find resource to monitor");
FNRET(I_FAIL);
}
mon = g_new(lrm_mon_t, 1);
mon->op_type = "status";
mon->params = NULL;
mon->timeout = 0;
mon->user_data = rsc;
mon->mode = LRM_MONITOR_SET;
mon->interval = 2;
mon->target = 1;
rsc->ops->set_monitor(rsc,mon);
mon = g_new(lrm_mon_t, 1);
} else if(operation != NULL) {
if(rsc == NULL) {
// add it to the list
- CRM_DEBUG("add_rsc...");
+ CRM_DEBUG("adding rsc %s before operation", rid);
fsa_lrm_conn->lrm_ops->add_rsc(
fsa_lrm_conn, rid,
get_xml_attr_nested(msg,
rsc_path,
DIMOF(rsc_path) -2,
"class", TRUE),
get_xml_attr_nested(msg,
rsc_path,
DIMOF(rsc_path) -2,
XML_ATTR_TYPE, TRUE),
NULL);
rsc = fsa_lrm_conn->lrm_ops->get_rsc(
fsa_lrm_conn, rid);
}
if(rsc == NULL) {
cl_log(LOG_ERR, "Could not add resource to LRM");
FNRET(I_FAIL);
}
// now do the op
CRM_DEBUG("performing op %s...", operation);
op = g_new(lrm_op_t, 1);
op->op_type = operation;
op->params = xml2list(msg, rsc_path, DIMOF(rsc_path));
op->timeout = 0;
op->user_data = rsc;
rsc->ops->perform_op(rsc, op);
}
FNRET(next_input);
}
GHashTable *
xml2list(xmlNodePtr parent, const char**attr_path, int depth)
{
xmlNodePtr node_iter = NULL;
GHashTable *nvpair_hash =
g_hash_table_new(&g_str_hash, &g_str_equal);
xmlNodePtr nvpair_list =
find_xml_node_nested(parent, attr_path, depth);
if(nvpair_list != NULL){
node_iter = nvpair_list->children;
while(node_iter != NULL) {
const char *key = xmlGetProp(
node_iter, XML_NVPAIR_ATTR_NAME);
const char *value = xmlGetProp(
node_iter, XML_NVPAIR_ATTR_VALUE);
CRM_DEBUG("Added %s=%s", key, value);
g_hash_table_insert (nvpair_hash,
crm_strdup(key),
crm_strdup(value));
node_iter = node_iter->next;
}
}
return nvpair_hash;
}
void
do_update_resource(lrm_rsc_t *rsc, int status, int rc, const char *op_type)
{
/*
<status>
<nodes_status id=uname>
<lrm>
<lrm_resources>
<lrm_resource id=>
</...>
*/
xmlNodePtr update, iter;
char *tmp = NULL;
xmlNodePtr fragment, tmp1;
update = create_xml_node(NULL, "node_state");
set_xml_property_copy(update, XML_ATTR_ID, fsa_our_uname);
iter = create_xml_node(update, XML_CIB_TAG_LRM);
iter = create_xml_node(iter, XML_LRM_TAG_RESOURCES);
iter = create_xml_node(iter, "lrm_resource");
set_xml_property_copy(iter, XML_ATTR_ID, rsc->id);
set_xml_property_copy(iter, XML_LRM_ATTR_LASTOP, op_type);
tmp = crm_itoa(status);
set_xml_property_copy(iter, XML_LRM_ATTR_OPSTATE, tmp);
crm_free(tmp);
tmp = crm_itoa(rc);
set_xml_property_copy(iter, XML_LRM_ATTR_OPCODE, tmp);
crm_free(tmp);
set_xml_property_copy(iter, XML_LRM_ATTR_TARGET, fsa_our_uname);
tmp1 = create_xml_node(NULL, XML_CIB_TAG_STATE);
set_xml_property_copy(tmp1, XML_ATTR_ID, fsa_our_uname);
add_node_copy(tmp1, update);
fragment = create_cib_fragment(tmp1, NULL);
send_request(NULL, fragment, CRM_OP_UPDATE,
fsa_our_dc, CRM_SYSTEM_DCIB, NULL);
free_xml(fragment);
free_xml(update);
free_xml(tmp1);
}
enum crmd_fsa_input
do_lrm_event(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input cur_input,
void *data)
{
FNIN();
if(cause == C_LRM_MONITOR_CALLBACK) {
lrm_mon_t* monitor = (lrm_mon_t*)data;
lrm_rsc_t* rsc = monitor->rsc;
switch(monitor->status) {
case LRM_OP_DONE:
- CRM_DEBUG("An LRM monitor operation passed");
+ CRM_NOTE("An LRM monitor operation passed");
FNRET(I_NULL);
break;
case LRM_OP_CANCELLED:
case LRM_OP_TIMEOUT:
case LRM_OP_NOTSUPPORTED:
case LRM_OP_ERROR:
cl_log(LOG_ERR,
"An LRM monitor operation failed"
" or was aborted");
do_update_resource(rsc,
monitor->status,
monitor->rc,
monitor->op_type);
break;
}
} else if(cause == C_LRM_OP_CALLBACK) {
lrm_op_t* op = (lrm_op_t*)data;
lrm_rsc_t* rsc = op->rsc;
switch(op->status) {
case LRM_OP_CANCELLED:
case LRM_OP_TIMEOUT:
case LRM_OP_NOTSUPPORTED:
case LRM_OP_ERROR:
cl_log(LOG_ERR,
"An LRM operation failed"
" or was aborted");
// keep going
case LRM_OP_DONE:
do_update_resource(rsc,
op->status,
op->rc,
op->op_type);
break;
}
} else {
FNRET(I_FAIL);
}
FNRET(I_NULL);
}
diff --git a/crm/crmd/messages.c b/crm/crmd/messages.c
index 65bd4daf22..d52b7a8dce 100644
--- a/crm/crmd/messages.c
+++ b/crm/crmd/messages.c
@@ -1,938 +1,939 @@
/*
* 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 <crm/crm.h>
#include <string.h>
#include <crmd_fsa.h>
#include <libxml/tree.h>
#include <crm/msg_xml.h>
#include <crm/common/crmutils.h>
#include <crm/common/xmlutils.h>
#include <crm/common/msgutils.h>
#include <crm/cib.h>
#include <crmd.h>
#include <crmd_messages.h>
#include <crm/dmalloc_wrapper.h>
FILE *msg_in_strm = NULL;
FILE *router_strm = NULL;
fsa_message_queue_t fsa_message_queue = NULL;
gboolean relay_message(xmlNodePtr xml_relay_message,
gboolean originated_locally);
#ifdef MSG_LOG
# define ROUTER_RESULT(x) char *msg_text = dump_xml(xml_relay_message);\
if(router_strm == NULL) { \
router_strm = fopen("/tmp/router.log", "w"); \
} \
fprintf(router_strm, "[%d RESULT (%s)]\t%s\t%s\n", \
AM_I_DC, \
xmlGetProp(xml_relay_message, XML_ATTR_REFERENCE),\
x, msg_text); \
fflush(router_strm); \
crm_free(msg_text);
#else
-# define ROUTER_RESULT(x) CRM_DEBUG(x);
+# define ROUTER_RESULT(x) CRM_DEBUG(x, NULL);
#endif
/* returns the current head of the FIFO queue */
fsa_message_queue_t
put_message(xmlNodePtr new_message)
{
int old_len = g_slist_length(fsa_message_queue);
// make sure to free it properly later
fsa_message_queue = g_slist_append(fsa_message_queue,
copy_xml_node_recursive(new_message));
CRM_DEBUG("Queue len: %d -> %d", old_len,
g_slist_length(fsa_message_queue));
if(old_len == g_slist_length(fsa_message_queue)){
cl_log(LOG_ERR, "Couldnt add message to the queue");
}
return fsa_message_queue;
}
/* returns the next message */
xmlNodePtr
get_message(void)
{
xmlNodePtr message = g_slist_nth_data(fsa_message_queue, 0);
fsa_message_queue = g_slist_remove(fsa_message_queue, message);
return message;
}
/* returns the current head of the FIFO queue */
gboolean
is_message(void)
{
return (g_slist_length(fsa_message_queue) > 0);
}
/* A_MSG_STORE */
enum crmd_fsa_input
do_msg_store(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
// xmlNodePtr new_message = (xmlNodePtr)data;
FNIN();
// put_message(new_message);
FNRET(I_NULL);
}
/* A_MSG_ROUTE */
enum crmd_fsa_input
do_msg_route(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input result = I_NULL;
xmlNodePtr xml_message = (xmlNodePtr)data;
gboolean routed = FALSE, defer = TRUE, do_process = TRUE;
FNIN();
#if 0
// if(cause == C_IPC_MESSAGE) {
if (crmd_authorize_message(root_xml_node,
msg,
curr_client) == FALSE) {
CRM_DEBUG("Message not authorized");
do_process = FALSE;
}
// }
#endif
if(do_process) {
/* try passing the buck first */
routed = relay_message(xml_message, cause==C_IPC_MESSAGE);
if(routed == FALSE) {
defer = TRUE;
/* calculate defer */
result = handle_message(xml_message);
switch(result) {
case I_NULL:
defer = FALSE;
break;
case I_DC_HEARTBEAT:
defer = FALSE;
break;
/* what else should go here? */
default:
- CRM_DEBUG("Defering local processing of message");
+ CRM_NOTE("Defering local processing of message");
put_message(xml_message);
result = I_REQUEST;
break;
}
}
}
FNRET(result);
}
void
crmd_ha_input_callback(const struct ha_msg* msg, void* private_data)
{
const char *from = ha_msg_value(msg, F_ORIG);
const char *to = NULL;
xmlNodePtr root_xml_node;
FNIN();
#ifdef MSG_LOG
if(msg_in_strm == NULL) {
msg_in_strm = fopen("/tmp/inbound.log", "w");
}
#endif
if(from == NULL || strcmp(from, fsa_our_uname) == 0) {
#ifdef MSG_LOG
fprintf(msg_in_strm,
"Discarded message [F_SEQ=%s] from ourselves.\n",
ha_msg_value(msg, F_SEQ));
#endif
FNOUT();
}
#ifdef MSG_LOG
fprintf(msg_in_strm, "[%s (%s:%s)]\t%s\n",
from,
ha_msg_value(msg, F_SEQ),
ha_msg_value(msg, F_TYPE),
ha_msg_value(msg, "xml")
);
fflush(msg_in_strm);
#endif
root_xml_node = find_xml_in_hamessage(msg);
to = xmlGetProp(root_xml_node, XML_ATTR_HOSTTO);
if(to != NULL && strlen(to) > 0 && strcmp(to, fsa_our_uname) != 0) {
#ifdef MSG_LOG
fprintf(msg_in_strm,
"Discarding message [F_SEQ=%s] for someone else.",
ha_msg_value(msg, F_SEQ));
#endif
FNOUT();
}
set_xml_property_copy(root_xml_node, XML_ATTR_HOSTFROM, from);
s_crmd_fsa(C_HA_MESSAGE, I_ROUTER, root_xml_node);
free_xml(root_xml_node);
FNOUT();
}
/*
* Apparently returning TRUE means "stay connected, keep doing stuff".
* Returning FALSE means "we're all done, close the connection"
*/
gboolean
crmd_ipc_input_callback(IPC_Channel *client, gpointer user_data)
{
int lpc = 0;
char *buffer = NULL;
IPC_Message *msg = NULL;
gboolean hack_return_good = TRUE;
xmlNodePtr root_xml_node;
crmd_client_t *curr_client = (crmd_client_t*)user_data;
FNIN();
CRM_DEBUG("Processing IPC message from %s",
curr_client->table_key);
while(client->ops->is_message_pending(client)) {
if (client->ch_status == IPC_DISCONNECT) {
/* The message which was pending for us is that
* the IPC status is now IPC_DISCONNECT */
break;
}
if (client->ops->recv(client, &msg) != IPC_OK) {
perror("Receive failure:");
FNRET(!hack_return_good);
}
if (msg == NULL) {
- CRM_DEBUG("No message this time");
+ cl_log(LOG_WARNING, "No message this time");
continue;
}
lpc++;
buffer = (char*)msg->msg_body;
CRM_DEBUG("Processing xml from %s [text=%s]",
curr_client->table_key, buffer);
root_xml_node =
find_xml_in_ipcmessage(msg, FALSE);
if (root_xml_node != NULL) {
if (crmd_authorize_message(root_xml_node,
msg,
curr_client)) {
- CRM_DEBUG("Message authorized,about to relay");
s_crmd_fsa(C_IPC_MESSAGE,
I_ROUTER,
root_xml_node);
}
} else {
cl_log(LOG_INFO,
"IPC Message was not valid... discarding.");
}
free_xml(root_xml_node);
msg->msg_done(msg);
msg = NULL;
buffer = NULL;
root_xml_node = NULL;
}
CRM_DEBUG("Processed %d messages", lpc);
if (client->ch_status == IPC_DISCONNECT)
{
cl_log(LOG_INFO,
"received HUP from %s",
curr_client->table_key);
if (curr_client != NULL) {
struct crm_subsystem_s *the_subsystem = NULL;
if (curr_client->sub_sys == NULL) {
- CRM_DEBUG("Client had not registered with us yet");
- } else if (strcmp(CRM_SYSTEM_PENGINE, curr_client->sub_sys) == 0) {
+ cl_log(LOG_WARNING,
+ "Client had not registered with us yet");
+ } else if (strcmp(CRM_SYSTEM_PENGINE,
+ curr_client->sub_sys) == 0) {
the_subsystem = pe_subsystem;
- } else if (strcmp(CRM_SYSTEM_TENGINE, curr_client->sub_sys) == 0) {
+ } else if (strcmp(CRM_SYSTEM_TENGINE,
+ curr_client->sub_sys) == 0) {
the_subsystem = te_subsystem;
- } else if (strcmp(CRM_SYSTEM_CIB, curr_client->sub_sys) == 0){
+ } else if (strcmp(CRM_SYSTEM_CIB,
+ curr_client->sub_sys) == 0){
the_subsystem = cib_subsystem;
}
if(the_subsystem != NULL) {
cleanup_subsystem(the_subsystem);
} // else that was a transient client
if (curr_client->table_key != NULL) {
/*
* Key is destroyed below: curr_client->table_key
* Value is cleaned up by G_main_del_IPC_Channel
*/
g_hash_table_remove(ipc_clients,
curr_client->table_key);
}
if(curr_client->client_source != NULL) {
- gboolean det =
- G_main_del_IPC_Channel(curr_client->client_source);
+ gboolean det = G_main_del_IPC_Channel(
+ curr_client->client_source);
CRM_DEBUG("crm_client was %s detached",
det?"successfully":"not");
}
crm_free(curr_client->table_key);
crm_free(curr_client->sub_sys);
crm_free(curr_client->uuid);
crm_free(curr_client);
}
- CRM_DEBUG("this client has now left the building.");
FNRET(!hack_return_good);
}
FNRET(hack_return_good);
}
/*
* This method adds a copy of xml_response_data
*/
gboolean
send_request(xmlNodePtr msg_options, xmlNodePtr msg_data,
const char *operation, const char *host_to, const char *sys_to,
char **msg_reference)
{
gboolean was_sent = FALSE;
xmlNodePtr request = NULL;
FNIN();
msg_options = set_xml_attr(msg_options, XML_TAG_OPTIONS,
XML_ATTR_OP, operation, TRUE);
request = create_request(msg_options,
msg_data,
host_to,
sys_to,
AM_I_DC?CRM_SYSTEM_DC:CRM_SYSTEM_CRMD,
NULL,
NULL);
// xml_message_debug(request, "Final request...");
if(msg_reference != NULL) {
*msg_reference = crm_strdup(xmlGetProp(request, XML_ATTR_REFERENCE));
}
was_sent = relay_message(request, TRUE);
if(was_sent == FALSE) {
put_message(request);
}
free_xml(request);
FNRET(was_sent);
}
/*
* This method adds a copy of xml_response_data
*/
gboolean
store_request(xmlNodePtr msg_options, xmlNodePtr msg_data,
const char *operation, const char *sys_to)
{
xmlNodePtr request = NULL;
FNIN();
msg_options = set_xml_attr(msg_options, XML_TAG_OPTIONS,
XML_ATTR_OP, operation, TRUE);
crm_debug("Storing op=%s message for later processing", operation);
request = create_request(msg_options,
msg_data,
NULL,
sys_to,
AM_I_DC?CRM_SYSTEM_DC:CRM_SYSTEM_CRMD,
NULL,
NULL);
put_message(request);
free_xml(request);
FNRET(TRUE);
}
gboolean
relay_message(xmlNodePtr xml_relay_message, gboolean originated_locally)
{
int is_for_dc = 0;
int is_for_dcib = 0;
int is_for_crm = 0;
int is_for_cib = 0;
int is_local = 0;
gboolean dont_cc= TRUE;
gboolean processing_complete = FALSE;
const char *host_to = xmlGetProp(xml_relay_message,XML_ATTR_HOSTTO);
const char *sys_to = xmlGetProp(xml_relay_message,XML_ATTR_SYSTO);
FNIN();
if(xml_relay_message == NULL) {
cl_log(LOG_ERR, "Cannot route empty message");
FNRET(TRUE);
}
if(strcmp(CRM_OP_HELLO, xml_relay_message->name) == 0) {
/* quietly ignore */
FNRET(TRUE);
}
if(strcmp(XML_MSG_TAG, xml_relay_message->name) != 0) {
xml_message_debug(xml_relay_message,
"Bad message type, should be crm_message");
cl_log(LOG_ERR, "Ignoring message of type %s",
xml_relay_message->name);
FNRET(TRUE);
}
if(sys_to == NULL) {
xml_message_debug(xml_relay_message,
"Message did not have any value for sys_to");
cl_log(LOG_ERR, "Message did not have any value for %s",
XML_ATTR_SYSTO);
FNRET(TRUE);
}
is_for_dc = (strcmp(CRM_SYSTEM_DC, sys_to) == 0);
is_for_dcib = (strcmp(CRM_SYSTEM_DCIB, sys_to) == 0);
is_for_cib = (strcmp(CRM_SYSTEM_CIB, sys_to) == 0);
is_for_crm = (strcmp(CRM_SYSTEM_CRMD, sys_to) == 0);
is_local = 0;
if(host_to == NULL || strlen(host_to) == 0) {
if(is_for_dc)
is_local = 0;
else if(is_for_crm && originated_locally)
is_local = 0;
else
is_local = 1;
} else if(strcmp(fsa_our_uname, host_to) == 0) {
is_local=1;
}
#if 0
CRM_DEBUG("is_local %d", is_local);
CRM_DEBUG("is_for_dcib %d", is_for_dcib);
CRM_DEBUG("is_for_dc %d", is_for_dc);
CRM_DEBUG("is_for_crm %d", is_for_crm);
CRM_DEBUG("AM_I_DC %d", AM_I_DC);
CRM_DEBUG("sys_to %s", sys_to);
CRM_DEBUG("host_to %s", host_to);
#endif
if(is_for_dc || is_for_dcib) {
if(AM_I_DC) {
ROUTER_RESULT("Message result: DC/CRMd process");
processing_complete = FALSE; // more to be done by caller
} else if(originated_locally) {
ROUTER_RESULT("Message result: External relay to DC");
send_msg_via_ha(xml_relay_message, NULL);
processing_complete = TRUE;
} else {
ROUTER_RESULT("Message result: Discard, not DC");
processing_complete = TRUE; // discard
}
} else if(is_local && (is_for_crm || is_for_cib)) {
ROUTER_RESULT("Message result: CRMd process");
} else if(is_local) {
if(dont_cc) {
ROUTER_RESULT("Message result: Local relay");
} else {
/* The DC should also get this message */
ROUTER_RESULT("Message result: Local relay with CC");
}
send_msg_via_ipc(xml_relay_message, sys_to);
processing_complete = TRUE & dont_cc;
} else {
if(dont_cc) {
ROUTER_RESULT("Message result: External relay");
} else {
/* The DC should also get this message */
ROUTER_RESULT("Message result: External relay with CC");
}
send_msg_via_ha(xml_relay_message, host_to);
processing_complete = TRUE & dont_cc;
}
FNRET(processing_complete);
}
void
send_msg_via_ha(xmlNodePtr action, const char *dest_node)
{
FNIN();
if (action == NULL) FNOUT();
if (validate_crm_message(action, NULL, NULL, NULL) == NULL)
{
cl_log(LOG_ERR,
"Relay message to (%s) via HA was invalid, ignoring",
dest_node);
FNOUT();
}
// CRM_DEBUG("Relaying message to (%s) via HA", dest_node);
set_xml_property_copy(action, XML_ATTR_HOSTTO, dest_node);
send_xmlha_message(fsa_cluster_conn, action);
FNOUT();
}
void
send_msg_via_ipc(xmlNodePtr action, const char *sys)
{
IPC_Channel *client_channel;
FNIN();
// cl_log(LOG_DEBUG, "relaying msg to sub_sys=%s via IPC", sys);
client_channel =
(IPC_Channel*)g_hash_table_lookup (ipc_clients, sys);
if (client_channel != NULL) {
cl_log(LOG_DEBUG, "Sending message via channel %s.", sys);
send_xmlipc_message(client_channel, action);
} else if(sys != NULL && strcmp(sys, CRM_SYSTEM_CIB) == 0) {
cl_log(LOG_ERR,
"Sub-system (%s) has been incorporated into the CRMd.",
sys);
xml_message_debug(action, "Change the way we handle");
relay_message(process_cib_message(action, TRUE), TRUE);
} else if(sys != NULL && strcmp(sys, CRM_SYSTEM_LRMD) == 0) {
do_lrm_invoke(A_LRM_INVOKE, C_IPC_MESSAGE,
fsa_state, I_MESSAGE, action);
} else {
cl_log(LOG_ERR,
"Unknown Sub-system (%s)... discarding message.",
sys);
}
FNOUT();
}
gboolean
crmd_authorize_message(xmlNodePtr root_xml_node,
IPC_Message *client_msg,
crmd_client_t *curr_client)
{
// check the best case first
const char *sys_from = xmlGetProp(root_xml_node,
XML_ATTR_SYSFROM);
char *uuid = NULL;
char *client_name = NULL;
char *major_version = NULL;
char *minor_version = NULL;
const char *filtered_from;
gpointer table_key = NULL;
gboolean result;
const char *op = get_xml_attr(root_xml_node, XML_TAG_OPTIONS,
- XML_ATTR_OP, FALSE);
+ XML_ATTR_OP, TRUE);
FNIN();
if (safe_str_neq(CRM_OP_HELLO, op)) {
-
+
if(sys_from == NULL) {
return FALSE;
}
gboolean can_reply = FALSE; // no-one has registered with this id
filtered_from = sys_from;
/* The CIB can have two names on the DC */
if(strcmp(sys_from, CRM_SYSTEM_DCIB) == 0)
filtered_from = CRM_SYSTEM_CIB;
if (g_hash_table_lookup (ipc_clients, filtered_from) != NULL)
can_reply = TRUE; // reply can be routed
CRM_DEBUG("Message reply can%s be routed from %s.",
can_reply?"":" not", sys_from);
if(can_reply == FALSE) {
cl_log(LOG_ERR, "Message not authorized");
}
return can_reply;
}
cl_log(LOG_INFO,
"received client join msg: %s",
(char*)client_msg->msg_body);
result = process_hello_message(root_xml_node,
&uuid,
&client_name,
&major_version,
&minor_version);
if (result == TRUE) {
// check version
int mav = atoi(major_version);
int miv = atoi(minor_version);
if (mav < 0 || miv < 0) {
cl_log(LOG_ERR,
"Client version (%d:%d) is not acceptable",
mav,
miv);
result = FALSE;
}
crm_free(major_version);
crm_free(minor_version);
}
struct crm_subsystem_s *the_subsystem = NULL;
if (result == TRUE) {
/* if we already have one of those clients
* only applies to te, pe etc. not admin clients
*/
if (client_name == NULL)
- CRM_DEBUG("Client had not registered with us yet");
+ cl_log(LOG_WARNING,
+ "Client had not registered with us yet");
else if (strcmp(CRM_SYSTEM_PENGINE, client_name) == 0)
the_subsystem = pe_subsystem;
else if (strcmp(CRM_SYSTEM_TENGINE, client_name) == 0)
the_subsystem = te_subsystem;
else if (strcmp(CRM_SYSTEM_CIB, client_name) == 0)
the_subsystem = cib_subsystem;
if (the_subsystem != NULL) {
// do we already have one?
result =(fsa_input_register & the_subsystem->flag)==0;
if(result) {
the_subsystem->ipc =
curr_client->client_channel;
} // else we didnt ask for the client to start
} else if(client_name != NULL && uuid != NULL) {
table_key = (gpointer)
generate_hash_key(client_name, uuid);
} else {
result = FALSE;
cl_log(LOG_ERR,
"Bad client details (client_name=%s, uuid=%s)",
client_name, uuid);
}
}
- if(result == TRUE && table_key == NULL)
+ if(result == TRUE && table_key == NULL) {
table_key = (gpointer)crm_strdup(client_name);
-
+ }
+
if (result == TRUE) {
cl_log(LOG_INFO, "Accepted client %s", (char*)table_key);
curr_client->table_key = table_key;
curr_client->sub_sys = crm_strdup(client_name);
curr_client->uuid = crm_strdup(uuid);
g_hash_table_insert (ipc_clients,
table_key,
curr_client->client_channel);
send_hello_message(curr_client->client_channel,
"n/a", CRM_SYSTEM_CRMD,
"0", "1");
cl_log(LOG_INFO, "Updated client list with %s",
(char*)table_key);
if(the_subsystem != NULL) {
set_bit_inplace(&fsa_input_register,
the_subsystem->flag);
}
s_crmd_fsa(C_SUBSYSTEM_CONNECT, I_NULL, NULL);
} else {
cl_log(LOG_ERR, "Rejected client logon request");
curr_client->client_channel->ch_status = IPC_DISC_PENDING;
}
if(uuid != NULL) crm_free(uuid);
if(client_name != NULL) crm_free(client_name);
/* hello messages should never be processed further */
return FALSE;
}
enum crmd_fsa_input
handle_message(xmlNodePtr stored_msg)
{
enum crmd_fsa_input next_input = I_NULL;
const char *sys_to = get_xml_attr(stored_msg, NULL,
XML_ATTR_SYSTO, TRUE);
const char *sys_from = get_xml_attr(stored_msg, NULL,
XML_ATTR_SYSFROM, TRUE);
- const char *host_from = get_xml_attr(stored_msg, NULL,
+ const char *host_from= get_xml_attr(stored_msg, NULL,
XML_ATTR_HOSTFROM, TRUE);
const char *msg_ref = get_xml_attr(stored_msg, NULL,
XML_ATTR_REFERENCE, TRUE);
const char *type = get_xml_attr(stored_msg, NULL,
XML_ATTR_MSGTYPE, TRUE);
const char *op = get_xml_attr(stored_msg, XML_TAG_OPTIONS,
XML_ATTR_OP, TRUE);
// xml_message_debug(stored_msg, "Processing message");
cl_log(LOG_DEBUG,
"Received %s %s in state %s",
op, type, fsa_state2string(fsa_state));
if(type == NULL || op == NULL) {
cl_log(LOG_ERR, "Ignoring message (type=%s), (op=%s)",
type, op);
xml_message_debug(stored_msg, "Bad message");
} else if(strcmp(type, XML_ATTR_REQUEST) == 0){
if(strcmp(op, CRM_OP_VOTE) == 0) {
next_input = I_ELECTION;
} else if(AM_I_DC && strcmp(op, CRM_OP_TEABORT) == 0) {
next_input = I_PE_CALC;
} else if(AM_I_DC
&& strcmp(op, CRM_OP_TECOMPLETE) == 0) {
if(fsa_state == S_TRANSITION_ENGINE) {
next_input = I_SUCCESS;
/* silently ignore? probably means the TE is signaling OK too early
} else {
cl_log(LOG_WARNING,
"Op %s is only valid in state %s (%s)",
op,
fsa_state2string(S_TRANSITION_ENGINE),
fsa_state2string(fsa_state));
*/
}
} else if(strcmp(op, CRM_OP_HBEAT) == 0) {
next_input = I_DC_HEARTBEAT;
} else if(strcmp(op, CRM_OP_WELCOME) == 0) {
next_input = I_WELCOME;
} else if(strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
/* create cib fragment and add to message */
/* handle here to avoid potential version issues
* where the shutdown message/proceedure may have
* been changed in later versions.
*
* This way the DC is always in control of the shutdown
*/
xmlNodePtr frag = NULL;
time_t now = time(NULL);
char *now_s = crm_itoa((int)now);
xmlNodePtr node_state =
create_xml_node(NULL, XML_CIB_TAG_STATE);
cl_log(LOG_INFO, "Creating shutdown request for %s",
host_from);
set_xml_property_copy(
node_state, XML_ATTR_ID, host_from);
set_xml_property_copy(
node_state, XML_CIB_ATTR_SHUTDOWN, now_s);
set_xml_property_copy(
node_state,
XML_CIB_ATTR_EXPSTATE,
CRMD_STATE_INACTIVE);
frag = create_cib_fragment(node_state, NULL);
xmlAddChild(stored_msg, frag);
free_xml(node_state);
crm_free(now_s);
next_input = I_CIB_OP;
} else if(strcmp(op, CRM_OP_SHUTDOWN) == 0) {
next_input = I_TERMINATE;
} else if(strcmp(op, CRM_OP_ANNOUNCE) == 0) {
next_input = I_NODE_JOIN;
} else if(strcmp(op, CRM_OP_REPLACE) == 0
|| strcmp(op, CRM_OP_ERASE) == 0) {
next_input = I_CIB_OP;
fprintf(router_strm, "Message result: CIB Op\n");
} else if(AM_I_DC
&& (strcmp(op, CRM_OP_CREATE) == 0
|| strcmp(op, CRM_OP_UPDATE) == 0
|| strcmp(op, CRM_OP_DELETE) == 0)) {
/* updates should only be performed on the DC */
next_input = I_CIB_OP;
} else if(strcmp(op, CRM_OP_PING) == 0) {
/* eventually do some stuff to figure out
* if we /are/ ok
*/
xmlNodePtr ping =
createPingAnswerFragment(sys_to, "ok");
xmlNodePtr wrapper = create_reply(stored_msg, ping);
relay_message(wrapper, TRUE);
free_xml(wrapper);
} else {
cl_log(LOG_ERR,
"Unexpected request (op=%s) sent to the %s",
op, AM_I_DC?"DC":"CRMd");
}
} else if(strcmp(type, XML_ATTR_RESPONSE) == 0) {
if(strcmp(op, CRM_OP_WELCOME) == 0) {
next_input = I_WELCOME_ACK;
} else if(AM_I_DC
&& strcmp(op, CRM_OP_PECALC) == 0) {
if(fsa_state == S_POLICY_ENGINE
&& safe_str_eq(msg_ref, fsa_pe_ref)) {
next_input = I_SUCCESS;
} else if(fsa_state != S_POLICY_ENGINE) {
cl_log(LOG_ERR,
"Reply to %s is only valid in state %s",
op, fsa_state2string(S_POLICY_ENGINE));
} else {
CRM_DEBUG("Skipping superceeded reply from %s",
sys_from);
}
} else if(strcmp(op, CRM_OP_VOTE) == 0
|| strcmp(op, CRM_OP_HBEAT) == 0
|| strcmp(op, CRM_OP_WELCOME) == 0
|| strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0
|| strcmp(op, CRM_OP_SHUTDOWN) == 0
|| strcmp(op, CRM_OP_ANNOUNCE) == 0) {
next_input = I_NULL;
} else if(strcmp(op, CRM_OP_CREATE) == 0
|| strcmp(op, CRM_OP_UPDATE) == 0
|| strcmp(op, CRM_OP_DELETE) == 0
|| strcmp(op, CRM_OP_REPLACE) == 0
|| strcmp(op, CRM_OP_ERASE) == 0) {
/* perhaps we should do somethign with these replies,
* especially check that the actions passed
*/
/* fprintf(router_strm, "Message result: CIB Reply\n"); */
} else {
cl_log(LOG_ERR,
"Unexpected response (op=%s) sent to the %s",
op, AM_I_DC?"DC":"CRMd");
next_input = I_NULL;
}
} else {
cl_log(LOG_ERR, "Unexpected message type %s", type);
}
/* CRM_DEBUG("%s: Next input is %s", __FUNCTION__, */
/* fsa_input2string(next_input)); */
return next_input;
}
void lrm_op_callback (lrm_op_t* op)
{
- CRM_DEBUG("In lrm_op_callback()");
-
s_crmd_fsa(C_LRM_OP_CALLBACK, I_LRM_EVENT, op);
}
void lrm_monitor_callback (lrm_mon_t* monitor)
{
- CRM_DEBUG("In lrm_monitor_callback()");
s_crmd_fsa(C_LRM_MONITOR_CALLBACK, I_LRM_EVENT, monitor);
}
diff --git a/crm/crmd/subsystems.c b/crm/crmd/subsystems.c
index 51f9a7c5d2..7705a5215e 100644
--- a/crm/crmd/subsystems.c
+++ b/crm/crmd/subsystems.c
@@ -1,644 +1,641 @@
/*
* 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 <crm/crm.h>
#include <crmd_fsa.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h> // for access
#include <clplumbing/cl_signal.h>
#include <clplumbing/realtime.h>
#include <sys/types.h> // for calls to open
#include <sys/stat.h> // for calls to open
#include <fcntl.h> // for calls to open
#include <pwd.h> // for getpwuid
#include <grp.h> // for initgroups
#include <sys/time.h> // for getrlimit
#include <sys/resource.h>// for getrlimit
#include <crm/common/crmutils.h>
#include <crm/common/ipcutils.h>
#include <crm/common/msgutils.h>
#include <crm/msg_xml.h>
#include <crm/common/xmlutils.h>
#include <crm/cib.h>
#include <crmd.h>
#include <crmd_messages.h>
#include <string.h>
#include <errno.h>
#include <crm/dmalloc_wrapper.h>
#define CLIENT_EXIT_WAIT 10
static gboolean stop_subsystem (struct crm_subsystem_s *centry);
static gboolean start_subsystem(struct crm_subsystem_s *centry);
struct crm_subsystem_s *cib_subsystem = NULL;
struct crm_subsystem_s *te_subsystem = NULL;
struct crm_subsystem_s *pe_subsystem = NULL;
/* A_CIB_STOP, A_CIB_START, A_CIB_RESTART, */
enum crmd_fsa_input
do_cib_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input result = I_NULL;
struct crm_subsystem_s *this_subsys = cib_subsystem;
long long stop_actions = A_CIB_STOP;
long long start_actions = A_CIB_START;
FNIN();
if(action & stop_actions) {
// dont do anything, its embedded now
}
if(action & start_actions) {
if(cur_state != S_STOPPING) {
if(startCib(CIB_FILENAME) == FALSE)
result = I_FAIL;
} else {
cl_log(LOG_INFO,
"Ignoring request to start %s after shutdown",
this_subsys->command);
}
}
FNRET(result);
}
/* A_CIB_INVOKE, A_CIB_BUMPGEN, A_UPDATE_NODESTATUS */
enum crmd_fsa_input
do_cib_invoke(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
xmlNodePtr cib_msg = NULL;
xmlNodePtr answer = NULL;
xmlNodePtr new_options = NULL;
const char *section = NULL;
FNIN();
if(data != NULL) {
cib_msg = (xmlNodePtr)data;
}
if(action & A_CIB_INVOKE) {
const char *op = get_xml_attr(cib_msg, XML_TAG_OPTIONS,
XML_ATTR_OP, TRUE);
xml_message_debug(cib_msg, "[CIB] Invoking with");
if(cib_msg == NULL) {
cl_log(LOG_ERR, "No message for CIB command");
FNRET(I_NULL); // I_ERROR
}
set_xml_property_copy(cib_msg, XML_ATTR_SYSTO, "cib");
answer = process_cib_message(cib_msg, TRUE);
if(relay_message(answer, TRUE) == FALSE) {
cl_log(LOG_ERR, "Confused what to do with cib result");
xml_message_debug(answer, "Couldnt route: ");
}
if(op != NULL && AM_I_DC
&& (strcmp(op, CRM_OP_CREATE) == 0
|| strcmp(op, CRM_OP_UPDATE) == 0
|| strcmp(op, CRM_OP_DELETE) == 0
|| strcmp(op, CRM_OP_REPLACE) == 0
|| strcmp(op, CRM_OP_WELCOME) == 0
|| strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0
|| strcmp(op, CRM_OP_ERASE) == 0)) {
FNRET(I_CIB_UPDATE);
}
if(op == NULL) {
xml_message_debug(cib_msg, "Invalid CIB Message");
}
// check the answer, see if we are interested in it also
#if 0
if(interested in reply) {
put_message(answer);
FNRET(I_REQUEST);
}
#endif
free_xml(answer);
/* experimental */
} else if(action & A_CIB_INVOKE_LOCAL) {
xml_message_debug(cib_msg, "[CIB] Invoking with");
if(cib_msg == NULL) {
cl_log(LOG_ERR, "No message for CIB command");
FNRET(I_NULL); // I_ERROR
}
answer = process_cib_message(cib_msg, TRUE);
put_message(answer);
FNRET(I_REQUEST);
} else if(action & A_CIB_BUMPGEN) {
// check if the response was ok before next bit
section = get_xml_attr(cib_msg, XML_TAG_OPTIONS,
XML_ATTR_FILTER_TYPE, FALSE);
/* set the section so that we dont always send the
* whole thing
*/
if(section != NULL) {
new_options = set_xml_attr(NULL, XML_TAG_OPTIONS,
XML_ATTR_FILTER_TYPE,
section, TRUE);
}
answer = process_cib_request(CRM_OP_BUMP,
new_options, NULL);
free_xml(new_options);
if(answer == NULL) {
cl_log(LOG_ERR, "Result of BUMP in %s was NULL",
__FUNCTION__);
FNRET(I_FAIL);
}
send_request(NULL, answer, CRM_OP_REPLACE,
NULL, CRM_SYSTEM_CRMD, NULL);
free_xml(answer);
} else {
cl_log(LOG_ERR, "Unexpected action %s in %s",
fsa_action2string(action), __FUNCTION__);
}
FNRET(I_NULL);
}
/* A_PE_START, A_PE_STOP, A_TE_RESTART */
enum crmd_fsa_input
do_pe_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input result = I_NULL;
struct crm_subsystem_s *this_subsys = pe_subsystem;
long long stop_actions = A_PE_STOP;
long long start_actions = A_PE_START;
FNIN();
if(action & stop_actions) {
if(stop_subsystem(this_subsys) == FALSE)
result = I_FAIL;
else if(this_subsys->pid > 0){
int lpc = CLIENT_EXIT_WAIT;
int pid_status = -1;
while(lpc-- > 0
&& this_subsys->pid > 0
&& CL_PID_EXISTS(this_subsys->pid)) {
sleep(1);
waitpid(this_subsys->pid, &pid_status, WNOHANG);
}
if(CL_PID_EXISTS(this_subsys->pid)) {
cl_log(LOG_ERR,
"Process %s is still active with pid=%d",
this_subsys->command, this_subsys->pid);
result = I_FAIL;
}
}
cleanup_subsystem(this_subsys);
}
if(action & start_actions) {
if(cur_state != S_STOPPING) {
if(start_subsystem(this_subsys) == FALSE) {
result = I_FAIL;
cleanup_subsystem(this_subsys);
}
} else {
cl_log(LOG_INFO,
"Ignoring request to start %s while shutting down",
this_subsys->command);
}
}
FNRET(result);
}
char *fsa_pe_ref = NULL;
/* A_PE_INVOKE */
enum crmd_fsa_input
do_pe_invoke(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
FNIN();
stopTimer(integration_timer);
if(is_set(fsa_input_register, R_PE_CONNECTED) == FALSE){
cl_log(LOG_INFO, "Waiting for the PE to connect");
FNRET(I_WAIT_FOR_EVENT);
}
xmlNodePtr local_cib = get_cib_copy();
CRM_DEBUG("Invoking %s with %p", CRM_SYSTEM_PENGINE, local_cib);
if(fsa_pe_ref) {
crm_free(fsa_pe_ref);
fsa_pe_ref = NULL;
}
send_request(NULL, local_cib, CRM_OP_PECALC,
NULL, CRM_SYSTEM_PENGINE, &fsa_pe_ref);
FNRET(I_NULL);
}
/* A_TE_START, A_TE_STOP, A_TE_RESTART */
enum crmd_fsa_input
do_te_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input result = I_NULL;
struct crm_subsystem_s *this_subsys = te_subsystem;
long long stop_actions = A_TE_STOP;
long long start_actions = A_TE_START;
FNIN();
/* if(action & stop_actions && cur_state != S_STOPPING */
/* && is_set(fsa_input_register, R_TE_PEND)) { */
/* result = I_WAIT_FOR_EVENT; */
/* FNRET(result); */
/* } */
if(action & stop_actions) {
if(stop_subsystem(this_subsys) == FALSE)
result = I_FAIL;
else if(this_subsys->pid > 0){
int lpc = CLIENT_EXIT_WAIT;
int pid_status = -1;
while(lpc-- > 0
&& this_subsys->pid > 0
&& CL_PID_EXISTS(this_subsys->pid)) {
sleep(1);
waitpid(this_subsys->pid, &pid_status, WNOHANG);
}
if(CL_PID_EXISTS(this_subsys->pid)) {
cl_log(LOG_ERR,
"Process %s is still active with pid=%d",
this_subsys->command, this_subsys->pid);
result = I_FAIL;
}
}
cleanup_subsystem(this_subsys);
}
if(action & start_actions) {
if(cur_state != S_STOPPING) {
if(start_subsystem(this_subsys) == FALSE) {
result = I_FAIL;
cleanup_subsystem(this_subsys);
}
} else {
cl_log(LOG_INFO,
"Ignoring request to start %s while shutting down",
this_subsys->command);
}
}
FNRET(result);
}
static xmlNodePtr te_last_input = NULL;
static xmlNodePtr te_lastcc = NULL;
/* A_TE_COPYTO */
enum crmd_fsa_input
do_te_copyto(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
xmlNodePtr message = NULL;
xmlNodePtr opts = NULL;
const char *true_op = NULL;
FNIN();
if(data != NULL) {
message = copy_xml_node_recursive((xmlNodePtr)data);
opts = find_xml_node(message, XML_TAG_OPTIONS);
true_op = xmlGetProp(opts, XML_ATTR_OP);
set_xml_property_copy(opts, XML_ATTR_OP, CRM_OP_EVENTCC);
set_xml_property_copy(opts, XML_ATTR_TRUEOP, true_op);
set_xml_property_copy(message,
XML_ATTR_SYSTO,
CRM_SYSTEM_TENGINE);
}
if(is_set(fsa_input_register, R_TE_CONNECTED) == FALSE){
cl_log(LOG_INFO, "Waiting for the TE to connect");
if(data != NULL) {
free_xml(te_lastcc);
te_lastcc = message;
}
FNRET(I_WAIT_FOR_EVENT);
}
if(message == NULL) {
message = te_lastcc;
te_lastcc = NULL;
} else {
free_xml(te_lastcc);
}
relay_message(message, FALSE);
// only free it if it was a local copy
if(data == NULL) {
free_xml(message);
}
FNRET(I_NULL);
}
/* A_TE_INVOKE, A_TE_CANCEL */
enum crmd_fsa_input
do_te_invoke(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
xmlNodePtr graph = NULL;
xmlNodePtr msg = (xmlNodePtr)data;
FNIN();
if(is_set(fsa_input_register, R_TE_CONNECTED) == FALSE){
cl_log(LOG_INFO, "Waiting for the TE to connect");
if(data != NULL) {
free_xml(te_last_input);
te_last_input = copy_xml_node_recursive(msg);
}
FNRET(I_WAIT_FOR_EVENT);
}
if(msg == NULL) {
msg = te_last_input;
te_last_input = NULL;
} else {
free_xml(te_last_input);
}
if(action & A_TE_INVOKE) {
graph = find_xml_node(msg, "transition_graph");
if(graph == NULL) {
FNRET(I_FAIL);
}
send_request(NULL, graph, CRM_OP_TRANSITION,
NULL, CRM_SYSTEM_TENGINE, NULL);
} else {
send_request(NULL, graph, CRM_OP_ABORT,
NULL, CRM_SYSTEM_TENGINE, NULL);
}
// only free it if it was a local copy
if(data == NULL) {
free_xml(msg);
}
FNRET(I_NULL);
}
gboolean
crmd_client_connect(IPC_Channel *client_channel, gpointer user_data)
{
FNIN();
- CRM_DEBUG("A client tried to connect... and there was much rejoicing.");
-
if (client_channel == NULL) {
cl_log(LOG_ERR, "Channel was NULL");
} else if (client_channel->ch_status == IPC_DISCONNECT) {
cl_log(LOG_ERR, "Channel was disconnected");
} else {
crmd_client_t *blank_client =
(crmd_client_t *)crm_malloc(sizeof(crmd_client_t));
if (blank_client == NULL) {
cl_log(LOG_ERR,
"Could not allocate memory for a blank crmd_client_t");
FNRET(FALSE);
}
client_channel->ops->set_recv_qlen(client_channel, 100);
client_channel->ops->set_send_qlen(client_channel, 100);
blank_client->client_channel = client_channel;
blank_client->sub_sys = NULL;
blank_client->uuid = NULL;
blank_client->table_key = NULL;
- CRM_DEBUG("Adding IPC Channel to main thread.");
blank_client->client_source =
G_main_add_IPC_Channel(G_PRIORITY_LOW,
client_channel,
FALSE,
crmd_ipc_input_callback,
blank_client,
default_ipc_input_destroy);
}
FNRET(TRUE);
}
static gboolean
stop_subsystem(struct crm_subsystem_s* centry)
{
cl_log(LOG_INFO, "Stopping sub-system \"%s\"", centry->name);
if (centry->pid <= 0) {
cl_log(LOG_ERR,
"OOPS! client %s not running yet",
centry->command);
} else {
cl_log(LOG_INFO, "Sending quit message to %s.", centry->name);
send_request(NULL, NULL, CRM_OP_QUIT, NULL, centry->name, NULL);
}
return TRUE;
}
static gboolean
start_subsystem(struct crm_subsystem_s* centry)
{
pid_t pid;
struct stat buf;
int s_res;
cl_log(LOG_INFO, "Starting sub-system \"%s\"", centry->command);
if (centry->pid != 0) {
cl_log(LOG_ERR, "OOPS! client %s already running as pid %d"
, centry->command, (int) centry->pid);
}
/*
* We need to ensure that the exec will succeed before
* we bother forking. We don't want to respawn something that
* won't exec in the first place.
*/
if (access(centry->path, F_OK|X_OK) != 0) {
cl_perror("Cannot (access) exec %s", centry->path);
return FALSE;
}
s_res = stat(centry->command, &buf);
if(s_res != 0) {
cl_perror("Cannot (stat) exec %s", centry->command);
return FALSE;
}
/* We need to fork so we can make child procs not real time */
switch(pid=fork()) {
case -1:
cl_log(LOG_ERR, "start_a_child_client: Cannot fork.");
return FALSE;
default: /* Parent */
centry->pid = pid;
return TRUE;
case 0: /* Child */
break;
}
/* Child process: start the managed child */
cl_make_normaltime();
setpgid(0,0);
/* Limit peak resource usage, maximize success chances */
if (centry->shortrcount > 0) {
alarm(0);
sleep(1);
}
cl_log(LOG_INFO, "Executing \"%s\" (pid %d)",
centry->command, (int) getpid());
if(CL_SIGINTERRUPT(SIGALRM, 0) < 0) {
cl_perror("Cannot set interrupt for child process %s",
centry->command);
}else{
const char * devnull = "/dev/null";
unsigned int j;
struct rlimit oflimits;
CL_SIGNAL(SIGCHLD, SIG_DFL);
alarm(0);
CL_IGNORE_SIG(SIGALRM);
/* A precautionary measure */
getrlimit(RLIMIT_NOFILE, &oflimits);
for (j=0; j < oflimits.rlim_cur; ++j) {
close(j);
}
(void)devnull;
(void)open(devnull, O_RDONLY); /* Stdin: fd 0 */
(void)open(devnull, O_WRONLY); /* Stdout: fd 1 */
(void)open(devnull, O_WRONLY); /* Stderr: fd 2 */
(void)execl("/bin/sh", "sh", "-c", centry->command, (const char *)NULL);
/* Should not happen */
cl_perror("Cannot exec %s", centry->command);
}
/* Suppress respawning */
exit(100);
// never reached
return TRUE;
}
diff --git a/crm/pengine/penginemain.c b/crm/pengine/penginemain.c
index ae385862e9..b81042be35 100644
--- a/crm/pengine/penginemain.c
+++ b/crm/pengine/penginemain.c
@@ -1,238 +1,238 @@
-/* $Id: penginemain.c,v 1.13 2004/06/01 12:25:16 andrew Exp $ */
+/* $Id: penginemain.c,v 1.14 2004/06/01 16:12:50 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 <crm/crm.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <hb_api.h>
#include <apphb.h>
#include <clplumbing/ipc.h>
#include <clplumbing/Gmain_timeout.h>
#include <clplumbing/cl_log.h>
#include <clplumbing/cl_signal.h>
#include <clplumbing/lsb_exitcodes.h>
#include <clplumbing/uids.h>
#include <clplumbing/realtime.h>
#include <clplumbing/GSource.h>
#include <clplumbing/cl_poll.h>
#include <crm/common/ipcutils.h>
#include <crm/common/crmutils.h>
#include <crm/common/msgutils.h>
#include <crm/dmalloc_wrapper.h>
#define SYS_NAME CRM_SYSTEM_PENGINE
#define OPTARGS "skrh"
#define PID_FILE WORKING_DIR "/"SYS_NAME".pid"
#define DAEMON_LOG "/var/log/"SYS_NAME".log"
#define DAEMON_DEBUG "/var/log/"SYS_NAME".debug"
GMainLoop* mainloop = NULL;
const char* crm_system_name = SYS_NAME;
void usage(const char* cmd, int exit_status);
int init_start(void);
void pengine_shutdown(int nsig);
extern gboolean process_pe_message(xmlNodePtr msg, IPC_Channel *sender);
int
main(int argc, char ** argv)
{
int req_restart = FALSE;
int req_status = FALSE;
int req_stop = FALSE;
int argerr = 0;
int flag;
cl_log_set_entity(crm_system_name);
cl_log_enable_stderr(TRUE);
cl_log_set_facility(LOG_USER);
if (0)
{
send_ipc_message(NULL, NULL);
}
while ((flag = getopt(argc, argv, OPTARGS)) != EOF) {
switch(flag) {
case 's': /* Status */
req_status = TRUE;
break;
case 'k': /* Stop (kill) */
req_stop = TRUE;
break;
case 'r': /* Restart */
req_restart = TRUE;
break;
case 'h': /* Help message */
usage(crm_system_name, LSB_EXIT_OK);
break;
default:
++argerr;
break;
}
}
if (optind > argc) {
++argerr;
}
if (argerr) {
usage(crm_system_name,LSB_EXIT_GENERIC);
}
// read local config file
if (req_status){
return init_status(PID_FILE, crm_system_name);
}
if (req_stop){
return init_stop(PID_FILE);
}
if (req_restart) {
init_stop(PID_FILE);
}
return init_start();
}
int
init_start(void)
{
long pid;
ll_cluster_t* hb_fd = NULL;
int facility;
IPC_Channel *crm_ch = NULL;
#ifdef REALTIME_SUPPORT
static int crm_realtime = 1;
#endif
if ((pid = get_running_pid(PID_FILE, NULL)) > 0) {
cl_log(LOG_CRIT, "already running: [pid %ld].", pid);
exit(LSB_EXIT_OK);
}
cl_log_set_logfile(DAEMON_LOG);
// if (crm_debug()) {
cl_log_set_debugfile(DAEMON_DEBUG);
// }
/* change the logging facility to the one used by heartbeat daemon */
hb_fd = ll_cluster_new("heartbeat");
cl_log(LOG_INFO, "Switching to Heartbeat logger");
if ((facility = hb_fd->llc_ops->get_logfacility(hb_fd))>0) {
cl_log_set_facility(facility);
}
cl_log(LOG_INFO, "Register PID");
register_pid(PID_FILE, FALSE, pengine_shutdown);
- crm_ch = init_client_ipc_comms("crmd",
+ crm_ch = init_client_ipc_comms(CRM_SYSTEM_CRMD,
subsystem_input_dispatch,
(void*)process_pe_message);
if(crm_ch != NULL) {
send_hello_message(crm_ch, "1234", CRM_SYSTEM_PENGINE, "0", "1");
/* Create the mainloop and run it... */
mainloop = g_main_new(FALSE);
cl_log(LOG_INFO, "Starting %s", crm_system_name);
#ifdef REALTIME_SUPPORT
if (crm_realtime == 1){
cl_enable_realtime();
}else if (crm_realtime == 0){
cl_disable_realtime();
}
cl_make_realtime(SCHED_RR, 5, 64, 64);
#endif
g_main_run(mainloop);
} else {
cl_log(LOG_ERR, "Could not connect to the CRMd");
}
return_to_orig_privs();
if (unlink(PID_FILE) == 0) {
cl_log(LOG_INFO, "[%s] stopped", crm_system_name);
}
if(crm_ch != NULL)
return 0;
return 1;
}
void
usage(const char* cmd, int exit_status)
{
FILE* stream;
stream = exit_status ? stderr : stdout;
fprintf(stream, "usage: %s [-srkh]"
"[-c configure file]\n", cmd);
/* fprintf(stream, "\t-d\tsets debug level\n"); */
/* fprintf(stream, "\t-s\tgets daemon status\n"); */
/* fprintf(stream, "\t-r\trestarts daemon\n"); */
/* fprintf(stream, "\t-k\tstops daemon\n"); */
/* fprintf(stream, "\t-h\thelp message\n"); */
fflush(stream);
exit(exit_status);
}
void
pengine_shutdown(int nsig)
{
static int shuttingdown = 0;
CL_SIGNAL(nsig, pengine_shutdown);
if (!shuttingdown) {
shuttingdown = 1;
}
if (mainloop != NULL && g_main_is_running(mainloop)) {
g_main_quit(mainloop);
}else{
exit(LSB_EXIT_OK);
}
}
diff --git a/crm/tengine/tenginemain.c b/crm/tengine/tenginemain.c
index 7d988e4ea2..61dd5ea2b4 100644
--- a/crm/tengine/tenginemain.c
+++ b/crm/tengine/tenginemain.c
@@ -1,237 +1,237 @@
-/* $Id: tenginemain.c,v 1.13 2004/05/06 12:11:59 andrew Exp $ */
+/* $Id: tenginemain.c,v 1.14 2004/06/01 16:12:50 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 <crm/crm.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <hb_api.h>
#include <apphb.h>
#include <clplumbing/ipc.h>
#include <clplumbing/Gmain_timeout.h>
#include <clplumbing/cl_log.h>
#include <clplumbing/cl_signal.h>
#include <clplumbing/lsb_exitcodes.h>
#include <clplumbing/uids.h>
#include <clplumbing/realtime.h>
#include <clplumbing/GSource.h>
#include <clplumbing/cl_poll.h>
#include <crm/common/ipcutils.h>
#include <crm/common/crmutils.h>
#include <crm/common/msgutils.h>
#include <tengine.h>
#include <crm/dmalloc_wrapper.h>
#define OPTARGS "skrh"
#define PID_FILE WORKING_DIR "/transitioner.pid"
#define DAEMON_LOG "/var/log/transitioner.log"
#define DAEMON_DEBUG "/var/log/transitioner.debug"
GMainLoop* mainloop = NULL;
const char* crm_system_name = "transitioner";
void usage(const char* cmd, int exit_status);
int init_start(void);
void tengine_shutdown(int nsig);
int
main(int argc, char ** argv)
{
int req_restart = FALSE;
int req_status = FALSE;
int req_stop = FALSE;
int argerr = 0;
int flag;
cl_log_set_entity(crm_system_name);
cl_log_enable_stderr(TRUE);
cl_log_set_facility(LOG_USER);
if (0)
{
send_ipc_message(NULL, NULL);
}
while ((flag = getopt(argc, argv, OPTARGS)) != EOF) {
switch(flag) {
case 's': /* Status */
req_status = TRUE;
break;
case 'k': /* Stop (kill) */
req_stop = TRUE;
break;
case 'r': /* Restart */
req_restart = TRUE;
break;
case 'h': /* Help message */
usage(crm_system_name, LSB_EXIT_OK);
break;
default:
++argerr;
break;
}
}
if (optind > argc) {
++argerr;
}
if (argerr) {
usage(crm_system_name,LSB_EXIT_GENERIC);
}
// read local config file
if (req_status){
return init_status(PID_FILE, crm_system_name);
}
if (req_stop){
return init_stop(PID_FILE);
}
if (req_restart) {
init_stop(PID_FILE);
}
return init_start();
}
int
init_start(void)
{
long pid;
ll_cluster_t* hb_fd = NULL;
int facility;
#ifdef REALTIME_SUPPORT
static int crm_realtime = 1;
#endif
if ((pid = get_running_pid(PID_FILE, NULL)) > 0) {
cl_log(LOG_CRIT, "already running: [pid %ld].", pid);
exit(LSB_EXIT_OK);
}
cl_log_set_logfile(DAEMON_LOG);
// if (crm_debug()) {
cl_log_set_debugfile(DAEMON_DEBUG);
// }
/* change the logging facility to the one used by heartbeat daemon */
hb_fd = ll_cluster_new("heartbeat");
cl_log(LOG_INFO, "Switching to Heartbeat logger");
if ((facility = hb_fd->llc_ops->get_logfacility(hb_fd))>0) {
cl_log_set_facility(facility);
}
cl_log(LOG_INFO, "Register PID");
register_pid(PID_FILE, FALSE, tengine_shutdown);
- crm_ch = init_client_ipc_comms("crmd",
+ crm_ch = init_client_ipc_comms(CRM_SYSTEM_CRMD,
subsystem_input_dispatch,
(void*)process_te_message);
if(crm_ch != NULL) {
send_hello_message(crm_ch, "1234", CRM_SYSTEM_TENGINE, "0", "1");
/* Create the mainloop and run it... */
mainloop = g_main_new(FALSE);
cl_log(LOG_INFO, "Starting %s", crm_system_name);
#ifdef REALTIME_SUPPORT
if (crm_realtime == 1){
cl_enable_realtime();
}else if (crm_realtime == 0){
cl_disable_realtime();
}
cl_make_realtime(SCHED_RR, 5, 64, 64);
#endif
g_main_run(mainloop);
} else {
cl_log(LOG_ERR, "Could not connect to the CRMd");
}
return_to_orig_privs();
if (unlink(PID_FILE) == 0) {
cl_log(LOG_INFO, "[%s] stopped", crm_system_name);
}
if(crm_ch != NULL)
return 0;
return 1;
}
void
usage(const char* cmd, int exit_status)
{
FILE* stream;
stream = exit_status ? stderr : stdout;
fprintf(stream, "usage: %s [-srkh]"
"[-c configure file]\n", cmd);
/* fprintf(stream, "\t-d\tsets debug level\n"); */
/* fprintf(stream, "\t-s\tgets daemon status\n"); */
/* fprintf(stream, "\t-r\trestarts daemon\n"); */
/* fprintf(stream, "\t-k\tstops daemon\n"); */
/* fprintf(stream, "\t-h\thelp message\n"); */
fflush(stream);
exit(exit_status);
}
void
tengine_shutdown(int nsig)
{
static int shuttingdown = 0;
CL_SIGNAL(nsig, tengine_shutdown);
if (!shuttingdown) {
shuttingdown = 1;
}
if (mainloop != NULL && g_main_is_running(mainloop)) {
g_main_quit(mainloop);
}else{
exit(LSB_EXIT_OK);
}
}
diff --git a/crm/tengine/ttest.c b/crm/tengine/ttest.c
index c160666ff7..665a5c46ce 100644
--- a/crm/tengine/ttest.c
+++ b/crm/tengine/ttest.c
@@ -1,152 +1,152 @@
-/* $Id: ttest.c,v 1.2 2004/05/23 19:54:04 andrew Exp $ */
+/* $Id: ttest.c,v 1.3 2004/06/01 16:12:50 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 <crm/crm.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <hb_api.h>
#include <apphb.h>
#include <clplumbing/ipc.h>
#include <clplumbing/Gmain_timeout.h>
#include <clplumbing/cl_log.h>
#include <clplumbing/cl_signal.h>
#include <clplumbing/lsb_exitcodes.h>
#include <clplumbing/uids.h>
#include <clplumbing/realtime.h>
#include <clplumbing/GSource.h>
#include <clplumbing/cl_poll.h>
#include <crm/common/xmlutils.h>
#include <crm/msg_xml.h>
#include <crm/cib.h>
#define OPTARGS "V?i:o:D:C:S:HA:U:M:I:EWRFt:m:a:d:w:c:r:p:s:"
#include <getopt.h>
#include <glib.h>
#include <tengine.h>
extern gboolean unpack_graph(xmlNodePtr xml_graph);
extern gboolean initiate_transition(void);
extern gboolean initialize_graph(void);
int
main(int argc, char **argv)
{
int argerr = 0;
int flag;
cl_log_set_entity("ttest");
cl_log_enable_stderr(TRUE);
cl_log_set_facility(LOG_USER);
while (1) {
int option_index = 0;
static struct option long_options[] = {
// Top-level Options
{"daemon", 0, 0, 0},
{0, 0, 0, 0}
};
flag = getopt_long(argc, argv, OPTARGS,
long_options, &option_index);
if (flag == -1)
break;
switch(flag) {
case 0:
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
break;
/* 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':
printf("option %d", flag);
break;
default:
printf("?? getopt returned character code 0%o ??\n", 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) {
cl_log(LOG_ERR, "%d errors in option parsing", argerr);
}
cl_log(LOG_INFO, "=#=#=#=#= Getting XML =#=#=#=#=");
mtrace();
- CRM_DEBUG("Initializing graph...");
+ CRM_NOTE("Initializing graph...");
initialize_graph();
xmlNodePtr xml_graph = file2xml(stdin);
- CRM_DEBUG("Unpacking graph...");
+ CRM_NOTE("Unpacking graph...");
unpack_graph(xml_graph);
- CRM_DEBUG("Initiating transition...");
+ CRM_NOTE("Initiating transition...");
if(initiate_transition() == FALSE) {
// nothing to be done.. means we're done.
cl_log(LOG_INFO, "No actions to be taken..."
" transition compelte.");
}
initialize_graph();
free_xml(xml_graph);
muntrace();
- CRM_DEBUG("Transition complete...");
+ CRM_NOTE("Transition complete...");
return 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 10, 3:25 AM (11 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2003220
Default Alt Text
(180 KB)

Event Timeline