Add support to log IPMI events Add IPMI event logging support to servicelog package by reading from a FIFO created by the ipmievd daemon (part of ipmitool package). ipmilog daemon reads events from this FIFO and logs them to the servicelog database through servicelog APIs.
Signed-off-by: M. Mohan Kumar <mo...@in.ibm.com> --- configure.ac | 10 ++- src/Makefile.am | 2 +- src/ipmilog.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 335 insertions(+), 3 deletions(-) create mode 100644 src/ipmilog.c diff --git a/configure.ac b/configure.ac index 261c4c7..bd6b34e 100644 --- a/configure.ac +++ b/configure.ac @@ -37,20 +37,26 @@ VERSION=$GENERIC_VERSION # Checks for programs. AC_PROG_CC AC_PROG_INSTALL +AC_PROG_CXX +AC_PROG_LN_S +AC_PROG_RANLIB # Checks for libraries. AC_CHECK_LIB([servicelog], [servicelog_open servicelog_close]) # Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS([stdlib.h string.h unistd.h]) +AC_CHECK_HEADERS([stdlib.h string.h unistd.h fcntl.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T +AC_TYPE_PID_T # Checks for library functions. -AC_CHECK_FUNCS([memset strtol]) +AC_CHECK_FUNCS([memset strtol strerror fork]) +AC_FUNC_FORK() +AC_FUNC_MALLOC() AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile servicelog.spec]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index 7b7f5f5..4d84409 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ AM_CFLAGS = -Wall AM_LDFLAGS = -lservicelog -bin_PROGRAMS = servicelog servicelog_notify log_repair_action +bin_PROGRAMS = servicelog servicelog_notify log_repair_action ipmilog sbin_PROGRAMS = slog_common_event servicelog_SOURCES = servicelog.c diff --git a/src/ipmilog.c b/src/ipmilog.c new file mode 100644 index 0000000..9f1aaeb --- /dev/null +++ b/src/ipmilog.c @@ -0,0 +1,326 @@ +/** + * @file ipmilog.c + * @brief Program for getting IPMI events from ipmievd and logging them + * to servicelog database + * + * Copyright (C) 2008 IBM + * + * 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 + * of the License, or (at your option) any later version. + * + * This program 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 program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <time.h> +#include <stdlib.h> +#include <syslog.h> +#include <poll.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <servicelog-1/servicelog.h> + +#define FIFO "/var/log/sfifo" +#define MSG_SIZE 256 +#define REFCODE_SIZE 50 + +int fifo, listen, run_daemon = 1; +servicelog *ipmi; +char prog[50]; + +struct servicelog_info { + time_t time; + char type[REFCODE_SIZE]; + uint8_t severity; + char desc[MSG_SIZE]; + int serviceable; + int predictive; + int disposition; + int sel_id; + int sel_type; + int generator; + int version; + int s_type; + int s_num; + int e_type; + int e_class; + int e_dir; +}sinfo; + +void log_error(const char *string, ...); +void log_info(const char *string, ...); +void event_slog(struct servicelog_info sinfo); +int get_ipmi_event(void); +void cleanup(int signum); + +/** + * log_error + * @brief Print the error message to syslog or stderr + * + * @param string error message to print + */ +void +log_error(const char *string, ...) +{ + va_list vlist; + char msg[256]; + + va_start(vlist, string); + vsnprintf(msg, MSG_SIZE, string, vlist); + va_end(vlist); + + if (run_daemon) + syslog(LOG_ERR, "%s:%s", msg, strerror(errno)); + else + fprintf(stderr, "%s:%s\n", msg, strerror(errno)); + +} + +/** + * log_info + * @brief Print the message to syslog or stdout + * + * @param string message to print + */ +void +log_info(const char *string, ...) +{ + va_list vlist; + char msg[256]; + + va_start(vlist, string); + vsnprintf(msg, MSG_SIZE, string, vlist); + va_end(vlist); + + if (run_daemon) + syslog(LOG_INFO, "%s", msg); + else + printf("%s\n", msg); + +} + +/** + * cleanup + * @brief signal handler routine to cleanup while exiting + * + * @param signum signal number caught + */ +void cleanup(int signum) +{ + log_info("%s: exiting", prog); + servicelog_close(ipmi); + close(fifo); + exit(0); +} + +/** + * strprocess + * @brief function to convert a string to uppercase and remove whitespaces + * + * @param string to be converted + */ +static inline +char *strprocess(char *string) +{ + int i,j; + char *newstring; + + newstring = malloc(strlen(string)); + if (newstring == NULL) + return NULL; + for (i=0, j=0; i < strlen(string); i++) + if (!isspace(string[i])) + newstring[j++] = toupper(string[i]); + + newstring[j] = '\0'; + + return newstring; +} + +/** + * event_slog + * @brief function to log the event to servicelog db + * + * @param sinfo event structure + */ +void +event_slog(struct servicelog_info sinfo) +{ + uint64_t id; + char *sdesc, *refcode; + struct sl_event *event; + struct sl_data_bmc *bmc_info; + + if ((event = malloc(sizeof(struct sl_event))) == NULL) { + log_error("Can not allocate memory for event\n"); + return; + } + if ((bmc_info = malloc(sizeof(struct sl_data_bmc))) == NULL) { + log_error("Can not allocate memory for bmc\n"); + goto error1; + } + if ((sdesc = malloc(sizeof(char) * (strlen(sinfo.desc) + 1))) == NULL) { + log_error("Can not allocate memory for string desc\n"); + goto error2; + } + if ((refcode = malloc(sizeof(char) * 255)) == NULL) { + log_error("Can not allocate memory for string refcode\n"); + goto error3; + } + + memset(event, 0, sizeof(struct sl_event)); + memset(bmc_info, 0, sizeof(struct sl_data_bmc)); + memset(sdesc, 0, strlen(sinfo.desc)); + memset(refcode, 0, 255); + + strcpy(refcode, "#"); + strcat(refcode, strprocess(sinfo.type)); + + event->time_event = sinfo.time; + event->type = SL_TYPE_BMC; + event->severity = SL_SEV_EVENT; + event->description = sdesc; + strcpy(event->description,sinfo.desc); + event->refcode = refcode; + event->serviceable = sinfo.serviceable; + event->predictive = sinfo.predictive; + event->disposition = sinfo.disposition; + event->addl_data = bmc_info; + + bmc_info->sel_id = sinfo.sel_id; + bmc_info->sel_type = sinfo.sel_type; + bmc_info->generator = sinfo.generator; + bmc_info->version = sinfo.version; + bmc_info->sensor_type = sinfo.s_type; + bmc_info->sensor_number = sinfo.s_num; + bmc_info->event_class = sinfo.e_class; + bmc_info->event_type = sinfo.e_type; + bmc_info->direction = sinfo.e_dir; + + if (servicelog_event_log(ipmi, event, &id)) { + log_error("servicelog error: %s", servicelog_error(ipmi)); + goto error4; + } + servicelog_event_free(event); + return; + +error4: + free(refcode); +error3: + free(sdesc); +error2: + free(bmc_info); +error1: + free(event); + + return; +} + +/** + * get_ipmi_event + * @brief function reads from the ipmi event FIFO + */ +int +get_ipmi_event(void) +{ + int rc; + struct pollfd fd; + + memset(&fd, 0, sizeof(fd)); + fd.fd = fifo; + fd.events = POLLIN; + + do { + poll(&fd, 1, -1); + switch (fd.revents) { + case POLLHUP: + log_error("pollhup"); + break; + case POLLERR: + log_error("pollerr"); + break; + case POLLNVAL: + log_error("pollnval"); + break; + } + + rc = read(fifo, &sinfo, sizeof(sinfo)); + if (rc == 0) + return 0; + else if (rc < 0) { + log_error("reading from fifo"); + return 0; + } + event_slog(sinfo); + + } while (1); + + return 0; +} + +int +main(int argc, char **argv) +{ + int rc; + struct sigaction handler; + + if (argc > 1) { + if(!strcasecmp(argv[1], "nodaemon")) + run_daemon = 0; + else { + fprintf(stderr, "usage: %s [nodaemon]\n", argv[0]); + return -1; + } + } + + fifo = open(FIFO, O_RDONLY | O_NONBLOCK); + + if (fifo < 0) { + fprintf(stderr, "opening fifo %s", FIFO); + return -1; + } + + rc = servicelog_open(&ipmi, 0); + if (rc) { + fprintf(stderr, "Error opening servicelog: %s\n", strerror(rc)); + exit(2); + } + + if (run_daemon) + daemon(0,0); + + memset(&handler, 0, sizeof(handler)); + handler.sa_handler = cleanup; + if (sigaction(SIGTERM, &handler, NULL) < 0) + log_error("signal"); + + if (!run_daemon) + if (sigaction(SIGINT, &handler, NULL) < 0) + log_error("signal"); + + strcpy(prog, argv[0]); + + log_info("%s: started", prog); + get_ipmi_event(); + log_info("%s: exiting", prog); + servicelog_close(ipmi); + close(fifo); + return 0; +} -- 1.6.0.4 ------------------------------------------------------------------------------ SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada. The future of the web can't happen without you. Join us at MIX09 to help pave the way to the Next Web now. Learn more and register at http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/ _______________________________________________ Ipmitool-devel mailing list Ipmitool-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ipmitool-devel