Skip to content

Commit f41ecca

Browse files
authored
Implementation of a Monitoring Daemon for storage devices in SONiC switches (sonic-net#433)
* Initial commit of ssdmond
1 parent 28302d4 commit f41ecca

File tree

16 files changed

+1026
-0
lines changed

16 files changed

+1026
-0
lines changed

azure-pipelines.yml

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ parameters:
5656
- name: sensormond
5757
root_dir: sonic-sensormond
5858
python3: true
59+
- name: stormond
60+
root_dir: sonic-stormond
61+
python3: true
5962
- name: artifactBranch
6063
type: string
6164
default: 'refs/heads/master'

sonic-stormond/pytest.ini

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[pytest]
2+
addopts = --cov=scripts --cov-report html --cov-report term --cov-report xml --junitxml=test-results.xml -vv

sonic-stormond/scripts/stormond

+401
Large diffs are not rendered by default.

sonic-stormond/setup.cfg

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[aliases]
2+
test=pytest

sonic-stormond/setup.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from setuptools import setup
2+
3+
setup(
4+
name='sonic-stormond',
5+
version='1.0',
6+
description='Storage Device Monitoring Daemon for SONiC',
7+
license='Apache 2.0',
8+
author='SONiC Team',
9+
author_email='linuxnetdev@microsoft.com',
10+
url='https://github.com/sonic-net/sonic-platform-daemons',
11+
maintainer='Ashwin Srinivasan',
12+
maintainer_email='assrinivasan@microsoft.com',
13+
scripts=[
14+
'scripts/stormond',
15+
],
16+
setup_requires=[
17+
'pytest-runner',
18+
'wheel'
19+
],
20+
install_requires=[
21+
'enum34',
22+
'sonic-py-common',
23+
],
24+
tests_require=[
25+
'mock>=2.0.0',
26+
'pytest',
27+
'pytest-cov',
28+
],
29+
classifiers=[
30+
'Development Status :: 4 - Beta',
31+
'Environment :: No Input/Output (Daemon)',
32+
'Intended Audience :: Developers',
33+
'Intended Audience :: Information Technology',
34+
'Intended Audience :: System Administrators',
35+
'License :: OSI Approved :: Apache Software License',
36+
'Natural Language :: English',
37+
'Operating System :: POSIX :: Linux',
38+
'Topic :: System :: Hardware',
39+
],
40+
keywords='sonic SONiC ssd Ssd SSD ssdmond storage stormond storagemond',
41+
test_suite='setup.get_test_suite'
42+
)

sonic-stormond/tests/__init__.py

Whitespace-only changes.
+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
'''
2+
Mock implementation of swsscommon package for unit testing
3+
'''
4+
5+
from swsssdk import ConfigDBConnector, SonicDBConfig, SonicV2Connector
6+
7+
STATE_DB = ''
8+
9+
10+
class Table:
11+
def __init__(self, db, table_name):
12+
self.table_name = table_name
13+
self.mock_dict = {}
14+
self.mock_keys = ['sda']
15+
16+
def _del(self, key):
17+
del self.mock_dict[key]
18+
pass
19+
20+
def set(self, key, fvs):
21+
self.mock_dict[key] = fvs.fv_dict
22+
pass
23+
24+
def get(self, key):
25+
if key in self.mock_dict:
26+
return self.mock_dict[key]
27+
return None
28+
29+
def get_size(self):
30+
return (len(self.mock_dict))
31+
32+
def getKeys(self):
33+
return self.mock_keys
34+
35+
def hgetall(self):
36+
return self.mock_dict
37+
38+
39+
class FieldValuePairs:
40+
fv_dict = {}
41+
42+
def __init__(self, tuple_list):
43+
if isinstance(tuple_list, list) and isinstance(tuple_list[0], tuple):
44+
self.fv_dict = dict(tuple_list)
45+
46+
def __setitem__(self, key, kv_tuple):
47+
self.fv_dict[kv_tuple[0]] = kv_tuple[1]
48+
49+
def __getitem__(self, key):
50+
return self.fv_dict[key]
51+
52+
def __eq__(self, other):
53+
if not isinstance(other, FieldValuePairs):
54+
# don't attempt to compare against unrelated types
55+
return NotImplemented
56+
57+
return self.fv_dict == other.fv_dict
58+
59+
def __repr__(self):
60+
return repr(self.fv_dict)
61+
62+
def __str__(self):
63+
return repr(self.fv_dict)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"""
2+
Mock implementation of sonic_platform package for unit testing
3+
"""
4+
5+
from . import pcie
6+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""
2+
Mock implementation of sonic_platform package for unit testing
3+
"""
4+
5+
from sonic_platform_base.pcie_base import PcieBase
6+
7+
8+
class Pcie(PcieBase):
9+
def __init__(self):
10+
self.platform_pcieutil = "/tmp/Pcie"
11+
12+
def __str__(self):
13+
return self.platform_pcieutil
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

sonic-stormond/tests/mocked_libs/sonic_platform_base/sonic_storage/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#
2+
# storage_base.py
3+
#
4+
# Base class for implementing common SSD health features
5+
#
6+
7+
8+
class StorageBase(object):
9+
"""
10+
Base class for interfacing with a SSD
11+
"""
12+
def __init__(self, diskdev):
13+
"""
14+
Constructor
15+
16+
Args:
17+
diskdev: Linux device name to get parameters for
18+
"""
19+
pass
20+
21+
def get_health(self):
22+
"""
23+
Retrieves current disk health in percentages
24+
25+
Returns:
26+
A float number of current ssd health
27+
e.g. 83.5
28+
"""
29+
raise NotImplementedError
30+
31+
def get_temperature(self):
32+
"""
33+
Retrieves current disk temperature in Celsius
34+
35+
Returns:
36+
A float number of current temperature in Celsius
37+
e.g. 40.1
38+
"""
39+
raise NotImplementedError
40+
41+
def get_model(self):
42+
"""
43+
Retrieves model for the given disk device
44+
45+
Returns:
46+
A string holding disk model as provided by the manufacturer
47+
"""
48+
raise NotImplementedError
49+
50+
def get_firmware(self):
51+
"""
52+
Retrieves firmware version for the given disk device
53+
54+
Returns:
55+
A string holding disk firmware version as provided by the manufacturer
56+
"""
57+
raise NotImplementedError
58+
59+
def get_serial(self):
60+
"""
61+
Retrieves serial number for the given disk device
62+
63+
Returns:
64+
A string holding disk serial number as provided by the manufacturer
65+
"""
66+
raise NotImplementedError
67+
68+
def get_vendor_output(self):
69+
"""
70+
Retrieves vendor specific data for the given disk device
71+
72+
Returns:
73+
A string holding some vendor specific disk information
74+
"""
75+
raise NotImplementedError
76+
77+
def get_disk_io_reads(self):
78+
"""
79+
Retrieves the total number of Input/Output (I/O) reads done on a storage disk
80+
81+
Returns:
82+
An integer value of the total number of I/O reads
83+
"""
84+
raise NotImplementedError
85+
86+
def get_disk_io_writes(self):
87+
"""
88+
Retrieves the total number of Input/Output (I/O) writes done on a storage disk
89+
90+
Returns:
91+
An integer value of the total number of I/O writes
92+
"""
93+
raise NotImplementedError
94+
95+
def get_reserved_blocks(self):
96+
"""
97+
Retrieves the total number of reserved blocks in an storage disk
98+
99+
Returns:
100+
An integer value of the total number of reserved blocks
101+
"""
102+
raise NotImplementedError
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
BLKDEV_BASE_PATH = ''
3+
4+
class StorageDevices:
5+
def __init__(self):
6+
self.devices = {'sda' : None}
7+
8+
def _get_storage_devices(self):
9+
pass
10+
11+
def _storage_device_object_factory(self, key):
12+
pass
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'''
2+
Mock implementation of swsscommon package for unit testing
3+
'''
4+
5+
from . import swsscommon
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
'''
2+
Mock implementation of swsscommon package for unit testing
3+
'''
4+
5+
STATE_DB = ''
6+
7+
8+
class Table:
9+
def __init__(self, db, table_name):
10+
self.table_name = table_name
11+
self.mock_dict = {}
12+
13+
def _del(self, key):
14+
del self.mock_dict[key]
15+
pass
16+
17+
def set(self, key, fvs):
18+
self.mock_dict[key] = fvs.fv_dict
19+
pass
20+
21+
def get(self, key):
22+
if key in self.mock_dict:
23+
return self.mock_dict[key]
24+
return None
25+
26+
def get_size(self):
27+
return (len(self.mock_dict))
28+
29+
def getKeys(self):
30+
return list(self.mock_dict.keys())
31+
32+
33+
class FieldValuePairs:
34+
fv_dict = {}
35+
36+
def __init__(self, tuple_list):
37+
if isinstance(tuple_list, list) and isinstance(tuple_list[0], tuple):
38+
self.fv_dict = dict(tuple_list)
39+
40+
def __setitem__(self, key, kv_tuple):
41+
self.fv_dict[kv_tuple[0]] = kv_tuple[1]
42+
43+
def __getitem__(self, key):
44+
return self.fv_dict[key]
45+
46+
def __eq__(self, other):
47+
if not isinstance(other, FieldValuePairs):
48+
# don't attempt to compare against unrelated types
49+
return NotImplemented
50+
51+
return self.fv_dict == other.fv_dict
52+
53+
def __repr__(self):
54+
return repr(self.fv_dict)
55+
56+
def __str__(self):
57+
return repr(self.fv_dict)
58+
59+
class ConfigDBConnector:
60+
pass
61+
62+
class SonicDBConfig:
63+
pass
64+
65+
class SonicV2Connector:
66+
pass

0 commit comments

Comments
 (0)