def __init__(self, *args, **kwargs): super(ExtremeVlan, self).__init__(*args, **kwargs) self.extremevlan = ExtremeVlanMib(self.agent) self.bridge = BridgeMib(self.agent) self.baseport_ifindex = {}
class ExtremeVlan(Plugin): """Collects 802.1q info from EXTREME-VLAN-MIB and BRIDGE-MIB""" def __init__(self, *args, **kwargs): super(ExtremeVlan, self).__init__(*args, **kwargs) self.extremevlan = ExtremeVlanMib(self.agent) self.bridge = BridgeMib(self.agent) self.baseport_ifindex = {} @classmethod def can_handle(cls, netbox): daddy_says_ok = super(ExtremeVlan, cls).can_handle(netbox) if netbox.type: vendor_id = netbox.type.get_enterprise_id() if vendor_id != VENDORID_EXTREMENETWORKS: return False return daddy_says_ok def handle(self): self._logger.debug( "Collecting Extreme Networks proprietary 802.1q VLAN information") return self._get_vlan_data() @inlineCallbacks def _get_vlan_data(self): vlan_ports = yield self.extremevlan.get_vlan_ports() if not vlan_ports: # Doesn't appear to have VLAN data in EXTREME MIBs, get out now. returnValue(None) ifindex_vlan = yield self.extremevlan.get_ifindex_vlan_map() self.baseport_ifindex = yield self.bridge.get_baseport_ifindex_map() vlan_config = self._consolidate_vlan_config(vlan_ports, ifindex_vlan) self._store_access_ports(vlan_config) self._store_trunk_ports(vlan_config) def _consolidate_vlan_config(self, vlan_ports, ifindex_vlan): config = {} for vlan_ifindex, (tagged, untagged) in vlan_ports.items(): vlanid = ifindex_vlan.get(vlan_ifindex, None) if not vlanid: continue tagged_indexes = self._portnums_to_ifindexes(tagged) untagged_indexes = self._portnums_to_ifindexes(untagged) config[vlanid] = (tagged_indexes, untagged_indexes) return config def _portnums_to_ifindexes(self, portnums): return [self.baseport_ifindex[portnum] for portnum in portnums if portnum in self.baseport_ifindex] def _store_access_ports(self, vlan_config): """Store vlan memberships for all ports.""" for vlanid, (_tagged, untagged) in vlan_config.items(): for ifindex in untagged: interface = self.containers.factory(ifindex, shadows.Interface) interface.trunk = False interface.vlan = vlanid def _store_trunk_ports(self, vlan_config): """Store the set of enabled vlans for each trunk port.""" ifindex_vlans = {} for vlanid, (tagged, _untagged) in vlan_config.items(): for ifindex in tagged: if ifindex not in ifindex_vlans: ifindex_vlans[ifindex] = set() ifindex_vlans[ifindex].add(vlanid) for ifindex, vlans in ifindex_vlans.items(): interface = self.containers.factory(ifindex, shadows.Interface) interface.trunk = True interface.vlan = None allowed = self.containers.factory(ifindex, shadows.SwPortAllowedVlan) allowed.interface = interface allowed.hex_string = vlan_list_to_hex(vlans)
def __init__(self, *args, **kwargs): super(Dot1q, self).__init__(*args, **kwargs) self.bridgemib = BridgeMib(self.agent) self.qbridgemib = QBridgeMib(self.agent)
class Dot1q(Plugin): """Collect 802.1q info from BRIDGE and Q-BRIDGE MIBs.""" baseports = {} pvids = {} def __init__(self, *args, **kwargs): super(Dot1q, self).__init__(*args, **kwargs) self.bridgemib = BridgeMib(self.agent) self.qbridgemib = QBridgeMib(self.agent) def _remap_vlan(self, vlan_ident): """Hook-in for subclasses to remap VLAN numbers if necessary""" return vlan_ident @inlineCallbacks def handle(self): """Collects VLAN configuration using Q-BRIDGE-MIB. If no PVID information can be found in Q-BRIDGE, the plugin assumes the device either doesn't support Q-BRIDGE or doesn't support 802.1q and exits. """ self._logger.debug("Collecting 802.1q VLAN information") self.baseports = yield self.bridgemib.get_baseport_ifindex_map() self.pvids = yield self.qbridgemib.get_baseport_pvid_map() if self.pvids: self._process_pvids() else: return yield self._get_vlan_names() yield self._get_tagging_info() def _process_pvids(self): """Process the list of collected port/PVID mappings. If no PVID data was found, it is assumed that this bridge either does not support Q-BRIDGE-MIB or does not support 802.1q, and the plugin exits. """ self._logger.debug("PVID mapping: %r", self.pvids) for port, pvid in self.pvids.items(): self._set_port_pvid(port, pvid) def _set_port_pvid(self, port, pvid): if port in self.baseports: ifindex = self.baseports[port] interface = self.containers.factory(ifindex, shadows.Interface) interface.vlan = pvid interface.trunk = False # default all ports to non-tagging at first else: self._logger.debug("saw reference to non-existant baseport %s", port) @inlineCallbacks def _get_tagging_info(self): """Retrieves and processes information about VLAN egress ports and tagging. The set of untagged ports is subtracted from the total set of egress ports for each vlan, resulting in a set of ports that transmit and receive tagged frames for this vlan (i.e. trunk ports). """ egress, untagged = yield self._retrieve_vlan_ports() trunkports = self._find_trunkports(egress, untagged) self._logger.debug("trunkports: %r", trunkports) self._store_trunkports(trunkports) @inlineCallbacks def _retrieve_vlan_ports(self): query = self.qbridgemib egress = yield query.get_vlan_current_egress_ports() untagged = yield query.get_vlan_current_untagged_ports() if not egress and not untagged: egress = yield query.get_vlan_static_egress_ports() untagged = yield query.get_vlan_static_untagged_ports() returnValue((egress, untagged)) def _find_trunkports(self, egress, untagged): trunkports = defaultdict(list) for vlan, (egress, untagged) in mergedicts(egress, untagged).items(): try: tagged = egress - untagged except ValueError: self._logger.error( "vlan %s subtraction mismatch between " "EgressPorts and UntaggedPorts", vlan) else: for port in tagged: trunkports[port].append(vlan) finally: self._logger.debug("vlan: %s egress: %r untagged: %r", vlan, egress, untagged) return trunkports def _store_trunkports(self, trunkports): for port, vlans in trunkports.items(): self._set_trunkport(port, vlans) def _set_trunkport(self, port, vlans): if port not in self.baseports: self._logger.debug("saw reference to non-existant baseport %s", port) return # Mark as trunk ifindex = self.baseports[port] interface = self.containers.factory(ifindex, shadows.Interface) interface.trunk = True # Store a hex string representation of enabled VLANs # in swportallowedvlan allowed = self.containers.factory(ifindex, shadows.SwPortAllowedVlan) allowed.interface = interface allowed.hex_string = vlan_list_to_hex(vlans) @inlineCallbacks def _get_vlan_names(self): names = yield self.qbridgemib.get_vlan_static_names() if names: for vlannum, name in names.items(): vlannum = self._remap_vlan(vlannum) suffix = '+{}'.format(vlannum) if name.endswith(suffix): name = name[:-len(suffix)] vlan = self.containers.factory(name, shadows.Vlan) vlan.net_type = shadows.NetType.get('lan') vlan.vlan = vlannum vlan.net_ident = name vlan.netbox = self.netbox self._logger.debug("Found vlan {}: {}".format(vlannum, name))
class Dot1q(Plugin): """Collect 802.1q info from BRIDGE and Q-BRIDGE MIBs.""" baseports = {} pvids = {} def __init__(self, *args, **kwargs): super(Dot1q, self).__init__(*args, **kwargs) self.bridgemib = BridgeMib(self.agent) self.qbridgemib = QBridgeMib(self.agent) @inlineCallbacks def handle(self): """Collects VLAN configuration using Q-BRIDGE-MIB. If no PVID information can be found in Q-BRIDGE, the plugin assumes the device either doesn't support Q-BRIDGE or doesn't support 802.1q and exits. """ self._logger.debug("Collecting 802.1q VLAN information") self.baseports = yield self.bridgemib.get_baseport_ifindex_map() self.pvids = yield self.qbridgemib.get_baseport_pvid_map() if self.pvids: self._process_pvids() else: return yield self._get_tagging_info() def _process_pvids(self): """Process the list of collected port/PVID mappings. If no PVID data was found, it is assumed that this bridge either does not support Q-BRIDGE-MIB or does not support 802.1q, and the plugin exits. """ self._logger.debug("PVID mapping: %r", self.pvids) for port, pvid in self.pvids.items(): self._set_port_pvid(port, pvid) def _set_port_pvid(self, port, pvid): if port in self.baseports: ifindex = self.baseports[port] interface = self.containers.factory(ifindex, shadows.Interface) interface.vlan = pvid else: self._logger.debug("saw reference to non-existant baseport %s", port) @inlineCallbacks def _get_tagging_info(self): """Retrieves and processes information about VLAN egress ports and tagging. The set of untagged ports is subtracted from the total set of egress ports for each vlan, resulting in a set of ports that transmit and receive tagged frames for this vlan (i.e. trunk ports). """ egress, untagged = yield self._retrieve_vlan_ports() trunkports = self._find_trunkports(egress, untagged) self._logger.debug("trunkports: %r", trunkports) self._store_trunkports(trunkports) @inlineCallbacks def _retrieve_vlan_ports(self): query = self.qbridgemib egress = yield query.get_vlan_current_egress_ports() untagged = yield query.get_vlan_current_untagged_ports() if not egress or not untagged: egress = yield query.get_vlan_static_egress_ports() untagged = yield query.get_vlan_static_untagged_ports() returnValue((egress, untagged)) def _find_trunkports(self, egress, untagged): trunkports = {} for vlan, (egress, untagged) in mergedicts(egress, untagged).items(): try: tagged = egress - untagged except ValueError: self._logger.error("vlan %s subtraction mismatch between " "EgressPorts and UntaggedPorts", vlan) else: for port in tagged.get_ports(): if port not in trunkports: trunkports[port] = [vlan] else: trunkports[port].append(vlan) finally: self._logger.debug("vlan: %s egress: %r untagged: %r", vlan, egress.get_ports(), untagged.get_ports()) return trunkports def _store_trunkports(self, trunkports): for port, vlans in trunkports.items(): self._set_trunkport(port, vlans) def _set_trunkport(self, port, vlans): if port not in self.baseports: self._logger.debug("saw reference to non-existant baseport %s", port) return # Mark as trunk ifindex = self.baseports[port] interface = self.containers.factory(ifindex, shadows.Interface) interface.trunk = True # Store a hex string representation of enabled VLANs # in swportallowedvlan allowed = self.containers.factory(ifindex, shadows.SwPortAllowedVlan) allowed.interface = interface allowed.hex_string = vlan_list_to_hex(vlans)