[PATCH] Log IPMI events to a FIFO

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 enabled by default. Servicelog
support can be disabled by, running "configure with --disable-servicelog".
Similarly servicelog runtime support can be disabled by passing the command
line parameter "noservicelog" to ipmievd.

Signed-off-by: M. Mohan Kumar <mo...@in.ibm.com>
---
 configure.in                       |   20 +++++
 include/ipmitool/ipmi_servicelog.h |   44 +++++++++++
 lib/ipmi_sel.c                     |   23 ++++++
 src/ipmievd.c                      |  149 +++++++++++++++++++++++++++++++++---
 4 files changed, 226 insertions(+), 10 deletions(-)
 create mode 100644 include/ipmitool/ipmi_servicelog.h

diff --git a/configure.in b/configure.in
index 4096e39..e8d89e5 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=yes]])],
+       [], [enable_servicelog=yes])
+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
@@ -526,5 +545,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..0a23416
--- /dev/null
+++ b/include/ipmitool/ipmi_servicelog.h
@@ -0,0 +1,44 @@
+#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 REFCODE_SIZE 50
+#define MSG_SIZE 256
+
+/* structure compatible with servicelog structures */
+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;
+};
+
+#ifdef ENABLE_SERVICELOG
+void servicelog_log(struct servicelog_info sinfo, const char *string);
+#else
+inline void servicelog_log(struct servicelog_info sinfo, const char *string)
+{
+}
+#endif
+
+#endif /* IPMI_SERVICELOG_H */
diff --git a/lib/ipmi_sel.c b/lib/ipmi_sel.c
index fa081d5..2028360 100644
--- a/lib/ipmi_sel.c
+++ b/lib/ipmi_sel.c
@@ -661,6 +661,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..f9d8d90 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 = 1;
+#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,18 @@ ipmi_event_intf_load(char * name)
        return NULL;
 }
 
+
+#ifdef ENABLE_SERVICELOG
+void servicelog_log(struct servicelog_info sinfo, const char *string)
+{
+       if (servicelog) {
+               strcpy(sinfo.desc, string);
+               if (write(fifo, &sinfo, sizeof(sinfo)) < 0)
+                       lperror(LOG_ERR, "writing fifo");
+       }
+}
+#endif
+
 static void
 log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt)
 {
@@ -192,18 +213,29 @@ 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 servicelog_info sinfo;
 
        if (evt == NULL)
                return;
 
+#ifdef ENABLE_SERVICELOG
+       memset(&sinfo, 0, sizeof(sinfo));
+#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);
+               servicelog_log(sinfo, 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);
+               servicelog_log(sinfo, string);
                return;
        }
 
@@ -215,16 +247,35 @@ 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
+       sinfo.time = evt->sel_type.standard_type.timestamp;
+       sinfo.sel_id = evt->record_id;
+       sinfo.sel_type = evt->record_type;
+       sinfo.generator = evt->sel_type.standard_type.gen_id;
+       sinfo.version = evt->sel_type.standard_type.evm_rev;
+       strcpy(sinfo.type, type);
+       sinfo.s_type = evt->sel_type.standard_type.sensor_type;
+       sinfo.s_num = evt->sel_type.standard_type.sensor_num;
+       sinfo.e_type = evt->sel_type.standard_type.event_type;
+       sinfo.e_class = 
ipmi_sel_get_sensor_event_class_offset(evt->sel_type.standard_type.sensor_type,
+                                              
evt->sel_type.standard_type.event_data[0]);
+       sinfo.e_dir = evt->sel_type.standard_type.event_dir;
+#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(sinfo, 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(sinfo, string);
                }
                return;
        }
@@ -248,7 +299,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 +312,21 @@ 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));
+                       sinfo.serviceable = 1;
+                       sinfo.predictive = 1;
+                       sinfo.disposition = SL_DISP_RECOVERABLE;
+                       lprintf(LOG_NOTICE, string);
+                       servicelog_log(sinfo, 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(sinfo, 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 +335,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(sinfo, 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(sinfo, 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(sinfo, 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(sinfo, string);
                break;
        }
 
@@ -613,9 +679,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 +767,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 +810,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.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

Reply via email to