freeipmi.plugin; fixes #1799; fixes #1794; fixes #1309; fixes #1729
Costa Tsaousis (ktsaou) committed
Mar 3, 2017 at 01:11 UTC
f266bab3d154e9e082403b89ea60d0fe35fe4096
5 files changed
+1638
-4
CMakeLists.txt
+27
-1
@@ -33,6 +33,9 @@ set(NETDATA_SOURCE_FILES
33
src/global_statistics.h
34
src/health.c
35
src/health.h
36
+ src/health_config.c
37
+ src/health_json.c
38
+ src/health_log.c
39
src/inlined.h
40
src/ipc.c
41
src/ipc.h
@@ -103,6 +106,19 @@ set(NETDATA_SOURCE_FILES
106
src/rrd.h
107
src/rrd2json.c
108
src/rrd2json.h
109
+ src/rrd2json_api_old.c
110
+ src/rrd2json_api_old.h
111
+ src/rrdcalc.c
112
+ src/rrdcalctemplate.c
113
+ src/rrddim.c
114
+ src/rrddimvar.c
115
+ src/rrdfamily.c
116
+ src/rrdhost.c
117
+ src/rrdpush.c
118
+ src/rrdpush.h
119
+ src/rrdset.c
120
+ src/rrdsetvar.c
121
+ src/rrdvar.c
122
src/simple_pattern.c
123
src/simple_pattern.h
124
src/socket.c src/socket.h
@@ -116,6 +132,10 @@ set(NETDATA_SOURCE_FILES
132
src/unit_test.h
133
src/url.c
134
src/url.h
135
+ src/web_api_old.c
136
+ src/web_api_old.h
137
+ src/web_api_v1.c
138
+ src/web_api_v1.h
139
src/web_buffer.c
140
src/web_buffer.h
141
src/web_buffer_svg.c
@@ -124,7 +144,7 @@ set(NETDATA_SOURCE_FILES
144
src/web_client.h
145
src/web_server.c
146
src/web_server.h
127
- src/rrdhost.c src/rrdfamily.c src/rrdset.c src/rrddim.c src/health_log.c src/health_config.c src/health_json.c src/rrdcalc.c src/rrdcalctemplate.c src/rrdvar.c src/rrddimvar.c src/rrdsetvar.c src/rrdpush.c src/rrdpush.h src/web_api_old.c src/web_api_old.h src/web_api_v1.c src/web_api_v1.h src/rrd2json_api_old.c src/rrd2json_api_old.h)
147
+ )
148
149
set(APPS_PLUGIN_SOURCE_FILES
150
src/appconfig.c
@@ -142,6 +162,9 @@ set(APPS_PLUGIN_SOURCE_FILES
162
src/web_buffer.h
163
config.h)
164
165
+set(FREEIPMI_PLUGIN_SOURCE_FILES
166
+ src/plugin_freeipmi.c)
167
+
168
include_directories(AFTER .)
169
170
add_definitions(-DHAVE_CONFIG_H -DCACHE_DIR="/var/cache/netdata" -DCONFIG_DIR="/etc/netdata" -DLOG_DIR="/var/log/netdata" -DPLUGINS_DIR="/usr/libexec/netdata" -DWEB_DIR="/usr/share/netdata" -DVARLIB_DIR="/var/lib/netdata")
@@ -151,3 +174,6 @@ target_link_libraries (netdata m z uuid ${CMAKE_THREAD_LIBS_INIT})
174
175
add_executable(apps.plugin ${APPS_PLUGIN_SOURCE_FILES} src/inlined.h)
176
target_link_libraries (apps.plugin m ${CMAKE_THREAD_LIBS_INIT})
177
+
178
+add_executable(freeipmi.plugin ${FREEIPMI_PLUGIN_SOURCE_FILES})
179
+target_link_libraries (freeipmi.plugin ipmimonitoring)
configure.ac
+24
-1
@@ -77,6 +77,12 @@ AC_ARG_ENABLE(
77
,
78
[enable_plugin_nfacct="no"]
79
)
80
+AC_ARG_ENABLE(
81
+ [plugin-freeipmi],
82
+ [AS_HELP_STRING([--enable-plugin-freeipmi], [freeipmi plugin, requires root])],
83
+ ,
84
+ [enable_plugin_freeipmi="no"]
85
+)
86
AC_ARG_ENABLE(
87
[pedantic],
88
[AS_HELP_STRING([--enable-pedantic], [enable pedantic compiler warnings])],
@@ -191,6 +197,19 @@ AC_DEFINE([NETDATA_WITH_UUID], [1], [uuid settings])
197
OPTIONAL_UUID_CLFAGS="${UUID_CFLAGS}"
198
OPTIONAL_UUID_LIBS="${UUID_LIBS}"
199
200
+if test "${enable_plugin_freeipmi}" = "yes"; then
201
+ PKG_CHECK_MODULES(
202
+ [IPMIMONITORING],
203
+ [libipmimonitoring],
204
+ )
205
+ test -z "${IPMIMONITORING_LIBS}" && AC_MSG_ERROR([ipmimonitoring required but not found. Try installing 'libipmimonitoring-dev' or 'libipmimonitoring-devel'])
206
+ freeipmi=yes
207
+ AC_DEFINE([HAVE_FREEIPMI], [1], [ipmimonitoring usability])
208
+ OPTIONAL_IPMIMONITORING_CLFAGS="${IPMIMONITORING_CFLAGS}"
209
+ OPTIONAL_IPMIMONITORING_LIBS="${IPMIMONITORING_LIBS}"
210
+fi
211
+AM_CONDITIONAL([FREEIPMI], [test x$freeipmi = xyes])
212
+
213
if test "${enable_plugin_nfacct}" = "yes"; then
214
PKG_CHECK_MODULES(
215
[NFACCT],
@@ -206,6 +225,7 @@ if test "${enable_plugin_nfacct}" = "yes"; then
225
OPTIONAL_NFACCT_CLFAGS="${NFACCT_CFLAGS} ${LIBMNL_CFLAGS}"
226
OPTIONAL_NFACCT_LIBS="${NFACCT_LIBS} ${LIBMNL_LIBS}"
227
fi
228
+
229
if test "${with_zlib}" = "yes"; then
230
PKG_CHECK_MODULES(
231
[ZLIB],
@@ -216,6 +236,7 @@ if test "${with_zlib}" = "yes"; then
236
OPTIONAL_ZLIB_CLFAGS="${ZLIB_CFLAGS}"
237
OPTIONAL_ZLIB_LIBS="${ZLIB_LIBS}"
238
fi
239
+
240
if test "${with_math}" = "yes"; then
241
test -z "${MATH_LIBS}" && AC_MSG_ERROR([math required but not found])
242
AC_DEFINE([STORAGE_WITH_MATH], [1], [math settings])
@@ -258,6 +279,8 @@ AC_SUBST([OPTIONAL_ZLIB_LIBS])
279
AC_SUBST([OPTIONAL_UUID_CLFAGS])
280
AC_SUBST([OPTIONAL_UUID_LIBS])
281
AC_SUBST([OPTIONAL_CAP_LIBS])
282
+AC_SUBST([OPTIONAL_IPMIMONITORING_CFLAGS])
283
+AC_SUBST([OPTIONAL_IPMIMONITORING_LIBS])
284
285
AC_CONFIG_FILES([
286
Makefile
@@ -275,4 +298,4 @@ AC_CONFIG_FILES([
298
AC_OUTPUT
299
300
test "${with_math}" != "yes" && AC_MSG_WARN([You are building without math. math allows accurate calculations. It should be enabled.]) || :
278
-test "${with_zlib}" != "yes" && AC_MSG_WARN([You are building without zlib. zlib allows netdata to trasnfer a lot less data with web clients. It should be enabled.]) || :
301
+test "${with_zlib}" != "yes" && AC_MSG_WARN([You are building without zlib. zlib allows netdata to transfer a lot less data with web clients. It should be enabled.]) || :
netdata-installer.sh
+21
-1
@@ -73,6 +73,7 @@ DONOTSTART=0
73
DONOTWAIT=0
74
NETDATA_PREFIX=
75
LIBS_ARE_HERE=0
76
+NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS-}"
77
78
usage() {
79
netdata_banner "installer command line options"
@@ -97,6 +98,10 @@ Valid <installer options> are:
98
Do not wait for the user to press ENTER.
99
Start immediately building it.
100
101
+ --enable-plugin-freeipmi
102
+
103
+ Enable the FreeIPMI plugin.
104
+
105
--zlib-is-really-here
106
--libs-are-really-here
107
@@ -184,6 +189,10 @@ do
189
then
190
DONOTWAIT=1
191
shift 1
192
+ elif [ "$1" = "--enable-plugin-freeipmi" ]
193
+ then
194
+ NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS} --enable-plugin-freeipmi"
195
+ shift 1
196
elif [ "$1" = "--help" -o "$1" = "-h" ]
197
then
198
usage
@@ -402,7 +411,10 @@ run ./configure \
411
--prefix="${NETDATA_PREFIX}/usr" \
412
--sysconfdir="${NETDATA_PREFIX}/etc" \
413
--localstatedir="${NETDATA_PREFIX}/var" \
405
- --with-zlib --with-math --with-user=netdata \
414
+ --with-zlib \
415
+ --with-math \
416
+ --with-user=netdata \
417
+ ${NETDATA_CONFIGURE_OPTIONS} \
418
CFLAGS="${CFLAGS}" || exit 1
419
420
# remove the build_error hook
@@ -734,6 +746,13 @@ if [ ${UID} -eq 0 ]
746
run chown root "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
747
run chmod 4755 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin"
748
fi
749
+
750
+ if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/freeipmi.plugin" ]
751
+ then
752
+ run chown root "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/freeipmi.plugin"
753
+ run chmod 4755 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/freeipmi.plugin"
754
+ fi
755
+
756
else
757
run chown "${NETDATA_USER}:${NETDATA_USER}" "${NETDATA_LOG_DIR}"
758
run chown -R "${NETDATA_USER}:${NETDATA_USER}" "${NETDATA_PREFIX}/usr/libexec/netdata"
@@ -1243,6 +1262,7 @@ force=0
1262
1263
export PATH="\${PATH}:${PATH}"
1264
export CFLAGS="${CFLAGS}"
1265
+export NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS}"
1266
1267
INSTALL_UID="${UID}"
1268
if [ "\${INSTALL_UID}" != "\${UID}" ]
src/Makefile.am
+14
-1
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
12
-DRUN_DIR="\"$(localstatedir)/run/netdata\"" \
13
-DWEB_DIR="\"$(webdir)\"" \
14
$(NULL)
15
+
16
AM_CFLAGS = \
17
$(OPTIONAL_MATH_CFLAGS) \
18
$(OPTIONAL_NFACCT_CLFAGS) \
@@ -24,8 +25,9 @@ dist_cache_DATA = .keep
25
dist_varlib_DATA = .keep
26
dist_registry_DATA = .keep
27
dist_log_DATA = .keep
28
+plugins_PROGRAMS =
29
if !MACOS
28
-plugins_PROGRAMS = apps.plugin
30
+plugins_PROGRAMS += apps.plugin
31
endif
32
33
netdata_SOURCES = \
@@ -159,3 +161,14 @@ apps_plugin_LDADD = \
161
$(OPTIONAL_CAP_LIBS) \
162
$(NULL)
163
164
+if FREEIPMI
165
+plugins_PROGRAMS += freeipmi.plugin
166
+
167
+freeipmi_plugin_SOURCES = \
168
+ freeipmi_plugin.c \
169
+ $(NULL)
170
+
171
+freeipmi_plugin_LDADD = \
172
+ $(OPTIONAL_IPMIMONITORING_LIBS) \
173
+ $(NULL)
174
+endif
src/freeipmi_plugin.c
new
+1552
@@ -0,0 +1,1552 @@
1
+/*****************************************************************************\
2
+ * $Id: ipmimonitoring-sensors.c,v 1.51 2016/11/02 23:46:24 chu11 Exp $
3
+ * $Id: ipmimonitoring-sel.c,v 1.51 2016/11/02 23:46:24 chu11 Exp $
4
+ *****************************************************************************
5
+ * Copyright (C) 2007-2015 Lawrence Livermore National Security, LLC.
6
+ * Copyright (C) 2006-2007 The Regents of the University of California.
7
+ * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
8
+ * Written by Albert Chu <chu11@llnl.gov>
9
+ * UCRL-CODE-222073
10
+ *
11
+ * This file is part of Ipmimonitoring, an IPMI sensor monitoring
12
+ * library. For details, see http://www.llnl.gov/linux/.
13
+ *
14
+ * Ipmimonitoring is free software; you can redistribute it and/or modify
15
+ * it under the terms of the GNU General Public License as published by the
16
+ * Free Software Foundation; either version 3 of the License, or (at your
17
+ * option) any later version.
18
+ *
19
+ * Ipmimonitoring is distributed in the hope that it will be useful, but
20
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22
+ * for more details.
23
+ *
24
+ * You should have received a copy of the GNU General Public License along
25
+ * with Ipmimonitoring. If not, see <http://www.gnu.org/licenses/>.
26
+\*****************************************************************************/
27
+
28
+#include "config.h"
29
+
30
+#include <stdio.h>
31
+#include <stdlib.h>
32
+#include <stdint.h>
33
+#include <string.h>
34
+#include <assert.h>
35
+#include <errno.h>
36
+#include <unistd.h>
37
+#include <sys/time.h>
38
+
39
+#ifdef HAVE_FREEIPMI
40
+
41
+#include <ipmi_monitoring.h>
42
+#include <ipmi_monitoring_bitmasks.h>
43
+
44
+/* Communication Configuration - Initialize accordingly */
45
+
46
+/* Hostname, NULL for In-band communication, non-null for a hostname */
47
+char *hostname = NULL;
48
+
49
+/* In-band Communication Configuration */
50
+int driver_type = IPMI_MONITORING_DRIVER_TYPE_KCS; /* or -1 for default */
51
+int disable_auto_probe = 0; /* probe for in-band device */
52
+unsigned int driver_address = 0; /* not used if probing */
53
+unsigned int register_spacing = 0; /* not used if probing */
54
+char *driver_device = NULL; /* not used if probing */
55
+
56
+/* Out-of-band Communication Configuration */
57
+int protocol_version = IPMI_MONITORING_PROTOCOL_VERSION_1_5; /* or -1 for default */
58
+char *username = "foousername";
59
+char *password = "foopassword";
60
+unsigned char *k_g = NULL;
61
+unsigned int k_g_len = 0;
62
+int privilege_level = IPMI_MONITORING_PRIVILEGE_LEVEL_USER; /* or -1 for default */
63
+int authentication_type = IPMI_MONITORING_AUTHENTICATION_TYPE_MD5; /* or -1 for default */
64
+int cipher_suite_id = 0; /* or -1 for default */
65
+int session_timeout = 0; /* 0 for default */
66
+int retransmission_timeout = 0; /* 0 for default */
67
+
68
+/* Workarounds - specify workaround flags if necessary */
69
+unsigned int workaround_flags = 0;
70
+
71
+/* Initialize w/ record id numbers to only monitor specific record ids */
72
+unsigned int record_ids[] = {0};
73
+unsigned int record_ids_length = 0;
74
+
75
+/* Initialize w/ sensor types to only monitor specific sensor types
76
+ * see ipmi_monitoring.h sensor types list.
77
+ */
78
+unsigned int sensor_types[] = {0};
79
+unsigned int sensor_types_length = 0;
80
+
81
+/* Set to an appropriate alternate if desired */
82
+char *sdr_cache_directory = "/tmp";
83
+char *sensor_config_file = NULL;
84
+
85
+/* Set to 1 or 0 to enable these sensor reading flags
86
+ * - See ipmi_monitoring.h for descriptions of these flags.
87
+ */
88
+int reread_sdr_cache = 0;
89
+int ignore_non_interpretable_sensors = 1;
90
+int bridge_sensors = 0;
91
+int interpret_oem_data = 0;
92
+int shared_sensors = 0;
93
+int discrete_reading = 0;
94
+int ignore_scanning_disabled = 0;
95
+int assume_bmc_owner = 0;
96
+int entity_sensor_names = 0;
97
+
98
+/* Initialization flags
99
+ *
100
+ * Most commonly bitwise OR IPMI_MONITORING_FLAGS_DEBUG and/or
101
+ * IPMI_MONITORING_FLAGS_DEBUG_IPMI_PACKETS for extra debugging
102
+ * information.
103
+ */
104
+unsigned int ipmimonitoring_init_flags = 0;
105
+
106
+int errnum;
107
+
108
+// ----------------------------------------------------------------------------
109
+// SEL only variables
110
+
111
+/* Initialize w/ date range to only monitoring specific date range */
112
+char *date_begin = NULL; /* use MM/DD/YYYY format */
113
+char *date_end = NULL; /* use MM/DD/YYYY format */
114
+
115
+int assume_system_event_record = 0;
116
+
117
+char *sel_config_file = NULL;
118
+
119
+
120
+// ----------------------------------------------------------------------------
121
+// functions common to sensors and SEL
122
+
123
+static void
124
+_init_ipmi_config (struct ipmi_monitoring_ipmi_config *ipmi_config)
125
+{
126
+ assert (ipmi_config);
127
+
128
+ ipmi_config->driver_type = driver_type;
129
+ ipmi_config->disable_auto_probe = disable_auto_probe;
130
+ ipmi_config->driver_address = driver_address;
131
+ ipmi_config->register_spacing = register_spacing;
132
+ ipmi_config->driver_device = driver_device;
133
+
134
+ ipmi_config->protocol_version = protocol_version;
135
+ ipmi_config->username = username;
136
+ ipmi_config->password = password;
137
+ ipmi_config->k_g = k_g;
138
+ ipmi_config->k_g_len = k_g_len;
139
+ ipmi_config->privilege_level = privilege_level;
140
+ ipmi_config->authentication_type = authentication_type;
141
+ ipmi_config->cipher_suite_id = cipher_suite_id;
142
+ ipmi_config->session_timeout_len = session_timeout;
143
+ ipmi_config->retransmission_timeout_len = retransmission_timeout;
144
+
145
+ ipmi_config->workaround_flags = workaround_flags;
146
+}
147
+
148
+#ifdef NETDATA_COMMENTED
149
+static const char *
150
+_get_sensor_type_string (int sensor_type)
151
+{
152
+ switch (sensor_type)
153
+ {
154
+ case IPMI_MONITORING_SENSOR_TYPE_RESERVED:
155
+ return ("Reserved");
156
+ case IPMI_MONITORING_SENSOR_TYPE_TEMPERATURE:
157
+ return ("Temperature");
158
+ case IPMI_MONITORING_SENSOR_TYPE_VOLTAGE:
159
+ return ("Voltage");
160
+ case IPMI_MONITORING_SENSOR_TYPE_CURRENT:
161
+ return ("Current");
162
+ case IPMI_MONITORING_SENSOR_TYPE_FAN:
163
+ return ("Fan");
164
+ case IPMI_MONITORING_SENSOR_TYPE_PHYSICAL_SECURITY:
165
+ return ("Physical Security");
166
+ case IPMI_MONITORING_SENSOR_TYPE_PLATFORM_SECURITY_VIOLATION_ATTEMPT:
167
+ return ("Platform Security Violation Attempt");
168
+ case IPMI_MONITORING_SENSOR_TYPE_PROCESSOR:
169
+ return ("Processor");
170
+ case IPMI_MONITORING_SENSOR_TYPE_POWER_SUPPLY:
171
+ return ("Power Supply");
172
+ case IPMI_MONITORING_SENSOR_TYPE_POWER_UNIT:
173
+ return ("Power Unit");
174
+ case IPMI_MONITORING_SENSOR_TYPE_COOLING_DEVICE:
175
+ return ("Cooling Device");
176
+ case IPMI_MONITORING_SENSOR_TYPE_OTHER_UNITS_BASED_SENSOR:
177
+ return ("Other Units Based Sensor");
178
+ case IPMI_MONITORING_SENSOR_TYPE_MEMORY:
179
+ return ("Memory");
180
+ case IPMI_MONITORING_SENSOR_TYPE_DRIVE_SLOT:
181
+ return ("Drive Slot");
182
+ case IPMI_MONITORING_SENSOR_TYPE_POST_MEMORY_RESIZE:
183
+ return ("POST Memory Resize");
184
+ case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_FIRMWARE_PROGRESS:
185
+ return ("System Firmware Progress");
186
+ case IPMI_MONITORING_SENSOR_TYPE_EVENT_LOGGING_DISABLED:
187
+ return ("Event Logging Disabled");
188
+ case IPMI_MONITORING_SENSOR_TYPE_WATCHDOG1:
189
+ return ("Watchdog 1");
190
+ case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_EVENT:
191
+ return ("System Event");
192
+ case IPMI_MONITORING_SENSOR_TYPE_CRITICAL_INTERRUPT:
193
+ return ("Critical Interrupt");
194
+ case IPMI_MONITORING_SENSOR_TYPE_BUTTON_SWITCH:
195
+ return ("Button/Switch");
196
+ case IPMI_MONITORING_SENSOR_TYPE_MODULE_BOARD:
197
+ return ("Module/Board");
198
+ case IPMI_MONITORING_SENSOR_TYPE_MICROCONTROLLER_COPROCESSOR:
199
+ return ("Microcontroller/Coprocessor");
200
+ case IPMI_MONITORING_SENSOR_TYPE_ADD_IN_CARD:
201
+ return ("Add In Card");
202
+ case IPMI_MONITORING_SENSOR_TYPE_CHASSIS:
203
+ return ("Chassis");
204
+ case IPMI_MONITORING_SENSOR_TYPE_CHIP_SET:
205
+ return ("Chip Set");
206
+ case IPMI_MONITORING_SENSOR_TYPE_OTHER_FRU:
207
+ return ("Other Fru");
208
+ case IPMI_MONITORING_SENSOR_TYPE_CABLE_INTERCONNECT:
209
+ return ("Cable/Interconnect");
210
+ case IPMI_MONITORING_SENSOR_TYPE_TERMINATOR:
211
+ return ("Terminator");
212
+ case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_BOOT_INITIATED:
213
+ return ("System Boot Initiated");
214
+ case IPMI_MONITORING_SENSOR_TYPE_BOOT_ERROR:
215
+ return ("Boot Error");
216
+ case IPMI_MONITORING_SENSOR_TYPE_OS_BOOT:
217
+ return ("OS Boot");
218
+ case IPMI_MONITORING_SENSOR_TYPE_OS_CRITICAL_STOP:
219
+ return ("OS Critical Stop");
220
+ case IPMI_MONITORING_SENSOR_TYPE_SLOT_CONNECTOR:
221
+ return ("Slot/Connector");
222
+ case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE:
223
+ return ("System ACPI Power State");
224
+ case IPMI_MONITORING_SENSOR_TYPE_WATCHDOG2:
225
+ return ("Watchdog 2");
226
+ case IPMI_MONITORING_SENSOR_TYPE_PLATFORM_ALERT:
227
+ return ("Platform Alert");
228
+ case IPMI_MONITORING_SENSOR_TYPE_ENTITY_PRESENCE:
229
+ return ("Entity Presence");
230
+ case IPMI_MONITORING_SENSOR_TYPE_MONITOR_ASIC_IC:
231
+ return ("Monitor ASIC/IC");
232
+ case IPMI_MONITORING_SENSOR_TYPE_LAN:
233
+ return ("LAN");
234
+ case IPMI_MONITORING_SENSOR_TYPE_MANAGEMENT_SUBSYSTEM_HEALTH:
235
+ return ("Management Subsystem Health");
236
+ case IPMI_MONITORING_SENSOR_TYPE_BATTERY:
237
+ return ("Battery");
238
+ case IPMI_MONITORING_SENSOR_TYPE_SESSION_AUDIT:
239
+ return ("Session Audit");
240
+ case IPMI_MONITORING_SENSOR_TYPE_VERSION_CHANGE:
241
+ return ("Version Change");
242
+ case IPMI_MONITORING_SENSOR_TYPE_FRU_STATE:
243
+ return ("FRU State");
244
+ }
245
+
246
+ return ("Unrecognized");
247
+}
248
+#endif // NETDATA_COMMENTED
249
+
250
+
251
+// ----------------------------------------------------------------------------
252
+// BEGIN NETDATA CODE
253
+
254
+static int debug = 0;
255
+
256
+static int netdata_update_every = 5;
257
+static int netdata_priority = 90000;
258
+
259
+static size_t netdata_sensors_updated = 0;
260
+static size_t netdata_sensors_collected = 0;
261
+static size_t netdata_sel_events = 0;
262
+
263
+struct sensor {
264
+ int record_id;
265
+ int sensor_number;
266
+ int sensor_type;
267
+ int sensor_state;
268
+ int sensor_units;
269
+ char *sensor_name;
270
+
271
+ int sensor_reading_type;
272
+ union {
273
+ uint8_t bool_value;
274
+ uint32_t uint32_value;
275
+ double double_value;
276
+ } sensor_reading;
277
+
278
+ int sent;
279
+ int ignore;
280
+ int exposed;
281
+ int updated;
282
+ struct sensor *next;
283
+} *sensors_root = NULL;
284
+
285
+static void netdata_mark_as_not_updated() {
286
+ struct sensor *sn;
287
+ for(sn = sensors_root; sn ;sn = sn->next)
288
+ sn->updated = sn->sent = 0;
289
+
290
+ netdata_sensors_updated = 0;
291
+ netdata_sensors_collected = 0;
292
+ netdata_sel_events = 0;
293
+}
294
+
295
+static void send_chart_to_netdata_for_units(int units) {
296
+ struct sensor *sn;
297
+
298
+ switch(units) {
299
+ case IPMI_MONITORING_SENSOR_UNITS_CELSIUS:
300
+ printf("CHART ipmi.temperatures_c '' 'System Celcius Temperatures read by IPMI' 'Celcius' 'temperatures' 'ipmi.temperatures_c' 'line' %d %d\n"
301
+ , netdata_priority
302
+ , netdata_update_every
303
+ );
304
+ break;
305
+
306
+ case IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT:
307
+ printf("CHART ipmi.temperatures_f '' 'System Fahrenheit Temperatures read by IPMI' 'Fahrenheit' 'temperatures' 'ipmi.temperatures_f' 'line' %d %d\n"
308
+ , netdata_priority
309
+ , netdata_update_every
310
+ );
311
+ break;
312
+
313
+ case IPMI_MONITORING_SENSOR_UNITS_VOLTS:
314
+ printf("CHART ipmi.volts '' 'System Voltages read by IPMI' 'Volts' 'voltages' 'ipmi.voltages' 'line' %d %d\n"
315
+ , netdata_priority
316
+ , netdata_update_every
317
+ );
318
+ break;
319
+
320
+ case IPMI_MONITORING_SENSOR_UNITS_AMPS:
321
+ printf("CHART ipmi.amps '' 'System Current read by IPMI' 'Amps' 'current' 'ipmi.amps' 'line' %d %d\n"
322
+ , netdata_priority
323
+ , netdata_update_every
324
+ );
325
+ break;
326
+
327
+ case IPMI_MONITORING_SENSOR_UNITS_RPM:
328
+ printf("CHART ipmi.rpm '' 'System Fans read by IPMI' 'RPM' 'fans' 'ipmi.rpm' 'line' %d %d\n"
329
+ , netdata_priority
330
+ , netdata_update_every
331
+ );
332
+ break;
333
+
334
+ case IPMI_MONITORING_SENSOR_UNITS_WATTS:
335
+ printf("CHART ipmi.watts '' 'System Power read by IPMI' 'Watts' 'power' 'ipmi.watts' 'line' %d %d\n"
336
+ , netdata_priority
337
+ , netdata_update_every
338
+ );
339
+ break;
340
+
341
+ case IPMI_MONITORING_SENSOR_UNITS_PERCENT:
342
+ printf("CHART ipmi.percent '' 'System Metrics read by IPMI' '%%' 'other' 'ipmi.percent' 'line' %d %d\n"
343
+ , netdata_priority
344
+ , netdata_update_every
345
+ );
346
+ break;
347
+
348
+ default:
349
+ for(sn = sensors_root; sn; sn = sn->next)
350
+ if(sn->sensor_units == units)
351
+ sn->ignore = 1;
352
+ return;
353
+ }
354
+
355
+ for(sn = sensors_root; sn; sn = sn->next) {
356
+ if(sn->sensor_units == units && sn->updated && !sn->ignore) {
357
+ sn->exposed = 1;
358
+
359
+ switch(sn->sensor_reading_type) {
360
+ case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL:
361
+ case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32:
362
+ printf("DIMENSION i%d_n%d_r%d '%s i%d' absolute 1 1\n"
363
+ , sn->sensor_number
364
+ , sn->record_id
365
+ , sn->sensor_reading_type
366
+ , sn->sensor_name
367
+ , sn->sensor_number
368
+ );
369
+ break;
370
+
371
+ case IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE:
372
+ printf("DIMENSION i%d_n%d_r%d '%s i%d' absolute 1 1000\n"
373
+ , sn->sensor_number
374
+ , sn->record_id
375
+ , sn->sensor_reading_type
376
+ , sn->sensor_name
377
+ , sn->sensor_number
378
+ );
379
+ break;
380
+
381
+ default:
382
+ sn->ignore = 1;
383
+ break;
384
+ }
385
+ }
386
+ }
387
+}
388
+
389
+static void send_metrics_to_netdata_for_units(int units) {
390
+ struct sensor *sn;
391
+
392
+ switch(units) {
393
+ case IPMI_MONITORING_SENSOR_UNITS_CELSIUS:
394
+ printf("BEGIN ipmi.temperatures_c\n");
395
+ break;
396
+
397
+ case IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT:
398
+ printf("BEGIN ipmi.temperatures_f\n");
399
+ break;
400
+
401
+ case IPMI_MONITORING_SENSOR_UNITS_VOLTS:
402
+ printf("BEGIN ipmi.volts\n");
403
+ break;
404
+
405
+ case IPMI_MONITORING_SENSOR_UNITS_AMPS:
406
+ printf("BEGIN ipmi.amps\n");
407
+ break;
408
+
409
+ case IPMI_MONITORING_SENSOR_UNITS_RPM:
410
+ printf("BEGIN ipmi.rpm\n");
411
+ break;
412
+
413
+ case IPMI_MONITORING_SENSOR_UNITS_WATTS:
414
+ printf("BEGIN ipmi.watts\n");
415
+ break;
416
+
417
+ case IPMI_MONITORING_SENSOR_UNITS_PERCENT:
418
+ printf("BEGIN ipmi.percent\n");
419
+ break;
420
+
421
+ default:
422
+ for(sn = sensors_root; sn; sn = sn->next)
423
+ if(sn->sensor_units == units)
424
+ sn->ignore = 1;
425
+ return;
426
+ }
427
+
428
+ for(sn = sensors_root; sn; sn = sn->next) {
429
+ if(sn->sensor_units == units && sn->updated && !sn->sent && !sn->ignore) {
430
+ netdata_sensors_updated++;
431
+
432
+ sn->sent = 1;
433
+
434
+ switch(sn->sensor_reading_type) {
435
+ case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL:
436
+ printf("SET i%d_n%d_r%d = %u\n"
437
+ , sn->sensor_number
438
+ , sn->record_id
439
+ , sn->sensor_reading_type
440
+ , sn->sensor_reading.bool_value
441
+ );
442
+ break;
443
+
444
+ case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32:
445
+ printf("SET i%d_n%d_r%d = %u\n"
446
+ , sn->sensor_number
447
+ , sn->record_id
448
+ , sn->sensor_reading_type
449
+ , sn->sensor_reading.uint32_value
450
+ );
451
+ break;
452
+
453
+ case IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE:
454
+ printf("SET i%d_n%d_r%d = %lld\n"
455
+ , sn->sensor_number
456
+ , sn->record_id
457
+ , sn->sensor_reading_type
458
+ , (long long int)(sn->sensor_reading.double_value * 1000)
459
+ );
460
+ break;
461
+
462
+ default:
463
+ sn->ignore = 1;
464
+ break;
465
+ }
466
+ }
467
+ }
468
+
469
+ printf("END\n");
470
+}
471
+
472
+static void send_metrics_to_netdata() {
473
+ static int sel_chart_generated = 0;
474
+ struct sensor *sn;
475
+
476
+ if(!sel_chart_generated) {
477
+ printf("CHART ipmi.events '' 'IPMI Events' 'events' 'events' 'ipmi.sel' 'area' %d %d\n"
478
+ , netdata_priority
479
+ , netdata_update_every
480
+ );
481
+ printf("DIMENSION events '' absolute 1 1\n");
482
+ }
483
+
484
+ // generate the CHART/DIMENSION lines, if we have to
485
+ for(sn = sensors_root; sn; sn = sn->next)
486
+ if(sn->updated && !sn->exposed && !sn->ignore)
487
+ send_chart_to_netdata_for_units(sn->sensor_units);
488
+
489
+ printf("BEGIN ipmi.events\nSET events = %zu\nEND\n", netdata_sel_events);
490
+
491
+ // send metrics to netdata
492
+ for(sn = sensors_root; sn; sn = sn->next)
493
+ if(sn->updated && sn->exposed && !sn->sent && !sn->ignore)
494
+ send_metrics_to_netdata_for_units(sn->sensor_units);
495
+
496
+}
497
+
498
+static void netdata_get_sensor(
499
+ int record_id
500
+ , int sensor_number
501
+ , int sensor_type
502
+ , int sensor_state
503
+ , int sensor_units
504
+ , int sensor_reading_type
505
+ , char *sensor_name
506
+ , void *sensor_reading
507
+) {
508
+ // find the sensor record
509
+ struct sensor *sn;
510
+ for(sn = sensors_root; sn ;sn = sn->next)
511
+ if( sn->record_id == record_id &&
512
+ sn->sensor_number == sensor_number &&
513
+ sn->sensor_reading_type == sensor_reading_type &&
514
+ sn->sensor_units == sensor_units &&
515
+ !strcmp(sn->sensor_name, sensor_name)
516
+ )
517
+ break;
518
+
519
+ if(!sn) {
520
+ // not found, create it
521
+
522
+ sn = calloc(1, sizeof(struct sensor));
523
+ if(!sn) {
524
+ fprintf(stderr, "freeipmi.plugin: cannot allocate %zu bytes of memory.", sizeof(struct sensor));
525
+ exit(1);
526
+ }
527
+
528
+ sn->record_id = record_id;
529
+ sn->sensor_number = sensor_number;
530
+ sn->sensor_type = sensor_type;
531
+ sn->sensor_state = sensor_state;
532
+ sn->sensor_units = sensor_units;
533
+ sn->sensor_reading_type = sensor_reading_type;
534
+ sn->sensor_name = strdup(sensor_name);
535
+ if(!sn->sensor_name) {
536
+ fprintf(stderr, "freeipmi.plugin: cannot allocate %zu bytes of memory.", strlen(sensor_name));
537
+ exit(1);
538
+ }
539
+
540
+ sn->next = sensors_root;
541
+ sensors_root = sn;
542
+ }
543
+
544
+ switch(sensor_reading_type) {
545
+ case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL:
546
+ sn->sensor_reading.bool_value = *((uint8_t *)sensor_reading);
547
+ sn->updated = 1;
548
+ netdata_sensors_collected++;
549
+ break;
550
+
551
+ case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32:
552
+ sn->sensor_reading.uint32_value = *((uint32_t *)sensor_reading);
553
+ sn->updated = 1;
554
+ netdata_sensors_collected++;
555
+ break;
556
+
557
+ case IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE:
558
+ sn->sensor_reading.double_value = *((double *)sensor_reading);
559
+ sn->updated = 1;
560
+ netdata_sensors_collected++;
561
+ break;
562
+
563
+ default:
564
+ sn->ignore = 1;
565
+ break;
566
+ }
567
+
568
+/* switch(sensor_state) {
569
+ case IPMI_MONITORING_STATE_NOMINAL:
570
+ case IPMI_MONITORING_STATE_WARNING:
571
+ case IPMI_MONITORING_STATE_CRITICAL:
572
+ default:
573
+ break;
574
+ }
575
+*/
576
+}
577
+
578
+static void netdata_get_sel(
579
+ int record_id
580
+ , int record_type_class
581
+ , int sel_state
582
+) {
583
+ (void)record_id;
584
+ (void)record_type_class;
585
+ (void)sel_state;
586
+
587
+ netdata_sel_events++;
588
+}
589
+
590
+
591
+static unsigned long long now_realtime_usec() {
592
+ struct timeval tv;
593
+ gettimeofday(&tv, NULL);
594
+ return tv.tv_sec * 1000000ULL + tv.tv_usec;
595
+}
596
+
597
+// END NETDATA CODE
598
+// ----------------------------------------------------------------------------
599
+
600
+
601
+/* This is an example of how to use the libipmimonitoring library to
602
+ * read and monitor sensors.
603
+ *
604
+ * At the top of this file, you'll find a number of variables for
605
+ * configuration of IPMI communication and what sensors you are
606
+ * interested in monitoring. Those variables are used in the
607
+ * libipmimonitoring calls below.
608
+ *
609
+ * Hopefully this example will be sufficient to help anyone program
610
+ * IPMI monitoring software for their environment.
611
+ *
612
+ * To compile, linking against the library should be sufficient for
613
+ * most environments. e.g.
614
+ *
615
+ * gcc -o freeipmi.plugin freeipmi_plugin.c -lipmimonitoring
616
+ */
617
+
618
+static int
619
+_ipmimonitoring_sensors (struct ipmi_monitoring_ipmi_config *ipmi_config)
620
+{
621
+ ipmi_monitoring_ctx_t ctx = NULL;
622
+ unsigned int sensor_reading_flags = 0;
623
+ int i;
624
+ int sensor_count;
625
+ int rv = -1;
626
+
627
+ if (!(ctx = ipmi_monitoring_ctx_create ()))
628
+ {
629
+ perror ("ipmi_monitoring_ctx_create:");
630
+ goto cleanup;
631
+ }
632
+
633
+ if (sdr_cache_directory)
634
+ {
635
+ if (ipmi_monitoring_ctx_sdr_cache_directory (ctx,
636
+ sdr_cache_directory) < 0)
637
+ {
638
+ fprintf (stderr,
639
+ "ipmi_monitoring_ctx_sdr_cache_directory: %s\n",
640
+ ipmi_monitoring_ctx_errormsg (ctx));
641
+ goto cleanup;
642
+ }
643
+ }
644
+
645
+ /* Must call otherwise only default interpretations ever used */
646
+ if (sensor_config_file)
647
+ {
648
+ if (ipmi_monitoring_ctx_sensor_config_file (ctx,
649
+ sensor_config_file) < 0)
650
+ {
651
+ fprintf (stderr,
652
+ "ipmi_monitoring_ctx_sensor_config_file: %s\n",
653
+ ipmi_monitoring_ctx_errormsg (ctx));
654
+ goto cleanup;
655
+ }
656
+ }
657
+ else
658
+ {
659
+ if (ipmi_monitoring_ctx_sensor_config_file (ctx, NULL) < 0)
660
+ {
661
+ fprintf (stderr,
662
+ "ipmi_monitoring_ctx_sensor_config_file: %s\n",
663
+ ipmi_monitoring_ctx_errormsg (ctx));
664
+ goto cleanup;
665
+ }
666
+ }
667
+
668
+ if (reread_sdr_cache)
669
+ sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_REREAD_SDR_CACHE;
670
+
671
+ if (ignore_non_interpretable_sensors)
672
+ sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_NON_INTERPRETABLE_SENSORS;
673
+
674
+ if (bridge_sensors)
675
+ sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_BRIDGE_SENSORS;
676
+
677
+ if (interpret_oem_data)
678
+ sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_INTERPRET_OEM_DATA;
679
+
680
+ if (shared_sensors)
681
+ sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_SHARED_SENSORS;
682
+
683
+ if (discrete_reading)
684
+ sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_DISCRETE_READING;
685
+
686
+ if (ignore_scanning_disabled)
687
+ sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_SCANNING_DISABLED;
688
+
689
+ if (assume_bmc_owner)
690
+ sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_ASSUME_BMC_OWNER;
691
+
692
+#ifdef IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES
693
+ if (entity_sensor_names)
694
+ sensor_reading_flags |= IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES;
695
+#endif // IPMI_MONITORING_SENSOR_READING_FLAGS_ENTITY_SENSOR_NAMES
696
+
697
+ if (!record_ids_length && !sensor_types_length)
698
+ {
699
+ if ((sensor_count = ipmi_monitoring_sensor_readings_by_record_id (ctx,
700
+ hostname,
701
+ ipmi_config,
702
+ sensor_reading_flags,
703
+ NULL,
704
+ 0,
705
+ NULL,
706
+ NULL)) < 0)
707
+ {
708
+ fprintf (stderr,
709
+ "ipmi_monitoring_sensor_readings_by_record_id: %s\n",
710
+ ipmi_monitoring_ctx_errormsg (ctx));
711
+ goto cleanup;
712
+ }
713
+ }
714
+ else if (record_ids_length)
715
+ {
716
+ if ((sensor_count = ipmi_monitoring_sensor_readings_by_record_id (ctx,
717
+ hostname,
718
+ ipmi_config,
719
+ sensor_reading_flags,
720
+ record_ids,
721
+ record_ids_length,
722
+ NULL,
723
+ NULL)) < 0)
724
+ {
725
+ fprintf (stderr,
726
+ "ipmi_monitoring_sensor_readings_by_record_id: %s\n",
727
+ ipmi_monitoring_ctx_errormsg (ctx));
728
+ goto cleanup;
729
+ }
730
+ }
731
+ else
732
+ {
733
+ if ((sensor_count = ipmi_monitoring_sensor_readings_by_sensor_type (ctx,
734
+ hostname,
735
+ ipmi_config,
736
+ sensor_reading_flags,
737
+ sensor_types,
738
+ sensor_types_length,
739
+ NULL,
740
+ NULL)) < 0)
741
+ {
742
+ fprintf (stderr,
743
+ "ipmi_monitoring_sensor_readings_by_sensor_type: %s\n",
744
+ ipmi_monitoring_ctx_errormsg (ctx));
745
+ goto cleanup;
746
+ }
747
+ }
748
+
749
+#ifdef NETDATA_COMMENTED
750
+ printf ("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
751
+ "Record ID",
752
+ "Sensor Name",
753
+ "Sensor Number",
754
+ "Sensor Type",
755
+ "Sensor State",
756
+ "Sensor Reading",
757
+ "Sensor Units",
758
+ "Sensor Event/Reading Type Code",
759
+ "Sensor Event Bitmask",
760
+ "Sensor Event String");
761
+#endif // NETDATA_COMMENTED
762
+
763
+ for (i = 0; i < sensor_count; i++, ipmi_monitoring_sensor_iterator_next (ctx))
764
+ {
765
+ int record_id, sensor_number, sensor_type, sensor_state, sensor_units,
766
+ sensor_reading_type;
767
+
768
+#ifdef NETDATA_COMMENTED
769
+ int sensor_bitmask_type, sensor_bitmask, event_reading_type_code;
770
+ char **sensor_bitmask_strings = NULL;
771
+ const char *sensor_type_str;
772
+ const char *sensor_state_str;
773
+#endif // NETDATA_COMMENTED
774
+
775
+ char *sensor_name = NULL;
776
+ void *sensor_reading;
777
+
778
+ if ((record_id = ipmi_monitoring_sensor_read_record_id (ctx)) < 0)
779
+ {
780
+ fprintf (stderr,
781
+ "ipmi_monitoring_sensor_read_record_id: %s\n",
782
+ ipmi_monitoring_ctx_errormsg (ctx));
783
+ goto cleanup;
784
+ }
785
+
786
+ if ((sensor_number = ipmi_monitoring_sensor_read_sensor_number (ctx)) < 0)
787
+ {
788
+ fprintf (stderr,
789
+ "ipmi_monitoring_sensor_read_sensor_number: %s\n",
790
+ ipmi_monitoring_ctx_errormsg (ctx));
791
+ goto cleanup;
792
+ }
793
+
794
+ if ((sensor_type = ipmi_monitoring_sensor_read_sensor_type (ctx)) < 0)
795
+ {
796
+ fprintf (stderr,
797
+ "ipmi_monitoring_sensor_read_sensor_type: %s\n",
798
+ ipmi_monitoring_ctx_errormsg (ctx));
799
+ goto cleanup;
800
+ }
801
+
802
+ if (!(sensor_name = ipmi_monitoring_sensor_read_sensor_name (ctx)))
803
+ {
804
+ fprintf (stderr,
805
+ "ipmi_monitoring_sensor_read_sensor_name: %s\n",
806
+ ipmi_monitoring_ctx_errormsg (ctx));
807
+ goto cleanup;
808
+ }
809
+
810
+ if ((sensor_state = ipmi_monitoring_sensor_read_sensor_state (ctx)) < 0)
811
+ {
812
+ fprintf (stderr,
813
+ "ipmi_monitoring_sensor_read_sensor_state: %s\n",
814
+ ipmi_monitoring_ctx_errormsg (ctx));
815
+ goto cleanup;
816
+ }
817
+
818
+ if ((sensor_units = ipmi_monitoring_sensor_read_sensor_units (ctx)) < 0)
819
+ {
820
+ fprintf (stderr,
821
+ "ipmi_monitoring_sensor_read_sensor_units: %s\n",
822
+ ipmi_monitoring_ctx_errormsg (ctx));
823
+ goto cleanup;
824
+ }
825
+
826
+#ifdef NETDATA_COMMENTED
827
+ if ((sensor_bitmask_type = ipmi_monitoring_sensor_read_sensor_bitmask_type (ctx)) < 0)
828
+ {
829
+ fprintf (stderr,
830
+ "ipmi_monitoring_sensor_read_sensor_bitmask_type: %s\n",
831
+ ipmi_monitoring_ctx_errormsg (ctx));
832
+ goto cleanup;
833
+ }
834
+ if ((sensor_bitmask = ipmi_monitoring_sensor_read_sensor_bitmask (ctx)) < 0)
835
+ {
836
+ fprintf (stderr,
837
+ "ipmi_monitoring_sensor_read_sensor_bitmask: %s\n",
838
+ ipmi_monitoring_ctx_errormsg (ctx));
839
+ goto cleanup;
840
+ }
841
+
842
+ if (!(sensor_bitmask_strings = ipmi_monitoring_sensor_read_sensor_bitmask_strings (ctx)))
843
+ {
844
+ fprintf (stderr,
845
+ "ipmi_monitoring_sensor_read_sensor_bitmask_strings: %s\n",
846
+ ipmi_monitoring_ctx_errormsg (ctx));
847
+ goto cleanup;
848
+ }
849
+#endif // NETDATA_COMMENTED
850
+
851
+ if ((sensor_reading_type = ipmi_monitoring_sensor_read_sensor_reading_type (ctx)) < 0)
852
+ {
853
+ fprintf (stderr,
854
+ "ipmi_monitoring_sensor_read_sensor_reading_type: %s\n",
855
+ ipmi_monitoring_ctx_errormsg (ctx));
856
+ goto cleanup;
857
+ }
858
+
859
+ sensor_reading = ipmi_monitoring_sensor_read_sensor_reading (ctx);
860
+
861
+#ifdef NETDATA_COMMENTED
862
+ if ((event_reading_type_code = ipmi_monitoring_sensor_read_event_reading_type_code (ctx)) < 0)
863
+ {
864
+ fprintf (stderr,
865
+ "ipmi_monitoring_sensor_read_event_reading_type_code: %s\n",
866
+ ipmi_monitoring_ctx_errormsg (ctx));
867
+ goto cleanup;
868
+ }
869
+#endif // NETDATA_COMMENTED
870
+
871
+ netdata_get_sensor(
872
+ record_id
873
+ , sensor_number
874
+ , sensor_type
875
+ , sensor_state
876
+ , sensor_units
877
+ , sensor_reading_type
878
+ , sensor_name
879
+ , sensor_reading
880
+ );
881
+
882
+#ifdef NETDATA_COMMENTED
883
+ if (!strlen (sensor_name))
884
+ sensor_name = "N/A";
885
+
886
+ sensor_type_str = _get_sensor_type_string (sensor_type);
887
+
888
+ printf ("%u, %s, %u, %s",
889
+ record_id,
890
+ sensor_name,
891
+ sensor_number,
892
+ sensor_type_str);
893
+
894
+ if (sensor_state == IPMI_MONITORING_STATE_NOMINAL)
895
+ sensor_state_str = "Nominal";
896
+ else if (sensor_state == IPMI_MONITORING_STATE_WARNING)
897
+ sensor_state_str = "Warning";
898
+ else if (sensor_state == IPMI_MONITORING_STATE_CRITICAL)
899
+ sensor_state_str = "Critical";
900
+ else
901
+ sensor_state_str = "N/A";
902
+
903
+ printf (", %s", sensor_state_str);
904
+
905
+ if (sensor_reading)
906
+ {
907
+ const char *sensor_units_str;
908
+
909
+ if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL)
910
+ printf (", %s",
911
+ (*((uint8_t *)sensor_reading) ? "true" : "false"));
912
+ else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32)
913
+ printf (", %u",
914
+ *((uint32_t *)sensor_reading));
915
+ else if (sensor_reading_type == IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE)
916
+ printf (", %.2f",
917
+ *((double *)sensor_reading));
918
+ else
919
+ printf (", N/A");
920
+
921
+ if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_CELSIUS)
922
+ sensor_units_str = "C";
923
+ else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT)
924
+ sensor_units_str = "F";
925
+ else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_VOLTS)
926
+ sensor_units_str = "V";
927
+ else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_AMPS)
928
+ sensor_units_str = "A";
929
+ else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_RPM)
930
+ sensor_units_str = "RPM";
931
+ else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_WATTS)
932
+ sensor_units_str = "W";
933
+ else if (sensor_units == IPMI_MONITORING_SENSOR_UNITS_PERCENT)
934
+ sensor_units_str = "%";
935
+ else
936
+ sensor_units_str = "N/A";
937
+
938
+ printf (", %s", sensor_units_str);
939
+ }
940
+ else
941
+ printf (", N/A, N/A");
942
+
943
+ printf (", %Xh", event_reading_type_code);
944
+
945
+ /* It is possible you may want to monitor specific event
946
+ * conditions that may occur. If that is the case, you may want
947
+ * to check out what specific bitmask type and bitmask events
948
+ * occurred. See ipmi_monitoring_bitmasks.h for a list of
949
+ * bitmasks and types.
950
+ */
951
+
952
+ if (sensor_bitmask_type != IPMI_MONITORING_SENSOR_BITMASK_TYPE_UNKNOWN)
953
+ printf (", %Xh", sensor_bitmask);
954
+ else
955
+ printf (", N/A");
956
+
957
+ if (sensor_bitmask_type != IPMI_MONITORING_SENSOR_BITMASK_TYPE_UNKNOWN)
958
+ {
959
+ unsigned int i = 0;
960
+
961
+ printf (",");
962
+
963
+ while (sensor_bitmask_strings[i])
964
+ {
965
+ printf (" ");
966
+
967
+ printf ("'%s'",
968
+ sensor_bitmask_strings[i]);
969
+
970
+ i++;
971
+ }
972
+ }
973
+ else
974
+ printf (", N/A");
975
+
976
+ printf ("\n");
977
+#endif // NETDATA_COMMENTED
978
+ }
979
+
980
+ rv = 0;
981
+ cleanup:
982
+ if (ctx)
983
+ ipmi_monitoring_ctx_destroy (ctx);
984
+ return (rv);
985
+}
986
+
987
+
988
+/* This is an example of how to use the libipmimonitoring library to
989
+ * read and monitor the SEL.
990
+ *
991
+ * At the top of this file, you'll find a number of variables for
992
+ * configuration of IPMI communication and what SEL records you are
993
+ * interested in monitoring. Those variables are used in the
994
+ * libipmimonitoring calls below.
995
+ *
996
+ * Hopefully this example will be sufficient to help anyone program
997
+ * IPMI monitoring software for their environment.
998
+ *
999
+ * To compile, linking against the library should be sufficient for
1000
+ * most environments. e.g.
1001
+ *
1002
+ * gcc -o ipmimonitoring-sel ipmimonitoring-sel.c -lipmimonitoring
1003
+ */
1004
+
1005
+/* Communication Configuration - Initialize accordingly */
1006
+
1007
+static int
1008
+_ipmimonitoring_sel (struct ipmi_monitoring_ipmi_config *ipmi_config)
1009
+{
1010
+ ipmi_monitoring_ctx_t ctx = NULL;
1011
+ unsigned int sel_flags = 0;
1012
+ int i;
1013
+ int sel_count;
1014
+ int rv = -1;
1015
+
1016
+ if (!(ctx = ipmi_monitoring_ctx_create ()))
1017
+ {
1018
+ perror ("ipmi_monitoring_ctx_create:");
1019
+ goto cleanup;
1020
+ }
1021
+
1022
+ if (sdr_cache_directory)
1023
+ {
1024
+ if (ipmi_monitoring_ctx_sdr_cache_directory (ctx,
1025
+ sdr_cache_directory) < 0)
1026
+ {
1027
+ fprintf (stderr,
1028
+ "ipmi_monitoring_ctx_sdr_cache_directory: %s\n",
1029
+ ipmi_monitoring_ctx_errormsg (ctx));
1030
+ goto cleanup;
1031
+ }
1032
+ }
1033
+
1034
+ /* Must call otherwise only default interpretations ever used */
1035
+ if (sel_config_file)
1036
+ {
1037
+ if (ipmi_monitoring_ctx_sel_config_file (ctx,
1038
+ sel_config_file) < 0)
1039
+ {
1040
+ fprintf (stderr,
1041
+ "ipmi_monitoring_ctx_sel_config_file: %s\n",
1042
+ ipmi_monitoring_ctx_errormsg (ctx));
1043
+ goto cleanup;
1044
+ }
1045
+ }
1046
+ else
1047
+ {
1048
+ if (ipmi_monitoring_ctx_sel_config_file (ctx, NULL) < 0)
1049
+ {
1050
+ fprintf (stderr,
1051
+ "ipmi_monitoring_ctx_sel_config_file: %s\n",
1052
+ ipmi_monitoring_ctx_errormsg (ctx));
1053
+ goto cleanup;
1054
+ }
1055
+ }
1056
+
1057
+ if (reread_sdr_cache)
1058
+ sel_flags |= IPMI_MONITORING_SEL_FLAGS_REREAD_SDR_CACHE;
1059
+
1060
+ if (interpret_oem_data)
1061
+ sel_flags |= IPMI_MONITORING_SEL_FLAGS_INTERPRET_OEM_DATA;
1062
+
1063
+ if (assume_system_event_record)
1064
+ sel_flags |= IPMI_MONITORING_SEL_FLAGS_ASSUME_SYSTEM_EVENT_RECORD;
1065
+
1066
+#ifdef IPMI_MONITORING_SEL_FLAGS_ENTITY_SENSOR_NAMES
1067
+ if (entity_sensor_names)
1068
+ sel_flags |= IPMI_MONITORING_SEL_FLAGS_ENTITY_SENSOR_NAMES;
1069
+#endif // IPMI_MONITORING_SEL_FLAGS_ENTITY_SENSOR_NAMES
1070
+
1071
+ if (record_ids_length)
1072
+ {
1073
+ if ((sel_count = ipmi_monitoring_sel_by_record_id (ctx,
1074
+ hostname,
1075
+ ipmi_config,
1076
+ sel_flags,
1077
+ record_ids,
1078
+ record_ids_length,
1079
+ NULL,
1080
+ NULL)) < 0)
1081
+ {
1082
+ fprintf (stderr,
1083
+ "ipmi_monitoring_sel_by_record_id: %s\n",
1084
+ ipmi_monitoring_ctx_errormsg (ctx));
1085
+ goto cleanup;
1086
+ }
1087
+ }
1088
+ else if (sensor_types_length)
1089
+ {
1090
+ if ((sel_count = ipmi_monitoring_sel_by_sensor_type (ctx,
1091
+ hostname,
1092
+ ipmi_config,
1093
+ sel_flags,
1094
+ sensor_types,
1095
+ sensor_types_length,
1096
+ NULL,
1097
+ NULL)) < 0)
1098
+ {
1099
+ fprintf (stderr,
1100
+ "ipmi_monitoring_sel_by_sensor_type: %s\n",
1101
+ ipmi_monitoring_ctx_errormsg (ctx));
1102
+ goto cleanup;
1103
+ }
1104
+ }
1105
+ else if (date_begin
1106
+ || date_end)
1107
+ {
1108
+ if ((sel_count = ipmi_monitoring_sel_by_date_range (ctx,
1109
+ hostname,
1110
+ ipmi_config,
1111
+ sel_flags,
1112
+ date_begin,
1113
+ date_end,
1114
+ NULL,
1115
+ NULL)) < 0)
1116
+ {
1117
+ fprintf (stderr,
1118
+ "ipmi_monitoring_sel_by_sensor_type: %s\n",
1119
+ ipmi_monitoring_ctx_errormsg (ctx));
1120
+ goto cleanup;
1121
+ }
1122
+ }
1123
+ else
1124
+ {
1125
+ if ((sel_count = ipmi_monitoring_sel_by_record_id (ctx,
1126
+ hostname,
1127
+ ipmi_config,
1128
+ sel_flags,
1129
+ NULL,
1130
+ 0,
1131
+ NULL,
1132
+ NULL)) < 0)
1133
+ {
1134
+ fprintf (stderr,
1135
+ "ipmi_monitoring_sel_by_record_id: %s\n",
1136
+ ipmi_monitoring_ctx_errormsg (ctx));
1137
+ goto cleanup;
1138
+ }
1139
+ }
1140
+
1141
+#ifdef NETDATA_COMMENTED
1142
+ printf ("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
1143
+ "Record ID",
1144
+ "Record Type",
1145
+ "SEL State",
1146
+ "Timestamp",
1147
+ "Sensor Name",
1148
+ "Sensor Type",
1149
+ "Event Direction",
1150
+ "Event Type Code",
1151
+ "Event Data",
1152
+ "Event Offset",
1153
+ "Event Offset String");
1154
+#endif // NETDATA_COMMENTED
1155
+
1156
+ for (i = 0; i < sel_count; i++, ipmi_monitoring_sel_iterator_next (ctx))
1157
+ {
1158
+ int record_id, record_type, sel_state, record_type_class;
1159
+#ifdef NETDATA_COMMENTED
1160
+ int sensor_type, sensor_number, event_direction,
1161
+ event_offset_type, event_offset, event_type_code, manufacturer_id;
1162
+ unsigned int timestamp, event_data1, event_data2, event_data3;
1163
+ char *event_offset_string = NULL;
1164
+ const char *sensor_type_str;
1165
+ const char *event_direction_str;
1166
+ const char *sel_state_str;
1167
+ char *sensor_name = NULL;
1168
+ unsigned char oem_data[64];
1169
+ int oem_data_len;
1170
+ unsigned int j;
1171
+#endif // NETDATA_COMMENTED
1172
+
1173
+ if ((record_id = ipmi_monitoring_sel_read_record_id (ctx)) < 0)
1174
+ {
1175
+ fprintf (stderr,
1176
+ "ipmi_monitoring_sel_read_record_id: %s\n",
1177
+ ipmi_monitoring_ctx_errormsg (ctx));
1178
+ goto cleanup;
1179
+ }
1180
+
1181
+ if ((record_type = ipmi_monitoring_sel_read_record_type (ctx)) < 0)
1182
+ {
1183
+ fprintf (stderr,
1184
+ "ipmi_monitoring_sel_read_record_type: %s\n",
1185
+ ipmi_monitoring_ctx_errormsg (ctx));
1186
+ goto cleanup;
1187
+ }
1188
+
1189
+ if ((record_type_class = ipmi_monitoring_sel_read_record_type_class (ctx)) < 0)
1190
+ {
1191
+ fprintf (stderr,
1192
+ "ipmi_monitoring_sel_read_record_type_class: %s\n",
1193
+ ipmi_monitoring_ctx_errormsg (ctx));
1194
+ goto cleanup;
1195
+ }
1196
+
1197
+ if ((sel_state = ipmi_monitoring_sel_read_sel_state (ctx)) < 0)
1198
+ {
1199
+ fprintf (stderr,
1200
+ "ipmi_monitoring_sel_read_sel_state: %s\n",
1201
+ ipmi_monitoring_ctx_errormsg (ctx));
1202
+ goto cleanup;
1203
+ }
1204
+
1205
+ netdata_get_sel(
1206
+ record_id
1207
+ , record_type_class
1208
+ , sel_state
1209
+ );
1210
+
1211
+#ifdef NETDATA_COMMENTED
1212
+ if (sel_state == IPMI_MONITORING_STATE_NOMINAL)
1213
+ sel_state_str = "Nominal";
1214
+ else if (sel_state == IPMI_MONITORING_STATE_WARNING)
1215
+ sel_state_str = "Warning";
1216
+ else if (sel_state == IPMI_MONITORING_STATE_CRITICAL)
1217
+ sel_state_str = "Critical";
1218
+ else
1219
+ sel_state_str = "N/A";
1220
+
1221
+ printf ("%u, %u, %s",
1222
+ record_id,
1223
+ record_type,
1224
+ sel_state_str);
1225
+
1226
+ if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_SYSTEM_EVENT_RECORD
1227
+ || record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD)
1228
+ {
1229
+
1230
+ if (ipmi_monitoring_sel_read_timestamp (ctx, ×tamp) < 0)
1231
+ {
1232
+ fprintf (stderr,
1233
+ "ipmi_monitoring_sel_read_timestamp: %s\n",
1234
+ ipmi_monitoring_ctx_errormsg (ctx));
1235
+ goto cleanup;
1236
+ }
1237
+
1238
+ /* XXX: This should be converted to a nice date output using
1239
+ * your favorite timestamp -> string conversion functions.
1240
+ */
1241
+ printf (", %u", timestamp);
1242
+ }
1243
+ else
1244
+ printf (", N/A");
1245
+
1246
+ if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_SYSTEM_EVENT_RECORD)
1247
+ {
1248
+ /* If you are integrating ipmimonitoring SEL into a monitoring application,
1249
+ * you may wish to count the number of times a specific error occurred
1250
+ * and report that to the monitoring application.
1251
+ *
1252
+ * In this particular case, you'll probably want to check out
1253
+ * what sensor type each SEL event is reporting, the
1254
+ * event offset type, and the specific event offset that occurred.
1255
+ *
1256
+ * See ipmi_monitoring_offsets.h for a list of event offsets
1257
+ * and types.
1258
+ */
1259
+
1260
+ if (!(sensor_name = ipmi_monitoring_sel_read_sensor_name (ctx)))
1261
+ {
1262
+ fprintf (stderr,
1263
+ "ipmi_monitoring_sel_read_sensor_name: %s\n",
1264
+ ipmi_monitoring_ctx_errormsg (ctx));
1265
+ goto cleanup;
1266
+ }
1267
+
1268
+ if ((sensor_type = ipmi_monitoring_sel_read_sensor_type (ctx)) < 0)
1269
+ {
1270
+ fprintf (stderr,
1271
+ "ipmi_monitoring_sel_read_sensor_type: %s\n",
1272
+ ipmi_monitoring_ctx_errormsg (ctx));
1273
+ goto cleanup;
1274
+ }
1275
+
1276
+ if ((sensor_number = ipmi_monitoring_sel_read_sensor_number (ctx)) < 0)
1277
+ {
1278
+ fprintf (stderr,
1279
+ "ipmi_monitoring_sel_read_sensor_number: %s\n",
1280
+ ipmi_monitoring_ctx_errormsg (ctx));
1281
+ goto cleanup;
1282
+ }
1283
+
1284
+ if ((event_direction = ipmi_monitoring_sel_read_event_direction (ctx)) < 0)
1285
+ {
1286
+ fprintf (stderr,
1287
+ "ipmi_monitoring_sel_read_event_direction: %s\n",
1288
+ ipmi_monitoring_ctx_errormsg (ctx));
1289
+ goto cleanup;
1290
+ }
1291
+
1292
+ if ((event_type_code = ipmi_monitoring_sel_read_event_type_code (ctx)) < 0)
1293
+ {
1294
+ fprintf (stderr,
1295
+ "ipmi_monitoring_sel_read_event_type_code: %s\n",
1296
+ ipmi_monitoring_ctx_errormsg (ctx));
1297
+ goto cleanup;
1298
+ }
1299
+
1300
+ if (ipmi_monitoring_sel_read_event_data (ctx,
1301
+ &event_data1,
1302
+ &event_data2,
1303
+ &event_data3) < 0)
1304
+ {
1305
+ fprintf (stderr,
1306
+ "ipmi_monitoring_sel_read_event_data: %s\n",
1307
+ ipmi_monitoring_ctx_errormsg (ctx));
1308
+ goto cleanup;
1309
+ }
1310
+
1311
+ if ((event_offset_type = ipmi_monitoring_sel_read_event_offset_type (ctx)) < 0)
1312
+ {
1313
+ fprintf (stderr,
1314
+ "ipmi_monitoring_sel_read_event_offset_type: %s\n",
1315
+ ipmi_monitoring_ctx_errormsg (ctx));
1316
+ goto cleanup;
1317
+ }
1318
+
1319
+ if ((event_offset = ipmi_monitoring_sel_read_event_offset (ctx)) < 0)
1320
+ {
1321
+ fprintf (stderr,
1322
+ "ipmi_monitoring_sel_read_event_offset: %s\n",
1323
+ ipmi_monitoring_ctx_errormsg (ctx));
1324
+ goto cleanup;
1325
+ }
1326
+
1327
+ if (!(event_offset_string = ipmi_monitoring_sel_read_event_offset_string (ctx)))
1328
+ {
1329
+ fprintf (stderr,
1330
+ "ipmi_monitoring_sel_read_event_offset_string: %s\n",
1331
+ ipmi_monitoring_ctx_errormsg (ctx));
1332
+ goto cleanup;
1333
+ }
1334
+
1335
+ if (!strlen (sensor_name))
1336
+ sensor_name = "N/A";
1337
+
1338
+ sensor_type_str = _get_sensor_type_string (sensor_type);
1339
+
1340
+ if (event_direction == IPMI_MONITORING_SEL_EVENT_DIRECTION_ASSERTION)
1341
+ event_direction_str = "Assertion";
1342
+ else
1343
+ event_direction_str = "Deassertion";
1344
+
1345
+ printf (", %s, %s, %u, %s, %Xh, %Xh-%Xh-%Xh",
1346
+ sensor_name,
1347
+ sensor_type_str,
1348
+ sensor_number,
1349
+ event_direction_str,
1350
+ event_type_code,
1351
+ event_data1,
1352
+ event_data2,
1353
+ event_data3);
1354
+
1355
+ if (event_offset_type != IPMI_MONITORING_EVENT_OFFSET_TYPE_UNKNOWN)
1356
+ printf (", %Xh", event_offset);
1357
+ else
1358
+ printf (", N/A");
1359
+
1360
+ if (event_offset_type != IPMI_MONITORING_EVENT_OFFSET_TYPE_UNKNOWN)
1361
+ printf (", %s", event_offset_string);
1362
+ else
1363
+ printf (", N/A");
1364
+ }
1365
+ else if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD
1366
+ || record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_NON_TIMESTAMPED_OEM_RECORD)
1367
+ {
1368
+ if (record_type_class == IPMI_MONITORING_SEL_RECORD_TYPE_CLASS_TIMESTAMPED_OEM_RECORD)
1369
+ {
1370
+ if ((manufacturer_id = ipmi_monitoring_sel_read_manufacturer_id (ctx)) < 0)
1371
+ {
1372
+ fprintf (stderr,
1373
+ "ipmi_monitoring_sel_read_manufacturer_id: %s\n",
1374
+ ipmi_monitoring_ctx_errormsg (ctx));
1375
+ goto cleanup;
1376
+ }
1377
+
1378
+ printf (", Manufacturer ID = %Xh", manufacturer_id);
1379
+ }
1380
+
1381
+ if ((oem_data_len = ipmi_monitoring_sel_read_oem_data (ctx, oem_data, 1024)) < 0)
1382
+ {
1383
+ fprintf (stderr,
1384
+ "ipmi_monitoring_sel_read_oem_data: %s\n",
1385
+ ipmi_monitoring_ctx_errormsg (ctx));
1386
+ goto cleanup;
1387
+ }
1388
+
1389
+ printf (", OEM Data = ");
1390
+
1391
+ for (j = 0; j < oem_data_len; j++)
1392
+ printf ("%02Xh ", oem_data[j]);
1393
+ }
1394
+ else
1395
+ printf (", N/A, N/A, N/A, N/A, N/A, N/A, N/A");
1396
+
1397
+ printf ("\n");
1398
+#endif // NETDATA_COMMENTED
1399
+ }
1400
+
1401
+ rv = 0;
1402
+ cleanup:
1403
+ if (ctx)
1404
+ ipmi_monitoring_ctx_destroy (ctx);
1405
+ return (rv);
1406
+}
1407
+
1408
+// ----------------------------------------------------------------------------
1409
+// MAIN PROGRAM FOR NETDATA PLUGIN
1410
+
1411
+int ipmi_collect_data(struct ipmi_monitoring_ipmi_config *ipmi_config) {
1412
+
1413
+ if (_ipmimonitoring_sensors(ipmi_config) < 0) return -1;
1414
+ if (_ipmimonitoring_sel (ipmi_config) < 0) return -2;
1415
+
1416
+ return 0;
1417
+}
1418
+
1419
+int ipmi_detect_speed_secs(struct ipmi_monitoring_ipmi_config *ipmi_config) {
1420
+ int i, checks = 10;
1421
+ unsigned long long total = 0;
1422
+
1423
+ for(i = 0 ; i < checks ; i++) {
1424
+ if(debug) fprintf(stderr, "freeipmi.plugin: checking data collection speed iteration %d of %d\n", i+1, checks);
1425
+
1426
+ // measure the time a data collection needs
1427
+ unsigned long long start = now_realtime_usec();
1428
+ if(ipmi_collect_data(ipmi_config) < 0) {
1429
+ fprintf(stderr, "freeipmi.plugin: data collection failed.\n");
1430
+ exit(1);
1431
+ }
1432
+ unsigned long long end = now_realtime_usec();
1433
+
1434
+ if(debug) fprintf(stderr, "freeipmi.plugin: data collection speed was %llu usec\n", end - start);
1435
+
1436
+ // add it to our total
1437
+ total += end - start;
1438
+
1439
+ // wait the same time
1440
+ // to avoid flooding the IPMI processor with requests
1441
+ usleep(end - start);
1442
+ }
1443
+
1444
+ // so, we assume it needed 3x the time
1445
+ // we find the average in microseconds
1446
+ // and we round-up to the closest second
1447
+
1448
+ return (( total * 3 / checks / 1000000 ) + 1);
1449
+}
1450
+
1451
+int main (int argc, char **argv) {
1452
+ struct ipmi_monitoring_ipmi_config ipmi_config;
1453
+
1454
+ // parse command line parameters
1455
+
1456
+ int i, freq = 0;
1457
+ for(i = 1; i < argc ; i++) {
1458
+ if(!freq) {
1459
+ int n = atoi(argv[i]);
1460
+ if(n > 0) {
1461
+ freq = n;
1462
+ continue;
1463
+ }
1464
+ }
1465
+
1466
+ if(strcmp("debug", argv[i]) == 0) {
1467
+ debug = 1;
1468
+ continue;
1469
+ }
1470
+
1471
+ fprintf(stderr, "freeipmi.plugin: ignoring parameter '%s'\n", argv[i]);
1472
+ }
1473
+
1474
+ if(freq > 0 && freq < netdata_update_every)
1475
+ netdata_update_every = freq;
1476
+
1477
+ else if(freq)
1478
+ fprintf(stderr, "freeipmi.plugin: update frequency %d seconds is too small for IPMI. Using %d", freq, netdata_update_every);
1479
+
1480
+
1481
+ // initialize IPMI
1482
+
1483
+ if(debug) fprintf(stderr, "freeipmi.plugin: calling _init_ipmi_config()\n");
1484
+
1485
+ _init_ipmi_config(&ipmi_config);
1486
+
1487
+ if(debug) fprintf(stderr, "freeipmi.plugin: calling ipmi_monitoring_init()\n");
1488
+
1489
+ if(ipmi_monitoring_init(ipmimonitoring_init_flags, &errnum) < 0) {
1490
+ fprintf(stderr, "ipmi_monitoring_init: %s\n", ipmi_monitoring_ctx_strerror(errnum));
1491
+ exit(1);
1492
+ }
1493
+
1494
+ if(debug) fprintf(stderr, "freeipmi.plugin: detecting IPMI minimum update frequency...\n");
1495
+ freq = ipmi_detect_speed_secs(&ipmi_config);
1496
+ if(debug) fprintf(stderr, "freeipmi.plugin: IPMI minimum update frequency was calculated to %d seconds.\n", freq);
1497
+
1498
+ if(netdata_update_every < freq) {
1499
+ fprintf(stderr, "freeipmi.plugin: enforcing minimum data collection frequency, calculated to %d seconds.\n", freq);
1500
+ netdata_update_every = freq;
1501
+ }
1502
+
1503
+ // the main loop
1504
+ if(debug) fprintf(stderr, "freeipmi.plugin: starting data collection\n");
1505
+
1506
+ size_t iteration = 0;
1507
+ unsigned long long step = netdata_update_every * 1000000ULL;
1508
+ unsigned long long now = now_realtime_usec();
1509
+ unsigned long long next = now - (now % step) + step;
1510
+ while(1) {
1511
+ unsigned long long last = now;
1512
+ now = now_realtime_usec();
1513
+ if(debug && iteration)
1514
+ fprintf(stderr, "freeipmi.plugin: iteration %zu, dt %llu usec, sensors collected %zu, sensors sent to netdata %zu \n"
1515
+ , iteration
1516
+ , now - last
1517
+ , netdata_sensors_collected
1518
+ , netdata_sensors_updated
1519
+ );
1520
+
1521
+ while(now < next) {
1522
+ if(debug) fprintf(stderr, "freeipmi.plugin: sleeping for %llu usec\n", next - now);
1523
+ usleep(next - now);
1524
+ now = now_realtime_usec();
1525
+ }
1526
+ next = now - (now % step) + step;
1527
+
1528
+ netdata_mark_as_not_updated();
1529
+
1530
+ if(debug) fprintf(stderr, "freeipmi.plugin: calling ipmi_collect_data()\n");
1531
+ if(ipmi_collect_data(&ipmi_config) < 0) {
1532
+ fprintf(stderr, "freeipmi.plugin: data collection failed.\n");
1533
+ exit(1);
1534
+ }
1535
+
1536
+ if(debug) fprintf(stderr, "freeipmi.plugin: calling send_metrics_to_netdata()\n");
1537
+ send_metrics_to_netdata();
1538
+ fflush(stdout);
1539
+
1540
+ iteration++;
1541
+ }
1542
+ exit(0);
1543
+}
1544
+
1545
+#else // !HAVE_FREEIPMI
1546
+
1547
+int main(int argc, char **argv) {
1548
+ fprintf(stderr, "freeipmi.plugin: not compiled.");
1549
+ exit(1);
1550
+}
1551
+
1552
+#endif