Skip to content

Commit cd623fa

Browse files
authored
[202012] Backport Enhance ssd_generic with more error handling to avoid python crash #273
Signed-off-by: Kebo Liu [email protected] Description Backport #271 to 202012 Judge the self._parse_re return value, if it's N/A then stop further string slice handling to avoid a crash. Update the regular expression pattern for Innodisk SSD health, to handle the case that the output of the health section is different when its lifetime reaches the end. Motivation and Context Original code doesn't handle the case that self._parse_re returns N/A, it's assuming that self._parse_re will always return a none N/A value thus further handling the result w/o judge, which could in a crash. On Innodisk SSD, when the SSD remaining lifetime reaches the end, the output of the Health section will be a number w/o %, e.g. Health: 0.00 instead of Health: 95.0% in the normal case, need to update the regular expression to handle this case. How Has This Been Tested? UT test has been added. Tested the change on platforms with different types of SSD.
1 parent e9a4a81 commit cd623fa

File tree

2 files changed

+256
-3
lines changed

2 files changed

+256
-3
lines changed

sonic_platform_base/sonic_ssd/ssd_generic.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,21 @@ def parse_generic_ssd_info(self):
7777
self.model = self._parse_re('Device Model:\s*(.+?)\n', self.ssd_info)
7878
self.serial = self._parse_re('Serial Number:\s*(.+?)\n', self.ssd_info)
7979
self.firmware = self._parse_re('Firmware Version:\s*(.+?)\n', self.ssd_info)
80-
self.health = self._parse_re('Remaining_Lifetime_Perc\s*(.+?)\n', self.ssd_info).split()[-1]
81-
self.temperature = self._parse_re('Temperature_Celsius\s*(.+?)\n', self.ssd_info).split()[-6]
80+
81+
health_raw = self._parse_re('Remaining_Lifetime_Perc\s*(.+?)\n', self.ssd_info)
82+
if health_raw == NOT_AVAILABLE:
83+
self.health = NOT_AVAILABLE
84+
else:
85+
self.health = health_raw.split()[-1]
86+
87+
temp_raw = self._parse_re('Temperature_Celsius\s*(.+?)\n', self.ssd_info)
88+
if temp_raw == NOT_AVAILABLE:
89+
self.temperature = NOT_AVAILABLE
90+
else:
91+
self.temperature = temp_raw.split()[-6]
8292

8393
def parse_innodisk_info(self):
84-
self.health = self._parse_re('Health:\s*(.+?)%', self.vendor_ssd_info)
94+
self.health = self._parse_re('Health:\s*(.+?)%?', self.vendor_ssd_info)
8595
self.temperature = self._parse_re('Temperature\s*\[\s*(.+?)\]', self.vendor_ssd_info)
8696

8797
def parse_virtium_info(self):

tests/ssd_generic_test.py

