From ef553646186f0a7250160c89d6fca8df745b2d5a Mon Sep 17 00:00:00 2001 From: dflynn-Nokia <60479697+dflynn-Nokia@users.noreply.github.com> Date: Wed, 10 Nov 2021 20:41:58 -0500 Subject: [PATCH] SSD Health: Retrieve SSD health and temperature values from generic SSD info (#229) The problem: The current SSD health API uses a SSD vendor specific utility to retrieve values for overall SSD health and internal SSD temperature. These utilities are typically made available only in binary form and are not always available for all platform architectures (amd64, arm64, armhf, etc.) Vendor licensing agreements can prevent the inclusion of utility source code in the Sonic build. The solution presented here is to retrieve SSD health and temperature values from the generic SSD info retrieved via the open-source smartmontools utility (smartctl). These values can be overwritten with values retrieved using a vendor specific utility when available. smartmontools is already included in the Sonic source tree and is being built for all platform architectures. --- sonic_platform_base/sonic_ssd/ssd_generic.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sonic_platform_base/sonic_ssd/ssd_generic.py b/sonic_platform_base/sonic_ssd/ssd_generic.py index aff5be00b132..8cd1f6c00ef7 100644 --- a/sonic_platform_base/sonic_ssd/ssd_generic.py +++ b/sonic_platform_base/sonic_ssd/ssd_generic.py @@ -63,6 +63,9 @@ def __init__(self, diskdev): def _execute_shell(self, cmd): process = subprocess.Popen(cmd.split(), universal_newlines=True, stdout=subprocess.PIPE) output, error = process.communicate() + exit_code = process.returncode + if exit_code: + return None return output def _parse_re(self, pattern, buffer): @@ -72,10 +75,13 @@ def _parse_re(self, pattern, buffer): def fetch_generic_ssd_info(self, diskdev): self.ssd_info = self._execute_shell(self.vendor_ssd_utility["Generic"]["utility"].format(diskdev)) + # Health and temperature values may be overwritten with vendor specific data def parse_generic_ssd_info(self): self.model = self._parse_re('Device Model:\s*(.+?)\n', self.ssd_info) self.serial = self._parse_re('Serial Number:\s*(.+?)\n', self.ssd_info) self.firmware = self._parse_re('Firmware Version:\s*(.+?)\n', self.ssd_info) + self.health = self._parse_re('Remaining_Lifetime_Perc\s*(.+?)\n', self.ssd_info).split()[-1] + self.temperature = self._parse_re('Temperature_Celsius\s*(.+?)\n', self.ssd_info).split()[-6] def parse_innodisk_info(self): self.health = self._parse_re('Health:\s*(.+?)%', self.vendor_ssd_info) @@ -94,7 +100,8 @@ def fetch_vendor_ssd_info(self, diskdev, model): self.vendor_ssd_info = self._execute_shell(self.vendor_ssd_utility[model]["utility"].format(diskdev)) def parse_vendor_ssd_info(self, model): - self.vendor_ssd_utility[model]["parser"]() + if self.vendor_ssd_info: + self.vendor_ssd_utility[model]["parser"]() def get_health(self): """