~iheino+ub/+junk/nut-upsconf-docfix

« back to all changes in this revision

Viewing changes to drivers/nut-libfreeipmi.c

  • Committer: Tuomas Heino
  • Author(s): Laurent Bigonville
  • Date: 2014-04-22 20:46:12 UTC
  • Revision ID: iheino+ub@cc.hut.fi-20140422204612-1x2gh3nkezfsdao4
Tags: upstream-2.7.2
Import upstream version 2.7.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  nut-libfreeipmi.c - NUT IPMI backend, using FreeIPMI
 
2
 *
 
3
 *  Copyright (C)
 
4
 *    2011 - 2012  Arnaud Quette <arnaud.quette@free.fr>
 
5
 *    2011 - Albert Chu <chu11@llnl.gov>
 
6
 *
 
7
 *  Based on the sample codes 'ipmi-fru-example.c', 'frulib.c' and
 
8
 *    'ipmimonitoring-sensors.c', from FreeIPMI
 
9
 *
 
10
 *  This program is free software; you can redistribute it and/or modify
 
11
 *  it under the terms of the GNU General Public License as published by
 
12
 *  the Free Software Foundation; either version 2 of the License, or
 
13
 *  (at your option) any later version.
 
14
 *
 
15
 *  This program is distributed in the hope that it will be useful,
 
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *  GNU General Public License for more details.
 
19
 *
 
20
 *  You should have received a copy of the GNU General Public License
 
21
 *  along with this program; if not, write to the Free Software
 
22
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
23
 *
 
24
 TODO:
 
25
 * add power control support (ipmipower): seems OOB only!
 
26
  -n, --on                   Power on the target hosts.
 
27
  -f, --off                  Power off the target hosts.
 
28
  -c, --cycle                Power cycle the target hosts.
 
29
  -r, --reset                Reset the target hosts.
 
30
  -s, --stat                 Get power status of the target hosts.
 
31
      --pulse                Send power diagnostic interrupt to target hosts.
 
32
      --soft                 Initiate a soft-shutdown of the OS via ACPI.
 
33
      --on-if-off            Issue a power on command instead of a power cycle
 
34
                             or hard reset command if the remote machine's
 
35
                             power is currently off.
 
36
      --wait-until-off       Regularly query the remote BMC and return only
 
37
                             after the machine has powered off.
 
38
      --wait-until-on        Regularly query the remote BMC and return only
 
39
 
 
40
 */
 
41
 
 
42
#include <stdlib.h>
 
43
#include <string.h>
 
44
#include "timehead.h"
 
45
#include "common.h"
 
46
#include <freeipmi/freeipmi.h>
 
47
#include <ipmi_monitoring.h>
 
48
#if HAVE_FREEIPMI_MONITORING
 
49
#include <ipmi_monitoring_bitmasks.h>
 
50
#endif
 
51
#include "nut-ipmi.h"
 
52
#include "dstate.h"
 
53
 
 
54
/* FreeIPMI defines */
 
55
#define IPMI_FRU_STR_BUFLEN    1024
 
56
/* haven't seen a motherboard with more than 2-3 so far,
 
57
 * 64 should be more than enough */
 
58
#define IPMI_FRU_CUSTOM_FIELDS 64
 
59
 
 
60
/* FreeIPMI contexts and configuration*/
 
61
ipmi_ctx_t ipmi_ctx = NULL;
 
62
ipmi_monitoring_ctx_t mon_ctx = NULL;
 
63
struct ipmi_monitoring_ipmi_config ipmi_config;
 
64
 
 
65
/* SDR management API has changed with 1.1.X and later */
 
66
#ifdef HAVE_FREEIPMI_11X_12X
 
67
  ipmi_sdr_ctx_t sdr_ctx = NULL;
 
68
  ipmi_fru_ctx_t fru_ctx = NULL;
 
69
  #define SDR_PARSE_CTX sdr_ctx
 
70
#else
 
71
  ipmi_sdr_cache_ctx_t sdr_ctx = NULL;
 
72
  ipmi_sdr_parse_ctx_t sdr_parse_ctx = NULL;
 
73
  #define SDR_PARSE_CTX sdr_parse_ctx
 
74
  ipmi_fru_parse_ctx_t fru_ctx = NULL;
 
75
  /* Functions remapping */
 
76
  #define ipmi_sdr_ctx_create                           ipmi_sdr_cache_ctx_create
 
77
  #define ipmi_sdr_ctx_destroy                          ipmi_sdr_cache_ctx_destroy
 
78
  #define ipmi_sdr_ctx_errnum                           ipmi_sdr_cache_ctx_errnum
 
79
  #define ipmi_sdr_ctx_errormsg                         ipmi_sdr_cache_ctx_errormsg
 
80
  #define ipmi_fru_ctx_create                           ipmi_fru_parse_ctx_create
 
81
  #define ipmi_fru_ctx_destroy                          ipmi_fru_parse_ctx_destroy
 
82
  #define ipmi_fru_ctx_set_flags                        ipmi_fru_parse_ctx_set_flags
 
83
  #define ipmi_fru_ctx_strerror                         ipmi_fru_parse_ctx_strerror
 
84
  #define ipmi_fru_ctx_errnum                           ipmi_fru_parse_ctx_errnum
 
85
  #define ipmi_fru_open_device_id                       ipmi_fru_parse_open_device_id
 
86
  #define ipmi_fru_close_device_id                      ipmi_fru_parse_close_device_id
 
87
  #define ipmi_fru_ctx_errormsg                         ipmi_fru_parse_ctx_errormsg
 
88
  #define ipmi_fru_read_data_area                       ipmi_fru_parse_read_data_area
 
89
  #define ipmi_fru_next                                 ipmi_fru_parse_next
 
90
  #define ipmi_fru_type_length_field_to_string          ipmi_fru_parse_type_length_field_to_string
 
91
  #define ipmi_fru_multirecord_power_supply_information ipmi_fru_parse_multirecord_power_supply_information
 
92
  #define ipmi_fru_board_info_area                      ipmi_fru_parse_board_info_area
 
93
  #define ipmi_fru_field_t                              ipmi_fru_parse_field_t
 
94
  /* Constants */
 
95
  #define IPMI_SDR_MAX_RECORD_LENGTH                               IPMI_SDR_CACHE_MAX_SDR_RECORD_LENGTH
 
96
  #define IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST             IPMI_SDR_CACHE_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST
 
97
  #define IPMI_FRU_AREA_SIZE_MAX                                   IPMI_FRU_PARSE_AREA_SIZE_MAX
 
98
  #define IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS                      IPMI_FRU_PARSE_FLAGS_SKIP_CHECKSUM_CHECKS
 
