This source file includes following definitions.
- getStringExecOutput
- getSerialNumber
- getProductName
- con_usage
- usage
- ipmi2servicelog
- sensor_threshold_event_handler
- sensor_discrete_event_handler
- sensor_change
- entity_change
- setup_done
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include <crm_internal.h>
38
39 #ifndef _GNU_SOURCE
40 # define _GNU_SOURCE
41 #endif
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <malloc.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <fcntl.h>
50 #include <unistd.h>
51 #include <netdb.h>
52 #include <ctype.h>
53 #include <time.h>
54 #include <sys/wait.h>
55 #include <sys/utsname.h>
56
57 #include <OpenIPMI/ipmiif.h>
58 #include <OpenIPMI/ipmi_smi.h>
59 #include <OpenIPMI/ipmi_err.h>
60 #include <OpenIPMI/ipmi_auth.h>
61 #include <OpenIPMI/ipmi_lan.h>
62 #include <OpenIPMI/ipmi_posix.h>
63 #include <OpenIPMI/ipmi_fru.h>
64
65 #include <servicelog.h>
66
67 #include <crm/crm.h>
68
69 #define COMPLEX 1
70
71 static os_handler_t *os_hnd;
72
73 char *getStringExecOutput(const char *const args[]);
74 char *getSerialNumber(void);
75 char *getProductName(void);
76 static void con_usage(const char *name, const char *help, void *cb_data);
77 static void usage(const char *progname);
78 void ipmi2servicelog(struct sl_data_bmc *bmc_data);
79 static int sensor_threshold_event_handler(ipmi_sensor_t * sensor, enum ipmi_event_dir_e dir,
80 enum ipmi_thresh_e threshold,
81 enum ipmi_event_value_dir_e high_low,
82 enum ipmi_value_present_e value_present,
83 unsigned int raw_value, double value, void *cb_data,
84 ipmi_event_t * event);
85 static int sensor_discrete_event_handler(ipmi_sensor_t * sensor, enum ipmi_event_dir_e dir,
86 int offset, int severity, int prev_severity, void *cb_data,
87 ipmi_event_t * event);
88 static void sensor_change(enum ipmi_update_e op, ipmi_entity_t * ent, ipmi_sensor_t * sensor,
89 void *cb_data);
90 static void entity_change(enum ipmi_update_e op, ipmi_domain_t * domain, ipmi_entity_t * entity,
91 void *cb_data);
92 void setup_done(ipmi_domain_t * domain, int err, unsigned int conn_num, unsigned int port_num,
93 int still_connected, void *user_data);
94
95 char *
96 getStringExecOutput(const char *const args[])
97 {
98 int rc;
99 pid_t pid;
100 int pipefd[2];
101
102 rc = pipe2(pipefd, 0);
103
104 if (rc == -1) {
105
106 crm_err("Error: pipe errno = %d", errno);
107
108 return NULL;
109 }
110
111 pid = fork();
112
113 if (0 < pid) {
114
115
116 int childExitStatus;
117 char serialNumber[256];
118 ssize_t sizeRead;
119
120
121 rc = close(pipefd[1]);
122 if (rc == -1) {
123 crm_err("Error: parent close (pipefd[1]) = %d", errno);
124 }
125
126
127 rc = dup2(pipefd[0], 0);
128 if (rc == -1) {
129 crm_err("Error: parent dup2 (pipefd[0]) = %d", errno);
130 }
131
132
133 rc = close(pipefd[0]);
134 if (rc == -1) {
135 crm_err("Error: parent close (pipefd[0]) = %d", errno);
136 }
137
138 waitpid(pid, &childExitStatus, 0);
139
140 if (!WIFEXITED(childExitStatus)) {
141
142 crm_err("waitpid() exited with an error: status = %d", WEXITSTATUS(childExitStatus));
143
144 return NULL;
145
146 } else if (WIFSIGNALED(childExitStatus)) {
147
148 crm_err("waitpid() exited due to a signal = %d", WTERMSIG(childExitStatus));
149
150 return NULL;
151
152 }
153
154 memset(serialNumber, 0, sizeof(serialNumber));
155
156 sizeRead = read(0, serialNumber, sizeof(serialNumber) - 1);
157
158 if (sizeRead > 0) {
159
160 char *end = serialNumber + strlen(serialNumber) - 1;
161
162 while (end > serialNumber
163 && (*end == '\n' || *end == '\r' || *end == '\t' || *end == ' ')
164 ) {
165 *end = '\0';
166 end--;
167 }
168 return strdup(serialNumber);
169 }
170
171 return NULL;
172
173 } else if (pid == 0) {
174
175
176
177
178 rc = close(pipefd[0]);
179 if (rc == -1) {
180 crm_err("Error: child close (pipefd[0]) = %d", errno);
181 }
182
183
184 rc = dup2(pipefd[1], 1);
185 if (rc == -1) {
186 crm_err("Error: child dup2 (pipefd[1]) = %d", errno);
187 }
188
189
190 rc = close(pipefd[1]);
191 if (rc == -1) {
192 crm_err("Error: child close (pipefd[1]) = %d", errno);
193 }
194
195
196
197
198
199 rc = execvp(args[0], (char *const *) args);
200
201 if (rc == -1) {
202 crm_err("Error: child execvp = %d", errno);
203 }
204
205
206 return NULL;
207
208 } else {
209
210
211 crm_err("fork errno = %d", errno);
212
213 return NULL;
214 }
215
216 return NULL;
217 }
218
219 char *
220 getSerialNumber(void)
221 {
222 const char *const dmiArgs[] = {
223 "dmidecode",
224 "--string",
225 "system-serial-number",
226 NULL
227 };
228
229 return getStringExecOutput(dmiArgs);
230 }
231
232 char *
233 getProductName(void)
234 {
235 const char *dmiArgs[] = {
236 "dmidecode",
237 "--string",
238 "system-product-name",
239 NULL
240 };
241
242 return getStringExecOutput(dmiArgs);
243 }
244
245 static void
246 con_usage(const char *name, const char *help, void *cb_data)
247 {
248 printf("%s\n", help);
249 }
250
251 static void
252 usage(const char *progname)
253 {
254 printf("Usage:\n");
255 printf(" %s <con_parms>\n", progname);
256 printf(" Where <con_parms> is one of:\n");
257 ipmi_parse_args_iter_help(con_usage, NULL);
258 }
259
260 void
261 ipmi2servicelog(struct sl_data_bmc *bmc_data)
262 {
263 servicelog *slog = NULL;
264 struct sl_event sl_event;
265 uint64_t new_id = 0;
266 struct utsname name;
267 char *serial_number = NULL;
268 char *product_name = NULL;
269 int rc;
270
271 if (uname(&name) == -1) {
272 crm_err("Error: uname failed");
273 return;
274 }
275
276 rc = servicelog_open(&slog, 0);
277
278 if (!slog) {
279 crm_err("Error: servicelog_open failed, rc = %d", rc);
280 return;
281 }
282
283 serial_number = getSerialNumber();
284 if (serial_number) {
285 if (strlen(serial_number) > 20) {
286 serial_number[20] = '\0';
287 }
288 }
289
290 product_name = getProductName();
291 if (product_name) {
292 if (strlen(product_name) > 20) {
293 product_name[20] = '\0';
294 }
295 }
296
297 memset(&sl_event, 0, sizeof(sl_event));
298
299
300 sl_event.next = NULL;
301 sl_event.id = 0;
302 sl_event.time_logged = time (NULL);
303 sl_event.time_event = time (NULL);
304 sl_event.time_last_update = time (NULL);
305 sl_event.type = SL_TYPE_BMC;
306 sl_event.severity = SL_SEV_WARNING;
307 sl_event.platform = name.machine;
308 sl_event.machine_serial = serial_number;
309 sl_event.machine_model = product_name;
310 sl_event.nodename = name.nodename;
311 sl_event.refcode = strdup("ipmi");
312 sl_event.description = strdup("ipmi event");
313 sl_event.serviceable = 1;
314 sl_event.predictive = 0;
315 sl_event.disposition = SL_DISP_RECOVERABLE;
316 sl_event.call_home_status = SL_CALLHOME_NONE;
317
318 sl_event.closed = 1;
319 sl_event.repair = 0;
320 sl_event.callouts = NULL;
321 sl_event.raw_data_len = 0;
322 sl_event.raw_data = NULL;
323 sl_event.addl_data = &bmc_data;
324
325
326 rc = servicelog_event_log(slog, &sl_event, &new_id);
327
328 if (rc != 0) {
329 crm_err("Error: servicelog_event_log, rc = %d (\"%s\")", rc, servicelog_error(slog));
330 } else {
331 crm_debug("Sending to servicelog database");
332 }
333
334 free(sl_event.refcode);
335 free(sl_event.description);
336 free(serial_number);
337 free(product_name);
338
339 servicelog_close(slog);
340 }
341
342 static int
343 sensor_threshold_event_handler(ipmi_sensor_t * sensor,
344 enum ipmi_event_dir_e dir,
345 enum ipmi_thresh_e threshold,
346 enum ipmi_event_value_dir_e high_low,
347 enum ipmi_value_present_e value_present,
348 unsigned int raw_value,
349 double value, void *cb_data, ipmi_event_t * event)
350 {
351 ipmi_entity_t *ent = ipmi_sensor_get_entity(sensor);
352 char name[IPMI_ENTITY_NAME_LEN];
353 struct sl_data_bmc bmc_data;
354 uint32_t sel_id;
355 uint32_t sel_type;
356 uint16_t generator;
357 uint8_t version;
358 uint8_t sensor_type;
359 int sensor_lun;
360 int sensor_number;
361 uint8_t event_class;
362 uint8_t event_type;
363 int direction;
364
365 ipmi_sensor_get_id(sensor, name, sizeof(name));
366
367 ipmi_sensor_get_num(sensor, &sensor_lun, &sensor_number);
368
369 sel_id = ipmi_entity_get_entity_id(ent);
370 sel_type = ipmi_entity_get_type(ent);
371 generator = ipmi_entity_get_slave_address(ent) | (sensor_lun << 5);
372 version = 0x04;
373 sensor_type = ipmi_sensor_get_sensor_type(sensor);
374 event_class = 0;
375 event_type = ipmi_event_get_type(event);
376 direction = dir;
377
378 memset(&bmc_data, 0, sizeof(bmc_data));
379
380 bmc_data.sel_id = sel_id;
381 bmc_data.sel_type = sel_type;
382 bmc_data.generator = generator;
383 bmc_data.version = version;
384 bmc_data.sensor_type = sensor_type;
385 bmc_data.sensor_number = sensor_number;
386 bmc_data.event_class = event_class;
387 bmc_data.event_type = event_type;
388 bmc_data.direction = direction;
389
390 crm_debug("Writing bmc_data (%08x, %08x, %04x, %02x, %02x, %02x, %02x, %02x, %d)",
391 bmc_data.sel_id,
392 bmc_data.sel_type,
393 bmc_data.generator,
394 bmc_data.version,
395 bmc_data.sensor_type,
396 bmc_data.sensor_number,
397 bmc_data.event_class, bmc_data.event_type, bmc_data.direction);
398
399 ipmi2servicelog(&bmc_data);
400
401
402
403 return IPMI_EVENT_NOT_HANDLED;
404 }
405
406 static int
407 sensor_discrete_event_handler(ipmi_sensor_t * sensor,
408 enum ipmi_event_dir_e dir,
409 int offset,
410 int severity, int prev_severity, void *cb_data, ipmi_event_t * event)
411 {
412 ipmi_entity_t *ent = ipmi_sensor_get_entity(sensor);
413 char name[IPMI_ENTITY_NAME_LEN];
414 struct sl_data_bmc bmc_data;
415 uint32_t sel_id;
416 uint32_t sel_type;
417 uint16_t generator;
418 uint8_t version;
419 uint8_t sensor_type;
420 int sensor_lun;
421 int sensor_number;
422 uint8_t event_class;
423 uint8_t event_type;
424 int direction;
425
426 ipmi_sensor_get_id(sensor, name, sizeof(name));
427
428 ipmi_sensor_get_num(sensor, &sensor_lun, &sensor_number);
429
430 sel_id = ipmi_entity_get_entity_id(ent);
431 sel_type = ipmi_entity_get_type(ent);
432 generator = ipmi_entity_get_slave_address(ent) | (sensor_lun << 5);
433 version = 0x04;
434 sensor_type = ipmi_sensor_get_sensor_type(sensor);
435
436 event_class = 0;
437 event_type = ipmi_event_get_type(event);
438 direction = dir;
439
440 memset(&bmc_data, 0, sizeof(bmc_data));
441
442 bmc_data.sel_id = sel_id;
443 bmc_data.sel_type = sel_type;
444 bmc_data.generator = generator;
445 bmc_data.version = version;
446 bmc_data.sensor_type = sensor_type;
447 bmc_data.sensor_number = sensor_number;
448 bmc_data.event_class = event_class;
449 bmc_data.event_type = event_type;
450 bmc_data.direction = direction;
451
452 crm_debug("Writing bmc_data (%08x, %08x, %04x, %02x, %02x, %02x, %02x, %02x, %d)",
453 bmc_data.sel_id,
454 bmc_data.sel_type,
455 bmc_data.generator,
456 bmc_data.version,
457 bmc_data.sensor_type,
458 bmc_data.sensor_number,
459 bmc_data.event_class, bmc_data.event_type, bmc_data.direction);
460
461 ipmi2servicelog(&bmc_data);
462
463
464
465 return IPMI_EVENT_NOT_HANDLED;
466 }
467
468
469
470
471 static void
472 sensor_change(enum ipmi_update_e op, ipmi_entity_t * ent, ipmi_sensor_t * sensor, void *cb_data)
473 {
474 int rv;
475
476 if (op == IPMI_ADDED) {
477 if (ipmi_sensor_get_event_reading_type(sensor) == IPMI_EVENT_READING_TYPE_THRESHOLD)
478 rv = ipmi_sensor_add_threshold_event_handler(sensor,
479 sensor_threshold_event_handler, NULL);
480 else
481 rv = ipmi_sensor_add_discrete_event_handler(sensor,
482 sensor_discrete_event_handler, NULL);
483 if (rv)
484 crm_err("Unable to add the sensor event handler: %x", rv);
485 }
486 }
487
488
489
490
491 static void
492 entity_change(enum ipmi_update_e op, ipmi_domain_t * domain, ipmi_entity_t * entity, void *cb_data)
493 {
494 int rv;
495
496 if (op == IPMI_ADDED) {
497
498
499 rv = ipmi_entity_add_sensor_update_handler(entity, sensor_change, entity);
500 if (rv) {
501 crm_err("ipmi_entity_set_sensor_update_handler: 0x%x", rv);
502 crm_exit(CRM_EX_ERROR);
503 }
504 }
505 }
506
507
508
509
510 void
511 setup_done(ipmi_domain_t * domain,
512 int err,
513 unsigned int conn_num, unsigned int port_num, int still_connected, void *user_data)
514 {
515 int rv;
516
517
518
519 rv = ipmi_domain_add_entity_update_handler(domain, entity_change, domain);
520 if (rv) {
521 crm_err("ipmi_domain_add_entity_update_handler return error: %d", rv);
522 return;
523 }
524
525 }
526
527 int
528 main(int argc, char *argv[])
529 {
530 int rv;
531 int curr_arg = 1;
532 ipmi_args_t *args;
533 ipmi_con_t *con;
534
535
536 os_hnd = ipmi_posix_setup_os_handler();
537 if (!os_hnd) {
538 crm_err("ipmi_smi_setup_con: Unable to allocate os handler");
539 crm_exit(CRM_EX_ERROR);
540 }
541
542
543 ipmi_init(os_hnd);
544
545
546 if (argc > 1) {
547 for (char **arg = &argv[1]; *arg != NULL; ++arg) {
548 if (!strcmp(*arg, "--help") || !strcmp(*arg, "-?")) {
549 usage(argv[0]);
550 return CRM_EX_OK;
551 } else if (!strcmp(*arg, "--version") || !strcmp(*arg, "-$")) {
552 pcmk__cli_help('$', CRM_EX_OK);
553 }
554 }
555 }
556
557 #ifdef COMPLEX
558 rv = ipmi_parse_args2(&curr_arg, argc, argv, &args);
559 if (rv) {
560 crm_err("Error parsing command arguments, argument %d: %s", curr_arg, strerror(rv));
561 usage(argv[0]);
562 crm_exit(CRM_EX_USAGE);
563 }
564 #endif
565
566 pcmk__daemonize("ipmiservicelogd", PCMK_RUN_DIR "/ipmiservicelogd.pid0");
567 crm_log_cli_init("ipmiservicelogd");
568
569
570
571 #ifdef COMPLEX
572 rv = ipmi_args_setup_con(args, os_hnd, NULL, &con);
573 if (rv) {
574 crm_err("ipmi_ip_setup_con: %s", strerror(rv));
575 crm_err("Error: Is IPMI configured correctly?");
576 crm_exit(CRM_EX_ERROR);
577 }
578 #else
579
580
581
582
583
584
585
586
587 rv = ipmi_smi_setup_con(0, os_hnd, NULL, &con);
588 if (rv) {
589 crm_err("ipmi_smi_setup_con: %s", strerror(rv));
590 crm_err("Error: Is IPMI configured correctly?");
591 crm_exit(CRM_EX_ERROR);
592 }
593 #endif
594
595 rv = ipmi_open_domain("", &con, 1, setup_done, NULL, NULL, NULL, NULL, 0, NULL);
596 if (rv) {
597 crm_err("ipmi_init_domain: %s", strerror(rv));
598 crm_exit(CRM_EX_ERROR);
599 }
600
601
602
603
604 os_hnd->operation_loop(os_hnd);
605
606
607 os_hnd->free_os_handler(os_hnd);
608 return CRM_EX_OK;
609 }