Skip to content

Commit ab54549

Browse files
keboliumssonicbld
authored andcommitted
[Mellanox] Skip the leftover hardware reboot cause in case of last boot is warm/fast reboot (sonic-net#13246)
- Why I did it In case of warm/fast reboot, the hardware reboot cause will NOT be cleared because CPLD will not be touched in this flow. To not confuse the reboot cause determine logic, the leftover hardware reboot cause shall be skipped by the platform API, platform API will return the 'REBOOT_CAUSE_NON_HARDWARE' instead of the "hardware" reboot cause. - How I did it Check the proc cmdline to see whether the last reboot is a warm or fast reboot, if yes skip checking the leftover hardware reboot cause. - How to verify it a. Manual test: - Perform a power loss - Perform a warm/fast reboot - Check the reboot cause should be "warm-reboot" or "fast-reboot" instead of "power loss" b. Run reboot cause related regression test. Signed-off-by: Kebo Liu <[email protected]>
1 parent e631f42 commit ab54549

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py

+25
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from .utils import extract_RJ45_ports_index
3131
from . import utils
3232
from .device_data import DeviceDataManager
33+
import re
3334
except ImportError as e:
3435
raise ImportError (str(e) + "- required module not found")
3536

@@ -61,6 +62,10 @@
6162

6263
REBOOT_CAUSE_FILE_LENGTH = 1
6364

65+
REBOOT_TYPE_KEXEC_FILE = "/proc/cmdline"
66+
REBOOT_TYPE_KEXEC_PATTERN_WARM = ".*SONIC_BOOT_TYPE=(warm|fastfast).*"
67+
REBOOT_TYPE_KEXEC_PATTERN_FAST = ".*SONIC_BOOT_TYPE=(fast|fast-reboot).*"
68+
6469
# Global logger class instance
6570
logger = Logger()
6671

@@ -736,6 +741,18 @@ def initialize_reboot_cause(self):
736741
self.reboot_by_software = 'reset_sw_reset'
737742
self.reboot_cause_initialized = True
738743

744+
def _parse_warmfast_reboot_from_proc_cmdline(self):
745+
if os.path.isfile(REBOOT_TYPE_KEXEC_FILE):
746+
with open(REBOOT_TYPE_KEXEC_FILE) as cause_file:
747+
cause_file_kexec = cause_file.readline()
748+
m = re.search(REBOOT_TYPE_KEXEC_PATTERN_WARM, cause_file_kexec)
749+
if m and m.group(1):
750+
return 'warm-reboot'
751+
m = re.search(REBOOT_TYPE_KEXEC_PATTERN_FAST, cause_file_kexec)
752+
if m and m.group(1):
753+
return 'fast-reboot'
754+
return None
755+
739756
def get_reboot_cause(self):
740757
"""
741758
Retrieves the cause of the previous reboot
@@ -748,6 +765,14 @@ def get_reboot_cause(self):
748765
to pass a description of the reboot cause.
749766
"""
750767
#read reboot causes files in the following order
768+
769+
# To avoid the leftover hardware reboot cause confusing the reboot cause determine service
770+
# Skip the hardware reboot cause check if warm/fast reboot cause found from cmdline
771+
if utils.is_host():
772+
reboot_cause = self._parse_warmfast_reboot_from_proc_cmdline()
773+
if reboot_cause:
774+
return self.REBOOT_CAUSE_NON_HARDWARE, ''
775+
751776
if not self.reboot_cause_initialized:
752777
self.initialize_reboot_cause()
753778

platform/mellanox/mlnx-platform-api/tests/test_chassis.py

+29
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,35 @@ def read_int_from_file(file_path, *args, **kwargs):
224224
assert minor == value
225225
mock_file_content[file_path] = 0
226226

227+
utils.is_host = mock.MagicMock(return_value=True)
228+
chassis._parse_warmfast_reboot_from_proc_cmdline = mock.MagicMock(return_value='warm-reboot')
229+
for key, value in chassis.reboot_major_cause_dict.items():
230+
file_path = os.path.join(REBOOT_CAUSE_ROOT, key)
231+
mock_file_content[file_path] = 1
232+
major, minor = chassis.get_reboot_cause()
233+
assert major == chassis.REBOOT_CAUSE_NON_HARDWARE
234+
assert minor == ''
235+
mock_file_content[file_path] = 0
236+
237+
for key, value in chassis.reboot_minor_cause_dict.items():
238+
file_path = os.path.join(REBOOT_CAUSE_ROOT, key)
239+
mock_file_content[file_path] = 1
240+
major, minor = chassis.get_reboot_cause()
241+
assert major == chassis.REBOOT_CAUSE_NON_HARDWARE
242+
assert minor == value
243+
mock_file_content[file_path] = 0
244+
245+
def test_parse_warmfast_reboot_from_proc_cmdline(self):
246+
chassis = Chassis()
247+
with mock.patch("builtins.open", mock.mock_open(read_data="SONIC_BOOT_TYPE=warm")):
248+
assert chassis._parse_warmfast_reboot_from_proc_cmdline() == "warm-reboot"
249+
250+
with mock.patch("builtins.open", mock.mock_open(read_data="SONIC_BOOT_TYPE=fast")):
251+
assert chassis._parse_warmfast_reboot_from_proc_cmdline() == "fast-reboot"
252+
253+
with mock.patch("builtins.open", mock.mock_open(read_data="SONIC_BOOT_TYPE=None")):
254+
assert chassis._parse_warmfast_reboot_from_proc_cmdline() == None
255+
227256
def test_module(self):
228257
from sonic_platform.chassis import ModularChassis
229258
# Test get_num_modules, it should not create any SFP objects

0 commit comments

Comments
 (0)