99
  #define IPMI_FRU_AREA_TYPE_BOARD_INFO_AREA                       IPMI_FRU_PARSE_AREA_TYPE_BOARD_INFO_AREA
 
100
  #define IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION  IPMI_FRU_PARSE_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION
 
101
  #define IPMI_FRU_AREA_STRING_MAX                                 IPMI_FRU_PARSE_AREA_STRING_MAX
 
102
#endif /* HAVE_FREEIPMI_11X_12X */
 
103
 
 
104
/* FIXME: freeipmi auto selects a cache based on the hostname you are
 
105
 * connecting too, but this is probably fine for you
 
106
 */
 
107
#define CACHE_LOCATION "/tmp/sdrcache"
 
108
 
 
109
/* Support functions */
 
110
static const char* libfreeipmi_getfield (uint8_t language_code,
 
111
        ipmi_fru_field_t *field);
 
112
 
 
113
static void libfreeipmi_cleanup();
 
114
 
 
115
static int libfreeipmi_get_psu_info (const void *areabuf,
 
116
        uint8_t area_length, IPMIDevice_t *ipmi_dev);
 
117
 
 
118
static int libfreeipmi_get_board_info (const void *areabuf,
 
119
        uint8_t area_length, IPMIDevice_t *ipmi_dev);
 
120
 
 
121
static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev);
 
122
 
 
123
 
 
124
/*******************************************************************************
 
125
 * Implementation
 
126
 ******************************************************************************/
 
127
int nut_ipmi_open(int ipmi_id, IPMIDevice_t *ipmi_dev)
 
128
{
 
129
        int ret = -1;
 
130
        uint8_t areabuf[IPMI_FRU_AREA_SIZE_MAX+1];
 
131
        unsigned int area_type = 0;
 
132
        unsigned int area_length = 0;
 
133
 
 
134
        upsdebugx(1, "nut-libfreeipmi: nutipmi_open()...");
 
135
 
 
136
        /* Initialize the FreeIPMI library. */
 
137
        if (!(ipmi_ctx = ipmi_ctx_create ()))
 
138
        {
 
139
                /* we have to force cleanup, since exit handler is not yet installed */
 
140
                libfreeipmi_cleanup();
 
141
                fatal_with_errno(EXIT_FAILURE, "ipmi_ctx_create");
 
142
        }
 
143
 
 
144
        if ((ret = ipmi_ctx_find_inband (ipmi_ctx,
 
145
                                NULL,
 
146
                                0, /* don't disable auto-probe */
 
147
                                0,
 
148
                                0,
 
149
                                NULL,
 
150
                                0, /* workaround flags, none by default */
 
151
                                0  /* flags */
 
152
                                )) < 0)
 
153
        {
 
154
                libfreeipmi_cleanup();
 
155
                fatalx(EXIT_FAILURE, "ipmi_ctx_find_inband: %s",
 
156
                        ipmi_ctx_errormsg (ipmi_ctx));
 
157
        }
 
158
        if (!ret)
 
159
        {
 
160
                libfreeipmi_cleanup();
 
161
                fatalx(EXIT_FAILURE, "could not find inband device");
 
162
        }
 
163
 
 
164
        upsdebugx(1, "FreeIPMI initialized...");
 
165
 
 
166
        /* Parse FRU information */
 
167
        if (!(fru_ctx = ipmi_fru_ctx_create (ipmi_ctx)))
 
168
        {
 
169
                libfreeipmi_cleanup();
 
170
                fatal_with_errno(EXIT_FAILURE, "ipmi_fru_ctx_create()");
 
171
        }
 
172
      
 
173
        /* lots of motherboards calculate checksums incorrectly */
 
174
        if (ipmi_fru_ctx_set_flags (fru_ctx, IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS) < 0)
 
175
        {
 
176
                libfreeipmi_cleanup();
 
177
                fatalx(EXIT_FAILURE, "ipmi_fru_ctx_set_flags: %s\n",
 
178
                        ipmi_fru_ctx_strerror (ipmi_fru_ctx_errnum (fru_ctx)));
 
179
        }
 
180
 
 
181
        /* Now open the requested (local) PSU */
 
182
        if (ipmi_fru_open_device_id (fru_ctx, ipmi_id) < 0)
 
183
        {
 
184
                libfreeipmi_cleanup();
 
185
                fatalx(EXIT_FAILURE, "ipmi_fru_open_device_id: %s\n",
 
186
                        ipmi_fru_ctx_errormsg (fru_ctx));
 
187
        }
 
188
 
 
189
        /* Set IPMI identifier */
 
190
        ipmi_dev->ipmi_id = ipmi_id;
 
191
 
 
192
        do
 
193
        {
 
194
                /* clear fields */
 
195
                area_type = 0;
 
196
                area_length = 0;
 
197
                memset (areabuf, '\0', IPMI_FRU_AREA_SIZE_MAX + 1);
 
198
 
 
199
                /* parse FRU buffer */
 
200
                if (ipmi_fru_read_data_area (fru_ctx,
 
201
                                                                                        &area_type,
 
202
                                                                                        &area_length,
 
203
                                                                                        areabuf,
 
204
                                                                                        IPMI_FRU_AREA_SIZE_MAX) < 0)
 
205
                {
 
206
                        libfreeipmi_cleanup();
 
207
                        fatal_with_errno(EXIT_FAILURE, 
 
208
                                "ipmi_fru_read_data_area: %s\n",
 
209
                                ipmi_fru_ctx_errormsg (fru_ctx));
 
210
                }
 
211
 
 
212
                if (area_length)
 
213
                {
 
214
                        switch (area_type)
 
215
                        {
 
216
                                /* get generic board information */
 
217
                                case IPMI_FRU_AREA_TYPE_BOARD_INFO_AREA:
 
218
 
 
219
                                        if(libfreeipmi_get_board_info (areabuf, area_length,
 
220
                                                ipmi_dev) < 0)
 
221
                                        {
 
222
                                                upsdebugx(1, "Can't retrieve board information");
 
223
                                        }
 
224
                                        break;
 
225
                                /* get specific PSU information */
 
226
                                case IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION:
 
227
 
 
228
                                        if(libfreeipmi_get_psu_info (areabuf, area_length, ipmi_dev) < 0)
 
229
                                        {
 
230
                                                upsdebugx(1, "Can't retrieve PSU information");
 
231
                                        }
 
232
                                        break;
 
233
                                default:
 
234
                                        upsdebugx (5, "FRU: discarding FRU Area Type Read: %02Xh", area_type);
 
235
                                        break;
 
236
                        }
 
237
                }
 
238
        } while ((ret = ipmi_fru_next (fru_ctx)) == 1);
 
239
 
 
240
        /* check for errors */
 
241
        if (ret < 0) {
 
242
                libfreeipmi_cleanup();
 
243
                fatal_with_errno(EXIT_FAILURE, "ipmi_fru_next: %s",
 
244
                        ipmi_fru_ctx_errormsg (fru_ctx));
 
245
        }
 
246
        else {
 
247
                /* Get all related sensors information */
 
248
                libfreeipmi_get_sensors_info (ipmi_dev);
 
249
        }
 
250
 
 
251
        /* cleanup context */
 
252
        libfreeipmi_cleanup();
 
253
 
 
254
        return (0);
 
255
}
 
