get_chassis_id.py 3.77 KB
Newer Older
1
2
3
# ---------------------------------------------------------------------
# Generic.get_chassis_id
# ---------------------------------------------------------------------
4
# Copyright (C) 2007-2020 The NOC Project
5
6
7
# See LICENSE for details
# ---------------------------------------------------------------------

8
# Python modules
9
10
from typing import Dict, List

11
12
# NOC modules
from noc.core.script.base import BaseScript
13
from noc.core.snmp.error import SNMPError
14
15
from noc.sa.interfaces.igetchassisid import IGetChassisID
from noc.core.mac import MAC
16
from noc.core.mib import mib
17
from noc.core.snmp.render import render_mac
18
19
20
21
22
23


class Script(BaseScript):
    name = "Generic.get_chassis_id"
    cache = True
    interface = IGetChassisID
24
25
    # OIDS to get MACs via SNMP GET
    # capability -> [oid, ...]
26
    SNMP_GET_OIDS: Dict[str, List[str]] = {
Dmitry Volodin's avatar
Dmitry Volodin committed
27
        "SNMP": [mib["BRIDGE-MIB::dot1dBaseBridgeAddress", 0], mib["LLDP-MIB::lldpLocChassisId", 0]]
28
29
30
    }
    # OIDS to get MACs via SNMP GETNEXT request
    # capability -> [oid, ...]
31
    SNMP_GETNEXT_OIDS: Dict[str, List[str]] = {}
32
33
34
    #
    IGNORED_MACS = {
        "00:00:00:00:00:00",  # Empty MAC
35
        "00:01:02:03:04:00",  # Very Smart programmer
36
        "00:01:02:03:04:05",  # Very Smart+ programmer
37
        "00:02:03:04:05:06",  # Ubiquity Programmers
38
39
        "00:AA:BB:CC:DD:13",
        "06:00:00:00:00:80",
Dmitry Volodin's avatar
Dmitry Volodin committed
40
        "FF:FF:FF:FF:FF:FF",  # Broadcast
41
    }
42

43
44
    def snmp_safe(self, oids):
        r = {}
45
        for k, v in oids.items():
46
            try:
47
48
49
50
51
                r.update(
                    self.snmp.get(
                        {k: v}, display_hints={mib["LLDP-MIB::lldpLocChassisId", 0]: render_mac}
                    )
                )
52
53
54
55
            except SNMPError:
                continue
        return r

56
    def execute_snmp(self):
57
58
59
60
        macs = set()
        # Process SNMP GET
        oids = self.get_snmp_get_oids()
        if oids:
61
            r = self.snmp_safe(dict(zip(oids, oids)))
62
63
64
65
66
67
68
69
70
            for k in r:
                v = r[k]
                if v:
                    try:
                        macs.add(MAC(v))
                    except ValueError:
                        pass
        # Process SNMP GETNEXT requests
        oids = self.get_snmp_getnext_oids()
71
72
73
74
75
76
77
78
79
80
        try:
            for oid in oids:
                for k, v in self.snmp.getnext(oid):
                    if v:
                        try:
                            macs.add(MAC(v))
                        except ValueError:
                            pass
        except SNMPError:
            pass
81
        # Filter and convert macs
Dmitry Volodin's avatar
Dmitry Volodin committed
82
83
84
85
86
        r = [
            {"first_chassis_mac": mac, "last_chassis_mac": mac}
            for mac in sorted(macs)
            if not self.is_ignored_mac(mac)
        ]
87
88
89
        if not r:
            raise NotImplementedError
        return r
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

    def get_oids_by_caps(self, oids_map):
        """
        Process caps -> [oid, ...] mappings
        :param oids_map:
        :return:
        """
        oids = set()
        for cap in oids_map:
            if cap in self.capabilities:
                oids.update(oids_map[cap])
        return list(oids)

    def get_snmp_get_oids(self):
        """
        Get list of SNMP GET oids to request MAC addresses.
        Can be overriden
        :return:
        """
        return self.get_oids_by_caps(self.SNMP_GET_OIDS)

    def get_snmp_getnext_oids(self):
        """
        Get list of SNMP GET oids to request MAC addresses.
        Can be overriden
        :return:
        """
        return self.get_oids_by_caps(self.SNMP_GETNEXT_OIDS)

    def is_ignored_mac(self, mac):
        """
        Check if MAC address should be ignored
        :param mac: Normalized MAC address
        :return: True if MAC should be ignored
        """
125
        return mac in self.IGNORED_MACS or mac.is_multicast