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"
34 from shinken
.basemodule
import BaseModule
35 from shinken
.external_command
import ExternalCommand
38 'type' : 'nsca_server',
40 'phases' : ['running'],
43 def decrypt_xor(data
, 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
== '*':
59 if hasattr(plugin
, 'port'):
60 port
= int(plugin
.port
)
63 if hasattr(plugin
, 'encryption_method'):
64 encryption_method
= int(plugin
.encryption_method
)
67 if hasattr(plugin
, 'password'):
68 password
= plugin
.password
72 instance
= NSCA_arbiter(plugin
, host
, port
, encryption_method
, password
)
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
)
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"
91 h
= {'name' : 'dummy host from dummy arbiter module',
96 print "[Dummy] Returning to Arbiter the hosts:", r
99 def send_init_packet(self
, socket
):
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
)
110 def read_check_result(self
, data
, iv
):
112 Read the check result
119 204-715 : output of the plugin
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
)
142 extcmd
= "[%lu] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n" % (timestamp
,hostname
,service
,rc
,output
)
144 e
= ExternalCommand(extcmd
)
148 # When you are in "external" mode, that is the main loop of your process
150 self
.set_exit_handler()
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
)
161 while not self
.interrupted
:
162 inputready
,outputready
,exceptready
= select
.select(input,[],[], 1)
166 # handle the server socket
167 client
, address
= server
.accept()
168 iv
= self
.send_init_packet(client
)
172 # handle all other sockets
175 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
])
183 self
.post_command(timestamp
,rc
,hostname
,service
,output
)
186 except Exception , exp
: