def _update_entity_cache(self, fan_name): fan_info = Namespace.dbs_get_all(self.mib_updater.statedb, mibs.STATE_DB, mibs.fan_info_table(fan_name)) if not fan_info: return model, presence, serial, speed, replaceable = get_db_data( fan_info, FanInfoDB) if presence.lower() != 'true': self._remove_entity_cache(fan_name) return fan_relation_info = self.get_physical_relation_info(fan_name) fan_position, fan_parent_name = get_db_data(fan_relation_info, PhysicalRelationInfoDB) fan_position = int(fan_position) if fan_parent_name in self.mib_updater.physical_name_to_oid_map: self._update_fan_mib_info(fan_parent_name, fan_position, fan_name, serial, model, speed, replaceable) else: args = [ fan_parent_name, fan_position, fan_name, serial, model, speed, replaceable ] self.mib_updater.add_pending_entity_name_callback( fan_parent_name, self._update_fan_mib_info, args)
class FanCacheUpdater(PhysicalEntityCacheUpdater): KEY_PATTERN = mibs.fan_info_table("*") def __init__(self, mib_updater): super(FanCacheUpdater, self).__init__(mib_updater) def get_key_pattern(self): return FanCacheUpdater.KEY_PATTERN def _update_entity_cache(self, fan_name): fan_info = Namespace.dbs_get_all(self.mib_updater.statedb, mibs.STATE_DB, mibs.fan_info_table(fan_name)) if not fan_info: return model, presence, serial, speed, replaceable = get_db_data( fan_info, FanInfoDB) if presence.lower() != 'true': self._remove_entity_cache(fan_name) return fan_relation_info = self.get_physical_relation_info(fan_name) fan_position, fan_parent_name = get_db_data(fan_relation_info, PhysicalRelationInfoDB) fan_position = int(fan_position) if fan_parent_name in self.mib_updater.physical_name_to_oid_map: self._update_fan_mib_info(fan_parent_name, fan_position, fan_name, serial, model, speed, replaceable) else: args = [ fan_parent_name, fan_position, fan_name, serial, model, speed, replaceable ] self.mib_updater.add_pending_entity_name_callback( fan_parent_name, self._update_fan_mib_info, args) def _update_fan_mib_info(self, fan_parent_name, fan_position, fan_name, serial, model, speed, replaceable): fan_parent_sub_id = self.mib_updater.physical_name_to_oid_map[ fan_parent_name] fan_sub_id = get_fan_sub_id(fan_parent_sub_id, fan_position) self._add_entity_related_oid(fan_name, fan_sub_id) #self.mib_updater.update_name_to_oid_map(fan_name, fan_sub_id) # add fan to available OID list self.mib_updater.add_sub_id(fan_sub_id) self.mib_updater.set_phy_class(fan_sub_id, PhysicalClass.FAN) self.mib_updater.set_phy_descr(fan_sub_id, fan_name) self.mib_updater.set_phy_name(fan_sub_id, fan_name) self.mib_updater.set_phy_parent_relative_pos(fan_sub_id, fan_position) self.mib_updater.set_phy_contained_in(fan_sub_id, fan_parent_name) if serial and not is_null_str(serial): self.mib_updater.set_phy_serial_num(fan_sub_id, serial) if model and not is_null_str(model): self.mib_updater.set_phy_model_name(fan_sub_id, model) self.mib_updater.set_phy_fru(fan_sub_id, replaceable) # add fan tachometers as a physical entity if speed and not is_null_str(speed): fan_tachometers_sub_id = get_fan_tachometers_sub_id(fan_sub_id) self._add_entity_related_oid(fan_name, fan_tachometers_sub_id) self.mib_updater.add_sub_id(fan_tachometers_sub_id) self.mib_updater.set_phy_class(fan_tachometers_sub_id, PhysicalClass.SENSOR) desc = 'Tachometers for {}'.format(fan_name) self.mib_updater.set_phy_descr(fan_tachometers_sub_id, desc) self.mib_updater.set_phy_name(fan_tachometers_sub_id, desc) self.mib_updater.set_phy_parent_relative_pos( fan_tachometers_sub_id, 1) self.mib_updater.set_phy_contained_in(fan_tachometers_sub_id, fan_sub_id) self.mib_updater.set_phy_fru(fan_tachometers_sub_id, False)
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): """ ctor """ super().__init__() self.statedb = Namespace.init_namespace_dbs() Namespace.connect_all_dbs(self.statedb, mibs.STATE_DB) # list of available sub OIDs self.sub_ids = [] # sensor MIB required values self.ent_phy_sensor_type_map = {} self.ent_phy_sensor_scale_map = {} self.ent_phy_sensor_precision_map = {} self.ent_phy_sensor_value_map = {} self.ent_phy_sensor_oper_state_map = {} self.transceiver_dom = [] self.fan_sensor = [] self.psu_sensor = [] self.thermal_sensor = [] def reinit_data(self): """ Reinit data, clear cache """ # clear cache self.ent_phy_sensor_type_map = {} self.ent_phy_sensor_scale_map = {} self.ent_phy_sensor_precision_map = {} 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) if transceiver_dom_encoded: self.transceiver_dom = [entry for entry in transceiver_dom_encoded] # 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[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[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[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] def update_xcvr_dom_data(self): if not self.transceiver_dom: return # update transceiver sensors cache for transceiver_dom_entry in self.transceiver_dom: # extract interface name interface = transceiver_dom_entry.split( mibs.TABLE_NAME_SEPARATOR_VBAR)[-1] ifindex = port_util.get_index_from_str(interface) if ifindex is None: mibs.logger.warning("Invalid interface name in {} \ in STATE_DB, skipping".format(transceiver_dom_entry)) 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) if not transceiver_dom_entry_data: continue sensor_data_list = TransceiverSensorData.create_sensor_data( transceiver_dom_entry_data) for sensor_data in sensor_data_list: raw_sensor_value = sensor_data.get_raw_value() sensor = sensor_data.get_sensor_interface() sub_id = get_transceiver_sensor_sub_id( ifindex, sensor_data.get_oid_offset()) try: mib_values = sensor.mib_values(raw_sensor_value) except (ValueError, ArithmeticError): mibs.logger.error( "Exception occurred when converting" "value for sensor {} interface {}".format( sensor, interface)) 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_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 = 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[ HOST_NAMESPACE_DB_IDX].get_all( self.statedb[HOST_NAMESPACE_DB_IDX].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 = 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 fan_position = int(fan_position) if CHASSIS_NAME_SUB_STRING in fan_parent_name: fan_parent_sub_id = (CHASSIS_SUB_ID, ) else: 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) fan_parent_position = int(fan_parent_position) 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) 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 = 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)) 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 = 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 \ CHASSIS_NAME_SUB_STRING not in thermal_parent_name.lower(): continue thermal_position = int(thermal_position) 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 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): """ :param sub_id: Input sub_id. :return: The next sub id. """ right = bisect_right(self.sub_ids, sub_id) if right == len(self.sub_ids): return None return self.sub_ids[right] def get_ent_physical_sensor_type(self, sub_id): """ Get sensor type based on sub OID :param sub_id: sub ID of the sensor :return: sensor type from EntitySensorDataType enum or None if sub_id not in the cache. """ if sub_id in self.sub_ids: return self.ent_phy_sensor_type_map.get( sub_id, EntitySensorDataType.UNKNOWN) return None def get_ent_physical_sensor_scale(self, sub_id): """ Get sensor scale value based on sub OID :param sub_id: sub ID of the sensor :return: sensor scale from EntitySensorDataScale enum or None if sub_id not in the cache. """ if sub_id in self.sub_ids: return self.ent_phy_sensor_scale_map.get(sub_id, 0) return None def get_ent_physical_sensor_precision(self, sub_id): """ Get sensor precision value based on sub OID :param sub_id: sub ID of the sensor :return: sensor precision in range (-8, 9) or None if sub_id not in the cache. """ if sub_id in self.sub_ids: return self.ent_phy_sensor_precision_map.get(sub_id, 0) return None def get_ent_physical_sensor_value(self, sub_id): """ Get sensor value based on sub OID :param sub_id: sub ID of the sensor :return: sensor value converted according to tuple (type, scale, precision) """ if sub_id in self.sub_ids: return self.ent_phy_sensor_value_map.get(sub_id, 0) return None def get_ent_physical_sensor_oper_status(self, sub_id): """ Get sensor operational state based on sub OID :param sub_id: sub ID of the sensor :return: sensor's operational state """ if sub_id in self.sub_ids: return self.ent_phy_sensor_oper_state_map.get( sub_id, EntitySensorStatus.UNAVAILABLE) return None