256
 
 
257
void nut_ipmi_close(void)
 
258
{
 
259
        upsdebugx(1, "nutipmi_close...");
 
260
 
 
261
        libfreeipmi_cleanup();
 
262
}
 
263
 
 
264
static const char* libfreeipmi_getfield (uint8_t language_code,
 
265
                                                                        ipmi_fru_field_t *field)
 
266
{
 
267
        static char strbuf[IPMI_FRU_AREA_STRING_MAX + 1];
 
268
        unsigned int strbuflen = IPMI_FRU_AREA_STRING_MAX;
 
269
 
 
270
        if (!field->type_length_field_length)
 
271
                return NULL;
 
272
 
 
273
        memset (strbuf, '\0', IPMI_FRU_AREA_STRING_MAX + 1);
 
274
 
 
275
        if (ipmi_fru_type_length_field_to_string (fru_ctx,
 
276
                                                                                                        field->type_length_field,
 
277
                                                                                                        field->type_length_field_length,
 
278
                                                                                                        language_code,
 
279
                                                                                                        strbuf,
 
280
                                                                                                        &strbuflen) < 0)
 
281
                {
 
282
                        upsdebugx (2, "ipmi_fru_type_length_field_to_string: %s",
 
283
                                ipmi_fru_ctx_errormsg (fru_ctx));
 
284
                        return NULL;
 
285
                }
 
286
 
 
287
        if (strbuflen)
 
288
                return strbuf;
 
289
 
 
290
  return NULL;
 
291
}
 
292
 
 
293
/* Get voltage value from the IPMI voltage code */
 
294
static float libfreeipmi_get_voltage (uint8_t voltage_code)
 
295
{
 
296
  if (voltage_code == IPMI_FRU_VOLTAGE_12V)
 
297
    return 12;
 
298
  else if (voltage_code == IPMI_FRU_VOLTAGE_MINUS12V)
 
299
    return -12;
 
300
  else if (voltage_code == IPMI_FRU_VOLTAGE_5V)
 
301
    return 5;
 
302
  else if (voltage_code == IPMI_FRU_VOLTAGE_3_3V)
 
303
    return 3.3;
 
304
  else
 
305
    return 0;
 
306
}
 
307
 
 
308
/* Cleanup IPMI contexts */
 
309
static void libfreeipmi_cleanup()
 
310
{
 
311
        /* cleanup */
 
312
        if (fru_ctx) {
 
313
                ipmi_fru_close_device_id (fru_ctx);
 
314
                ipmi_fru_ctx_destroy (fru_ctx);
 
315
        }
 
316
 
 
317
        if (sdr_ctx) {
 
318
                ipmi_sdr_ctx_destroy (sdr_ctx);
 
319
        }
 
320
 
 
321
#ifndef HAVE_FREEIPMI_11X_12X
 
322
        if (sdr_parse_ctx) {
 
323
                ipmi_sdr_parse_ctx_destroy (sdr_parse_ctx);
 
324
        }
 
325
#endif
 
326
 
 
327
        if (ipmi_ctx) {
 
328
                ipmi_ctx_close (ipmi_ctx);
 
329
                ipmi_ctx_destroy (ipmi_ctx);
 
330
        }
 
331
 
 
332
        if (mon_ctx) {
 
333
                ipmi_monitoring_ctx_destroy (mon_ctx);
 
334
        }
 
335
}
 
336
 
 
337
/* Get generic board information (manufacturer and model names, serial, ...)
 
338
 * from IPMI FRU */
 
339
static int libfreeipmi_get_psu_info (const void *areabuf,
 
340
                                                                                uint8_t area_length,
 
341
                                                                                IPMIDevice_t *ipmi_dev)
 
342
{
 
343
        /* FIXME: directly use ipmi_dev fields */
 
344
        unsigned int overall_capacity;
 
345
        unsigned int low_end_input_voltage_range_1;
 
346
        unsigned int high_end_input_voltage_range_1;
 
347
        unsigned int low_end_input_frequency_range;
 
348
        unsigned int high_end_input_frequency_range;
 
349
        unsigned int voltage_1;
 
350
 
 
351
        /* FIXME: check for the interest and capability to use these data */
 
352
        unsigned int peak_va;
 
353
        unsigned int inrush_current;
 
354
        unsigned int inrush_interval;
 
355
        unsigned int low_end_input_voltage_range_2;
 
356
        unsigned int high_end_input_voltage_range_2;
 
357
        unsigned int ac_dropout_tolerance;
 
358
        unsigned int predictive_fail_support;
 
359
        unsigned int power_factor_correction;
 
360
        unsigned int autoswitch;
 
361
        unsigned int hot_swap_support;
 
362
        unsigned int tachometer_pulses_per_rotation_predictive_fail_polarity;
 
363
        unsigned int peak_capacity;
 
364
        unsigned int hold_up_time;
 
365
        unsigned int voltage_2;
 
366
        unsigned int total_combined_wattage;
 
367
        unsigned int predictive_fail_tachometer_lower_threshold;
 
368
 
 
369
        upsdebugx(1, "entering libfreeipmi_get_psu_info()");
 
370
 
 
371
        if (ipmi_fru_multirecord_power_supply_information (fru_ctx,
 
372
                        areabuf,
 
373
                        area_length,
 
374
                        &overall_capacity,
 
375
                        &peak_va,
 
376
                        &inrush_current,
 
377
                        &inrush_interval,
 
378
                        &low_end_input_voltage_range_1,
 
379
                        &high_end_input_voltage_range_1,
 
380
                        &low_end_input_voltage_range_2,
 
381
                        &high_end_input_voltage_range_2,
 
382
                        &low_end_input_frequency_range,
 
383
                        &high_end_input_frequency_range,
 
384
                        &ac_dropout_tolerance,
 
385
                        &predictive_fail_support,
 
386
                        &power_factor_correction,
 
387
                        &autoswitch,
 
388
                        &hot_swap_support,
 
389
                        &tachometer_pulses_per_rotation_predictive_fail_polarity,
 
390
                        &peak_capacity,
 
391
                        &hold_up_time,
 
392
                        &voltage_1,
 
393
                        &voltage_2,
 
394
                        &total_combined_wattage,
 
395
                        &predictive_fail_tachometer_lower_threshold) < 0)
 
396
        {
 
397
                fatalx(EXIT_FAILURE, "ipmi_fru_multirecord_power_supply_information: %s",
 
398
                        ipmi_fru_ctx_errormsg (fru_ctx));
 
399
        }
 
400
 
 
401
        ipmi_dev->overall_capacity = overall_capacity;
 
402
 
 
403
        /* Voltages are in mV! */
 
404
        ipmi_dev->input_minvoltage = low_end_input_voltage_range_1 / 1000;
 
405
        ipmi_dev->input_maxvoltage = high_end_input_voltage_range_1 / 1000;
 
406
 
 
407
        ipmi_dev->input_minfreq = low_end_input_frequency_range;
 
408
        ipmi_dev->input_maxfreq = high_end_input_frequency_range;
 
409
 
 
410
        ipmi_dev->voltage = libfreeipmi_get_voltage(voltage_1);
 
411
 
 
412
        upsdebugx(1, "libfreeipmi_get_psu_info() retrieved successfully");
 
413
 
 
414
        return (0);
 
415
}
 
