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
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)
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)