diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py index 96a7b9e2315a..e13b90d6c0ca 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -30,6 +30,7 @@ from .utils import extract_RJ45_ports_index from . import utils from .device_data import DeviceDataManager + import re except ImportError as e: raise ImportError (str(e) + "- required module not found") @@ -61,6 +62,10 @@ REBOOT_CAUSE_FILE_LENGTH = 1 +REBOOT_TYPE_KEXEC_FILE = "/proc/cmdline" +REBOOT_TYPE_KEXEC_PATTERN_WARM = ".*SONIC_BOOT_TYPE=(warm|fastfast).*" +REBOOT_TYPE_KEXEC_PATTERN_FAST = ".*SONIC_BOOT_TYPE=(fast|fast-reboot).*" + # Global logger class instance logger = Logger() @@ -736,6 +741,18 @@ def initialize_reboot_cause(self): self.reboot_by_software = 'reset_sw_reset' self.reboot_cause_initialized = True + def _parse_warmfast_reboot_from_proc_cmdline(self): + if os.path.isfile(REBOOT_TYPE_KEXEC_FILE): + with open(REBOOT_TYPE_KEXEC_FILE) as cause_file: + cause_file_kexec = cause_file.readline() + m = re.search(REBOOT_TYPE_KEXEC_PATTERN_WARM, cause_file_kexec) + if m and m.group(1): + return 'warm-reboot' + m = re.search(REBOOT_TYPE_KEXEC_PATTERN_FAST, cause_file_kexec) + if m and m.group(1): + return 'fast-reboot' + return None + def get_reboot_cause(self): """ Retrieves the cause of the previous reboot @@ -748,6 +765,14 @@ def get_reboot_cause(self): to pass a description of the reboot cause. """ #read reboot causes files in the following order + + # To avoid the leftover hardware reboot cause confusing the reboot cause determine service + # Skip the hardware reboot cause check if warm/fast reboot cause found from cmdline + if utils.is_host(): + reboot_cause = self._parse_warmfast_reboot_from_proc_cmdline() + if reboot_cause: + return self.REBOOT_CAUSE_NON_HARDWARE, '' + if not self.reboot_cause_initialized: self.initialize_reboot_cause() diff --git a/platform/mellanox/mlnx-platform-api/tests/test_chassis.py b/platform/mellanox/mlnx-platform-api/tests/test_chassis.py index 8ae4ece8eec6..e71f75f0a954 100644 --- a/platform/mellanox/mlnx-platform-api/tests/test_chassis.py +++ b/platform/mellanox/mlnx-platform-api/tests/test_chassis.py @@ -224,6 +224,35 @@ def read_int_from_file(file_path, *args, **kwargs): assert minor == value mock_file_content[file_path] = 0 + utils.is_host = mock.MagicMock(return_value=True) + chassis._parse_warmfast_reboot_from_proc_cmdline = mock.MagicMock(return_value='warm-reboot') + for key, value in chassis.reboot_major_cause_dict.items(): + file_path = os.path.join(REBOOT_CAUSE_ROOT, key) + mock_file_content[file_path] = 1 + major, minor = chassis.get_reboot_cause() + assert major == chassis.REBOOT_CAUSE_NON_HARDWARE + assert minor == '' + mock_file_content[file_path] = 0 + + for key, value in chassis.reboot_minor_cause_dict.items(): + file_path = os.path.join(REBOOT_CAUSE_ROOT, key) + mock_file_content[file_path] = 1 + major, minor = chassis.get_reboot_cause() + assert major == chassis.REBOOT_CAUSE_NON_HARDWARE + assert minor == value + mock_file_content[file_path] = 0 + + def test_parse_warmfast_reboot_from_proc_cmdline(self): + chassis = Chassis() + with mock.patch("builtins.open", mock.mock_open(read_data="SONIC_BOOT_TYPE=warm")): + assert chassis._parse_warmfast_reboot_from_proc_cmdline() == "warm-reboot" + + with mock.patch("builtins.open", mock.mock_open(read_data="SONIC_BOOT_TYPE=fast")): + assert chassis._parse_warmfast_reboot_from_proc_cmdline() == "fast-reboot" + + with mock.patch("builtins.open", mock.mock_open(read_data="SONIC_BOOT_TYPE=None")): + assert chassis._parse_warmfast_reboot_from_proc_cmdline() == None + def test_module(self): from sonic_platform.chassis import ModularChassis # Test get_num_modules, it should not create any SFP objects