416
 
 
417
/* Get specific PSU information from IPMI FRU */
 
418
static int libfreeipmi_get_board_info (const void *areabuf,
 
419
        uint8_t area_length, IPMIDevice_t *ipmi_dev)
 
420
{
 
421
        uint8_t language_code;
 
422
        uint32_t mfg_date_time;
 
423
        ipmi_fru_field_t board_manufacturer;
 
424
        ipmi_fru_field_t board_product_name;
 
425
        ipmi_fru_field_t board_serial_number;
 
426
        ipmi_fru_field_t board_part_number;
 
427
        ipmi_fru_field_t board_fru_file_id;
 
428
        ipmi_fru_field_t board_custom_fields[IPMI_FRU_CUSTOM_FIELDS];
 
429
        const char *string = NULL;
 
430
        time_t timetmp;
 
431
        struct tm mfg_date_time_tm;
 
432
        char mfg_date_time_buf[IPMI_FRU_STR_BUFLEN + 1];
 
433
 
 
434
        upsdebugx(1, "entering libfreeipmi_get_board_info()");
 
435
 
 
436
        /* clear fields */
 
437
        memset (&board_manufacturer, '\0', sizeof (ipmi_fru_field_t));
 
438
        memset (&board_product_name, '\0', sizeof (ipmi_fru_field_t));
 
439
        memset (&board_serial_number, '\0', sizeof (ipmi_fru_field_t));
 
440
        memset (&board_fru_file_id, '\0', sizeof (ipmi_fru_field_t));
 
441
        memset (&board_custom_fields[0], '\0',
 
442
                        sizeof (ipmi_fru_field_t) * IPMI_FRU_CUSTOM_FIELDS);
 
443
 
 
444
        /* parse FRU buffer */
 
445
        if (ipmi_fru_board_info_area (fru_ctx,
 
446
                        areabuf,
 
447
                        area_length,
 
448
                        &language_code,
 
449
                        &mfg_date_time,
 
450
                        &board_manufacturer,
 
451
                        &board_product_name,
 
452
                        &board_serial_number,
 
453
                        &board_part_number,
 
454
                        &board_fru_file_id,
 
455
                        board_custom_fields,
 
456
                        IPMI_FRU_CUSTOM_FIELDS) < 0)
 
457
        {
 
458
                libfreeipmi_cleanup();
 
459
                fatalx(EXIT_FAILURE, "ipmi_fru_board_info_area: %s",
 
460
                        ipmi_fru_ctx_errormsg (fru_ctx));
 
461
        }
 
462
 
 
463
 
 
464
        if (IPMI_FRU_LANGUAGE_CODE_VALID (language_code)) {
 
465
                upsdebugx (5, "FRU Board Language: %s", ipmi_fru_language_codes[language_code]);
 
466
        }
 
467
        else {
 
468
                upsdebugx (5, "FRU Board Language Code: %02Xh", language_code);
 
469
        }
 
470
 
 
471
        /* Posix says individual calls need not clear/set all portions of
 
472
         * 'struct tm', thus passing 'struct tm' between functions could
 
473
         * have issues.  So we need to memset */
 
474
        memset (&mfg_date_time_tm, '\0', sizeof (struct tm));
 
475
        timetmp = mfg_date_time;
 
476
        localtime_r (&timetmp, &mfg_date_time_tm);
 
477
        memset (mfg_date_time_buf, '\0', IPMI_FRU_STR_BUFLEN + 1);
 
478
        strftime (mfg_date_time_buf, IPMI_FRU_STR_BUFLEN, "%D - %T", &mfg_date_time_tm);
 
479
 
 
480
        /* Store values */
 
481
        ipmi_dev->date = xstrdup(mfg_date_time_buf);
 
482
        upsdebugx(2, "FRU Board Manufacturing Date/Time: %s", ipmi_dev->date);
 
483
 
 
484
        if ((string = libfreeipmi_getfield (language_code, &board_manufacturer)) != NULL)
 
485
                ipmi_dev->manufacturer = xstrdup(string);
 
486
        else
 
487
                ipmi_dev->manufacturer = xstrdup("Generic IPMI manufacturer");
 
488
 
 
489
        if ((string = libfreeipmi_getfield (language_code, &board_product_name)) != NULL)
 
490
                ipmi_dev->product = xstrdup(string);
 
491
        else
 
492
                ipmi_dev->product = xstrdup("Generic PSU");
 
493
 
 
494
        if ((string = libfreeipmi_getfield (language_code, &board_serial_number)) != NULL)
 
495
                ipmi_dev->serial = xstrdup(string);
 
496
        else
 
497
                ipmi_dev->serial = NULL;
 
498
 
 
499
        if ((string = libfreeipmi_getfield (language_code, &board_part_number)) != NULL)
 
500
                ipmi_dev->part = xstrdup(string);
 
501
        else
 
502
                ipmi_dev->part = NULL;
 
503
 
 
504
        return (0);
 
505
}
 
506
 
 
507
 
 
508
/* Get the sensors list & values, specific to the given FRU ID
 
509
 * Return -1 on error, or the number of sensors found otherwise */
 
510
static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev)
 
