📄 stonithd_lib.c
字号:
/* File: stonithd_lib.c * Description: Client library to STONITH deamon. * * Author: Sun Jiang Dong <sunjd@cn.ibm.com> * Copyright (c) 2004 International Business Machines * * 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 <config.h>#include <portability.h>#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <unistd.h>#include <fcntl.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <errno.h>#include <glib.h>#include <ha_msg.h>#include <clplumbing/cl_signal.h>#include <clplumbing/GSource.h>#include <clplumbing/uids.h>#include <clplumbing/cl_log.h>#include <clplumbing/lsb_exitcodes.h>#include <clplumbing/proctrack.h>#include <fencing/stonithd_api.h>#include <fencing/stonithd_msg.h>static const char * CLIENT_NAME = NULL;static pid_t CLIENT_PID = 0;static char CLIENT_PID_STR[16];static gboolean DEBUG_MODE = FALSE;static gboolean SIGNONED_TO_STONITHD = FALSE;static IPC_Channel * chan = NULL;static gboolean INT_BY_ALARM = FALSE;static unsigned int DEFAULT_TIMEOUT = 6;/* Must correspond to stonith_type_t *//* Not use it yet static const char * stonith_op_strname[] ={ "QUERY", "RESET", "POWERON", "POWEROFF"};*/static stonith_ops_callback_t stonith_ops_cb = NULL; static void * stonith_ops_cb_private_data = NULL;static stonithRA_ops_callback_t stonithRA_ops_cb = NULL;static void * stonithRA_ops_cb_private_data = NULL;static struct ha_msg * create_basic_reqmsg_fields(const char * apitype);static gboolean is_expected_msg(const struct ha_msg * msg, const char * field_name1, const char * field_content1, const char * field_name2, const char * field_content2 );static int chan_waitin_timeout(IPC_Channel * chan, unsigned int timeout);static int chan_waitout_timeout(IPC_Channel * chan, unsigned int timeout);static void sigalarm_handler(int signum);static void stdlib_log(int priority, const char * fmt, ...)G_GNUC_PRINTF(2,3);static void free_stonith_ops_t(stonith_ops_t * st_op);static void free_stonithRA_ops_t(stonithRA_ops_t * ra_op);intstonithd_signon(const char * client_name){ int rc = ST_FAIL; char path[] = IPC_PATH_ATTR; char sock[] = STONITHD_SOCK; struct ha_msg * request; struct ha_msg * reply; GHashTable * wchanattrs; uid_t my_euid; gid_t my_egid; const char * tmpstr; if ( SIGNONED_TO_STONITHD ) { /* if server is broken, then signoff and signon? important */ stdlib_log(LOG_INFO, "stonithd_signon: has sigoned to " "stonithd."); return ST_OK; } wchanattrs = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(wchanattrs, path, sock); /* Connect to the stonith deamon */ chan = ipc_channel_constructor(IPC_ANYTYPE, wchanattrs); g_hash_table_destroy(wchanattrs); if (chan == NULL) { stdlib_log(LOG_ERR, "stonithd_signon: Can't connect to " "stonithd"); return ST_FAIL; } if (chan->ops->initiate_connection(chan) != IPC_OK) { stdlib_log(LOG_ERR, "stonithd_signon: Can't initiate " "connection to stonithd"); return ST_FAIL; } CLIENT_PID = getpid(); snprintf(CLIENT_PID_STR, sizeof(CLIENT_PID_STR), "%d", CLIENT_PID); if ( client_name != NULL ) { CLIENT_NAME = client_name; } else { CLIENT_NAME = CLIENT_PID_STR; } if ( (request = create_basic_reqmsg_fields(ST_SIGNON)) == NULL) { return ST_FAIL; } /* important error check client name length */ my_euid = geteuid(); my_egid = getegid(); if ( ( ha_msg_add_int(request, F_STONITHD_CEUID, my_euid) != HA_OK ) ||( ha_msg_add_int(request, F_STONITHD_CEGID, my_egid) != HA_OK ) ) { stdlib_log(LOG_ERR, "stonithd_signon: " "cannot add field to ha_msg."); ZAPMSG(request); ZAPCHAN(chan); return ST_FAIL; } /* Send the registration request message */ if (msg2ipcchan(request, chan) != HA_OK) { ZAPMSG(request); ZAPCHAN(chan); stdlib_log(LOG_ERR, "can't send signon message to IPC"); return ST_FAIL; } /* waiting for the output to finish */ chan_waitout_timeout(chan, DEFAULT_TIMEOUT); ZAPMSG(request); /* Read the reply... */ stdlib_log(LOG_DEBUG, "waiting for the signon reply msg."); if ( IPC_OK != chan_waitin_timeout(chan, DEFAULT_TIMEOUT) ) { stdlib_log(LOG_ERR, "waitin failed."); /* how to deal. important */ return ST_FAIL; } if ( (reply = msgfromIPC_noauth(chan)) == NULL ) { stdlib_log(LOG_ERR, "stonithd_signon: to fetch reply failed."); return ST_FAIL; } if ( TRUE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_RSIGNON) ) { if ( ((tmpstr=cl_get_string(reply, F_STONITHD_APIRET)) != NULL) && (strncmp(tmpstr, ST_APIOK, strlen(ST_APIOK)) == 0) ) { SIGNONED_TO_STONITHD = TRUE; rc = ST_OK; stdlib_log(LOG_DEBUG, "signoned to the stonithd."); } else { stdlib_log(LOG_DEBUG, "failed to signon to the " "stonithd."); } } else { stdlib_log(LOG_DEBUG, "stonithd_signon: " "Got an unexpected message."); /* Handle it furtherly ? */ } ZAPMSG(reply); return rc;}int stonithd_signoff(void){ int rc = ST_FAIL; struct ha_msg * request, * reply; const char * tmpstr; if (SIGNONED_TO_STONITHD == FALSE) { stdlib_log(LOG_NOTICE, "Has been in signoff status."); return ST_OK; } if ( (request = create_basic_reqmsg_fields(ST_SIGNOFF)) == NULL) { return ST_FAIL; } /* Send the signoff request message */ if (msg2ipcchan(request, chan) != HA_OK) { ZAPMSG(request); stdlib_log(LOG_ERR, "can't send signoff message to IPC"); return ST_FAIL; } /* waiting for the output to finish */ chan_waitout_timeout(chan, DEFAULT_TIMEOUT); ZAPMSG(request); /* Read the reply... */ stdlib_log(LOG_DEBUG, "waiting for the signoff reply msg."); if ( IPC_OK != chan_waitin_timeout(chan, DEFAULT_TIMEOUT) ) { stdlib_log(LOG_ERR, "waitin failed."); return ST_FAIL; } if ( (reply = msgfromIPC_noauth(chan)) == NULL ) { stdlib_log(LOG_ERR, "stonithd_signoff: to fetch the reply msg " "failed."); return ST_FAIL; } if ( TRUE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_RSIGNOFF) ) { if ( ((tmpstr=cl_get_string(reply, F_STONITHD_APIRET)) != NULL) && (strncmp(tmpstr, ST_APIOK, strlen(ST_APIOK)) == 0) ) { SIGNONED_TO_STONITHD = FALSE; CLIENT_NAME = NULL; rc = ST_OK; stdlib_log(LOG_INFO, "succeeded to sign off the " "stonithd."); } else { stdlib_log(LOG_INFO, "fail to sign off the stonithd."); } } else { stdlib_log(LOG_DEBUG, "stonithd_signoff: " "Got an unexpected message."); } ha_msg_del(reply); return rc;}IPC_Channel *stonithd_input_IPC_channel(void){ if ( SIGNONED_TO_STONITHD == TRUE ) { return chan; } else { stdlib_log(LOG_ERR, "stonithd_input_IPC_channel: not signon."); return NULL; }}int stonithd_node_fence(stonith_ops_t * op){ int rc = ST_FAIL; struct ha_msg * request, * reply; const char * tmpstr; if (op == NULL) { stdlib_log(LOG_ERR, "stonithd_node_fence: op==NULL"); return ST_FAIL; } if (SIGNONED_TO_STONITHD == FALSE) { stdlib_log(LOG_NOTICE, "Has been in signoff status."); return ST_FAIL; } if ( (request = create_basic_reqmsg_fields(ST_STONITH)) == NULL) { return ST_FAIL; } if ( (ha_msg_add_int(request, F_STONITHD_OPTYPE, op->optype) != HA_OK ) ||(ha_msg_add(request, F_STONITHD_NODE, op->node_name ) != HA_OK) ||(ha_msg_add_int(request, F_STONITHD_TIMEOUT, op->timeout) != HA_OK) ) { stdlib_log(LOG_ERR, "stonithd_node_fence: " "cannot add field to ha_msg."); ZAPMSG(request); return ST_FAIL; } /* Send the stonith request message */ if (msg2ipcchan(request, chan) != HA_OK) { ZAPMSG(request); stdlib_log(LOG_ERR, "can't send signoff message to IPC"); return ST_FAIL; } /* waiting for the output to finish */ chan_waitout_timeout(chan, DEFAULT_TIMEOUT); ZAPMSG(request); /* Read the reply... */ stdlib_log(LOG_DEBUG, "waiting for the stonith reply msg."); if ( IPC_OK != chan_waitin_timeout(chan, DEFAULT_TIMEOUT) ) { stdlib_log(LOG_ERR, "stonithd_node_fence: waitin failed."); /* how to deal. important */ return ST_FAIL; } if ( (reply = msgfromIPC_noauth(chan)) == NULL ) { stdlib_log(LOG_ERR, "stonithd_node_fence: fail to fetch reply"); return ST_FAIL; } if ( TRUE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_RSTONITH) ) { if ( ((tmpstr = cl_get_string(reply, F_STONITHD_APIRET)) != NULL) && (strncmp(tmpstr, ST_APIOK, strlen(ST_APIOK)) == 0) ) { rc = ST_OK; stdlib_log(LOG_DEBUG, "stonith msg is sent to stonithd."); } else { stdlib_log(LOG_DEBUG, "failed to send stonith request to " "the stonithd."); } } else { stdlib_log(LOG_DEBUG, "stonithd_node_fence: " "Got an unexpected message."); /* Need to handle in other way? */ } ZAPMSG(reply); return rc;}gboolean stonithd_op_result_ready(void){ if ( SIGNONED_TO_STONITHD == FALSE ) { stdlib_log(LOG_ERR, "stonithd_op_result_ready: " "failed due to not on signon status."); return FALSE; } if ( chan == NULL ) { stdlib_log(LOG_ERR, "stonithd_op_result_ready: " "failed due to IPC channel chan == NULL."); return FALSE; } /* * Regards IPC_DISCONNECT as a special result, so to prevent the caller * from the possible endless waiting. That can be caused by the way * in which the caller uses it. */ return (chan->ops->is_message_pending(chan) || chan->ch_status == IPC_DISCONNECT);}intstonithd_receive_ops_result(gboolean blocking){ struct ha_msg* reply = NULL; const char * tmpstr = NULL; int tmpint = 0; int rc = ST_OK; stdlib_log(LOG_DEBUG, "stonithd_receive_ops_result: begin"); /* If there is no msg ready and none blocking mode, then return */ if ((stonithd_op_result_ready() == FALSE) && (blocking == FALSE)) { stdlib_log(LOG_INFO, "stonithd_receive_ops_result: " "no result available."); return ST_OK; } if (stonithd_op_result_ready() == FALSE) { /* at that time, blocking must be TRUE */ if (IPC_OK != chan->ops->waitin(chan)) { return ST_FAIL; } } reply = msgfromIPC_noauth(chan); if ( TRUE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_STRET) ) { stonith_ops_t * st_op = NULL; stdlib_log(LOG_DEBUG, "received stonith final ret."); /* handle the stonith op result message */ st_op = g_new(stonith_ops_t, 1); if ( ha_msg_value_int(reply, F_STONITHD_OPTYPE, &tmpint) == HA_OK) { st_op->optype = tmpint; } else { stdlib_log(LOG_ERR, "stonithd_receive_ops_result: the " "reply message contains no optype field."); rc = ST_FAIL; } if ((tmpstr = cl_get_string(reply, F_STONITHD_NODE)) != NULL) { st_op->node_name = g_strdup(tmpstr); } else { stdlib_log(LOG_ERR, "stonithd_receive_ops_result: the " "reply contains no node_name field."); rc = ST_FAIL; } if ( ha_msg_value_int(reply, F_STONITHD_TIMEOUT, &tmpint) == HA_OK ) { st_op->timeout = tmpint; } else { stdlib_log(LOG_ERR, "stonithd_receive_ops_result: the " "reply message contains no timeout field."); rc = ST_FAIL; } if ( ha_msg_value_int(reply, F_STONITHD_CALLID, &tmpint) == HA_OK ) { st_op->call_id = tmpint; } else { stdlib_log(LOG_ERR, "stonithd_receive_ops_result: the " "reply message contains no call_id field."); rc = ST_FAIL; } if (ha_msg_value_int(reply, F_STONITHD_FRC, &tmpint) == HA_OK) { st_op->op_result = tmpint; } else { stdlib_log(LOG_ERR, "stonithd_receive_ops_result: the " "reply contains no op_result field."); rc = ST_FAIL; } if ((tmpstr=cl_get_string(reply, F_STONITHD_APPEND)) != NULL) { st_op->node_list = g_strdup(tmpstr); } else { st_op->node_list = NULL; stdlib_log(LOG_DEBUG, "stonithd_receive_ops_result: the " "reply message contains no appendix field."); } if (stonith_ops_cb != NULL) { stdlib_log(LOG_DEBUG, "trigger stonith op callback."); stonith_ops_cb(st_op, stonith_ops_cb_private_data); } else { stdlib_log(LOG_DEBUG, "No stonith op callback."); } free_stonith_ops_t(st_op); ZAPMSG(reply); return ST_OK; } if ( TRUE == is_expected_msg(reply, F_STONITHD_TYPE, ST_APIRPL, F_STONITHD_APIRPL, ST_RAOPRET ) ) { stonithRA_ops_t * ra_op = NULL; stdlib_log(LOG_DEBUG, "received stonithRA op final ret."); /* handle the stonithRA op result message */ ra_op = g_new(stonithRA_ops_t, 1); tmpstr = cl_get_string(reply, F_STONITHD_RSCID); if (tmpstr != NULL) { ra_op->rsc_id = g_strdup(tmpstr); stdlib_log(LOG_DEBUG, "ra_op->rsc_id=%s.", ra_op->rsc_id); } else { stdlib_log(LOG_ERR, "stonithd_receive_ops_result: the " "reply message contains no rsc_id field."); rc = ST_FAIL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -