freeipmi_plugin.c 66 KB

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