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