Commit 6da70853 authored by Andrey Vertiprahov's avatar Andrey Vertiprahov
Browse files

Merge branch 'cherry-pick-8b671348' into 'release-20.4'

release-20.4:Backport!4634

See merge request noc/noc!4696
parents 79f537b0 55ebfd15
...@@ -5,10 +5,12 @@ ...@@ -5,10 +5,12 @@
# See LICENSE for details # See LICENSE for details
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
# Python modules
import re
from noc.core.script.base import BaseScript # NOC modules
from noc.sa.profiles.Generic.get_chassis_id import Script as BaseScript
from noc.sa.interfaces.igetchassisid import IGetChassisID from noc.sa.interfaces.igetchassisid import IGetChassisID
import re
class Script(BaseScript): class Script(BaseScript):
...@@ -18,7 +20,7 @@ class Script(BaseScript): ...@@ -18,7 +20,7 @@ class Script(BaseScript):
rx_id = re.compile(r"^\s*MAC_ADDRESS\s+:\s+(?P<id>\S+)", re.IGNORECASE | re.MULTILINE) rx_id = re.compile(r"^\s*MAC_ADDRESS\s+:\s+(?P<id>\S+)", re.IGNORECASE | re.MULTILINE)
def execute(self): def execute_cli(self, **kwargs):
match = self.re_search(self.rx_id, self.cli("display device manuinfo", cached=True)) match = self.re_search(self.rx_id, self.cli("display device manuinfo", cached=True))
mac = match.group("id") mac = match.group("id")
return {"first_chassis_mac": mac, "last_chassis_mac": mac} return {"first_chassis_mac": mac, "last_chassis_mac": mac}
...@@ -15,7 +15,8 @@ class Script(BaseScript): ...@@ -15,7 +15,8 @@ class Script(BaseScript):
name = "HP.Comware.get_config" name = "HP.Comware.get_config"
interface = IGetConfig interface = IGetConfig
def execute_cli(self, **kwargs): def execute_cli(self, policy="r"):
assert policy in ("r", "s")
self.cli("undo terminal monitor") self.cli("undo terminal monitor")
config = self.cli("display current-configuration") config = self.cli("display current-configuration")
config = self.profile.clean_spaces(config) config = self.profile.clean_spaces(config)
......
# ---------------------------------------------------------------------
# HP.Comware.get_fqdn
# ---------------------------------------------------------------------
# Copyright (C) 2007-2020 The NOC Project
# See LICENSE for details
# ---------------------------------------------------------------------
# NOC modules
from noc.sa.profiles.Generic.get_fqdn import Script as BaseScript
from noc.sa.interfaces.igetfqdn import IGetFQDN
class Script(BaseScript):
name = "HP.Comware.get_fqdn"
interface = IGetFQDN
always_prefer = "S"
...@@ -11,19 +11,13 @@ import re ...@@ -11,19 +11,13 @@ import re
# NOC modules # NOC modules
from noc.core.script.base import BaseScript from noc.core.script.base import BaseScript
from noc.sa.interfaces.igetinterfaces import IGetInterfaces from noc.sa.interfaces.igetinterfaces import IGetInterfaces
from noc.core.text import parse_kv
class Script(BaseScript): class Script(BaseScript):
name = "HP.Comware.get_interfaces" name = "HP.Comware.get_interfaces"
interface = IGetInterfaces interface = IGetInterfaces
rx_sh_int = re.compile(
r"^\s*(?P<interface>\S+) current state\s*:\s*(?P<oper_status>UP|DOWN|DOWN \( Administratively \))\s*\n"
r"(^\s*Line protocol current state\s*:\s*(?P<line_status>UP|UP \(spoofing\)|DOWN|DOWN \( Administratively \))\s*\n)?"
r"(^\s*IP (?:Packet Frame Type:|Sending Frames\' Format is) PKTFMT_ETHNT_2, Hardware Address(?: is|:) (?P<mac>\S+)\s*\n)?"
r"^\s*Description\s*:(?P<descr>[^\n]*)\n",
re.MULTILINE | re.IGNORECASE | re.DOTALL,
)
rx_mtu = re.compile(r"The Maximum Frame Length is (?P<mtu>\d+)") rx_mtu = re.compile(r"The Maximum Frame Length is (?P<mtu>\d+)")
rx_port_type = re.compile(r"Port link-type: (?P<port_type>hybrid|access|trunk)") rx_port_type = re.compile(r"Port link-type: (?P<port_type>hybrid|access|trunk)")
rx_port_other = re.compile( rx_port_other = re.compile(
...@@ -39,194 +33,158 @@ class Script(BaseScript): ...@@ -39,194 +33,158 @@ class Script(BaseScript):
rx_ip = re.compile(r"Internet Address is (?P<ip>\S+) Primary") rx_ip = re.compile(r"Internet Address is (?P<ip>\S+) Primary")
rx_ips = re.compile(r"Internet Address is (?P<ip>\S+) Sub") rx_ips = re.compile(r"Internet Address is (?P<ip>\S+) Sub")
rx_mac = re.compile( rx_mac = re.compile(
r"IP (?:Packet Frame Type:|Sending Frames' Format is) PKTFMT_ETHNT_2, Hardware Address(?: is|:) (?P<mac>\S+)" r"IP (?:Packet Frame Type:|Sending Frames' Format is)\s*PKTFMT_ETHNT_2, Hardware Address(?: is|:) (?P<mac>\S+)"
)
rx_sh_vlan = re.compile(
r"^(?P<interface>\S+) current state\s*:\s*(?P<oper_status>UP|DOWN|DOWN \( Administratively \))\s*\n"
r"^Line protocol current state\s*:\s*(?P<line_status>UP|UP \(spoofing\)|DOWN|DOWN \( Administratively \))\s*\n"
r"(^IP (?:Packet Frame Type:|Sending Frames\' Format is) PKTFMT_ETHNT_2, Hardware address(?: is|:) (?P<mac>\S+)\s*\n)?"
r"(^Internet Address is (?P<ip>\S+) Primary\s*\n)?"
r"(^Internet protocol processing\s*:\s*\S+\s*\n)?"
r"^Description\s*:(?P<descr>.*?)\n"
r"^The Maximum Transmit Unit is (?P<mtu>\d+)",
re.MULTILINE,
) )
rx_name = re.compile(r"^Vlan-interface(?P<vlan>\d+)?")
rx_vlan_name = re.compile(r"^Vlan-interface(?P<vlan>\d+)?")
rx_isis = re.compile(r"Interface:\s+(?P<iface>\S+)") rx_isis = re.compile(r"Interface:\s+(?P<iface>\S+)")
rx_sub_default_vlan = re.compile(r"\(default vlan\),?") rx_sub_default_vlan = re.compile(r"\(default vlan\),?")
rx_parse_interface_vlan = re.compile(r"(\d+)(?:\(.+\))?")
rx_iface_block_splitter = re.compile(r"^\s*\S+\d+(?:/\d+)+", re.MULTILINE)
def execute(self): def get_isis_interfaces(self):
isis = [] r = []
try: try:
v = self.cli("display isis interface") v = self.cli("display isis interface")
for match in self.rx_isis.finditer(v): for match in self.rx_isis.finditer(v):
isis += [match.group("iface")] r += [match.group("iface")]
except self.CLISyntaxError: except self.CLISyntaxError:
pass pass
return r
interface_map = {
"current state": "oper_status",
"line protocol state": "line_status",
"description": "description",
"maximum transmit unit": "mtu",
"port link-type": "port_type",
"pvid": "pvid",
"untagged vlan id": "untagged_vlan",
"untagged vlan": "untagged_vlan",
"tagged vlan id": "tagged_vlans",
"vlan passing": "vlan_passing",
"vlan permitted": "vlan_permitted",
}
def parse_interface_block(self, block):
r = parse_kv(self.interface_map, block)
if "mtu" not in r and self.rx_mtu.search(block):
r["mtu"] = self.rx_mtu.search(block).group(1)
if self.rx_mac.search(block):
r["mac"] = self.rx_mac.search(block).group(1)
ip_match = self.rx_ip.search(block)
if ip_match:
r["ip"] = ip_match.group(1)
if "tagged_vlans" in r and self.rx_sub_default_vlan.search(r["tagged_vlans"]):
r["tagged_vlans"] = r["tagged_vlans"].replace("(default vlan)", "")
if "vlan_passing" in r and self.rx_sub_default_vlan.search(r["vlan_passing"]):
r["vlan_passing"] = r["vlan_passing"].replace("(default vlan)", "")
if "vlan_permitted" in r and self.rx_sub_default_vlan.search(r["vlan_permitted"]):
r["vlan_permitted"] = r["vlan_permitted"].replace("(default vlan)", "")
if "untagged_vlan" not in r and "pvid" in r:
r["untagged_vlan"] = r["pvid"]
if "untagged_vlan" in r:
r["untagged_vlan"] = self.rx_parse_interface_vlan.match(r["untagged_vlan"]).group(1)
return r
def iter_block(self, v):
for b in v.split("\n\n"):
start = 0
for match in self.rx_iface_block_splitter.finditer(b):
"""
Fixed
0 aborts, 0 deferred, 0 collisions, 0 late collisions
- lost carrier, - no carrier
GigabitEthernet1/3
Current state: UP
"""
if match.start() > 0:
start = match.start()
yield b[:start]
yield b[start:]
if start:
continue
else:
yield b
def execute_cli(self, **kwargs):
isis = self.get_isis_interfaces()
# Get portchannels
portchannel_members = {} portchannel_members = {}
for pc in self.scripts.get_portchannel(): for pc in self.scripts.get_portchannel():
i = pc["interface"] i = pc["interface"]
t = pc["type"] == "L" t = pc["type"] == "L"
for m in pc["members"]: for m in pc["members"]:
portchannel_members[m] = (i, t) portchannel_members[m] = (i, t)
interfaces = [] interfaces = {}
v = self.cli("display interface").split("\n\n") v = self.cli("display interface")
for i in v: # "display interface Vlan-interface"
match = self.rx_sh_int.search(i) # "display interface NULL"
if not match: for block in self.iter_block(v):
if not block:
continue continue
ifname = match.group("interface") ifname, block = block.split(None, 1)
if ifname.startswith("Bridge-Aggregation") or ifname.startswith("Route-Aggregation"): # print(ifname, "\n\n", block, "\n\n")
iftype = "aggregated" if ifname in interfaces:
elif ifname.startswith("LoopBack"):
iftype = "loopback"
elif ifname.startswith("Vlan-interface"):
continue continue
elif ifname.startswith("NULL"): r = self.parse_interface_block(block)
if not r:
continue continue
iftype = self.profile.get_interface_type(ifname)
self.logger.info("Process interface: %s", ifname)
o_status = r.get("oper_status", "").lower() == "up"
a_status = False if "Administratively" in r.get("oper_status", "") else True
name = ifname
vlan_ids = 0
if "." in ifname:
ifname, vlan_ids = ifname.split(".", 1)
else: else:
iftype = "physical" interfaces[ifname] = {
o_stat = match.group("oper_status").lower() == "up" "name": ifname,
if match.group("oper_status") == r"DOWN ( Administratively\)": "type": iftype,
a_stat = False "admin_status": a_status,
else: "oper_status": o_status,
a_stat = True "enabled_protocols": [],
iface = { "subinterfaces": [],
"name": ifname, }
"type": iftype, if "description" in r:
"admin_status": a_stat, interfaces[ifname]["description"] = r["description"]
"oper_status": o_stat, if "mac" in r:
"enabled_protocols": [], interfaces[ifname]["mac"] = r["mac"]
"subinterfaces": [], if ifname in portchannel_members:
} ai, is_lacp = portchannel_members[ifname]
interfaces[ifname]["aggregated_interface"] = ai
interfaces[ifname]["enabled_protocols"] += ["LACP"]
if self.rx_vlan_name.match(ifname):
vlan_ids = self.rx_vlan_name.match(name).group(1)
sub = { sub = {
"name": ifname, "name": name,
"admin_status": a_stat, "admin_status": a_status,
"oper_status": o_stat, "oper_status": o_status,
"enabled_afi": ["BRIDGE"],
"enabled_protocols": [], "enabled_protocols": [],
"enabled_afi": [],
} }
if ifname in isis: if ifname in isis:
sub["enabled_protocols"] += ["ISIS"] sub["enabled_protocols"] += ["ISIS"]
if match.group("mac"): if "mac" in r:
iface["mac"] = match.group("mac") sub["mac"] = r["mac"]
sub["mac"] = match.group("mac") if "ip" in r:
if match.group("descr"):
iface["description"] = match.group("descr").strip()
sub["description"] = match.group("descr").strip()
match1 = self.rx_mtu.search(i)
if match1:
sub["mtu"] = int(match1.group("mtu"))
match1 = self.rx_ip.search(i)
if match1:
sub["enabled_afi"] += ["IPv4"] sub["enabled_afi"] += ["IPv4"]
sub["ipv4_addresses"] = [match1.group("ip")] sub["ipv4_addresses"] = [r["ip"]]
match1 = self.rx_port_type.search(i) if vlan_ids:
if match1: sub["vlan_ids"] = [int(vlan_ids)]
port_type = match1.group("port_type") if "port_type" in r:
if port_type in ["access", "hybrid"]: sub["enabled_afi"] += ["BRIDGE"]
match2 = self.rx_port_other.search(i) # Bridge interface
if match2.group("untagged") and match2.group("untagged") != "none": if r["port_type"] in ["access", "hybrid"] and "untagged_vlan" in r:
sub["untagged_vlan"] = int(match2.group("untagged")) sub["untagged_vlan"] = int(r["untagged_vlan"])
if match2.group("tagged") and match2.group("tagged") != "none": if r["port_type"] in ["access", "hybrid"] and "tagged_vlans" in r:
sub["tagged_vlan"] = self.expand_rangelist(match2.group("tagged")) sub["tagged_vlans"] = self.expand_rangelist((r["tagged_vlans"]))
if port_type == "trunk": if r["port_type"] == "trunk" and "vlan_permitted" in r:
match2 = self.rx_port_trunk.search(i) sub["tagged_vlans"] = self.expand_rangelist(r["vlan_permitted"])
if match2.group("passing") and match2.group("passing") != "none": interfaces[ifname]["subinterfaces"] += [sub]
passing = re.sub(self.rx_sub_default_vlan, "", match2.group("passing"))
sub["tagged_vlan"] = self.expand_rangelist(passing) return [{"interfaces": list(interfaces.values())}]
iface["subinterfaces"] += [sub]
if ifname in portchannel_members:
ai, is_lacp = portchannel_members[ifname]
iface["aggregated_interface"] = ai
iface["enabled_protocols"] += ["LACP"]
interfaces += [iface]
v = self.cli("display interface Vlan-interface").split("\n\n")
for i in v:
match = self.rx_sh_vlan.search(i)
if not match:
continue
ifname = match.group("interface")
o_stat = match.group("oper_status").lower() == "up"
if match.group("oper_status") == r"DOWN ( Administratively\)":
a_stat = False
else:
a_stat = True
iface = {
"name": ifname,
"type": "SVI",
"admin_status": a_stat,
"oper_status": o_stat,
"enabled_protocols": [],
"subinterfaces": [],
}
sub = {
"name": ifname,
"admin_status": a_stat,
"oper_status": o_stat,
"enabled_afi": [],
}
if match.group("descr"):
iface["description"] = match.group("descr").strip()
sub["description"] = match.group("descr").strip()
if match.group("mtu"):
sub["mtu"] = int(match.group("mtu"))
match1 = self.rx_mac.search(i)
if match1:
iface["mac"] = match1.group("mac")
sub["mac"] = match1.group("mac")
match1 = self.rx_ip.search(i)
if match1:
sub["enabled_afi"] += ["IPv4"]
sub["ipv4_addresses"] = [match1.group("ip")]
match1 = self.rx_ips.search(i)
if match1:
sub["ipv4_addresses"] += [match1.group("ip")]
vlan = self.rx_name.search(ifname).group("vlan")
sub["vlan_ids"] = [vlan]
iface["subinterfaces"] += [sub]
interfaces += [iface]
v = self.cli("display interface NULL").split("\n\n")
for i in v:
match = self.rx_sh_vlan.search(i)
if not match:
continue
ifname = match.group("interface")
o_stat = match.group("oper_status").lower() == "up (spoofing)"
if match.group("oper_status") == r"DOWN ( Administratively\)":
a_stat = False
else:
a_stat = True
iface = {
"name": ifname,
"type": "null",
"admin_status": a_stat,
"oper_status": o_stat,
"enabled_protocols": [],
"subinterfaces": [],
}
sub = {
"name": ifname,
"admin_status": a_stat,
"oper_status": o_stat,
"enabled_afi": [],
}
if match.group("descr"):
iface["description"] = match.group("descr").strip()
sub["description"] = match.group("descr").strip()
if match.group("mtu"):
sub["mtu"] = int(match.group("mtu"))
match1 = self.rx_mac.search(i)
if match1:
iface["mac"] = match1.group("mac")
sub["mac"] = match1.group("mac")
match1 = self.rx_ip.search(i)
if match1:
sub["enabled_afi"] += ["IPv4"]
sub["ipv4_addresses"] = [match1.group("ip")]
match1 = self.rx_ips.search(i)
if match1:
sub["ipv4_addresses"] += [match1.group("ip")]
iface["subinterfaces"] += [sub]
interfaces += [iface]
return [{"interfaces": interfaces}]
...@@ -10,78 +10,122 @@ ...@@ -10,78 +10,122 @@
import re import re
# NOC modules # NOC modules
from noc.core.script.base import BaseScript from noc.sa.profiles.Generic.get_lldp_neighbors import Script as BaseScript
from noc.sa.interfaces.igetlldpneighbors import IGetLLDPNeighbors from noc.sa.interfaces.igetlldpneighbors import IGetLLDPNeighbors
from noc.core.lldp import (
LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT,
LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT,
LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS,
LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME,
LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS,
LLDP_CHASSIS_SUBTYPE_LOCAL,
LLDP_CHASSIS_SUBTYPE_MAC,
LLDP_PORT_SUBTYPE_ALIAS,
LLDP_PORT_SUBTYPE_COMPONENT,
LLDP_PORT_SUBTYPE_NAME,
LLDP_PORT_SUBTYPE_MAC,
LLDP_PORT_SUBTYPE_NETWORK_ADDRESS,
LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID,
LLDP_PORT_SUBTYPE_LOCAL,
LLDP_CAP_NAMES,
lldp_caps_to_bits,
)
from noc.core.text import parse_kv
class Script(BaseScript): class Script(BaseScript):
name = "HP.Comware.get_lldp_neighbors" name = "HP.Comware.get_lldp_neighbors"
interface = IGetLLDPNeighbors interface = IGetLLDPNeighbors
rx_item = re.compile( lldp_kv_map = {
r"^LLDP neighbor-information of port \d+\[(?P<interface>\S+)\]\:\n" "neighbor index": "neighbor_index",
r"^ Neighbor index : \d+\n" "lldp neighbor index": "neighbor_index",
r"^ Update time : .+?\n" "update time": "update_time",
r"^ Chassis type : (?P<chassis_type>.+?)\n" "chassis type": "remote_chassis_id_subtype",
r"^ Chassis ID : (?P<chassis_id>\S+)\n" "chassis id": "remote_chassis_id",
r"^ Port ID type : (?P<port_id_type>.+?)\n" "port id type": "remote_port_subtype",
r"^ Port ID : (?P<port_id>.+?)\n" "port id": "remote_port",
r"^ Port description : (?P<port_descr>.+?)\n" "port description": "remote_port_description",
r"^ System name : (?P<system_name>.+?)\n" "system name": "remote_system_name",
r"(^ System description : (?P<system_descr>.+?)\n)?" "system description": "remote_system_description",
r"(^ System capabilities supported : (?P<system_caps_s>.+?)\n)?", "system capabilities supported": "remote_capabilities",
re.MULTILINE, "capabilities": "remote_capabilities",
) "chassisid/subtype": "remote_chassis_id_type",
"portid/subtype": "remote_port_type",
}
def execute(self): rx_lldp_neighbor_split = re.compile(r"LLDP neighbor-information of port")
r = []
rx_local_port = re.compile(r"^\s*\d+\[(?P<interface>\S+)\]\:")
chassis_type_map = {
"chassis component": LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT,
"interface alias": LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS,
"port component": LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT,
"mac address": LLDP_CHASSIS_SUBTYPE_MAC,
"network address": LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS,
"interface name": LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME,
"local": LLDP_CHASSIS_SUBTYPE_LOCAL,
}
port_type_map = {
"interface alias": LLDP_PORT_SUBTYPE_ALIAS,
"port component": LLDP_PORT_SUBTYPE_COMPONENT,
"mac address": LLDP_PORT_SUBTYPE_MAC,
"network address": LLDP_PORT_SUBTYPE_NETWORK_ADDRESS,
"interface name": LLDP_PORT_SUBTYPE_NAME,
"agent circuit id": LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID,
"locally assigned": LLDP_PORT_SUBTYPE_LOCAL,
}
def execute_cli(self, **kwargs):
result = []
try: try:
v = self.cli("display lldp neighbor-information") v = self.cli("display lldp neighbor-information")
except self.CLISyntaxError: except self.CLISyntaxError:
return [] return []
for match in self.rx_item.finditer(v): for nei in self.rx_lldp_neighbor_split.split(v):
i = {"local_interface": match.group("interface"), "neighbors": []} if not nei.strip():
continue
match = self.rx_local_port.search(nei)
if not match:
self.logger.info("Not find local port")
continue
n = {} n = {}
n["remote_chassis_id_subtype"] = { r = parse_kv(self.lldp_kv_map, nei)
"Chassis Component": 1, if "remote_chassis_id_subtype" in r:
"Interface Alias": 2, n["remote_chassis_id_subtype"] = r["remote_chassis_id_subtype"]
"Port Component": 3, if "remote_chassis_id_type" in r:
"MAC Address": 4, n["remote_chassis_id"], n["remote_chassis_id_subtype"] = r[
"Network Address": 5, "remote_chassis_id_type"
"Interface Name": 6, ].rsplit("/", 1)
"local": 7, if "remote_chassis_id" in r:
}.get(match.group("chassis_type")) n["remote_chassis_id"] = r["remote_chassis_id"]
n["remote_chassis_id"] = match.group("chassis_id").strip() if "remote_chassis_id" not in n:
n["remote_port_subtype"] = { self.logger.warning(
"Interface Alias": 1, "[%s] Not found remote chassis id on output", match.group("interface")
"Port Component": 2, )
"MAC Address": 3, continue
"Network Address": 4, n["remote_chassis_id_subtype"] = self.chassis_type_map[
"Interface Name": 5, n["remote_chassis_id_subtype"].lower()
"Agent Circuit ID": 6, ]
"Locally assigned": 7, # Port fields
}.get(match.group("port_id_type")) if "remote_port_subtype" in r:
n["remote_port"] = match.group("port_id").strip() n["remote_port_subtype"] = r["remote_port_subtype"]
n["remote_port_description"] = match.group("port_descr").strip()