2 #Copyright (C) 2009-2011 :
3 # Denis GERMAIN, dt.germain@gmail.com
4 # Gabes Jean, naparuba@gmail.com
5 # Gerhard Lausser, Gerhard.Lausser@consol.de
6 # Gregory Starck, g.starck@gmail.com
7 # Hartmut Goebel, h.goebel@goebel-consult.de
9 #This file is part of Shinken.
11 #Shinken is free software: you can redistribute it and/or modify
12 #it under the terms of the GNU Affero General Public License as published by
13 #the Free Software Foundation, either version 3 of the License, or
14 #(at your option) any later version.
16 #Shinken is distributed in the hope that it will be useful,
17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 #GNU Affero General Public License for more details.
21 #You should have received a copy of the GNU Affero General Public License
22 #along with Shinken. If not, see <http://www.gnu.org/licenses/>.
24 ################################################
26 # This check is getting daemons state from
27 # a arbiter connexion.
28 ################################################
32 # Exit statuses recognized by Nagios and thus by Shinken
38 #Name of the Pyro Object we are searching
39 PYRO_OBJECT
= 'ForArbiter'
40 daemon_types
= ['arbiter', 'broker', 'scheduler', 'poller', 'reactionner']
45 # If importing shinken fails, try to load from current directory
46 # or parent directory to support running without installation.
47 # Submodules will then be loaded from there, too.
49 if not hasattr(os
, "getuid") or os
.getuid() != 0:
50 imp
.load_module('shinken', *imp
.find_module('shinken', [".", ".."]))
53 from optparse
import OptionParser
55 import shinken
.pyro_wrapper
as pyro
56 from shinken
.pyro_wrapper
import Pyro
57 except ImportError, exp
:
58 print 'CRITICAL : check_shinken requires the Python Pyro and the shinken.pyro_wrapper module. Please install it. (%s)' % exp
59 raise SystemExit, CRITICAL
62 def check_deamons_numbers(result
, target
):
63 total_number
= len(result
)
64 alive_number
= len([e
for e
in result
.values() if e
['alive']])
65 total_spare_number
= len([e
for e
in result
.values() if e
['spare']])
66 alive_spare_number
= len([e
for e
in result
.values() if e
['spare'] and e
['alive']])
67 dead_number
= total_number
- alive_number
68 dead_list
= ','.join([n
for n
in result
if not result
[n
]['alive']])
69 #TODO : perfdata to graph deamons would be nice (in big HA architectures)
70 #if alive_number <= critical, then we have a big problem
71 if alive_number
<= options
.critical
:
72 print "CRITICAL - only %d/%d %s(s) UP. Down elements : %s" % (alive_number
, total_number
, target
, dead_list
)
73 raise SystemExit, CRITICAL
74 #We are not in a case where there is no more daemons, but are there daemons down?
75 elif dead_number
>= options
.warning
:
76 print "WARNING - %d/%d %s(s) DOWN :%s" % (dead_number
, total_number
, target
, dead_list
)
77 raise SystemExit, WARNING
78 #Everything seems fine. But that's no surprise, is it?
80 print "OK - %d/%d %s(s) UP, with %d/%d spare(s) UP" % (alive_number
, total_number
, target
, alive_spare_number
, total_spare_number
)
83 # Adding options. None are required, check_shinken will use shinken defaults
84 #TODO : Add more control in args problem and usage than the default OptionParser one
85 parser
= OptionParser()
86 parser
.add_option('-a', '--hostname', dest
='hostname', default
='127.0.0.1')
87 parser
.add_option('-p', '--portnumber', dest
='portnum', default
=7770)
88 parser
.add_option('-s', '--ssl', dest
='ssl', default
=False)
89 #TODO : Add a list of correct values for target and don't authorize anything else
90 parser
.add_option('-t', '--target', dest
='target')
91 parser
.add_option('-d', '--daemonname', dest
='daemon', default
='')
92 #In HA architectures, a warning should be displayed if there's one daemon down
93 parser
.add_option('-w','--warning', dest
='warning', default
= 1)
94 #If no deamon is left, display a critical (but shinken will be probably dead already)
95 parser
.add_option('-c', '--critical', dest
='critical', default
= 0)
98 options
, args
= parser
.parse_args()
99 #TODO : for now, helpme doesn't work as desired
100 options
.helpme
= False
102 # Check for required option target
103 if not getattr(options
, 'target'):
104 print 'CRITICAL - target is not specified; You must specify which daemons you want to check!'
106 raise SystemExit, CRITICAL
107 elif options
.target
not in daemon_types
:
108 print 'CRITICAL - target %s is not a Shinken daemon!' % options
.target
110 raise SystemExit, CRITICAL
112 uri
= pyro
.create_uri(options
.hostname
, options
.portnum
, PYRO_OBJECT
, options
.ssl
)
115 # We just want a check for a single satellite daemon
116 # Only OK or CRITICAL here
117 daemon_name
= options
.daemon
119 result
= Pyro
.core
.getProxyForURI(uri
).get_satellite_status(options
.target
, daemon_name
)
120 except Pyro
.errors
.ProtocolError
, exp
:
121 print "CRITICAL : the Arbiter is not reachable : (%s)." % exp
122 raise SystemExit, CRITICAL
126 print 'OK - %s alive' % daemon_name
129 print 'CRITICAL - %s down' % daemon_name
130 raise SystemExit, CRITICAL
132 print 'UNKNOWN - %s status could not be retrieved' % daemon_name
133 raise SystemExit, UNKNOWN
135 # If no daemonname is specified, we want a general overview of the "target" daemons
139 daemon_list
= Pyro
.core
.getProxyForURI(uri
).get_satellite_list(options
.target
)
140 except Pyro
.errors
.ProtocolError
, exp
:
141 print "CRITICAL : the Arbiter is not reachable : (%s)." % exp
142 raise SystemExit, CRITICAL
144 for daemon_name
in daemon_list
:
145 # Getting individual daemon and putting status info in the result dictionnary
147 result
[daemon_name
] = Pyro
.core
.getProxyForURI(uri
).get_satellite_status(options
.target
, daemon_name
)
148 except Pyro
.errors
.ProtocolError
, exp
:
149 print "CRITICAL : the Arbiter is not reachable : (%s)." % exp
150 raise SystemExit, CRITICAL
152 # Now we have all data
154 check_deamons_numbers(result
, options
.target
)
156 print 'UNKNOWN - Arbiter could not retrieve status for %s' % options
.target
157 raise SystemExit, UNKNOWN