Beispiel #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
Beispiel #2
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 = get_portnamemap(conn)
    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][0] != 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][0])
                })
                _nodesbymac[mac] = (None, None)
            else:
                _nodesbymac[mac] = (nodename, maccounts[ifname])
Beispiel #3
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())