Centreon Broker provides a stream connector. If no suitable connector is found among those provided then surely this stream connector will match your needs. Its principle is to expose a part of Centreon Broker API through the Lua interpreter and the user has just to fill it with his needs.
Here is the minimal acceptable Lua code to work as stream connector:
function init(conf)
end
function write(d)
return true
end
We recommand to put Lua scripts in the /usr/share/centreon-broker/lua directory. If it does not exist, we can create it. Just be careful that directory to be accesible for the centreon-broker user. If a stream connector is composed of several files (a main script and a module for example), you can put them in that directory. If a dynamic library (\*.so file) is used by a Lua script, put it in the /usr/share/centreon-broker/lua/lib directory.
When Centreon Broker starts, it initializes all the configured connectors. For the stream connector, it loads the Lua script, checks its syntax and verifies that the init() and write() functions exist.
Centreon Broker checks also if a function filter(category, type) exists.
Let’s focus on those functions. init function is called when the connector is initialized. The argument provided to this function is a Lua table containing information given by the user in the Centreon web output broker configuration interface. For example, if an IP address is provided with the name address and the value 192.168.1.18, then this information will be accessible through conf["address"].
The write() function is called each time an event is received from a poller through the broker. This event is configured to be sent to this connector. This function needs one argument which is the event translated as a Lua table.
The write() must return a boolean that is true if the events are processed and false otherwise.
If this function does not return a boolean, Broker will rise an error.
To simplify Lua developer’s life, several objects are proposed and directly available to the script.
Here is an example:
function init(conf)
-- Here, we allow all logs with level 3 and set the output to
-- /tmp/test.log.
broker_log:set_parameters(3, "/tmp/test.log")
end
function write(d)
-- For each entry, we write the key and the value.
for k,v in pairs(d) do
broker_log:info(3, k .. " => " .. tostring(v))
end
return true
end
Here, when the init function is executed, the broker_log object is parametrized with a max level 3 and an output file /tmp/test.log.
Then on each write() call, events received are logged as info. We get a result like this:
Fri Jan 26 08:31:49 2018: INFO: service_id => 21
Fri Jan 26 08:31:49 2018: INFO: type => 0
Fri Jan 26 08:31:49 2018: INFO: host_id => 13
Fri Jan 26 08:31:49 2018: INFO: element => 1
Fri Jan 26 08:31:49 2018: INFO: comment_data =>
Note - To use a method in Lua, the separator between the object and the method is : ; broker_log is an object since it contains informations such as the max level or the destination file.
A basic TCP socket is available in the Broker SDK. A simple example is the following:
local socket = broker_tcp_socket.new()
socket:connect("10.40.1.2", 9002)
socket:write(message)
answer = socket:read()
socket:close()
This socket object also provides a method get_state() that returns a string:
Several functions are available in this table. These functions are not methods, broker is just a table containing them. We can find here:
local obj = {
a = 1,
b = 2,
c = { 'aa', 'bb', 'cc' }
}
local json = broker.json_encode(obj)
print(json)
that returns
{ "a": 1, "b": 2, "c": [ 'aa', 'bb', 'cc' ] }
A second example is the following:
local json = { "a": 1, "b": 2, "c": [ 'aa', 'bb', 'cc' ] }
local obj = broker.json_decode(json)
for i,v in pairs(obj) do
print(i .. " => " .. tostring(v))
end
should return something like this:
a => 1
b => 2
c => table: 0x12ef67b5
It is also easy to access to each field of the object, for example: obj['a'] gives 1, or obj['c'][1] gives aa, or obj.b gives 2.
Here is an example showing the possibilities of the parse_perfdata function.
local perf, err_str = broker.parse_perfdata(" 'one value'=2s;3;5;0;9 'a b c'=3.14KB;0.8;1;0;10")
if perf then
for i,v in pairs(perf) do
print(i .. " => " .. tostring(v))
end
else
print("parse_perfdata error: " .. err_str)
end
should return something like this:
a b c => 3.14
one value => 2
If now, we call the same function with true as second argument:
local perf, err_str = broker.parse_perfdata("pl=45%;40;80;0;100", true)
if perf then
print("Content of 'pl'")
for i,v in pairs(perf['pl']) do
print(i .. " => " .. tostring(v))
end
else
print("parse_perfdata error: " .. err_str)
end
should return something like this:
Content of 'pl'
value => 45
uom => %
min => 0
max => 100
warning_low => 0
warning_high => 40
warning_mode => false
critical_low => 0
critical_high => 80
critical_mode => false
Be careful, keys are not sorted in hash tables, so if you make a such program, you will probably not have data in the same order.
local str = broker.url_encode("La leçon du château de l'araignée")
print(str)
should return something like this:
La%20le%C3%A7on%20du%20ch%C3%A2teau%20de%20l%27araign%C3%A9e
This object provides several methods to access the cache. Among data, we can get hostnames, etc...
Note - The functions described here need the cache to be filled. It is important for that to enable the NEB events, otherwise those functions will just return nil. The cache is filled when an engine restarts.
The available methods are:
This function must not be defined as local, otherwise it will not be detected by centreon broker.
Imagine we have made such configuration:
with two custom entries:
Then, the init() function has access to them like this:
function init(conf)
local my_address = conf['elastic-address']
local port = conf['elastic-port']
end
This function must not be defined as local, otherwise it will not be seen by broker.
The only argument given to the write() function is an event. It is given with the same data as the ones we can see in Centreon Broker.
To classify the event, we have two data that are category and element. Those two informations are integers. If we concatenate those two numbers we obtain a longer integer equal to the event type also available in the event.
int | short | short |
type = | category | elem |
Sometimes, one can want the hostname corresponding to an event but he only gets the host_id. It is possible to get it thanks to the broker_cache:get_hostname(id) method.
For example:
function write(d)
if d.category == 3 and d.element == 1 then
local hostname = broker_cache:get_hostname(d.host_id)
if hostname then
broker_log:info("host name "
.. hostname .. " corresponds to host id " .. d.host_id)
else
-- Unable to get the name, we wait for the next time, wishing
-- the cache will contain the name. And so return 0
return true
end
end
-- Here, we can add the event processing...
return true
end
The write function return value is a boolean. While this value is false, Broker keeps the sent events in memory and if needed in retention. When we are sure all events are processed, the idea is that write returns true and then Broker frees the events stack.
Behind this, it is possible to avoid to commit events one by one. The write function can stock them in a stack and return false, and when a given limit is reached, it can send all of them to their destination and return true.
The function must not be defined as local, otherwise it will not be detected by Centreon Broker.
It takes account of two parameters: category and element that we’ve already seen in the previous section. The category is an integer from 1 to 7, or the value 65535. The element gives details on the event, for example, for the category NEB, elements are Acknowledgement, Comment, etc... given as integers.
For details on types, categories and their id, see https://documentation.centreon.com/docs/centreon-broker/en/latest/dev/bbdo.html