511
{
 
512
        uint8_t sdr_record[IPMI_SDR_MAX_RECORD_LENGTH];
 
513
        uint8_t record_type, logical_physical_fru_device, logical_fru_device_device_slave_address;
 
514
        uint8_t tmp_entity_id, tmp_entity_instance;
 
515
        int sdr_record_len;
 
516
        uint16_t record_count;
 
517
        int found_device_id = 0;
 
518
        uint16_t record_id;
 
519
        uint8_t entity_id, entity_instance;
 
520
        int i;
 
521
 
 
522
        if (ipmi_ctx == NULL)
 
523
                return (-1);
 
524
 
 
525
        /* Clear the sensors list */
 
526
        ipmi_dev->sensors_count = 0;
 
527
        memset(ipmi_dev->sensors_id_list, 0, sizeof(ipmi_dev->sensors_id_list));
 
528
 
 
529
        if (!(sdr_ctx = ipmi_sdr_ctx_create ()))
 
530
        {
 
531
                libfreeipmi_cleanup();
 
532
                fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_ctx_create()");
 
533
        }
 
534
 
 
535
#ifndef HAVE_FREEIPMI_11X_12X
 
536
        if (!(sdr_parse_ctx = ipmi_sdr_parse_ctx_create ()))
 
537
        {
 
538
                libfreeipmi_cleanup();
 
539
                fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_parse_ctx_create()");
 
540
        }
 
541
#endif
 
542
 
 
543
        if (ipmi_sdr_cache_open (sdr_ctx, ipmi_ctx, CACHE_LOCATION) < 0)
 
544
        {
 
545
                if (ipmi_sdr_ctx_errnum (sdr_ctx) != IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST)
 
546
                {
 
547
                        libfreeipmi_cleanup();
 
548
                        fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_open: %s",
 
549
                                ipmi_sdr_ctx_errormsg (sdr_ctx));
 
550
                }
 
551
        }
 
552
 
 
553
        if (ipmi_sdr_ctx_errnum (sdr_ctx) == IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST)
 
554
        {
 
555
                if (ipmi_sdr_cache_create (sdr_ctx,
 
556
                                 ipmi_ctx, CACHE_LOCATION,
 
557
                                 IPMI_SDR_CACHE_CREATE_FLAGS_DEFAULT,
 
558
#ifndef HAVE_FREEIPMI_11X_12X
 
559
                                 IPMI_SDR_CACHE_VALIDATION_FLAGS_DEFAULT,
 
560
#endif
 
561
                                 NULL, NULL) < 0)
 
562
                {
 
563
                        libfreeipmi_cleanup();
 
564
                        fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_create: %s",
 
565
                                ipmi_sdr_ctx_errormsg (sdr_ctx));
 
566
                }
 
567
                if (ipmi_sdr_cache_open (sdr_ctx, ipmi_ctx, CACHE_LOCATION) < 0)
 
568
                {
 
569
                        if (ipmi_sdr_ctx_errnum (sdr_ctx) != IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST)
 
570
                        {
 
571
                                libfreeipmi_cleanup();
 
572
                                fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_open: %s",
 
573
                                        ipmi_sdr_ctx_errormsg (sdr_ctx));
 
574
                        }
 
575
                }
 
576
        }
 
577
 
 
578
        if (ipmi_sdr_cache_record_count (sdr_ctx, &record_count) < 0) {
 
579
                fprintf (stderr,
 
580
                        "ipmi_sdr_cache_record_count: %s\n",
 
581
                        ipmi_sdr_ctx_errormsg (sdr_ctx));
 
582
                goto cleanup;
 
583
        }
 
584
 
 
585
        upsdebugx(3, "Found %i records in SDR cache", record_count);
 
586
 
 
587
        for (i = 0; i < record_count; i++, ipmi_sdr_cache_next (sdr_ctx))
 
588
        {
 
589
                memset (sdr_record, '\0', IPMI_SDR_MAX_RECORD_LENGTH);
 
590
 
 
591
                if ((sdr_record_len = ipmi_sdr_cache_record_read (sdr_ctx,
 
592
                                sdr_record,
 
593
                                IPMI_SDR_MAX_RECORD_LENGTH)) < 0)
 
594
                {
 
595
                        fprintf (stderr, "ipmi_sdr_cache_record_read: %s\n",
 
596
                                ipmi_sdr_ctx_errormsg (sdr_ctx));
 
597
                        goto cleanup;
 
598
                }
 
599
                if (ipmi_sdr_parse_record_id_and_type (SDR_PARSE_CTX,
 
600
                                sdr_record,
 
601
                                sdr_record_len,
 
602
                                NULL,
 
603
                                &record_type) < 0)
 
604
                {
 
605
                        fprintf (stderr, "ipmi_sdr_parse_record_id_and_type: %s\n",
 
606
                                ipmi_sdr_ctx_errormsg (sdr_ctx));
 
607
                        goto cleanup;
 
608
                }
 
609
 
 
610
                upsdebugx (5, "Checking record %i (/%i)", i, record_count);
 
611
 
 
612
                if (record_type != IPMI_SDR_FORMAT_FRU_DEVICE_LOCATOR_RECORD) {
 
613
                        upsdebugx(1, "=======> not device locator (%i)!!", record_type);
 
614
                        continue;
 
615
                }
 
616
 
 
617
                if (ipmi_sdr_parse_fru_device_locator_parameters (SDR_PARSE_CTX,
 
618
                                sdr_record,
 
619
                                sdr_record_len,
 
620
                                NULL,
 
621
                                &logical_fru_device_device_slave_address,
 
622
                                NULL,
 
623
                                NULL,
 
624
                                &logical_physical_fru_device,
 
625
                                NULL) < 0)
 
626
                {
 
627
                        fprintf (stderr, "ipmi_sdr_parse_fru_device_locator_parameters: %s\n",
 
628
                                ipmi_sdr_ctx_errormsg (sdr_ctx));
 
629
                        goto cleanup;
 
630
                }
 
631
 
 
632
                upsdebugx(2, "Checking device %i/%i", logical_physical_fru_device,
 
633
                                        logical_fru_device_device_slave_address);
 
634
 
 
635
                if (logical_physical_fru_device
 
636
                        && logical_fru_device_device_slave_address == ipmi_dev->ipmi_id)
 
637
                {
 
638
                        found_device_id++;
 
639
 
 
640
                        if (ipmi_sdr_parse_fru_entity_id_and_instance (SDR_PARSE_CTX,
 
641
                                        sdr_record,
 
642
                                        sdr_record_len,
 
643
                                        &entity_id,
 
644
                                        &entity_instance) < 0)
 
645
                        {
 
646
                                fprintf (stderr,
 
647
                                        "ipmi_sdr_parse_fru_entity_id_and_instance: %s\n",
 
648
                                        ipmi_sdr_ctx_errormsg (sdr_ctx));
 
649
                                goto cleanup;
 
650
                        }
 
651
                        break;
 
652
                }
 
653
        }
 
654
 
 
655
        if (!found_device_id)
 
656
        {
 
657
                fprintf (stderr, "Couldn't find device id %d\n", ipmi_dev->ipmi_id);
 
658
                goto cleanup;
 
659
        }
 
660
        else
 
661
                upsdebugx(1, "Found device id %d", ipmi_dev->ipmi_id);
 
662
 
 
663
        if (ipmi_sdr_cache_first (sdr_ctx) < 0)
 
664
        {
 
665
                fprintf (stderr, "ipmi_sdr_cache_first: %s\n", 
 
666
                        ipmi_sdr_ctx_errormsg (sdr_ctx));
 
667
                goto cleanup;
 
668
        }
 
669
 
 
670
        for (i = 0; i < record_count; i++, ipmi_sdr_cache_next (sdr_ctx))
 
671
        {
 
672
                /* uint8_t sdr_record[IPMI_SDR_CACHE_MAX_SDR_RECORD_LENGTH];
 
673
                uint8_t record_type, tmp_entity_id, tmp_entity_instance;
 
674
                int sdr_record_len; */
 
675
 
 
676
                memset (sdr_record, '\0', IPMI_SDR_MAX_RECORD_LENGTH);
 
677
                if ((sdr_record_len = ipmi_sdr_cache_record_read (sdr_ctx,
 
678
                                sdr_record,
 
679
                                IPMI_SDR_MAX_RECORD_LENGTH)) < 0)
 
680
                {
 
681
                        fprintf (stderr, "ipmi_sdr_cache_record_read: %s\n",
 
682
                                ipmi_sdr_ctx_errormsg (sdr_ctx));
 
683
                        goto cleanup;
 
684
                }
 
685
 
 
686
                if (ipmi_sdr_parse_record_id_and_type (SDR_PARSE_CTX,
 
687
                                sdr_record,
 
688
                                sdr_record_len,
 
689
                                &record_id,
 
690
                                &record_type) < 0)
 
691
                {
 
692
                        fprintf (stderr, "ipmi_sdr_parse_record_id_and_type: %s\n",
 
693
                                ipmi_sdr_ctx_errormsg (sdr_ctx));
 
694
                        goto cleanup;
 
695
                }
 
696
 
 
697
                upsdebugx (5, "Checking record %i (/%i)", record_id, record_count);
 
698
 
 
699
                if (record_type != IPMI_SDR_FORMAT_FULL_SENSOR_RECORD
 
700
                        && record_type != IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD
 
701
                        && record_type != IPMI_SDR_FORMAT_EVENT_ONLY_RECORD) {
 
702
                        continue;
 
703
                }
 
704
 
 
705
                if (ipmi_sdr_parse_entity_id_instance_type (SDR_PARSE_CTX,
 
706
                                sdr_record,
 
707
                                sdr_record_len,
 
708
                                &tmp_entity_id,
 
709
                                &tmp_entity_instance,
 
710
                                NULL) < 0)
 
711
                {
 
712
                        fprintf (stderr, "ipmi_sdr_parse_entity_instance_type: %s\n",
 
713
                                ipmi_sdr_ctx_errormsg (sdr_ctx));
 
714
                        goto cleanup;
 
715
                }
 
716
 
 
717
                if (tmp_entity_id == entity_id
 
718
                        && tmp_entity_instance == entity_instance)
 
719
                {
 
720
                        upsdebugx (1, "Found record id = %u for device id %u",
 
721
                                record_id, ipmi_dev->ipmi_id);
 
722
 
 
723
                        /* Add it to the tracked list */
 
724
                        ipmi_dev->sensors_id_list[ipmi_dev->sensors_count] = record_id;
 
725
                        ipmi_dev->sensors_count++;
 
726
                }
 
727
        }
 
728
 
 
729
 
 
730
cleanup:
 
731
        /* Cleanup */
 
732
        if (sdr_ctx) {
 
733
                ipmi_sdr_ctx_destroy (sdr_ctx);
 
734
        }
 
735
 
 
736
#ifndef HAVE_FREEIPMI_11X_12X
 
737
        if (sdr_parse_ctx) {
 
738
                ipmi_sdr_parse_ctx_destroy (sdr_parse_ctx);
 
739
        }
 
740
#endif /* HAVE_FREEIPMI_11X_12X */
 
741
 
 
742
        return ipmi_dev->sensors_count;
 
743
}
 
744
 
 
745
 
 
746
/*
 
747
=> Nominal conditions
 
748
 
 
749
 
 
750
Record ID, Sensor Name, Sensor Number, Sensor Type, Sensor State, Sensor Reading, Sensor Units, Sensor Event/Reading Type Code, Sensor Event Bitmask, Sensor Event String
 
751
52, Presence, 84, Entity Presence, Nominal, N/A, N/A, 6Fh, 1h, 'Entity Present'
 
752
57, Status, 100, Power Supply, Nominal, N/A, N/A, 6Fh, 1h, 'Presence detected'
 
753
116, Current, 148, Current, Nominal, 0.20, A, 1h, C0h, 'OK'
 
754
118, Voltage, 150, Voltage, Nominal, 236.00, V, 1h, C0h, 'OK'
 
755
 
 
756
=> Power failure conditions
 
757
 
 
758
Record ID, Sensor Name, Sensor Number, Sensor Type, Sensor State, Sensor Reading, Sensor Units, Sensor Event/Reading Type Code, Sensor Event Bitmask, Sensor Event String
 
759
52, Presence, 84, Entity Presence, Nominal, N/A, N/A, 6Fh, 1h, 'Entity Present'
 
760
57, Status, 100, Power Supply, Critical, N/A, N/A, 6Fh, 9h, 'Presence detected' 'Power Supply input lost (AC/DC)'
 
761
 
 
762
=> PSU removed
 
763
 
 
764
Record ID, Sensor Name, Sensor Number, Sensor Type, Sensor State, Sensor Reading, Sensor Units, Sensor Event/Reading Type Code, Sensor Event Bitmask, Sensor Event String
 
765
52, Presence, 84, Entity Presence, Critical, N/A, N/A, 6Fh, 2h, 'Entity Absent'
 
766
57, Status, 100, Power Supply, Critical, N/A, N/A, 6Fh, 8h, 'Power Supply input lost (AC/DC)'
 
767
 
 
768
*/
 
769
 
 
770
int nut_ipmi_monitoring_init()
 
