From 6aa3dc643b6e011e85c68ced566fbded2908e9f4 Mon Sep 17 00:00:00 2001 From: keboliu Date: Sun, 28 Mar 2021 21:15:09 +0800 Subject: [PATCH 1/8] Extend RFC3433 to support more sensors including: Fan tachometers Thermal sensors PSU Voltage, Current, Power Signed-off-by: Kebo Liu --- .../mibs/ietf/fan_sensor_data.py | 92 +++++ .../mibs/ietf/psu_sensor_data.py | 113 ++++++ src/sonic_ax_impl/mibs/ietf/rfc3433.py | 331 +++++++++++++++++- .../mibs/ietf/thermal_sensor_data.py | 92 +++++ tests/test_sensor.py | 161 ++++++++- 5 files changed, 753 insertions(+), 36 deletions(-) create mode 100644 src/sonic_ax_impl/mibs/ietf/fan_sensor_data.py create mode 100644 src/sonic_ax_impl/mibs/ietf/psu_sensor_data.py create mode 100644 src/sonic_ax_impl/mibs/ietf/thermal_sensor_data.py diff --git a/src/sonic_ax_impl/mibs/ietf/fan_sensor_data.py b/src/sonic_ax_impl/mibs/ietf/fan_sensor_data.py new file mode 100644 index 000000000..49307ffa0 --- /dev/null +++ b/src/sonic_ax_impl/mibs/ietf/fan_sensor_data.py @@ -0,0 +1,92 @@ +import re + +from .physical_entity_sub_oid_generator import SENSOR_TYPE_FAN + + +class FANSensorData: + """ + Base FAN sensor data class. Responsible for: + 1. Manage concrete sensor data class + 2. Create concrete sensor data instances + 3. Provide common logic for concrete sensor data class + """ + + sensor_attr_dict = { + 'speed': { + 'pattern': 'speed', + 'name': 'Speed', + 'oid_offset_base': SENSOR_TYPE_FAN, + 'sort_factor': 0 + } + } + + def __init__(self, key, value, sensor_attrs, match_result): + self._key = key + self._value = value + self._sensor_attrs = sensor_attrs + self._match_result = match_result + + @classmethod + def create_sensor_data(cls, sensor_data_dict): + """ + Create sensor data instances according to the sensor data got from redis + :param sensor_data_dict: sensor data got from redis + :return: A sorted sensor data instance list + """ + sensor_data_list = [] + for name, value in sensor_data_dict.items(): + for sensor_attrs in cls.sensor_attr_dict.values(): + match_result = re.fullmatch(sensor_attrs['pattern'], name) + if match_result: + sensor_data = FANSensorData(name, value, sensor_attrs, match_result) + sensor_data_list.append(sensor_data) + + return sensor_data_list + + @classmethod + def sort_sensor_data(cls, sensor_data_list): + return sorted(sensor_data_list, key=lambda x: x.get_sort_factor()) + + @classmethod + def bind_sensor_interface(cls, sensor_interface_dict): + for name, sensor_attrs in cls.sensor_attr_dict.items(): + if name in sensor_interface_dict: + sensor_attrs['sensor_interface'] = sensor_interface_dict[name] + + def get_key(self): + """ + Get the redis key of this sensor + """ + return self._key + + def get_raw_value(self): + """ + Get raw redis value of this sensor + """ + return self._value + + def get_name(self): + """ + Get the name of this sensor. Concrete sensor data class must override + this. + """ + return self._sensor_attrs['name'] + + def get_sort_factor(self): + """ + Get sort factor for this sensor. Concrete sensor data class must override + this. + """ + return self._sensor_attrs['sort_factor'] + + def get_oid_offset(self): + """ + Get OID offset of this sensor. + """ + return self._sensor_attrs['oid_offset_base'] + + def get_sensor_interface(self): + """ + Get sensor interface of this sensor. Used by rfc3433. + """ + return self._sensor_attrs['sensor_interface'] diff --git a/src/sonic_ax_impl/mibs/ietf/psu_sensor_data.py b/src/sonic_ax_impl/mibs/ietf/psu_sensor_data.py new file mode 100644 index 000000000..24efa789a --- /dev/null +++ b/src/sonic_ax_impl/mibs/ietf/psu_sensor_data.py @@ -0,0 +1,113 @@ +import re + +from .physical_entity_sub_oid_generator import SENSOR_TYPE_TEMP +from .physical_entity_sub_oid_generator import SENSOR_TYPE_POWER +from .physical_entity_sub_oid_generator import SENSOR_TYPE_CURRENT +from .physical_entity_sub_oid_generator import SENSOR_TYPE_VOLTAGE + + +class PSUSensorData: + """ + Base PSU sensor data class. Responsible for: + 1. Manage concrete sensor data class + 2. Create concrete sensor data instances + 3. Provide common logic for concrete sensor data class + """ + + sensor_attr_dict = { + 'temperature': { + 'pattern': 'temp', + 'name': 'Temperature', + 'oid_offset_base': SENSOR_TYPE_TEMP, + 'sort_factor': 0 + }, + 'voltage': { + 'pattern': 'voltage', + 'name': 'Voltage', + 'oid_offset_base': SENSOR_TYPE_VOLTAGE, + 'sort_factor': 9000 + }, + 'power': { + 'pattern': 'power', + 'name': 'Power', + 'oid_offset_base': SENSOR_TYPE_POWER, + 'sort_factor': 2000 + }, + 'current': { + 'pattern': 'current', + 'name': 'Current', + 'oid_offset_base': SENSOR_TYPE_CURRENT, + 'sort_factor': 1000 + } + } + + def __init__(self, key, value, sensor_attrs, match_result): + self._key = key + self._value = value + self._sensor_attrs = sensor_attrs + self._match_result = match_result + + @classmethod + def create_sensor_data(cls, sensor_data_dict): + """ + Create sensor data instances according to the sensor data got from redis + :param sensor_data_dict: sensor data got from redis + :return: A sorted sensor data instance list + """ + sensor_data_list = [] + for name, value in sensor_data_dict.items(): + for sensor_attrs in cls.sensor_attr_dict.values(): + match_result = re.fullmatch(sensor_attrs['pattern'], name) + if match_result: + sensor_data = PSUSensorData(name, value, sensor_attrs, match_result) + sensor_data_list.append(sensor_data) + + return sensor_data_list + + @classmethod + def sort_sensor_data(cls, sensor_data_list): + return sorted(sensor_data_list, key=lambda x: x.get_sort_factor()) + + @classmethod + def bind_sensor_interface(cls, sensor_interface_dict): + for name, sensor_attrs in cls.sensor_attr_dict.items(): + if name in sensor_interface_dict: + sensor_attrs['sensor_interface'] = sensor_interface_dict[name] + + def get_key(self): + """ + Get the redis key of this sensor + """ + return self._key + + def get_raw_value(self): + """ + Get raw redis value of this sensor + """ + return self._value + + def get_name(self): + """ + Get the name of this sensor. Concrete sensor data class must override + this. + """ + return self._sensor_attrs['name'] + + def get_sort_factor(self): + """ + Get sort factor for this sensor. Concrete sensor data class must override + this. + """ + return self._sensor_attrs['sort_factor'] + + def get_oid_offset(self): + """ + Get OID offset of this sensor. + """ + return self._sensor_attrs['oid_offset_base'] + + def get_sensor_interface(self): + """ + Get sensor interface of this sensor. Used by rfc3433. + """ + return self._sensor_attrs['sensor_interface'] diff --git a/src/sonic_ax_impl/mibs/ietf/rfc3433.py b/src/sonic_ax_impl/mibs/ietf/rfc3433.py index 82879cba8..51646bd1b 100644 --- a/src/sonic_ax_impl/mibs/ietf/rfc3433.py +++ b/src/sonic_ax_impl/mibs/ietf/rfc3433.py @@ -9,9 +9,51 @@ from ax_interface import MIBMeta, MIBUpdater, ValueType, SubtreeMIBEntry from sonic_ax_impl import mibs from sonic_ax_impl.mibs import Namespace - +from .physical_entity_sub_oid_generator import CHASSIS_SUB_ID from .physical_entity_sub_oid_generator import get_transceiver_sensor_sub_id +from .physical_entity_sub_oid_generator import get_fan_drawer_sub_id +from .physical_entity_sub_oid_generator import get_fan_sub_id +from .physical_entity_sub_oid_generator import get_fan_tachometers_sub_id +from .physical_entity_sub_oid_generator import get_psu_sub_id +from .physical_entity_sub_oid_generator import get_psu_sensor_sub_id +from .physical_entity_sub_oid_generator import get_chassis_thermal_sub_id from .transceiver_sensor_data import TransceiverSensorData +from .psu_sensor_data import PSUSensorData +from .fan_sensor_data import FANSensorData +from .thermal_sensor_data import ThermalSensorData + +NOT_AVAILABLE = 'N/A' + + +def is_null_empty_str(value): + """ + Indicate if a string value is null + :param value: input string value + :return: True is string value is empty or equal to 'N/A' or 'None' + """ + if not isinstance(value, str) or value == NOT_AVAILABLE or value == 'None' or value == '': + return True + return False + + +def get_db_data(info_dict, enum_type): + """ + :param info_dict: db info dict + :param enum_type: db field enum + :return: tuple of fields values defined in enum_type; + Empty string if field not in info_dict + """ + return (info_dict.get(field.value, "") + for field in enum_type) + + +@unique +class PhysicalRelationInfoDB(str, Enum): + """ + Physical relation info keys + """ + POSITION_IN_PARENT = 'position_in_parent' + PARENT_NAME = 'parent_name' @unique @@ -101,7 +143,6 @@ class SensorInterface: PRECISION = None CONVERTER = None - @classmethod def mib_values(cls, raw_value): """ @@ -219,12 +260,93 @@ class XcvrTxPowerSensor(SensorInterface): }) +class PSUTempSensor(SensorInterface): + """ + PSU temperature sensor. + """ + + TYPE = EntitySensorDataType.CELSIUS + SCALE = EntitySensorDataScale.UNITS + PRECISION = 3 + + +class PSUVoltageSensor(SensorInterface): + """ + PSU voltage sensor. + """ + + TYPE = EntitySensorDataType.VOLTS_DC + SCALE = EntitySensorDataScale.UNITS + PRECISION = 3 + + +class PSUCurrentSensor(SensorInterface): + """ + PSU current sensor. + """ + + TYPE = EntitySensorDataType.AMPERES + SCALE = EntitySensorDataScale.UNITS + PRECISION = 3 + + +class PSUPowerSensor(SensorInterface): + """ + PSU power sensor. + """ + + TYPE = EntitySensorDataType.WATTS + SCALE = EntitySensorDataScale.UNITS + PRECISION = 3 + + +PSUSensorData.bind_sensor_interface({ + 'temperature': PSUTempSensor, + 'voltage' : PSUVoltageSensor, + 'power' : PSUPowerSensor, + 'current' : PSUCurrentSensor +}) + + +class FANSpeedSensor(SensorInterface): + """ + FAN speed sensor. + """ + + TYPE = EntitySensorDataType.UNKNOWN + SCALE = EntitySensorDataScale.UNITS + PRECISION = 0 + + +FANSensorData.bind_sensor_interface({ + 'speed': FANSpeedSensor +}) + + +class ThermalSensor(SensorInterface): + """ + Temperature sensor. + """ + + TYPE = EntitySensorDataType.CELSIUS + SCALE = EntitySensorDataScale.UNITS + PRECISION = 1 + + +ThermalSensorData.bind_sensor_interface({ + 'temperature': ThermalSensor +}) + + class PhysicalSensorTableMIBUpdater(MIBUpdater): """ Updater for sensors. """ TRANSCEIVER_DOM_KEY_PATTERN = mibs.transceiver_dom_table("*") + PSU_SENSOR_KEY_PATTERN = mibs.psu_info_table("*") + FAN_SENSOR_KEY_PATTERN = mibs.fan_info_table("*") + THERMAL_SENSOR_KEY_PATTERN = mibs.thermal_info_table("*") def __init__(self): """ @@ -239,7 +361,7 @@ def __init__(self): # list of available sub OIDs self.sub_ids = [] - # sensor MIB requiered values + # sensor MIB required values self.ent_phy_sensor_type_map = {} self.ent_phy_sensor_scale_map = {} self.ent_phy_sensor_precision_map = {} @@ -247,6 +369,9 @@ def __init__(self): self.ent_phy_sensor_oper_state_map = {} self.transceiver_dom = [] + self.fan_sensor = [] + self.psu_sensor = [] + self.thermal_sensor = [] def reinit_data(self): """ @@ -260,18 +385,23 @@ def reinit_data(self): self.ent_phy_sensor_value_map = {} self.ent_phy_sensor_oper_state_map = {} - transceiver_dom_encoded = Namespace.dbs_keys(self.statedb, mibs.STATE_DB, - self.TRANSCEIVER_DOM_KEY_PATTERN) + transceiver_dom_encoded = Namespace.dbs_keys(self.statedb, mibs.STATE_DB, self.TRANSCEIVER_DOM_KEY_PATTERN) if transceiver_dom_encoded: self.transceiver_dom = [entry for entry in transceiver_dom_encoded] - def update_data(self): - """ - Update sensors cache. - """ + fan_sensor_encoded = Namespace.dbs_keys(self.statedb, mibs.STATE_DB, self.FAN_SENSOR_KEY_PATTERN) + if fan_sensor_encoded: + self.fan_sensor = [entry for entry in fan_sensor_encoded] - self.sub_ids = [] + psu_sensor_encoded = Namespace.dbs_keys(self.statedb, mibs.STATE_DB, self.PSU_SENSOR_KEY_PATTERN) + if psu_sensor_encoded: + self.psu_sensor = [entry for entry in psu_sensor_encoded] + thermal_sensor_encoded = Namespace.dbs_keys(self.statedb, mibs.STATE_DB, self.THERMAL_SENSOR_KEY_PATTERN) + if thermal_sensor_encoded: + self.thermal_sensor = [entry for entry in thermal_sensor_encoded] + + def update_xcvr_dom_data(self): if not self.transceiver_dom: return @@ -288,8 +418,7 @@ def update_data(self): continue # get transceiver sensors from transceiver dom entry in STATE DB - transceiver_dom_entry_data = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, - transceiver_dom_entry) + transceiver_dom_entry_data = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, transceiver_dom_entry) if not transceiver_dom_entry_data: continue @@ -303,19 +432,185 @@ def update_data(self): try: mib_values = sensor.mib_values(raw_sensor_value) except (ValueError, ArithmeticError): - mibs.logger.error("Exception occured when converting" + mibs.logger.error("Exception occurred when converting" "value for sensor {} interface {}".format(sensor, interface)) - # skip continue else: self.ent_phy_sensor_type_map[sub_id], \ - self.ent_phy_sensor_scale_map[sub_id], \ - self.ent_phy_sensor_precision_map[sub_id], \ - self.ent_phy_sensor_value_map[sub_id], \ - self.ent_phy_sensor_oper_state_map[sub_id] = mib_values + self.ent_phy_sensor_scale_map[sub_id], \ + self.ent_phy_sensor_precision_map[sub_id], \ + self.ent_phy_sensor_value_map[sub_id], \ + self.ent_phy_sensor_oper_state_map[sub_id] = mib_values + + self.sub_ids.append(sub_id) + + def update_psu_sensor_data(self): + if not self.psu_sensor: + return + + for psu_sensor_entry in self.psu_sensor: + psu_name = psu_sensor_entry.split(mibs.TABLE_NAME_SEPARATOR_VBAR)[-1] + psu_relation_info = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, + mibs.physical_entity_info_table(psu_name)) + psu_position, psu_parent_name = get_db_data(psu_relation_info, PhysicalRelationInfoDB) + if is_null_empty_str(psu_position): + continue + psu_position = int(psu_position) + psu_sub_id = get_psu_sub_id(psu_position) + + psu_sensor_entry_data = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, psu_sensor_entry) + + if not psu_sensor_entry_data: + continue + + sensor_data_list = PSUSensorData.create_sensor_data(psu_sensor_entry_data) + for sensor_data in sensor_data_list: + raw_sensor_value = sensor_data.get_raw_value() + if is_null_empty_str(raw_sensor_value): + continue + sensor = sensor_data.get_sensor_interface() + sub_id = get_psu_sensor_sub_id(psu_sub_id, sensor_data.get_name().lower()) + + try: + mib_values = sensor.mib_values(raw_sensor_value) + except (ValueError, ArithmeticError): + mibs.logger.error("Exception occurred when converting" + "value for sensor {} PSU {}".format(sensor, psu_name)) + continue + else: + self.ent_phy_sensor_type_map[sub_id], \ + self.ent_phy_sensor_scale_map[sub_id], \ + self.ent_phy_sensor_precision_map[sub_id], \ + self.ent_phy_sensor_value_map[sub_id], \ + self.ent_phy_sensor_oper_state_map[sub_id] = mib_values self.sub_ids.append(sub_id) + def update_fan_sensor_data(self): + if not self.fan_sensor: + return + + fan_parent_sub_id = 0 + for fan_sensor_entry in self.fan_sensor: + fan_name = fan_sensor_entry.split(mibs.TABLE_NAME_SEPARATOR_VBAR)[-1] + fan_relation_info = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, + mibs.physical_entity_info_table(fan_name)) + + fan_position, fan_parent_name = get_db_data(fan_relation_info, PhysicalRelationInfoDB) + if is_null_empty_str(fan_position): + continue + + fan_position = int(fan_position) + + if "chassis" in fan_parent_name: + fan_parent_sub_id = (CHASSIS_SUB_ID,) + else: + fan_parent_relation_info = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, + mibs.physical_entity_info_table(fan_parent_name)) + if fan_parent_relation_info: + fan_parent_position, fan_grad_parent_name = get_db_data(fan_parent_relation_info, + PhysicalRelationInfoDB) + + fan_parent_position = int(fan_parent_position) + + if "PSU" in fan_parent_name: + fan_parent_sub_id = get_psu_sub_id(fan_parent_position) + else: + fan_parent_sub_id = get_fan_drawer_sub_id(fan_parent_position) + else: + mibs.logger.error("fan_name = {} get fan parent failed".format(fan_name)) + continue + + fan_sub_id = get_fan_sub_id(fan_parent_sub_id, fan_position) + + fan_sensor_entry_data = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, fan_sensor_entry) + + if not fan_sensor_entry_data: + mibs.logger.error("fan_name = {} get fan_sensor_entry_data failed".format(fan_name)) + continue + + sensor_data_list = FANSensorData.create_sensor_data(fan_sensor_entry_data) + for sensor_data in sensor_data_list: + raw_sensor_value = sensor_data.get_raw_value() + if is_null_empty_str(raw_sensor_value): + continue + sensor = sensor_data.get_sensor_interface() + sub_id = get_fan_tachometers_sub_id(fan_sub_id) + + try: + mib_values = sensor.mib_values(raw_sensor_value) + except (ValueError, ArithmeticError): + mibs.logger.error("Exception occurred when converting" + "value for sensor {} PSU {}".format(sensor, fan_name)) + continue + else: + self.ent_phy_sensor_type_map[sub_id], \ + self.ent_phy_sensor_scale_map[sub_id], \ + self.ent_phy_sensor_precision_map[sub_id], \ + self.ent_phy_sensor_value_map[sub_id], \ + self.ent_phy_sensor_oper_state_map[sub_id] = mib_values + + self.sub_ids.append(sub_id) + + def update_thermal_sensor_data(self): + if not self.thermal_sensor: + return + + for thermal_sensor_entry in self.thermal_sensor: + thermal_name = thermal_sensor_entry.split(mibs.TABLE_NAME_SEPARATOR_VBAR)[-1] + thermal_relation_info = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, + mibs.physical_entity_info_table(thermal_name)) + thermal_position, thermal_parent_name = get_db_data(thermal_relation_info, PhysicalRelationInfoDB) + + if is_null_empty_str(thermal_parent_name) or is_null_empty_str(thermal_parent_name) or \ + "chassis" not in thermal_parent_name.lower(): + continue + + thermal_position = int(thermal_position) + + thermal_sensor_entry_data = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, thermal_sensor_entry) + + if not thermal_sensor_entry_data: + continue + + sensor_data_list = ThermalSensorData.create_sensor_data(thermal_sensor_entry_data) + for sensor_data in sensor_data_list: + raw_sensor_value = sensor_data.get_raw_value() + if is_null_empty_str(raw_sensor_value): + continue + sensor = sensor_data.get_sensor_interface() + sub_id = get_chassis_thermal_sub_id(thermal_position) + + try: + mib_values = sensor.mib_values(raw_sensor_value) + except (ValueError, ArithmeticError): + mibs.logger.error("Exception occurred when converting" + "value for sensor {} PSU {}".format(sensor, thermal_name)) + continue + else: + self.ent_phy_sensor_type_map[sub_id], \ + self.ent_phy_sensor_scale_map[sub_id], \ + self.ent_phy_sensor_precision_map[sub_id], \ + self.ent_phy_sensor_value_map[sub_id], \ + self.ent_phy_sensor_oper_state_map[sub_id] = mib_values + + self.sub_ids.append(sub_id) + + def update_data(self): + """ + Update sensors cache. + """ + + self.sub_ids = [] + + self.update_xcvr_dom_data() + + self.update_psu_sensor_data() + + self.update_fan_sensor_data() + + self.update_thermal_sensor_data() + self.sub_ids.sort() def get_next(self, sub_id): diff --git a/src/sonic_ax_impl/mibs/ietf/thermal_sensor_data.py b/src/sonic_ax_impl/mibs/ietf/thermal_sensor_data.py new file mode 100644 index 000000000..e9ac8d545 --- /dev/null +++ b/src/sonic_ax_impl/mibs/ietf/thermal_sensor_data.py @@ -0,0 +1,92 @@ +import re + +from .physical_entity_sub_oid_generator import SENSOR_TYPE_TEMP + + +class ThermalSensorData: + """ + Base Thermal sensor data class. Responsible for: + 1. Manage concrete sensor data class + 2. Create concrete sensor data instances + 3. Provide common logic for concrete sensor data class + """ + + sensor_attr_dict = { + 'temperature': { + 'pattern': 'temperature', + 'name': 'Temperature', + 'oid_offset_base': SENSOR_TYPE_TEMP, + 'sort_factor': 0 + } + } + + def __init__(self, key, value, sensor_attrs, match_result): + self._key = key + self._value = value + self._sensor_attrs = sensor_attrs + self._match_result = match_result + + @classmethod + def create_sensor_data(cls, sensor_data_dict): + """ + Create sensor data instances according to the sensor data got from redis + :param sensor_data_dict: sensor data got from redis + :return: A sorted sensor data instance list + """ + sensor_data_list = [] + for name, value in sensor_data_dict.items(): + for sensor_attrs in cls.sensor_attr_dict.values(): + match_result = re.fullmatch(sensor_attrs['pattern'], name) + if match_result: + sensor_data = ThermalSensorData(name, value, sensor_attrs, match_result) + sensor_data_list.append(sensor_data) + + return sensor_data_list + + @classmethod + def sort_sensor_data(cls, sensor_data_list): + return sorted(sensor_data_list, key=lambda x: x.get_sort_factor()) + + @classmethod + def bind_sensor_interface(cls, sensor_interface_dict): + for name, sensor_attrs in cls.sensor_attr_dict.items(): + if name in sensor_interface_dict: + sensor_attrs['sensor_interface'] = sensor_interface_dict[name] + + def get_key(self): + """ + Get the redis key of this sensor + """ + return self._key + + def get_raw_value(self): + """ + Get raw redis value of this sensor + """ + return self._value + + def get_name(self): + """ + Get the name of this sensor. Concrete sensor data class must override + this. + """ + return self._sensor_attrs['name'] + + def get_sort_factor(self): + """ + Get sort factor for this sensor. Concrete sensor data class must override + this. + """ + return self._sensor_attrs['sort_factor'] + + def get_oid_offset(self): + """ + Get OID offset of this sensor. + """ + return self._sensor_attrs['oid_offset_base'] + + def get_sensor_interface(self): + """ + Get sensor interface of this sensor. Used by rfc3433. + """ + return self._sensor_attrs['sensor_interface'] diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 78e7f75f2..41cc2381d 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -16,6 +16,12 @@ from ax_interface.encodings import ObjectIdentifier from ax_interface.constants import PduTypes from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_transceiver_sub_id, get_transceiver_sensor_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_psu_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_psu_sensor_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_fan_drawer_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_fan_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_fan_tachometers_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_chassis_thermal_sub_id from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import SENSOR_TYPE_TEMP from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import SENSOR_TYPE_VOLTAGE from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import SENSOR_TYPE_PORT_RX_POWER @@ -31,6 +37,11 @@ def setUpClass(cls): cls.IFINDEX = 1 cls.XCVR_SUB_ID = get_transceiver_sub_id(cls.IFINDEX) cls.XCVR_CHANNELS = (1, 2, 3, 4) + cls.PSU_POSITION = 2 + cls.FAN_DRAWER_POSITION = 1 + cls.FAN_POSITION = 1 + cls.PSU_FAN_POSITION = 1 + cls.THERMAL_POSITION = 1 # Update MIBs for updater in cls.lut.updater_instances: @@ -43,7 +54,7 @@ def generate_oids_for_physical_sensor_mib(sub_id): return [ObjectIdentifier(12, 0, 0, 0, (1, 3, 6, 1, 2, 1, 99, 1, 1, 1, i, sub_id)) for i in range(1, 5)] - def _test_getpdu_xcvr_sensor(self, sub_id, expected_values): + def _test_getpdu_sensor(self, sub_id, expected_values): """ Test case for correctness of transceiver sensor MIB values :param sub_id: sub OID of the sensor @@ -67,10 +78,9 @@ def _test_getpdu_xcvr_sensor(self, sub_id, expected_values): self.assertEqual(value.type_, ValueType.INTEGER) self.assertEqual(value.data, expected_values[index]) - def test_getpdu_xcvr_temperature_sensor(self): """ - Test case for correct transceiver temperature sensor MIB values + Test case for correctness of transceiver temperature sensor MIB values """ expected_values = [ @@ -81,11 +91,11 @@ def test_getpdu_xcvr_temperature_sensor(self): rfc3433.EntitySensorStatus.OK ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_TEMP)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_TEMP)[0], expected_values) def test_getpdu_xcvr_voltage_sensor(self): """ - Test case for correct transceiver voltage sensor MIB values + Test case for correctness of transceiver voltage sensor MIB values """ expected_values = [ @@ -96,11 +106,11 @@ def test_getpdu_xcvr_voltage_sensor(self): rfc3433.EntitySensorStatus.OK ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_VOLTAGE)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_VOLTAGE)[0], expected_values) def test_getpdu_xcvr_rx_power_sensor_minus_infinity(self): """ - Test case for correct transceiver rx power sensor MIB values + Test case for correctness of transceiver rx power sensor MIB values in case when rx power == -inf """ @@ -112,11 +122,11 @@ def test_getpdu_xcvr_rx_power_sensor_minus_infinity(self): rfc3433.EntitySensorStatus.OK ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 1 + SENSOR_TYPE_PORT_RX_POWER)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 1 + SENSOR_TYPE_PORT_RX_POWER)[0], expected_values) def test_getpdu_xcvr_rx_power_sensor(self): """ - Test case for correct transceiver rx power sensor MIB values + Test case for correctness of transceiver rx power sensor MIB values """ expected_values = [ @@ -129,11 +139,11 @@ def test_getpdu_xcvr_rx_power_sensor(self): # test for each channel except first, we already test above for channel in (2, 3, 4): - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_RX_POWER + channel)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_RX_POWER + channel)[0], expected_values) def test_getpdu_xcvr_tx_power_sensor(self): """ - Test case for correct transceiver rx power sensor MIB values + Test case for correctness of transceiver rx power sensor MIB values """ expected_values = [ @@ -146,11 +156,11 @@ def test_getpdu_xcvr_tx_power_sensor(self): # test for each channel except first, we already test above for channel in (1, 2, 3, 4): - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_TX_POWER + channel)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_TX_POWER + channel)[0], expected_values) def test_getpdu_xcvr_tx_bias_sensor_unknown(self): """ - Test case for correct transceiver tx bias sensor MIB values, when + Test case for correctness of transceiver tx bias sensor MIB values, when tx bias sensor is set to "UNKNOWN" in state DB """ @@ -162,11 +172,11 @@ def test_getpdu_xcvr_tx_bias_sensor_unknown(self): rfc3433.EntitySensorStatus.UNAVAILABLE ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 1 + SENSOR_TYPE_PORT_TX_BIAS)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 1 + SENSOR_TYPE_PORT_TX_BIAS)[0], expected_values) def test_getpdu_xcvr_tx_bias_sensor_overflow(self): """ - Test case for correct transceiver tx bias sensor MIB values + Test case for correctness of transceiver tx bias sensor MIB values when tx bias is grater than 1E9 """ @@ -178,11 +188,11 @@ def test_getpdu_xcvr_tx_bias_sensor_overflow(self): rfc3433.EntitySensorStatus.OK ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 3 + SENSOR_TYPE_PORT_TX_BIAS)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 3 + SENSOR_TYPE_PORT_TX_BIAS)[0], expected_values) def test_getpdu_xcvr_tx_bias_sensor(self): """ - Test case for correct transceiver tx bias sensor MIB values + Test case for correctness of transceiver tx bias sensor MIB values """ expected_values = [ @@ -195,4 +205,119 @@ def test_getpdu_xcvr_tx_bias_sensor(self): # test for each channel for channel in (2, 4): - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_TX_BIAS + channel)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_TX_BIAS + channel)[0], expected_values) + + def test_getpdu_psu_temp_sensor(self): + """ + Test case for correctness of psu temperature sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.CELSIUS, + rfc3433.EntitySensorDataScale.UNITS, + 3, # precision + 31100, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + psu_sub_id = get_psu_sub_id(self.PSU_POSITION) + self._test_getpdu_sensor(get_psu_sensor_sub_id(psu_sub_id, "temperature")[0], expected_values) + + def test_getpdu_psu_voltage_sensor(self): + """ + Test case for correctness of psu voltage sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.VOLTS_DC, + rfc3433.EntitySensorDataScale.UNITS, + 3, # precision + 13100, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + psu_sub_id = get_psu_sub_id(self.PSU_POSITION) + self._test_getpdu_sensor(get_psu_sensor_sub_id(psu_sub_id, "voltage")[0], expected_values) + + def test_getpdu_psu_power_sensor(self): + """ + Test case for correctness of psu voltage sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.WATTS, + rfc3433.EntitySensorDataScale.UNITS, + 3, # precision + 312600, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + psu_sub_id = get_psu_sub_id(self.PSU_POSITION) + self._test_getpdu_sensor(get_psu_sensor_sub_id(psu_sub_id, "power")[0], expected_values) + + def test_getpdu_psu_current_sensor(self): + """ + Test case for correctness of psu current sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.AMPERES, + rfc3433.EntitySensorDataScale.UNITS, + 3, # precision + 13400, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + psu_sub_id = get_psu_sub_id(self.PSU_POSITION) + self._test_getpdu_sensor(get_psu_sensor_sub_id(psu_sub_id, "current")[0], expected_values) + + def test_getpdu_chassis_fan_speed_sensor(self): + """ + Test case for correctness of fan speed sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.UNKNOWN, + rfc3433.EntitySensorDataScale.UNITS, + 0, # precision + 50, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + fan_parent_sub_id = get_fan_drawer_sub_id(self.FAN_DRAWER_POSITION) + fan_sub_id = get_fan_sub_id(fan_parent_sub_id, self.FAN_POSITION) + + self._test_getpdu_sensor(get_fan_tachometers_sub_id(fan_sub_id)[0], expected_values) + + def test_getpdu_psu_fan_speed_sensor(self): + """ + Test case for correctness of psu fan speed sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.UNKNOWN, + rfc3433.EntitySensorDataScale.UNITS, + 0, # precision + 57, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + psu_sub_id = get_psu_sub_id(self.PSU_POSITION) + fan_sub_id = get_fan_sub_id(psu_sub_id, self.PSU_FAN_POSITION) + + self._test_getpdu_sensor(get_fan_tachometers_sub_id(fan_sub_id)[0], expected_values) + + def test_getpdu_chassis_temp_sensor(self): + """ + Test case for correctness of chassis temp sensors MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.CELSIUS, + rfc3433.EntitySensorDataScale.UNITS, + 1, # precision + 205, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + self._test_getpdu_sensor(get_chassis_thermal_sub_id(self.THERMAL_POSITION)[0], expected_values) From 7b62632b3c7b48c52e94589da01fb59ad07dbaac Mon Sep 17 00:00:00 2001 From: keboliu Date: Sat, 10 Apr 2021 19:28:31 +0800 Subject: [PATCH 2/8] reduce the redundant code Signed-off-by: Kebo Liu --- .../mibs/ietf/fan_sensor_data.py | 92 ------ .../mibs/ietf/psu_sensor_data.py | 113 ------- src/sonic_ax_impl/mibs/ietf/rfc3433.py | 7 +- src/sonic_ax_impl/mibs/ietf/sensor_data.py | 281 ++++++++++++++++++ .../mibs/ietf/thermal_sensor_data.py | 92 ------ .../mibs/ietf/transceiver_sensor_data.py | 132 -------- tests/test_sensor.py | 4 +- 7 files changed, 285 insertions(+), 436 deletions(-) delete mode 100644 src/sonic_ax_impl/mibs/ietf/fan_sensor_data.py delete mode 100644 src/sonic_ax_impl/mibs/ietf/psu_sensor_data.py create mode 100644 src/sonic_ax_impl/mibs/ietf/sensor_data.py delete mode 100644 src/sonic_ax_impl/mibs/ietf/thermal_sensor_data.py delete mode 100644 src/sonic_ax_impl/mibs/ietf/transceiver_sensor_data.py diff --git a/src/sonic_ax_impl/mibs/ietf/fan_sensor_data.py b/src/sonic_ax_impl/mibs/ietf/fan_sensor_data.py deleted file mode 100644 index 49307ffa0..000000000 --- a/src/sonic_ax_impl/mibs/ietf/fan_sensor_data.py +++ /dev/null @@ -1,92 +0,0 @@ -import re - -from .physical_entity_sub_oid_generator import SENSOR_TYPE_FAN - - -class FANSensorData: - """ - Base FAN sensor data class. Responsible for: - 1. Manage concrete sensor data class - 2. Create concrete sensor data instances - 3. Provide common logic for concrete sensor data class - """ - - sensor_attr_dict = { - 'speed': { - 'pattern': 'speed', - 'name': 'Speed', - 'oid_offset_base': SENSOR_TYPE_FAN, - 'sort_factor': 0 - } - } - - def __init__(self, key, value, sensor_attrs, match_result): - self._key = key - self._value = value - self._sensor_attrs = sensor_attrs - self._match_result = match_result - - @classmethod - def create_sensor_data(cls, sensor_data_dict): - """ - Create sensor data instances according to the sensor data got from redis - :param sensor_data_dict: sensor data got from redis - :return: A sorted sensor data instance list - """ - sensor_data_list = [] - for name, value in sensor_data_dict.items(): - for sensor_attrs in cls.sensor_attr_dict.values(): - match_result = re.fullmatch(sensor_attrs['pattern'], name) - if match_result: - sensor_data = FANSensorData(name, value, sensor_attrs, match_result) - sensor_data_list.append(sensor_data) - - return sensor_data_list - - @classmethod - def sort_sensor_data(cls, sensor_data_list): - return sorted(sensor_data_list, key=lambda x: x.get_sort_factor()) - - @classmethod - def bind_sensor_interface(cls, sensor_interface_dict): - for name, sensor_attrs in cls.sensor_attr_dict.items(): - if name in sensor_interface_dict: - sensor_attrs['sensor_interface'] = sensor_interface_dict[name] - - def get_key(self): - """ - Get the redis key of this sensor - """ - return self._key - - def get_raw_value(self): - """ - Get raw redis value of this sensor - """ - return self._value - - def get_name(self): - """ - Get the name of this sensor. Concrete sensor data class must override - this. - """ - return self._sensor_attrs['name'] - - def get_sort_factor(self): - """ - Get sort factor for this sensor. Concrete sensor data class must override - this. - """ - return self._sensor_attrs['sort_factor'] - - def get_oid_offset(self): - """ - Get OID offset of this sensor. - """ - return self._sensor_attrs['oid_offset_base'] - - def get_sensor_interface(self): - """ - Get sensor interface of this sensor. Used by rfc3433. - """ - return self._sensor_attrs['sensor_interface'] diff --git a/src/sonic_ax_impl/mibs/ietf/psu_sensor_data.py b/src/sonic_ax_impl/mibs/ietf/psu_sensor_data.py deleted file mode 100644 index 24efa789a..000000000 --- a/src/sonic_ax_impl/mibs/ietf/psu_sensor_data.py +++ /dev/null @@ -1,113 +0,0 @@ -import re - -from .physical_entity_sub_oid_generator import SENSOR_TYPE_TEMP -from .physical_entity_sub_oid_generator import SENSOR_TYPE_POWER -from .physical_entity_sub_oid_generator import SENSOR_TYPE_CURRENT -from .physical_entity_sub_oid_generator import SENSOR_TYPE_VOLTAGE - - -class PSUSensorData: - """ - Base PSU sensor data class. Responsible for: - 1. Manage concrete sensor data class - 2. Create concrete sensor data instances - 3. Provide common logic for concrete sensor data class - """ - - sensor_attr_dict = { - 'temperature': { - 'pattern': 'temp', - 'name': 'Temperature', - 'oid_offset_base': SENSOR_TYPE_TEMP, - 'sort_factor': 0 - }, - 'voltage': { - 'pattern': 'voltage', - 'name': 'Voltage', - 'oid_offset_base': SENSOR_TYPE_VOLTAGE, - 'sort_factor': 9000 - }, - 'power': { - 'pattern': 'power', - 'name': 'Power', - 'oid_offset_base': SENSOR_TYPE_POWER, - 'sort_factor': 2000 - }, - 'current': { - 'pattern': 'current', - 'name': 'Current', - 'oid_offset_base': SENSOR_TYPE_CURRENT, - 'sort_factor': 1000 - } - } - - def __init__(self, key, value, sensor_attrs, match_result): - self._key = key - self._value = value - self._sensor_attrs = sensor_attrs - self._match_result = match_result - - @classmethod - def create_sensor_data(cls, sensor_data_dict): - """ - Create sensor data instances according to the sensor data got from redis - :param sensor_data_dict: sensor data got from redis - :return: A sorted sensor data instance list - """ - sensor_data_list = [] - for name, value in sensor_data_dict.items(): - for sensor_attrs in cls.sensor_attr_dict.values(): - match_result = re.fullmatch(sensor_attrs['pattern'], name) - if match_result: - sensor_data = PSUSensorData(name, value, sensor_attrs, match_result) - sensor_data_list.append(sensor_data) - - return sensor_data_list - - @classmethod - def sort_sensor_data(cls, sensor_data_list): - return sorted(sensor_data_list, key=lambda x: x.get_sort_factor()) - - @classmethod - def bind_sensor_interface(cls, sensor_interface_dict): - for name, sensor_attrs in cls.sensor_attr_dict.items(): - if name in sensor_interface_dict: - sensor_attrs['sensor_interface'] = sensor_interface_dict[name] - - def get_key(self): - """ - Get the redis key of this sensor - """ - return self._key - - def get_raw_value(self): - """ - Get raw redis value of this sensor - """ - return self._value - - def get_name(self): - """ - Get the name of this sensor. Concrete sensor data class must override - this. - """ - return self._sensor_attrs['name'] - - def get_sort_factor(self): - """ - Get sort factor for this sensor. Concrete sensor data class must override - this. - """ - return self._sensor_attrs['sort_factor'] - - def get_oid_offset(self): - """ - Get OID offset of this sensor. - """ - return self._sensor_attrs['oid_offset_base'] - - def get_sensor_interface(self): - """ - Get sensor interface of this sensor. Used by rfc3433. - """ - return self._sensor_attrs['sensor_interface'] diff --git a/src/sonic_ax_impl/mibs/ietf/rfc3433.py b/src/sonic_ax_impl/mibs/ietf/rfc3433.py index 51646bd1b..42d2570d8 100644 --- a/src/sonic_ax_impl/mibs/ietf/rfc3433.py +++ b/src/sonic_ax_impl/mibs/ietf/rfc3433.py @@ -17,10 +17,7 @@ from .physical_entity_sub_oid_generator import get_psu_sub_id from .physical_entity_sub_oid_generator import get_psu_sensor_sub_id from .physical_entity_sub_oid_generator import get_chassis_thermal_sub_id -from .transceiver_sensor_data import TransceiverSensorData -from .psu_sensor_data import PSUSensorData -from .fan_sensor_data import FANSensorData -from .thermal_sensor_data import ThermalSensorData +from .sensor_data import ThermalSensorData, FANSensorData, PSUSensorData, TransceiverSensorData NOT_AVAILABLE = 'N/A' @@ -330,7 +327,7 @@ class ThermalSensor(SensorInterface): TYPE = EntitySensorDataType.CELSIUS SCALE = EntitySensorDataScale.UNITS - PRECISION = 1 + PRECISION = 3 ThermalSensorData.bind_sensor_interface({ diff --git a/src/sonic_ax_impl/mibs/ietf/sensor_data.py b/src/sonic_ax_impl/mibs/ietf/sensor_data.py new file mode 100644 index 000000000..7f864e57a --- /dev/null +++ b/src/sonic_ax_impl/mibs/ietf/sensor_data.py @@ -0,0 +1,281 @@ +import re + +from .physical_entity_sub_oid_generator import SENSOR_TYPE_TEMP +from .physical_entity_sub_oid_generator import SENSOR_TYPE_PORT_TX_POWER +from .physical_entity_sub_oid_generator import SENSOR_TYPE_PORT_RX_POWER +from .physical_entity_sub_oid_generator import SENSOR_TYPE_PORT_TX_BIAS +from .physical_entity_sub_oid_generator import SENSOR_TYPE_VOLTAGE +from .physical_entity_sub_oid_generator import SENSOR_TYPE_FAN +from .physical_entity_sub_oid_generator import SENSOR_TYPE_POWER +from .physical_entity_sub_oid_generator import SENSOR_TYPE_CURRENT + + +class BaseSensorData: + """ + Base sensor data class. Responsible for: + 1. Manage concrete sensor data class + 2. Create concrete sensor data instances + 3. Provide common logic for concrete sensor data class + """ + sensor_attr_dict = {} + + @classmethod + def sort_sensor_data(cls, sensor_data_list): + return sorted(sensor_data_list, key=lambda x: x.get_sort_factor()) + + @classmethod + def bind_sensor_interface(cls, sensor_interface_dict): + for name, sensor_attrs in cls.sensor_attr_dict.items(): + if name in sensor_interface_dict: + sensor_attrs['sensor_interface'] = sensor_interface_dict[name] + + def __init__(self, key, value, sensor_attrs, match_result): + self._key = key + self._value = value + self._sensor_attrs = sensor_attrs + self._match_result = match_result + + def get_key(self): + """ + Get the redis key of this sensor + """ + return self._key + + def get_raw_value(self): + """ + Get raw redis value of this sensor + """ + return self._value + + def get_name(self): + """ + Get the name of this sensor. Concrete sensor data class must override + this. + """ + return self._sensor_attrs['name'] + + def get_sort_factor(self): + """ + Get sort factor for this sensor. Concrete sensor data class must override + this. + """ + return self._sensor_attrs['sort_factor'] + + def get_oid_offset(self): + """ + Get OID offset of this sensor. + """ + return self._sensor_attrs['oid_offset_base'] + + def get_sensor_interface(self): + """ + Get sensor interface of this sensor. Used by rfc3433. + """ + return self._sensor_attrs['sensor_interface'] + + +class TransceiverSensorData(BaseSensorData): + """ + Base transceiver sensor data class. Responsible for: + 1. Manage concrete sensor data class + 2. Create concrete sensor data instances + 3. Provide common logic for concrete sensor data class + """ + + sensor_attr_dict = { + 'temperature': { + 'pattern': 'temperature', + 'name': 'Temperature', + 'oid_offset_base': SENSOR_TYPE_TEMP, + 'sort_factor': 0, + 'lane_based_sensor': False + }, + 'voltage': { + 'pattern': 'voltage', + 'name': 'Voltage', + 'oid_offset_base': SENSOR_TYPE_VOLTAGE, + 'sort_factor': 9000, + 'lane_based_sensor': False + }, + 'rxpower': { + 'pattern': r'rx(\d+)power', + 'name': 'RX Power', + 'oid_offset_base': SENSOR_TYPE_PORT_RX_POWER, + 'sort_factor': 2000, + 'lane_based_sensor': True + }, + 'txpower': { + 'pattern': r'tx(\d+)power', + 'name': 'TX Power', + 'oid_offset_base': SENSOR_TYPE_PORT_TX_POWER, + 'sort_factor': 1000, + 'lane_based_sensor': True + }, + 'txbias': { + 'pattern': r'tx(\d+)bias', + 'name': 'TX Bias', + 'oid_offset_base': SENSOR_TYPE_PORT_TX_BIAS, + 'sort_factor': 3000, + 'lane_based_sensor': True + } + } + + @classmethod + def create_sensor_data(cls, sensor_data_dict): + """ + Create sensor data instances according to the sensor data got from redis + :param sensor_data_dict: sensor data got from redis + :return: A sorted sensor data instance list + """ + sensor_data_list = [] + for name, value in sensor_data_dict.items(): + for sensor_attrs in cls.sensor_attr_dict.values(): + match_result = re.match(sensor_attrs['pattern'], name) + if match_result: + sensor_data = TransceiverSensorData(name, value, sensor_attrs, match_result) + sensor_data_list.append(sensor_data) + + return sensor_data_list + + def get_sort_factor(self): + """ + Get sort factor for this sensor. Concrete sensor data class must override + this. + """ + return self._sensor_attrs['sort_factor'] + self.get_lane_number() + + def get_lane_number(self): + """ + Get lane number of this sensor. For example, some transceivers have more than one rx power sensor, the sub index + of rx1power is 1, the sub index of rx2power is 2. + """ + return int(self._match_result.group(1)) if self._sensor_attrs['lane_based_sensor'] else 0 + + def get_oid_offset(self): + """ + Get OID offset of this sensor. + """ + return self._sensor_attrs['oid_offset_base'] + self.get_lane_number() + + +class PSUSensorData(BaseSensorData): + """ + Base PSU sensor data class. Responsible for: + 1. Manage concrete sensor data class + 2. Create concrete sensor data instances + 3. Provide common logic for concrete sensor data class + """ + + sensor_attr_dict = { + 'temperature': { + 'pattern': 'temp', + 'name': 'Temperature', + 'oid_offset_base': SENSOR_TYPE_TEMP, + 'sort_factor': 0 + }, + 'voltage': { + 'pattern': 'voltage', + 'name': 'Voltage', + 'oid_offset_base': SENSOR_TYPE_VOLTAGE, + 'sort_factor': 9000 + }, + 'power': { + 'pattern': 'power', + 'name': 'Power', + 'oid_offset_base': SENSOR_TYPE_POWER, + 'sort_factor': 2000 + }, + 'current': { + 'pattern': 'current', + 'name': 'Current', + 'oid_offset_base': SENSOR_TYPE_CURRENT, + 'sort_factor': 1000 + } + } + + @classmethod + def create_sensor_data(cls, sensor_data_dict): + """ + Create sensor data instances according to the sensor data got from redis + :param sensor_data_dict: sensor data got from redis + :return: A sorted sensor data instance list + """ + sensor_data_list = [] + for name, value in sensor_data_dict.items(): + for sensor_attrs in cls.sensor_attr_dict.values(): + match_result = re.fullmatch(sensor_attrs['pattern'], name) + if match_result: + sensor_data = PSUSensorData(name, value, sensor_attrs, match_result) + sensor_data_list.append(sensor_data) + + return sensor_data_list + + +class FANSensorData(BaseSensorData): + """ + Base FAN sensor data class. Responsible for: + 1. Manage concrete sensor data class + 2. Create concrete sensor data instances + 3. Provide common logic for concrete sensor data class + """ + + sensor_attr_dict = { + 'speed': { + 'pattern': 'speed', + 'name': 'Speed', + 'oid_offset_base': SENSOR_TYPE_FAN, + 'sort_factor': 0 + } + } + + @classmethod + def create_sensor_data(cls, sensor_data_dict): + """ + Create sensor data instances according to the sensor data got from redis + :param sensor_data_dict: sensor data got from redis + :return: A sorted sensor data instance list + """ + sensor_data_list = [] + for name, value in sensor_data_dict.items(): + for sensor_attrs in cls.sensor_attr_dict.values(): + match_result = re.fullmatch(sensor_attrs['pattern'], name) + if match_result: + sensor_data = FANSensorData(name, value, sensor_attrs, match_result) + sensor_data_list.append(sensor_data) + + return sensor_data_list + + +class ThermalSensorData(BaseSensorData): + """ + Base Thermal sensor data class. Responsible for: + 1. Manage concrete sensor data class + 2. Create concrete sensor data instances + 3. Provide common logic for concrete sensor data class + """ + + sensor_attr_dict = { + 'temperature': { + 'pattern': 'temperature', + 'name': 'Temperature', + 'oid_offset_base': SENSOR_TYPE_TEMP, + 'sort_factor': 0 + } + } + + @classmethod + def create_sensor_data(cls, sensor_data_dict): + """ + Create sensor data instances according to the sensor data got from redis + :param sensor_data_dict: sensor data got from redis + :return: A sorted sensor data instance list + """ + sensor_data_list = [] + for name, value in sensor_data_dict.items(): + for sensor_attrs in cls.sensor_attr_dict.values(): + match_result = re.fullmatch(sensor_attrs['pattern'], name) + if match_result: + sensor_data = ThermalSensorData(name, value, sensor_attrs, match_result) + sensor_data_list.append(sensor_data) + + return sensor_data_list diff --git a/src/sonic_ax_impl/mibs/ietf/thermal_sensor_data.py b/src/sonic_ax_impl/mibs/ietf/thermal_sensor_data.py deleted file mode 100644 index e9ac8d545..000000000 --- a/src/sonic_ax_impl/mibs/ietf/thermal_sensor_data.py +++ /dev/null @@ -1,92 +0,0 @@ -import re - -from .physical_entity_sub_oid_generator import SENSOR_TYPE_TEMP - - -class ThermalSensorData: - """ - Base Thermal sensor data class. Responsible for: - 1. Manage concrete sensor data class - 2. Create concrete sensor data instances - 3. Provide common logic for concrete sensor data class - """ - - sensor_attr_dict = { - 'temperature': { - 'pattern': 'temperature', - 'name': 'Temperature', - 'oid_offset_base': SENSOR_TYPE_TEMP, - 'sort_factor': 0 - } - } - - def __init__(self, key, value, sensor_attrs, match_result): - self._key = key - self._value = value - self._sensor_attrs = sensor_attrs - self._match_result = match_result - - @classmethod - def create_sensor_data(cls, sensor_data_dict): - """ - Create sensor data instances according to the sensor data got from redis - :param sensor_data_dict: sensor data got from redis - :return: A sorted sensor data instance list - """ - sensor_data_list = [] - for name, value in sensor_data_dict.items(): - for sensor_attrs in cls.sensor_attr_dict.values(): - match_result = re.fullmatch(sensor_attrs['pattern'], name) - if match_result: - sensor_data = ThermalSensorData(name, value, sensor_attrs, match_result) - sensor_data_list.append(sensor_data) - - return sensor_data_list - - @classmethod - def sort_sensor_data(cls, sensor_data_list): - return sorted(sensor_data_list, key=lambda x: x.get_sort_factor()) - - @classmethod - def bind_sensor_interface(cls, sensor_interface_dict): - for name, sensor_attrs in cls.sensor_attr_dict.items(): - if name in sensor_interface_dict: - sensor_attrs['sensor_interface'] = sensor_interface_dict[name] - - def get_key(self): - """ - Get the redis key of this sensor - """ - return self._key - - def get_raw_value(self): - """ - Get raw redis value of this sensor - """ - return self._value - - def get_name(self): - """ - Get the name of this sensor. Concrete sensor data class must override - this. - """ - return self._sensor_attrs['name'] - - def get_sort_factor(self): - """ - Get sort factor for this sensor. Concrete sensor data class must override - this. - """ - return self._sensor_attrs['sort_factor'] - - def get_oid_offset(self): - """ - Get OID offset of this sensor. - """ - return self._sensor_attrs['oid_offset_base'] - - def get_sensor_interface(self): - """ - Get sensor interface of this sensor. Used by rfc3433. - """ - return self._sensor_attrs['sensor_interface'] diff --git a/src/sonic_ax_impl/mibs/ietf/transceiver_sensor_data.py b/src/sonic_ax_impl/mibs/ietf/transceiver_sensor_data.py deleted file mode 100644 index 587d8adbe..000000000 --- a/src/sonic_ax_impl/mibs/ietf/transceiver_sensor_data.py +++ /dev/null @@ -1,132 +0,0 @@ -import re - -from .physical_entity_sub_oid_generator import SENSOR_TYPE_TEMP -from .physical_entity_sub_oid_generator import SENSOR_TYPE_PORT_TX_POWER -from .physical_entity_sub_oid_generator import SENSOR_TYPE_PORT_RX_POWER -from .physical_entity_sub_oid_generator import SENSOR_TYPE_PORT_TX_BIAS -from .physical_entity_sub_oid_generator import SENSOR_TYPE_VOLTAGE - - -class TransceiverSensorData: - """ - Base transceiver sensor data class. Responsible for: - 1. Manage concrete sensor data class - 2. Create concrete sensor data instances - 3. Provide common logic for concrete sensor data class - """ - - sensor_attr_dict = { - 'temperature': { - 'pattern': 'temperature', - 'name': 'Temperature', - 'oid_offset_base': SENSOR_TYPE_TEMP, - 'sort_factor': 0, - 'lane_based_sensor': False - }, - 'voltage': { - 'pattern': 'voltage', - 'name': 'Voltage', - 'oid_offset_base': SENSOR_TYPE_VOLTAGE, - 'sort_factor': 9000, - 'lane_based_sensor': False - }, - 'rxpower': { - 'pattern': r'rx(\d+)power', - 'name': 'RX Power', - 'oid_offset_base': SENSOR_TYPE_PORT_RX_POWER, - 'sort_factor': 2000, - 'lane_based_sensor': True - }, - 'txpower': { - 'pattern': r'tx(\d+)power', - 'name': 'TX Power', - 'oid_offset_base': SENSOR_TYPE_PORT_TX_POWER, - 'sort_factor': 1000, - 'lane_based_sensor': True - }, - 'txbias': { - 'pattern': r'tx(\d+)bias', - 'name': 'TX Bias', - 'oid_offset_base': SENSOR_TYPE_PORT_TX_BIAS, - 'sort_factor': 3000, - 'lane_based_sensor': True - } - } - - def __init__(self, key, value, sensor_attrs, match_result): - self._key = key - self._value = value - self._sensor_attrs = sensor_attrs - self._match_result = match_result - - @classmethod - def create_sensor_data(cls, sensor_data_dict): - """ - Create sensor data instances according to the sensor data got from redis - :param sensor_data_dict: sensor data got from redis - :return: A sorted sensor data instance list - """ - sensor_data_list = [] - for name, value in sensor_data_dict.items(): - for sensor_attrs in cls.sensor_attr_dict.values(): - match_result = re.match(sensor_attrs['pattern'], name) - if match_result: - sensor_data = TransceiverSensorData(name, value, sensor_attrs, match_result) - sensor_data_list.append(sensor_data) - - return sensor_data_list - - @classmethod - def sort_sensor_data(cls, sensor_data_list): - return sorted(sensor_data_list, key=lambda x: x.get_sort_factor()) - - @classmethod - def bind_sensor_interface(cls, sensor_interface_dict): - for name, sensor_attrs in cls.sensor_attr_dict.items(): - if name in sensor_interface_dict: - sensor_attrs['sensor_interface'] = sensor_interface_dict[name] - - def get_key(self): - """ - Get the redis key of this sensor - """ - return self._key - - def get_raw_value(self): - """ - Get raw redis value of this sensor - """ - return self._value - - def get_name(self): - """ - Get the name of this sensor. Concrete sensor data class must override - this. - """ - return self._sensor_attrs['name'] - - def get_sort_factor(self): - """ - Get sort factor for this sensor. Concrete sensor data class must override - this. - """ - return self._sensor_attrs['sort_factor'] + self.get_lane_number() - - def get_lane_number(self): - """ - Get lane number of this sensor. For example, some transceivers have more than one rx power sensor, the sub index - of rx1power is 1, the sub index of rx2power is 2. - """ - return int(self._match_result.group(1)) if self._sensor_attrs['lane_based_sensor'] else 0 - - def get_oid_offset(self): - """ - Get OID offset of this sensor. - """ - return self._sensor_attrs['oid_offset_base'] + self.get_lane_number() - - def get_sensor_interface(self): - """ - Get sensor interface of this sensor. Used by rfc3433. - """ - return self._sensor_attrs['sensor_interface'] diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 41cc2381d..1dc0f0bb6 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -315,8 +315,8 @@ def test_getpdu_chassis_temp_sensor(self): expected_values = [ rfc3433.EntitySensorDataType.CELSIUS, rfc3433.EntitySensorDataScale.UNITS, - 1, # precision - 205, # expected sensor value + 3, # precision + 20500, # expected sensor value rfc3433.EntitySensorStatus.OK ] From 01313dc3c7b6ab4d65d58cb1af59cabffaa02f89 Mon Sep 17 00:00:00 2001 From: keboliu Date: Sat, 10 Apr 2021 23:43:18 +0800 Subject: [PATCH 3/8] import TransceiverSensorData from new sensor_data.py Signed-off-by: Kebo Liu --- src/sonic_ax_impl/mibs/ietf/rfc2737.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sonic_ax_impl/mibs/ietf/rfc2737.py b/src/sonic_ax_impl/mibs/ietf/rfc2737.py index db5b86579..9c123bf25 100644 --- a/src/sonic_ax_impl/mibs/ietf/rfc2737.py +++ b/src/sonic_ax_impl/mibs/ietf/rfc2737.py @@ -21,8 +21,7 @@ from .physical_entity_sub_oid_generator import get_psu_sensor_sub_id from .physical_entity_sub_oid_generator import get_transceiver_sub_id from .physical_entity_sub_oid_generator import get_transceiver_sensor_sub_id -from .transceiver_sensor_data import TransceiverSensorData - +from .sensor_data import TransceiverSensorData @unique class PhysicalClass(int, Enum): From fddab1714808706ead14876ffbc2195f63f161b0 Mon Sep 17 00:00:00 2001 From: keboliu Date: Sun, 11 Apr 2021 00:17:33 +0800 Subject: [PATCH 4/8] Update test mock state_db.json for new added unit test Signed-off-by: Kebo Liu --- tests/mock_tables/state_db.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/mock_tables/state_db.json b/tests/mock_tables/state_db.json index 20066305d..ae45b16a4 100644 --- a/tests/mock_tables/state_db.json +++ b/tests/mock_tables/state_db.json @@ -94,6 +94,10 @@ "position_in_parent": 1, "parent_name": "chassis 1" }, + "PHYSICAL_ENTITY_INFO|psu_2_fan_1": { + "position_in_parent": "1", + "parent_name": "PSU 2" + }, "FAN_DRAWER_INFO|drawer1": { "model": "DRAWERMODEL", "serial": "DRAWERSERIAL", @@ -107,6 +111,15 @@ "presence": "True", "is_replaceable": "True" }, + "FAN_INFO|psu_2_fan_1": { + "presence": "True", + "status": "True", + "speed": "57", + "drawer_name": "N/A", + "model": "PSUFANMODEL", + "serial": "PSUFANSERIAL", + "is_replaceable": "False" +}, "TEMPERATURE_INFO|thermal1": { "temperature": "20.5", "is_replaceable": "False" From a093bbcdad206fcf14225cf21cf2f5f437b0d86b Mon Sep 17 00:00:00 2001 From: keboliu Date: Sun, 25 Apr 2021 14:37:15 +0800 Subject: [PATCH 5/8] Make the function names in tests/namespace/test_sensor.py align with tests/test_sensor.py Signed-off-by: Kebo Liu --- tests/namespace/test_sensor.py | 42 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/namespace/test_sensor.py b/tests/namespace/test_sensor.py index 3c12bb68a..c5cc9fad7 100644 --- a/tests/namespace/test_sensor.py +++ b/tests/namespace/test_sensor.py @@ -48,7 +48,7 @@ def generate_oids_for_physical_sensor_mib(sub_id): return [ObjectIdentifier(12, 0, 0, 0, (1, 3, 6, 1, 2, 1, 99, 1, 1, 1, i, sub_id)) for i in range(1, 5)] - def _test_getpdu_xcvr_sensor(self, sub_id, expected_values): + def _test_getpdu_sensor(self, sub_id, expected_values): """ Test case for correctness of transceiver sensor MIB values :param sub_id: sub OID of the sensor @@ -75,7 +75,7 @@ def _test_getpdu_xcvr_sensor(self, sub_id, expected_values): def test_getpdu_xcvr_temperature_sensor(self): """ - Test case for correct transceiver temperature sensor MIB values + Test case for correctness of transceiver temperature sensor MIB values """ expected_values = [ rfc3433.EntitySensorDataType.CELSIUS, @@ -85,12 +85,12 @@ def test_getpdu_xcvr_temperature_sensor(self): rfc3433.EntitySensorStatus.OK ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_TEMP)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_TEMP)[0], expected_values) def test_getpdu_xcvr_temperature_sensor_asic1(self): """ - Test case for correct transceiver temperature sensor MIB values + Test case for correctness of transceiver temperature sensor MIB values """ print(rfc3433.PhysicalSensorTableMIB.updater.sub_ids) expected_values = [ @@ -101,11 +101,11 @@ def test_getpdu_xcvr_temperature_sensor_asic1(self): rfc3433.EntitySensorStatus.OK ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX_ASIC1, SENSOR_TYPE_TEMP)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX_ASIC1, SENSOR_TYPE_TEMP)[0], expected_values) def test_getpdu_xcvr_voltage_sensor(self): """ - Test case for correct transceiver voltage sensor MIB values + Test case for correctness of transceiver voltage sensor MIB values """ expected_values = [ @@ -116,12 +116,12 @@ def test_getpdu_xcvr_voltage_sensor(self): rfc3433.EntitySensorStatus.OK ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_VOLTAGE)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_VOLTAGE)[0], expected_values) def test_getpdu_xcvr_voltage_sensor_asic1(self): """ - Test case for correct transceiver voltage sensor MIB values + Test case for correctness of transceiver voltage sensor MIB values """ expected_values = [ @@ -132,11 +132,11 @@ def test_getpdu_xcvr_voltage_sensor_asic1(self): rfc3433.EntitySensorStatus.OK ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX_ASIC1, SENSOR_TYPE_VOLTAGE)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX_ASIC1, SENSOR_TYPE_VOLTAGE)[0], expected_values) def test_getpdu_xcvr_rx_power_sensor_minus_infinity(self): """ - Test case for correct transceiver rx power sensor MIB values + Test case for correctness of transceiver rx power sensor MIB values in case when rx power == -inf """ @@ -148,11 +148,11 @@ def test_getpdu_xcvr_rx_power_sensor_minus_infinity(self): rfc3433.EntitySensorStatus.OK ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 1 + SENSOR_TYPE_PORT_RX_POWER)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 1 + SENSOR_TYPE_PORT_RX_POWER)[0], expected_values) def test_getpdu_xcvr_rx_power_sensor(self): """ - Test case for correct transceiver rx power sensor MIB values + Test case for correctness of transceiver rx power sensor MIB values """ expected_values = [ @@ -165,11 +165,11 @@ def test_getpdu_xcvr_rx_power_sensor(self): # test for each channel except first, we already test above for channel in (2, 3, 4): - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_RX_POWER + channel)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_RX_POWER + channel)[0], expected_values) def test_getpdu_xcvr_tx_power_sensor(self): """ - Test case for correct transceiver rx power sensor MIB values + Test case for correctness of transceiver rx power sensor MIB values """ expected_values = [ @@ -182,11 +182,11 @@ def test_getpdu_xcvr_tx_power_sensor(self): # test for each channel except first, we already test above for channel in (1, 2, 3, 4): - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_TX_POWER + channel)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_TX_POWER + channel)[0], expected_values) def test_getpdu_xcvr_tx_bias_sensor_unknown(self): """ - Test case for correct transceiver tx bias sensor MIB values, when + Test case for correctness of transceiver tx bias sensor MIB values, when tx bias sensor is set to "UNKNOWN" in state DB """ @@ -198,11 +198,11 @@ def test_getpdu_xcvr_tx_bias_sensor_unknown(self): rfc3433.EntitySensorStatus.UNAVAILABLE ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 1 + SENSOR_TYPE_PORT_TX_BIAS)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 1 + SENSOR_TYPE_PORT_TX_BIAS)[0], expected_values) def test_getpdu_xcvr_tx_bias_sensor_overflow(self): """ - Test case for correct transceiver tx bias sensor MIB values + Test case for correctness of transceiver tx bias sensor MIB values when tx bias is grater than 1E9 """ @@ -214,11 +214,11 @@ def test_getpdu_xcvr_tx_bias_sensor_overflow(self): rfc3433.EntitySensorStatus.OK ] - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 3 + SENSOR_TYPE_PORT_TX_BIAS)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, 3 + SENSOR_TYPE_PORT_TX_BIAS)[0], expected_values) def test_getpdu_xcvr_tx_bias_sensor(self): """ - Test case for correct transceiver tx bias sensor MIB values + Test case for correctness of transceiver tx bias sensor MIB values """ expected_values = [ @@ -231,5 +231,5 @@ def test_getpdu_xcvr_tx_bias_sensor(self): # test for each channel for channel in (2, 4): - self._test_getpdu_xcvr_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_TX_BIAS + channel)[0], expected_values) + self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_TX_BIAS + channel)[0], expected_values) From b409e1db108bbc78ea69f9002b954bdb956b10e2 Mon Sep 17 00:00:00 2001 From: keboliu Date: Wed, 5 May 2021 21:17:10 +0800 Subject: [PATCH 6/8] fix review comments --- src/sonic_ax_impl/mibs/ietf/rfc3433.py | 39 +++---- tests/mock_tables/global_db/state_db.json | 125 ++++++++++++++++++++++ tests/namespace/test_sensor.py | 125 ++++++++++++++++++++++ 3 files changed, 271 insertions(+), 18 deletions(-) diff --git a/src/sonic_ax_impl/mibs/ietf/rfc3433.py b/src/sonic_ax_impl/mibs/ietf/rfc3433.py index 42d2570d8..6602fca72 100644 --- a/src/sonic_ax_impl/mibs/ietf/rfc3433.py +++ b/src/sonic_ax_impl/mibs/ietf/rfc3433.py @@ -20,6 +20,8 @@ from .sensor_data import ThermalSensorData, FANSensorData, PSUSensorData, TransceiverSensorData NOT_AVAILABLE = 'N/A' +CHASSIS_NAME_SUB_STRING = 'chassis' +PSU_NAME_SUB_STRING = 'PSU' def is_null_empty_str(value): @@ -386,15 +388,17 @@ def reinit_data(self): if transceiver_dom_encoded: self.transceiver_dom = [entry for entry in transceiver_dom_encoded] - fan_sensor_encoded = Namespace.dbs_keys(self.statedb, mibs.STATE_DB, self.FAN_SENSOR_KEY_PATTERN) + # for FAN, PSU and thermal sensors, they are in host namespace DB, to avoid iterating all namespace DBs, + # just get data from host namespace DB, which is self.statedb[0]. + fan_sensor_encoded = self.statedb[0].keys(self.statedb[0].STATE_DB, self.FAN_SENSOR_KEY_PATTERN) if fan_sensor_encoded: self.fan_sensor = [entry for entry in fan_sensor_encoded] - psu_sensor_encoded = Namespace.dbs_keys(self.statedb, mibs.STATE_DB, self.PSU_SENSOR_KEY_PATTERN) + psu_sensor_encoded = self.statedb[0].keys(self.statedb[0].STATE_DB, self.PSU_SENSOR_KEY_PATTERN) if psu_sensor_encoded: self.psu_sensor = [entry for entry in psu_sensor_encoded] - thermal_sensor_encoded = Namespace.dbs_keys(self.statedb, mibs.STATE_DB, self.THERMAL_SENSOR_KEY_PATTERN) + thermal_sensor_encoded = self.statedb[0].keys(self.statedb[0].STATE_DB, self.THERMAL_SENSOR_KEY_PATTERN) if thermal_sensor_encoded: self.thermal_sensor = [entry for entry in thermal_sensor_encoded] @@ -447,15 +451,15 @@ def update_psu_sensor_data(self): for psu_sensor_entry in self.psu_sensor: psu_name = psu_sensor_entry.split(mibs.TABLE_NAME_SEPARATOR_VBAR)[-1] - psu_relation_info = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, - mibs.physical_entity_info_table(psu_name)) + psu_relation_info = self.statedb[0].get_all(self.statedb[0].STATE_DB, + mibs.physical_entity_info_table(psu_name)) psu_position, psu_parent_name = get_db_data(psu_relation_info, PhysicalRelationInfoDB) if is_null_empty_str(psu_position): continue psu_position = int(psu_position) psu_sub_id = get_psu_sub_id(psu_position) - psu_sensor_entry_data = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, psu_sensor_entry) + psu_sensor_entry_data = self.statedb[0].get_all(self.statedb[0].STATE_DB, psu_sensor_entry) if not psu_sensor_entry_data: continue @@ -490,27 +494,26 @@ def update_fan_sensor_data(self): fan_parent_sub_id = 0 for fan_sensor_entry in self.fan_sensor: fan_name = fan_sensor_entry.split(mibs.TABLE_NAME_SEPARATOR_VBAR)[-1] - fan_relation_info = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, - mibs.physical_entity_info_table(fan_name)) - + fan_relation_info = self.statedb[0].get_all(self.statedb[0].STATE_DB, + mibs.physical_entity_info_table(fan_name)) fan_position, fan_parent_name = get_db_data(fan_relation_info, PhysicalRelationInfoDB) if is_null_empty_str(fan_position): continue fan_position = int(fan_position) - if "chassis" in fan_parent_name: + if CHASSIS_NAME_SUB_STRING in fan_parent_name: fan_parent_sub_id = (CHASSIS_SUB_ID,) else: - fan_parent_relation_info = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, - mibs.physical_entity_info_table(fan_parent_name)) + fan_parent_relation_info = self.statedb[0].get_all(self.statedb[0].STATE_DB, + mibs.physical_entity_info_table(fan_parent_name)) if fan_parent_relation_info: fan_parent_position, fan_grad_parent_name = get_db_data(fan_parent_relation_info, PhysicalRelationInfoDB) fan_parent_position = int(fan_parent_position) - if "PSU" in fan_parent_name: + if PSU_NAME_SUB_STRING in fan_parent_name: fan_parent_sub_id = get_psu_sub_id(fan_parent_position) else: fan_parent_sub_id = get_fan_drawer_sub_id(fan_parent_position) @@ -520,7 +523,7 @@ def update_fan_sensor_data(self): fan_sub_id = get_fan_sub_id(fan_parent_sub_id, fan_position) - fan_sensor_entry_data = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, fan_sensor_entry) + fan_sensor_entry_data = self.statedb[0].get_all(self.statedb[0].STATE_DB, fan_sensor_entry) if not fan_sensor_entry_data: mibs.logger.error("fan_name = {} get fan_sensor_entry_data failed".format(fan_name)) @@ -555,17 +558,17 @@ def update_thermal_sensor_data(self): for thermal_sensor_entry in self.thermal_sensor: thermal_name = thermal_sensor_entry.split(mibs.TABLE_NAME_SEPARATOR_VBAR)[-1] - thermal_relation_info = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, - mibs.physical_entity_info_table(thermal_name)) + thermal_relation_info = self.statedb[0].get_all(self.statedb[0].STATE_DB, + mibs.physical_entity_info_table(thermal_name)) thermal_position, thermal_parent_name = get_db_data(thermal_relation_info, PhysicalRelationInfoDB) if is_null_empty_str(thermal_parent_name) or is_null_empty_str(thermal_parent_name) or \ - "chassis" not in thermal_parent_name.lower(): + CHASSIS_NAME_SUB_STRING not in thermal_parent_name.lower(): continue thermal_position = int(thermal_position) - thermal_sensor_entry_data = Namespace.dbs_get_all(self.statedb, mibs.STATE_DB, thermal_sensor_entry) + thermal_sensor_entry_data = self.statedb[0].get_all(self.statedb[0].STATE_DB, thermal_sensor_entry) if not thermal_sensor_entry_data: continue diff --git a/tests/mock_tables/global_db/state_db.json b/tests/mock_tables/global_db/state_db.json index 2c63c0851..0674d83ab 100644 --- a/tests/mock_tables/global_db/state_db.json +++ b/tests/mock_tables/global_db/state_db.json @@ -1,2 +1,127 @@ { + "DEVICE_METADATA|localhost": { + "chassis_serial_number": "SAMPLETESTSN" + }, + "PSU_INFO|PSU 1": { + "presence": "false", + "status": "false", + "current": "15.4", + "power": "302.6", + "voltage": "15.1", + "temp": "30.1" + }, + "PSU_INFO|PSU 2": { + "presence": "true", + "status": "true", + "current": "13.4", + "power": "312.6", + "voltage": "13.1", + "temp": "31.1", + "model": "PSU_MODEL", + "serial": "PSU_SERIAL", + "is_replaceable": "True" + }, + "PSU_INFO|PSU 3": { + "presence": "true", + "status": "false", + "current": "15.5", + "power": "302.8", + "voltage": "15.5", + "temp": "30.8" + }, + "CHASSIS_INFO|chassis 1": { + "psu_num": "3" + }, + "TRANSCEIVER_INFO|Ethernet0": { + "type": "QSFP+", + "hardware_rev": "A1", + "serial": "SERIAL_NUM", + "manufacturer": "VENDOR_NAME", + "model": "MODEL_NAME", + "is_replaceable": "True" + }, + "TRANSCEIVER_INFO|Ethernet1": { + "type": "QSFP-DD", + "hardware_rev": "A1", + "serial": "SERIAL_NUM", + "manufacturer": "VENDOR_NAME", + "model": "MODEL_NAME", + "is_replaceable": "True" + }, + "TRANSCEIVER_DOM_SENSOR|Ethernet0": { + "temperature": 25.39, + "voltage": 3.37, + "tx1bias": "N/A", + "tx2bias": 4.44, + "tx3bias": "inf", + "tx4bias": 4.44, + "rx1power": "-inf", + "rx2power": -0.97, + "rx3power": -0.97, + "rx4power": -0.97, + "tx1power": -5.4, + "tx2power": -5.4, + "tx3power": -5.4, + "tx4power": -5.4 + }, + "MGMT_PORT_TABLE|eth0": { + "oper_status": "down" + }, + "MGMT_PORT_TABLE|eth1": { + "oper_status": "up" + }, + "PHYSICAL_ENTITY_INFO|PSU 1": { + "position_in_parent": 1, + "parent_name": "chassis 1" + }, + "PHYSICAL_ENTITY_INFO|PSU 2": { + "position_in_parent": 2, + "parent_name": "chassis 1" + }, + "PHYSICAL_ENTITY_INFO|PSU 3": { + "position_in_parent": 3, + "parent_name": "chassis 1" + }, + "PHYSICAL_ENTITY_INFO|drawer1": { + "position_in_parent": 1, + "parent_name": "chassis 1" + }, + "PHYSICAL_ENTITY_INFO|fan1": { + "position_in_parent": 1, + "parent_name": "drawer1" + }, + "PHYSICAL_ENTITY_INFO|thermal1": { + "position_in_parent": 1, + "parent_name": "chassis 1" + }, + "PHYSICAL_ENTITY_INFO|psu_2_fan_1": { + "position_in_parent": "1", + "parent_name": "PSU 2" + }, + "FAN_DRAWER_INFO|drawer1": { + "model": "DRAWERMODEL", + "serial": "DRAWERSERIAL", + "presence": "True", + "is_replaceable": "True" + }, + "FAN_INFO|fan1": { + "model": "FANMODEL", + "serial": "FANSERIAL", + "speed": "50", + "presence": "True", + "is_replaceable": "True" + }, + "FAN_INFO|psu_2_fan_1": { + "presence": "True", + "status": "True", + "speed": "57", + "drawer_name": "N/A", + "model": "PSUFANMODEL", + "serial": "PSUFANSERIAL", + "is_replaceable": "False" + }, + "TEMPERATURE_INFO|thermal1": { + "temperature": "20.5", + "is_replaceable": "False" + } } diff --git a/tests/namespace/test_sensor.py b/tests/namespace/test_sensor.py index c5cc9fad7..b5eaf7cae 100644 --- a/tests/namespace/test_sensor.py +++ b/tests/namespace/test_sensor.py @@ -17,6 +17,12 @@ from ax_interface.encodings import ObjectIdentifier from ax_interface.constants import PduTypes from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_transceiver_sub_id, get_transceiver_sensor_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_psu_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_psu_sensor_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_fan_drawer_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_fan_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_fan_tachometers_sub_id +from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import get_chassis_thermal_sub_id from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import SENSOR_TYPE_TEMP from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import SENSOR_TYPE_VOLTAGE from sonic_ax_impl.mibs.ietf.physical_entity_sub_oid_generator import SENSOR_TYPE_PORT_RX_POWER @@ -36,6 +42,11 @@ def setUpClass(cls): cls.XCVR_SUB_ID = get_transceiver_sub_id(cls.IFINDEX) cls.XCVR_SUB_ID_ASIC1 = get_transceiver_sub_id(cls.IFINDEX_ASIC1) cls.XCVR_CHANNELS = (1, 2, 3, 4) + cls.PSU_POSITION = 2 + cls.FAN_DRAWER_POSITION = 1 + cls.FAN_POSITION = 1 + cls.PSU_FAN_POSITION = 1 + cls.THERMAL_POSITION = 1 # Update MIBs for updater in cls.lut.updater_instances: @@ -233,3 +244,117 @@ def test_getpdu_xcvr_tx_bias_sensor(self): for channel in (2, 4): self._test_getpdu_sensor(get_transceiver_sensor_sub_id(self.IFINDEX, SENSOR_TYPE_PORT_TX_BIAS + channel)[0], expected_values) + def test_getpdu_psu_temp_sensor(self): + """ + Test case for correctness of psu temperature sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.CELSIUS, + rfc3433.EntitySensorDataScale.UNITS, + 3, # precision + 31100, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + psu_sub_id = get_psu_sub_id(self.PSU_POSITION) + self._test_getpdu_sensor(get_psu_sensor_sub_id(psu_sub_id, "temperature")[0], expected_values) + + def test_getpdu_psu_voltage_sensor(self): + """ + Test case for correctness of psu voltage sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.VOLTS_DC, + rfc3433.EntitySensorDataScale.UNITS, + 3, # precision + 13100, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + psu_sub_id = get_psu_sub_id(self.PSU_POSITION) + self._test_getpdu_sensor(get_psu_sensor_sub_id(psu_sub_id, "voltage")[0], expected_values) + + def test_getpdu_psu_power_sensor(self): + """ + Test case for correctness of psu voltage sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.WATTS, + rfc3433.EntitySensorDataScale.UNITS, + 3, # precision + 312600, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + psu_sub_id = get_psu_sub_id(self.PSU_POSITION) + self._test_getpdu_sensor(get_psu_sensor_sub_id(psu_sub_id, "power")[0], expected_values) + + def test_getpdu_psu_current_sensor(self): + """ + Test case for correctness of psu current sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.AMPERES, + rfc3433.EntitySensorDataScale.UNITS, + 3, # precision + 13400, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + psu_sub_id = get_psu_sub_id(self.PSU_POSITION) + self._test_getpdu_sensor(get_psu_sensor_sub_id(psu_sub_id, "current")[0], expected_values) + + def test_getpdu_chassis_fan_speed_sensor(self): + """ + Test case for correctness of fan speed sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.UNKNOWN, + rfc3433.EntitySensorDataScale.UNITS, + 0, # precision + 50, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + fan_parent_sub_id = get_fan_drawer_sub_id(self.FAN_DRAWER_POSITION) + fan_sub_id = get_fan_sub_id(fan_parent_sub_id, self.FAN_POSITION) + + self._test_getpdu_sensor(get_fan_tachometers_sub_id(fan_sub_id)[0], expected_values) + + def test_getpdu_psu_fan_speed_sensor(self): + """ + Test case for correctness of psu fan speed sensor MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.UNKNOWN, + rfc3433.EntitySensorDataScale.UNITS, + 0, # precision + 57, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + psu_sub_id = get_psu_sub_id(self.PSU_POSITION) + fan_sub_id = get_fan_sub_id(psu_sub_id, self.PSU_FAN_POSITION) + + self._test_getpdu_sensor(get_fan_tachometers_sub_id(fan_sub_id)[0], expected_values) + + def test_getpdu_chassis_temp_sensor(self): + """ + Test case for correctness of chassis temp sensors MIB values + """ + + expected_values = [ + rfc3433.EntitySensorDataType.CELSIUS, + rfc3433.EntitySensorDataScale.UNITS, + 3, # precision + 20500, # expected sensor value + rfc3433.EntitySensorStatus.OK + ] + + self._test_getpdu_sensor(get_chassis_thermal_sub_id(self.THERMAL_POSITION)[0], expected_values) From 8a8e7896f3edbfd49e7f9247c46bfa2dd6a23823 Mon Sep 17 00:00:00 2001 From: keboliu Date: Thu, 6 May 2021 18:37:35 +0800 Subject: [PATCH 7/8] fix review comments --- src/sonic_ax_impl/mibs/__init__.py | 2 ++ src/sonic_ax_impl/mibs/ietf/rfc3433.py | 35 +++++++++++++++----------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/sonic_ax_impl/mibs/__init__.py b/src/sonic_ax_impl/mibs/__init__.py index f3b0d17fa..fe7e74ddb 100644 --- a/src/sonic_ax_impl/mibs/__init__.py +++ b/src/sonic_ax_impl/mibs/__init__.py @@ -25,6 +25,8 @@ TABLE_NAME_SEPARATOR_COLON = ':' TABLE_NAME_SEPARATOR_VBAR = '|' +HOST_NAMESPACE_DB_IDX = 0 + redis_kwargs = {'unix_socket_path': '/var/run/redis/redis.sock'} diff --git a/src/sonic_ax_impl/mibs/ietf/rfc3433.py b/src/sonic_ax_impl/mibs/ietf/rfc3433.py index 6602fca72..1bde5d4ab 100644 --- a/src/sonic_ax_impl/mibs/ietf/rfc3433.py +++ b/src/sonic_ax_impl/mibs/ietf/rfc3433.py @@ -8,6 +8,7 @@ from swsssdk import port_util from ax_interface import MIBMeta, MIBUpdater, ValueType, SubtreeMIBEntry from sonic_ax_impl import mibs +from sonic_ax_impl.mibs import HOST_NAMESPACE_DB_IDX from sonic_ax_impl.mibs import Namespace from .physical_entity_sub_oid_generator import CHASSIS_SUB_ID from .physical_entity_sub_oid_generator import get_transceiver_sensor_sub_id @@ -390,15 +391,18 @@ def reinit_data(self): # for FAN, PSU and thermal sensors, they are in host namespace DB, to avoid iterating all namespace DBs, # just get data from host namespace DB, which is self.statedb[0]. - fan_sensor_encoded = self.statedb[0].keys(self.statedb[0].STATE_DB, self.FAN_SENSOR_KEY_PATTERN) + fan_sensor_encoded = self.statedb[HOST_NAMESPACE_DB_IDX].keys(self.statedb[HOST_NAMESPACE_DB_IDX].STATE_DB, + self.FAN_SENSOR_KEY_PATTERN) if fan_sensor_encoded: self.fan_sensor = [entry for entry in fan_sensor_encoded] - psu_sensor_encoded = self.statedb[0].keys(self.statedb[0].STATE_DB, self.PSU_SENSOR_KEY_PATTERN) + psu_sensor_encoded = self.statedb[HOST_NAMESPACE_DB_IDX].keys(self.statedb[HOST_NAMESPACE_DB_IDX].STATE_DB, + self.PSU_SENSOR_KEY_PATTERN) if psu_sensor_encoded: self.psu_sensor = [entry for entry in psu_sensor_encoded] - thermal_sensor_encoded = self.statedb[0].keys(self.statedb[0].STATE_DB, self.THERMAL_SENSOR_KEY_PATTERN) + thermal_sensor_encoded = self.statedb[HOST_NAMESPACE_DB_IDX].keys(self.statedb[HOST_NAMESPACE_DB_IDX].STATE_DB, + self.THERMAL_SENSOR_KEY_PATTERN) if thermal_sensor_encoded: self.thermal_sensor = [entry for entry in thermal_sensor_encoded] @@ -451,15 +455,16 @@ def update_psu_sensor_data(self): for psu_sensor_entry in self.psu_sensor: psu_name = psu_sensor_entry.split(mibs.TABLE_NAME_SEPARATOR_VBAR)[-1] - psu_relation_info = self.statedb[0].get_all(self.statedb[0].STATE_DB, - mibs.physical_entity_info_table(psu_name)) + psu_relation_info = self.statedb[HOST_NAMESPACE_DB_IDX].get_all( + self.statedb[HOST_NAMESPACE_DB_IDX].STATE_DB, mibs.physical_entity_info_table(psu_name)) psu_position, psu_parent_name = get_db_data(psu_relation_info, PhysicalRelationInfoDB) if is_null_empty_str(psu_position): continue psu_position = int(psu_position) psu_sub_id = get_psu_sub_id(psu_position) - psu_sensor_entry_data = self.statedb[0].get_all(self.statedb[0].STATE_DB, psu_sensor_entry) + psu_sensor_entry_data = self.statedb[HOST_NAMESPACE_DB_IDX].get_all( + self.statedb[HOST_NAMESPACE_DB_IDX].STATE_DB, psu_sensor_entry) if not psu_sensor_entry_data: continue @@ -494,8 +499,8 @@ def update_fan_sensor_data(self): fan_parent_sub_id = 0 for fan_sensor_entry in self.fan_sensor: fan_name = fan_sensor_entry.split(mibs.TABLE_NAME_SEPARATOR_VBAR)[-1] - fan_relation_info = self.statedb[0].get_all(self.statedb[0].STATE_DB, - mibs.physical_entity_info_table(fan_name)) + fan_relation_info = self.statedb[HOST_NAMESPACE_DB_IDX].get_all( + self.statedb[HOST_NAMESPACE_DB_IDX].STATE_DB, mibs.physical_entity_info_table(fan_name)) fan_position, fan_parent_name = get_db_data(fan_relation_info, PhysicalRelationInfoDB) if is_null_empty_str(fan_position): continue @@ -505,8 +510,8 @@ def update_fan_sensor_data(self): if CHASSIS_NAME_SUB_STRING in fan_parent_name: fan_parent_sub_id = (CHASSIS_SUB_ID,) else: - fan_parent_relation_info = self.statedb[0].get_all(self.statedb[0].STATE_DB, - mibs.physical_entity_info_table(fan_parent_name)) + fan_parent_relation_info = self.statedb[HOST_NAMESPACE_DB_IDX].get_all( + self.statedb[HOST_NAMESPACE_DB_IDX].STATE_DB, mibs.physical_entity_info_table(fan_parent_name)) if fan_parent_relation_info: fan_parent_position, fan_grad_parent_name = get_db_data(fan_parent_relation_info, PhysicalRelationInfoDB) @@ -523,7 +528,8 @@ def update_fan_sensor_data(self): fan_sub_id = get_fan_sub_id(fan_parent_sub_id, fan_position) - fan_sensor_entry_data = self.statedb[0].get_all(self.statedb[0].STATE_DB, fan_sensor_entry) + fan_sensor_entry_data = self.statedb[HOST_NAMESPACE_DB_IDX].get_all( + self.statedb[HOST_NAMESPACE_DB_IDX].STATE_DB, fan_sensor_entry) if not fan_sensor_entry_data: mibs.logger.error("fan_name = {} get fan_sensor_entry_data failed".format(fan_name)) @@ -558,8 +564,8 @@ def update_thermal_sensor_data(self): for thermal_sensor_entry in self.thermal_sensor: thermal_name = thermal_sensor_entry.split(mibs.TABLE_NAME_SEPARATOR_VBAR)[-1] - thermal_relation_info = self.statedb[0].get_all(self.statedb[0].STATE_DB, - mibs.physical_entity_info_table(thermal_name)) + thermal_relation_info = self.statedb[HOST_NAMESPACE_DB_IDX].get_all( + self.statedb[HOST_NAMESPACE_DB_IDX].STATE_DB, mibs.physical_entity_info_table(thermal_name)) thermal_position, thermal_parent_name = get_db_data(thermal_relation_info, PhysicalRelationInfoDB) if is_null_empty_str(thermal_parent_name) or is_null_empty_str(thermal_parent_name) or \ @@ -568,7 +574,8 @@ def update_thermal_sensor_data(self): thermal_position = int(thermal_position) - thermal_sensor_entry_data = self.statedb[0].get_all(self.statedb[0].STATE_DB, thermal_sensor_entry) + thermal_sensor_entry_data = self.statedb[HOST_NAMESPACE_DB_IDX].get_all( + self.statedb[HOST_NAMESPACE_DB_IDX].STATE_DB, thermal_sensor_entry) if not thermal_sensor_entry_data: continue From 3c19b14c7ca3c84e6fa5dd4a0059ee86a50443e4 Mon Sep 17 00:00:00 2001 From: Qi Luo Date: Mon, 17 May 2021 23:05:05 +0000 Subject: [PATCH 8/8] Add lgtm.yml Signed-off-by: Qi Luo --- lgtm.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 lgtm.yml diff --git a/lgtm.yml b/lgtm.yml new file mode 100644 index 000000000..124b90c50 --- /dev/null +++ b/lgtm.yml @@ -0,0 +1,25 @@ +extraction: + python: + python_setup: + version: "3" + prepare: + packages: + - libxml-simple-perl + - aspell + - aspell-en + - libhiredis-dev + - libnl-3-dev + - libnl-genl-3-dev + - libnl-route-3-dev + - libnl-nf-3-dev + - libzmq3-dev + - libzmq5 + - swig3.0 + - libpython2.7-dev + - libgtest-dev + - dh-exec + - doxygen + - graphviz + after_prepare: + - git clone https://github.com/Azure/sonic-py-swsssdk.git; pushd sonic-py-swsssdk; python3 setup.py bdist_wheel; popd + - pip3 install --upgrade --user sonic-py-swsssdk/dist/swsssdk-2.0.1-py3-none-any.whl