11#!/usr/bin/env python3
22
3- # MIT License
4- #
5- # Copyright (c) 2021 NETWAYS GmbH
6- #
7- # Permission is hereby granted, free of charge, to any person obtaining a copy
8- # of this software and associated documentation files (the "Software"), to deal
9- # in the Software without restriction, including without limitation the rights
10- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11- # copies of the Software, and to permit persons to whom the Software is
12- # furnished to do so, subject to the following conditions:
13- #
14- # The above copyright notice and this permission notice shall be included in all
15- # copies or substantial portions of the Software.
16- #
17- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23- # SOFTWARE.
3+ # monit.h Reference
4+ # typedef enum {
5+ # Monitor_Not = 0x0,
6+ # Monitor_Yes = 0x1,
7+ # Monitor_Init = 0x2,
8+ # Monitor_Waiting = 0x4
9+ # } Monitor_State;
10+
11+ # typedef enum {
12+ # State_Succeeded = 0x0,
13+ # State_Failed = 0x1,
14+ # State_Changed = 0x2,
15+ # State_ChangedNot = 0x4,
16+ # State_Init = 0x8,
17+ # State_None = State_Init // Alias
18+ # } State_Type;
19+
20+ # typedef enum {
21+ # Service_Filesystem = 0,
22+ # Service_Directory,
23+ # Service_File,
24+ # Service_Process,
25+ # Service_Host,
26+ # Service_System,
27+ # Service_Fifo,
28+ # Service_Program,
29+ # Service_Net,
30+ # Service_Last = Service_Net
31+ # } Service_Type;
2432
2533import sys
2634import argparse
3846 3 : 'UNKNOWN'
3947}
4048
41-
4249def commandline (args ):
4350
4451 parser = argparse .ArgumentParser (prog = "check_monit.py" )
@@ -57,7 +64,6 @@ def commandline(args):
5764
5865
5966def print_output (status , count_ok , count_all , items ):
60-
6167 s = icinga_status [status ]
6268
6369 print (f"[{ s } ]: Monit Service Status { count_ok } /{ count_all } " )
@@ -69,16 +75,19 @@ def print_output(status, count_ok, count_all, items):
6975 print (' ' + item ['output' ])
7076
7177
72- def service_output (service_type , element ):
78+ def get_service_output (service_type , element ):
79+ # Service Type Filesystem
7380 if service_type == 0 :
7481 block = float (element .findall ('block/percent' )[0 ].text )
7582 inode = float (element .findall ('inode/percent' )[0 ].text )
7683 return 'user={0}%;inodes={1}%' .format (block , inode )
7784
85+ # Service Type Process
7886 if service_type == 3 :
79- # service type: PROCESS
8087 status = element .find ('status' ).text
8188 return status
89+
90+ # Service Type Host
8291 if service_type == 5 :
8392 output = []
8493
@@ -98,66 +107,70 @@ def service_output(service_type, element):
98107
99108 return ';' .join (output )
100109
110+ # Service Type Program
101111 if service_type == 7 :
102- # status = float(element.findall('program/status')[0].text)
103112 return element .findall ('program/output' )[0 ].text
104113
105114 return 'Service (type={0}) not implemented' .format (service_type )
106115
116+ def get_service_states (services ):
117+ items = []
118+ count_all = 0
119+ count_ok = 0
120+
121+ for service in services :
122+ # Get the monitor state for the service (0: Not, 1: Yes, 2: Init, 4: Waiting)
123+ monitor = int (service .find ('monitor' ).text )
124+ # if the monitor is yes or initialize, check its status
125+ if monitor in (1 , 2 ):
126+ status = int (service .find ('status' ).text )
127+ if status == 0 :
128+ count_ok += 1
129+
130+ count_all += 1
131+
132+ items .append ({
133+ "name" : service .find ('name' ).text ,
134+ "status" : status ,
135+ "output" : get_service_output (int (service .get ('type' )), service )
136+ })
137+
138+ return items , count_all , count_ok
107139
108140def main (args ):
109141 url = '{0}:{1}/_status?format=xml' .format (args .host , args .port )
110142
111143 try :
112144 r = requests .get (url , auth = (args .user , args .password ), timeout = 5 )
113145 except Exception as e : # pylint: disable=broad-except
114- print ('[UNKNOWN]: Monit Socket error={0}' .format (str (e )))
146+ print ('[UNKNOWN]: Could not connect to Monit. error={0}' .format (str (e )))
115147 return 3
116148
117149 status_code = r .status_code
118150
119151 if status_code != 200 :
120- print ('[UNKNOWN]: Monit HTTP status ={0}' .format (status_code ))
152+ print ('[UNKNOWN]: No valid response from Monit HTTP Server. error ={0}' .format (status_code ))
121153 return 3
122154
123155 try :
124156 tree = ElementTree .fromstring (r .content )
125157 except Exception as e : # pylint: disable=broad-except
126- print ('[UNKNOWN]: Monit XML error={0}' .format (str (e )))
158+ print ('[UNKNOWN]: Unable to parse XML response from Monit HTTP Server. error={0}' .format (str (e )))
127159 return 3
128160
129- items = []
130161 services = tree .findall ('service' )
162+ items , count_all , count_ok = get_service_states (services )
131163
132- count_all = 0
133- count_ok = 0
134-
135- for service in services :
136- monitor = int (service .find ('monitor' ).text )
137- if monitor in (1 , 2 ):
138- status = int (service .find ('status' ).text )
139- if status == 0 :
140- count_ok += 1
141-
142- count_all += 1
143-
144- items .append ({
145- "name" : service .find ('name' ).text ,
146- "status" : status ,
147- "output" : service_output (int (service .get ('type' )), service )
148- })
149-
150- status = 0
151-
164+ exit_status = 0
152165 if count_ok < count_all :
153- status = 2
166+ exit_status = 2
154167
155168 if count_ok == 0 :
156- status = 2
169+ exit_status = 2
157170
158- print_output (status , count_ok , count_all , items )
171+ print_output (exit_status , count_ok , count_all , items )
159172
160- return status
173+ return exit_status
161174
162175
163176if __package__ == '__main__' or __package__ is None : # pragma: no cover
0 commit comments