Advertisement
Guest User

get_spanning_tree

a guest
May 21st, 2015
295
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.90 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. ##----------------------------------------------------------------------
  3. ## Eltex.MES.get_spanning_tree
  4. ##----------------------------------------------------------------------
  5. ## Copyright (C) 2007-2015 The NOC Project
  6. ## See LICENSE for details
  7. ##----------------------------------------------------------------------
  8.  
  9. ## Python modules
  10. import re
  11. ## NOC modules
  12. from noc.sa.script import Script as NOCScript
  13. from noc.sa.interfaces import IGetSpanningTree
  14. from noc.lib.text import parse_table
  15.  
  16. class Script(NOCScript):
  17.     name = "Eltex.MES.get_spanning_tree"
  18.     implements = [IGetSpanningTree]
  19.  
  20.     TIMEOUT = 240
  21.  
  22.     rx_ins = re.compile(
  23.         r"^(?P<instance>\d+)\s+Vlans Mapped:\s+(?P<vlans>\S+)$",
  24.         re.MULTILINE)
  25.  
  26.     def get_ports_attrs(self, cli_stp, sep):
  27.         """
  28.        Get port attributes (Link type and edge status)
  29.        :param cli_stp:
  30.        :return: hash of port -> {link_type: , edge, role, status}
  31.        """
  32.  
  33.         ports = {}  # instance -> port -> attributes
  34.  
  35.         instance_id = 0
  36.         for instance in cli_stp.split(sep):
  37.             match = self.rx_ins.search(instance)
  38.             if match:
  39.                 instance_id = int(match.group("instance"))
  40.             ports[instance_id] = {}
  41.             for I in parse_table(instance):
  42.                 interface = I[0]
  43.                 priority = I[2].split('.')[0]
  44.                 ports[instance_id][interface] = {
  45.                     "status": I[1].lower() == 'enabled',
  46.                     "priority": priority,
  47.                     "port_id": I[2],
  48.                     "cost": I[3],
  49.                     "state": {
  50.                         "bkn": "broken",
  51.                         "dsbl": "disabled",
  52.                         "dscr": "discarding",
  53.                         "frw": "forwarding",
  54.                         "lbk": "loopback",
  55.                         "lrn": "learning",
  56.                         "lis": "listen",
  57.                         "??": "learning",
  58.                         }[I[4].lower()],
  59.                     "role": {
  60.                         "altn": "alternate",
  61.                         "back": "backup",
  62.                         "boun": "master",
  63.                         "desg": "designated",
  64.                         "dsbl": "disabled",
  65.                         "mstr": "master",
  66.                         "root": "root",
  67.                         "????": "nonstp",
  68.                         "_": "unknown"
  69.                         }[I[5].lower()],
  70.                     "point_to_point": "p2p" in I[7].lower(
  71.                         ).split(' '),
  72.                     }
  73.         return ports
  74.  
  75.     #
  76.     # STP/RSTP Parsing
  77.     #
  78.     rx_pvst_root = re.compile(
  79.         r"^\s+Root ID\s+Priority\s+(?P<root_priority>\d+).\s+"
  80.         r"Address\s+(?P<root_id>\S+)",
  81.         re.MULTILINE | re.IGNORECASE | re.DOTALL)
  82.  
  83.     rx_pvst_bridge = re.compile(
  84.         r"^\s+Bridge ID\s+Priority\s+(?P<bridge_priority>\d+).\s+"
  85.         r"Address\s+(?P<bridge_id>\S+)",
  86.         re.MULTILINE | re.IGNORECASE | re.DOTALL)
  87.  
  88.     rx_pvst_interfaces = re.compile(
  89.         r"Port\s+(?P<interface>\S+)\s+(?P<status>(enabled|disabled))\s*."
  90.         r"State:\s+\S+\s+Role:\s+\S+\s*."
  91.         r"Port id:\s+(?P<port_id>\d+\.\d+)\s+Port cost:\s+(?P<cost>\d+)\s*."
  92.         r"Type:\s+\S+\s+\(configured:\S+\s+(\S+\s+|)\)\s+(\S+\s+|)"
  93.         r"Port Fast:\s+\S+\s+\(configured:\S+\)\s*."
  94.         r"Designated bridge Priority\s*:\s+"
  95.         r"(?P<designated_bridge_priority>\d+)\s+"
  96.         r"Address:\s+(?P<designated_bridge_id>\S+)\s*."
  97.         r"Designated port id:\s+(?P<designated_port_id>\d+\.\d+)",
  98.         re.DOTALL | re.IGNORECASE | re.MULTILINE)
  99.  
  100.     def process_pvst(self, cli_stp, proto, sep):
  101.         # Save port attributes
  102.         ports = self.get_ports_attrs(cli_stp, sep)
  103.         r = {
  104.             "mode": proto,
  105.             "instances": []
  106.         }
  107.         interfaces = {}
  108.         instance_id = 0
  109.         interfaces[instance_id] = []
  110.         for I in self.cli("show spanning-tree detail").split("BPDU: sent"):
  111.             match_r = self.rx_pvst_root.search(I)
  112.             match_b = self.rx_pvst_bridge.search(I)
  113.             if match_b:
  114.                 r["instances"] += [{
  115.                     "id": instance_id,
  116.                     "vlans": "",
  117.                     "root_id": match_r.group("root_id"),
  118.                     "root_priority": match_r.group("root_priority"),
  119.                     "bridge_id": match_b.group("bridge_id"),
  120.                     "bridge_priority": match_b.group("bridge_priority"),
  121.                     }]
  122.             elif match_r:
  123.                 r["instances"] += [{
  124.                     "id": instance_id,
  125.                     "vlans": "",
  126.                     "root_id": match_r.group("root_id"),
  127.                     "root_priority": match_r.group("root_priority"),
  128.                     "bridge_id": match_r.group("root_id"),
  129.                     "bridge_priority": match_r.group("root_priority"),
  130.                     }]
  131.  
  132.             match = self.rx_pvst_interfaces.search(I)
  133.             if match:
  134.                 interface = match.group("interface")
  135.                 port_attrs = ports[instance_id][interface]
  136.                 interfaces[instance_id] += [{
  137.                     "interface": interface,
  138.                     "port_id": match.group("port_id"),
  139.                     "state": port_attrs["state"],
  140.                     "role": port_attrs["role"],
  141.                     "priority": port_attrs["priority"],
  142.                     "designated_bridge_id": match.group(
  143.                         "designated_bridge_id"),
  144.                     "designated_bridge_priority": match.group(
  145.                         "designated_bridge_priority"),
  146.                     "designated_port_id": match.group("designated_port_id"),
  147.                     "point_to_point": port_attrs["point_to_point"],
  148.                     "edge": port_attrs["status"],
  149.                     }]
  150.             for I in r["instances"]:
  151.                 I["interfaces"] = interfaces[I["id"]]
  152.         return r
  153.  
  154.     #
  155.     # MSTP Parsing
  156.     #
  157.  
  158.     rx_mstp_rev = re.compile(
  159.         r"^Name: (?P<region>\S+).Revision: (?P<revision>\d+)",
  160.         re.DOTALL | re.MULTILINE)
  161.  
  162.     rx_mstp_ins = re.compile(
  163.         r"^\s*(?P<instance>\d+)\s+Vlans Mapped:\s+(?P<vlans>\S+)\s*$",
  164.         re.MULTILINE)
  165.  
  166.     rx_mstp_root = re.compile(
  167.         r"^(CST |)Root ID\s+Priority\s+(?P<root_priority>\d+).\s+"
  168.         r"Address\s+(?P<root_id>\S+)",
  169.         re.MULTILINE | re.IGNORECASE | re.DOTALL)
  170.  
  171.     rx_mstp_bridge = re.compile(
  172.         r"^Bridge ID\s+Priority\s+(?P<bridge_priority>\d+).\s+"
  173.         r"Address\s+(?P<bridge_id>\S+)",
  174.         re.MULTILINE | re.IGNORECASE | re.DOTALL)
  175.  
  176.     rx_mstp_interfaces = re.compile(
  177.         r"Port\s+(?P<interface>\S+)\s+(?P<status>(enabled|disabled))\s*."
  178.         r"State:\s+\S+\s+Role:\s+\S+\s*."
  179.         r"Port id:\s+(?P<port_id>\d+\.\d+)\s+Port cost:\s+(?P<cost>\d+)\s*."
  180.         r"Type:\s+\S+\s+\(configured:\S+\s+(\S+\s*|)\)\s+"
  181.         r"(\S+\s+\S+\s+|\S+\s+|)"
  182.         r"Port Fast:\s+\S+\s+\(configured:\s*\S+\)\s*."
  183.         r"Designated bridge Priority\s*:\s+"
  184.         r"(?P<designated_bridge_priority>\d+)\s+"
  185.         r"Address:\s+(?P<designated_bridge_id>\S+)\s*."
  186.         r"Designated port id:\s+(?P<designated_port_id>\d+.\d+)",
  187.         re.DOTALL | re.IGNORECASE | re.MULTILINE)
  188.  
  189.     def process_mstp(self, cli_stp, sep):
  190.         # Save port attributes
  191.         ports = self.get_ports_attrs(cli_stp, sep)
  192.  
  193.         v = self.cli("show spanning-tree mst-configuration")
  194.         match = self.rx_mstp_rev.search(v)
  195.         r = {
  196.             "mode": "MSTP",
  197.             "instances": [],
  198.             "configuration": {
  199.                 "MSTP": {
  200.                     "region": match.group("region"),
  201.                     "revision": match.group("revision"),
  202.                     }
  203.             }
  204.         }
  205.  
  206.         interfaces = {}
  207.         v = self.cli("show spanning-tree detail")
  208.         instance_id = 0
  209.         vlans = ""
  210.         for instance in v.split(sep):
  211.             match = self.rx_mstp_ins.search(instance)
  212.             if match:
  213.                 instance_id = int(match.group("instance"))
  214.                 vlans = match.group("vlans")
  215.             interfaces[instance_id] = []
  216.             for I in instance.split("BPDU: sent"):
  217.                 match_r = self.rx_mstp_root.search(I)
  218.                 match_b = self.rx_mstp_bridge.search(I)
  219.                 if match_b:
  220.                     r["instances"] += [{
  221.                         "id": instance_id,
  222.                         "vlans": vlans,
  223.                         "root_id": match_r.group("root_id"),
  224.                         "root_priority": match_r.group("root_priority"),
  225.                         "bridge_id": match_b.group("bridge_id"),
  226.                         "bridge_priority": match_b.group("bridge_priority"),
  227.                         }]
  228.                 elif match_r:
  229.                     r["instances"] += [{
  230.                         "id": instance_id,
  231.                         "vlans": vlans,
  232.                         "root_id": match_r.group("root_id"),
  233.                         "root_priority": match_r.group("root_priority"),
  234.                         "bridge_id": match_r.group("root_id"),
  235.                         "bridge_priority": match_r.group("root_priority"),
  236.                         }]
  237.  
  238.                 match = self.rx_mstp_interfaces.search(I)
  239.                 if match:
  240.                     interface = match.group("interface")
  241.                     port_attrs = ports[instance_id][interface]
  242.                     interfaces[instance_id] += [{
  243.                         "interface": interface,
  244.                         "port_id": match.group("port_id"),
  245.                         "state": port_attrs["state"],
  246.                         "role": port_attrs["role"],
  247.                         "priority": port_attrs["priority"],
  248.                         "designated_bridge_id": match.group(
  249.                             "designated_bridge_id"),
  250.                         "designated_bridge_priority": match.group(
  251.                             "designated_bridge_priority"),
  252.                         "designated_port_id": match.group(
  253.                             "designated_port_id").replace(' ', '.'),
  254.                         "point_to_point": port_attrs["point_to_point"],
  255.                         "edge": port_attrs["status"],
  256.                         }]
  257.         for I in r["instances"]:
  258.             I["interfaces"] = interfaces[I["id"]]
  259.         return r
  260.  
  261.     def execute(self):
  262.         v = self.cli("show spanning-tree")
  263.         if "Spanning tree enabled mode STP" in v:
  264.             return self.process_pvst(v, proto="STP", sep="###### STP ")
  265.         elif "Spanning tree enabled mode RSTP" in v:
  266.             return self.process_pvst(v, proto="RSTP", sep="###### RST ")
  267.         elif "Spanning tree enabled mode MSTP" in v:
  268.             return self.process_mstp(v, sep="###### MST ")
  269.         else:
  270.             return {"mode": "None", "instances": []}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement