Skip to content

Commit fb9f5ce

Browse files
[platform] Add hwrebootcause for IX7 to retrieve power loss info from BMC elist
1 parent 92fa266 commit fb9f5ce

File tree

2 files changed

+106
-3
lines changed

2 files changed

+106
-3
lines changed

platform/broadcom/sonic-platform-modules-quanta/ix7-32x/sonic_platform/chassis.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from sonic_platform.fan import Fan
1717
from sonic_platform.fan_drawer import FanDrawer
1818
from sonic_platform.thermal import Thermal
19+
from sonic_platform.hwrebootcause import HWRebootCause
1920

2021
except ImportError as e:
2122
raise ImportError(str(e) + "- required module not found")
@@ -79,6 +80,8 @@ def __init__(self):
7980
self._component_list.extend(ComponentCPLD.get_component_list())
8081
self._component_list.append(ComponentPCIE())
8182

83+
self.hw_reboot_cause = HWRebootCause()
84+
8285
##############################################
8386
# Device methods
8487
##############################################
@@ -221,9 +224,10 @@ def get_reboot_cause(self):
221224
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
222225
to pass a description of the reboot cause.
223226
"""
224-
return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
225-
#TODO: Add Hardware and watchdog reboot cause
226-
#return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
227+
if self.hw_reboot_cause.check_power_loss():
228+
return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
229+
else:
230+
return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
227231

228232
##############################################
229233
# Other methods
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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

Comments
 (0)