예제 #1
0
파일: entity.py 프로젝트: wujcheng/nav
class Entity(Plugin):
    """Plugin to collect physical entity data from devices"""

    def __init__(self, *args, **kwargs):
        super(Entity, self).__init__(*args, **kwargs)
        self.alias_mapping = {}
        self.entitymib = EntityMib(self.agent)
        self.stampcheck = TimestampChecker(self.agent, self.containers,
                                           INFO_VAR_NAME)

    @defer.inlineCallbacks
    def handle(self):
        self._logger.debug("Collecting physical entity data")
        need_to_collect = yield self._need_to_collect()
        #if need_to_collect:
        if True:
            physical_table = (
                yield self.entitymib.get_entity_physical_table())
            self._logger.debug("found %d entities", len(physical_table))
            self._process_entities(physical_table)
        self.stampcheck.save()

    @defer.inlineCallbacks
    def _need_to_collect(self):
        yield self.stampcheck.load()
        yield self.stampcheck.collect([self.entitymib.get_last_change_time()])

        result = yield self.stampcheck.is_changed()
        defer.returnValue(result)

    def _process_entities(self, result):
        """Process the list of collected entities."""
        # be able to look up all entities using entPhysicalIndex
        entities = EntityTable(result)
        entities.clean_unicode()
        containers = [self._container_from_entity(entity)
                      for entity in entities.values()]
        self._fix_hierarchy(containers)

    def _fix_hierarchy(self, containers):
        by_index = {c.index: c for c in containers}
        ghosts = set()
        for container in containers:
            if container.contained_in:
                parent_id = unicode(container.contained_in)
                parent = by_index.get(parent_id)
                if parent:
                    container.contained_in = parent
                else:
                    ghosts.add(str(container.contained_in))
                    container.contained_in = None

        if ghosts:
            self._logger.info(
                "kick your device vendor in the shin. entPhysicalContainedIn "
                "values refer to non-existant entities: %s", ", ".join(ghosts))

    field_map = {k: 'entPhysical'+v for k, v in dict(
        index='Index',
        descr='Descr',
        vendor_type='VendorType',
        contained_in='ContainedIn',
        physical_class='Class',
        parent_relpos='ParentRelPos',
        name='Name',
        hardware_revision='HardwareRev',
        firmware_revision='FirmwareRev',
        software_revision='SoftwareRev',
        mfg_name='MfgName',
        model_name='ModelName',
        alias='Alias',
        asset_id='AssetID',
        fru='IsFRU',
        mfg_date='MfgDate',
        uris='Uris',
        serial='SerialNum',
    ).items()}

    class_map = {name: value
                 for value, name in manage.NetboxEntity.CLASS_CHOICES}

    def _container_from_entity(self, ent):
        device_key = 'ENTITY-MIB:' + str(ent.get(0))

        container = self.containers.factory(device_key, NetboxEntity)
        netbox = self.containers.factory(None, shadows.Netbox)
        container.netbox = netbox
        container.index = ent.get(0)
        container.source = 'ENTITY-MIB'

        for attr, column in self.field_map.items():
            value = ent.get(column)
            if column == 'entPhysicalClass':
                value = self.class_map.get(value)
            if value is not None:
                setattr(container, attr, value)

        if getattr(container, 'serial', None):
            device = self.containers.factory(container.serial, shadows.Device)
            device.serial = container.serial
            for key in ('hardware', 'firmware', 'software'):
                val = getattr(container, key + '_revision')
                if val:
                    setattr(device, key + '_version', val)
            device.active = True
            container.device = device

        return container
예제 #2
0
class EntitySensorMib(mibretriever.MibRetriever):
    from nav.smidumps.entity_sensor_mib import MIB as mib
    TYPE_COLUMN = 'entPhySensorType'
    SCALE_COLUMN = 'entPhySensorScale'
    PRECISION_COLUMN = 'entPhySensorPrecision'
    VALUE_COLUMN = 'entPhySensorValue'
    STATUS_COLUMN = 'entPhySensorOperStatus'

    def __init__(self, agent_proxy):
        """Good old constructor..."""
        super(EntitySensorMib, self).__init__(agent_proxy)
        self.entity_mib = EntityMib(self.agent_proxy)

    def _get_sensors(self):
        """ Collect all sensors from the box."""
        df = self.retrieve_columns([
            self.TYPE_COLUMN,
            self.SCALE_COLUMN,
            self.PRECISION_COLUMN,
            self.VALUE_COLUMN,
            self.STATUS_COLUMN,
        ])
        df.addCallback(reduce_index)
        return df

    @defer.inlineCallbacks
    def get_all_sensors(self):
        """ Collect all sensors and names on a netbox, and match
            sensors with names.

            Return a list with dictionaries, each dictionary
            represent a sensor."""
        sensors = yield self._get_sensors()
        entities = yield self.entity_mib.get_entity_physical_table()
        aliases = yield self.entity_mib.get_alias_mapping()
        for idx, row in entities.items():
            if idx in sensors:
                sensors[idx]['entPhysicalDescr'] = row.get(
                    'entPhysicalDescr', None)
                sensors[idx]['entPhysicalName'] = row.get(
                    'entPhysicalName', None)
                port = entities.get_nearest_port_parent(row)
                if port and port.index[-1] in aliases:
                    ifindices = aliases[port.index[-1]]
                    if len(ifindices) == 1:
                        sensors[idx]['ifindex'] = ifindices[0]
        result = []
        for row_id, row in sensors.items():
            row_oid = row.get(0, None)
            mibobject = self.nodes.get(self.VALUE_COLUMN, None)
            oid = str(mibobject.oid) + str(row_oid)
            unit_of_measurement = row.get(self.TYPE_COLUMN, 2)
            precision = row.get(self.PRECISION_COLUMN, 0)
            scale = row.get(self.SCALE_COLUMN, None)
            op_status = row.get(self.STATUS_COLUMN, None)
            description = row.get('entPhysicalDescr', None)
            name = row.get('entPhysicalName', None)
            ifindex = row.get('ifindex')
            internal_name = name
            if op_status == 1:
                result.append({
                    'oid':
                    oid,
                    'unit_of_measurement':
                    UNITS_OF_MEASUREMENTS.get(unit_of_measurement, None),
                    'precision':
                    precision,
                    'scale':
                    DATA_SCALE.get(scale, None),
                    'description':
                    description,
                    'name':
                    name,
                    'internal_name':
                    internal_name,
                    'mib':
                    self.get_module_name(),
                    'ifindex':
                    ifindex,
                })
        self._logger.debug('get_all_sensors: result=%s', result)
        defer.returnValue(result)
예제 #3
0
class Modules(Plugin):
    """Plugin to collect module data from devices"""
    def __init__(self, *args, **kwargs):
        super(Modules, self).__init__(*args, **kwargs)
        self.alias_mapping = {}
        self.entitymib = EntityMib(self.agent)
        self.stampcheck = TimestampChecker(self.agent, self.containers,
                                           INFO_VAR_NAME)

    @defer.inlineCallbacks
    def handle(self):
        self._logger.debug("Collecting ENTITY-MIB module data")
        need_to_collect = yield self._need_to_collect()
        if need_to_collect:
            physical_table = (yield self.entitymib.get_entity_physical_table())

            self.alias_mapping = yield self.entitymib.get_alias_mapping()
            self._process_entities(physical_table)
        self.stampcheck.save()

    @defer.inlineCallbacks
    def _need_to_collect(self):
        yield self.stampcheck.load()
        yield self.stampcheck.collect([self.entitymib.get_last_change_time()])

        result = yield self.stampcheck.is_changed()
        defer.returnValue(result)

    def _device_from_entity(self, ent):
        serial_column = 'entPhysicalSerialNum'
        if serial_column in ent and ent[serial_column] and \
            ent[serial_column].strip():
            serial_number = ent[serial_column].strip()
            device_key = serial_number
        else:
            serial_number = None
            device_key = 'unknown-%s' % ent[0]

        device = self.containers.factory(device_key, shadows.Device)
        if serial_number:
            device.serial = serial_number
        if ent['entPhysicalHardwareRev']:
            device.hardware_version = ent['entPhysicalHardwareRev'].strip()
        if ent['entPhysicalSoftwareRev']:
            device.software_version = ent['entPhysicalSoftwareRev'].strip()
        if ent['entPhysicalFirmwareRev']:
            device.firmware_version = ent['entPhysicalFirmwareRev'].strip()
        device.active = True
        return device

    def _module_from_entity(self, ent):
        module = self.containers.factory(ent['entPhysicalSerialNum'],
                                         shadows.Module)
        netbox = self.containers.factory(None, shadows.Netbox)

        module.netbox = netbox
        module.model = ent['entPhysicalModelName'].strip()
        module.description = ent['entPhysicalDescr'].strip()
        module.name = ent['entPhysicalName'].strip()
        if module.name.strip().isdigit():
            module.module_number = int(module.name.strip())
        module.parent = None
        return module

    def _process_modules(self, entities):
        # map entity indexes to module containers
        module_containers = {}
        modules = entities.get_modules()
        for ent in modules:
            entity_index = ent[0]
            device = self._device_from_entity(ent)
            module = self._module_from_entity(ent)
            module.device = device

            module_containers[entity_index] = module
            self._logger.debug("module (entPhysIndex=%s): %r", entity_index,
                               module)

        return module_containers

    def _process_ports(self, entities, module_containers):
        ports = entities.get_ports()
        netbox = self.containers.factory(None, shadows.Netbox)

        # Map interfaces to modules, if possible
        module_ifindex_map = {}  # just for logging debug info
        for port in ports:
            entity_index = port[0]
            if entity_index in self.alias_mapping:
                module_entity = entities.get_nearest_module_parent(port)

                if module_entity and module_entity[0] in module_containers:
                    module = module_containers[module_entity[0]]
                    indices = self.alias_mapping[entity_index]
                    for ifindex in indices:
                        interface = self.containers.factory(
                            ifindex, shadows.Interface)
                        interface.netbox = netbox
                        interface.ifindex = ifindex
                        interface.module = module

                        if module.name in module_ifindex_map:
                            module_ifindex_map[module.name].append(ifindex)
                        else:
                            module_ifindex_map[module.name] = [ifindex]

        if module_ifindex_map:
            self._logger.debug("module/ifindex mapping: %r",
                               module_ifindex_map)

    def _process_entities(self, result):
        """Process the list of collected entities."""
        # be able to look up all entities using entPhysicalIndex
        entities = EntityTable(result)

        module_containers = self._process_modules(entities)
        self._process_ports(entities, module_containers)