def _get_psu_status(self, psu_index):
        """
        Get PSU status
        :return: the status of particular PSU
        """
        psu_name = PSU_INFO_KEY_TEMPLATE.format(psu_index)
        psu_info = self.statedb.get_all(self.statedb.STATE_DB, mibs.psu_info_table(psu_name))
        presence, status = get_psu_data(psu_info)

        return status == PSU_STATUS_OK
    def _get_psu_presence(self, psu_index):
        """
        Get PSU presence
        :return: the presence of particular PSU
        """
        psu_name = PSU_INFO_KEY_TEMPLATE.format(psu_index)
        psu_info = self.statedb.get_all(self.statedb.STATE_DB, mibs.psu_info_table(psu_name))
        presence, status = get_psu_data(psu_info)

        return presence == PSU_PRESENCE_OK
Example #3
0
    def _get_psu_status(self, psu_index):
        """
        Get PSU status
        :return: the status of particular PSU
        """
        psu_name = PSU_INFO_KEY_TEMPLATE.format(psu_index)
        psu_info = self.statedb.get_all(self.statedb.STATE_DB, mibs.psu_info_table(psu_name))
        presence, status = get_psu_data(psu_info)

        return status == PSU_STATUS_OK
Example #4
0
    def _get_psu_presence(self, psu_index):
        """
        Get PSU presence
        :return: the presence of particular PSU
        """
        psu_name = PSU_INFO_KEY_TEMPLATE.format(psu_index)
        psu_info = self.statedb.get_all(self.statedb.STATE_DB, mibs.psu_info_table(psu_name))
        presence, status = get_psu_data(psu_info)

        return presence == PSU_PRESENCE_OK
Example #5
0
    def _update_entity_cache(self, psu_name):
        psu_info = Namespace.dbs_get_all(self.mib_updater.statedb,
                                         mibs.STATE_DB,
                                         mibs.psu_info_table(psu_name))

        if not psu_info:
            return

        model, serial, current, power, presence, voltage, temperature, replaceable = get_db_data(
            psu_info, PsuInfoDB)
        if presence.lower() != 'true':
            self._remove_entity_cache(psu_name)
            return

        psu_relation_info = self.get_physical_relation_info(psu_name)
        psu_position, psu_parent_name = get_db_data(psu_relation_info,
                                                    PhysicalRelationInfoDB)
        psu_position = int(psu_position)
        psu_sub_id = get_psu_sub_id(psu_position)
        self._add_entity_related_oid(psu_name, psu_sub_id)
        self.mib_updater.update_name_to_oid_map(psu_name, psu_sub_id)

        # add PSU to available OID list
        self.mib_updater.add_sub_id(psu_sub_id)
        self.mib_updater.set_phy_class(psu_sub_id, PhysicalClass.POWERSUPPLY)
        self.mib_updater.set_phy_descr(psu_sub_id, psu_name)
        self.mib_updater.set_phy_name(psu_sub_id, psu_name)
        if not is_null_str(model):
            self.mib_updater.set_phy_model_name(psu_sub_id, model)
        if not is_null_str(serial):
            self.mib_updater.set_phy_serial_num(psu_sub_id, serial)
        self.mib_updater.set_phy_parent_relative_pos(psu_sub_id, psu_position)
        self.mib_updater.set_phy_contained_in(psu_sub_id, psu_parent_name)
        self.mib_updater.set_phy_fru(psu_sub_id, replaceable)

        # add psu current sensor as a physical entity
        if current and not is_null_str(current):
            self._update_psu_sensor_cache(psu_name, psu_sub_id, 'current')
        if power and not is_null_str(power):
            self._update_psu_sensor_cache(psu_name, psu_sub_id, 'power')
        if temperature and not is_null_str(temperature):
            self._update_psu_sensor_cache(psu_name, psu_sub_id, 'temperature')
        if voltage and not is_null_str(voltage):
            self._update_psu_sensor_cache(psu_name, psu_sub_id, 'voltage')
Example #6
0
class PsuCacheUpdater(PhysicalEntityCacheUpdater):
    KEY_PATTERN = mibs.psu_info_table("*")

    def __init__(self, mib_updater):
        super(PsuCacheUpdater, self).__init__(mib_updater)

    def get_key_pattern(self):
        return PsuCacheUpdater.KEY_PATTERN

    def _update_entity_cache(self, psu_name):
        psu_info = Namespace.dbs_get_all(self.mib_updater.statedb,
                                         mibs.STATE_DB,
                                         mibs.psu_info_table(psu_name))

        if not psu_info:
            return

        model, serial, current, power, presence, voltage, temperature, replaceable = get_db_data(
            psu_info, PsuInfoDB)
        if presence.lower() != 'true':
            self._remove_entity_cache(psu_name)
            return

        psu_relation_info = self.get_physical_relation_info(psu_name)
        psu_position, psu_parent_name = get_db_data(psu_relation_info,
                                                    PhysicalRelationInfoDB)
        psu_position = int(psu_position)
        psu_sub_id = get_psu_sub_id(psu_position)
        self._add_entity_related_oid(psu_name, psu_sub_id)
        self.mib_updater.update_name_to_oid_map(psu_name, psu_sub_id)

        # add PSU to available OID list
        self.mib_updater.add_sub_id(psu_sub_id)
        self.mib_updater.set_phy_class(psu_sub_id, PhysicalClass.POWERSUPPLY)
        self.mib_updater.set_phy_descr(psu_sub_id, psu_name)
        self.mib_updater.set_phy_name(psu_sub_id, psu_name)
        if not is_null_str(model):
            self.mib_updater.set_phy_model_name(psu_sub_id, model)
        if not is_null_str(serial):
            self.mib_updater.set_phy_serial_num(psu_sub_id, serial)
        self.mib_updater.set_phy_parent_relative_pos(psu_sub_id, psu_position)
        self.mib_updater.set_phy_contained_in(psu_sub_id, psu_parent_name)
        self.mib_updater.set_phy_fru(psu_sub_id, replaceable)

        # add psu current sensor as a physical entity
        if current and not is_null_str(current):
            self._update_psu_sensor_cache(psu_name, psu_sub_id, 'current')
        if power and not is_null_str(power):
            self._update_psu_sensor_cache(psu_name, psu_sub_id, 'power')
        if temperature and not is_null_str(temperature):
            self._update_psu_sensor_cache(psu_name, psu_sub_id, 'temperature')
        if voltage and not is_null_str(voltage):
            self._update_psu_sensor_cache(psu_name, psu_sub_id, 'voltage')

    def _update_psu_sensor_cache(self, psu_name, psu_sub_id, sensor_name):
        psu_current_sub_id = get_psu_sensor_sub_id(psu_sub_id, sensor_name)
        self._add_entity_related_oid(psu_name, psu_current_sub_id)
        self.mib_updater.add_sub_id(psu_current_sub_id)
        self.mib_updater.set_phy_class(psu_current_sub_id,
                                       PhysicalClass.SENSOR)
        desc = '{} for {}'.format(PSU_SENSOR_NAME_MAP[sensor_name], psu_name)
        self.mib_updater.set_phy_descr(psu_current_sub_id, desc)
        self.mib_updater.set_phy_name(psu_current_sub_id, desc)
        self.mib_updater.set_phy_parent_relative_pos(
            psu_current_sub_id, PSU_SENSOR_POSITION_MAP[sensor_name])
        self.mib_updater.set_phy_contained_in(psu_current_sub_id, psu_sub_id)
        self.mib_updater.set_phy_fru(psu_current_sub_id, False)
Example #7
0
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