nagios library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

status.py 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import argparse
  2. import json
  3. import os
  4. import requests
  5. import time
  6. DEBUG = False
  7. class colors:
  8. HEADER = '\033[95m'
  9. OKBLUE = '\033[94m'
  10. OKCYAN = '\033[96m'
  11. OKGREEN = '\033[92m'
  12. WARNING = '\033[93m'
  13. FAIL = '\033[91m'
  14. ENDC = '\033[0m'
  15. BOLD = '\033[1m'
  16. UNDERLINE = '\033[4m'
  17. def headline(color: bool) -> str:
  18. rv = ""
  19. if color:
  20. rv += colors.BOLD + colors.UNDERLINE
  21. rv += "NAGIOS Status:"
  22. if color:
  23. rv += colors.ENDC
  24. rv += "\n\n"
  25. return rv
  26. class nagios_service(dict):
  27. SID_OK = 2
  28. SID_WARNING = 4
  29. SID_ERROR = 16
  30. #
  31. SNAME_OK = "OKAY"
  32. SNAME_WARNING_LAST = "WARNING_LAST"
  33. SNAME_ERROR_LAST = "ERROR_LAST"
  34. SNAME_FLAPPING = "FLAPPING"
  35. SNAME_WARNING = "WARNING"
  36. SNAME_ERROR = "ERROR"
  37. SNAME_UNKNOWN = "UNKNOWN"
  38. TIMEFORMAT = "%d.%m.%Y %H:%M"
  39. def __init__(self, service_dict, last) -> None:
  40. super().__init__(service_dict)
  41. self.__last__ = last
  42. def is_problem(self):
  43. return self.status() != self.SNAME_OK
  44. def host_name(self):
  45. return self['host_name']
  46. def name(self):
  47. return self['description']
  48. def status(self):
  49. status = self["status"]
  50. default = self.SNAME_UNKNOWN
  51. tm_interrest = time.localtime(time.time() - 60 * 60 * self.__last__)
  52. if status == self.SID_OK:
  53. if self.flapping():
  54. return self.SNAME_FLAPPING
  55. elif self.__last_critical__() > tm_interrest:
  56. return self.SNAME_ERROR_LAST
  57. elif self.__last_warning__() > tm_interrest:
  58. return self.SNAME_WARNING_LAST
  59. return {
  60. self.SID_OK: self.SNAME_OK,
  61. self.SID_WARNING: self.SNAME_WARNING,
  62. self.SID_ERROR: self.SNAME_ERROR
  63. }.get(status, default)
  64. def last_okay(self):
  65. return time.strftime(self.TIMEFORMAT, time.localtime(self["last_time_ok"] / 1000))
  66. def __last_warning__(self):
  67. return time.localtime(self["last_time_warning"] / 1000)
  68. def last_warning(self):
  69. return time.strftime(self.TIMEFORMAT, self.__last_warning__())
  70. def __last_critical__(self):
  71. return time.localtime(self["last_time_critical"] / 1000)
  72. def last_critical(self):
  73. return time.strftime(self.TIMEFORMAT, self.__last_critical__())
  74. def last_unknown(self):
  75. return time.strftime(self.TIMEFORMAT, time.localtime(self["last_time_unknown"] / 1000))
  76. def info(self):
  77. return self.get("plugin_output") or self.get("long_plugin_output")
  78. def flapping(self):
  79. return self["is_flapping"]
  80. def __color__(self):
  81. return {
  82. self.SNAME_OK: colors.OKGREEN,
  83. self.SNAME_WARNING_LAST: colors.OKBLUE,
  84. self.SNAME_ERROR_LAST: colors.OKBLUE,
  85. self.SNAME_FLAPPING: colors.OKBLUE,
  86. self.SNAME_WARNING: colors.WARNING,
  87. self.SNAME_ERROR: colors.FAIL,
  88. self.SNAME_UNKNOWN: colors.OKCYAN
  89. }.get(self.status())
  90. def __head__(self, color=False):
  91. rv = headline(color)
  92. rv += "+---------------------------------------------------------------------------------------------\n"
  93. rv += "| Host | Service Name | State | Last time Okay |\n"
  94. rv += "+---------------------------+-----------------+--------------+------------------+-------------\n"
  95. return rv
  96. def __foot__(self):
  97. return "+---------------------------+-----------------+--------------+------------------+-------------\n"
  98. def __str__(self, color=False):
  99. cols = []
  100. cols.append((self.host_name, 25, False))
  101. cols.append((self.name, 15, color))
  102. cols.append((self.status, 12, color))
  103. cols.append((self.last_okay, 16, color))
  104. cols.append((self.info, 0, False))
  105. #
  106. rv = ""
  107. for txt_method, l, c in cols:
  108. txt = txt_method()
  109. if len(rv) > 0:
  110. rv += " | "
  111. if c:
  112. if txt_method == self.last_okay:
  113. rv += colors.OKGREEN
  114. else:
  115. rv += self.__color__()
  116. if l > 0:
  117. rv += txt[:l]
  118. rv += " " * (l-len(txt))
  119. else:
  120. rv += txt
  121. if c:
  122. rv += colors.ENDC
  123. #
  124. rv = "| " + rv + "\n"
  125. if DEBUG:
  126. rv += json.dumps(self, indent=4, sort_keys=True)
  127. return rv
  128. class __nagios_status__(dict):
  129. def __init__(self) -> None:
  130. super().__init__()
  131. def all_problems(self):
  132. rv = __nagios_status__()
  133. for host in self:
  134. for service in self[host]:
  135. if service.is_problem():
  136. rv.__add_service__(host, service, service.__last__)
  137. return rv
  138. def __add_service__(self, host, service, last):
  139. if host not in self:
  140. self[host] = []
  141. self[host].append(nagios_service(service, last))
  142. def __str__(self, color=False) -> str:
  143. rv = ""
  144. for host in self:
  145. for service in self[host]:
  146. if len(rv) == 0:
  147. rv += service.__head__(color=color)
  148. rv += service.__str__(color=color)
  149. if len(rv) > 0:
  150. rv += service.__foot__()
  151. else:
  152. rv += headline(color)
  153. rv += "No monitorings to be reported."
  154. return rv + "\n"
  155. class nagios_status(__nagios_status__):
  156. URL = "nagios4/cgi-bin/statusjson.cgi?query=servicelist&details=true"
  157. KEY_DATA = 'data'
  158. KEY_SERVICELIST = 'servicelist'
  159. def __init__(self, host, secure, last) -> None:
  160. super().__init__()
  161. #
  162. if secure:
  163. prefix = "https://"
  164. else:
  165. prefix = "http://"
  166. r = requests.get(os.path.join(prefix, host, self.URL))
  167. data = r.json()
  168. hosts = data.get(self.KEY_DATA, {}).get(self.KEY_SERVICELIST, {})
  169. for host in hosts:
  170. for service in hosts.get(host, {}):
  171. self.__add_service__(host, hosts.get(host).get(service), last)
  172. if __name__ == "__main__":
  173. parser = argparse.ArgumentParser(description="Returns the status of all or partial nagios monitorings.")
  174. parser.add_argument("hostname", help="The hostname and port of the nagios server (e.g. nagios:8080)")
  175. parser.add_argument("-a", "--all", action="store_true", default=False,
  176. help="print the status of all nagios monitorings. Default is all problems.")
  177. parser.add_argument("-last", "--last", type=int, default=0, help="Report problems of the last l hours.")
  178. parser.add_argument("-s", "--secure", action="store_true", default=False, help="Enables secure connection (https)")
  179. parser.add_argument("-m", "--monochrome", action="store_true", default=False, help="No colored output")
  180. args = parser.parse_args()
  181. #
  182. try:
  183. s = nagios_status(args.hostname, args.secure, args.last)
  184. except requests.ConnectionError:
  185. print(headline(not args.monochrome) + "Can not connect to given host.")
  186. except json.decoder.JSONDecodeError:
  187. print(headline(not args.monochrome) + "No data received. Nagios is possibly down.")
  188. else:
  189. if args.all:
  190. print(s.__str__(color=not args.monochrome))
  191. else:
  192. print(s.all_problems().__str__(color=not args.monochrome))