/** * servevent * @brief Generate a serviceable event and an entry to the servicelog * * @param refcode the SRN or SRC for the serviceable event * @param sev the severity of the event * @param text the description of the serviceable event * @param vpd a structure containing the VPD of the target * @param callouts a linked list of FRU callouts * @return key of the new servicelog entry */ uint32_t servevent(char *refcode, int sev, char *text, struct dev_vpd *vpd, struct sl_callout *callouts) { struct servicelog *slog; struct sl_event *entry = NULL; struct sl_data_enclosure *encl = NULL; uint64_t key; int rc; if ((refcode == NULL) || (text == NULL) || (vpd == NULL)) return 0; entry = (struct sl_event *)malloc(sizeof(struct sl_event)); if (entry == NULL) { fprintf(stderr, "Out of memory\n"); return 0; } memset(entry, 0, sizeof(struct sl_event)); encl = (struct sl_data_enclosure *)malloc( sizeof(struct sl_data_enclosure)); if (encl == NULL) { fprintf(stderr, "Out of memory\n"); return 0; } memset(encl, 0, sizeof(struct sl_data_enclosure)); entry->addl_data = encl; entry->time_event = time(NULL); entry->type = SL_TYPE_ENCLOSURE; entry->severity = sev; entry->disposition = SL_DISP_UNRECOVERABLE; entry->serviceable = 1; entry->call_home_status = SL_CALLHOME_CANDIDATE; entry->description = (char *)malloc(strlen(text) + 1); strcpy(entry->description, text); entry->refcode = (char *)malloc(strlen(refcode) + 1); strcpy(entry->refcode, refcode); encl->enclosure_model = (char *)malloc(strlen(vpd->mtm) + 1); strcpy(encl->enclosure_model, vpd->mtm); encl->enclosure_serial = (char *)malloc(strlen(vpd->sn) + 1); strcpy(encl->enclosure_serial, vpd->sn); entry->callouts = callouts; rc = servicelog_open(&slog, 0); if (rc != 0) { fprintf(stderr, "%s", servicelog_error(slog)); return 0; } rc = servicelog_event_log(slog, entry, &key); servicelog_event_free(entry); servicelog_close(slog); if (rc != 0) { fprintf(stderr, "%s", servicelog_error(slog)); return 0; } return key; }
int main(int argc, char *argv[]) { int argerr = 0; int flag; int index = 0; int rc = 0; servicelog *slog = NULL; struct sl_event *event = NULL; uint64_t event_id = 0; crm_log_init_quiet("notifyServicelogEvent", LOG_INFO, FALSE, TRUE, argc, argv); crm_set_options(NULL, "event_id ", long_options, "Gets called upon events written to servicelog database"); if (argc < 2) { argerr++; } while (1) { flag = crm_get_option(argc, argv, &index); if (flag == -1) break; switch (flag) { case '?': case '$': crm_help(flag, CRM_EX_OK); break; default: ++argerr; break; } } if (argc - optind != 1) { ++argerr; } if (argerr) { crm_help('?', CRM_EX_USAGE); } openlog("notifyServicelogEvent", LOG_NDELAY, LOG_USER); if (sscanf(argv[optind], U64T, &event_id) != 1) { crm_err("Error: could not read event_id from args!"); rc = 1; goto cleanup; } if (event_id == 0) { crm_err("Error: event_id is 0!"); rc = 1; goto cleanup; } rc = servicelog_open(&slog, 0); /* flags is one of SL_FLAG_xxx */ if (!slog) { crm_err("Error: servicelog_open failed, rc = %d", rc); rc = 1; goto cleanup; } if (slog) { rc = servicelog_event_get(slog, event_id, &event); } if (rc == 0) { STATUS status = STATUS_GREEN; const char *health_component = "#health-ipmi"; const char *health_status = NULL; crm_debug("Event id = " U64T ", Log timestamp = %s, Event timestamp = %s", event_id, ctime(&(event->time_logged)), ctime(&(event->time_event))); status = event2status(event); health_status = status2char(status); if (health_status) { gboolean rc; /* @TODO pass attrd_opt_remote when appropriate */ rc = (attrd_update_delegate(NULL, 'v', NULL, health_component, health_status, NULL, NULL, NULL, NULL, attrd_opt_none) > 0); crm_debug("Updating attribute ('%s', '%s') = %d", health_component, health_status, rc); } else { crm_err("Error: status2char failed, status = %d", status); rc = 1; } } else { crm_err("Error: servicelog_event_get failed, rc = %d", rc); } cleanup: if (event) { servicelog_event_free(event); } if (slog) { servicelog_close(slog); } closelog(); return rc; }
/** * main * @brief Parse command line args process database * * @param argc the number of command-line arguments * @param argv array of command-line arguments * @return exit status: 0 for normal exit, 1 for usage error, >1 for other error */ int main(int argc, char *argv[]) { struct servicelog *slog; int rc; struct sl_event *event, *events; struct sl_repair_action *repair, *repairs; struct sl_notify *notify, *notifications; int option_index, action=ACTION_UNSPECIFIED; int flag_force=0; int age = 60; /* default age for --clean */ int platform = 0; char buf[124]; char *tmp; char *next_char; uint32_t num=0, num_repaired=0, num_unrepaired=0, num_info=0, num_ra=0; uint32_t span; time_t now; cmd = argv[0]; platform = get_platform(); switch (platform) { case PLATFORM_UNKNOWN: case PLATFORM_POWERNV: fprintf(stderr, "%s: is not supported on the %s platform\n", cmd, __power_platform_name(platform)); exit(1); } if (argc <= 1) { print_usage(); exit(0); } for (;;) { option_index = 0; rc = getopt_long(argc, argv, ARG_LIST, long_options, &option_index); if (rc == -1) break; switch (rc) { case 's': if (action != ACTION_UNSPECIFIED) action = ACTION_TOOMANY; if (action != ACTION_TOOMANY) action = ACTION_STATUS; break; case 't': if (!optarg) { fprintf(stderr, "The --truncate option " "requires either \"events\" or " "\"notify\" as an argument.\n"); print_usage(); exit(1); } if (!strcmp(optarg, "events")) { if (action != ACTION_UNSPECIFIED) action = ACTION_TOOMANY; if (action != ACTION_TOOMANY) action = ACTION_TRUNCATE_EVENTS; } else if (!strcmp(optarg, "notify")) { if (action != ACTION_UNSPECIFIED) action = ACTION_TOOMANY; if (action != ACTION_TOOMANY) action = ACTION_TRUNCATE_NOTIFY; } else { fprintf(stderr, "The --truncate option " "requires either \"events\" or " "\"notify\" as an argument.\n"); print_usage(); exit(1); } break; case 'c': if (action != ACTION_UNSPECIFIED) action = ACTION_TOOMANY; if (action != ACTION_TOOMANY) action = ACTION_CLEAN; break; case 'a': age = (int)strtoul(optarg, &next_char, 10); if (optarg[0] == '\0' || *next_char != '\0' || age < 0) { print_usage(); exit(1); } break; case 'f': flag_force = 1; break; case 'h': /* help */ print_usage(); exit(0); case '?': print_usage(); exit(1); default: printf("Invalid argument: %s\n", optarg); print_usage(); exit(1); } } if (optind < argc) { print_usage(); exit(1); } /* Command-line validation */ if (action == ACTION_UNSPECIFIED) { fprintf(stderr, "One of the action options is required.\n"); print_usage(); exit(1); } if (action == ACTION_TOOMANY) { fprintf(stderr, "Only one of the action options may be " "specified.\n"); print_usage(); exit(1); } switch (action) { case ACTION_STATUS: rc = servicelog_open(&slog, 0); if (rc != 0) { fprintf(stderr, "%s: Could not open servicelog " "database.\n%s\n", argv[0], servicelog_error(slog)); exit(2); } rc = servicelog_event_query(slog, "", &events); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } for (event = events; event; event = event->next) { num++; // total event count if (event->serviceable && (event->repair > 0)) num_repaired++; else if (event->serviceable) num_unrepaired++; else num_info++; // informational events } servicelog_event_free(events); // Now need to query repair actions: rc = servicelog_repair_query(slog, "", &repairs); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } for (repair = repairs; repair; repair = repair->next) num_ra++; servicelog_repair_free(repairs); servicelog_close(slog); printf("%-39s%10u\n", "Logged events:", num); printf(" %-35s%10u\n", "unrepaired serviceable events:", num_unrepaired); printf(" %-35s%10u\n", "repaired serviceable events:", num_repaired); printf(" %-35s%10u\n", "informational events:", num_info); printf(" %-35s%10u\n", "repair actions:", num_ra); break; case ACTION_TRUNCATE_EVENTS: if (geteuid() != 0) // Check to see if user is root { printf("Must be root to truncate the database!\n"); exit(2); } num = 0; if (!flag_force) { printf("Are you certain you wish to delete ALL events " "from the servicelog?\n"); printf("Enter 'yes' to continue > "); tmp = fgets(buf, 80, stdin); if (!tmp) exit(2); if (strcasecmp(buf, "yes\n")) { printf("Operation cancelled.\n"); exit(4); } } rc = servicelog_open(&slog, SL_FLAG_ADMIN); if (rc != 0) { fprintf(stderr, "%s: Could not open servicelog " "database.\n%s\n", argv[0], servicelog_error(slog)); exit(2); } rc = servicelog_event_query(slog, "", &events); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } for (event = events; event; event = event->next) { num++; servicelog_event_delete(slog, event->id); } servicelog_event_free(events); // Delete repair actions as well. rc = servicelog_repair_query(slog, "", &repairs); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } for (repair = repairs; repair; repair = repair->next) { num_ra++; servicelog_repair_delete(slog, repair->id); } servicelog_repair_free(repairs); printf("Deleted %u records.\n", num + num_ra); servicelog_close(slog); break; case ACTION_TRUNCATE_NOTIFY: if (geteuid() != 0) // Check to see if user is root { printf("Must be root to truncate the database!\n"); exit(2); } num = 0; if (!flag_force) { printf("Are you certain you wish to delete ALL " "notification tools from the servicelog?\n"); printf("Enter 'yes' to continue > "); tmp = fgets(buf, 80, stdin); if (!tmp) exit(2); if (strcasecmp(buf, "yes\n")) { printf("Operation cancelled.\n"); exit(4); } } rc = servicelog_open(&slog, SL_FLAG_ADMIN); if (rc != 0) { fprintf(stderr, "%s: Could not open servicelog " "database.\n%s\n", argv[0], servicelog_error(slog)); exit(2); } rc = servicelog_notify_query(slog, "", ¬ifications); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } for (notify = notifications; notify; notify = notify->next) { num++; servicelog_notify_delete(slog, notify->id); } servicelog_notify_free(notifications); servicelog_close(slog); printf("Deleted %u records.\n", num); break; case ACTION_CLEAN: if (geteuid() != 0) { // Check to see if user is root printf("Must be root to purge older events " "in the database!\n"); exit(2); } if (!flag_force) { printf("Are you certain you wish to perform the " "following tasks?\n" " - Delete all repaired serviceable events\n" " - Delete all informational events older than " "%d days\n" " - Delete all repair actions older than " "%d days\n" " - Delete anything older than 1 year\n", age, age); printf("Enter 'yes' to continue > "); tmp = fgets(buf, 80, stdin); if (!tmp) exit(2); if (strcasecmp(buf, "yes\n")) { printf("Operation cancelled.\n"); break; } } rc = servicelog_open(&slog, 0); if (rc != 0) { fprintf(stderr, "%s: Could not open servicelog " "database.\n%s\n", argv[0], servicelog_error(slog)); exit(2); } now = time(NULL); span = age * SECONDS_IN_DAY; rc = servicelog_event_query(slog, "", &events); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } for (event = events; event; event = event->next) { if (event->serviceable && event->closed) { num_repaired++; servicelog_event_delete(slog, event->id); } else if (!event->serviceable && (event->time_logged + span) < now) { num_info++; servicelog_event_delete(slog, event->id); } else if ((event->time_logged + SECONDS_IN_YEAR) < now) { num++; servicelog_event_delete(slog, event->id); } } servicelog_event_free(events); /* Delete repair actions which are older than age */ rc = servicelog_repair_query(slog, "", &repairs); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } for (repair = repairs; repair; repair = repair->next) { if ((repair->time_logged + span) < now ) { num_ra++; servicelog_repair_delete(slog, repair->id); } } servicelog_repair_free(repairs); servicelog_close(slog); printf("Removed %u repaired serviceable events.\n", num_repaired); printf("Removed %u informational events older than %d days.\n", num_info, age); printf("Removed %u repair actions older than %d days.\n", num_ra, age); printf("Removed %u other events older than one year.\n", num); break; default: fprintf(stderr, "Internal error; unknown action %d\n", action); exit(3); } exit(0); }