Browse Source

status.py: Excetion changed for compatibility

master
Dirk Alders 2 months ago
parent
commit
d08b899fb5
2 changed files with 228 additions and 1 deletions
  1. 1
    1
      status.py
  2. 227
    0
      status.py_

+ 1
- 1
status.py View File

@@ -218,7 +218,7 @@ if __name__ == "__main__":
218 218
         s = nagios_status(args.hostname, args.secure, args.last)
219 219
     except requests.ConnectionError:
220 220
         print(headline(not args.monochrome) + "Can not connect to given host.")
221
-    except requests.exceptions.JSONDecodeError:
221
+    except json.decoder.JSONDecodeError:
222 222
         print(headline(not args.monochrome) + "No data received. Nagios is possibly down.")
223 223
     else:
224 224
         if args.all:

+ 227
- 0
status.py_ View File

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

Loading…
Cancel
Save