Skip to content

Commit 888075d

Browse files
[ssd_generic] Add support Transcend ssd-health. (#436)
Signed-off-by: michael_shih <[email protected]>
1 parent 538ec67 commit 888075d

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

sonic_platform_base/sonic_ssd/ssd_generic.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
SMARTCTL = "smartctl {} -a"
1818
INNODISK = "iSmart -d {}"
1919
VIRTIUM = "SmartCmd -m {}"
20+
TRANSCEND = "scopepro -all {}"
2021

2122
NOT_AVAILABLE = "N/A"
2223

@@ -25,6 +26,8 @@
2526
INNODISK_TEMPERATURE_ID = 194
2627
SWISSBIT_HEALTH_ID = 248
2728
SWISSBIT_TEMPERATURE_ID = 194
29+
TRANSCEND_HEALTH_ID = 169
30+
TRANSCEND_TEMPERATURE_ID = 194
2831

2932
class SsdUtil(SsdBase):
3033
"""
@@ -46,6 +49,7 @@ def __init__(self, diskdev):
4649
"StorFly" : { "utility" : VIRTIUM, "parser" : self.parse_virtium_info },
4750
"Virtium" : { "utility" : VIRTIUM, "parser" : self.parse_virtium_info },
4851
"Swissbit" : { "utility" : SMARTCTL, "parser" : self.parse_swissbit_info },
52+
"Transcend" : { "utility" : TRANSCEND, "parser" : self.parse_transcend_info },
4953
}
5054

5155
self.dev = diskdev
@@ -83,6 +87,8 @@ def _parse_vendor(self):
8387
return 'Virtium'
8488
elif self.model.startswith('SFS'):
8589
return 'Swissbit'
90+
elif self.model.startswith('TS'):
91+
return 'Transcend'
8692
else:
8793
return None
8894

@@ -179,6 +185,22 @@ def parse_swissbit_info(self):
179185
else:
180186
self.temperature = temp_raw.split()[-3]
181187

188+
def parse_transcend_info(self):
189+
if self.vendor_ssd_info:
190+
self.model = self._parse_re('Model\s*:(.+?)\s*\n', self.vendor_ssd_info)
191+
self.serial = self._parse_re('Serial No\s*:(.+?)\s*\n', self.vendor_ssd_info)
192+
self.firmware = self._parse_re('FW Version\s*:(.+?)\s*\n', self.vendor_ssd_info)
193+
health_raw = self._parse_re('{}\s*(.+?)\n'.format(hex(TRANSCEND_HEALTH_ID).upper()[2:]), self.vendor_ssd_info) #169 -> A9
194+
if health_raw == NOT_AVAILABLE:
195+
self.health = NOT_AVAILABLE
196+
else:
197+
self.health = health_raw.split()[-1]
198+
temp_raw = self._parse_re('{}\s*(.+?)\n'.format(hex(TRANSCEND_TEMPERATURE_ID).upper()[2:]), self.vendor_ssd_info) #194 -> C2
199+
if temp_raw == NOT_AVAILABLE:
200+
self.temperature = NOT_AVAILABLE
201+
else:
202+
self.temperature = temp_raw.split()[-1]
203+
182204
def fetch_vendor_ssd_info(self, diskdev, model):
183205
self.vendor_ssd_info = self._execute_shell(self.vendor_ssd_utility[model]["utility"].format(diskdev))
184206

tests/ssd_generic_test.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,51 @@
774774
If Selective self-test is pending on power-up, resume after 0 minute delay.
775775
"""
776776

777+
output_transcend_vendor = """
778+
scopepro-cli 1.21 2023/11/24
779+
Copyright (c) 2021-24, Transcend information, Inc. All rights reserved.
780+
781+
[/dev/sda]
782+
---------- Disk Information ----------
783+
Model :TS32XBTMM1600
784+
FW Version :O0918B
785+
Serial No :F318410080
786+
Support Interface :SATA
787+
---------------- S.M.A.R.T Information ----------------
788+
01 Read Error Rate 0
789+
05 Reallocated Sectors Count 0
790+
09 Power-On Hour Count 2295
791+
0C Power Cycle Count 2580
792+
A0 Uncorrectable sectors count when read/write 0
793+
A1 Number of Valid Spare Blocks 56
794+
A3 Number of Initial Invalid Blocks 12
795+
A4 Total Erase Count 924312
796+
A5 Maximum Erase Count 931
797+
A6 Minimum Erase Count 831
798+
A7 Average Erase Count 898
799+
A8 Max Erase Count of Spec 3000
800+
A9 Remain Life (percentage) 71
801+
AF Program fail count in worst die 0
802+
B0 Erase fail count in worst die 0
803+
B1 Total Wear Level Count 481
804+
B2 Runtime Invalid Block Count 0
805+
B5 Total Program Fail Count 0
806+
B6 Total Erase Fail Count 0
807+
C0 Power-Off Retract Count 59
808+
C2 Controlled Temperature 40
809+
C3 Hardware ECC Recovered 1668
810+
C4 Reallocation Event Count 0
811+
C5 Current Pending Sector Count 0
812+
C6 Uncorrectable Error Count Off-Line 0
813+
C7 Ultra DMA CRC Error Count 0
814+
E8 Available Reserved Space 100
815+
F1 Total LBA Written (each write unit=32MB) 671696
816+
F2 Total LBA Read (each read unit=32MB) 393162
817+
F5 Flash Write Sector Count 924312
818+
---------------- Health Information ----------------
819+
Health Percentage: 71%
820+
"""
821+
777822
class TestSsdGeneric:
778823
@mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_nvme_ssd))
779824
def test_nvme_ssd(self):
@@ -891,3 +936,15 @@ def test_swissbit_ssd(self, mock_exec):
891936
assert swissbit_ssd.get_firmware() == "SBR15004"
892937
assert swissbit_ssd.get_temperature() == '25'
893938
assert swissbit_ssd.get_serial() == "00006022750795000010"
939+
940+
@mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell')
941+
def test_transcend_ssd(self, mock_exec):
942+
mock_exec.return_value = output_transcend_vendor
943+
transcend_ssd = SsdUtil('/dev/sda')
944+
transcend_ssd.vendor_ssd_info = mock_exec.return_value
945+
transcend_ssd.parse_vendor_ssd_info('Transcend')
946+
assert transcend_ssd.get_health() == '71'
947+
assert transcend_ssd.get_model() == 'TS32XBTMM1600'
948+
assert transcend_ssd.get_firmware() == "O0918B"
949+
assert transcend_ssd.get_temperature() == '40'
950+
assert transcend_ssd.get_serial() == "F318410080"

0 commit comments

Comments
 (0)