From 7058060594f720c37924e00df7cb28d9f4ac914a Mon Sep 17 00:00:00 2001 From: "Dmitry S. Luhtionov" Date: Thu, 8 Feb 2018 21:10:37 +0200 Subject: [PATCH] Fix Zyxel.MSAN profile --- sa/profiles/Zyxel/MSAN/__init__.py | 7 +- sa/profiles/Zyxel/MSAN/get_interfaces.py | 125 ++++++++++++++---- sa/profiles/Zyxel/MSAN/get_inventory.py | 18 ++- .../Zyxel/MSAN/get_mac_address_table.py | 10 +- sa/profiles/Zyxel/MSAN/get_version.py | 7 +- 5 files changed, 127 insertions(+), 40 deletions(-) diff --git a/sa/profiles/Zyxel/MSAN/__init__.py b/sa/profiles/Zyxel/MSAN/__init__.py index 5bb6bc5bbf..39c0248569 100644 --- a/sa/profiles/Zyxel/MSAN/__init__.py +++ b/sa/profiles/Zyxel/MSAN/__init__.py @@ -3,7 +3,7 @@ # Vendor: Zyxel # OS: MSAN # --------------------------------------------------------------------- -# Copyright (C) 2007-2016 The NOC Project +# Copyright (C) 2007-2018 The NOC Project # See LICENSE for details # --------------------------------------------------------------------- """ @@ -16,12 +16,13 @@ from noc.core.profile.base import BaseProfile class Profile(BaseProfile): name = "Zyxel.MSAN" - pattern_prompt = r"^(?P[a-zA-Z0-9-_\.`\s/]+)?[#>]\s*" + pattern_prompt = r"^(?P[a-zA-Z0-9-_\.`\s/]+?)(config|chips|bridge|ethernet|adsl|gshdsl|vlan1q)?[#>]\s*" # pattern_unprivileged_prompt = r"^(?P[a-zA-Z0-9-_\.\s/]+)?>\s*" pattern_syntax_error = "((Unknown|invalid) (command|input)|Commands are:)" pattern_more = [ (r"Press any key to continue, 'n' to nopause,'e' to exit", "n"), - (r"Press any key to continue, 'e' to exit, 'n' for nopause", "n") + (r"Press any key to continue, 'e' to exit, 'n' for nopause", "n"), + (r"Using command \"stop\" to terminate", "stop"), ] config_volatile = [r"^time\s+(\d+|date).*?^"] command_more = "n" diff --git a/sa/profiles/Zyxel/MSAN/get_interfaces.py b/sa/profiles/Zyxel/MSAN/get_interfaces.py index 3ebddaa16b..212e452163 100644 --- a/sa/profiles/Zyxel/MSAN/get_interfaces.py +++ b/sa/profiles/Zyxel/MSAN/get_interfaces.py @@ -2,7 +2,7 @@ # --------------------------------------------------------------------- # Zyxel.MSAN.get_interfaces # --------------------------------------------------------------------- -# Copyright (C) 2007-2016 The NOC Project +# Copyright (C) 2007-2018 The NOC Project # See LICENSE for details # --------------------------------------------------------------------- @@ -36,6 +36,9 @@ class Script(BaseScript): rx_sub_o2 = re.compile( r"^\s*Port (?P\d+): (?PUp|Down)", re.MULTILINE) + rx_sub_o3 = re.compile( + r"^\s*(?P\d+)\s.+(?PEnabled|Disabled)\s*/(?PUp|Down)\s*\n", + re.MULTILINE) rx_ipif = re.compile( r"^\s*(?P\S+)\s+(?P\d+\.\d+\.\d+\.\d+)\s+" r"(?P\d+\.\d+\.\d+\.\d+)\s*(?P\d+|\-)?\s*$", re.MULTILINE) @@ -60,10 +63,13 @@ class Script(BaseScript): r"^\s*(?P\d+)\s+\-\s+(?Pv)\s+.+\n", re.MULTILINE) rx_vlan5 = re.compile( r"^\s*Port\s+0:\s+(?P\d+)\s*\n", re.MULTILINE) + rx_vlan6 = re.compile( + r"^\s*Port\s+(?P\d+):\s+(?P\d+)\s*\n", re.MULTILINE) rx_mac = re.compile( r"^\s*mac address\s*: (?P\S+)\s*\n", re.MULTILINE | re.IGNORECASE) rx_ports = re.compile( - r"^Port\s+\d+\s+\((?Pethernet|adsl\d+)\): (?:Enabled|Disabled)\s*\n", + r"^Port\s+\d+\s+\((?Pethernet|adsl\d+|gshdsl\d+)\): " + r"(?:Enabled|Disabled)\s*\n", re.MULTILINE) rx_stp = re.compile(r"^\s*(?P\S+)\s+V\s+\d+\s+", re.MULTILINE) @@ -102,11 +108,15 @@ class Script(BaseScript): else: raise self.NotSupportedError() for v in vlans: - if v["ports"][port_num] == "F" \ - and v["mode"][port_num] == "U": + if ( + v["ports"][port_num] == "F" and + v["mode"][port_num] == "U" + ): untagged = v["vid"] - if v["ports"][port_num] == "F" \ - and v["mode"][port_num] == "T": + if ( + v["ports"][port_num] == "F" and + v["mode"][port_num] == "T" + ): tagged += [v["vid"]] iface = { "name": ifname, @@ -160,23 +170,29 @@ class Script(BaseScript): else: ver = self.scripts.get_version() if ver["platform"] in ["IES-1248", "IES-612"]: - for match in self.rx_vlan2.finditer(self.cli("switch vlan show *")): + v = self.cli("switch vlan show *") + for match in self.rx_vlan2.finditer(v): vlans += [{ "vid": int(match.group("vlan_id")), "ports": "%s%s" % (match.group("ports"), match.group("eports")), "mode": "%s%s" % (match.group("mode"), match.group("emode")) }] port_num = 0 - for match in self.rx_vlan3.finditer(self.cli("switch vlan portshow")): + v = self.cli("switch vlan portshow") + for match in self.rx_vlan3.finditer(v): untagged = 0 tagged = [] ifname = self.profile.convert_interface_name(match.group("port")) for v in vlans: - if v["ports"][port_num] == "F" \ - and v["mode"][port_num] == "U": + if ( + v["ports"][port_num] == "F" and + v["mode"][port_num] == "U" + ): untagged = v["vid"] - if v["ports"][port_num] == "F" \ - and v["mode"][port_num] == "T": + if ( + v["ports"][port_num] == "F" and + v["mode"][port_num] == "T" + ): tagged += [v["vid"]] iface = { "name": ifname, @@ -194,7 +210,8 @@ class Script(BaseScript): iface["subinterfaces"][0]["tagged_vlans"] = tagged interfaces += [iface] port_num += 1 - for match in self.rx_sub_pvc2.finditer(self.cli("adsl pvc show")): + v = self.cli("adsl pvc show") + for match in self.rx_sub_pvc2.finditer(v): ifname = match.group("sub") for i in interfaces: if ifname == i["name"]: @@ -210,8 +227,13 @@ class Script(BaseScript): match = self.rx_mac.search(self.cli("sys info show")) iface_mac += [{"ifname": "Ethernet", "mac": match.group("mac")}] if ver["platform"] in ["IES-1000"]: - adsl = self.cli("adsl show ports") - for match in self.rx_ports.finditer(self.cli("bridge macfilter")): + try: + adsl = self.cli("adsl show ports") + except self.CLISyntaxError: + adsl = self.cli("gshdsl list ports") + vlans_pvid = self.cli("vlan1q vlan status") + v = self.cli("bridge macfilter") + for match in self.rx_ports.finditer(v): ifname = match.group("port") iface = { "name": ifname, @@ -220,13 +242,12 @@ class Script(BaseScript): } if ifname.startswith("ethernet"): sub = { - "name": ifname, - "admin_status": True, - "enabled_afi": ["BRIDGE"], - "tagged_vlans": [] - } - v = self.cli("vlan1q vlan status") - for match in self.rx_vlan4.finditer(v): + "name": ifname, + "admin_status": True, + "enabled_afi": ["BRIDGE"], + "tagged_vlans": [] + } + for match in self.rx_vlan4.finditer(vlans_pvid): vid = int(match.group("vlan_id")) if vid == 1: continue @@ -249,6 +270,33 @@ class Script(BaseScript): "vci": int(match.group("vci")) }] interfaces += [iface] + if ifname.startswith("gshdsl"): + for match in self.rx_sub_o3.finditer(adsl): + if match.group("sub") == ifname[6:]: + iface["admin_status"] = match.group("admin_status") == "Enabled" + iface["oper_status"] = match.group("oper_status") == "Up" + break + vid = 1 + for match in self.rx_vlan6.finditer(vlans_pvid): + if match.group("port") == ifname[6:]: + vid = int(match.group("vlan_id")) + break + v = self.cli("gshdsl show pvc %s" % ifname[6:]) + match = self.rx_sub_pvc2.search(v) + sub = { + "name": match.group("sub"), + "admin_status": iface["admin_status"], + "oper_status": iface["oper_status"], + "enabled_afi": ["BRIDGE", "ATM"], + "vpi": int(match.group("vpi")), + "vci": int(match.group("vci")) + } + if match.group("pvid") != "*": + sub["vlan_ids"] = int(match.group("pvid")) + elif vid != 1: + sub["vlan_ids"] = int(vid) + iface["subinterfaces"] = [sub] + interfaces += [iface] c = self.cli("ip device list") for match in self.rx_ipif1.finditer(c): ifname = match.group("ifname") @@ -280,7 +328,10 @@ class Script(BaseScript): interfaces += [iface] return [{"interfaces": interfaces}] - c = self.cli("ip show") + try: + c = self.cli("ip show") + except self.CLISyntaxError: + c = self.cli("ip device") for match in self.rx_ipif.finditer(c): ifname = match.group("ifname") addr = match.group("ip") @@ -303,8 +354,32 @@ class Script(BaseScript): iface["subinterfaces"][0]["vlan_ids"] = [int(match.group('vid'))] else: if match.group("vid") is None: - match = self.rx_ipif_vlan.search(self.cli("switch vlan cpu show")) - iface["subinterfaces"][0]["vlan_ids"] = [int(match.group('vid'))] + v = self.cli("switch vlan cpu show") + match1 = self.rx_ipif_vlan.search(v) + iface["subinterfaces"][0]["vlan_ids"] = [int(match1.group('vid'))] + for m in iface_mac: + if ifname == m["ifname"]: + iface["mac"] = m["mac"] + iface["subinterfaces"][0]["mac"] = m["mac"] + interfaces += [iface] + for match in self.rx_ipif1.finditer(c): + ifname = match.group("ifname") + addr = match.group("ip") + mask = match.group("mask") + ip_address = "%s/%s" % (addr, IPv4.netmask_to_len(mask)) + iface = { + "name": ifname, + "type": "SVI", + "admin_status": True, # always True, since inactive + "oper_status": True, # SVIs aren't shown at all + "subinterfaces": [{ + "name": ifname, + "admin_status": True, + "oper_status": True, + "enabled_afi": ["IPv4"], + "ipv4_addresses": [ip_address], + }] + } for m in iface_mac: if ifname == m["ifname"]: iface["mac"] = m["mac"] diff --git a/sa/profiles/Zyxel/MSAN/get_inventory.py b/sa/profiles/Zyxel/MSAN/get_inventory.py index b51f091126..87f7cc46e2 100644 --- a/sa/profiles/Zyxel/MSAN/get_inventory.py +++ b/sa/profiles/Zyxel/MSAN/get_inventory.py @@ -2,16 +2,15 @@ # --------------------------------------------------------------------- # Zyxel.MSAN.get_inventory # --------------------------------------------------------------------- -# Copyright (C) 2007-2016 The NOC Project +# Copyright (C) 2007-2018 The NOC Project # See LICENSE for details # --------------------------------------------------------------------- - + # Python modules import re # NOC modules from noc.core.script.base import BaseScript from noc.sa.interfaces.igetinventory import IGetInventory -from noc.sa.interfaces.base import InterfaceTypeError from noc.lib.text import parse_table @@ -38,7 +37,7 @@ class Script(BaseScript): r"^\s*Hardware Version: (?P\S+)\s*\n" r"^\s*Serial Number: (?P\S+)\s*\n", re.MULTILINE) - rx_chips = re.compile(r"^\s*(?P\S+)\s+") + rx_chips = re.compile(r"^\s*(?P\S+?)(/(?P\S+))?\s+") M_TYPE = { "IES-2000": "MSC1000", @@ -94,18 +93,27 @@ class Script(BaseScript): "part_no": part_no }] else: + module = None match = self.rx_hw.search(self.cli("sys info show", cached=True)) if match: c = self.profile.get_platform(self, slots, match.group("part_no")) else: match1 = self.rx_chips.search(self.cli("chips info")) c = match1.group("platform") + module = match1.group("module") match = self.rx_hw2.search(self.cli("sys info show", cached=True)) - return [{ + r = [{ "type": "CHASSIS", "vendor": "ZYXEL", "part_no": c, "serial": match.group("serial"), "revision": match.group("revision") }] + if module: + r += [{ + "type": "LINECARD", + "number": 1, + "vendor": "ZYXEL", + "part_no": module + }] return r diff --git a/sa/profiles/Zyxel/MSAN/get_mac_address_table.py b/sa/profiles/Zyxel/MSAN/get_mac_address_table.py index f5aa9e5bc8..3ded16910e 100644 --- a/sa/profiles/Zyxel/MSAN/get_mac_address_table.py +++ b/sa/profiles/Zyxel/MSAN/get_mac_address_table.py @@ -44,16 +44,18 @@ class Script(BaseScript): try: macs = self.cli(cmd) for match in self.rx_line.finditer(macs): - mac_address = match.group("mac") iface = match.group("interface").replace(" ", "") - r.append({ + r += [{ "vlan_id": match.group("vlan_id"), "mac": match.group("mac"), "interfaces": [self.profile.convert_interface_name(iface)], "type": "D" - }) + }] except self.CLISyntaxError: - macs = self.cli("statistics mac") + try: + macs = self.cli("statistics mac") + except self.CLISyntaxError: + return [] for match in self.rx_port.finditer(macs): port = self.profile.convert_interface_name(match.group("interface")) for match1 in self.rx_mac.finditer(match.group("macs")): diff --git a/sa/profiles/Zyxel/MSAN/get_version.py b/sa/profiles/Zyxel/MSAN/get_version.py index 5b84607fa7..242c01baa4 100644 --- a/sa/profiles/Zyxel/MSAN/get_version.py +++ b/sa/profiles/Zyxel/MSAN/get_version.py @@ -2,7 +2,7 @@ # --------------------------------------------------------------------- # Zyxel.MSAN.get_version # --------------------------------------------------------------------- -# Copyright (C) 2007-2016 The NOC Project +# Copyright (C) 2007-2018 The NOC Project # See LICENSE for details # --------------------------------------------------------------------- """ @@ -47,12 +47,13 @@ class Script(BaseScript): r"^\s*Serial Number: (?P.+)\s*\n" r"^\s*F/W Version: (?P\S+)\s*\n", re.MULTILINE) - rx_chips = re.compile(r"^\s*(?P\S+)\s+") + rx_chips = re.compile(r"^\s*(?P\S+?)(/\S+)?\s+") def execute(self): slots = self.profile.get_slots_n(self) try: - match = self.rx_ver1.search(self.cli("sys version")) + c = self.cli("sys version") + match = self.rx_ver1.search(c) except self.CLISyntaxError: c = self.cli("sys info show", cached=True) match = self.rx_ver2.search(c) -- GitLab