Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4639792
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
180 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment