Example #1
0
def _snmp_map_switch(switch, password, user):
    haveqbridge = False
    mactobridge = {}
    conn = snmp.Session(switch, password, user)
    ifnamemap = get_portnamemap(conn)
    for vb in conn.walk('1.3.6.1.2.1.17.7.1.2.2.1.2'):
        haveqbridge = True
        oid, bridgeport = vb
        if not bridgeport:
            continue
        oid = str(oid).rsplit('.', 6)
        # if 7, then oid[1] would be vlan id
        macaddr = '{0:02x}:{1:02x}:{2:02x}:{3:02x}:{4:02x}:{5:02x}'.format(
            *([int(x) for x in oid[-6:]]))
        mactobridge[macaddr] = int(bridgeport)
    if not haveqbridge:
        for vb in conn.walk('1.3.6.1.2.1.17.4.3.1.2'):
            oid, bridgeport = vb
            if not bridgeport:
                continue
            oid = str(oid).rsplit('.', 6)
            macaddr = '{0:02x}:{1:02x}:{2:02x}:{3:02x}:{4:02x}:{5:02x}'.format(
                *([int(x) for x in oid[-6:]]))
            mactobridge[macaddr] = int(bridgeport)
    vlanstocheck = set([])
    try:
        #ciscoiftovlanmap = {}
        for vb in conn.walk('.1.3.6.1.4.1.9.9.68.1.2.2.1.2'):
            vlanstocheck.add(vb[1])
        #ciscotrunktovlanmap = {}
        for vb in conn.walk('.1.3.6.1.4.1.9.9.46.1.6.1.1.5'):
            vlanstocheck.add(vb[1])
    except Exception:
        # We might have crashed snmp on a non-cisco switch
        # in such a case, delay 8 seconds to allow recovery to complete
        eventlet.sleep(8)
    if not vlanstocheck:
        vlanstocheck.add(None)
    bridgetoifmap = {}
    for vlan in vlanstocheck:
        if vlan:
            if user:
                conn = snmp.Session(switch, password, user,
                                    'vlan-{}'.format(vlan))
            else:
                if not isinstance(password, str):
                    password = password.decode('utf8')
                conn = snmp.Session(switch, '{}@{}'.format(password, vlan))
        for vb in conn.walk('1.3.6.1.2.1.17.1.4.1.2'):
            bridgeport, ifidx = vb
            bridgeport = int(str(bridgeport).rsplit('.', 1)[1])
            try:
                bridgetoifmap[bridgeport] = int(ifidx)
            except ValueError:
                # ifidx might be '', skip in such a case
                continue
    #OFFLOAD: end of need to offload?
    return mactobridge, ifnamemap, bridgetoifmap
Example #2
0
def _extract_neighbor_data_b(args):
    """Build LLDP data about elements connected to switch

    args are carried as a tuple, because of eventlet convenience
    """
    switch, password, user = args
    conn = snmp.Session(switch, password, user)
    sid = None
    lldpdata = {}
    for sysid in conn.walk('1.3.6.1.2.1.1.2'):
        sid = str(sysid[1][6:])
    idxtoifname = {}
    for oidindex in conn.walk('1.0.8802.1.1.2.1.3.7.1.4'):
        idx = oidindex[0][-1]
        idxtoifname[idx] = _lldpdesc_to_ifname(sid, idx, str(oidindex[1]))
    for remotedesc in conn.walk('1.0.8802.1.1.2.1.4.1.1.10'):
        iname = idxtoifname[remotedesc[0][-2]]
        lldpdata[iname] = {'description': str(remotedesc[1])}
    for remotename in conn.walk('1.0.8802.1.1.2.1.4.1.1.9'):
        iname = idxtoifname[remotename[0][-2]]
        if iname not in lldpdata:
            lldpdata[iname] = {}
        lldpdata[iname]['name'] = str(remotename[1])
    for remoteid in conn.walk('1.0.8802.1.1.2.1.4.1.1.5'):
        iname = idxtoifname[remoteid[0][-2]]
        if iname not in lldpdata:
            lldpdata[iname] = {}
        lldpdata[iname]['chassisid'] = str(remoteid[1])
    print(repr(lldpdata))
Example #3
0
def _extract_neighbor_data_b(args):
    """Build LLDP data about elements connected to switch

    args are carried as a tuple, because of eventlet convenience
    """
    switch, password, user, cfm, force = args[:5]
    vintage = _neighdata.get(switch, {}).get('!!vintage', 0)
    now = util.monotonic_time()
    if vintage > (now - 60) and not force:
        return
    lldpdata = {'!!vintage': now}
    try:
        return _extract_neighbor_data_affluent(switch, user, password, cfm,
                                               lldpdata)
    except Exception:
        pass
    conn = snmp.Session(switch, password, user)
    sid = None
    for sysid in conn.walk('1.3.6.1.2.1.1.2'):
        sid = str(sysid[1][6:])
    _noaffluent.add(switch)
    idxtoifname = {}
    idxtoportid = {}
    _chassisidbyswitch[switch] = sanitize(
        list(conn.walk('1.0.8802.1.1.2.1.3.2'))[0][1])
    for oidindex in conn.walk('1.0.8802.1.1.2.1.3.7.1.3'):
        idx = oidindex[0][-1]
        idxtoportid[idx] = sanitize(oidindex[1])
    for oidindex in conn.walk('1.0.8802.1.1.2.1.3.7.1.4'):
        idx = oidindex[0][-1]
        idxtoifname[idx] = _lldpdesc_to_ifname(sid, idx, str(oidindex[1]))
    for remotedesc in conn.walk('1.0.8802.1.1.2.1.4.1.1.10'):
        iname = idxtoifname[remotedesc[0][-2]]
        _init_lldp(lldpdata, iname, remotedesc[0][-2], idxtoportid, switch)
        _extract_extended_desc(lldpdata[iname], remotedesc[1], user)
    for remotename in conn.walk('1.0.8802.1.1.2.1.4.1.1.9'):
        iname = idxtoifname[remotename[0][-2]]
        _init_lldp(lldpdata, iname, remotename[0][-2], idxtoportid, switch)
        lldpdata[iname]['peername'] = str(remotename[1])
    for remotename in conn.walk('1.0.8802.1.1.2.1.4.1.1.7'):
        iname = idxtoifname[remotename[0][-2]]
        _init_lldp(lldpdata, iname, remotename[0][-2], idxtoportid, switch)
        lldpdata[iname]['peerportid'] = sanitize(remotename[1])
    for remoteid in conn.walk('1.0.8802.1.1.2.1.4.1.1.5'):
        iname = idxtoifname[remoteid[0][-2]]
        _init_lldp(lldpdata, iname, remoteid[0][-2], idxtoportid, switch)
        lldpdata[iname]['peerchassisid'] = sanitize(remoteid[1])
    for entry in lldpdata:
        if entry == '!!vintage':
            continue
        entry = lldpdata[entry]
        entry['switch'] = switch
        peerid = '{0}.{1}'.format(
            entry.get('peerchassisid', '').replace(':', '-').replace('/', '-'),
            entry.get('peerportid', '').replace(':', '-').replace('/', '-'))
        entry['peerid'] = peerid
        _neighbypeerid[peerid] = entry
    _neighdata[switch] = lldpdata
Example #4
0
def _map_switch_backend(args):
    """Manipulate portions of mac address map relevant to a given switch
    """

    # 1.3.6.1.2.1.17.7.1.2.2.1.2 - mactoindex (qbridge - preferred)
    #  if not, check for cisco and if cisco, build list of all relevant vlans:
    #  .1.3.6.1.4.1.9.9.46.1.6.1.1.5 - trunk port vlan map (cisco only)
    #  .1.3.6.1.4.1.9.9.68.1.2.2.1.2 - access port vlan map (cisco only)
    # if cisco, vlan community string indexed or snmpv3 contest for:
    # 1.3.6.1.2.1.17.4.3.1.2 - mactoindx (bridge - low-end switches and cisco)
    #     .1.3.6.1.2.1.17.1.4.1.2 - bridge index to if index map
    # no vlan index or context for:
    #  .1.3.6.1.2.1.31.1.1.1.1 - ifName... but some switches don't do it
    #  .1.3.6.1.2.1.2.2.1.2 - ifDescr, usually useless, but a
    #   fallback if ifName is empty
    #
    global _macmap
    if len(args) == 3:
        switch, password, user = args
        if not user:
            user = None
    else:
        switch, password = args
        user = None
    haveqbridge = False
    mactobridge = {}
    conn = snmp.Session(switch, password, user)
    for vb in conn.walk('1.3.6.1.2.1.17.7.1.2.2.1.2'):
        haveqbridge = True
        oid, bridgeport = vb
        if not bridgeport:
            continue
        oid = str(oid).rsplit('.', 6)  # if 7, then oid[1] would be vlan id
        macaddr = '{0:02x}:{1:02x}:{2:02x}:{3:02x}:{4:02x}:{5:02x}'.format(
            *([int(x) for x in oid[-6:]]))
        mactobridge[macaddr] = int(bridgeport)
    if not haveqbridge:
        for vb in conn.walk('1.3.6.1.2.1.17.4.3.1.2'):
            oid, bridgeport = vb
            if not bridgeport:
                continue
            oid = str(oid).rsplit('.', 6)
            macaddr = '{0:02x}:{1:02x}:{2:02x}:{3:02x}:{4:02x}:{5:02x}'.format(
                *([int(x) for x in oid[-6:]]))
            mactobridge[macaddr] = int(bridgeport)
    bridgetoifmap = {}
    for vb in conn.walk('1.3.6.1.2.1.17.1.4.1.2'):
        bridgeport, ifidx = vb
        bridgeport = int(str(bridgeport).rsplit('.', 1)[1])
        try:
            bridgetoifmap[bridgeport] = int(ifidx)
        except ValueError:
            # ifidx might be '', skip in such a case
            continue
    ifnamemap = {}
    havenames = False
    for vb in conn.walk('1.3.6.1.2.1.31.1.1.1.1'):
        ifidx, ifname = vb
        if not ifname:
            continue
        havenames = True
        ifidx = int(str(ifidx).rsplit('.', 1)[1])
        ifnamemap[ifidx] = str(ifname)
    if not havenames:
        for vb in conn.walk('1.3.6.1.2.1.2.2.1.2'):
            ifidx, ifname = vb
            ifidx = int(str(ifidx).rsplit('.', 1)[1])
            ifnamemap[ifidx] = str(ifname)
    maccounts = {}
    bridgetoifvalid = False
    for mac in mactobridge:
        try:
            ifname = ifnamemap[bridgetoifmap[mactobridge[mac]]]
            bridgetoifvalid = True
        except KeyError:
            continue
        if ifname not in maccounts:
            maccounts[ifname] = 1
        else:
            maccounts[ifname] += 1
    if not bridgetoifvalid:
        bridgetoifmap = {}
        # Not a single mac address resolved to an interface index, chances are
        # that the switch is broken, and the mactobridge is reporting ifidx
        # instead of bridge port index
        # try again, skipping the bridgetoifmap lookup
        for mac in mactobridge:
            try:
                ifname = ifnamemap[mactobridge[mac]]
                bridgetoifmap[mactobridge[mac]] = mactobridge[mac]
            except KeyError:
                continue
            if ifname not in maccounts:
                maccounts[ifname] = 1
            else:
                maccounts[ifname] += 1
    _macsbyswitch[switch] = {}
    for mac in mactobridge:
        # We want to merge it so that when a mac appears in multiple
        # places, it is captured.
        try:
            ifname = ifnamemap[bridgetoifmap[mactobridge[mac]]]
        except KeyError:
            continue
        if mac in _macmap:
            _macmap[mac].append((switch, ifname, maccounts[ifname]))
        else:
            _macmap[mac] = [(switch, ifname, maccounts[ifname])]
        if ifname in _macsbyswitch[switch]:
            _macsbyswitch[switch][ifname].append(mac)
        else:
            _macsbyswitch[switch][ifname] = [mac]
        nodename = _nodelookup(switch, ifname)
        if nodename is not None:
            if mac in _nodesbymac and _nodesbymac[mac] != nodename:
                # For example, listed on both a real edge port
                # and by accident a trunk port
                log.log({
                    'error':
                    '{0} and {1} described by ambiguous'
                    ' switch topology values'.format(nodename,
                                                     _nodesbymac[mac])
                })
                _nodesbymac[mac] = None
            else:
                _nodesbymac[mac] = nodename
Example #5
0
def _list_interfaces(switchname, configmanager):
    switchcreds = get_switchcreds(configmanager, (switchname,))
    switchcreds = switchcreds[0]
    conn = snmp.Session(*switchcreds)
    ifnames = netutil.get_portnamemap(conn)
    return util.natural_sort(ifnames.values())
Example #6
0
def _map_switch_backend(args):
    """Manipulate portions of mac address map relevant to a given switch
    """

    # 1.3.6.1.2.1.17.7.1.2.2.1.2 - mactoindex (qbridge - preferred)
    #  if not, check for cisco and if cisco, build list of all relevant vlans:
    #  .1.3.6.1.4.1.9.9.46.1.6.1.1.5 - trunk port vlan map (cisco only)
    #  .1.3.6.1.4.1.9.9.68.1.2.2.1.2 - access port vlan map (cisco only)
    # if cisco, vlan community string indexed or snmpv3 contest for:
    # 1.3.6.1.2.1.17.4.3.1.2 - mactoindx (bridge - low-end switches and cisco)
    #     .1.3.6.1.2.1.17.1.4.1.2 - bridge index to if index map
    # no vlan index or context for:
    #  .1.3.6.1.2.1.31.1.1.1.1 - ifName... but some switches don't do it
    #  .1.3.6.1.2.1.2.2.1.2 - ifDescr, usually useless, but a
    #   fallback if ifName is empty
    #
    global _macmap
    switch, password, user = args
    haveqbridge = False
    mactobridge = {}
    conn = snmp.Session(switch, password, user)
    for vb in conn.walk('1.3.6.1.2.1.17.7.1.2.2.1.2'):
        haveqbridge = True
        oid, bridgeport = vb
        if not bridgeport:
            continue
        oid = str(oid).rsplit('.', 6)  # if 7, then oid[1] would be vlan id
        macaddr = '{0:02x}:{1:02x}:{2:02x}:{3:02x}:{4:02x}:{5:02x}'.format(
            *([int(x) for x in oid[-6:]]))
        mactobridge[macaddr] = int(bridgeport)
    if not haveqbridge:
        raise exc.NotImplementedException('TODO: Bridge-MIB without QBRIDGE')
    bridgetoifmap = {}
    for vb in conn.walk('1.3.6.1.2.1.17.1.4.1.2'):
        bridgeport, ifidx = vb
        bridgeport = int(str(bridgeport).rsplit('.', 1)[1])
        bridgetoifmap[bridgeport] = int(ifidx)
    ifnamemap = {}
    havenames = False
    for vb in conn.walk('1.3.6.1.2.1.31.1.1.1.1'):
        ifidx, ifname = vb
        if not ifname:
            continue
        havenames = True
        ifidx = int(str(ifidx).rsplit('.', 1)[1])
        ifnamemap[ifidx] = str(ifname)
    if not havenames:
        for vb in conn.walk('1.3.6.1.2.1.2.2.1.2'):
            ifidx, ifname = vb
            ifidx = int(str(ifidx).rsplit('.', 1)[1])
            ifnamemap[ifidx] = str(ifname)
    maccounts = {}
    for mac in mactobridge:
        ifname = ifnamemap[bridgetoifmap[mactobridge[mac]]]
        if ifname not in maccounts:
            maccounts[ifname] = 1
        else:
            maccounts[ifname] += 1
    _macsbyswitch[switch] = {}
    for mac in mactobridge:
        # We want to merge it so that when a mac appears in multiple
        # places, it is captured.
        ifname = ifnamemap[bridgetoifmap[mactobridge[mac]]]
        if mac in _macmap:
            _macmap[mac].append((switch, ifname, maccounts[ifname]))
        else:
            _macmap[mac] = [(switch, ifname, maccounts[ifname])]
        if ifname in _macsbyswitch[switch]:
            _macsbyswitch[switch][ifname].append(mac)
        else:
            _macsbyswitch[switch][ifname] = [mac]
        nodename = _nodelookup(switch, ifname)
        if nodename is not None:
            if mac in _nodesbymac and _nodesbymac[mac] != nodename:
                log.log({
                    'warning':
                    '{0} and {1} described by ambiguous'
                    ' switch topology values'.format(nodename,
                                                     _nodesbymac[mac])
                })
            _nodesbymac[mac] = nodename