771
{
 
772
        int errnum;
 
773
 
 
774
        if (ipmi_monitoring_init (0, &errnum) < 0) {
 
775
                upsdebugx (1, "ipmi_monitoring_init() error: %s", ipmi_monitoring_ctx_strerror (errnum));
 
776
                return -1;
 
777
        }
 
778
 
 
779
        if (!(mon_ctx = ipmi_monitoring_ctx_create ())) {
 
780
                upsdebugx (1, "ipmi_monitoring_ctx_create() failed");
 
781
                return -1;
 
782
        }
 
783
 
 
784
#if HAVE_FREEIPMI_MONITORING
 
785
        /* FIXME: replace "/tmp" by a proper place, using mkdtemp() or similar */
 
786
        if (ipmi_monitoring_ctx_sdr_cache_directory (mon_ctx, "/tmp") < 0) {
 
787
                upsdebugx (1, "ipmi_monitoring_ctx_sdr_cache_directory() error: %s",
 
788
                                        ipmi_monitoring_ctx_errormsg (mon_ctx));
 
789
                return -1;
 
790
        }
 
791
 
 
792
        if (ipmi_monitoring_ctx_sensor_config_file (mon_ctx, NULL) < 0) {
 
793
                upsdebugx (1, "ipmi_monitoring_ctx_sensor_config_file() error: %s",
 
794
                                        ipmi_monitoring_ctx_errormsg (mon_ctx));
 
795
                return -1;
 
796
        }
 
797
#endif /* HAVE_FREEIPMI_MONITORING */
 
798
 
 
799
        return 0;
 
800
}
 
801
 
 
802
int nut_ipmi_get_sensors_status(IPMIDevice_t *ipmi_dev)
 
