profile.py 5.69 KB
Newer Older
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
1
2
3
4
# ---------------------------------------------------------------------
# Vendor: Eltex
# OS:     MES
# ---------------------------------------------------------------------
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
5
# Copyright (C) 2007-2021 The NOC Project
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
6
7
# See LICENSE for details
# ---------------------------------------------------------------------
Dmitry Volodin's avatar
Dmitry Volodin committed
8

MaksimSmile13's avatar
MaksimSmile13 committed
9
10
# Python modules
import re
Dmitry Volodin's avatar
Dmitry Volodin committed
11

Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
12
# NOC modules
Dmitry Volodin's avatar
Dmitry Volodin committed
13
from noc.core.profile.base import BaseProfile
MaksimSmile13's avatar
MaksimSmile13 committed
14
from noc.sa.interfaces.base import InterfaceTypeError
kk's avatar
kk committed
15
from noc.core.validators import is_int
16
from noc.core.snmp.render import render_mac
17

Dmitry Volodin's avatar
Dmitry Volodin committed
18

Dmitry Volodin's avatar
Dmitry Volodin committed
19
class Profile(BaseProfile):
Dmitry Volodin's avatar
Dmitry Volodin committed
20
    name = "Eltex.MES"
21

Dmitry Volodin's avatar
Dmitry Volodin committed
22
    pattern_more = [
23
24
25
26
27
28
29
        (rb"^More: <space>,  Quit: q, One line: <return>$", b" "),
        (rb"\[Yes/press any key for no\]", b"Y"),
        (rb"<return>, Quit: q or <ctrl>", b" "),
        (rb"q or <ctrl>+z", b" "),
        (rb"Overwrite file \[startup-config\].... \(Y\/N\)", b"Y"),
        (rb"Would you like to continue \? \(Y\/N\)\[N\]", b"Y"),
        (rb"Clear Logging File \? \(Y\/N\)\[N\]", b"Y"),
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
30
    ]
31
    pattern_unprivileged_prompt = rb"^(?P<hostname>\S+)>\s*"
Dmitry Volodin's avatar
Dmitry Volodin committed
32
    pattern_syntax_error = (
33
34
35
        rb"% (Unrecognized command|Incomplete command|"
        rb"Wrong number of parameters or invalid range, size or "
        rb"characters entered)"
Dmitry Volodin's avatar
Dmitry Volodin committed
36
    )
Dmitry Volodin's avatar
Dmitry Volodin committed
37
    command_disable_pager = "terminal datadump"
38
    command_super = b"enable"
Dmitry Volodin's avatar
Dmitry Volodin committed
39
40
41
    command_enter_config = "configure"
    command_leave_config = "end"
    command_save_config = "copy running-config startup-config"
42
    pattern_prompt = rb"^(?P<hostname>[A-Za-z0-9-_ \:\.\*\'\,\(\)\/]+)?(?:\(config[^\)]*\))?#"
43
    rogue_chars = [re.compile(rb"\d+-\w+-\d+\s\d+:\d+:\d+\s\%\S+\:.+"), b"\r"]
44
45
    # to one SNMP GET request
    snmp_metrics_get_chunk = 10
46
    config_tokenizer = "indent"
Dmitry Volodin's avatar
Dmitry Volodin committed
47
    config_tokenizer_settings = {"line_comment": "!", "end_of_context": "exit"}
48
49
50
51
52
53
    config_normalizer = "MESNormalizer"
    confdb_defaults = [
        ("hints", "interfaces", "defaults", "admin-status", True),
        ("hints", "protocols", "lldp", "status", True),
        ("hints", "protocols", "spanning-tree", "status", False),
        ("hints", "protocols", "spanning-tree", "priority", "32768"),
Dmitry Volodin's avatar
Dmitry Volodin committed
54
        ("hints", "protocols", "loop-detect", "status", False),
Dmitry Volodin's avatar
Dmitry Volodin committed
55
56
        ("hints", "protocols", "ntp", "mode", "server"),
        ("hints", "protocols", "ntp", "version", "3"),
57
    ]
Maksim13's avatar
Maksim13 committed
58

59
60
    collators = ["noc.core.confdb.collator.ifpath.IfPathCollator"]

61
62
    matchers = {
        "is_has_image": {"image": {"$regex": r"^\S+"}},
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
63
        "is_has_chgroup": {"version": {"$regex": r"^([12]\.[15]\.4[4-9]|4\.0\.[1,5-9]|6\.1\.2)"}},
64
        "is_3124": {"platform": {"$regex": "3[13](24|48)"}},
65
    }
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
66

