def collect_routes(self): """ Collects the routing table, filters out what we consider to be static routes worthy of storage in NAV, and ensure storage as prefixes. """ mib = IpForwardMib(self.agent) ifmib = IfMib(self.agent) routes = yield mib.get_decoded_routes(protocols=WANTED_PROTOCOLS) filtered = [r for r in routes if self.is_wanted_route(r)] self._logger.debug( "%d of %d collected routes are static candidates", len(filtered), len(routes), ) self._logger.debug( "collected destinations: %r", [r.destination for r in filtered] ) for route in filtered: ifindex = yield mib.get_cidr_route_column('IfIndex', route.index) alias = None if ifindex: alias = yield ifmib.retrieve_column_by_index('ifAlias', (ifindex,)) self.route_to_containers(route, descr=alias) Prefix.add_static_routes_sentinel(self.containers)
def _make_interface_lookup_dict(self): ifmib = IfMib(self.agent_proxy) ifnames = yield ifmib.get_ifnames() lookup = {} for ifindex, (ifname, ifdescr) in ifnames.items(): lookup[ifdescr] = ifindex lookup[ifname] = ifindex returnValue(lookup)
def handle(self): if self.netbox.master: self._logger.debug("this is a virtual instance of %s, not polling", self.netbox.master) returnValue(None) ifmib = IfMib(self.agent) result = yield ifmib.retrieve_columns( ['ifName', 'ifAdminStatus', 'ifOperStatus']).addCallback(reduce_index) self._put_results(result)
def _get_stats(self): ifmib = IfMib(self.agent) ipmib = IpMib(self.agent) stats = yield ifmib.retrieve_columns( ("ifName", "ifDescr") + USED_COUNTERS).addCallback(reduce_index) ipv6stats = yield ipmib.get_ipv6_octet_counters() if ipv6stats: self._logger.debug("found ipv6 octet counters for %d interfaces", len(ipv6stats)) for ifindex, (in_octets, out_octets) in ipv6stats.items(): if ifindex in stats: stats[ifindex][IF_IN_OCTETS_IPV6] = in_octets stats[ifindex][IF_OUT_OCTETS_IPV6] = out_octets defer.returnValue(stats)
class LinkAggregate(Plugin): """Collects information about link aggregation""" def __init__(self, *args, **kwargs): super(LinkAggregate, self).__init__(*args, **kwargs) self.ifmib = IfMib(self.agent) self.lagmib = IEEE8023LagMib(self.agent) @inlineCallbacks def handle(self): self._logger.debug("Collecting link aggregations") result = yield self.lagmib.retrieve_aggregations_by_operational_key() aggregates = yield self._convert_to_interfaces(result) self._log_aggregates(aggregates) self._create_aggregate_containers(aggregates) @inlineCallbacks def _convert_to_interfaces(self, aggregatedict): result = [] for aggregator_idx, aggregates in aggregatedict.items(): aggregator = yield self._get_interface(aggregator_idx) for if_idx in aggregates: interface = yield self._get_interface(if_idx) result.append((interface, aggregator)) returnValue(result) @inlineCallbacks def _get_interface(self, ifindex): ifc = self.containers.factory(ifindex, shadows.Interface, ifindex=ifindex) if not ifc.ifname: # In case no other plugins ran before us to collect this: self._logger.debug("retrieving ifName.%s", ifindex) ifc.ifname = yield self.ifmib.retrieve_column_by_index( 'ifName', (ifindex, )) returnValue(ifc) def _log_aggregates(self, aggregates): self._logger.debug("%r", aggregates) if not self._logger.isEnabledFor(logging.DEBUG): return aggr = defaultdict(list) for ifc, aggregator in aggregates: aggr[aggregator.ifname].append(ifc.ifname) for aggregator, ports in aggr.items(): self._logger.debug("%s aggregates these ports: %s", aggregator, ', '.join(ports)) def _create_aggregate_containers(self, aggregates): for interface, aggregator in aggregates: key = aggregator.ifindex, interface.ifindex aggregate = self.containers.factory(key, shadows.InterfaceAggregate) aggregate.aggregator = aggregator aggregate.interface = interface
def get_vlan_interfaces(self): """Get all virtual VLAN interfaces. Any interface whose ifName matches the VLAN_PATTERN regexp will be included in the result. Return value: A deferred whose result is a dictionary: { ifindex: vlan } """ ifmib = IfMib(self.agent) df = ifmib.retrieve_column('ifName') df.addCallback(reduce_index) interfaces = yield df vlan_ifs = {} for ifindex, ifname in interfaces.items(): match = VLAN_PATTERN.match(ifname) if match: vlan = int(match.group('vlan')) vlan_ifs[ifindex] = vlan defer.returnValue(vlan_ifs)
class LinkState(Plugin): def handle(self): self.ifmib = IfMib(self.agent) df = self.ifmib.retrieve_columns(['ifName', 'ifOperStatus']) df.addCallback(reduce_index) return df.addCallback(self._put_results) def _put_results(self, results): netbox = self.containers.factory(None, shadows.Netbox) for index, row in results.items(): self._update_interface(netbox, index, row) def _update_interface(self, netbox, ifindex, row): ifc = self.containers.factory(ifindex, shadows.Interface) ifc.netbox = netbox ifc.ifindex = ifindex if row['ifName']: ifc.ifname = row['ifName'] ifc.ifoperstatus = row['ifOperStatus']
def handle(self): self.ifmib = IfMib(self.agent) df = self.ifmib.retrieve_columns(['ifName', 'ifOperStatus']) df.addCallback(reduce_index) return df.addCallback(self._put_results)
def _get_ifindexes(self): ifmib = IfMib(self.agent) indexes = yield ifmib.get_ifindexes() defer.returnValue(set(indexes))
def __init__(self, *args, **kwargs): super(LinkAggregate, self).__init__(*args, **kwargs) self.ifmib = IfMib(self.agent) self.lagmib = IEEE8023LagMib(self.agent)
def _get_adminup_ifcs(self): ifmib = IfMib(self.agent) statuses = yield ifmib.get_admin_status() result = set(ifindex for ifindex, status in statuses.items() if status == 'up') defer.returnValue(result)
def _get_ifc_aliases(self): return IfMib(self.agent).get_ifaliases()
def __init__(self, *args, **kwargs): super(Interfaces, self).__init__(*args, **kwargs) self.ifmib = IfMib(self.agent) self.etherlikemib = EtherLikeMib(self.agent)
class Interfaces(Plugin): "Collects comprehensive information about device's network interfaces" def __init__(self, *args, **kwargs): super(Interfaces, self).__init__(*args, **kwargs) self.ifmib = IfMib(self.agent) self.etherlikemib = EtherLikeMib(self.agent) @defer.inlineCallbacks def handle(self): self._logger.debug("Collecting interface data") df = self._get_iftable_columns() df.addCallback(self._retrieve_duplex) df.addCallback(self._process_interfaces) df.addCallback(self._get_stack_status) yield df shadows.Interface.add_sentinel(self.containers) def _get_iftable_columns(self): df = self.ifmib.retrieve_columns( [ 'ifDescr', 'ifType', 'ifSpeed', 'ifPhysAddress', 'ifAdminStatus', 'ifOperStatus', 'ifName', 'ifHighSpeed', 'ifConnectorPresent', 'ifAlias', ] ) return df.addCallback(reduce_index) def _process_interfaces(self, result): """Process the list of collected interfaces.""" self._logger.debug("Found %d interfaces", len(result)) # Now save stuff to containers and pass the list of containers # to the next callback netbox = self.containers.factory(None, shadows.Netbox) interfaces = [ self._convert_row_to_container(netbox, ifindex, row) for ifindex, row in result.items() if isinstance(ifindex, int) ] return interfaces def _convert_row_to_container(self, netbox, ifindex, row): """Convert a collected ifTable/ifXTable row into a container object.""" interface = self.containers.factory(ifindex, shadows.Interface) interface.ifindex = ifindex interface.ifdescr = row['ifDescr'] interface.iftype = row['ifType'] speed = self._extract_interface_speed( row["ifSpeed"], row["ifHighSpeed"], always_use_highspeed=self.config.getboolean( "interfaces", "always_use_ifhighspeed" ), ) if speed is not None: interface.speed = speed interface.ifphysaddress = typesafe_binary_mac_to_hex(row['ifPhysAddress']) interface.ifadminstatus = row['ifAdminStatus'] interface.ifoperstatus = row['ifOperStatus'] interface.ifname = row['ifName'] or interface.baseport or row['ifDescr'] interface.ifconnectorpresent = row['ifConnectorPresent'] == 1 interface.ifalias = safestring(row['ifAlias']) # Set duplex if sucessfully retrieved if 'duplex' in row and row['duplex'] in DUPLEX_MAP: interface.duplex = DUPLEX_MAP[row['duplex']] interface.gone_since = None interface.netbox = netbox return interface @staticmethod def _extract_interface_speed(speed, highspeed, always_use_highspeed=False): """Determines the interface speed from a combination of ifSpeed and ifHighSpeed values. The IF-MIB spec says to use the ifHighSpeed value if the 32-bit unsigned ifSpeed value is maxed out. However, some devices, like Cisco SG350X-24T running 2.5.5.47 firmware, have an incorrect implementation that causes ifSpeed=ifHighSpeed. Yet other buggy implementations even have no discernable correlation between the two values, and only their ifHighSpeed value can be trusted. """ if always_use_highspeed and isinstance(highspeed, int): return float(highspeed) if isinstance(speed, int): if 4294967295 > speed != highspeed: return speed / 1000000.0 elif isinstance(highspeed, int): return float(highspeed) @defer.inlineCallbacks def _get_stack_status(self, interfaces): """Retrieves data from the ifStackTable and initiates a search for a proper ifAlias value for those interfaces that lack it. """ def _stackify(stackstatus): ifindex_map = dict((ifc.ifindex, ifc) for ifc in interfaces) stack = [ (ifindex_map[higher], ifindex_map[lower]) for higher, lower in stackstatus if higher in ifindex_map and lower in ifindex_map ] return stack stack = yield self.ifmib.get_stack_status().addCallback(_stackify) self._get_ifalias_from_lower_layers(stack) self._create_stack_containers(stack) defer.returnValue(interfaces) def _get_ifalias_from_lower_layers(self, stack): """For each interface without an ifAlias value, attempts to find ifAlias from a lower layer interface. By popular convention, some devices are configured with virtual router ports that are conceptually a layer above the physical interface. The virtual port may have no ifAlias value, but the physical interface may have. We want an ifAlias value, since it tells us the netident of the router port's network. """ for higher, lower in stack: if not higher.ifalias and lower.ifalias: higher.ifalias = lower.ifalias self._logger.debug( "%s alias set from lower layer %s: %s", higher.ifname, lower.ifname, higher.ifalias, ) def _create_stack_containers(self, stacklist): for higher, lower in stacklist: key = higher.ifindex, lower.ifindex stack = self.containers.factory(key, shadows.InterfaceStack) stack.higher = higher stack.lower = lower def _retrieve_duplex(self, interfaces): """Get duplex from EtherLike-MIB and update the ifTable results.""" def update_result(duplexes): self._logger.debug("Got duplex information: %r", duplexes) for index, duplex in duplexes.items(): if index in interfaces: interfaces[index]['duplex'] = duplex return interfaces deferred = self.etherlikemib.get_duplex() deferred.addCallback(update_result) return deferred