Skip to content

Commit 082dc93

Browse files
authored
[sonic_ssd] add ssd_emmc.py with EmmcUtil (sonic-net#362)
EmmcUtil class implements SsdBase API and can be used by ssdutil instead of the default SsdUtil class on platforms that have eMMC. The class is copied from Arista platform. Signed-off-by: Yakiv Huryk <[email protected]>
1 parent 9c73610 commit 082dc93

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#
2+
# ssd_emmc.py
3+
#
4+
# Implementation of SSD Utility API for eMMC.
5+
# It reads eMMC health, model, firmware, and serial from /sys/block/*.
6+
#
7+
8+
try:
9+
import os
10+
from .ssd_base import SsdBase
11+
except ImportError as e:
12+
raise ImportError(str(e) + "- required module not found")
13+
14+
15+
class EmmcUtil(SsdBase):
16+
def __init__(self, diskdev):
17+
self.diskdev = diskdev
18+
self.path = os.path.join('/sys/block', os.path.basename(diskdev))
19+
20+
def _read_device_entry(self, entry, default=None):
21+
path = os.path.join(self.path, 'device', entry)
22+
try:
23+
with open(path) as f:
24+
return f.read().rstrip()
25+
except OSError:
26+
return default
27+
28+
def _is_slc(self):
29+
return bool(self._read_device_entry('enhanced_area_offset'))
30+
31+
def get_health(self):
32+
data = self._read_device_entry('life_time')
33+
if data is None:
34+
raise NotImplementedError
35+
value = int(data.split()[0 if self._is_slc() else 1], 0)
36+
return float(100 - (10 * (value - 1)))
37+
38+
def get_temperature(self):
39+
return 'N/A'
40+
41+
def get_model(self):
42+
return self._read_device_entry('name')
43+
44+
def get_firmware(self):
45+
return self._read_device_entry('fwrev')
46+
47+
def get_serial(self):
48+
return self._read_device_entry('serial')
49+
50+
def get_vendor_output(self):
51+
return ''

tests/ssd_emmc_test.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import sys
2+
if sys.version_info.major == 3:
3+
from unittest.mock import mock_open, patch
4+
else:
5+
from mock import mock_open, patch
6+
7+
from sonic_platform_base.sonic_ssd.ssd_emmc import EmmcUtil
8+
9+
mocked_files = {
10+
'/sys/block/emmctest/device/enhanced_area_offset': '0',
11+
'/sys/block/emmctest/device/life_time': '0x02 0x02',
12+
'/sys/block/emmctest/device/name': 'Test eMMC device',
13+
'/sys/block/emmctest/device/fwrev': '0xAA00000000000000',
14+
'/sys/block/emmctest/device/serial': '0xabcdefef'
15+
}
16+
17+
18+
def build_mocked_sys_fs_open(files):
19+
mocks = dict([(fname, mock_open(read_data=cnt).return_value)
20+
for fname, cnt in files.items()])
21+
22+
def mopen(fname):
23+
if fname in mocks:
24+
return mocks[fname]
25+
else:
26+
raise FileNotFoundError(fname)
27+
return mopen
28+
29+
30+
class TestSsdEMMC:
31+
32+
@patch('builtins.open', new=build_mocked_sys_fs_open(mocked_files))
33+
def test_check(self, *args):
34+
util = EmmcUtil('emmctest')
35+
36+
assert (util.get_health() == 90.0)
37+
assert (util.get_temperature() == 'N/A')
38+
assert (util.get_model() == 'Test eMMC device')
39+
assert (util.get_firmware() == '0xAA00000000000000')
40+
assert (util.get_serial() == '0xabcdefef')

0 commit comments

Comments
 (0)