67
68
    snmp_display_hints = {"1.3.6.1.4.1.89.53.4.1.7.1": render_mac}

Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
    PLATFORMS = {
        "24": "MES-3124",
        "26": "MES-5148",
        "30": "MES-3124F",
        "35": "MES-3108",
        "36": "MES-3108F",
        "38": "MES-3116",
        "39": "MES-3116F",
        "40": "MES-3224",
        "41": "MES-3224F",
        "42": "MES-1024",
        "43": "MES-2124",
        "52": "MES-1124",
        "54": "MES-5248",
        "58": "MES-2208P",
        "59": "MES-2124P",
        "74": "MES-5324",
        "75": "MES-2124F",
        "76": "MES-2324",
88
        "77": "MES-2324F",
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
89
90
91
92
93
94
95
96
        "78": "MES-2324FB",
        "80": "MES-3324",
        "81": "MES-3324F",
        "83": "MES-2324B",
        "86": "MES-2348B",
        "88": "MES-2308",
        "89": "MES-2308P",
        "92": "MES-2324P",
Dmitry Volodin's avatar
Dmitry Volodin committed
97
        "98": "MES-3508P",
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
98
        "112": "MES-2308R",
99
        "116": "MES-3308F",
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
100
        "120": "MES-3348F",
101
        "136": "MES-5316A",
102
        "190": "MES-3324F",  # rev.B
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
103
104
    }

105
106
    REVISIONS = {"190": "rev.B"}

Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
107
    def get_platform(self, s):
108
        return self.PLATFORMS.get(s), self.REVISIONS.get(s)
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
109

Maksim13's avatar
Maksim13 committed
110
    INTERFACE_TYPES = {
Dmitry Volodin's avatar
Dmitry Volodin committed
111
112
        "as": "physical",  # Async
        "at": "physical",  # ATM
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
113
114
115
        "bv": "aggregated",  # BVI
        "bu": "aggregated",  # Bundle
        # "C": "physical",     # @todo: fix
Dmitry Volodin's avatar
Dmitry Volodin committed
116
117
118
119
120
121
122
123
        "ca": "physical",  # Cable
        "cd": "physical",  # CDMA Ix
        "ce": "physical",  # Cellular
        "et": "physical",  # Ethernet
        "fa": "physical",  # FastEthernet
        "gi": "physical",  # GigabitEthernet
        "gr": "physical",  # Group-Async
        "lo": "loopback",  # Loopback
124
        "oo": "management",  # oob
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
125
126
127
128
        "mf": "aggregated",  # Multilink Frame Relay
        "mu": "aggregated",  # Multilink-group interface
        "po": "aggregated",  # Port-channel/Portgroup
        # "R": "aggregated",   # @todo: fix
Dmitry Volodin's avatar
Dmitry Volodin committed
129
130
        "sr": "physical",  # Spatial Reuse Protocol
        "se": "physical",  # Serial
131
        "st": "management",  # Stack-port
Dmitry Volodin's avatar
Dmitry Volodin committed
132
133
134
135
136
        "te": "physical",  # TenGigabitEthernet
        "fo": "physical",  # FortyGigabitEthernet
        "tu": "tunnel",  # Tunnel
        "vl": "SVI",  # VLAN, found on C3500XL
        "xt": "SVI",  # Extended Tag ATM
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
137
    }
Maksim13's avatar
Maksim13 committed
138
139
140

    @classmethod
    def get_interface_type(cls, name):
Dmitry Lukhtionov's avatar
Dmitry Lukhtionov committed
141
        return cls.INTERFACE_TYPES.get((name[:2]).lower())
MaksimSmile13's avatar
MaksimSmile13 committed
142
143
144
145
146

    # Eltex-like translation
    rx_eltex_interface_name = re.compile(
        r"^(?P<type>[a-z]{2})[a-z\-]*\s*"
        r"(?P<number>\d+(/\d+(/\d+)?)?(\.\d+(/\d+)*(\.\d+)?)?(:\d+(\.\d+)*)?(/[a-z]+\d+(\.\d+)?)?(A|B)?)?",
Dmitry Volodin's avatar
Dmitry Volodin committed
147
        re.IGNORECASE,
MaksimSmile13's avatar
MaksimSmile13 committed
148
149
150
151
152
153
154
155
156
    )

    def convert_interface_name(self, s):
        """
        >>> Profile().convert_interface_name_cisco("gi1/0/1")
        'Gi 1/0/1'
        >>> Profile().convert_interface_name_cisco("gi1/0/1?")
        'Gi 1/0/1'
        """
Dmitry Lukhtionov's avatar
Fix    
Dmitry Lukhtionov committed
157
        match = self.rx_eltex_interface_name.match(str(s))
MaksimSmile13's avatar
MaksimSmile13 committed
158
159
        if is_int(s):
            return "Vl %s" % s
160
161
        elif s in ["oob", "stack-port"]:
            return s
MaksimSmile13's avatar
MaksimSmile13 committed
162
        elif match:
Dmitry Volodin's avatar
Dmitry Volodin committed
163
            return "%s %s" % (match.group("type").capitalize(), match.group("number"))
MaksimSmile13's avatar
MaksimSmile13 committed
164
        else:
MaksimSmile13's avatar
MaksimSmile13 committed
165
            raise InterfaceTypeError("Invalid interface '%s'" % s)