Skip to content

Commit b043372

Browse files
authored
[sonic_ssd] Nokia-7215: "show platform ssdhealth" not showing health percent (sonic-net#279)
Description The command is not showing the correct value for ssd health. admin@sonic:~$ show platform ssdhealth Device Model : M.2 (S42) 3IE4 Health : N/A Temperature : 25C Motivation and Context SSD health percentage not displayed on Nokia-7215 platform. How Has This Been Tested? "show platform ssdhealth" cli command Output after fix: admin@sonic:~$ show platform ssdhealth Device Model : M.2 (S42) 3IE4 Health : 100% Temperature : 25C
1 parent d62d3d6 commit b043372

File tree

2 files changed

+112
-11
lines changed

2 files changed

+112
-11
lines changed

sonic_platform_base/sonic_ssd/ssd_generic.py

+25-11
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020

2121
NOT_AVAILABLE = "N/A"
2222

23+
# Set Vendor Specific IDs
24+
INNODISK_HEALTH_ID = 169
25+
INNODISK_TEMPERATURE_ID = 194
2326

2427
class SsdUtil(SsdBase):
2528
"""
@@ -109,24 +112,32 @@ def parse_generic_ssd_info(self):
109112
self.firmware = self._parse_re('Firmware Version:\s*(.+?)\n', self.ssd_info)
110113

111114
def parse_innodisk_info(self):
112-
self.health = self._parse_re('Health:\s*(.+?)%?', self.vendor_ssd_info)
113-
self.temperature = self._parse_re('Temperature\s*\[\s*(.+?)\]', self.vendor_ssd_info)
115+
if self.vendor_ssd_info:
116+
self.health = self._parse_re('Health:\s*(.+?)%?', self.vendor_ssd_info)
117+
self.temperature = self._parse_re('Temperature\s*\[\s*(.+?)\]', self.vendor_ssd_info)
118+
else:
119+
if self.health == NOT_AVAILABLE:
120+
health_raw = self.parse_id_number(INNODISK_HEALTH_ID)
121+
self.health = health_raw.split()[-1]
122+
if self.temperature == NOT_AVAILABLE:
123+
temp_raw = self.parse_id_number(INNODISK_TEMPERATURE_ID)
124+
self.temperature = temp_raw.split()[-6]
114125

115126
def parse_virtium_info(self):
116-
self.temperature = self._parse_re('Temperature_Celsius\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info)
117-
nand_endurance = self._parse_re('NAND_Endurance\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info)
118-
avg_erase_count = self._parse_re('Average_Erase_Count\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info)
119-
try:
120-
self.health = 100 - (float(avg_erase_count) * 100 / float(nand_endurance))
121-
except ValueError:
122-
pass
127+
if self.vendor_ssd_info:
128+
self.temperature = self._parse_re('Temperature_Celsius\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info)
129+
nand_endurance = self._parse_re('NAND_Endurance\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info)
130+
avg_erase_count = self._parse_re('Average_Erase_Count\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info)
131+
try:
132+
self.health = 100 - (float(avg_erase_count) * 100 / float(nand_endurance))
133+
except (ValueError, ZeroDivisionError):
134+
pass
123135

124136
def fetch_vendor_ssd_info(self, diskdev, model):
125137
self.vendor_ssd_info = self._execute_shell(self.vendor_ssd_utility[model]["utility"].format(diskdev))
126138

127139
def parse_vendor_ssd_info(self, model):
128-
if self.vendor_ssd_info:
129-
self.vendor_ssd_utility[model]["parser"]()
140+
self.vendor_ssd_utility[model]["parser"]()
130141

131142
def get_health(self):
132143
"""
@@ -183,3 +194,6 @@ def get_vendor_output(self):
183194
A string holding some vendor specific disk information
184195
"""
185196
return self.vendor_ssd_info
197+
198+
def parse_id_number(self, id):
199+
return self._parse_re('{}\s*(.+?)\n'.format(id), self.ssd_info)

tests/ssd_generic_test.py

+87
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,84 @@
266266
267267
0 5275 0 0x0001 0x0004 - 0 1 -"""
268268

269+
output_Innodisk_missing_names_ssd = """smartctl 6.6 2017-11-05 r4594 [armv7l-linux-4.19.0-12-2-armmp] (local build)
270+
Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org
271+
272+
=== START OF INFORMATION SECTION ===
273+
Model Family: Innodisk 3IE3/3ME3/3ME4 SSDs
274+
Device Model: M.2 (S42) 3ME4
275+
Serial Number: YCA12003110020080
276+
LU WWN Device Id: 5 02b2a2 01d1c1b1a
277+
Firmware Version: L17606
278+
User Capacity: 16,013,942,784 bytes [16.0 GB]
279+
Sector Size: 512 bytes logical/physical
280+
Rotation Rate: Solid State Device
281+
Device is: In smartctl database [for details use: -P show]
282+
ATA Version is: ACS-3 T13/2161-D revision 4
283+
SATA Version is: SATA 3.2, 6.0 Gb/s (current: 6.0 Gb/s)
284+
Local Time is: Tue Apr 26 00:57:00 2022 UTC
285+
SMART support is: Available - device has SMART capability.
286+
SMART support is: Enabled
287+
288+
=== START OF READ SMART DATA SECTION ===
289+
SMART overall-health self-assessment test result: PASSED
290+
291+
General SMART Values:
292+
Offline data collection status: (0x02) Offline data collection activity
293+
was completed without error.
294+
Auto Offline Data Collection: Disabled.
295+
Total time to complete Offline
296+
data collection: ( 32) seconds.
297+
Offline data collection
298+
capabilities: (0x00) Offline data collection not supported.
299+
SMART capabilities: (0x0002) Does not save SMART data before
300+
entering power-saving mode.
301+
Supports SMART auto save timer.
302+
Error logging capability: (0x00) Error logging NOT supported.
303+
General Purpose Logging supported.
304+
305+
SMART Attributes Data Structure revision number: 16
306+
Vendor Specific SMART Attributes with Thresholds:
307+
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
308+
1 Raw_Read_Error_Rate 0x0000 000 000 000 Old_age Offline - 0
309+
2 Throughput_Performance 0x0000 000 000 000 Old_age Offline - 0
310+
5 Later_Bad_Block 0x0012 100 100 001 Old_age Always - 0
311+
7 Seek_Error_Rate 0x0000 000 000 000 Old_age Offline - 0
312+
8 Seek_Time_Performance 0x0000 000 000 000 Old_age Offline - 0
313+
9 Power_On_Hours 0x0012 253 000 000 Old_age Always - 14151
314+
10 Spin_Retry_Count 0x0000 000 000 000 Old_age Offline - 0
315+
12 Power_Cycle_Count 0x0012 036 000 000 Old_age Always - 36
316+
163 Total_Bad_Block_Count 0x0000 000 000 000 Old_age Offline - 9
317+
168 SATA_PHY_Error_Count 0x0000 000 000 000 Old_age Offline - 0
318+
169 Unknown Attribute 0x0000 094 000 000 Old_age Offline - 94
319+
175 Bad_Cluster_Table_Count 0x0000 000 000 000 Old_age Offline - 0
320+
192 Power-Off_Retract_Count 0x0012 000 000 000 Old_age Always - 3
321+
194 Unknown Attribute 0x0002 039 100 000 Old_age Always - 39 (3 42 0 33 0)
322+
197 Current_Pending_Sector 0x0000 000 000 000 Old_age Offline - 0
323+
225 Data_Log_Write_Count 0x0000 000 000 000 Old_age Offline - 0
324+
240 Write_Head 0x0000 000 000 000 Old_age Offline - 0
325+
165 Max_Erase_Count 0x0012 223 100 000 Old_age Always - 223
326+
167 Average_Erase_Count 0x0012 000 100 000 Old_age Always - 187
327+
170 Spare_Block_Count 0x0013 100 100 010 Pre-fail Always - 72
328+
171 Program_Fail_Count 0x0012 000 100 000 Old_age Always - 0
329+
172 Erase_Fail_Count 0x0012 000 100 000 Old_age Always - 0
330+
176 RANGE_RECORD_Count 0x0000 000 000 000 Old_age Offline - 0
331+
184 End-to-End_Error 0x0012 000 000 000 Old_age Always - 0
332+
187 Reported_Uncorrect 0x0012 000 000 000 Old_age Always - 0
333+
229 Flash_ID 0x0000 100 100 000 Old_age Offline - 0x51769394de98
334+
232 Spares_Remaining_Perc 0x0013 000 000 000 Pre-fail Always - 0
335+
235 Later_Bad_Blk_Inf_R/W/E 0x0002 000 000 000 Old_age Always - 0 0 0
336+
241 Host_Writes_32MiB 0x0002 100 100 000 Old_age Always - 14452
337+
242 Host_Reads_32MiB 0x0002 100 100 000 Old_age Always - 42566
338+
339+
SMART Error Log not supported
340+
341+
SMART Self-test Log not supported
342+
343+
Selective Self-tests/Logging not supported
344+
345+
"""
346+
269347
class TestSsdGeneric:
270348
@mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_nvme_ssd))
271349
def test_nvme_ssd(self):
@@ -325,3 +403,12 @@ def test_Innodisk_ssd(self):
325403
assert(Innodisk_ssd.get_temperature() == '0')
326404
assert(Innodisk_ssd.get_serial() == "20171126AAAA11730156")
327405

406+
@mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_Innodisk_missing_names_ssd))
407+
def test_Innodisk_missing_names_ssd(self):
408+
# Test parsing Innodisk ssd info
409+
Innodisk_ssd = SsdUtil('/dev/sda')
410+
Innodisk_ssd.vendor_ssd_info = ''
411+
Innodisk_ssd.parse_vendor_ssd_info('InnoDisk')
412+
assert(Innodisk_ssd.get_health() == '94')
413+
assert(Innodisk_ssd.get_temperature() == '39')
414+

0 commit comments

Comments
 (0)