Skip to content

Commit 1adf47b

Browse files
authored
[chassisd] Add script to initialize chassis info in STATE_DB (sonic-net#183)
#### Description I added a new script `chassis_db_init` that uploads chassis hardware information such as serial number, model number and hardware revision to the STATE_DB under the CHASSIS_INFO table. #### Motivation and Context I made this change in order to expose the chassis hardware information to SONiC user space and allow CLI utilities to access it in order to expose it to the user.
1 parent e60804c commit 1adf47b

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
chassis_db_init
5+
Chassis information update tool for SONiC
6+
This tool runs one time at the launch of the platform monitor in order to populate STATE_DB with chassis information such as model, serial number, and revision.
7+
"""
8+
9+
try:
10+
import os
11+
import sys
12+
13+
from sonic_py_common import daemon_base, logger
14+
15+
# If unit testing is occurring, mock swsscommon and module_base
16+
if os.getenv("CHASSIS_DB_INIT_UNIT_TESTING") == "1":
17+
from tests import mock_swsscommon as swsscommon
18+
else:
19+
from swsscommon import swsscommon
20+
except ImportError as e:
21+
raise ImportError(str(e) + " - required module not found")
22+
23+
#
24+
# Constants
25+
#
26+
27+
SYSLOG_IDENTIFIER = "chassis_db_init"
28+
29+
CHASSIS_INFO_TABLE = 'CHASSIS_INFO'
30+
CHASSIS_INFO_KEY_TEMPLATE = 'chassis {}'
31+
CHASSIS_INFO_CARD_NUM_FIELD = 'module_num'
32+
CHASSIS_INFO_SERIAL_FIELD = 'serial'
33+
CHASSIS_INFO_MODEL_FIELD = 'model'
34+
CHASSIS_INFO_REV_FIELD = 'revision'
35+
36+
CHASSIS_LOAD_ERROR = 1
37+
38+
NOT_AVAILABLE = 'N/A'
39+
40+
#
41+
# Helper functions =============================================================
42+
#
43+
44+
# try get information from platform API and return a default value if caught NotImplementedError
45+
46+
47+
def try_get(callback, *args, **kwargs):
48+
"""
49+
Handy function to invoke the callback and catch NotImplementedError
50+
:param callback: Callback to be invoked
51+
:param args: Arguments to be passed to callback
52+
:param kwargs: Default return value if exception occur
53+
:return: Default return value if exception occur else return value of the callback
54+
"""
55+
default = kwargs.get('default', NOT_AVAILABLE)
56+
try:
57+
ret = callback(*args)
58+
if ret is None:
59+
ret = default
60+
except NotImplementedError:
61+
ret = default
62+
63+
return ret
64+
65+
#
66+
# Functions
67+
#
68+
69+
def provision_db(platform_chassis, log):
70+
# Init state db connection
71+
state_db = daemon_base.db_connect("STATE_DB")
72+
chassis_table = swsscommon.Table(state_db, CHASSIS_INFO_TABLE)
73+
74+
# Populate DB with chassis hardware info
75+
fvs = swsscommon.FieldValuePairs([
76+
(CHASSIS_INFO_SERIAL_FIELD, try_get(platform_chassis.get_serial)),
77+
(CHASSIS_INFO_MODEL_FIELD, try_get(platform_chassis.get_model)),
78+
(CHASSIS_INFO_REV_FIELD, try_get(platform_chassis.get_revision))
79+
])
80+
chassis_table.set(CHASSIS_INFO_KEY_TEMPLATE.format(1), fvs)
81+
log.log_info("STATE_DB provisioned with chassis info.")
82+
83+
return chassis_table
84+
85+
86+
#
87+
# Main
88+
#
89+
90+
def main():
91+
log = logger.Logger(SYSLOG_IDENTIFIER)
92+
log.log_info("Provisioning Database with Chassis Info...")
93+
94+
# Load platform api class
95+
try:
96+
import sonic_platform.platform
97+
platform_chassis = sonic_platform.platform.Platform().get_chassis()
98+
except Exception as e:
99+
log.log_error("Failed to load chassis due to {}".format(repr(e)))
100+
sys.exit(CHASSIS_LOAD_ERROR)
101+
102+
provision_db(platform_chassis, log)
103+
104+
if __name__ == '__main__':
105+
main()

sonic-chassisd/setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
],
1616
scripts=[
1717
'scripts/chassisd',
18+
'scripts/chassis_db_init'
1819
],
1920
setup_requires=[
2021
'pytest-runner',

sonic-chassisd/tests/mock_platform.py

+9
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,12 @@ def get_module_index(self, module_name):
9292

9393
def init_midplane_switch(self):
9494
return True
95+
96+
def get_serial(self):
97+
return "Serial No"
98+
99+
def get_model(self):
100+
return "Model A"
101+
102+
def get_revision(self):
103+
return "Rev C"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import os
2+
import sys
3+
from imp import load_source
4+
5+
from mock import Mock, MagicMock, patch
6+
from sonic_py_common import daemon_base
7+
8+
from .mock_platform import MockChassis, MockModule
9+
from .mock_module_base import ModuleBase
10+
11+
SYSLOG_IDENTIFIER = 'chassis_db_init_test'
12+
NOT_AVAILABLE = 'N/A'
13+
14+
daemon_base.db_connect = MagicMock()
15+
16+
test_path = os.path.dirname(os.path.abspath(__file__))
17+
modules_path = os.path.dirname(test_path)
18+
scripts_path = os.path.join(modules_path, "scripts")
19+
sys.path.insert(0, modules_path)
20+
21+
os.environ["CHASSIS_DB_INIT_UNIT_TESTING"] = "1"
22+
load_source('chassis_db_init', scripts_path + '/chassis_db_init')
23+
from chassis_db_init import *
24+
25+
26+
def test_provision_db():
27+
chassis = MockChassis()
28+
log = MagicMock()
29+
serial = "Serial No"
30+
model = "Model A"
31+
revision = "Rev C"
32+
33+
chassis_table = provision_db(chassis, log)
34+
35+
fvs = chassis_table.get(CHASSIS_INFO_KEY_TEMPLATE.format(1))
36+
assert serial == fvs[CHASSIS_INFO_SERIAL_FIELD]
37+
assert model == fvs[CHASSIS_INFO_MODEL_FIELD]
38+
assert revision == fvs[CHASSIS_INFO_REV_FIELD]

0 commit comments

Comments
 (0)