err_disable.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #!/usr/bin/env python
  2. #
  3. # Copyright (c) 2017-2023 Joe Clarke <jclarke@cisco.com>
  4. # All rights reserved.
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions
  8. # are met:
  9. # 1. Redistributions of source code must retain the above copyright
  10. # notice, this list of conditions and the following disclaimer.
  11. # 2. Redistributions in binary form must reproduce the above copyright
  12. # notice, this list of conditions and the following disclaimer in the
  13. # documentation and/or other materials provided with the distribution.
  14. #
  15. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. # SUCH DAMAGE.
  26. import sys
  27. from sparker import Sparker, MessageType # type: ignore
  28. import CLEUCreds # type: ignore
  29. import re
  30. import os
  31. import json
  32. import time
  33. from cleu.config import Config as C # type: ignore
  34. SPARK_ROOM = "Err Disable Alarms"
  35. CACHE_FILE = "/home/jclarke/err_disable_cache.json"
  36. def make_tool_link(switch, port):
  37. return '<a href="{}switchname={}&portname={}">**{}**</a>'.format(
  38. C.TOOL_BASE,
  39. switch,
  40. port,
  41. port,
  42. )
  43. if __name__ == "__main__":
  44. spark = Sparker(token=CLEUCreds.SPARK_TOKEN)
  45. curr_ports = {}
  46. if os.path.exists(CACHE_FILE):
  47. with open(CACHE_FILE, "r") as fd:
  48. curr_ports = json.load(fd)
  49. while True:
  50. output = ""
  51. for line in sys.stdin.readline():
  52. output += line
  53. host, msghdr, msg = output.split("~")
  54. hname = msghdr.replace(": ", "")
  55. hpart = ""
  56. if hname != "" and hname != "GMT" and hname != "CET":
  57. hpart = "({}) ".format(hname)
  58. m = re.search(r": ([^,]+), putting ([^\s]+) in err-disable state", msg)
  59. if m:
  60. spark.post_to_spark(
  61. C.WEBEX_TEAM,
  62. SPARK_ROOM,
  63. "Port {} on **{}** **{}**has been put in an err-disable state because {}".format(
  64. make_tool_link(host, m.group(2)), host, hpart, m.group(1)
  65. ),
  66. MessageType.WARNING,
  67. )
  68. curr_ports[f"{host}:{m.group(2)}"] = int(time.time() * 1000)
  69. else:
  70. m = re.search(r"recover from .+? err-disable state on (\S+)", msg)
  71. if m:
  72. if f"{host}:{m.group(1)}" in curr_ports:
  73. # Only send an up if we haven't seen another down for 5 seconds.
  74. if int(time.time() * 1000) - curr_ports[f"{host}:{m.group(1)}"] >= 5000:
  75. spark.post_to_spark(
  76. C.WEBEX_TEAM,
  77. SPARK_ROOM,
  78. "Port {} on **{}** **{}**is recovering from err-disable".format(make_tool_link(host, m.group(1)), host, hpart),
  79. MessageType.GOOD,
  80. )
  81. del curr_ports[f"{host}:{m.group(1)}"]
  82. with open(CACHE_FILE, "w") as fd:
  83. json.dump(curr_ports, fd)