def handle(self): if self.netbox.master: self._logger.debug("this is a virtual instance of %s, not polling", self.netbox.master) returnValue(None) poemib = PowerEthernetMib(self.agent) if self.netbox.type and self.netbox.type.vendor.id == 'cisco': cisco_mib = CiscoPowerEthernetExtMib(self.agent) port_phy_index = yield cisco_mib.retrieve_column( "cpeExtPsePortEntPhyIndex") group_phy_index = yield cisco_mib.retrieve_column( "cpeExtMainPseEntPhyIndex") entity_mib = EntityMib(self.agent) alias_mapping = yield entity_mib.get_alias_mapping() port_ifindices = self._resolve_ifindex(port_phy_index, alias_mapping) else: port_ifindices = {} group_phy_index = {} groups = yield poemib.get_groups_table() self._process_groups(groups, group_phy_index) ports = yield poemib.get_ports_table() self._process_ports(ports, port_ifindices) self._log_invalid_portgroups()
def _map_cisco_power_ports_to_ifindex(self): """Uses the Cisco proprietary CISCO-POWER-ETHERNET-EXT-MIB to map the group/port index pairs used exclusively in PORT-ETHERNET-MIB to an actual ifIndex, that most other MIBs (and NAV's Interface model) uses for identification of interfaces/ports. POWER-ETHERNET-MIB provides only a very vague identification of power-enabled ports. These identifiers are not universally and consistently mappable to an ifIndex, for example. A more conclusive mapping to interfaces may be provided on a vendor-by-vendor basis. The only supported vendor for mapping in this codebase so far is Cisco. Cisco's mapping is indirect via the ENTITY-MIB - each entry from the power ethernet tables is mapped to a physical port in ENTITY-MIB::entPhysicalTable via its entPhysicalIndex. This table, in turn, can map physical ports to interface indexes from the IF-MIB::ifTable. """ cisco_mib = CiscoPowerEthernetExtMib(self.agent) port_phy_index = yield cisco_mib.retrieve_column("cpeExtPsePortEntPhyIndex") group_phy_index = yield cisco_mib.retrieve_column("cpeExtMainPseEntPhyIndex") entity_mib = EntityMib(self.agent) alias_mapping = yield entity_mib.get_alias_mapping() port_ifindices = self._resolve_ifindex(port_phy_index, alias_mapping) returnValue((group_phy_index, port_ifindices))
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)