Add support to log the IPMI events to a FIFO. ipmilog daemon (part of servicelog utility) reads IPMI events from this FIFO and logs them to the servicelog utility. Servicelog support is disabled by default. Servicelog support can be enabled by, running "configure with --enable-servicelog". Similarly servicelog runtime support can be enabled by passing the command line parameter "servicelog" to ipmievd.
Changes from v2 to v3: v2 enabled servicelog by default. In v3 servicelog support is not enabled by default. Signed-off-by: M. Mohan Kumar <mo...@in.ibm.com> --- configure.in | 20 +++++ include/ipmitool/ipmi_servicelog.h | 31 ++++++++ lib/ipmi_sel.c | 23 ++++++ src/ipmievd.c | 139 +++++++++++++++++++++++++++++++++--- 4 files changed, 203 insertions(+), 10 deletions(-) create mode 100644 include/ipmitool/ipmi_servicelog.h diff --git a/configure.in b/configure.in index 5855808..ecec4ab 100644 --- a/configure.in +++ b/configure.in @@ -74,6 +74,7 @@ solaris*) enable_intf_lipmi=no enable_ipmishell=no enable_all_options=no + enable_servicelog=no ;; *cygwin*) # disable the linux and solaris-specific interfaces @@ -82,6 +83,7 @@ solaris*) enable_intf_lipmi=no enable_intf_bmc=no enable_ipmishell=no + enable_servicelog=no ;; *darwin*) # disable the linux and solaris-specific interfaces @@ -90,17 +92,20 @@ solaris*) enable_intf_lipmi=no enable_intf_bmc=no enable_ipmishell=no + enable_servicelog=no ;; *freebsd*) enable_intf_imb=no enable_intf_lipmi=no enable_intf_bmc=no + enable_servicelog=no ;; *netbsd*) enable_intf_imb=no enable_intf_lipmi=no enable_intf_bmc=no enable_intf_open=no + enable_servicelog=no ;; esac @@ -454,6 +459,20 @@ if test "x$enable_intf_bmc" = "xyes"; then IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB bmc/libintf_bmc.la" fi +dnl enable Servicelog +AC_ARG_ENABLE([servicelog], + [AC_HELP_STRING([--enable-servicelog], + [enable logging IPMI events to servicelog +[default=no]])], + [], [enable_servicelog=no]) +if test "x$enable_servicelog" = "xstatic" || test "x$enable_servicelog" = "xplugin"; then + enable_servicelog=yes +fi +if test "x$enable_servicelog" = "xyes"; then + AC_DEFINE(ENABLE_SERVICELOG, [1], [Define to 1 to enable logging IPMI +events to servicelog.]) +fi + AC_SUBST(IPMITOOL_INTF_LIB) dnl check for readline library to enable ipmi shell @@ -550,5 +569,6 @@ AC_MSG_RESULT([ lipmi : $enable_intf_lipmi]) AC_MSG_RESULT([]) AC_MSG_RESULT([Extra tools]) AC_MSG_RESULT([ ipmievd : yes]) +AC_MSG_RESULT([ servicelog : $enable_servicelog]) AC_MSG_RESULT([]) diff --git a/include/ipmitool/ipmi_servicelog.h b/include/ipmitool/ipmi_servicelog.h new file mode 100644 index 0000000..fe66596 --- /dev/null +++ b/include/ipmitool/ipmi_servicelog.h @@ -0,0 +1,31 @@ +#ifndef IPMI_SERVICELOG_H +#define IPMI_SERVICELOG_H + +#define FIFO "/var/log/sfifo" + +/* Taken from servicelog */ +/* defines for sl_event.disposition */ +#define SL_DISP_RECOVERABLE 0 +#define SL_DISP_UNRECOVERABLE 1 +#define SL_DISP_BYPASSED 2 /* unrecoverable, bypassed with degraded + performance */ + +#define MSG_SIZE 256 +#define REFCODE_SIZE 50 + +struct sel_event_record_sl { + struct sel_event_record sl; + char desc[MSG_SIZE]; + char type[REFCODE_SIZE]; + uint8_t e_class; +}; + +#ifdef ENABLE_SERVICELOG +void servicelog_log(struct sel_event_record_sl *event, const char *string); +#else +inline void servicelog_log(struct sel_event_record_sl *event, const char *string) +{ +} +#endif + +#endif /* IPMI_SERVICELOG_H */ diff --git a/lib/ipmi_sel.c b/lib/ipmi_sel.c index 516c85b..bfd3dc5 100644 --- a/lib/ipmi_sel.c +++ b/lib/ipmi_sel.c @@ -662,6 +662,29 @@ ipmi_sel_get_sensor_type_offset(uint8_t code, uint8_t offset) return ipmi_sel_get_sensor_type(code); } +#ifdef ENABLE_SERVICELOG +uint8_t +ipmi_sel_get_sensor_event_class(uint8_t code) +{ + struct ipmi_event_sensor_types *st; + for (st = sensor_specific_types; st->type != NULL; st++) + if (st->code == code) + return st->class; + return -1; +} + +uint8_t +ipmi_sel_get_sensor_event_class_offset(uint8_t code, uint8_t offset) +{ + struct ipmi_event_sensor_types *st; + for (st = sensor_specific_types; st->type != NULL; st++) + if (st->code == code && st->offset == (offset&0xf)) + return st->class; + + return ipmi_sel_get_sensor_event_class(code); +} +#endif + static int ipmi_sel_get_info(struct ipmi_intf * intf) { diff --git a/src/ipmievd.c b/src/ipmievd.c index 5d17696..c7303a9 100644 --- a/src/ipmievd.c +++ b/src/ipmievd.c @@ -74,6 +74,7 @@ #include <ipmitool/ipmi_sdr.h> #include <ipmitool/ipmi_strings.h> #include <ipmitool/ipmi_main.h> +#include <ipmitool/ipmi_servicelog.h> #define DEFAULT_PIDFILE _PATH_VARRUN "ipmievd.pid" char pidfile[64]; @@ -85,6 +86,10 @@ uint16_t selwatch_count = 0; /* number of entries in the SEL */ uint16_t selwatch_lastid = 0; /* current last entry in the SEL */ int selwatch_timeout = 10; /* default to 10 seconds */ +#ifdef ENABLE_SERVICELOG +int fifo, servicelog = 0; +#endif + /* event interface definition */ struct ipmi_event_intf { char name[16]; @@ -143,6 +148,7 @@ struct ipmi_event_intf * ipmi_event_intf_table[] = { /*************************************************************************/ + static void ipmievd_usage(void) { @@ -150,6 +156,9 @@ ipmievd_usage(void) lprintf(LOG_NOTICE, "\ttimeout=# Time between checks for SEL polling method [default=10]"); lprintf(LOG_NOTICE, "\tdaemon Become a daemon [default]"); lprintf(LOG_NOTICE, "\tnodaemon Do NOT become a daemon"); +#ifdef ENABLE_SERVICELOG + lprintf(LOG_NOTICE, "\tservicelog Log the events to servicelog"); +#endif } /* ipmi_intf_load - Load an event interface from the table above @@ -183,6 +192,17 @@ ipmi_event_intf_load(char * name) return NULL; } +#ifdef ENABLE_SERVICELOG +void servicelog_log(struct sel_event_record_sl *event, const char *string) +{ + if (servicelog) { + strcpy(event->desc, string); + if (write(fifo, event, sizeof(*event)) < 0) + lperror(LOG_ERR, "writing fifo"); + } +} +#endif + static void log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) { @@ -192,18 +212,32 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) struct ipmi_intf * intf = eintf->intf; float trigger_reading = 0.0; float threshold_reading = 0.0; + static char string[255]; + struct sel_event_record_sl sl_event; if (evt == NULL) return; +#ifdef ENABLE_SERVICELOG + memset(&sl_event, 0, sizeof(sl_event)); + memcpy(&sl_event.sl, evt, sizeof(*evt)); +#endif + memset(string, 0, sizeof(string)); + if (evt->record_type == 0xf0) { - lprintf(LOG_ALERT, "%sLinux kernel panic: %.11s", + sprintf(string, "%sLinux kernel panic: %.11s", eintf->prefix, (char *) evt + 5); + lprintf(LOG_ALERT, string); + strcpy(sl_event.type, "PANIC"); + servicelog_log(&sl_event, string); return; } else if (evt->record_type >= 0xc0) { - lprintf(LOG_NOTICE, "%sIPMI Event OEM Record %02x", + sprintf(string, "%sIPMI Event OEM Record %02x", eintf->prefix, evt->record_type); + lprintf(LOG_NOTICE, string); + strcpy(sl_event.type, "OEMEvent"); + servicelog_log(&sl_event, string); return; } @@ -215,16 +249,26 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) sdr = ipmi_sdr_find_sdr_bynumtype(intf, evt->sel_type.standard_type.sensor_num, evt->sel_type.standard_type.sensor_type); +#ifdef ENABLE_SERVICELOG + strcpy(sl_event.type, type); + sl_event.e_class = ipmi_sel_get_sensor_event_class_offset(evt->sel_type.standard_type.sensor_type, + evt->sel_type.standard_type.event_data[0]); +#endif + if (sdr == NULL) { /* could not find matching SDR record */ if (desc) { - lprintf(LOG_NOTICE, "%s%s sensor - %s", + sprintf(string,"%s%s sensor - %s", eintf->prefix, type, desc); + lprintf(LOG_NOTICE, string); + servicelog_log(&sl_event, string); free(desc); } else { - lprintf(LOG_NOTICE, "%s%s sensor %02x", + sprintf(string, "%s%s sensor %02x", eintf->prefix, type, evt->sel_type.standard_type.sensor_num); + lprintf(LOG_NOTICE, string); + servicelog_log(&sl_event, string); } return; } @@ -248,7 +292,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) sdr->record.full, evt->sel_type.standard_type.event_data[2]); } - lprintf(LOG_NOTICE, "%s%s sensor %s %s (Reading %.*f %s Threshold %.*f %s)", + sprintf(string, "%s%s sensor %s %s (Reading %.*f %s Threshold %.*f %s)", eintf->prefix, type, sdr->record.full->id_string, @@ -261,14 +305,18 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) ipmi_sdr_get_unit_string(sdr->record.full->unit.modifier, sdr->record.full->unit.type.base, sdr->record.full->unit.type.modifier)); + lprintf(LOG_NOTICE, string); + servicelog_log(&sl_event, string); } else if ((evt->sel_type.standard_type.event_type >= 0x2 && evt->sel_type.standard_type.event_type <= 0xc) || (evt->sel_type.standard_type.event_type == 0x6f)) { /* * Discrete Event */ - lprintf(LOG_NOTICE, "%s%s sensor %s %s", + sprintf(string, "%s%s sensor %s %s", eintf->prefix, type, sdr->record.full->id_string, desc ? : ""); + lprintf(LOG_NOTICE, string); + servicelog_log(&sl_event, string); if (((evt->sel_type.standard_type.event_data[0] >> 6) & 3) == 1) { /* previous state and/or severity in event data byte 2 */ } @@ -277,29 +325,37 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) /* * OEM Event */ - lprintf(LOG_NOTICE, "%s%s sensor %s %s", + sprintf("%s%s sensor %s %s", eintf->prefix, type, sdr->record.full->id_string, desc ? : ""); + lprintf(LOG_NOTICE, string); + servicelog_log(&sl_event, string); } break; case SDR_RECORD_TYPE_COMPACT_SENSOR: if (evt->sel_type.standard_type.event_type == 0x6f) { - lprintf(LOG_NOTICE, "%s%s sensor %s - %s %s", + sprintf(string, "%s%s sensor %s - %s %s", eintf->prefix, type, sdr->record.compact->id_string, desc ? : "", evt->sel_type.standard_type.event_dir ? "Deasserted" : "Asserted"); + lprintf(LOG_NOTICE, string); + servicelog_log(&sl_event, string); } else { - lprintf(LOG_NOTICE, "%s%s sensor %s - %s", + sprintf("%s%s sensor %s - %s", eintf->prefix, type, sdr->record.compact->id_string, desc ? : ""); + lprintf(LOG_NOTICE, string); + servicelog_log(&sl_event, string); } break; default: - lprintf(LOG_NOTICE, "%s%s sensor - %s", + sprintf("%s%s sensor - %s", eintf->prefix, type, evt->sel_type.standard_type.sensor_num, desc ? : ""); + lprintf(LOG_NOTICE, string); + servicelog_log(&sl_event, string); break; } @@ -613,9 +669,56 @@ ipmievd_cleanup(int signal) (void)unlink(pidfile); } +#ifdef ENABLE_SERVICELOG + if (servicelog) + close(fifo); +#endif + exit(EXIT_SUCCESS); } +#ifdef ENABLE_SERVICELOG +int +create_servicelog_fifo(void) +{ + char buff[255]; + int rc = 0; + + fifo = open(FIFO, O_RDWR); + + if (fifo < 0) { + switch (errno) { + case EPERM: + lperror(LOG_ERR, "Could not open servicelog fifo, permission denied"); + servicelog = 0; + rc = -1; + break; + case ENOENT: + if (mkfifo(FIFO, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) < 0) { + lperror(LOG_ERR, "Could not create servicelog fifo"); + servicelog = 0; + rc = -1; + } + fifo = open(FIFO, O_RDWR); + if (fifo < 0) { + lperror(LOG_ERR, "Could not open servicelog fifo"); + servicelog = 0; + rc = -1; + } + break; + default: + lperror(LOG_ERR, "error opening servicelog fifo"); + servicelog = 0; + rc = -1; + break; + } + } + + lprintf(LOG_INFO, "servicelog is %d\n", servicelog); + return rc; +} +#endif + int ipmievd_main(struct ipmi_event_intf * eintf, int argc, char ** argv) { @@ -654,6 +757,18 @@ ipmievd_main(struct ipmi_event_intf * eintf, int argc, char ** argv) strncpy(pidfile, argv[i]+8, __min(strlen((const char *)(argv[i]+8)), 63)); } +#ifdef ENABLE_SERVICELOG + else if (strncasecmp(argv[i], "servicelog", 10) == 0) + servicelog = 1; + else if (strncasecmp(argv[i], "servicelog=", 11) == 0) { + if (strncasecmp(argv[i]+11, "on", 2) == 0 || + strncasecmp(argv[i]+11, "yes", 3) == 0) + servicelog = 1; + else if (strncasecmp(argv[i]+11, "off", 3) == 0 || + strncasecmp(argv[i]+11, "no", 2) == 0) + servicelog = 0; + } +#endif } /* @@ -685,6 +800,10 @@ ipmievd_main(struct ipmi_event_intf * eintf, int argc, char ** argv) fclose(fp); } } +#ifdef ENABLE_SERVICELOG + if (servicelog) + create_servicelog_fifo(); +#endif /* register signal handler for cleanup */ act.sa_handler = ipmievd_cleanup; -- 1.6.0.6 ------------------------------------------------------------------------------ This SF.net email is sponsored by: SourcForge Community SourceForge wants to tell your story. http://p.sf.net/sfu/sf-spreadtheword _______________________________________________ Ipmitool-devel mailing list Ipmitool-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ipmitool-devel