Fix : get back LiveStatus as default.
[shinken.git] / shinken / modules / nsca_arbiter.py
blobd6990b9f31b63ecc6830c23441dec889417d910d
1 #!/usr/bin/python
2 #Copyright (C) 2009 Gabes Jean, naparuba@gmail.com
4 #This file is part of Shinken.
6 #Shinken is free software: you can redistribute it and/or modify
7 #it under the terms of the GNU Affero General Public License as published by
8 #the Free Software Foundation, either version 3 of the License, or
9 #(at your option) any later version.
11 #Shinken is distributed in the hope that it will be useful,
12 #but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 #GNU Affero General Public License for more details.
16 #You should have received a copy of the GNU Affero General Public License
17 #along with Shinken. If not, see <http://www.gnu.org/licenses/>.
20 #This Class is an example of an Arbiter module
21 #Here for the configuration phase AND running one
24 #This text is print at the import
25 print "Detected module : NSCA module for Arbiter"
28 import time
29 import select
30 import socket
31 import struct
32 import random
34 from shinken.basemodule import BaseModule
35 from shinken.external_command import ExternalCommand
37 properties = {
38 'type' : 'nsca_server',
39 'external' : True,
40 'phases' : ['running'],
43 def decrypt_xor(data, key):
44 keylen = len(key)
45 crypted = [chr(ord(data[i]) ^ ord(key[i % keylen])) for i in xrange(len(data))]
46 return ''.join(crypted)
48 #called by the plugin manager to get a broker
49 def get_instance(plugin):
50 print "Get a NSCA arbiter module for plugin %s" % plugin.get_name()
52 if hasattr(plugin, 'host'):
53 if plugin.host == '*':
54 host = ''
55 else:
56 host = plugin.host
57 else:
58 host = '127.0.0.1'
59 if hasattr(plugin, 'port'):
60 port = int(plugin.port)
61 else:
62 port = 5667
63 if hasattr(plugin, 'encryption_method'):
64 encryption_method = int(plugin.encryption_method)
65 else:
66 encryption_method = 0
67 if hasattr(plugin, 'password'):
68 password = plugin.password
69 else:
70 password = ""
72 instance = NSCA_arbiter(plugin, host, port, encryption_method, password)
73 return instance
76 #Just print some stuff
77 class NSCA_arbiter(BaseModule):
78 def __init__(self, modconf, host, port, encryption_method, password):
79 BaseModule.__init__(self, modconf)
80 self.host = host
81 self.port = port
82 self.encryption_method = encryption_method
83 self.password = password
84 self.rng = random.Random(password)
87 #Ok, main function that is called in the CONFIGURATION phase
88 def get_objects(self):
89 print "[Dummy] ask me for objects to return"
90 r = {'hosts' : []}
91 h = {'name' : 'dummy host from dummy arbiter module',
92 'register' : '0',
95 r['hosts'].append(h)
96 print "[Dummy] Returning to Arbiter the hosts:", r
97 return r
99 def send_init_packet(self, socket):
101 Build an init packet
102 00-127 : IV
103 128-131 : unix timestamp
105 iv = ''.join([chr(self.rng.randrange(256)) for i in xrange(128)])
106 init_packet = struct.pack("!128sI", iv, int(time.mktime(time.gmtime())))
107 socket.send(init_packet)
108 return iv
110 def read_check_result(self, data, iv):
112 Read the check result
113 00-01 : Version
114 02-05 : CRC32
115 06-09 : Timestamp
116 10-11 : Return code
117 12-75 : hostname
118 76-203 : service
119 204-715 : output of the plugin
120 716-720 : padding
122 if len(data) != 720:
123 return None
125 if self.encryption_method == 1:
126 data = decrypt_xor(data,self.password)
127 data = decrypt_xor(data,iv)
129 (version, pad1, crc32, timestamp, rc, hostname_dirty, service_dirty, output_dirty, pad2) = struct.unpack("!hhIIh64s128s512sh",data)
130 hostname = hostname_dirty.split("\0", 1)[0]
131 service = service_dirty.partition("\0", 1)[0]
132 output = output_dirty.partition("\0", 1)[0]
133 return (timestamp, rc, hostname, service, output)
135 def post_command(self, timestamp, rc, hostname, service, output):
137 Send a check result command to the arbiter
139 if len(service) == 0:
140 extcmd = "[%lu] PROCESS_HOST_CHECK_RESULT;%s;%d;%s\n" % (timestamp,hostname,rc,output)
141 else:
142 extcmd = "[%lu] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n" % (timestamp,hostname,service,rc,output)
144 e = ExternalCommand(extcmd)
145 self.from_q.put(e)
148 # When you are in "external" mode, that is the main loop of your process
149 def main(self):
150 self.set_exit_handler()
151 backlog = 5
152 size = 8192
153 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
154 server.setblocking(0)
155 server.bind((self.host, self.port))
156 server.listen(backlog)
157 input = [server]
158 databuffer = {}
159 IVs = {}
161 while not self.interrupted:
162 inputready,outputready,exceptready = select.select(input,[],[], 1)
164 for s in inputready:
165 if s == server:
166 # handle the server socket
167 client, address = server.accept()
168 iv = self.send_init_packet(client)
169 IVs[client] = iv
170 input.append(client)
171 else:
172 # handle all other sockets
173 data = s.recv(size)
174 if s in databuffer:
175 databuffer[s] += data
176 else:
177 databuffer[s] = data
178 if len(databuffer[s]) == 720:
179 # end-of-transmission or an empty line was received
180 (timestamp, rc, hostname, service, output)=self.read_check_result(databuffer[s],IVs[s])
181 del databuffer[s]
182 del IVs[s]
183 self.post_command(timestamp,rc,hostname,service,output)
184 try:
185 s.shutdown(2)
186 except Exception , exp:
187 print exp
188 s.close()
189 input.remove(s)