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