803
{
 
804
        int retval = -1;
 
805
 
 
806
#if HAVE_FREEIPMI_MONITORING
 
807
        /* It seems we don't need more! */
 
808
        unsigned int sensor_reading_flags = IPMI_MONITORING_SENSOR_READING_FLAGS_IGNORE_NON_INTERPRETABLE_SENSORS;
 
809
        int sensor_count, i, str_count;
 
810
        int psu_status = PSU_STATUS_UNKNOWN;
 
811
 
 
812
        if (mon_ctx == NULL) {
 
813
                upsdebugx (1, "Monitoring context not initialized!");
 
814
                return -1;
 
815
        }
 
816
 
 
817
        /* Monitor only the list of sensors found previously */
 
818
        if ((sensor_count = ipmi_monitoring_sensor_readings_by_record_id (mon_ctx,
 
819
                                                                                                                                                NULL, /* hostname is NULL for In-band communication */
 
820
                                                                                                                                                NULL, /* FIXME: needed? ipmi_config */
 
821
                                                                                                                                                sensor_reading_flags,
 
822
                                                                                                                                                ipmi_dev->sensors_id_list,
 
823
                                                                                                                                                ipmi_dev->sensors_count,
 
824
                                                                                                                                                NULL,
 
825
                                                                                                                                                NULL)) < 0)
 
826
        {
 
827
                upsdebugx (1, "ipmi_monitoring_sensor_readings_by_record_id() error: %s",
 
828
                                        ipmi_monitoring_ctx_errormsg (mon_ctx));
 
829
                return -1;
 
830
        }
 
831
 
 
832
        upsdebugx (1, "nut_ipmi_get_sensors_status: %i sensors to check", sensor_count);
 
833
 
 
834
        for (i = 0; i < sensor_count; i++, ipmi_monitoring_sensor_iterator_next (mon_ctx))
 
835
        {
 
836
                int record_id, sensor_type;
 
837
                int sensor_bitmask_type = -1;
 
838
                /* int sensor_reading_type, sensor_state; */
 
839
                char **sensor_bitmask_strings = NULL;
 
840
                void *sensor_reading = NULL;
 
841
 
 
842
                if ((record_id = ipmi_monitoring_sensor_read_record_id (mon_ctx)) < 0)
 
843
                {
 
844
                        upsdebugx (1, "ipmi_monitoring_sensor_read_record_id() error: %s",
 
845
                                                ipmi_monitoring_ctx_errormsg (mon_ctx));
 
846
                        continue;
 
847
                }
 
848
 
 
849
                if ((sensor_type = ipmi_monitoring_sensor_read_sensor_type (mon_ctx)) < 0)
 
850
                {
 
851
                        upsdebugx (1, "ipmi_monitoring_sensor_read_sensor_type() error: %s",
 
852
                                                ipmi_monitoring_ctx_errormsg (mon_ctx));
 
853
                        continue;
 
854
                }
 
855
 
 
856
                upsdebugx (1, "checking sensor #%i, type %i", record_id, sensor_type);
 
857
 
 
858
                /* should we consider this for ALARM?
 
859
                 * IPMI_MONITORING_STATE_NOMINAL
 
860
                 * IPMI_MONITORING_STATE_WARNING
 
861
                 * IPMI_MONITORING_STATE_CRITICAL
 
862
                 * if ((sensor_state = ipmi_monitoring_sensor_read_sensor_state (mon_ctx)) < 0)
 
863
                 * ... */
 
864
 
 
865
                if ((sensor_reading = ipmi_monitoring_sensor_read_sensor_reading (mon_ctx)) < 0)
 
866
                {
 
867
                        upsdebugx (1, "ipmi_monitoring_sensor_read_sensor_reading() error: %s",
 
868
                                                ipmi_monitoring_ctx_errormsg (mon_ctx));
 
869
                }
 
870
 
 
871
                /* This can be needed to interpret sensor_reading format!
 
872
                if ((sensor_reading_type = ipmi_monitoring_sensor_read_sensor_reading_type (ctx)) < 0)
 
873
                {
 
874
                        upsdebugx (1, "ipmi_monitoring_sensor_read_sensor_reading_type() error: %s",
 
875
                                                ipmi_monitoring_ctx_errormsg (mon_ctx));
 
876
                } */
 
877
 
 
878
                if ((sensor_bitmask_type = ipmi_monitoring_sensor_read_sensor_bitmask_type (mon_ctx)) < 0)
 
879
                {
 
880
                        upsdebugx (1, "ipmi_monitoring_sensor_read_sensor_bitmask_type() error: %s",
 
881
                                                ipmi_monitoring_ctx_errormsg (mon_ctx));
 
882
                        continue;
 
883
                }
 
884
 
 
885
                if ((sensor_bitmask_strings = ipmi_monitoring_sensor_read_sensor_bitmask_strings (mon_ctx)) < 0)
 
886
                {
 
887
                        upsdebugx (1, "ipmi_monitoring_sensor_read_sensor_bitmask_strings() error: %s",
 
888
                                                ipmi_monitoring_ctx_errormsg (mon_ctx));
 
889
                        continue;
 
890
                }
 
891
 
 
892
                /* Only the few possibly interesting sensors are considered */
 
893
                switch (sensor_type)
 
894
                {
 
895
                        case IPMI_MONITORING_SENSOR_TYPE_TEMPERATURE:
 
896
                                ipmi_dev->temperature = *((double *)sensor_reading);
 
897
                                upsdebugx (3, "Temperature: %.2f", *((double *)sensor_reading));
 
898
                                dstate_setinfo("ambient.temperature", "%.2f", *((double *)sensor_reading));
 
899
                                retval = 0;
 
900
                                break;
 
901
                        case IPMI_MONITORING_SENSOR_TYPE_VOLTAGE:
 
902
                                ipmi_dev->voltage =  *((double *)sensor_reading);
 
903
                                upsdebugx (3, "Voltage: %.2f", *((double *)sensor_reading));
 
904
                                dstate_setinfo("input.voltage", "%.2f", *((double *)sensor_reading));
 
905
                                retval = 0;
 
906
                                break;
 
907
                        case IPMI_MONITORING_SENSOR_TYPE_CURRENT:
 
908
                                ipmi_dev->input_current = *((double *)sensor_reading);
 
909
                                upsdebugx (3, "Current: %.2f", *((double *)sensor_reading));
 
910
                                dstate_setinfo("input.current", "%.2f", *((double *)sensor_reading));
 
911
                                retval = 0;
 
912
                                break;
 
913
 
 
914
                        case IPMI_MONITORING_SENSOR_TYPE_POWER_SUPPLY:
 
915
                                /* Possible values:
 
916
                                 * 'Presence detected'
 
917
                                 * 'Power Supply input lost (AC/DC)' => maps to status:OFF */
 
918
                                upsdebugx (3, "Power Supply: status string");
 
919
                                if (sensor_bitmask_type == IPMI_MONITORING_SENSOR_BITMASK_TYPE_UNKNOWN) {
 
920
                                        upsdebugx(3, "No status string");
 
921
                                }
 
922
                                str_count = 0;
 
923
                                while (sensor_bitmask_strings[str_count])
 
924
                                {
 
925
                                        upsdebugx (3, "\t'%s'", sensor_bitmask_strings[str_count]);
 
926
                                        if (!strncmp("Power Supply input lost (AC/DC)",
 
927
                                                        sensor_bitmask_strings[str_count],
 
928
                                                        strlen("Power Supply input lost (AC/DC)"))) {
 
929
                                                                /* Don't override PSU absence! */
 
930
                                                                if (psu_status != PSU_ABSENT) {
 
931
                                                                        psu_status = PSU_POWER_FAILURE; /* = status OFF */
 
932
                                                                }
 
933
                                        }
 
934
                                        str_count++;
 
935
                                }
 
936
                                break;
 
937
                        case IPMI_MONITORING_SENSOR_TYPE_ENTITY_PRESENCE:
 
938
                                /* Possible values:
 
939
                                 * 'Entity Present' => maps to status:OL
 
940
                                 * 'Entity Absent' (PSU has been removed!) => declare staleness */
 
941
                                upsdebugx (3, "Entity Presence: status string");
 
942
                                if (sensor_bitmask_type == IPMI_MONITORING_SENSOR_BITMASK_TYPE_UNKNOWN) {
 
943
                                        upsdebugx(3, "No status string");
 
944
                                }
 
945
                                str_count = 0;
 
946
                                while (sensor_bitmask_strings[str_count])
 
947
                                {
 
948
                                        upsdebugx (3, "\t'%s'", sensor_bitmask_strings[str_count]);
 
949
                                        if (!strncmp("Entity Present",
 
950
                                                        sensor_bitmask_strings[str_count],
 
951
                                                        strlen("Entity Present"))) {
 
952
                                                                psu_status = PSU_PRESENT;
 
953
                                        }
 
954
                                        else if (!strncmp("Entity Absent",
 
955
                                                        sensor_bitmask_strings[str_count],
 
956
                                                        strlen("Entity Absent"))) {
 
957
                                                                psu_status = PSU_ABSENT;
 
958
                                        }
 
959
                                        str_count++;
 
960
                                }
 
961
                                break;
 
962
 
 
963
                        /* Not sure of the values of these, so get as much as possible... */
 
964
                        case IPMI_MONITORING_SENSOR_TYPE_POWER_UNIT:
 
965
                                upsdebugx (3, "Power Unit: status string");
 
966
                                str_count = 0;
 
967
                                while (sensor_bitmask_strings[str_count])
 
968
                                {
 
969
                                        upsdebugx (3, "\t'%s'", sensor_bitmask_strings[str_count]);
 
970
                                        str_count++;
 
971
                                }
 
972
                                break;
 
973
                        case IPMI_MONITORING_SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE:
 
974
                                upsdebugx (3, "System ACPI Power State: status string");
 
975
                                str_count = 0;
 
976
                                while (sensor_bitmask_strings[str_count])
 
977
                                {
 
978
                                        upsdebugx (3, "\t'%s'", sensor_bitmask_strings[str_count]);
 
979
                                        str_count++;
 
980
                                }
 
981
                                break;
 
982
                        case IPMI_MONITORING_SENSOR_TYPE_BATTERY:
 
983
                                upsdebugx (3, "Battery: status string");
 
984
                                str_count = 0;
 
985
                                while (sensor_bitmask_strings[str_count])
 
986
                                {
 
987
                                        upsdebugx (3, "\t'%s'", sensor_bitmask_strings[str_count]);
 
988
                                        str_count++;
 
989
                                }
 
990
                                break;
 
991
                }
 
992
        }
 
993
        
 
994
        /* Process status if needed */
 
995
        if (psu_status != PSU_STATUS_UNKNOWN) {
 
996
 
 
997
                status_init();
 
998
 
 
999
                switch (psu_status)
 
1000
                {
 
1001
                        case PSU_PRESENT:
 
1002
                                status_set("OL");
 
1003
                                retval = 0;
 
1004
                                break;
 
1005
                        case PSU_ABSENT:
 
1006
                                status_set("OFF");
 
1007
                                /* Declare stale */
 
1008
                                retval = -1;
 
1009
                                break;
 
1010
                        case PSU_POWER_FAILURE:
 
1011
                                status_set("OFF");
 
1012
                                retval = 0;
 
1013
                                break;
 
1014
                }
 
1015
        
 
1016
                status_commit();
 
1017
        }
 
1018
#endif /* HAVE_FREEIPMI_MONITORING */
 
1019
 
 
1020
        return retval;
 
1021
}
 
1022
 
 
1023
/*
 
1024
--chassis-control=CONTROL
 
1025
              Control the chassis. This command provides power-up, power-down, and reset control. Supported values: POWER-DOWN, POWER-UP, POWER-CYCLE, HARD-RESET, DIAGNOS‐
 
1026
              TIC-INTERRUPT, SOFT-SHUTDOWN.
 
1027
*/