X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fipmi.c;h=ad62299e3390bba91aedf9c5656f711643962e44;hb=4d370741101aeb037ae52f3529a4a0869e0dc08a;hp=2d6d2485a27c40e75a40e12646b696adf813e0c9;hpb=f5edd182195cb7a13fa32846ae869a8b8dcc1e3f;p=collectd.git diff --git a/src/ipmi.c b/src/ipmi.c index 2d6d2485..ad62299e 100644 --- a/src/ipmi.c +++ b/src/ipmi.c @@ -1,6 +1,8 @@ /** * collectd - src/ipmi.c - * Copyright (C) 2008 Florian octo Forster + * Copyright (C) 2008-2009 Florian octo Forster + * Copyright (C) 2008 Peter Holik + * Copyright (C) 2009 Bruno Prémont * * 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 @@ -16,16 +18,17 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: - * Florian octo Forster + * Florian octo Forster + * Peter Holik + * Bruno Prémont **/ #include "collectd.h" + #include "common.h" #include "plugin.h" #include "utils_ignorelist.h" -#include - #include #include #include @@ -41,6 +44,9 @@ typedef struct c_ipmi_sensor_list_s c_ipmi_sensor_list_t; struct c_ipmi_sensor_list_s { ipmi_sensor_id_t sensor_id; + char sensor_name[DATA_MAX_NAME_LEN]; + char sensor_type[DATA_MAX_NAME_LEN]; + int sensor_not_present; c_ipmi_sensor_list_t *next; }; @@ -50,26 +56,32 @@ struct c_ipmi_sensor_list_s static pthread_mutex_t sensor_list_lock = PTHREAD_MUTEX_INITIALIZER; static c_ipmi_sensor_list_t *sensor_list = NULL; +static int c_ipmi_init_in_progress = 0; static int c_ipmi_active = 0; static pthread_t thread_id = (pthread_t) 0; static const char *config_keys[] = { "Sensor", - "IgnoreSelected" + "IgnoreSelected", + "NotifySensorAdd", + "NotifySensorRemove", + "NotifySensorNotPresent" }; static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); static ignorelist_t *ignorelist = NULL; +static int c_ipmi_nofiy_add = 0; +static int c_ipmi_nofiy_remove = 0; +static int c_ipmi_nofiy_notpresent = 0; + /* * Misc private functions */ static void c_ipmi_error (const char *func, int status) { - char errbuf[4096]; - - memset (errbuf, 0, sizeof (errbuf)); + char errbuf[4096] = { 0 }; if (IPMI_IS_OS_ERR (status)) { @@ -98,44 +110,103 @@ static int sensor_list_remove (ipmi_sensor_t *sensor); static void sensor_read_handler (ipmi_sensor_t *sensor, int err, enum ipmi_value_present_e value_present, - unsigned int raw_value, + unsigned int __attribute__((unused)) raw_value, double value, - ipmi_states_t *states, + ipmi_states_t __attribute__((unused)) *states, void *user_data) { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - char sensor_name[IPMI_SENSOR_NAME_LEN]; - char *sensor_name_ptr; - int sensor_type; - const char *type; - - memset (sensor_name, 0, sizeof (sensor_name)); - ipmi_sensor_get_name (sensor, sensor_name, sizeof (sensor_name)); - sensor_name[sizeof (sensor_name) - 1] = 0; - - sensor_name_ptr = strstr (sensor_name, ")."); - if (sensor_name_ptr == NULL) - sensor_name_ptr = sensor_name; - else - sensor_name_ptr += 2; + c_ipmi_sensor_list_t *list_item = (c_ipmi_sensor_list_t *)user_data; if (err != 0) { - INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, " - "because it failed with status %#x.", - sensor_name_ptr, err); - sensor_list_remove (sensor); + if ((err & 0xff) == IPMI_NOT_PRESENT_CC) + { + if (list_item->sensor_not_present == 0) + { + list_item->sensor_not_present = 1; + + INFO ("ipmi plugin: sensor_read_handler: sensor %s " + "not present.", list_item->sensor_name); + + if (c_ipmi_nofiy_notpresent) + { + notification_t n = { NOTIF_WARNING, cdtime (), "", "", "ipmi", + "", "", "", NULL }; + + sstrncpy (n.host, hostname_g, sizeof (n.host)); + sstrncpy (n.type_instance, list_item->sensor_name, + sizeof (n.type_instance)); + sstrncpy (n.type, list_item->sensor_type, sizeof (n.type)); + ssnprintf (n.message, sizeof (n.message), + "sensor %s not present", list_item->sensor_name); + + plugin_dispatch_notification (&n); + } + } + } + else if (IPMI_IS_IPMI_ERR(err) && IPMI_GET_IPMI_ERR(err) == IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC) + { + INFO ("ipmi plugin: sensor_read_handler: Sensor %s not ready", + list_item->sensor_name); + } + else + { + if (IPMI_IS_IPMI_ERR(err)) + INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, " + "because it failed with IPMI error %#x.", + list_item->sensor_name, IPMI_GET_IPMI_ERR(err)); + else if (IPMI_IS_OS_ERR(err)) + INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, " + "because it failed with OS error %#x.", + list_item->sensor_name, IPMI_GET_OS_ERR(err)); + else if (IPMI_IS_RMCPP_ERR(err)) + INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, " + "because it failed with RMCPP error %#x.", + list_item->sensor_name, IPMI_GET_RMCPP_ERR(err)); + else if (IPMI_IS_SOL_ERR(err)) + INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, " + "because it failed with RMCPP error %#x.", + list_item->sensor_name, IPMI_GET_SOL_ERR(err)); + else + INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, " + "because it failed with error %#x. of class %#x", + list_item->sensor_name, err & 0xff, err & 0xffffff00); + sensor_list_remove (sensor); + } return; } + else if (list_item->sensor_not_present == 1) + { + list_item->sensor_not_present = 0; + + INFO ("ipmi plugin: sensor_read_handler: sensor %s present.", + list_item->sensor_name); + + if (c_ipmi_nofiy_notpresent) + { + notification_t n = { NOTIF_OKAY, cdtime (), "", "", "ipmi", + "", "", "", NULL }; + + sstrncpy (n.host, hostname_g, sizeof (n.host)); + sstrncpy (n.type_instance, list_item->sensor_name, + sizeof (n.type_instance)); + sstrncpy (n.type, list_item->sensor_type, sizeof (n.type)); + ssnprintf (n.message, sizeof (n.message), + "sensor %s present", list_item->sensor_name); + + plugin_dispatch_notification (&n); + } + } if (value_present != IPMI_BOTH_VALUES_PRESENT) { INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, " "because it provides %s. If you need this sensor, " "please file a bug report.", - sensor_name_ptr, + list_item->sensor_name, (value_present == IPMI_RAW_VALUE_PRESENT) ? "only the raw value" : "no value"); @@ -143,12 +214,76 @@ static void sensor_read_handler (ipmi_sensor_t *sensor, return; } - /* Both `ignorelist' and `plugin_instance' may be NULL. */ - if (ignorelist_match (ignorelist, sensor_name_ptr) != 0) + values[0].gauge = value; + + vl.values = values; + vl.values_len = 1; + + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "ipmi", sizeof (vl.plugin)); + sstrncpy (vl.type, list_item->sensor_type, sizeof (vl.type)); + sstrncpy (vl.type_instance, list_item->sensor_name, sizeof (vl.type_instance)); + + plugin_dispatch_values (&vl); +} /* void sensor_read_handler */ + +static int sensor_list_add (ipmi_sensor_t *sensor) +{ + ipmi_sensor_id_t sensor_id; + c_ipmi_sensor_list_t *list_item; + c_ipmi_sensor_list_t *list_prev; + + char buffer[DATA_MAX_NAME_LEN] = { 0 }; + const char *entity_id_string; + char sensor_name[DATA_MAX_NAME_LEN]; + char *sensor_name_ptr; + int sensor_type; + const char *type; + ipmi_entity_t *ent = ipmi_sensor_get_entity(sensor); + + sensor_id = ipmi_sensor_convert_to_id (sensor); + + ipmi_sensor_get_name (sensor, buffer, sizeof (buffer)); + buffer[sizeof (buffer) - 1] = 0; + + entity_id_string = ipmi_entity_get_entity_id_string (ent); + + if (entity_id_string == NULL) + sstrncpy (sensor_name, buffer, sizeof (sensor_name)); + else + ssnprintf (sensor_name, sizeof (sensor_name), + "%s %s", buffer, entity_id_string); + + sstrncpy (buffer, sensor_name, sizeof (buffer)); + sensor_name_ptr = strstr (buffer, ")."); + if (sensor_name_ptr != NULL) { - sensor_list_remove (sensor); - return; + /* If name is something like "foo (123).bar", + * change that to "bar (123)". + * Both, sensor_name_ptr and sensor_id_ptr point to memory within the + * `buffer' array, which holds a copy of the current `sensor_name'. */ + char *sensor_id_ptr; + + /* `sensor_name_ptr' points to ").bar". */ + sensor_name_ptr[1] = 0; + /* `buffer' holds "foo (123)\0bar\0". */ + sensor_name_ptr += 2; + /* `sensor_name_ptr' now points to "bar". */ + + sensor_id_ptr = strstr (buffer, "("); + if (sensor_id_ptr != NULL) + { + /* `sensor_id_ptr' now points to "(123)". */ + ssnprintf (sensor_name, sizeof (sensor_name), + "%s %s", sensor_name_ptr, sensor_id_ptr); + } + /* else: don't touch sensor_name. */ } + sensor_name_ptr = sensor_name; + + /* Both `ignorelist' and `plugin_instance' may be NULL. */ + if (ignorelist_match (ignorelist, sensor_name_ptr) != 0) + return (0); /* FIXME: Use rate unit or base unit to scale the value */ @@ -174,38 +309,16 @@ static void sensor_read_handler (ipmi_sensor_t *sensor, default: { const char *sensor_type_str; - + sensor_type_str = ipmi_sensor_get_sensor_type_string (sensor); - INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, " + INFO ("ipmi plugin: sensor_list_add: Ignore sensor %s, " "because I don't know how to handle its type (%#x, %s). " "If you need this sensor, please file a bug report.", sensor_name_ptr, sensor_type, sensor_type_str); - sensor_list_remove (sensor); - return; + return (-1); } } /* switch (sensor_type) */ - values[0].gauge = value; - - vl.values = values; - vl.values_len = 1; - vl.time = time (NULL); - - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, "ipmi", sizeof (vl.plugin)); - sstrncpy (vl.type_instance, sensor_name_ptr, sizeof (vl.type_instance)); - - plugin_dispatch_values (type, &vl); -} /* void sensor_read_handler */ - -static int sensor_list_add (ipmi_sensor_t *sensor) -{ - ipmi_sensor_id_t sensor_id; - c_ipmi_sensor_list_t *list_item; - c_ipmi_sensor_list_t *list_prev; - - sensor_id = ipmi_sensor_convert_to_id (sensor); - pthread_mutex_lock (&sensor_list_lock); list_prev = NULL; @@ -238,8 +351,27 @@ static int sensor_list_add (ipmi_sensor_t *sensor) else sensor_list = list_item; + sstrncpy (list_item->sensor_name, sensor_name_ptr, + sizeof (list_item->sensor_name)); + sstrncpy (list_item->sensor_type, type, sizeof (list_item->sensor_type)); + pthread_mutex_unlock (&sensor_list_lock); + if (c_ipmi_nofiy_add && (c_ipmi_init_in_progress == 0)) + { + notification_t n = { NOTIF_OKAY, cdtime (), "", "", "ipmi", + "", "", "", NULL }; + + sstrncpy (n.host, hostname_g, sizeof (n.host)); + sstrncpy (n.type_instance, list_item->sensor_name, + sizeof (n.type_instance)); + sstrncpy (n.type, list_item->sensor_type, sizeof (n.type)); + ssnprintf (n.message, sizeof (n.message), + "sensor %s added", list_item->sensor_name); + + plugin_dispatch_notification (&n); + } + return (0); } /* int sensor_list_add */ @@ -279,22 +411,35 @@ static int sensor_list_remove (ipmi_sensor_t *sensor) pthread_mutex_unlock (&sensor_list_lock); + if (c_ipmi_nofiy_remove && c_ipmi_active) + { + notification_t n = { NOTIF_WARNING, cdtime (), "", "", + "ipmi", "", "", "", NULL }; + + sstrncpy (n.host, hostname_g, sizeof (n.host)); + sstrncpy (n.type_instance, list_item->sensor_name, + sizeof (n.type_instance)); + sstrncpy (n.type, list_item->sensor_type, sizeof (n.type)); + ssnprintf (n.message, sizeof (n.message), + "sensor %s removed", list_item->sensor_name); + + plugin_dispatch_notification (&n); + } + free (list_item); return (0); } /* int sensor_list_remove */ static int sensor_list_read_all (void) { - c_ipmi_sensor_list_t *list_item; - pthread_mutex_lock (&sensor_list_lock); - for (list_item = sensor_list; + for (c_ipmi_sensor_list_t *list_item = sensor_list; list_item != NULL; list_item = list_item->next) { ipmi_sensor_id_get_reading (list_item->sensor_id, - sensor_read_handler, /* user data = */ NULL); + sensor_read_handler, /* user data = */ list_item); } /* for (list_item) */ pthread_mutex_unlock (&sensor_list_lock); @@ -329,9 +474,9 @@ static int sensor_list_remove_all (void) * Entity handlers */ static void entity_sensor_update_handler (enum ipmi_update_e op, - ipmi_entity_t *entity, + ipmi_entity_t __attribute__((unused)) *entity, ipmi_sensor_t *sensor, - void *user_data) + void __attribute__((unused)) *user_data) { /* TODO: Ignore sensors we cannot read */ @@ -350,9 +495,9 @@ static void entity_sensor_update_handler (enum ipmi_update_e op, * Domain handlers */ static void domain_entity_update_handler (enum ipmi_update_e op, - ipmi_domain_t *domain, + ipmi_domain_t __attribute__((unused)) *domain, ipmi_entity_t *entity, - void *user_data) + void __attribute__((unused)) *user_data) { int status; @@ -401,12 +546,11 @@ static void domain_connection_change_handler (ipmi_domain_t *domain, static int thread_init (os_handler_t **ret_os_handler) { os_handler_t *os_handler; - ipmi_open_option_t open_option[1]; ipmi_con_t *smi_connection = NULL; ipmi_domain_id_t domain_id; int status; - os_handler = ipmi_posix_thread_setup_os_handler (SIGUSR2); + os_handler = ipmi_posix_thread_setup_os_handler (SIGIO); if (os_handler == NULL) { ERROR ("ipmi plugin: ipmi_posix_thread_setup_os_handler failed."); @@ -425,9 +569,12 @@ static int thread_init (os_handler_t **ret_os_handler) return (-1); } - memset (open_option, 0, sizeof (open_option)); - open_option[0].option = IPMI_OPEN_OPTION_ALL; - open_option[0].ival = 1; + ipmi_open_option_t open_option[1] = { + [0] = { + .option = IPMI_OPEN_OPTION_ALL, + { .ival = 1 } + } + }; status = ipmi_open_domain ("mydomain", &smi_connection, /* num_con = */ 1, domain_connection_change_handler, /* user data = */ NULL, @@ -444,7 +591,7 @@ static int thread_init (os_handler_t **ret_os_handler) return (0); } /* int thread_init */ -static void *thread_main (void *user_data) +static void *thread_main (void __attribute__((unused)) *user_data) { int status; os_handler_t *os_handler = NULL; @@ -481,12 +628,25 @@ static int c_ipmi_config (const char *key, const char *value) else if (strcasecmp ("IgnoreSelected", key) == 0) { int invert = 1; - if ((strcasecmp ("True", value) == 0) - || (strcasecmp ("Yes", value) == 0) - || (strcasecmp ("On", value) == 0)) + if (IS_TRUE (value)) invert = 0; ignorelist_set_invert (ignorelist, invert); } + else if (strcasecmp ("NotifySensorAdd", key) == 0) + { + if (IS_TRUE (value)) + c_ipmi_nofiy_add = 1; + } + else if (strcasecmp ("NotifySensorRemove", key) == 0) + { + if (IS_TRUE (value)) + c_ipmi_nofiy_remove = 1; + } + else if (strcasecmp ("NotifySensorNotPresent", key) == 0) + { + if (IS_TRUE (value)) + c_ipmi_nofiy_notpresent = 1; + } else { return (-1); @@ -499,9 +659,13 @@ static int c_ipmi_init (void) { int status; + /* Don't send `ADD' notifications during startup (~ 1 minute) */ + time_t iv = CDTIME_T_TO_TIME_T (plugin_get_interval ()); + c_ipmi_init_in_progress = 1 + (60 / iv); + c_ipmi_active = 1; - status = pthread_create (&thread_id, /* attr = */ NULL, thread_main, + status = plugin_thread_create (&thread_id, /* attr = */ NULL, thread_main, /* user data = */ NULL); if (status != 0) { @@ -523,7 +687,12 @@ static int c_ipmi_read (void) } sensor_list_read_all (); - + + if (c_ipmi_init_in_progress > 0) + c_ipmi_init_in_progress--; + else + c_ipmi_init_in_progress = 0; + return (0); } /* int c_ipmi_read */