tool-to-librenms.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. from __future__ import print_function
  27. import requests
  28. from requests.packages.urllib3.exceptions import InsecureRequestWarning # type: ignore
  29. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
  30. import json
  31. import sys
  32. import time
  33. import os
  34. from subprocess import PIPE, run
  35. import shlex
  36. from sparker import Sparker # type: ignore
  37. import re
  38. import CLEUCreds # type: ignore
  39. from cleu.config import Config as C # type: ignore
  40. CACHE_FILE = "/home/jclarke/monitored_devs.json"
  41. def get_devs():
  42. url = "http://{}/get/switches/json".format(C.TOOL)
  43. devs = []
  44. response = requests.request("GET", url)
  45. code = 200
  46. code = response.status_code
  47. if code == 200:
  48. j = response.json()
  49. for dev in j:
  50. if dev["IPAddress"] == "0.0.0.0" or not dev["Reachable"]:
  51. continue
  52. if not re.search(r"^[0-9A-Za-z]{3}-", dev["Hostname"]):
  53. continue
  54. if (
  55. re.search(r".*CORE.*", dev["Hostname"], flags=re.I)
  56. or re.search(r"^WLC", dev["Hostname"], flags=re.I)
  57. or re.search(r".*MER[124]-dist.*", dev["Hostname"], flags=re.I)
  58. ):
  59. continue
  60. devs.append(dev)
  61. return devs
  62. def delete_device(dev):
  63. res = run(shlex.split("ssh -2 {} /usr/local/www/librenms/delhost.php {}".format(C.MONITORING, dev)), capture_output=True)
  64. return res
  65. if __name__ == "__main__":
  66. devs = {}
  67. force = False
  68. changed_devs = False
  69. if len(sys.argv) == 2:
  70. if sys.argv[1] == "-f":
  71. force = True
  72. try:
  73. with open(CACHE_FILE, "r") as fd:
  74. devs = json.load(fd)
  75. except Exception as e:
  76. print(f"Failed to open {CACHE_FILE}: {e}")
  77. tdevs = get_devs()
  78. i = 0
  79. for tdev in tdevs:
  80. i += 1
  81. if tdev["AssetTag"] in list(devs.keys()) and devs[tdev["AssetTag"]] != tdev["Hostname"]:
  82. print("=== Deleting device {} from LibreNMS ({} / {}) ===".format(tdev["Hostname"], i, len(tdevs)))
  83. res = delete_device(devs[tdev["AssetTag"]])
  84. if res.returncode != 0:
  85. print(
  86. "\n\n***WARNING: Failed to remove LibreNMS device for {}: out='{}', err='{}'".format(
  87. devs[tdev["AssetTag"]], res.stdout.decode("utf-8").strip(), res.stderr.decode("utf-8").strip()
  88. )
  89. )
  90. print("=== DONE. ===")
  91. changed_devs = True
  92. del devs[tdev["AssetTag"]]
  93. time.sleep(3)
  94. if tdev["AssetTag"] not in list(devs.keys()) or force:
  95. if force:
  96. print("=== Deleting device {} from LibreNMS ({} / {}) ===".format(tdev["Hostname"], i, len(tdevs)))
  97. res = delete_device(tdev["Hostname"])
  98. if res.returncode != 0:
  99. print(
  100. "\n\n***WARNING: Failed to remove LibreNMS device {}: out='{}', err='{}'".format(
  101. tdev["Hostname"], res.stdout.decode("utf-8").strip(), res.stderr.decode("utf-8").strip()
  102. )
  103. )
  104. print("=== DONE. ===")
  105. time.sleep(3)
  106. url = "https://librenms." + C.DNS_DOMAIN + "/api/v0/inventory/" + tdev["Hostname"]
  107. try:
  108. response = requests.request("GET", url, headers={"X-Auth-Token": CLEUCreds.LIBRENMS_TOKEN}, verify=False)
  109. response.raise_for_status()
  110. devs[tdev["AssetTag"]] = tdev["Hostname"]
  111. changed_devs = True
  112. continue
  113. except Exception as e:
  114. if not response or response.status_code != 400:
  115. text = ""
  116. if response:
  117. text = response.text
  118. print(f"Error retrieving device status for {tdev['Hostname']} from LibreNMS: {response.text}")
  119. print("=== Adding device {} to LibreNMS ({} / {}) ===".format(tdev["Hostname"], i, len(tdevs)))
  120. res = run(
  121. shlex.split(
  122. "ssh -2 {} /usr/local/www/librenms/addhost.php {} ap v3 CLEUR {} {} sha aes".format(
  123. C.MONITORING, tdev["Hostname"], CLEUCreds.SNMP_AUTH_PASS, CLEUCreds.SNMP_PRIV_PASS
  124. )
  125. ),
  126. capture_output=True,
  127. )
  128. if res.returncode != 0:
  129. print(
  130. "\n\n***ERROR: Failed to add {} to LibreNMS: out='{}', err='{}'".format(
  131. tdev["Hostname"], res.stdout.decode("utf-8").strip(), res.stderr.decode("utf-8").strip()
  132. )
  133. )
  134. continue
  135. print("=== DONE. ===")
  136. changed_devs = True
  137. devs[tdev["AssetTag"]] = tdev["Hostname"]
  138. if changed_devs:
  139. with open(CACHE_FILE, "w") as fd:
  140. json.dump(devs, fd)