Skip to content

Commit

Permalink
[ssd_generic] Add support Transcend ssd-health. (sonic-net#436)
Browse files Browse the repository at this point in the history
Signed-off-by: michael_shih <[email protected]>
  • Loading branch information
ec-michael-shih authored Feb 5, 2024
1 parent 538ec67 commit 888075d
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
22 changes: 22 additions & 0 deletions sonic_platform_base/sonic_ssd/ssd_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
SMARTCTL = "smartctl {} -a"
INNODISK = "iSmart -d {}"
VIRTIUM = "SmartCmd -m {}"
TRANSCEND = "scopepro -all {}"

NOT_AVAILABLE = "N/A"

Expand All @@ -25,6 +26,8 @@
INNODISK_TEMPERATURE_ID = 194
SWISSBIT_HEALTH_ID = 248
SWISSBIT_TEMPERATURE_ID = 194
TRANSCEND_HEALTH_ID = 169
TRANSCEND_TEMPERATURE_ID = 194

class SsdUtil(SsdBase):
"""
Expand All @@ -46,6 +49,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 },
}

self.dev = diskdev
Expand Down Expand Up @@ -83,6 +87,8 @@ def _parse_vendor(self):
return 'Virtium'
elif self.model.startswith('SFS'):
return 'Swissbit'
elif self.model.startswith('TS'):
return 'Transcend'
else:
return None

Expand Down Expand Up @@ -179,6 +185,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))

Expand Down
57 changes: 57 additions & 0 deletions tests/ssd_generic_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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%
"""

class TestSsdGeneric:
@mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_nvme_ssd))
def test_nvme_ssd(self):
Expand Down Expand Up @@ -891,3 +936,15 @@ def test_swissbit_ssd(self, mock_exec):
assert swissbit_ssd.get_firmware() == "SBR15004"
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"

0 comments on commit 888075d

Please sign in to comment.