|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +import os |
| 4 | +import subprocess |
| 5 | +from datetime import datetime |
| 6 | +from sonic_py_common.general import getstatusoutput_noshell_pipe |
| 7 | + |
| 8 | +GPIO_DIR = "/sys/class/gpio/" |
| 9 | +GPIO_EXPORT_PATH = GPIO_DIR + "export" |
| 10 | +POWER_LOSS_GPIO = "18" #TP_MB_PCA9555_PIN6 |
| 11 | +POWER_LOSS_GPIO_VALUE = GPIO_DIR + "gpio" + POWER_LOSS_GPIO + "/value" |
| 12 | +POWER_LOSS_GPIO_DIRECTION = GPIO_DIR + "gpio" + POWER_LOSS_GPIO + "/direction" |
| 13 | + |
| 14 | + |
| 15 | +class HWRebootCause(object): |
| 16 | + |
| 17 | + def __init__(self): |
| 18 | + pass |
| 19 | + |
| 20 | + def exec_cmd(self, cmd): |
| 21 | + status, output = subprocess.getstatusoutput(cmd) |
| 22 | + if status: |
| 23 | + print('Failed :' + cmd) |
| 24 | + return status, output |
| 25 | + |
| 26 | + @staticmethod |
| 27 | + def _get_command_result_pipe(cmd1, cmd2): |
| 28 | + try: |
| 29 | + rc, result = getstatusoutput_noshell_pipe(cmd1, cmd2) |
| 30 | + if rc != [0, 0]: |
| 31 | + raise RuntimeError("Failed to execute command {} {}, return code {}, {}".format(cmd1, cmd2, rc, result)) |
| 32 | + |
| 33 | + except OSError as e: |
| 34 | + raise RuntimeError("Failed to execute command {} {} due to {}".format(cmd1, cmd2, repr(e))) |
| 35 | + |
| 36 | + return result |
| 37 | + |
| 38 | + def check_power_loss(self): |
| 39 | + if os.path.isfile(POWER_LOSS_GPIO_VALUE): |
| 40 | + hw_reboot_cause = '0' |
| 41 | + with open(POWER_LOSS_GPIO_VALUE, 'r') as f: |
| 42 | + hw_reboot_cause = f.read() |
| 43 | + print("hw_reboot_cause:"+str(hw_reboot_cause)) |
| 44 | + return bool(hw_reboot_cause == '1') |
| 45 | + |
| 46 | + try: |
| 47 | + event_log = self._get_command_result_pipe(["ipmitool", "sel", "elist"], ["grep", 'AC lost | Asserted']) |
| 48 | + ac_lost_event = "1 | 01/01/2000 | 00:00:00 | Event log Initiated" # Init event log string |
| 49 | + if len(event_log) > 0: |
| 50 | + ac_lost_event = event_log.split('\n')[-1].strip() |
| 51 | + print(ac_lost_event) |
| 52 | + |
| 53 | + event_log = self._get_command_result_pipe(["ipmitool", "sel", "elist"], ["grep", 'Power Supply AC lost | Deasserted']) |
| 54 | + power_off_deasserted_event = "1 | 01/01/2000 | 00:00:00 | Event log Initiated" # Init event log string |
| 55 | + if len(event_log) > 0: |
| 56 | + power_off_deasserted_event = event_log.split('\n')[-1].strip() |
| 57 | + print(power_off_deasserted_event) |
| 58 | + |
| 59 | + event_log = self._get_command_result_pipe(["ipmitool", "sel", "elist"], ["grep", 'System Restart | Asserted']) |
| 60 | + sys_restart_event = "1 | 01/01/2000 | 00:00:00 | Event log Initiated" # Init event log string |
| 61 | + if len(event_log) > 0: |
| 62 | + sys_restart_event = event_log.split('\n')[-1].strip() |
| 63 | + print(sys_restart_event) |
| 64 | + |
| 65 | + """126 | 04/27/2020 | 13:16:27 | Power Unit Power Unit | AC lost | Asserted""" |
| 66 | + ac_lost_event = ac_lost_event.split("|") |
| 67 | + ac_lost_order = int(ac_lost_event[0], 16) |
| 68 | + """2a70 | 02/17/2021 | 09:45:25 | Power Supply PSU_n Input lost | Power Supply AC lost | Deasserted""" |
| 69 | + power_off_deasserted_event = power_off_deasserted_event.split("|") |
| 70 | + power_off_deasserted_time = datetime.strptime( |
| 71 | + power_off_deasserted_event[1] + power_off_deasserted_event[2], ' %m/%d/%Y %H:%M:%S ') |
| 72 | + |
| 73 | + """127 | 04/27/2020 | 13:16:26 | System Boot Initiated | System Restart | Asserted""" |
| 74 | + sys_restart_event = sys_restart_event.split("|") |
| 75 | + sys_restart_order = int(sys_restart_event[0], 16) |
| 76 | + sys_restart_time = datetime.strptime( |
| 77 | + sys_restart_event[1] + sys_restart_event[2], ' %m/%d/%Y %H:%M:%S ') |
| 78 | + |
| 79 | + except Exception as error: |
| 80 | + print("check_power_loss failed: {} !".format(str(error))) |
| 81 | + return False |
| 82 | + |
| 83 | + with open(GPIO_EXPORT_PATH, 'w') as f: |
| 84 | + f.write(POWER_LOSS_GPIO + '\n') |
| 85 | + |
| 86 | + with open(POWER_LOSS_GPIO_DIRECTION, 'w') as f: |
| 87 | + f.write('out\n') |
| 88 | + |
| 89 | + order_diff = sys_restart_order - ac_lost_order |
| 90 | + power_off_time_diff = power_off_deasserted_time - sys_restart_time |
| 91 | + |
| 92 | + if order_diff == 1 or (power_off_time_diff.total_seconds() > -5 and power_off_time_diff.total_seconds() < 12): |
| 93 | + with open(POWER_LOSS_GPIO_VALUE, 'w') as f: |
| 94 | + f.write('1\n') |
| 95 | + return True |
| 96 | + else: |
| 97 | + with open(POWER_LOSS_GPIO_VALUE, 'w') as f: |
| 98 | + f.write('0\n') |
| 99 | + return False |
0 commit comments