+243
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
2+
import sys
3+
if sys.version_info.major == 3:
4+
from unittest import mock
5+
else:
6+
import mock
7+
8+
from sonic_platform_base.sonic_ssd.ssd_generic import SsdUtil
9+
10+
output_ssd = """smartctl 6.6 2017-11-05 r4594 [x86_64-linux-5.10.0-8-2-amd64] (local build)
11+
Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org
12+
13+
=== START OF INFORMATION SECTION ===
14+
Model Family: 3IE3/3ME3/3ME4 SSDs
15+
Device Model: (S42) 3IE3
16+
Serial Number: BCA11712280210689
17+
LU WWN Device Id: 5 24693f 2ca215959
18+
Firmware Version: S16425i
19+
User Capacity: 16,013,942,784 bytes [16.0 GB]
20+
Sector Size: 512 bytes logical/physical
21+
Rotation Rate: Solid State Device
22+
Form Factor: 2.5 inches
23+
Device is: In smartctl database [for details use: -P show]
24+
ATA Version is: ATA8-ACS (minor revision not indicated)
25+
SATA Version is: SATA 3.0, 6.0 Gb/s (current: 6.0 Gb/s)
26+
Local Time is: Thu Mar 31 03:00:15 2022 UTC
27+
SMART support is: Available - device has SMART capability.
28+
SMART support is: Enabled
29+
30+
=== START OF READ SMART DATA SECTION ===
31+
SMART overall-health self-assessment test result: PASSED
32+
33+
General SMART Values:
34+
Offline data collection status: (0x00) Offline data collection activity
35+
was never started.
36+
Auto Offline Data Collection: Disabled.
37+
Total time to complete Offline
38+
data collection: ( 32) seconds.
39+
Offline data collection
40+
capabilities: (0x00) Offline data collection not supported.
41+
SMART capabilities: (0x0003) Saves SMART data before entering
42+
power-saving mode.
43+
Supports SMART auto save timer.
44+
Error logging capability: (0x00) Error logging NOT supported.
45+
No General Purpose Logging support.
46+
SCT capabilities: (0x0039) SCT Status supported.
47+
SCT Error Recovery Control supported.
48+
SCT Feature Control supported.
49+
SCT Data Table supported.
50+
51+
SMART Attributes Data Structure revision number: 16
52+
Vendor Specific SMART Attributes with Thresholds:
53+
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
54+
1 Raw_Read_Error_Rate 0x0000 000 000 000 Old_age Offline - 0
55+
2 Throughput_Performance 0x0000 000 000 000 Old_age Offline - 0
56+
3 Spin_Up_Time 0x0000 000 000 000 Old_age Offline - 0
57+
5 Later_Bad_Block 0x0013 100 100 001 Pre-fail Always - 0
58+
7 Seek_Error_Rate 0x0000 000 000 000 Old_age Offline - 0
59+
8 Seek_Time_Performance 0x0000 000 000 000 Old_age Offline - 0
60+
9 Power_On_Hours 0x0002 030 000 000 Old_age Always - 26142
61+
10 Spin_Retry_Count 0x0000 000 000 000 Old_age Offline - 0
62+
12 Power_Cycle_Count 0x0002 148 000 000 Old_age Always - 7828
63+
163 Total_Bad_Block_Count 0x0000 000 000 000 Old_age Offline - 8
64+
168 SATA_PHY_Error_Count 0x0000 000 000 000 Old_age Offline - 0
65+
169 Remaining_Lifetime_Perc 0x0000 095 000 000 Old_age Offline - 95
66+
175 Bad_Cluster_Table_Count 0x0000 000 000 000 Old_age Offline - 0
67+
192 Power-Off_Retract_Count 0x0000 000 000 000 Old_age Offline - 0
68+
194 Temperature_Celsius 0x0000 030 100 000 Old_age Offline - 30 (2 100 0 0 0)
69+
197 Current_Pending_Sector 0x0012 000 100 000 Old_age Always - 0
70+
225 Data_Log_Write_Count 0x0000 000 029 000 Old_age Offline - 45712577
71+
240 Write_Head 0x0000 000 000 000 Old_age Offline - 0
72+
165 Max_Erase_Count 0x0002 220 001 000 Old_age Always - 988
73+
167 Average_Erase_Count 0x0002 213 001 000 Old_age Always - 981
74+
170 Spare_Block_Count 0x0003 100 001 000 Pre-fail Always - 146
75+
171 Program_Fail_Count 0x0002 000 001 000 Old_age Always - 0
76+
172 Erase_Fail_Count 0x0002 000 001 000 Old_age Always - 0
77+
176 RANGE_RECORD_Count 0x0000 100 001 000 Old_age Offline - 0
78+
187 Reported_Uncorrect 0x0002 000 001 000 Old_age Always - 0
79+
229 Flash_ID 0x0002 100 001 000 Old_age Always - 0x517693943a98
80+
232 Spares_Remaining_Perc 0x0003 100 001 000 Pre-fail Always - 0
81+
235 Later_Bad_Blk_Inf_R/W/E 0x0002 000 000 000 Old_age Always - 0 0 0
82+
241 Host_Writes_32MiB 0x0002 100 001 000 Old_age Always - 178564
83+
242 Host_Reads_32MiB 0x0002 100 001 000 Old_age Always - 760991
84+
85+
SMART Error Log not supported
86+
87+
SMART Self-test Log not supported
88+
89+
Selective Self-tests/Logging not supported"""
90+
91+
output_Innodisk_ssd = """smartctl 6.6 2017-11-05 r4594 [x86_64-linux-4.19.0-12-2-amd64] (local build)
92+
Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org
93+
94+
=== START OF INFORMATION SECTION ===
95+
Model Family: Innodisk 1ME3/3ME/3SE SSDs
96+
Device Model: InnoDisk Corp. - mSATA 3ME
97+
Serial Number: 20171126AAAA11730156
98+
Firmware Version: S140714
99+
User Capacity: 32,017,047,552 bytes [32.0 GB]
100+
Sector Size: 512 bytes logical/physical
101+
Rotation Rate: Solid State Device
102+
Form Factor: 2.5 inches
103+
Device is: In smartctl database [for details use: -P show]
104+
ATA Version is: ACS-2 (minor revision not indicated)
105+
SATA Version is: SATA 3.0, 6.0 Gb/s (current: 6.0 Gb/s)
106+
Local Time is: Thu Mar 31 08:24:17 2022 UTC
107+
SMART support is: Available - device has SMART capability.
108+
SMART support is: Enabled
109+
110+
=== START OF READ SMART DATA SECTION ===
111+
SMART overall-health self-assessment test result: PASSED
112+
113+
General SMART Values:
114+
Offline data collection status: (0x00) Offline data collection activity
115+
was never started.
116+
Auto Offline Data Collection: Disabled.
117+
Total time to complete Offline
118+
data collection: ( 32) seconds.
119+
Offline data collection
120+
capabilities: (0x00) Offline data collection not supported.
121+
SMART capabilities: (0x0003) Saves SMART data before entering
122+
power-saving mode.
123+
Supports SMART auto save timer.
124+
Error logging capability: (0x00) Error logging NOT supported.
125+
General Purpose Logging supported.
126+
SCT capabilities: (0x0039) SCT Status supported.
127+
SCT Error Recovery Control supported.
128+
SCT Feature Control supported.
129+
SCT Data Table supported.
130+
131+
SMART Attributes Data Structure revision number: 16
132+
Vendor Specific SMART Attributes with Thresholds:
133+
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
134+
1 Raw_Read_Error_Rate 0x0000 000 000 000 Old_age Offline - 0
135+
2 Throughput_Performance 0x0000 000 000 000 Old_age Offline - 0
136+
3 Spin_Up_Time 0x0000 000 000 000 Old_age Offline - 0
137+
5 Reallocated_Sector_Ct 0x0002 100 100 000 Old_age Always - 0
138+
7 Seek_Error_Rate 0x0000 000 000 000 Old_age Offline - 0
139+
8 Seek_Time_Performance 0x0000 000 000 000 Old_age Offline - 0
140+
9 Power_On_Hours 0x0002 100 100 000 Old_age Always - 32474
141+
10 Spin_Retry_Count 0x0000 000 000 000 Old_age Offline - 0
142+
12 Power_Cycle_Count 0x0002 100 100 000 Old_age Always - 297
143+
168 SATA_PHY_Error_Count 0x0000 000 000 000 Old_age Offline - 0
144+
169 Unknown_Innodisk_Attr 0x0000 000 000 000 Old_age Offline - 0x000000000000
145+
175 Bad_Cluster_Table_Count 0x0000 000 000 000 Old_age Offline - 0
146+
192 Power-Off_Retract_Count 0x0000 000 000 000 Old_age Offline - 0
147+
1 Raw_Read_Error_Rate 0x0000 000 000 000 Old_age Offline - 2199023255552
148+
197 Current_Pending_Sector 0x0000 000 000 000 Old_age Offline - 0
149+
240 Write_Head 0x0000 000 000 000 Old_age Offline - 0
150+
225 Unknown_Innodisk_Attr 0x0000 000 000 000 Old_age Offline - 0
151+
170 Bad_Block_Count 0x0003 100 100 --- Pre-fail Always - 0 47 0
152+
173 Erase_Count 0x0002 100 100 --- Old_age Always - 0 7280 7192
153+
229 Flash_ID 0x0002 100 100 --- Old_age Always - 0x50769394de98
154+
236 Unstable_Power_Count 0x0002 100 100 --- Old_age Always - 0
155+
235 Later_Bad_Block 0x0002 100 000 --- Old_age Always - 0
156+
176 Uncorr_RECORD_Count 0x0000 100 000 --- Old_age Offline - 0
157+
158+
Read SMART Log Directory failed: scsi error badly formed scsi parameters
159+
160+
SMART Error Log not supported
161+
162+
SMART Self-test Log not supported
163+
164+
Selective Self-tests/Logging not supported
165+
166+
"""
167+
168+
output_Innodisk_vendor_info = """********************************************************************************************
169+
* Innodisk iSMART V3.9.41 2018/05/25 *
170+
********************************************************************************************
171+
Model Name: InnoDisk Corp. - mSATA 3ME
172+
FW Version: S140714
173+
Serial Number: 20171126AAAA11730156
174+
Health: 0.00
175+
Capacity: 29.818199 GB
176+
P/E Cycle: 3000
177+
Lifespan : 0 (Years : 0 Months : 0 Days : 0)
178+
Write Protect: Disable
179+
InnoRobust: Enable
180+
--------------------------------------------------------------------------------------------
181+
ID SMART Attributes Value Raw Value
182+
--------------------------------------------------------------------------------------------
183+
[09] Power On Hours [32474] [0902006464DA7E0000000000]
184+
[0C] Power Cycle Count [ 297] [0C0200646429010000000000]
185+
[AA] Total Bad Block Count [ 47] [AA0300646400002F00000000]
186+
[AD] Erase Count Max. [ 7280] [AD02006464181C701C000000]
187+
[AD] Erase Count Avg. [ 7192] [AD02006464181C701C000000]
188+
[C2] Temperature [ 0] [000000000000000000000000]
189+
[EB] Later Bad Block [ 0] [EB0200640000000000000000]
190+
[EB] Read Block [ 0] [EB0200640000000000000000]
191+
[EB] Write Block [ 0] [EB0200640000000000000000]
192+
[EB] Erase Block [ 0] [EB0200640000000000000000]
193+
[EC] Unstable Power Count [ 0] [EC0200646400000000000000]
194+
"""
195+
196+
output_lack_info_ssd = """smartctl 7.2 2020-12-30 r5155 [x86_64-linux-5.10.0-8-2-amd64] (local build)
197+
Copyright (C) 2002-20, Bruce Allen, Christian Franke, www.smartmontools.org
198+
199+
=== START OF INFORMATION SECTION ===
200+
201+
=== START OF SMART DATA SECTION ===
202+
203+
0 5275 0 0x0001 0x0004 - 0 1 -"""
204+
205+
class TestSsdGeneric:
206+
@mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_ssd))
207+
def test_ssd(self):
208+
# Test parsing a normal ssd info
209+
ssd = SsdUtil('/dev/sda')
210+
assert(ssd.get_health() == '95')
211+
assert(ssd.get_model() == '(S42) 3IE3')
212+
assert(ssd.get_firmware() == 'S16425i')
213+
assert(ssd.get_temperature() == '30')
214+
assert(ssd.get_serial() == 'BCA11712280210689')
215+
216+
@mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_lack_info_ssd))
217+
def test_ssd_with_na_path(self):
218+
# Test parsing normal ssd info which lack of expected sections
219+
ssd = SsdUtil('/dev/sda')
220+
assert(ssd.get_health() == 'N/A')
221+
assert(ssd.get_model() == 'N/A')
222+
assert(ssd.get_firmware() == "N/A")
223+
assert(ssd.get_temperature() == "N/A")
224+
assert(ssd.get_serial() == "N/A")
225+
226+
@mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_Innodisk_ssd))
227+
def test_Innodisk_ssd(self):
228+
# Test parsing Innodisk ssd info
229+
Innodisk_ssd = SsdUtil('/dev/sda')
230+
assert(Innodisk_ssd.get_health() == 'N/A')
231+
assert(Innodisk_ssd.get_model() == 'InnoDisk Corp. - mSATA 3ME')
232+
assert(Innodisk_ssd.get_firmware() == "S140714")
233+
assert(Innodisk_ssd.get_temperature() == 'N/A')
234+
assert(Innodisk_ssd.get_serial() == "20171126AAAA11730156")
235+
236+
Innodisk_ssd.vendor_ssd_info = output_Innodisk_vendor_info
237+
Innodisk_ssd.parse_vendor_ssd_info('InnoDisk')
238+
assert(Innodisk_ssd.get_health() == '0')
239+
assert(Innodisk_ssd.get_model() == 'InnoDisk Corp. - mSATA 3ME')
240+
assert(Innodisk_ssd.get_firmware() == "S140714")
241+
assert(Innodisk_ssd.get_temperature() == '0')
242+
assert(Innodisk_ssd.get_serial() == "20171126AAAA11730156")
243+

0 commit comments

Comments
 (0)