Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chassisd] Add script to initialize chassis info in STATE_DB #183

Merged
merged 3 commits into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions sonic-chassisd/scripts/chassis_db_init
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/usr/bin/env python3

"""
chassis_db_init
Chassis information update tool for SONiC
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.
"""

try:
import os
import sys

from sonic_py_common import daemon_base, logger

# If unit testing is occurring, mock swsscommon and module_base
if os.getenv("CHASSIS_DB_INIT_UNIT_TESTING") == "1":
from tests import mock_swsscommon as swsscommon
else:
from swsscommon import swsscommon
except ImportError as e:
raise ImportError(str(e) + " - required module not found")

#
# Constants
#

SYSLOG_IDENTIFIER = "chassis_db_init"

CHASSIS_INFO_TABLE = 'CHASSIS_INFO'
CHASSIS_INFO_KEY_TEMPLATE = 'chassis {}'
CHASSIS_INFO_CARD_NUM_FIELD = 'module_num'
CHASSIS_INFO_SERIAL_FIELD = 'serial'
CHASSIS_INFO_MODEL_FIELD = 'model'
CHASSIS_INFO_REV_FIELD = 'revision'

CHASSIS_LOAD_ERROR = 1

NOT_AVAILABLE = 'N/A'

#
# Helper functions =============================================================
#

# try get information from platform API and return a default value if caught NotImplementedError


def try_get(callback, *args, **kwargs):
"""
Handy function to invoke the callback and catch NotImplementedError
:param callback: Callback to be invoked
:param args: Arguments to be passed to callback
:param kwargs: Default return value if exception occur
:return: Default return value if exception occur else return value of the callback
"""
default = kwargs.get('default', NOT_AVAILABLE)
try:
ret = callback(*args)
if ret is None:
ret = default
except NotImplementedError:
ret = default

return ret

#
# Functions
#

def provision_db(platform_chassis, log):
# Init state db connection
state_db = daemon_base.db_connect("STATE_DB")
chassis_table = swsscommon.Table(state_db, CHASSIS_INFO_TABLE)

# Populate DB with chassis hardware info
fvs = swsscommon.FieldValuePairs([
(CHASSIS_INFO_SERIAL_FIELD, try_get(platform_chassis.get_serial)),
(CHASSIS_INFO_MODEL_FIELD, try_get(platform_chassis.get_model)),
(CHASSIS_INFO_REV_FIELD, try_get(platform_chassis.get_revision))
])
chassis_table.set(CHASSIS_INFO_KEY_TEMPLATE.format(1), fvs)
log.log_info("STATE_DB provisioned with chassis info.")

return chassis_table


#
# Main
#

def main():
log = logger.Logger(SYSLOG_IDENTIFIER)
log.log_info("Provisioning Database with Chassis Info...")

# Load platform api class
try:
import sonic_platform.platform
platform_chassis = sonic_platform.platform.Platform().get_chassis()
except Exception as e:
log.log_error("Failed to load chassis due to {}".format(repr(e)))
sys.exit(CHASSIS_LOAD_ERROR)

provision_db(platform_chassis, log)

if __name__ == '__main__':
main()
1 change: 1 addition & 0 deletions sonic-chassisd/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
],
scripts=[
'scripts/chassisd',
'scripts/chassis_db_init'
],
setup_requires=[
'pytest-runner',
Expand Down
9 changes: 9 additions & 0 deletions sonic-chassisd/tests/mock_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,12 @@ def get_module_index(self, module_name):

def init_midplane_switch(self):
return True

def get_serial(self):
return "Serial No"

def get_model(self):
return "Model A"

def get_revision(self):
return "Rev C"
40 changes: 40 additions & 0 deletions sonic-chassisd/tests/test_chassis_db_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import os
import sys
from imp import load_source

from mock import Mock, MagicMock, patch
from sonic_py_common import daemon_base

from .mock_platform import MockChassis, MockModule
from .mock_module_base import ModuleBase

SYSLOG_IDENTIFIER = 'chassis_db_init_test'
NOT_AVAILABLE = 'N/A'

daemon_base.db_connect = MagicMock()

test_path = os.path.dirname(os.path.abspath(__file__))
modules_path = os.path.dirname(test_path)
scripts_path = os.path.join(modules_path, "scripts")
sys.path.insert(0, modules_path)

os.environ["CHASSIS_DB_INIT_UNIT_TESTING"] = "1"
load_source('chassis_db_init', scripts_path + '/chassis_db_init')
from chassis_db_init import *


def test_provision_db():
chassis = MockChassis()
log = MagicMock()
serial = "Serial No"
model = "Model A"
revision = "Rev C"

chassis_table = provision_db(chassis, log)

fvs = chassis_table.get(CHASSIS_INFO_KEY_TEMPLATE.format(1))
assert serial == fvs[CHASSIS_INFO_SERIAL_FIELD]
assert model == fvs[CHASSIS_INFO_MODEL_FIELD]
assert revision == fvs[CHASSIS_INFO_REV_FIELD]


alexrallen marked this conversation as resolved.
Show resolved Hide resolved