From 0e822858975e143204b78c8d503b7d87a6ff76c7 Mon Sep 17 00:00:00 2001 From: Michael Shih <71379738+ec-michael-shih@users.noreply.github.com> Date: Tue, 6 Feb 2024 03:34:31 +0800 Subject: [PATCH] [ssd_generic] Add support Transcend ssd-health. (#436) Signed-off-by: michael_shih --- sonic_platform_base/sonic_ssd/ssd_generic.py | 22 ++++++++ tests/ssd_generic_test.py | 59 +++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/sonic_platform_base/sonic_ssd/ssd_generic.py b/sonic_platform_base/sonic_ssd/ssd_generic.py index d5f5cbf..0a40f55 100644 --- a/sonic_platform_base/sonic_ssd/ssd_generic.py +++ b/sonic_platform_base/sonic_ssd/ssd_generic.py @@ -18,6 +18,7 @@ SMARTCTL = "smartctl {} -a" INNODISK = "iSmart -d {}" VIRTIUM = "SmartCmd -m {}" +TRANSCEND = "scopepro -all {}" NOT_AVAILABLE = "N/A" @@ -26,6 +27,8 @@ INNODISK_TEMPERATURE_ID = 194 SWISSBIT_HEALTH_ID = 248 SWISSBIT_TEMPERATURE_ID = 194 +TRANSCEND_HEALTH_ID = 169 +TRANSCEND_TEMPERATURE_ID = 194 class SsdUtil(SsdBase): """ @@ -48,6 +51,7 @@ def __init__(self, diskdev): "StorFly" : { "utility" : VIRTIUM, "parser" : self.parse_virtium_info }, "Virtium" : { "utility" : VIRTIUM, "parser" : self.parse_virtium_info }, "Swissbit" : { "utility" : SMARTCTL, "parser" : self.parse_swissbit_info }, + "Transcend" : { "utility" : TRANSCEND, "parser" : self.parse_transcend_info }, "WDC" : { "utility" : SMARTCTL, "parser" : self.parse_wdc_ssd_info } } @@ -86,6 +90,8 @@ def _parse_vendor(self): return 'Virtium' elif self.model.startswith('SFS'): return 'Swissbit' + elif self.model.startswith('TS'): + return 'Transcend' elif self.model.startswith(('EPM3750', 'MPT160')): return 'Phison' else: @@ -208,6 +214,22 @@ def parse_swissbit_info(self): else: self.temperature = temp_raw.split()[-3] + def parse_transcend_info(self): + if self.vendor_ssd_info: + self.model = self._parse_re('Model\s*:(.+?)\s*\n', self.vendor_ssd_info) + self.serial = self._parse_re('Serial No\s*:(.+?)\s*\n', self.vendor_ssd_info) + self.firmware = self._parse_re('FW Version\s*:(.+?)\s*\n', self.vendor_ssd_info) + health_raw = self._parse_re('{}\s*(.+?)\n'.format(hex(TRANSCEND_HEALTH_ID).upper()[2:]), self.vendor_ssd_info) #169 -> A9 + if health_raw == NOT_AVAILABLE: + self.health = NOT_AVAILABLE + else: + self.health = health_raw.split()[-1] + temp_raw = self._parse_re('{}\s*(.+?)\n'.format(hex(TRANSCEND_TEMPERATURE_ID).upper()[2:]), self.vendor_ssd_info) #194 -> C2 + if temp_raw == NOT_AVAILABLE: + self.temperature = NOT_AVAILABLE + else: + self.temperature = temp_raw.split()[-1] + def fetch_vendor_ssd_info(self, diskdev, model): self.vendor_ssd_info = self._execute_shell(self.vendor_ssd_utility[model]["utility"].format(diskdev)) diff --git a/tests/ssd_generic_test.py b/tests/ssd_generic_test.py index f0f0207..c0c8f8c 100644 --- a/tests/ssd_generic_test.py +++ b/tests/ssd_generic_test.py @@ -774,6 +774,51 @@ If Selective self-test is pending on power-up, resume after 0 minute delay. """ +output_transcend_vendor = """ +scopepro-cli 1.21 2023/11/24 +Copyright (c) 2021-24, Transcend information, Inc. All rights reserved. + +[/dev/sda] +---------- Disk Information ---------- +Model :TS32XBTMM1600 +FW Version :O0918B +Serial No :F318410080 +Support Interface :SATA +---------------- S.M.A.R.T Information ---------------- +01 Read Error Rate 0 +05 Reallocated Sectors Count 0 +09 Power-On Hour Count 2295 +0C Power Cycle Count 2580 +A0 Uncorrectable sectors count when read/write 0 +A1 Number of Valid Spare Blocks 56 +A3 Number of Initial Invalid Blocks 12 +A4 Total Erase Count 924312 +A5 Maximum Erase Count 931 +A6 Minimum Erase Count 831 +A7 Average Erase Count 898 +A8 Max Erase Count of Spec 3000 +A9 Remain Life (percentage) 71 +AF Program fail count in worst die 0 +B0 Erase fail count in worst die 0 +B1 Total Wear Level Count 481 +B2 Runtime Invalid Block Count 0 +B5 Total Program Fail Count 0 +B6 Total Erase Fail Count 0 +C0 Power-Off Retract Count 59 +C2 Controlled Temperature 40 +C3 Hardware ECC Recovered 1668 +C4 Reallocation Event Count 0 +C5 Current Pending Sector Count 0 +C6 Uncorrectable Error Count Off-Line 0 +C7 Ultra DMA CRC Error Count 0 +E8 Available Reserved Space 100 +F1 Total LBA Written (each write unit=32MB) 671696 +F2 Total LBA Read (each read unit=32MB) 393162 +F5 Flash Write Sector Count 924312 +---------------- Health Information ---------------- +Health Percentage: 71% +""" + output_wdc_vendor = """ smartctl 7.2 2020-12-30 r5155 [x86_64-linux-5.10.0-18-2-amd64] (local build) Copyright (C) 2002-20, Bruce Allen, Christian Franke, www.smartmontools.org @@ -982,6 +1027,18 @@ def test_swissbit_ssd(self, mock_exec): assert swissbit_ssd.get_temperature() == '25' assert swissbit_ssd.get_serial() == "00006022750795000010" + @mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell') + def test_transcend_ssd(self, mock_exec): + mock_exec.return_value = output_transcend_vendor + transcend_ssd = SsdUtil('/dev/sda') + transcend_ssd.vendor_ssd_info = mock_exec.return_value + transcend_ssd.parse_vendor_ssd_info('Transcend') + assert transcend_ssd.get_health() == '71' + assert transcend_ssd.get_model() == 'TS32XBTMM1600' + assert transcend_ssd.get_firmware() == "O0918B" + assert transcend_ssd.get_temperature() == '40' + assert transcend_ssd.get_serial() == "F318410080" + @mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell') def test_wdc_ssd(self, mock_exec): mock_exec.return_value = output_wdc_vendor @@ -990,4 +1047,4 @@ def test_wdc_ssd(self, mock_exec): assert wdc_ssd.get_model() == 'WDC PC SA530 SDASN8Y1T00' assert wdc_ssd.get_firmware() == "40103000" assert wdc_ssd.get_temperature() == '23' - assert wdc_ssd.get_serial() == "2122FF441406" \ No newline at end of file + assert wdc_ssd.get_serial() == "2122FF441406"