-
Notifications
You must be signed in to change notification settings - Fork 113
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
Added logic to get PSU info directly from the state DB #101
Merged
lguohan
merged 3 commits into
sonic-net:master
from
nazariig:master-get-psu-info-from-db
Apr 3, 2019
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,48 @@ | ||
import imp | ||
import re | ||
import sys | ||
|
||
from enum import Enum, unique | ||
from sonic_ax_impl import mibs | ||
from ax_interface import MIBMeta, ValueType, MIBUpdater, MIBEntry, SubtreeMIBEntry | ||
from ax_interface.encodings import ObjectIdentifier | ||
from ax_interface import MIBMeta, ValueType, SubtreeMIBEntry | ||
from swsssdk import SonicV2Connector | ||
|
||
CHASSIS_INFO_KEY_TEMPLATE = 'chassis {}' | ||
PSU_INFO_KEY_TEMPLATE = 'PSU {}' | ||
|
||
PSU_PRESENCE_OK = 'true' | ||
PSU_STATUS_OK = 'true' | ||
|
||
@unique | ||
class CHASSISInfoDB(bytes, Enum): | ||
""" | ||
CHASSIS info keys | ||
""" | ||
|
||
PSU_NUM = b"psu_num" | ||
|
||
@unique | ||
class PSUInfoDB(bytes, Enum): | ||
""" | ||
PSU info keys | ||
""" | ||
|
||
PRESENCE = b"presence" | ||
STATUS = b"status" | ||
|
||
def get_chassis_data(chassis_info): | ||
""" | ||
:param chassis_info: chassis info dict | ||
:return: tuple (psu_num) of chassis; | ||
Empty string if field not in chassis_info | ||
""" | ||
|
||
return tuple(chassis_info.get(chassis_field.value, b"").decode() for chassis_field in CHASSISInfoDB) | ||
|
||
def get_psu_data(psu_info): | ||
""" | ||
:param psu_info: psu info dict | ||
:return: tuple (presence, status) of psu; | ||
Empty string if field not in psu_info | ||
""" | ||
|
||
PSU_PLUGIN_MODULE_NAME = 'psuutil' | ||
PSU_PLUGIN_MODULE_PATH = "/usr/share/sonic/platform/plugins/{}.py".format(PSU_PLUGIN_MODULE_NAME) | ||
PSU_PLUGIN_CLASS_NAME = 'PsuUtil' | ||
return tuple(psu_info.get(psu_field.value, b"").decode() for psu_field in PSUInfoDB) | ||
|
||
class PowerStatusHandler: | ||
""" | ||
|
@@ -18,38 +52,57 @@ def __init__(self): | |
""" | ||
init the handler | ||
""" | ||
self.psuutil = None | ||
self.statedb = SonicV2Connector() | ||
self.statedb.connect(self.statedb.STATE_DB) | ||
|
||
try: | ||
module = imp.load_source(PSU_PLUGIN_MODULE_NAME, PSU_PLUGIN_MODULE_PATH) | ||
except ImportError as e: | ||
mibs.logger.error("Failed to load PSU module '%s': %s" % (PSU_PLUGIN_MODULE_NAME, str(e)), True) | ||
return | ||
except FileNotFoundError as e: | ||
mibs.logger.error("Failed to get platform specific PSU module '%s': %s" % (PSU_PLUGIN_MODULE_NAME, str(e)), True) | ||
return | ||
def _get_num_psus(self): | ||
""" | ||
Get PSU number | ||
:return: the number of supported PSU | ||
""" | ||
chassis_name = CHASSIS_INFO_KEY_TEMPLATE.format(1) | ||
chassis_info = self.statedb.get_all(self.statedb.STATE_DB, mibs.chassis_info_table(chassis_name)) | ||
num_psus = get_chassis_data(chassis_info) | ||
|
||
try: | ||
platform_psuutil_class = getattr(module, PSU_PLUGIN_CLASS_NAME) | ||
self.psuutil = platform_psuutil_class() | ||
except AttributeError as e: | ||
mibs.logger.error("Failed to instantiate '%s' class: %s" % (PLATFORM_SPECIFIC_CLASS_NAME, str(e)), True) | ||
return int(num_psus[0]) | ||
|
||
def _get_psu_presence(self, psu_index): | ||
""" | ||
Get PSU presence | ||
:return: the presence of particular PSU | ||
""" | ||
psu_name = PSU_INFO_KEY_TEMPLATE.format(psu_index) | ||
psu_info = self.statedb.get_all(self.statedb.STATE_DB, mibs.psu_info_table(psu_name)) | ||
presence, status = get_psu_data(psu_info) | ||
|
||
return presence == PSU_PRESENCE_OK | ||
|
||
def _getPsuIndex(self, sub_id): | ||
def _get_psu_status(self, psu_index): | ||
""" | ||
Get PSU status | ||
:return: the status of particular PSU | ||
""" | ||
psu_name = PSU_INFO_KEY_TEMPLATE.format(psu_index) | ||
psu_info = self.statedb.get_all(self.statedb.STATE_DB, mibs.psu_info_table(psu_name)) | ||
presence, status = get_psu_data(psu_info) | ||
|
||
return status == PSU_STATUS_OK | ||
|
||
def _get_psu_index(self, sub_id): | ||
""" | ||
Get the PSU index from sub_id | ||
:return: the index of supported PSU | ||
""" | ||
if not self.psuutil or not sub_id or len(sub_id) > 1: | ||
if not sub_id or len(sub_id) > 1: | ||
return None | ||
|
||
psu_index = int(sub_id[0]) | ||
|
||
try: | ||
num_psus = self.psuutil.get_num_psus() | ||
num_psus = self._get_num_psus() | ||
except Exception: | ||
# Any unexpected exception or error, log it and keep running | ||
mibs.logger.exception("PowerStatusHandler._getPsuIndex() caught an unexpected exception during get_num_psus()") | ||
mibs.logger.exception("PowerStatusHandler._get_psu_index() caught an unexpected exception during _get_num_psus()") | ||
return None | ||
|
||
if psu_index < 1 or psu_index > num_psus: | ||
|
@@ -62,27 +115,23 @@ def get_next(self, sub_id): | |
:param sub_id: The 1-based snmp sub-identifier query. | ||
:return: the next sub id. | ||
""" | ||
if not self.psuutil: | ||
return None | ||
|
||
if not sub_id: | ||
return (1,) | ||
|
||
psu_index = self._getPsuIndex(sub_id) | ||
psu_index = self._get_psu_index(sub_id) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This is a sample:
|
||
try: | ||
num_psus = self.psuutil.get_num_psus() | ||
num_psus = self._get_num_psus() | ||
except Exception: | ||
# Any unexpected exception or error, log it and keep running | ||
mibs.logger.exception("PowerStatusHandler.get_next() caught an unexpected exception during get_num_psus()") | ||
mibs.logger.exception("PowerStatusHandler.get_next() caught an unexpected exception during _get_num_psus()") | ||
return None | ||
|
||
|
||
if psu_index and psu_index + 1 <= num_psus: | ||
return (psu_index + 1,) | ||
|
||
return None | ||
|
||
def getPsuStatus(self, sub_id): | ||
def get_psu_status(self, sub_id): | ||
""" | ||
:param sub_id: The 1-based sub-identifier query. | ||
:return: the status of requested PSU according to cefcModuleOperStatus ModuleOperType | ||
|
@@ -91,24 +140,24 @@ def getPsuStatus(self, sub_id): | |
8 - the module is provisioned, but it is missing. This is a failure state. | ||
:ref: https://www.cisco.com/c/en/us/td/docs/switches/wan/mgx/mgx_8850/software/mgx_r2-0-10/pxm/reference/guide/pxm/cscoent.html | ||
""" | ||
psu_index = self._getPsuIndex(sub_id) | ||
psu_index = self._get_psu_index(sub_id) | ||
|
||
if not psu_index: | ||
return None | ||
|
||
try: | ||
psu_presence = self.psuutil.get_psu_presence(psu_index) | ||
psu_presence = self._get_psu_presence(psu_index) | ||
except Exception: | ||
# Any unexpected exception or error, log it and keep running | ||
mibs.logger.exception("PowerStatusHandler.getPsuStatus() caught an unexpected exception during get_psu_presence()") | ||
mibs.logger.exception("PowerStatusHandler.get_psu_status() caught an unexpected exception during _get_psu_presence()") | ||
return None | ||
|
||
if psu_presence: | ||
try: | ||
psu_status = self.psuutil.get_psu_status(psu_index) | ||
psu_status = self._get_psu_status(psu_index) | ||
except Exception: | ||
# Any unexpected exception or error, log it and keep running | ||
mibs.logger.exception("PowerStatusHandler.getPsuStatus() caught an unexpected exception during get_psu_status()") | ||
mibs.logger.exception("PowerStatusHandler.get_psu_status() caught an unexpected exception during _get_psu_status()") | ||
return None | ||
|
||
if psu_status: | ||
|
@@ -118,7 +167,6 @@ def getPsuStatus(self, sub_id): | |
else: | ||
return 8 | ||
|
||
|
||
class cefcFruPowerStatusTable(metaclass=MIBMeta, prefix='.1.3.6.1.4.1.9.9.117.1.1.2'): | ||
""" | ||
'cefcFruPowerStatusTable' http://oidref.com/1.3.6.1.4.1.9.9.117.1.1.2 | ||
|
@@ -129,4 +177,4 @@ class cefcFruPowerStatusTable(metaclass=MIBMeta, prefix='.1.3.6.1.4.1.9.9.117.1. | |
# cefcFruPowerStatusTable = '1.3.6.1.4.1.9.9.117.1.1.2' | ||
# csqIfQosGroupStatsEntry = '1.3.6.1.4.1.9.9.117.1.1.2.1' | ||
|
||
psu_status = SubtreeMIBEntry('1.2', power_status_handler, ValueType.INTEGER, power_status_handler.getPsuStatus) | ||
psu_status = SubtreeMIBEntry('1.2', power_status_handler, ValueType.INTEGER, power_status_handler.get_psu_status) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +0,0 @@ | ||
import tests.mock_tables.imp | ||
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we don't need the module 'psutil', can we remove it from setup.py?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@qiluo-msft Unfortunately we can't remove it from setup.py
Summary:
From psutil:
psutil (process and system utilities) is a cross-platform library for retrieving information on running processes and system utilization (CPU, memory, disks, network, sensors) in Python.
Usage:
From sonic_ax_impl: